diff options
Diffstat (limited to 'src')
522 files changed, 32612 insertions, 9321 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 0edddc9fc..cd75de5e9 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -16,8 +16,16 @@ if USE_TLS SUBDIRS += libtls endif +if USE_LIBCHARON + SUBDIRS += libcharon +endif + if USE_FILE_CONFIG - SUBDIRS += libfreeswan starter ipsec _copyright + SUBDIRS += libfreeswan starter +endif + +if USE_IPSEC_SCRIPT + SUBDIRS += ipsec _copyright endif if USE_PLUTO @@ -25,7 +33,7 @@ if USE_PLUTO endif if USE_CHARON - SUBDIRS += libcharon charon + SUBDIRS += charon endif if USE_STROKE @@ -40,6 +48,10 @@ if USE_TOOLS SUBDIRS += libfreeswan openac scepclient pki endif +if USE_CONFTEST + SUBDIRS += conftest +endif + if USE_DUMM SUBDIRS += dumm endif @@ -64,4 +76,4 @@ EXTRA_DIST = strongswan.conf install-exec-local : test -e "$(DESTDIR)${sysconfdir}" || $(INSTALL) -d "$(DESTDIR)$(sysconfdir)" - test -e "$(DESTDIR)$(sysconfdir)/strongswan.conf" || $(INSTALL) -o ${ipsecuid} -g ${ipsecgid} -m 640 $(srcdir)/strongswan.conf $(DESTDIR)$(sysconfdir)/strongswan.conf || true + test -e "$(DESTDIR)$(sysconfdir)/strongswan.conf" || $(INSTALL) -m 640 $(srcdir)/strongswan.conf $(DESTDIR)$(sysconfdir)/strongswan.conf || true diff --git a/src/Makefile.in b/src/Makefile.in index cb688d795..63d29b694 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -37,17 +37,20 @@ host_triplet = @host@ @USE_LIBHYDRA_TRUE@am__append_2 = libhydra @USE_SIMAKA_TRUE@am__append_3 = libsimaka @USE_TLS_TRUE@am__append_4 = libtls -@USE_FILE_CONFIG_TRUE@am__append_5 = libfreeswan starter ipsec _copyright -@USE_PLUTO_TRUE@am__append_6 = pluto whack -@USE_CHARON_TRUE@am__append_7 = libcharon charon -@USE_STROKE_TRUE@am__append_8 = stroke -@USE_UPDOWN_TRUE@am__append_9 = _updown _updown_espmark -@USE_TOOLS_TRUE@am__append_10 = libfreeswan openac scepclient pki -@USE_DUMM_TRUE@am__append_11 = dumm -@USE_FAST_TRUE@am__append_12 = libfast -@USE_MANAGER_TRUE@am__append_13 = manager -@USE_MEDSRV_TRUE@am__append_14 = medsrv -@USE_INTEGRITY_TEST_TRUE@am__append_15 = checksum +@USE_LIBCHARON_TRUE@am__append_5 = libcharon +@USE_FILE_CONFIG_TRUE@am__append_6 = libfreeswan starter +@USE_IPSEC_SCRIPT_TRUE@am__append_7 = ipsec _copyright +@USE_PLUTO_TRUE@am__append_8 = pluto whack +@USE_CHARON_TRUE@am__append_9 = charon +@USE_STROKE_TRUE@am__append_10 = stroke +@USE_UPDOWN_TRUE@am__append_11 = _updown _updown_espmark +@USE_TOOLS_TRUE@am__append_12 = libfreeswan openac scepclient pki +@USE_CONFTEST_TRUE@am__append_13 = conftest +@USE_DUMM_TRUE@am__append_14 = dumm +@USE_FAST_TRUE@am__append_15 = libfast +@USE_MANAGER_TRUE@am__append_16 = manager +@USE_MEDSRV_TRUE@am__append_17 = medsrv +@USE_INTEGRITY_TEST_TRUE@am__append_18 = checksum subdir = src DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -82,9 +85,9 @@ AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ ETAGS = etags CTAGS = ctags DIST_SUBDIRS = . include libstrongswan libhydra libsimaka libtls \ - libfreeswan starter ipsec _copyright pluto whack libcharon \ + libcharon libfreeswan starter ipsec _copyright pluto whack \ charon stroke _updown _updown_espmark openac scepclient pki \ - dumm libfast manager medsrv checksum + conftest dumm libfast manager medsrv checksum DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ @@ -230,9 +233,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -271,6 +272,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ @@ -285,7 +288,8 @@ SUBDIRS = . include $(am__append_1) $(am__append_2) $(am__append_3) \ $(am__append_4) $(am__append_5) $(am__append_6) \ $(am__append_7) $(am__append_8) $(am__append_9) \ $(am__append_10) $(am__append_11) $(am__append_12) \ - $(am__append_13) $(am__append_14) $(am__append_15) + $(am__append_13) $(am__append_14) $(am__append_15) \ + $(am__append_16) $(am__append_17) $(am__append_18) EXTRA_DIST = strongswan.conf all: all-recursive @@ -636,7 +640,7 @@ uninstall-am: install-exec-local : test -e "$(DESTDIR)${sysconfdir}" || $(INSTALL) -d "$(DESTDIR)$(sysconfdir)" - test -e "$(DESTDIR)$(sysconfdir)/strongswan.conf" || $(INSTALL) -o ${ipsecuid} -g ${ipsecgid} -m 640 $(srcdir)/strongswan.conf $(DESTDIR)$(sysconfdir)/strongswan.conf || true + test -e "$(DESTDIR)$(sysconfdir)/strongswan.conf" || $(INSTALL) -m 640 $(srcdir)/strongswan.conf $(DESTDIR)$(sysconfdir)/strongswan.conf || true # 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. diff --git a/src/_copyright/Makefile.am b/src/_copyright/Makefile.am index 33c4ffc23..405e08b3d 100644 --- a/src/_copyright/Makefile.am +++ b/src/_copyright/Makefile.am @@ -1,6 +1,5 @@ ipsec_PROGRAMS = _copyright _copyright_SOURCES = _copyright.c -dist_man8_MANS = _copyright.8 INCLUDES = \ -I$(top_srcdir)/src/libfreeswan \ diff --git a/src/_copyright/Makefile.in b/src/_copyright/Makefile.in index 58ebb523c..8d4ef733e 100644 --- a/src/_copyright/Makefile.in +++ b/src/_copyright/Makefile.in @@ -36,8 +36,7 @@ build_triplet = @build@ host_triplet = @host@ ipsec_PROGRAMS = _copyright$(EXEEXT) subdir = src/_copyright -DIST_COMMON = $(dist_man8_MANS) $(srcdir)/Makefile.am \ - $(srcdir)/Makefile.in +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \ $(top_srcdir)/m4/config/ltoptions.m4 \ @@ -53,7 +52,7 @@ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ mkinstalldirs = $(install_sh) -d CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = -am__installdirs = "$(DESTDIR)$(ipsecdir)" "$(DESTDIR)$(man8dir)" +am__installdirs = "$(DESTDIR)$(ipsecdir)" PROGRAMS = $(ipsec_PROGRAMS) am__copyright_OBJECTS = _copyright.$(OBJEXT) _copyright_OBJECTS = $(am__copyright_OBJECTS) @@ -75,30 +74,6 @@ LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ $(LDFLAGS) -o $@ SOURCES = $(_copyright_SOURCES) DIST_SOURCES = $(_copyright_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' -man8dir = $(mandir)/man8 -NROFF = nroff -MANS = $(dist_man8_MANS) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) @@ -221,9 +196,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -262,6 +235,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ @@ -273,7 +248,6 @@ urandom_device = @urandom_device@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ _copyright_SOURCES = _copyright.c -dist_man8_MANS = _copyright.8 INCLUDES = \ -I$(top_srcdir)/src/libfreeswan \ -I$(top_srcdir)/src/libstrongswan @@ -394,40 +368,6 @@ mostlyclean-libtool: clean-libtool: -rm -rf .libs _libs -install-man8: $(dist_man8_MANS) - @$(NORMAL_INSTALL) - test -z "$(man8dir)" || $(MKDIR_P) "$(DESTDIR)$(man8dir)" - @list='$(dist_man8_MANS)'; test -n "$(man8dir)" || exit 0; \ - { for i in $$list; do echo "$$i"; done; \ - } | 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 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='$(dist_man8_MANS)'; test -n "$(man8dir)" || exit 0; \ - files=`{ for i in $$list; do echo "$$i"; done; \ - } | 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)'; \ @@ -482,19 +422,6 @@ 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)'; \ @@ -526,9 +453,9 @@ distdir: $(DISTFILES) done check-am: all-am check: check-am -all-am: Makefile $(PROGRAMS) $(MANS) +all-am: Makefile $(PROGRAMS) installdirs: - for dir in "$(DESTDIR)$(ipsecdir)" "$(DESTDIR)$(man8dir)"; do \ + for dir in "$(DESTDIR)$(ipsecdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am @@ -579,7 +506,7 @@ info: info-am info-am: -install-data-am: install-ipsecPROGRAMS install-man +install-data-am: install-ipsecPROGRAMS install-dvi: install-dvi-am @@ -595,7 +522,7 @@ install-info: install-info-am install-info-am: -install-man: install-man8 +install-man: install-pdf: install-pdf-am @@ -625,9 +552,7 @@ ps: ps-am ps-am: -uninstall-am: uninstall-ipsecPROGRAMS uninstall-man - -uninstall-man: uninstall-man8 +uninstall-am: uninstall-ipsecPROGRAMS .MAKE: install-am install-strip @@ -638,13 +563,12 @@ uninstall-man: uninstall-man8 install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am \ - install-ipsecPROGRAMS install-man install-man8 install-pdf \ - install-pdf-am install-ps install-ps-am install-strip \ - installcheck installcheck-am installdirs maintainer-clean \ + install-ipsecPROGRAMS install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ - tags uninstall uninstall-am uninstall-ipsecPROGRAMS \ - uninstall-man uninstall-man8 + tags uninstall uninstall-am uninstall-ipsecPROGRAMS # Tell versions [3.59,3.63) of GNU make to not export all variables. diff --git a/src/_copyright/_copyright.8 b/src/_copyright/_copyright.8 deleted file mode 100644 index 99386254b..000000000 --- a/src/_copyright/_copyright.8 +++ /dev/null @@ -1,29 +0,0 @@ -.TH _COPYRIGHT 8 "25 Apr 2002" -.SH NAME -ipsec _copyright \- prints FreeSWAN copyright -.SH DESCRIPTION -.I _copyright -outputs the FreeSWAN copyright, and version numbers for "ipsec --copyright" -.SH "SEE ALSO" -ipsec(8) -.SH HISTORY -Man page written for the Linux FreeS/WAN project -<http://www.freeswan.org/> -by Michael Richardson. Program written by Henry Spencer. -.\" -.\" $Log: _copyright.8,v $ -.\" Revision 1.1 2004/03/15 20:35:27 as -.\" added files from freeswan-2.04-x509-1.5.3 -.\" -.\" Revision 1.2 2002/04/29 22:39:31 mcr -.\" added basic man page for all internal commands. -.\" -.\" Revision 1.1 2002/04/26 01:21:43 mcr -.\" while tracking down a missing (not installed) /etc/ipsec.conf, -.\" MCR has decided that it is not okay for each program subdir to have -.\" some subset (determined with -f) of possible files. -.\" Each subdir that defines $PROGRAM, MUST have a PROGRAM.8 file as well as a PROGRAM file. -.\" Optional PROGRAM.5 files have been added to the makefiles. -.\" -.\" -.\" diff --git a/src/_updown/Makefile.in b/src/_updown/Makefile.in index 44c058d03..fa33bb570 100644 --- a/src/_updown/Makefile.in +++ b/src/_updown/Makefile.in @@ -200,9 +200,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -241,6 +239,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/_updown_espmark/Makefile.in b/src/_updown_espmark/Makefile.in index db44ee74e..a428db4e2 100644 --- a/src/_updown_espmark/Makefile.in +++ b/src/_updown_espmark/Makefile.in @@ -200,9 +200,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -241,6 +239,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/charon/Makefile.in b/src/charon/Makefile.in index 5a60af3d8..f502b0f25 100644 --- a/src/charon/Makefile.in +++ b/src/charon/Makefile.in @@ -199,9 +199,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -240,6 +238,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/charon/charon.c b/src/charon/charon.c index fd255e919..d1fff5bd9 100644 --- a/src/charon/charon.c +++ b/src/charon/charon.c @@ -26,6 +26,8 @@ #include <pthread.h> #include <sys/stat.h> #include <sys/types.h> +#include <syslog.h> +#include <errno.h> #include <unistd.h> #include <getopt.h> #include <pwd.h> @@ -42,6 +44,9 @@ #include <private/android_filesystem_config.h> #endif +#ifndef LOG_AUTHPRIV /* not defined on OpenSolaris */ +#define LOG_AUTHPRIV LOG_AUTH +#endif /** * PID file, in which charon stores its process id @@ -268,6 +273,134 @@ static void unlink_pidfile() unlink(PID_FILE); } +/** + * Initialize logging + */ +static void initialize_loggers(bool use_stderr, level_t levels[]) +{ + sys_logger_t *sys_logger; + file_logger_t *file_logger; + enumerator_t *enumerator; + char *facility, *filename; + int loggers_defined = 0; + debug_t group; + level_t def; + bool append, ike_name; + FILE *file; + + /* setup sysloggers */ + enumerator = lib->settings->create_section_enumerator(lib->settings, + "charon.syslog"); + while (enumerator->enumerate(enumerator, &facility)) + { + loggers_defined++; + + ike_name = lib->settings->get_bool(lib->settings, + "charon.syslog.%s.ike_name", FALSE, facility); + if (streq(facility, "daemon")) + { + sys_logger = sys_logger_create(LOG_DAEMON, ike_name); + } + else if (streq(facility, "auth")) + { + sys_logger = sys_logger_create(LOG_AUTHPRIV, ike_name); + } + else + { + continue; + } + def = lib->settings->get_int(lib->settings, + "charon.syslog.%s.default", 1, facility); + for (group = 0; group < DBG_MAX; group++) + { + sys_logger->set_level(sys_logger, group, + lib->settings->get_int(lib->settings, + "charon.syslog.%s.%N", def, + facility, debug_lower_names, group)); + } + charon->sys_loggers->insert_last(charon->sys_loggers, sys_logger); + charon->bus->add_listener(charon->bus, &sys_logger->listener); + } + enumerator->destroy(enumerator); + + /* and file loggers */ + enumerator = lib->settings->create_section_enumerator(lib->settings, + "charon.filelog"); + while (enumerator->enumerate(enumerator, &filename)) + { + loggers_defined++; + if (streq(filename, "stderr")) + { + file = stderr; + } + else if (streq(filename, "stdout")) + { + file = stdout; + } + else + { + append = lib->settings->get_bool(lib->settings, + "charon.filelog.%s.append", TRUE, filename); + file = fopen(filename, append ? "a" : "w"); + if (file == NULL) + { + DBG1(DBG_DMN, "opening file %s for logging failed: %s", + filename, strerror(errno)); + continue; + } + if (lib->settings->get_bool(lib->settings, + "charon.filelog.%s.flush_line", FALSE, filename)) + { + setlinebuf(file); + } + } + file_logger = file_logger_create(file, + lib->settings->get_str(lib->settings, + "charon.filelog.%s.time_format", NULL, filename), + lib->settings->get_bool(lib->settings, + "charon.filelog.%s.ike_name", FALSE, filename)); + def = lib->settings->get_int(lib->settings, + "charon.filelog.%s.default", 1, filename); + for (group = 0; group < DBG_MAX; group++) + { + file_logger->set_level(file_logger, group, + lib->settings->get_int(lib->settings, + "charon.filelog.%s.%N", def, + filename, debug_lower_names, group)); + } + charon->file_loggers->insert_last(charon->file_loggers, file_logger); + charon->bus->add_listener(charon->bus, &file_logger->listener); + + } + enumerator->destroy(enumerator); + + /* set up legacy style default loggers provided via command-line */ + if (!loggers_defined) + { + /* set up default stdout file_logger */ + file_logger = file_logger_create(stdout, NULL, FALSE); + charon->bus->add_listener(charon->bus, &file_logger->listener); + charon->file_loggers->insert_last(charon->file_loggers, file_logger); + /* set up default daemon sys_logger */ + sys_logger = sys_logger_create(LOG_DAEMON, FALSE); + charon->bus->add_listener(charon->bus, &sys_logger->listener); + charon->sys_loggers->insert_last(charon->sys_loggers, sys_logger); + for (group = 0; group < DBG_MAX; group++) + { + sys_logger->set_level(sys_logger, group, levels[group]); + if (use_stderr) + { + file_logger->set_level(file_logger, group, levels[group]); + } + } + + /* set up default auth sys_logger */ + sys_logger = sys_logger_create(LOG_AUTHPRIV, FALSE); + charon->bus->add_listener(charon->bus, &sys_logger->listener); + charon->sys_loggers->insert_last(charon->sys_loggers, sys_logger); + sys_logger->set_level(sys_logger, DBG_ANY, LEVEL_AUDIT); + } +} /** * print command line usage and exit @@ -395,8 +528,10 @@ int main(int argc, char *argv[]) goto deinit; } + initialize_loggers(!use_syslog, levels); + /* initialize daemon */ - if (!charon->initialize(charon, use_syslog, levels)) + if (!charon->initialize(charon)) { DBG1(DBG_DMN, "initialization failed - aborting charon"); goto deinit; diff --git a/src/checksum/Makefile.in b/src/checksum/Makefile.in index 61bfc1a9d..65aa91422 100644 --- a/src/checksum/Makefile.in +++ b/src/checksum/Makefile.in @@ -237,9 +237,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -278,6 +276,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/conftest/Makefile.am b/src/conftest/Makefile.am new file mode 100644 index 000000000..7eab0df27 --- /dev/null +++ b/src/conftest/Makefile.am @@ -0,0 +1,26 @@ +ipsec_PROGRAMS = conftest + +AM_CFLAGS = -rdynamic + +conftest_SOURCES = conftest.c conftest.h config.c config.h actions.c actions.h \ + hooks/hook.h hooks/ike_auth_fill.c hooks/unsort_message.c \ + hooks/add_notify.c hooks/unencrypted_notify.c hooks/ignore_message.c \ + hooks/add_payload.c hooks/set_critical.c hooks/force_cookie.c \ + hooks/set_ike_version.c hooks/pretend_auth.c hooks/set_length.c \ + hooks/log_proposals.c hooks/set_proposal_number.c hooks/log_ke.c \ + hooks/log_id.c hooks/custom_proposal.c hooks/set_ike_spi.c \ + hooks/set_ike_request.c hooks/set_reserved.c hooks/set_ike_initiator.c \ + hooks/log_ts.c hooks/rebuild_auth.c hooks/reset_seq.c + +INCLUDES = \ + -I$(top_srcdir)/src/libstrongswan \ + -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libcharon + +conftest_LDADD = \ + $(top_builddir)/src/libstrongswan/libstrongswan.la \ + $(top_builddir)/src/libhydra/libhydra.la \ + $(top_builddir)/src/libcharon/libcharon.la \ + -lm $(PTHREADLIB) $(DLLIB) + +EXTRA_DIST = README diff --git a/src/conftest/Makefile.in b/src/conftest/Makefile.in new file mode 100644 index 000000000..1c07710e0 --- /dev/null +++ b/src/conftest/Makefile.in @@ -0,0 +1,954 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 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. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@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 +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +ipsec_PROGRAMS = conftest$(EXEEXT) +subdir = src/conftest +DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +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)/m4/macros/add-plugin.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)" +PROGRAMS = $(ipsec_PROGRAMS) +am_conftest_OBJECTS = conftest.$(OBJEXT) config.$(OBJEXT) \ + actions.$(OBJEXT) ike_auth_fill.$(OBJEXT) \ + unsort_message.$(OBJEXT) add_notify.$(OBJEXT) \ + unencrypted_notify.$(OBJEXT) ignore_message.$(OBJEXT) \ + add_payload.$(OBJEXT) set_critical.$(OBJEXT) \ + force_cookie.$(OBJEXT) set_ike_version.$(OBJEXT) \ + pretend_auth.$(OBJEXT) set_length.$(OBJEXT) \ + log_proposals.$(OBJEXT) set_proposal_number.$(OBJEXT) \ + log_ke.$(OBJEXT) log_id.$(OBJEXT) custom_proposal.$(OBJEXT) \ + set_ike_spi.$(OBJEXT) set_ike_request.$(OBJEXT) \ + set_reserved.$(OBJEXT) set_ike_initiator.$(OBJEXT) \ + log_ts.$(OBJEXT) rebuild_auth.$(OBJEXT) reset_seq.$(OBJEXT) +conftest_OBJECTS = $(am_conftest_OBJECTS) +am__DEPENDENCIES_1 = +conftest_DEPENDENCIES = \ + $(top_builddir)/src/libstrongswan/libstrongswan.la \ + $(top_builddir)/src/libhydra/libhydra.la \ + $(top_builddir)/src/libcharon/libcharon.la \ + $(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) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(conftest_SOURCES) +DIST_SOURCES = $(conftest_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BTLIB = @BTLIB@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLIB = @DLLIB@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GPERF = @GPERF@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +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@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +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@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PTHREADLIB = @PTHREADLIB@ +RANLIB = @RANLIB@ +RTLIB = @RTLIB@ +RUBY = @RUBY@ +RUBYINCLUDE = @RUBYINCLUDE@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKLIB = @SOCKLIB@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +c_plugins = @c_plugins@ +datadir = @datadir@ +datarootdir = @datarootdir@ +dbusservicedir = @dbusservicedir@ +default_pkcs11 = @default_pkcs11@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +gtk_CFLAGS = @gtk_CFLAGS@ +gtk_LIBS = @gtk_LIBS@ +h_plugins = @h_plugins@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +ipsecdir = @ipsecdir@ +ipsecgroup = @ipsecgroup@ +ipsecuser = @ipsecuser@ +libcharon_plugins = @libcharon_plugins@ +libdir = @libdir@ +libexecdir = @libexecdir@ +linux_headers = @linux_headers@ +localedir = @localedir@ +localstatedir = @localstatedir@ +lt_ECHO = @lt_ECHO@ +maemo_CFLAGS = @maemo_CFLAGS@ +maemo_LIBS = @maemo_LIBS@ +manager_plugins = @manager_plugins@ +mandir = @mandir@ +medsrv_plugins = @medsrv_plugins@ +mkdir_p = @mkdir_p@ +nm_CFLAGS = @nm_CFLAGS@ +nm_LIBS = @nm_LIBS@ +nm_ca_dir = @nm_ca_dir@ +oldincludedir = @oldincludedir@ +openac_plugins = @openac_plugins@ +p_plugins = @p_plugins@ +pdfdir = @pdfdir@ +piddir = @piddir@ +pki_plugins = @pki_plugins@ +plugindir = @plugindir@ +pluto_plugins = @pluto_plugins@ +pool_plugins = @pool_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@ +s_plugins = @s_plugins@ +sbindir = @sbindir@ +scepclient_plugins = @scepclient_plugins@ +scripts_plugins = @scripts_plugins@ +sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ +srcdir = @srcdir@ +strongswan_conf = @strongswan_conf@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +urandom_device = @urandom_device@ +xml_CFLAGS = @xml_CFLAGS@ +xml_LIBS = @xml_LIBS@ +AM_CFLAGS = -rdynamic +conftest_SOURCES = conftest.c conftest.h config.c config.h actions.c actions.h \ + hooks/hook.h hooks/ike_auth_fill.c hooks/unsort_message.c \ + hooks/add_notify.c hooks/unencrypted_notify.c hooks/ignore_message.c \ + hooks/add_payload.c hooks/set_critical.c hooks/force_cookie.c \ + hooks/set_ike_version.c hooks/pretend_auth.c hooks/set_length.c \ + hooks/log_proposals.c hooks/set_proposal_number.c hooks/log_ke.c \ + hooks/log_id.c hooks/custom_proposal.c hooks/set_ike_spi.c \ + hooks/set_ike_request.c hooks/set_reserved.c hooks/set_ike_initiator.c \ + hooks/log_ts.c hooks/rebuild_auth.c hooks/reset_seq.c + +INCLUDES = \ + -I$(top_srcdir)/src/libstrongswan \ + -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libcharon + +conftest_LDADD = \ + $(top_builddir)/src/libstrongswan/libstrongswan.la \ + $(top_builddir)/src/libhydra/libhydra.la \ + $(top_builddir)/src/libcharon/libcharon.la \ + -lm $(PTHREADLIB) $(DLLIB) + +EXTRA_DIST = README +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/conftest/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/conftest/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(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)'; 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)'; 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)'; 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 +conftest$(EXEEXT): $(conftest_OBJECTS) $(conftest_DEPENDENCIES) + @rm -f conftest$(EXEEXT) + $(LINK) $(conftest_OBJECTS) $(conftest_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/actions.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/add_notify.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/add_payload.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/config.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conftest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/custom_proposal.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/force_cookie.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ignore_message.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_auth_fill.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/log_id.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/log_ke.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/log_proposals.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/log_ts.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pretend_auth.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rebuild_auth.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/reset_seq.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/set_critical.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/set_ike_initiator.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/set_ike_request.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/set_ike_spi.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/set_ike_version.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/set_length.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/set_proposal_number.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/set_reserved.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unencrypted_notify.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unsort_message.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@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@ $(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@ $(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 $@ $< + +ike_auth_fill.o: hooks/ike_auth_fill.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_auth_fill.o -MD -MP -MF $(DEPDIR)/ike_auth_fill.Tpo -c -o ike_auth_fill.o `test -f 'hooks/ike_auth_fill.c' || echo '$(srcdir)/'`hooks/ike_auth_fill.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_auth_fill.Tpo $(DEPDIR)/ike_auth_fill.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='hooks/ike_auth_fill.c' object='ike_auth_fill.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_auth_fill.o `test -f 'hooks/ike_auth_fill.c' || echo '$(srcdir)/'`hooks/ike_auth_fill.c + +ike_auth_fill.obj: hooks/ike_auth_fill.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ike_auth_fill.obj -MD -MP -MF $(DEPDIR)/ike_auth_fill.Tpo -c -o ike_auth_fill.obj `if test -f 'hooks/ike_auth_fill.c'; then $(CYGPATH_W) 'hooks/ike_auth_fill.c'; else $(CYGPATH_W) '$(srcdir)/hooks/ike_auth_fill.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ike_auth_fill.Tpo $(DEPDIR)/ike_auth_fill.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='hooks/ike_auth_fill.c' object='ike_auth_fill.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ike_auth_fill.obj `if test -f 'hooks/ike_auth_fill.c'; then $(CYGPATH_W) 'hooks/ike_auth_fill.c'; else $(CYGPATH_W) '$(srcdir)/hooks/ike_auth_fill.c'; fi` + +unsort_message.o: hooks/unsort_message.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT unsort_message.o -MD -MP -MF $(DEPDIR)/unsort_message.Tpo -c -o unsort_message.o `test -f 'hooks/unsort_message.c' || echo '$(srcdir)/'`hooks/unsort_message.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/unsort_message.Tpo $(DEPDIR)/unsort_message.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='hooks/unsort_message.c' object='unsort_message.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o unsort_message.o `test -f 'hooks/unsort_message.c' || echo '$(srcdir)/'`hooks/unsort_message.c + +unsort_message.obj: hooks/unsort_message.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT unsort_message.obj -MD -MP -MF $(DEPDIR)/unsort_message.Tpo -c -o unsort_message.obj `if test -f 'hooks/unsort_message.c'; then $(CYGPATH_W) 'hooks/unsort_message.c'; else $(CYGPATH_W) '$(srcdir)/hooks/unsort_message.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/unsort_message.Tpo $(DEPDIR)/unsort_message.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='hooks/unsort_message.c' object='unsort_message.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o unsort_message.obj `if test -f 'hooks/unsort_message.c'; then $(CYGPATH_W) 'hooks/unsort_message.c'; else $(CYGPATH_W) '$(srcdir)/hooks/unsort_message.c'; fi` + +add_notify.o: hooks/add_notify.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT add_notify.o -MD -MP -MF $(DEPDIR)/add_notify.Tpo -c -o add_notify.o `test -f 'hooks/add_notify.c' || echo '$(srcdir)/'`hooks/add_notify.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/add_notify.Tpo $(DEPDIR)/add_notify.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='hooks/add_notify.c' object='add_notify.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o add_notify.o `test -f 'hooks/add_notify.c' || echo '$(srcdir)/'`hooks/add_notify.c + +add_notify.obj: hooks/add_notify.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT add_notify.obj -MD -MP -MF $(DEPDIR)/add_notify.Tpo -c -o add_notify.obj `if test -f 'hooks/add_notify.c'; then $(CYGPATH_W) 'hooks/add_notify.c'; else $(CYGPATH_W) '$(srcdir)/hooks/add_notify.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/add_notify.Tpo $(DEPDIR)/add_notify.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='hooks/add_notify.c' object='add_notify.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o add_notify.obj `if test -f 'hooks/add_notify.c'; then $(CYGPATH_W) 'hooks/add_notify.c'; else $(CYGPATH_W) '$(srcdir)/hooks/add_notify.c'; fi` + +unencrypted_notify.o: hooks/unencrypted_notify.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT unencrypted_notify.o -MD -MP -MF $(DEPDIR)/unencrypted_notify.Tpo -c -o unencrypted_notify.o `test -f 'hooks/unencrypted_notify.c' || echo '$(srcdir)/'`hooks/unencrypted_notify.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/unencrypted_notify.Tpo $(DEPDIR)/unencrypted_notify.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='hooks/unencrypted_notify.c' object='unencrypted_notify.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o unencrypted_notify.o `test -f 'hooks/unencrypted_notify.c' || echo '$(srcdir)/'`hooks/unencrypted_notify.c + +unencrypted_notify.obj: hooks/unencrypted_notify.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT unencrypted_notify.obj -MD -MP -MF $(DEPDIR)/unencrypted_notify.Tpo -c -o unencrypted_notify.obj `if test -f 'hooks/unencrypted_notify.c'; then $(CYGPATH_W) 'hooks/unencrypted_notify.c'; else $(CYGPATH_W) '$(srcdir)/hooks/unencrypted_notify.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/unencrypted_notify.Tpo $(DEPDIR)/unencrypted_notify.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='hooks/unencrypted_notify.c' object='unencrypted_notify.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o unencrypted_notify.obj `if test -f 'hooks/unencrypted_notify.c'; then $(CYGPATH_W) 'hooks/unencrypted_notify.c'; else $(CYGPATH_W) '$(srcdir)/hooks/unencrypted_notify.c'; fi` + +ignore_message.o: hooks/ignore_message.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ignore_message.o -MD -MP -MF $(DEPDIR)/ignore_message.Tpo -c -o ignore_message.o `test -f 'hooks/ignore_message.c' || echo '$(srcdir)/'`hooks/ignore_message.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ignore_message.Tpo $(DEPDIR)/ignore_message.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='hooks/ignore_message.c' object='ignore_message.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ignore_message.o `test -f 'hooks/ignore_message.c' || echo '$(srcdir)/'`hooks/ignore_message.c + +ignore_message.obj: hooks/ignore_message.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ignore_message.obj -MD -MP -MF $(DEPDIR)/ignore_message.Tpo -c -o ignore_message.obj `if test -f 'hooks/ignore_message.c'; then $(CYGPATH_W) 'hooks/ignore_message.c'; else $(CYGPATH_W) '$(srcdir)/hooks/ignore_message.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ignore_message.Tpo $(DEPDIR)/ignore_message.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='hooks/ignore_message.c' object='ignore_message.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ignore_message.obj `if test -f 'hooks/ignore_message.c'; then $(CYGPATH_W) 'hooks/ignore_message.c'; else $(CYGPATH_W) '$(srcdir)/hooks/ignore_message.c'; fi` + +add_payload.o: hooks/add_payload.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT add_payload.o -MD -MP -MF $(DEPDIR)/add_payload.Tpo -c -o add_payload.o `test -f 'hooks/add_payload.c' || echo '$(srcdir)/'`hooks/add_payload.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/add_payload.Tpo $(DEPDIR)/add_payload.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='hooks/add_payload.c' object='add_payload.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o add_payload.o `test -f 'hooks/add_payload.c' || echo '$(srcdir)/'`hooks/add_payload.c + +add_payload.obj: hooks/add_payload.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT add_payload.obj -MD -MP -MF $(DEPDIR)/add_payload.Tpo -c -o add_payload.obj `if test -f 'hooks/add_payload.c'; then $(CYGPATH_W) 'hooks/add_payload.c'; else $(CYGPATH_W) '$(srcdir)/hooks/add_payload.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/add_payload.Tpo $(DEPDIR)/add_payload.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='hooks/add_payload.c' object='add_payload.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o add_payload.obj `if test -f 'hooks/add_payload.c'; then $(CYGPATH_W) 'hooks/add_payload.c'; else $(CYGPATH_W) '$(srcdir)/hooks/add_payload.c'; fi` + +set_critical.o: hooks/set_critical.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT set_critical.o -MD -MP -MF $(DEPDIR)/set_critical.Tpo -c -o set_critical.o `test -f 'hooks/set_critical.c' || echo '$(srcdir)/'`hooks/set_critical.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/set_critical.Tpo $(DEPDIR)/set_critical.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='hooks/set_critical.c' object='set_critical.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o set_critical.o `test -f 'hooks/set_critical.c' || echo '$(srcdir)/'`hooks/set_critical.c + +set_critical.obj: hooks/set_critical.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT set_critical.obj -MD -MP -MF $(DEPDIR)/set_critical.Tpo -c -o set_critical.obj `if test -f 'hooks/set_critical.c'; then $(CYGPATH_W) 'hooks/set_critical.c'; else $(CYGPATH_W) '$(srcdir)/hooks/set_critical.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/set_critical.Tpo $(DEPDIR)/set_critical.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='hooks/set_critical.c' object='set_critical.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o set_critical.obj `if test -f 'hooks/set_critical.c'; then $(CYGPATH_W) 'hooks/set_critical.c'; else $(CYGPATH_W) '$(srcdir)/hooks/set_critical.c'; fi` + +force_cookie.o: hooks/force_cookie.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT force_cookie.o -MD -MP -MF $(DEPDIR)/force_cookie.Tpo -c -o force_cookie.o `test -f 'hooks/force_cookie.c' || echo '$(srcdir)/'`hooks/force_cookie.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/force_cookie.Tpo $(DEPDIR)/force_cookie.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='hooks/force_cookie.c' object='force_cookie.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o force_cookie.o `test -f 'hooks/force_cookie.c' || echo '$(srcdir)/'`hooks/force_cookie.c + +force_cookie.obj: hooks/force_cookie.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT force_cookie.obj -MD -MP -MF $(DEPDIR)/force_cookie.Tpo -c -o force_cookie.obj `if test -f 'hooks/force_cookie.c'; then $(CYGPATH_W) 'hooks/force_cookie.c'; else $(CYGPATH_W) '$(srcdir)/hooks/force_cookie.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/force_cookie.Tpo $(DEPDIR)/force_cookie.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='hooks/force_cookie.c' object='force_cookie.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o force_cookie.obj `if test -f 'hooks/force_cookie.c'; then $(CYGPATH_W) 'hooks/force_cookie.c'; else $(CYGPATH_W) '$(srcdir)/hooks/force_cookie.c'; fi` + +set_ike_version.o: hooks/set_ike_version.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT set_ike_version.o -MD -MP -MF $(DEPDIR)/set_ike_version.Tpo -c -o set_ike_version.o `test -f 'hooks/set_ike_version.c' || echo '$(srcdir)/'`hooks/set_ike_version.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/set_ike_version.Tpo $(DEPDIR)/set_ike_version.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='hooks/set_ike_version.c' object='set_ike_version.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o set_ike_version.o `test -f 'hooks/set_ike_version.c' || echo '$(srcdir)/'`hooks/set_ike_version.c + +set_ike_version.obj: hooks/set_ike_version.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT set_ike_version.obj -MD -MP -MF $(DEPDIR)/set_ike_version.Tpo -c -o set_ike_version.obj `if test -f 'hooks/set_ike_version.c'; then $(CYGPATH_W) 'hooks/set_ike_version.c'; else $(CYGPATH_W) '$(srcdir)/hooks/set_ike_version.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/set_ike_version.Tpo $(DEPDIR)/set_ike_version.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='hooks/set_ike_version.c' object='set_ike_version.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o set_ike_version.obj `if test -f 'hooks/set_ike_version.c'; then $(CYGPATH_W) 'hooks/set_ike_version.c'; else $(CYGPATH_W) '$(srcdir)/hooks/set_ike_version.c'; fi` + +pretend_auth.o: hooks/pretend_auth.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pretend_auth.o -MD -MP -MF $(DEPDIR)/pretend_auth.Tpo -c -o pretend_auth.o `test -f 'hooks/pretend_auth.c' || echo '$(srcdir)/'`hooks/pretend_auth.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pretend_auth.Tpo $(DEPDIR)/pretend_auth.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='hooks/pretend_auth.c' object='pretend_auth.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o pretend_auth.o `test -f 'hooks/pretend_auth.c' || echo '$(srcdir)/'`hooks/pretend_auth.c + +pretend_auth.obj: hooks/pretend_auth.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pretend_auth.obj -MD -MP -MF $(DEPDIR)/pretend_auth.Tpo -c -o pretend_auth.obj `if test -f 'hooks/pretend_auth.c'; then $(CYGPATH_W) 'hooks/pretend_auth.c'; else $(CYGPATH_W) '$(srcdir)/hooks/pretend_auth.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pretend_auth.Tpo $(DEPDIR)/pretend_auth.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='hooks/pretend_auth.c' object='pretend_auth.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o pretend_auth.obj `if test -f 'hooks/pretend_auth.c'; then $(CYGPATH_W) 'hooks/pretend_auth.c'; else $(CYGPATH_W) '$(srcdir)/hooks/pretend_auth.c'; fi` + +set_length.o: hooks/set_length.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT set_length.o -MD -MP -MF $(DEPDIR)/set_length.Tpo -c -o set_length.o `test -f 'hooks/set_length.c' || echo '$(srcdir)/'`hooks/set_length.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/set_length.Tpo $(DEPDIR)/set_length.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='hooks/set_length.c' object='set_length.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o set_length.o `test -f 'hooks/set_length.c' || echo '$(srcdir)/'`hooks/set_length.c + +set_length.obj: hooks/set_length.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT set_length.obj -MD -MP -MF $(DEPDIR)/set_length.Tpo -c -o set_length.obj `if test -f 'hooks/set_length.c'; then $(CYGPATH_W) 'hooks/set_length.c'; else $(CYGPATH_W) '$(srcdir)/hooks/set_length.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/set_length.Tpo $(DEPDIR)/set_length.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='hooks/set_length.c' object='set_length.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o set_length.obj `if test -f 'hooks/set_length.c'; then $(CYGPATH_W) 'hooks/set_length.c'; else $(CYGPATH_W) '$(srcdir)/hooks/set_length.c'; fi` + +log_proposals.o: hooks/log_proposals.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT log_proposals.o -MD -MP -MF $(DEPDIR)/log_proposals.Tpo -c -o log_proposals.o `test -f 'hooks/log_proposals.c' || echo '$(srcdir)/'`hooks/log_proposals.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/log_proposals.Tpo $(DEPDIR)/log_proposals.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='hooks/log_proposals.c' object='log_proposals.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o log_proposals.o `test -f 'hooks/log_proposals.c' || echo '$(srcdir)/'`hooks/log_proposals.c + +log_proposals.obj: hooks/log_proposals.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT log_proposals.obj -MD -MP -MF $(DEPDIR)/log_proposals.Tpo -c -o log_proposals.obj `if test -f 'hooks/log_proposals.c'; then $(CYGPATH_W) 'hooks/log_proposals.c'; else $(CYGPATH_W) '$(srcdir)/hooks/log_proposals.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/log_proposals.Tpo $(DEPDIR)/log_proposals.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='hooks/log_proposals.c' object='log_proposals.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o log_proposals.obj `if test -f 'hooks/log_proposals.c'; then $(CYGPATH_W) 'hooks/log_proposals.c'; else $(CYGPATH_W) '$(srcdir)/hooks/log_proposals.c'; fi` + +set_proposal_number.o: hooks/set_proposal_number.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT set_proposal_number.o -MD -MP -MF $(DEPDIR)/set_proposal_number.Tpo -c -o set_proposal_number.o `test -f 'hooks/set_proposal_number.c' || echo '$(srcdir)/'`hooks/set_proposal_number.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/set_proposal_number.Tpo $(DEPDIR)/set_proposal_number.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='hooks/set_proposal_number.c' object='set_proposal_number.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o set_proposal_number.o `test -f 'hooks/set_proposal_number.c' || echo '$(srcdir)/'`hooks/set_proposal_number.c + +set_proposal_number.obj: hooks/set_proposal_number.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT set_proposal_number.obj -MD -MP -MF $(DEPDIR)/set_proposal_number.Tpo -c -o set_proposal_number.obj `if test -f 'hooks/set_proposal_number.c'; then $(CYGPATH_W) 'hooks/set_proposal_number.c'; else $(CYGPATH_W) '$(srcdir)/hooks/set_proposal_number.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/set_proposal_number.Tpo $(DEPDIR)/set_proposal_number.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='hooks/set_proposal_number.c' object='set_proposal_number.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o set_proposal_number.obj `if test -f 'hooks/set_proposal_number.c'; then $(CYGPATH_W) 'hooks/set_proposal_number.c'; else $(CYGPATH_W) '$(srcdir)/hooks/set_proposal_number.c'; fi` + +log_ke.o: hooks/log_ke.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT log_ke.o -MD -MP -MF $(DEPDIR)/log_ke.Tpo -c -o log_ke.o `test -f 'hooks/log_ke.c' || echo '$(srcdir)/'`hooks/log_ke.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/log_ke.Tpo $(DEPDIR)/log_ke.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='hooks/log_ke.c' object='log_ke.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o log_ke.o `test -f 'hooks/log_ke.c' || echo '$(srcdir)/'`hooks/log_ke.c + +log_ke.obj: hooks/log_ke.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT log_ke.obj -MD -MP -MF $(DEPDIR)/log_ke.Tpo -c -o log_ke.obj `if test -f 'hooks/log_ke.c'; then $(CYGPATH_W) 'hooks/log_ke.c'; else $(CYGPATH_W) '$(srcdir)/hooks/log_ke.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/log_ke.Tpo $(DEPDIR)/log_ke.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='hooks/log_ke.c' object='log_ke.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o log_ke.obj `if test -f 'hooks/log_ke.c'; then $(CYGPATH_W) 'hooks/log_ke.c'; else $(CYGPATH_W) '$(srcdir)/hooks/log_ke.c'; fi` + +log_id.o: hooks/log_id.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT log_id.o -MD -MP -MF $(DEPDIR)/log_id.Tpo -c -o log_id.o `test -f 'hooks/log_id.c' || echo '$(srcdir)/'`hooks/log_id.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/log_id.Tpo $(DEPDIR)/log_id.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='hooks/log_id.c' object='log_id.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o log_id.o `test -f 'hooks/log_id.c' || echo '$(srcdir)/'`hooks/log_id.c + +log_id.obj: hooks/log_id.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT log_id.obj -MD -MP -MF $(DEPDIR)/log_id.Tpo -c -o log_id.obj `if test -f 'hooks/log_id.c'; then $(CYGPATH_W) 'hooks/log_id.c'; else $(CYGPATH_W) '$(srcdir)/hooks/log_id.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/log_id.Tpo $(DEPDIR)/log_id.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='hooks/log_id.c' object='log_id.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o log_id.obj `if test -f 'hooks/log_id.c'; then $(CYGPATH_W) 'hooks/log_id.c'; else $(CYGPATH_W) '$(srcdir)/hooks/log_id.c'; fi` + +custom_proposal.o: hooks/custom_proposal.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT custom_proposal.o -MD -MP -MF $(DEPDIR)/custom_proposal.Tpo -c -o custom_proposal.o `test -f 'hooks/custom_proposal.c' || echo '$(srcdir)/'`hooks/custom_proposal.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/custom_proposal.Tpo $(DEPDIR)/custom_proposal.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='hooks/custom_proposal.c' object='custom_proposal.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o custom_proposal.o `test -f 'hooks/custom_proposal.c' || echo '$(srcdir)/'`hooks/custom_proposal.c + +custom_proposal.obj: hooks/custom_proposal.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT custom_proposal.obj -MD -MP -MF $(DEPDIR)/custom_proposal.Tpo -c -o custom_proposal.obj `if test -f 'hooks/custom_proposal.c'; then $(CYGPATH_W) 'hooks/custom_proposal.c'; else $(CYGPATH_W) '$(srcdir)/hooks/custom_proposal.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/custom_proposal.Tpo $(DEPDIR)/custom_proposal.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='hooks/custom_proposal.c' object='custom_proposal.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o custom_proposal.obj `if test -f 'hooks/custom_proposal.c'; then $(CYGPATH_W) 'hooks/custom_proposal.c'; else $(CYGPATH_W) '$(srcdir)/hooks/custom_proposal.c'; fi` + +set_ike_spi.o: hooks/set_ike_spi.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT set_ike_spi.o -MD -MP -MF $(DEPDIR)/set_ike_spi.Tpo -c -o set_ike_spi.o `test -f 'hooks/set_ike_spi.c' || echo '$(srcdir)/'`hooks/set_ike_spi.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/set_ike_spi.Tpo $(DEPDIR)/set_ike_spi.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='hooks/set_ike_spi.c' object='set_ike_spi.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o set_ike_spi.o `test -f 'hooks/set_ike_spi.c' || echo '$(srcdir)/'`hooks/set_ike_spi.c + +set_ike_spi.obj: hooks/set_ike_spi.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT set_ike_spi.obj -MD -MP -MF $(DEPDIR)/set_ike_spi.Tpo -c -o set_ike_spi.obj `if test -f 'hooks/set_ike_spi.c'; then $(CYGPATH_W) 'hooks/set_ike_spi.c'; else $(CYGPATH_W) '$(srcdir)/hooks/set_ike_spi.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/set_ike_spi.Tpo $(DEPDIR)/set_ike_spi.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='hooks/set_ike_spi.c' object='set_ike_spi.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o set_ike_spi.obj `if test -f 'hooks/set_ike_spi.c'; then $(CYGPATH_W) 'hooks/set_ike_spi.c'; else $(CYGPATH_W) '$(srcdir)/hooks/set_ike_spi.c'; fi` + +set_ike_request.o: hooks/set_ike_request.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT set_ike_request.o -MD -MP -MF $(DEPDIR)/set_ike_request.Tpo -c -o set_ike_request.o `test -f 'hooks/set_ike_request.c' || echo '$(srcdir)/'`hooks/set_ike_request.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/set_ike_request.Tpo $(DEPDIR)/set_ike_request.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='hooks/set_ike_request.c' object='set_ike_request.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o set_ike_request.o `test -f 'hooks/set_ike_request.c' || echo '$(srcdir)/'`hooks/set_ike_request.c + +set_ike_request.obj: hooks/set_ike_request.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT set_ike_request.obj -MD -MP -MF $(DEPDIR)/set_ike_request.Tpo -c -o set_ike_request.obj `if test -f 'hooks/set_ike_request.c'; then $(CYGPATH_W) 'hooks/set_ike_request.c'; else $(CYGPATH_W) '$(srcdir)/hooks/set_ike_request.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/set_ike_request.Tpo $(DEPDIR)/set_ike_request.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='hooks/set_ike_request.c' object='set_ike_request.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o set_ike_request.obj `if test -f 'hooks/set_ike_request.c'; then $(CYGPATH_W) 'hooks/set_ike_request.c'; else $(CYGPATH_W) '$(srcdir)/hooks/set_ike_request.c'; fi` + +set_reserved.o: hooks/set_reserved.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT set_reserved.o -MD -MP -MF $(DEPDIR)/set_reserved.Tpo -c -o set_reserved.o `test -f 'hooks/set_reserved.c' || echo '$(srcdir)/'`hooks/set_reserved.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/set_reserved.Tpo $(DEPDIR)/set_reserved.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='hooks/set_reserved.c' object='set_reserved.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o set_reserved.o `test -f 'hooks/set_reserved.c' || echo '$(srcdir)/'`hooks/set_reserved.c + +set_reserved.obj: hooks/set_reserved.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT set_reserved.obj -MD -MP -MF $(DEPDIR)/set_reserved.Tpo -c -o set_reserved.obj `if test -f 'hooks/set_reserved.c'; then $(CYGPATH_W) 'hooks/set_reserved.c'; else $(CYGPATH_W) '$(srcdir)/hooks/set_reserved.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/set_reserved.Tpo $(DEPDIR)/set_reserved.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='hooks/set_reserved.c' object='set_reserved.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o set_reserved.obj `if test -f 'hooks/set_reserved.c'; then $(CYGPATH_W) 'hooks/set_reserved.c'; else $(CYGPATH_W) '$(srcdir)/hooks/set_reserved.c'; fi` + +set_ike_initiator.o: hooks/set_ike_initiator.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT set_ike_initiator.o -MD -MP -MF $(DEPDIR)/set_ike_initiator.Tpo -c -o set_ike_initiator.o `test -f 'hooks/set_ike_initiator.c' || echo '$(srcdir)/'`hooks/set_ike_initiator.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/set_ike_initiator.Tpo $(DEPDIR)/set_ike_initiator.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='hooks/set_ike_initiator.c' object='set_ike_initiator.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o set_ike_initiator.o `test -f 'hooks/set_ike_initiator.c' || echo '$(srcdir)/'`hooks/set_ike_initiator.c + +set_ike_initiator.obj: hooks/set_ike_initiator.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT set_ike_initiator.obj -MD -MP -MF $(DEPDIR)/set_ike_initiator.Tpo -c -o set_ike_initiator.obj `if test -f 'hooks/set_ike_initiator.c'; then $(CYGPATH_W) 'hooks/set_ike_initiator.c'; else $(CYGPATH_W) '$(srcdir)/hooks/set_ike_initiator.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/set_ike_initiator.Tpo $(DEPDIR)/set_ike_initiator.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='hooks/set_ike_initiator.c' object='set_ike_initiator.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o set_ike_initiator.obj `if test -f 'hooks/set_ike_initiator.c'; then $(CYGPATH_W) 'hooks/set_ike_initiator.c'; else $(CYGPATH_W) '$(srcdir)/hooks/set_ike_initiator.c'; fi` + +log_ts.o: hooks/log_ts.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT log_ts.o -MD -MP -MF $(DEPDIR)/log_ts.Tpo -c -o log_ts.o `test -f 'hooks/log_ts.c' || echo '$(srcdir)/'`hooks/log_ts.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/log_ts.Tpo $(DEPDIR)/log_ts.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='hooks/log_ts.c' object='log_ts.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o log_ts.o `test -f 'hooks/log_ts.c' || echo '$(srcdir)/'`hooks/log_ts.c + +log_ts.obj: hooks/log_ts.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT log_ts.obj -MD -MP -MF $(DEPDIR)/log_ts.Tpo -c -o log_ts.obj `if test -f 'hooks/log_ts.c'; then $(CYGPATH_W) 'hooks/log_ts.c'; else $(CYGPATH_W) '$(srcdir)/hooks/log_ts.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/log_ts.Tpo $(DEPDIR)/log_ts.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='hooks/log_ts.c' object='log_ts.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o log_ts.obj `if test -f 'hooks/log_ts.c'; then $(CYGPATH_W) 'hooks/log_ts.c'; else $(CYGPATH_W) '$(srcdir)/hooks/log_ts.c'; fi` + +rebuild_auth.o: hooks/rebuild_auth.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rebuild_auth.o -MD -MP -MF $(DEPDIR)/rebuild_auth.Tpo -c -o rebuild_auth.o `test -f 'hooks/rebuild_auth.c' || echo '$(srcdir)/'`hooks/rebuild_auth.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/rebuild_auth.Tpo $(DEPDIR)/rebuild_auth.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='hooks/rebuild_auth.c' object='rebuild_auth.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rebuild_auth.o `test -f 'hooks/rebuild_auth.c' || echo '$(srcdir)/'`hooks/rebuild_auth.c + +rebuild_auth.obj: hooks/rebuild_auth.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rebuild_auth.obj -MD -MP -MF $(DEPDIR)/rebuild_auth.Tpo -c -o rebuild_auth.obj `if test -f 'hooks/rebuild_auth.c'; then $(CYGPATH_W) 'hooks/rebuild_auth.c'; else $(CYGPATH_W) '$(srcdir)/hooks/rebuild_auth.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/rebuild_auth.Tpo $(DEPDIR)/rebuild_auth.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='hooks/rebuild_auth.c' object='rebuild_auth.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rebuild_auth.obj `if test -f 'hooks/rebuild_auth.c'; then $(CYGPATH_W) 'hooks/rebuild_auth.c'; else $(CYGPATH_W) '$(srcdir)/hooks/rebuild_auth.c'; fi` + +reset_seq.o: hooks/reset_seq.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT reset_seq.o -MD -MP -MF $(DEPDIR)/reset_seq.Tpo -c -o reset_seq.o `test -f 'hooks/reset_seq.c' || echo '$(srcdir)/'`hooks/reset_seq.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/reset_seq.Tpo $(DEPDIR)/reset_seq.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='hooks/reset_seq.c' object='reset_seq.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o reset_seq.o `test -f 'hooks/reset_seq.c' || echo '$(srcdir)/'`hooks/reset_seq.c + +reset_seq.obj: hooks/reset_seq.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT reset_seq.obj -MD -MP -MF $(DEPDIR)/reset_seq.Tpo -c -o reset_seq.obj `if test -f 'hooks/reset_seq.c'; then $(CYGPATH_W) 'hooks/reset_seq.c'; else $(CYGPATH_W) '$(srcdir)/hooks/reset_seq.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/reset_seq.Tpo $(DEPDIR)/reset_seq.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='hooks/reset_seq.c' object='reset_seq.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o reset_seq.obj `if test -f 'hooks/reset_seq.c'; then $(CYGPATH_W) 'hooks/reset_seq.c'; else $(CYGPATH_W) '$(srcdir)/hooks/reset_seq.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + 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; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + 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; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + 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) + 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)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + 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 -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: + for dir in "$(DESTDIR)$(ipsecdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +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" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-ipsecPROGRAMS clean-libtool \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-ipsecPROGRAMS + +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-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-ipsecPROGRAMS + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-ipsecPROGRAMS clean-libtool ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am \ + install-ipsecPROGRAMS install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-ipsecPROGRAMS + + +# 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/conftest/README b/src/conftest/README new file mode 100644 index 000000000..e2156921f --- /dev/null +++ b/src/conftest/README @@ -0,0 +1,315 @@ + + + conftest - an IKEv2 conformance testing framework + ================================================= + + +1. Introduction +--------------- + +conftest is a conformance testing framework for IKEv2 and related protocols, +based on the strongSwan IKEv2 daemon charon. It uses a specialized configuration +and control front-end, but links against the mainstream strongSwan IKEv2 stack. + +The conftest framework can test other implementations of IKEv2 and related +standards. It can inject or mangle packets to test the behavior of other +implementations under certain conditions. + +2. Test suites +-------------- + +The framework can use different sets of conformance tests, called test suites. +Each test suite contains a global suite configuration file, usually named +suite.conf. It contains the global settings for all tests in this suite, mostly +credentials and connection definitions. + +A test suite consists of several test cases. Each test has its own configuration +file, often called test.conf. The test configuration file may contain test +specific credentials and connection definitions, but primarily defines actions +and hooks. Actions trigger certain protocol specific operations, such as +initiating or terminating a tunnel. Hooks are used to change the behavior of +the IKE stack, most likely to stress some factors of the IKE protocol and +provoke unintended behavior in the tested platform. + +3. Configuration syntax +----------------------- + +Both the suite and the test specific configuration file use the same syntax. +It is the same as used by the strongswan.conf file used to configure the +strongSwan software suite. + +The syntax is as follows: + + settings := (section|keyvalue)* + section := name { settings } + keyvalue := key = value\n + +Settings contain zero or more sub-sections or key/value pairs. A section +consists of a name, followed by curly open and close brackets. The value in the +key/value pair starts after the equal sign and is terminated by the end of the +line. + +The test specific configuration is merged to the suite configuration, resulting +in a unified configuration. Sections are merged, keys in the test configuration +overwrite existing identical keys in the suite configuration. + +4. Logging +---------- + +Logging verbosity can be controlled in the log section of a suite/test +configuration. The stdout subsection takes logging facility/verbosity key +value pairs, the different facility types are defined in debug_lower_names at +src/libstrongswan/debug.c. +Any other sub-section in the log section is considered as a file name to log +to. Each section takes the same facility/verbosity keys as the special stdout +section. + +5. Connections +-------------- + +Both the suite and test configuration may contain connection definitions under +the configs section. Each IKE_SA configuration has a sub-section. Each IKE_SA +sub-section contains one or more CHILD_SA configuration sub-sections: + +configs { + ike-a { + # ... ike options + child-a1 { + # ... child options + } + child-a2 { + # ... + } + } +} + +Configuration names can be chosen arbitrary, but should be unique within the +same file. + +The IKE_SA configuration uses the following options (as key/value pairs): + + lhost: Address (IP or Hostname) of this host + rhost: Address (IP or Hostname) of tested host + lid: IKEv2 identifier of this host + rid: IKEv2 identifier of tested host + proposal: IKE_SA proposal list, comma separated, e.g.: + aes128-sha1-modp2048,3des-md5-sha1-modp1024-modp1536 + Supported algorithm names are defined under + src/libstrongswan/crypt/proposal/proposal_keywords.txt + fake_nat: Fake the NAT_DETECTION_*_IP payloads to simulate a NAT + scenario + rsa_strength: connection requires a trustchain with RSA keys of given bits + ecdsa_strength: connection requires a trustchain with ECDSA keys of given bits + cert_policy: connection requries a certificate with the given OID policy + +The following CHILD_SA specific configuration options are supported: + + lts: Local side traffic selectors, comma separated CIDR subnets + rts: Remote side traffic selectors, comma separated CIDR subnets + transport: Propose IPsec transport mode instead of tunnel mode + tfc_padding: Inject Traffic Flow Confidentialty bytes to align packets to the + given length + +6. Credentials +-------------- + +Credentials may be defined globally in the suite or locally in the test specific +configuration file. Certificates files are defined in the certs section, either +in the trusted or in the untrusted section. Trusted certificates are trust +anchors, usually root CA certificates. Untrusted certificates do not build a +trust anchor and usually contain intermediate or end entity certificates. + +Certificates files are loaded relative to the configuration file path and may +be encoded either in plain ASN.1 DER or in PEM format. The prefix of the +key/value pair is used to specify the type of the certificate, usually x509 or +crl. + +Private keys can be defined in the suite or test config file under the keys +section. The prefix of the key/value pair must be either rsa or ecdsa, the +specified file may be encoded in ASN.1 DER or unencrypted PEM. + +certs { + trusted { + x509-a-ca = ca.pem + } + untrusted { + x509-me = /path/to/cert.pem + crl-from-ca = /path/to/crl.pem + } +} +keys { + ecdsa-me = /path/to/key.pem +} + +7. Actions +---------- + +The actions section in the test specific configuration file defines +the IKEv2 protocol actions to trigger. Currently, the following actions +are supported and take these arguments (as key/value pairs): + + initiate: Initiate an IKE- and CHILD_SA + config: name of the CHILD_SA configuration to initiate + delay: Delay to trigger action after startup + rekey_ike: Rekey an IKE_SA + config: name of originating IKE_SA configuration + delay: Delay to trigger action after startup + rekey_child: Rekey an CHILD_SA + config: name of originating CHILD_SA configuration + delay: Delay to trigger action after startup + liveness: Do a liveness check (DPD) on the IKE_SA + config: name of originating IKE_SA configuration + delay: Delay to trigger action after startup + close_ike: Close an IKE_SA + config: name of originating IKE_SA configuration + delay: Delay to trigger action after startup + close_child: Close a CHILD_SA + config: name of originating IKE_SA configuration + delay: Delay to trigger action after startup + +To trigger the same action multiple times, the action sections must be named +uniquely. Append an arbitrary string to the action name. The following example +initiates a connection and rekeys it twice: + +actions { + initiate { + config = child-a1 + } + rekey_ike-1 { + config = ike-a + delay = 3 + } + rekey_ike-2 { + config = ike-a + delay = 6 + } +} + +8. Hooks +-------- + +The hooks section section in the test configuration defines different hooks +to use to mangle packets or trigger other protocol modifications. These +hook functions are implemented in the hooks folder of conftest. + +Currently, the following hooks are defined with the following options: + + add_notify: Add a notify to a message + request: yes to include in request, no in response + id: IKEv2 message identifier of message to add notify + type: notify type to add, names defined in notify_type_names + under src/libcharon/encoding/payloads/notify_payload.c + data: notification data to add, prepend 0x to interpret the + string as hex string + spi: SPI to use in notify + esp: yes to send an ESP protocol notify, no for IKE + add_payload: Add an arbitrary payload to a message + request: yes to include in request, no in response + id: IKEv2 message identifier of message to add payload + type: type of the payload to add, names defined in + payload_type_short_names in payload.c + data: data to append after generic payload header, use 0x + prefix for hex encoded data + critical: yes to set payload critical bit + replace: yes to replace an existing payload of the same type + custom_proposal: set a custom proposal value in the SA payload + request: yes to include in request, no in response + id: IKEv2 message identifier of message to add notify + The hook takes subsections with numerical names, each + defining a proposal substructure. The substructure + takes key/value pairs, where key defines the type, value + the specific algorithm. + force_cookie: Reject IKE_SA_INIT requests with a COOKIE + ignore_message: Ignore a specific message, simulating packet loss + inbound: yes to ignore incoming, no for outgoing messages + request: yes to ignore requests, no for responses + id: IKEv2 message identifier of message to ignore + ike_auth_fill: Fill up IKE_AUTH message to a given size using a CERT + payload. + request: yes to fill requests messages, no for responses + id: IKEv2 message identifier of message to fill up + bytes: number of bytes the final IKE_AUTH message should have + log_id: Comfortably log received ID payload contents + log_ke: Comfortably log received KE payload DH groups + log_proposal: Comfortably log all proposals received in SA payloads + log_ts: Comfortably log all received TS payloads + pretend_auth: magically reconstruct IKE_AUTH response even if + AUTHENTICATION_FAILED received + rebuild_auth: rebuild AUTH payload, i.e. if ID payload changed + reset_seq: Reset sequence numbers of an ESP SA + delay: Seconds to delay reset after SA established + set_critical: Set critical bit on existing payloads: + request: yes to set in request, no in response + id: IKEv2 message identifier of message to mangle payloads + payloads: space separated payload list to set critical bit on + set_ike_initiator: toggle IKE initiator flag in IKE header + request: yes to set in request, no in response + id: IKEv2 message identifier of message to mangle + set_ike_request: toggle IKE request flag in IKE header + request: yes to set in request, no in response + id: IKEv2 message identifier of message to mangle + set_ike_spi: set the IKE SPIs in IKE header + request: yes to set in request, no in response + id: IKEv2 message identifier of message to mangle + spii: initiator SPI to set (as decimal integer) + spir: responder SPI to set + set_ike_version: set version fields in IKE header + request: yes to set in request, no in response + id: IKEv2 message identifier of message to mangle + major: major version to set + minor: minor version to set + higher: yes to set Higher Version Supported flag + set_length: set the length in a payload header + request: yes to set in request, no in response + id: IKEv2 message identifier of message to mangle + type: payload type to mangle + diff: difference to add/remove from real length (+1,-3 etc.) + set_proposal_number:Change the number of a proposal in a SA payload + request: yes to set in request, no in response + id: IKEv2 message identifier of message to mangle + from: proposal number to mangle + to: new porposal number to set instead of from + set_reserved: set arbitrary reserved bits/bytes in payloads + request: yes to set in request, no in response + id: IKEv2 message identifier of message to mangle + The hook takes a list of subsection, each named as payload + type. Each section takes a bits and a bytes key, the + value is a comma separated list of decimal numbers of + bits/bytes to mangle (1 is the first reserved bit/byte + in the payload). The byteval key defines to which value + set mangled bytes in the byte list. + unencrypted_notify: Send an unencrypted message with a notify after + establishing an IKE_SA + id: IKEv2 message identifier of message to send + type: notify type to add, names defined in notify_type_names + under src/libcharon/encoding/payloads/notify_payload.c + data: notification data to add, prepend 0x to interpret the + string as hex string + spi: SPI to use in notify + esp: yes to send an ESP protocol notify, no for IKE + unsort_message: reorder the payloads in a message + request: yes to reorder requests messages, no for responses + id: IKEv2 message identifier of message to reorder + order: payload order, space separated payload names as defined + in payload_type_short_names under + src/libcharon/encoding/payloads/payload.c + +9. Invoking +----------- + +Compile time options required depend on the test suite. A minimalistic +strongSwan build with the OpenSSL crypto backend can be configured with: + +./configure --sysconfdir=/etc --disable-pluto --disable-scripts \ + --disable-tools --disable-aes --disable-des --disable-md5 \ + --disable-sha1 --disable-sha2 --disable-fips-prf --disable-gmp \ + --disable-pubkey --disable-pgp --disable-dnskey --disable-updown \ + --disable-attr --disable-resolve --enable-openssl --enable-conftest \ + --enable-gcm --enable-ccm --enable-ctr + +The conftest utility is installed by default under /usr/local/libexec/ipsec/, +but can be invoked with the ipsec helper script. It takes a suite specific +configuration file after the --suite option and a test specific file with +the --test option: + + ipsec conftest --suite suite.conf --test 1.1.1/test.conf diff --git a/src/conftest/actions.c b/src/conftest/actions.c new file mode 100644 index 000000000..e66e9d7f1 --- /dev/null +++ b/src/conftest/actions.c @@ -0,0 +1,339 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * 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 "actions.h" +#include "conftest.h" + +#include <daemon.h> +#include <processing/jobs/callback_job.h> +#include <processing/jobs/rekey_ike_sa_job.h> +#include <processing/jobs/rekey_child_sa_job.h> +#include <processing/jobs/send_dpd_job.h> + +typedef struct private_actions_t private_actions_t; + +/** + * Private data of an actions_t object. + */ +struct private_actions_t { + + /** + * Public actions_t interface. + */ + actions_t public; +}; + +/** + * Initiate a CHILD_SA + */ +static job_requeue_t initiate(char *config) +{ + peer_cfg_t *peer_cfg; + child_cfg_t *child_cfg = NULL, *current; + enumerator_t *enumerator; + + peer_cfg = charon->backends->get_peer_cfg_by_name(charon->backends, config); + if (!peer_cfg) + { + DBG1(DBG_CFG, "initiating '%s' failed, config not found", config); + return JOB_REQUEUE_NONE; + } + enumerator = peer_cfg->create_child_cfg_enumerator(peer_cfg); + while (enumerator->enumerate(enumerator, ¤t)) + { + if (streq(current->get_name(current), config)) + { + child_cfg = current; + child_cfg->get_ref(child_cfg); + break; + } + } + enumerator->destroy(enumerator); + if (child_cfg) + { + DBG1(DBG_CFG, "initiating IKE_SA for CHILD_SA config '%s'", config); + charon->controller->initiate(charon->controller, peer_cfg, child_cfg, + NULL, NULL); + } + else + { + DBG1(DBG_CFG, "initiating '%s' failed, CHILD_SA config not found", + config); + } + + return JOB_REQUEUE_NONE; +} + +/** + * Rekey an IKE_SA + */ +static job_requeue_t rekey_ike(char *config) +{ + enumerator_t *enumerator; + job_t *job = NULL; + ike_sa_t *ike_sa; + + enumerator = charon->controller->create_ike_sa_enumerator(charon->controller); + while (enumerator->enumerate(enumerator, &ike_sa)) + { + if (strcaseeq(config, ike_sa->get_name(ike_sa))) + { + job = (job_t*)rekey_ike_sa_job_create(ike_sa->get_id(ike_sa), FALSE); + break; + } + } + enumerator->destroy(enumerator); + + if (job) + { + DBG1(DBG_CFG, "starting rekey of IKE_SA '%s'", config); + lib->processor->queue_job(lib->processor, job); + } + else + { + DBG1(DBG_CFG, "rekeying '%s' failed, IKE_SA not found", config); + } + return JOB_REQUEUE_NONE; +} + +/** + * Rekey an CHILD_SA + */ +static job_requeue_t rekey_child(char *config) +{ + enumerator_t *enumerator; + iterator_t *children; + ike_sa_t *ike_sa; + child_sa_t *child_sa; + u_int32_t reqid = 0, spi = 0; + protocol_id_t proto = PROTO_ESP; + + enumerator = charon->controller->create_ike_sa_enumerator(charon->controller); + while (enumerator->enumerate(enumerator, &ike_sa)) + { + children = ike_sa->create_child_sa_iterator(ike_sa); + while (children->iterate(children, (void**)&child_sa)) + { + if (streq(config, child_sa->get_name(child_sa))) + { + reqid = child_sa->get_reqid(child_sa); + proto = child_sa->get_protocol(child_sa); + spi = child_sa->get_spi(child_sa, TRUE); + break; + } + } + children->destroy(children); + } + enumerator->destroy(enumerator); + if (reqid) + { + DBG1(DBG_CFG, "starting rekey of CHILD_SA '%s'", config); + lib->processor->queue_job(lib->processor, + (job_t*)rekey_child_sa_job_create(reqid, proto, spi)); + } + else + { + DBG1(DBG_CFG, "rekeying '%s' failed, CHILD_SA not found", config); + } + return JOB_REQUEUE_NONE; +} + +/** + * Do a liveness check + */ +static job_requeue_t liveness(char *config) +{ + enumerator_t *enumerator; + job_t *job = NULL; + ike_sa_t *ike_sa; + + enumerator = charon->controller->create_ike_sa_enumerator(charon->controller); + while (enumerator->enumerate(enumerator, &ike_sa)) + { + if (strcaseeq(config, ike_sa->get_name(ike_sa))) + { + job = (job_t*)send_dpd_job_create(ike_sa->get_id(ike_sa)); + break; + } + } + enumerator->destroy(enumerator); + + if (job) + { + DBG1(DBG_CFG, "starting liveness check of IKE_SA '%s'", config); + lib->processor->queue_job(lib->processor, job); + } + else + { + DBG1(DBG_CFG, "liveness check for '%s' failed, IKE_SA not found", config); + } + return JOB_REQUEUE_NONE; +} + +/** + * Close an IKE_SA with all CHILD_SAs + */ +static job_requeue_t close_ike(char *config) +{ + enumerator_t *enumerator; + ike_sa_t *ike_sa; + int id = 0; + + enumerator = charon->controller->create_ike_sa_enumerator(charon->controller); + while (enumerator->enumerate(enumerator, &ike_sa)) + { + if (strcaseeq(config, ike_sa->get_name(ike_sa))) + { + id = ike_sa->get_unique_id(ike_sa); + break; + } + } + enumerator->destroy(enumerator); + if (id) + { + DBG1(DBG_CFG, "closing IKE_SA '%s'", config); + charon->controller->terminate_ike(charon->controller, id, NULL, NULL); + } + else + { + DBG1(DBG_CFG, "unable to close IKE_SA '%s', not found", config); + } + return JOB_REQUEUE_NONE; +} + +/** + * Close a CHILD_SAs + */ +static job_requeue_t close_child(char *config) +{ + enumerator_t *enumerator; + iterator_t *children; + ike_sa_t *ike_sa; + child_sa_t *child_sa; + int id = 0; + + enumerator = charon->controller->create_ike_sa_enumerator(charon->controller); + while (enumerator->enumerate(enumerator, &ike_sa)) + { + + children = ike_sa->create_child_sa_iterator(ike_sa); + while (children->iterate(children, (void**)&child_sa)) + { + if (streq(config, child_sa->get_name(child_sa))) + { + id = child_sa->get_reqid(child_sa); + break; + } + } + children->destroy(children); + } + enumerator->destroy(enumerator); + if (id) + { + DBG1(DBG_CFG, "closing CHILD_SA '%s'", config); + charon->controller->terminate_child(charon->controller, id, NULL, NULL); + } + else + { + DBG1(DBG_CFG, "unable to close CHILD_SA '%s', not found", config); + } + return JOB_REQUEUE_NONE; +} + +/** + * Load a single action + */ +static void load_action(settings_t *settings, char *action) +{ + static struct { + char *name; + callback_job_cb_t cb; + } actions[] = { + {"initiate", (void*)initiate}, + {"rekey_ike", (void*)rekey_ike}, + {"rekey_child", (void*)rekey_child}, + {"liveness", (void*)liveness}, + {"close_ike", (void*)close_ike}, + {"close_child", (void*)close_child}, + }; + bool found = FALSE; + int i; + + for (i = 0; i < countof(actions); i++) + { + if (strncaseeq(actions[i].name, action, strlen(actions[i].name))) + { + int delay; + char *config; + + found = TRUE; + delay = settings->get_int(settings, "actions.%s.delay", 0, action); + config = settings->get_str(settings, "actions.%s.config", + NULL, action); + if (!config) + { + DBG1(DBG_CFG, "no config defined for action '%s'", action); + break; + } + lib->scheduler->schedule_job(lib->scheduler, + (job_t*)callback_job_create(actions[i].cb, config, NULL, NULL), + delay); + } + } + if (!found) + { + DBG1(DBG_CFG, "unknown action '%s', skipped", action); + } +} + +/** + * Load configured actions + */ +static void load_actions(settings_t *settings) +{ + enumerator_t *enumerator; + char *action; + + enumerator = settings->create_section_enumerator(settings, "actions"); + while (enumerator->enumerate(enumerator, &action)) + { + load_action(settings, action); + } + enumerator->destroy(enumerator); +} + +METHOD(actions_t, destroy, void, + private_actions_t *this) +{ + free(this); +} + +/** + * See header + */ +actions_t *actions_create() +{ + private_actions_t *this; + + INIT(this, + .public = { + .destroy = _destroy, + }, + ); + + load_actions(conftest->test); + + return &this->public; +} diff --git a/src/conftest/actions.h b/src/conftest/actions.h new file mode 100644 index 000000000..2e1cbbacd --- /dev/null +++ b/src/conftest/actions.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * 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. + */ + +/** + * @defgroup actions actions + * @{ @ingroup conftest + */ + +#ifndef ACTIONS_H_ +#define ACTIONS_H_ + +typedef struct actions_t actions_t; + +/** + * actionss to trigger based on configuration. + */ +struct actions_t { + + /** + * Destroy a actions_t. + */ + void (*destroy)(actions_t *this); +}; + +/** + * Create a actions instance. + */ +actions_t *actions_create(); + +#endif /** ACTIONS_H_ @}*/ diff --git a/src/conftest/config.c b/src/conftest/config.c new file mode 100644 index 000000000..952141211 --- /dev/null +++ b/src/conftest/config.c @@ -0,0 +1,343 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * 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 "config.h" + +#include <daemon.h> +#include <conftest.h> + +typedef struct private_config_t private_config_t; + +/** + * Private data of an config_t object. + */ +struct private_config_t { + + /** + * Public config_t interface. + */ + config_t public; + + /** + * List of loaded peer configs + */ + linked_list_t *configs; +}; + +/** + * filter function for ike configs + */ +static bool ike_filter(void *data, peer_cfg_t **in, ike_cfg_t **out) +{ + *out = (*in)->get_ike_cfg(*in); + return TRUE; +} + +METHOD(backend_t, create_ike_cfg_enumerator, enumerator_t*, + private_config_t *this, host_t *me, host_t *other) +{ + + return enumerator_create_filter( + this->configs->create_enumerator(this->configs), + (void*)ike_filter, NULL, NULL); +} + +METHOD(backend_t, create_peer_cfg_enumerator, enumerator_t*, + private_config_t *this, identification_t *me, identification_t *other) +{ + return this->configs->create_enumerator(this->configs); +} + +METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*, + private_config_t *this, char *name) +{ + enumerator_t *e1, *e2; + peer_cfg_t *current, *found = NULL; + child_cfg_t *child; + + e1 = this->configs->create_enumerator(this->configs); + while (e1->enumerate(e1, ¤t)) + { + e2 = current->create_child_cfg_enumerator(current); + while (e2->enumerate(e2, &child)) + { + if (streq(child->get_name(child), name)) + { + found = current; + found->get_ref(found); + break; + } + } + e2->destroy(e2); + if (found) + { + break; + } + } + e1->destroy(e1); + return found; +} + +/** + * Load IKE config for a given section name + */ +static ike_cfg_t *load_ike_config(private_config_t *this, + settings_t *settings, char *config) +{ + enumerator_t *enumerator; + ike_cfg_t *ike_cfg; + proposal_t *proposal; + char *token; + + ike_cfg = ike_cfg_create(TRUE, + settings->get_bool(settings, "configs.%s.fake_nat", FALSE, config), + settings->get_str(settings, "configs.%s.lhost", "%any", config), + settings->get_int(settings, "configs.%s.lport", 500, config), + settings->get_str(settings, "configs.%s.rhost", "%any", config), + settings->get_int(settings, "configs.%s.rport", 500, config)); + token = settings->get_str(settings, "configs.%s.proposal", NULL, config); + if (token) + { + enumerator = enumerator_create_token(token, ",", " "); + while (enumerator->enumerate(enumerator, &token)) + { + proposal = proposal_create_from_string(PROTO_IKE, token); + if (proposal) + { + ike_cfg->add_proposal(ike_cfg, proposal); + } + else + { + DBG1(DBG_CFG, "parsing proposal '%s' failed, skipped", token); + } + } + enumerator->destroy(enumerator); + } + else + { + ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE)); + } + return ike_cfg; +} +/** + * Load CHILD config for given section names + */ +static child_cfg_t *load_child_config(private_config_t *this, + settings_t *settings, char *config, char *child) +{ + child_cfg_t *child_cfg; + lifetime_cfg_t lifetime = {}; + enumerator_t *enumerator; + proposal_t *proposal; + traffic_selector_t *ts; + ipsec_mode_t mode = MODE_TUNNEL; + host_t *net; + char *token; + int bits; + u_int32_t tfc; + + if (settings->get_bool(settings, "configs.%s.%s.transport", + FALSE, config, child)) + { + mode = MODE_TRANSPORT; + } + tfc = settings->get_int(settings, "configs.%s.%s.tfc_padding", + 0, config, child); + child_cfg = child_cfg_create(child, &lifetime, NULL, FALSE, mode, + ACTION_NONE, ACTION_NONE, ACTION_NONE, + FALSE, 0, 0, NULL, NULL, tfc); + + token = settings->get_str(settings, "configs.%s.%s.proposal", + NULL, config, child); + if (token) + { + enumerator = enumerator_create_token(token, ",", " "); + while (enumerator->enumerate(enumerator, &token)) + { + proposal = proposal_create_from_string(PROTO_ESP, token); + if (proposal) + { + child_cfg->add_proposal(child_cfg, proposal); + } + else + { + DBG1(DBG_CFG, "parsing proposal '%s' failed, skipped", token); + } + } + enumerator->destroy(enumerator); + } + else + { + child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP)); + } + + token = settings->get_str(settings, "configs.%s.%s.lts", NULL, config); + if (token) + { + enumerator = enumerator_create_token(token, ",", " "); + while (enumerator->enumerate(enumerator, &token)) + { + net = host_create_from_subnet(token, &bits); + if (net) + { + ts = traffic_selector_create_from_subnet(net, bits, 0, 0); + child_cfg->add_traffic_selector(child_cfg, TRUE, ts); + } + else + { + DBG1(DBG_CFG, "invalid local ts: %s, skipped", token); + } + } + enumerator->destroy(enumerator); + } + else + { + ts = traffic_selector_create_dynamic(0, 0, 65535); + child_cfg->add_traffic_selector(child_cfg, TRUE, ts); + } + + token = settings->get_str(settings, "configs.%s.%s.rts", NULL, config); + if (token) + { + enumerator = enumerator_create_token(token, ",", " "); + while (enumerator->enumerate(enumerator, &token)) + { + net = host_create_from_subnet(token, &bits); + if (net) + { + ts = traffic_selector_create_from_subnet(net, bits, 0, 0); + child_cfg->add_traffic_selector(child_cfg, FALSE, ts); + } + else + { + DBG1(DBG_CFG, "invalid remote ts: %s, skipped", token); + } + } + enumerator->destroy(enumerator); + } + else + { + ts = traffic_selector_create_dynamic(0, 0, 65535); + child_cfg->add_traffic_selector(child_cfg, FALSE, ts); + } + return child_cfg; +} + +/** + * Load peer config for a given section name + */ +static peer_cfg_t *load_peer_config(private_config_t *this, + settings_t *settings, char *config) +{ + ike_cfg_t *ike_cfg; + peer_cfg_t *peer_cfg; + auth_cfg_t *auth; + child_cfg_t *child_cfg; + enumerator_t *enumerator; + identification_t *lid, *rid; + char *child, *policy; + uintptr_t strength; + + ike_cfg = load_ike_config(this, settings, config); + peer_cfg = peer_cfg_create(config, 2, ike_cfg, CERT_ALWAYS_SEND, + UNIQUE_NO, 1, 0, 0, 0, 0, FALSE, 0, + NULL, NULL, FALSE, NULL, NULL); + + auth = auth_cfg_create(); + auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY); + lid = identification_create_from_string( + settings->get_str(settings, "configs.%s.lid", "%any", config)); + auth->add(auth, AUTH_RULE_IDENTITY, lid); + peer_cfg->add_auth_cfg(peer_cfg, auth, TRUE); + + auth = auth_cfg_create(); + auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY); + rid = identification_create_from_string( + settings->get_str(settings, "configs.%s.rid", "%any", config)); + strength = settings->get_int(settings, "configs.%s.rsa_strength", 0); + if (strength) + { + auth->add(auth, AUTH_RULE_RSA_STRENGTH, strength); + } + strength = settings->get_int(settings, "configs.%s.ecdsa_strength", 0); + if (strength) + { + auth->add(auth, AUTH_RULE_ECDSA_STRENGTH, strength); + } + policy = settings->get_str(settings, "configs.%s.cert_policy", NULL, config); + if (policy) + { + auth->add(auth, AUTH_RULE_CERT_POLICY, strdup(policy)); + } + auth->add(auth, AUTH_RULE_IDENTITY, rid); + peer_cfg->add_auth_cfg(peer_cfg, auth, FALSE); + + DBG1(DBG_CFG, "loaded config %s: %Y - %Y", config, lid, rid); + + enumerator = settings->create_section_enumerator(settings, + "configs.%s", config); + while (enumerator->enumerate(enumerator, &child)) + { + child_cfg = load_child_config(this, settings, config, child); + peer_cfg->add_child_cfg(peer_cfg, child_cfg); + } + enumerator->destroy(enumerator); + return peer_cfg; +} + +METHOD(config_t, load, void, + private_config_t *this, settings_t *settings) +{ + enumerator_t *enumerator; + char *config; + + enumerator = settings->create_section_enumerator(settings, "configs"); + while (enumerator->enumerate(enumerator, &config)) + { + this->configs->insert_last(this->configs, + load_peer_config(this, settings, config)); + } + enumerator->destroy(enumerator); +} + +METHOD(config_t, destroy, void, + private_config_t *this) +{ + this->configs->destroy_offset(this->configs, offsetof(peer_cfg_t, destroy)); + free(this); +} + +/** + * See header + */ +config_t *config_create() +{ + private_config_t *this; + + INIT(this, + .public = { + .backend = { + .create_ike_cfg_enumerator = _create_ike_cfg_enumerator, + .create_peer_cfg_enumerator = _create_peer_cfg_enumerator, + .get_peer_cfg_by_name = _get_peer_cfg_by_name, + }, + .load = _load, + .destroy = _destroy, + }, + .configs = linked_list_create(), + ); + + return &this->public; +} diff --git a/src/conftest/config.h b/src/conftest/config.h new file mode 100644 index 000000000..2a62b9ce0 --- /dev/null +++ b/src/conftest/config.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * 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. + */ + +/** + * @defgroup config config + * @{ @ingroup conftest + */ + +#ifndef CONFIG_H_ +#define CONFIG_H_ + +typedef struct config_t config_t; + +#include <config/backend.h> + +/** + * Conftest IKE and CHILD config backend + */ +struct config_t { + + /** + * Implements the backend_t interface. + */ + backend_t backend; + + /** + * Load configurations from a settings file. + * + * @param settings settings file to load configs from + */ + void (*load)(config_t *this, settings_t *settings); + + /** + * Destroy a config_t. + */ + void (*destroy)(config_t *this); +}; + +/** + * Create a config instance. + */ +config_t *config_create(); + +#endif /** CONFIG_H_ @}*/ diff --git a/src/conftest/conftest.c b/src/conftest/conftest.c new file mode 100644 index 000000000..fea88818e --- /dev/null +++ b/src/conftest/conftest.c @@ -0,0 +1,550 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * 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. + */ + +#define _GNU_SOURCE +#include <unistd.h> +#include <stdio.h> +#include <errno.h> +#include <signal.h> +#include <getopt.h> +#include <dlfcn.h> +#include <libgen.h> + +#include "conftest.h" +#include "config.h" +#include "hooks/hook.h" + +#include <threading/thread.h> +#include <credentials/certificates/x509.h> + +/** + * Conftest globals struct + */ +conftest_t *conftest; + +/** + * Print usage information + */ +static void usage(FILE *out) +{ + fprintf(out, "Usage:\n"); + fprintf(out, " --help show usage information\n"); + fprintf(out, " --version show conftest version\n"); + fprintf(out, " --suite <file> global testsuite configuration " + "(default: ./suite.conf)\n"); + fprintf(out, " --test <file> test specific configuration\n"); +} + +/** + * Handle SIGSEGV/SIGILL signals raised by threads + */ +static void segv_handler(int signal) +{ + fprintf(stderr, "thread %u received %d\n", thread_current_id(), signal); + abort(); +} + +/** + * Load suite and test specific configurations + */ +static bool load_configs(char *suite_file, char *test_file) +{ + if (!test_file) + { + fprintf(stderr, "Missing test configuration file.\n"); + return FALSE; + } + if (access(suite_file, R_OK) != 0) + { + fprintf(stderr, "Reading suite configuration file '%s' failed: %s.\n", + suite_file, strerror(errno)); + return FALSE; + } + if (access(test_file, R_OK) != 0) + { + fprintf(stderr, "Reading test configuration file '%s' failed: %s.\n", + test_file, strerror(errno)); + return FALSE; + } + conftest->test = settings_create(suite_file); + conftest->test->load_files(conftest->test, test_file); + conftest->suite_dir = strdup(dirname(suite_file)); + return TRUE; +} + +/** + * Load trusted/untrusted certificates + */ +static bool load_cert(settings_t *settings, bool trusted) +{ + enumerator_t *enumerator; + char *key, *value; + + enumerator = settings->create_key_value_enumerator(settings, + trusted ? "certs.trusted" : "certs.untrusted"); + while (enumerator->enumerate(enumerator, &key, &value)) + { + certificate_t *cert = NULL; + + if (strncaseeq(key, "x509", strlen("x509"))) + { + cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, + CERT_X509, BUILD_FROM_FILE, value, BUILD_END); + } + else if (strncaseeq(key, "crl", strlen("crl"))) + { + cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, + CERT_X509_CRL, BUILD_FROM_FILE, value, BUILD_END); + } + else + { + fprintf(stderr, "certificate type '%s' not supported\n", key); + enumerator->destroy(enumerator); + return FALSE; + } + if (!cert) + { + fprintf(stderr, "loading %strusted certificate '%s' from '%s' " + "failed\n", trusted ? "" : "un", key, value); + enumerator->destroy(enumerator); + return FALSE; + } + conftest->creds->add_cert(conftest->creds, trusted, cert); + } + enumerator->destroy(enumerator); + return TRUE; +} + +/** + * Load certificates from the confiuguration file + */ +static bool load_certs(settings_t *settings, char *dir) +{ + char wd[PATH_MAX]; + + if (getcwd(wd, sizeof(wd)) == NULL) + { + fprintf(stderr, "getting cwd failed: %s\n", strerror(errno)); + return FALSE; + } + if (chdir(dir) != 0) + { + fprintf(stderr, "opening directory '%s' failed: %s\n", + dir, strerror(errno)); + return FALSE; + } + + if (!load_cert(settings, TRUE) || + !load_cert(settings, FALSE)) + { + return FALSE; + } + + if (chdir(wd) != 0) + { + fprintf(stderr, "opening directory '%s' failed: %s\n", + wd, strerror(errno)); + return FALSE; + } + return TRUE; +} + +/** + * Load private keys from the confiuguration file + */ +static bool load_keys(settings_t *settings, char *dir) +{ + enumerator_t *enumerator; + char *type, *value, wd[PATH_MAX]; + private_key_t *key; + key_type_t key_type; + + if (getcwd(wd, sizeof(wd)) == NULL) + { + fprintf(stderr, "getting cwd failed: %s\n", strerror(errno)); + return FALSE; + } + if (chdir(dir) != 0) + { + fprintf(stderr, "opening directory '%s' failed: %s\n", + dir, strerror(errno)); + return FALSE; + } + + enumerator = settings->create_key_value_enumerator(settings, "keys"); + while (enumerator->enumerate(enumerator, &type, &value)) + { + if (strncaseeq(type, "ecdsa", strlen("ecdsa"))) + { + key_type = KEY_ECDSA; + } + else if (strncaseeq(type, "rsa", strlen("rsa"))) + { + key_type = KEY_RSA; + } + else + { + fprintf(stderr, "unknown key type: '%s'\n", type); + enumerator->destroy(enumerator); + return FALSE; + } + key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, key_type, + BUILD_FROM_FILE, value, BUILD_END); + if (!key) + { + fprintf(stderr, "loading %s key from '%s' failed\n", type, value); + enumerator->destroy(enumerator); + return FALSE; + } + conftest->creds->add_key(conftest->creds, key); + } + enumerator->destroy(enumerator); + + if (chdir(wd) != 0) + { + fprintf(stderr, "opening directory '%s' failed: %s\n", + wd, strerror(errno)); + return FALSE; + } + return TRUE; +} + +/** + * Load certificate distribution points + */ +static void load_cdps(settings_t *settings) +{ + enumerator_t *enumerator; + identification_t *id; + char *ca, *uri, *section; + certificate_type_t type; + x509_t *x509; + + enumerator = settings->create_section_enumerator(settings, "cdps"); + while (enumerator->enumerate(enumerator, §ion)) + { + if (strncaseeq(section, "crl", strlen("crl"))) + { + type = CERT_X509_CRL; + } + else if (strncaseeq(section, "ocsp", strlen("ocsp"))) + { + type = CERT_X509_OCSP_RESPONSE; + } + else + { + fprintf(stderr, "unknown cdp type '%s', ignored\n", section); + continue; + } + + uri = settings->get_str(settings, "cdps.%s.uri", NULL, section); + ca = settings->get_str(settings, "cdps.%s.ca", NULL, section); + if (!ca || !uri) + { + fprintf(stderr, "cdp '%s' misses ca/uri, ignored\n", section); + continue; + } + x509 = lib->creds->create(lib->creds, CRED_CERTIFICATE, + CERT_X509, BUILD_FROM_FILE, ca, BUILD_END); + if (!x509) + { + fprintf(stderr, "loading cdp '%s' ca failed, ignored\n", section); + continue; + } + id = identification_create_from_encoding(ID_KEY_ID, + x509->get_subjectKeyIdentifier(x509)); + conftest->creds->add_cdp(conftest->creds, type, id, uri); + DESTROY_IF((certificate_t*)x509); + id->destroy(id); + } + enumerator->destroy(enumerator); +} + +/** + * Load configured hooks + */ +static bool load_hooks() +{ + enumerator_t *enumerator; + char *name, *pos, buf[64]; + hook_t *(*create)(char*); + hook_t *hook; + + enumerator = conftest->test->create_section_enumerator(conftest->test, + "hooks"); + while (enumerator->enumerate(enumerator, &name)) + { + pos = strchr(name, '-'); + if (pos) + { + snprintf(buf, sizeof(buf), "%.*s_hook_create", pos - name, name); + } + else + { + snprintf(buf, sizeof(buf), "%s_hook_create", name); + } + create = dlsym(RTLD_DEFAULT, buf); + if (create) + { + hook = create(name); + if (hook) + { + conftest->hooks->insert_last(conftest->hooks, hook); + charon->bus->add_listener(charon->bus, &hook->listener); + } + } + else + { + fprintf(stderr, "dlsym() for hook '%s' failed: %s\n", name, dlerror()); + enumerator->destroy(enumerator); + return FALSE; + } + } + enumerator->destroy(enumerator); + return TRUE; +} + +/** + * atexit() cleanup handler + */ +static void cleanup() +{ + hook_t *hook; + + DESTROY_IF(conftest->test); + lib->credmgr->remove_set(lib->credmgr, &conftest->creds->set); + conftest->creds->destroy(conftest->creds); + DESTROY_IF(conftest->actions); + while (conftest->hooks->remove_last(conftest->hooks, + (void**)&hook) == SUCCESS) + { + charon->bus->remove_listener(charon->bus, &hook->listener); + hook->destroy(hook); + } + conftest->hooks->destroy(conftest->hooks); + if (conftest->config) + { + if (charon->backends) + { + charon->backends->remove_backend(charon->backends, + &conftest->config->backend); + } + conftest->config->destroy(conftest->config); + } + free(conftest->suite_dir); + free(conftest); + libcharon_deinit(); + libhydra_deinit(); + library_deinit(); +} + +/** + * Load log levels for a logger from section + */ +static void load_log_levels(file_logger_t *logger, char *section) +{ + debug_t group; + level_t def; + + def = conftest->test->get_int(conftest->test, "log.%s.default", 1, section); + for (group = 0; group < DBG_MAX; group++) + { + logger->set_level(logger, group, + conftest->test->get_int(conftest->test, "log.%s.%N", def, + section, debug_lower_names, group)); + } +} + +/** + * Load logger configuration + */ +static void load_loggers(file_logger_t *logger) +{ + enumerator_t *enumerator; + char *section; + FILE *file; + + load_log_levels(logger, "stdout"); + + enumerator = conftest->test->create_section_enumerator(conftest->test, "log"); + while (enumerator->enumerate(enumerator, §ion)) + { + if (!streq(section, "stdout")) + { + file = fopen(section, "w"); + if (file == NULL) + { + fprintf(stderr, "opening file %s for logging failed: %s", + section, strerror(errno)); + continue; + } + logger = file_logger_create(file, NULL, FALSE); + load_log_levels(logger, section); + charon->bus->add_listener(charon->bus, &logger->listener); + charon->file_loggers->insert_last(charon->file_loggers, logger); + } + } + enumerator->destroy(enumerator); +} + +/** + * Main function, starts the conftest daemon. + */ +int main(int argc, char *argv[]) +{ + struct sigaction action; + int status = 0; + sigset_t set; + int sig; + char *suite_file = "suite.conf", *test_file = NULL; + file_logger_t *logger; + + if (!library_init(NULL)) + { + library_deinit(); + return SS_RC_LIBSTRONGSWAN_INTEGRITY; + } + if (!libhydra_init("conftest")) + { + libhydra_deinit(); + library_deinit(); + return SS_RC_INITIALIZATION_FAILED; + } + if (!libcharon_init()) + { + libcharon_deinit(); + libhydra_deinit(); + library_deinit(); + return SS_RC_INITIALIZATION_FAILED; + } + + INIT(conftest, + .creds = mem_cred_create(), + ); + + logger = file_logger_create(stdout, NULL, FALSE); + logger->set_level(logger, DBG_ANY, LEVEL_CTRL); + charon->bus->add_listener(charon->bus, &logger->listener); + charon->file_loggers->insert_last(charon->file_loggers, logger); + + lib->credmgr->add_set(lib->credmgr, &conftest->creds->set); + conftest->hooks = linked_list_create(); + conftest->config = config_create(); + + atexit(cleanup); + + while (TRUE) + { + struct option long_opts[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, 'v' }, + { "suite", required_argument, NULL, 's' }, + { "test", required_argument, NULL, 't' }, + { 0,0,0,0 } + }; + switch (getopt_long(argc, argv, "", long_opts, NULL)) + { + case EOF: + break; + case 'h': + usage(stdout); + return 0; + case 'v': + printf("strongSwan %s conftest\n", VERSION); + return 0; + case 's': + suite_file = optarg; + continue; + case 't': + test_file = optarg; + continue; + default: + usage(stderr); + return 1; + } + break; + } + + if (!load_configs(suite_file, test_file)) + { + return 1; + } + load_loggers(logger); + + if (!lib->plugins->load(lib->plugins, NULL, + conftest->test->get_str(conftest->test, "preload", ""))) + { + return 1; + } + if (!charon->initialize(charon)) + { + return 1; + } + if (!load_certs(conftest->test, conftest->suite_dir)) + { + return 1; + } + if (!load_keys(conftest->test, conftest->suite_dir)) + { + return 1; + } + load_cdps(conftest->test); + if (!load_hooks()) + { + return 1; + } + charon->backends->add_backend(charon->backends, &conftest->config->backend); + conftest->config->load(conftest->config, conftest->test); + conftest->actions = actions_create(); + + /* set up thread specific handlers */ + action.sa_handler = segv_handler; + action.sa_flags = 0; + sigemptyset(&action.sa_mask); + sigaddset(&action.sa_mask, SIGINT); + sigaddset(&action.sa_mask, SIGTERM); + sigaddset(&action.sa_mask, SIGHUP); + sigaction(SIGSEGV, &action, NULL); + sigaction(SIGILL, &action, NULL); + sigaction(SIGBUS, &action, NULL); + action.sa_handler = SIG_IGN; + sigaction(SIGPIPE, &action, NULL); + pthread_sigmask(SIG_SETMASK, &action.sa_mask, NULL); + + /* start thread pool */ + charon->start(charon); + + /* handle SIGINT/SIGTERM in main thread */ + sigemptyset(&set); + sigaddset(&set, SIGINT); + sigaddset(&set, SIGHUP); + sigaddset(&set, SIGTERM); + sigprocmask(SIG_BLOCK, &set, NULL); + + while (sigwait(&set, &sig) == 0) + { + switch (sig) + { + case SIGINT: + case SIGTERM: + fprintf(stderr, "\nshutting down...\n"); + break; + default: + continue; + } + break; + } + return status; +} diff --git a/src/conftest/conftest.h b/src/conftest/conftest.h new file mode 100644 index 000000000..2caf9b3ce --- /dev/null +++ b/src/conftest/conftest.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * 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. + */ + +/** + * @defgroup conftest conftest + */ + +#ifndef CONFTEST_H_ +#define CONFTEST_H_ + +#include <library.h> +#include <hydra.h> +#include <daemon.h> +#include <credentials/sets/mem_cred.h> + +#include "config.h" +#include "actions.h" + +typedef struct conftest_t conftest_t; + +/** + * Global conftest variables. + */ +struct conftest_t { + + /** + * Merged suite/test configuration + */ + settings_t *test; + + /** + * Directory containing suite files + */ + char *suite_dir; + + /** + * Credentials loaded from configuration + */ + mem_cred_t *creds; + + /** + * Configurations loaded from config + */ + config_t *config; + + /** + * Loaded hooks + */ + linked_list_t *hooks; + + /** + * Action handling + */ + actions_t *actions; +}; + +/** + * Conftest globals + */ +extern conftest_t *conftest; + +#endif /** CONFTEST_H_ */ diff --git a/src/conftest/hooks/add_notify.c b/src/conftest/hooks/add_notify.c new file mode 100644 index 000000000..de46ca81f --- /dev/null +++ b/src/conftest/hooks/add_notify.c @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * 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 "hook.h" + +typedef struct private_add_notify_t private_add_notify_t; + +/** + * Private data of an add_notify_t object. + */ +struct private_add_notify_t { + + /** + * Implements the hook_t interface. + */ + hook_t hook; + + /** + * Alter requests or responses? + */ + bool req; + + /** + * ID of message to alter. + */ + int id; + + /** + * Notify type + */ + char *type; + + /** + * Notify data + */ + char *data; + + /** + * SPI of notify + */ + int spi; + + /** + * TRUE for a ESP protocol notify, FALSE for IKE + */ + bool esp; +}; + +METHOD(listener_t, message, bool, + private_add_notify_t *this, ike_sa_t *ike_sa, message_t *message, + bool incoming) +{ + if (!incoming && + message->get_request(message) == this->req && + message->get_message_id(message) == this->id) + { + notify_type_t type; + notify_payload_t *notify; + chunk_t data = chunk_empty; + + type = atoi(this->type); + if (!type) + { + type = enum_from_name(notify_type_names, this->type); + if (type == -1) + { + DBG1(DBG_CFG, "unknown notify: '%s', skipped", this->type); + return TRUE; + } + } + if (strncaseeq(this->data, "0x", 2)) + { + data = chunk_skip(chunk_create(this->data, strlen(this->data)), 2); + data = chunk_from_hex(data, NULL); + } + else if (this->data && strlen(this->data)) + { + data = chunk_clone(chunk_create(this->data, strlen(this->data))); + } + notify = notify_payload_create_from_protocol_and_type( + this->esp ? PROTO_ESP : PROTO_IKE, type); + notify->set_spi(notify, this->spi); + if (data.len) + { + notify->set_notification_data(notify, data); + free(data.ptr); + } + message->add_payload(message, ¬ify->payload_interface); + } + return TRUE; +} + +METHOD(hook_t, destroy, void, + private_add_notify_t *this) +{ + free(this); +} + +/** + * Create the IKE_AUTH fill hook + */ +hook_t *add_notify_hook_create(char *name) +{ + private_add_notify_t *this; + + INIT(this, + .hook = { + .listener = { + .message = _message, + }, + .destroy = _destroy, + }, + .req = conftest->test->get_bool(conftest->test, + "hooks.%s.request", TRUE, name), + .id = conftest->test->get_int(conftest->test, + "hooks.%s.id", 0, name), + .type = conftest->test->get_str(conftest->test, + "hooks.%s.type", "", name), + .data = conftest->test->get_str(conftest->test, + "hooks.%s.data", "", name), + .spi = conftest->test->get_int(conftest->test, + "hooks.%s.spi", 0, name), + .esp = conftest->test->get_bool(conftest->test, + "hooks.%s.esp", FALSE, name), + ); + + return &this->hook; +} diff --git a/src/conftest/hooks/add_payload.c b/src/conftest/hooks/add_payload.c new file mode 100644 index 000000000..03a47cc23 --- /dev/null +++ b/src/conftest/hooks/add_payload.c @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * 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 "hook.h" + +#include <encoding/payloads/unknown_payload.h> + +typedef struct private_add_payload_t private_add_payload_t; + +/** + * Private data of an add_payload_t object. + */ +struct private_add_payload_t { + + /** + * Implements the hook_t interface. + */ + hook_t hook; + + /** + * Alter requests or responses? + */ + bool req; + + /** + * ID of message to alter. + */ + int id; + + /** + * Payload type + */ + char *type; + + /** + * Payload data + */ + char *data; + + /** + * Set critical bit of the payload + */ + bool critical; + + /** + * True to replace existing payload of this type + */ + bool replace; +}; + +METHOD(listener_t, message, bool, + private_add_payload_t *this, ike_sa_t *ike_sa, message_t *message, + bool incoming) +{ + if (!incoming && + message->get_request(message) == this->req && + message->get_message_id(message) == this->id) + { + unknown_payload_t *unknown; + payload_t *payload; + enumerator_t *enumerator; + chunk_t data = chunk_empty; + payload_type_t type; + + type = atoi(this->type); + if (!type) + { + type = enum_from_name(payload_type_short_names, this->type); + if (type == -1) + { + DBG1(DBG_CFG, "unknown payload: '%s', skipped", this->type); + return TRUE; + } + } + if (this->replace) + { + enumerator = message->create_payload_enumerator(message); + while (enumerator->enumerate(enumerator, &payload)) + { + if (payload->get_type(payload) == type) + { + message->remove_payload_at(message, enumerator); + payload->destroy(payload); + break; + } + } + enumerator->destroy(enumerator); + } + if (strncaseeq(this->data, "0x", 2)) + { + data = chunk_skip(chunk_create(this->data, strlen(this->data)), 2); + data = chunk_from_hex(data, NULL); + } + else if (this->data && strlen(this->data)) + { + data = chunk_clone(chunk_create(this->data, strlen(this->data))); + } + unknown = unknown_payload_create_data(type, this->critical, data); + message->add_payload(message, &unknown->payload_interface); + } + return TRUE; +} + +METHOD(hook_t, destroy, void, + private_add_payload_t *this) +{ + free(this); +} + +/** + * Create the IKE_AUTH fill hook + */ +hook_t *add_payload_hook_create(char *name) +{ + private_add_payload_t *this; + + INIT(this, + .hook = { + .listener = { + .message = _message, + }, + .destroy = _destroy, + }, + .req = conftest->test->get_bool(conftest->test, + "hooks.%s.request", TRUE, name), + .id = conftest->test->get_int(conftest->test, + "hooks.%s.id", 0, name), + .type = conftest->test->get_str(conftest->test, + "hooks.%s.type", "", name), + .data = conftest->test->get_str(conftest->test, + "hooks.%s.data", "", name), + .critical = conftest->test->get_bool(conftest->test, + "hooks.%s.critical", FALSE, name), + .replace = conftest->test->get_bool(conftest->test, + "hooks.%s.replace", FALSE, name), + ); + + return &this->hook; +} diff --git a/src/conftest/hooks/custom_proposal.c b/src/conftest/hooks/custom_proposal.c new file mode 100644 index 000000000..e4acd841f --- /dev/null +++ b/src/conftest/hooks/custom_proposal.c @@ -0,0 +1,188 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * 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 "hook.h" + +#include <errno.h> + +#include <encoding/payloads/sa_payload.h> +#include <config/proposal.h> +#include <crypto/proposal/proposal_keywords.h> + +typedef struct private_custom_proposal_t private_custom_proposal_t; + +/** + * Private data of an custom_proposal_t object. + */ +struct private_custom_proposal_t { + + /** + * Implements the hook_t interface. + */ + hook_t hook; + + /** + * Alter requests or responses? + */ + bool req; + + /** + * ID of message to alter. + */ + int id; + + /** + * hook name + */ + char *name; +}; + +/** + * Load custom proposal configuration to proposal list + */ +static linked_list_t* load_proposals(private_custom_proposal_t *this, + protocol_id_t proto, u_int64_t spi) +{ + enumerator_t *props, *algs; + char *number, *key, *value; + linked_list_t *list; + + list = linked_list_create(); + props = conftest->test->create_section_enumerator(conftest->test, + "hooks.%s", this->name); + while (props->enumerate(props, &number)) + { + const proposal_token_t *token = NULL; + proposal_t *proposal; + u_int16_t type, alg, keysize = 0; + char *end; + + proposal = proposal_create(proto, atoi(number)); + proposal->set_spi(proposal, spi); + + algs = conftest->test->create_key_value_enumerator(conftest->test, + "hooks.%s.%s", this->name, number); + while (algs->enumerate(algs, &key, &value)) + { + errno = 0; + type = strtoul(key, &end, 10); + if (end == key || errno) + { + type = enum_from_name(transform_type_names, key); + if (type == -1) + { + DBG1(DBG_CFG, "unknown transform: '%s', skipped", key); + continue; + } + } + errno = 0; + alg = strtoul(value, &end, 10); + if (end == value || errno) + { + token = proposal_get_token(value, strlen(value)); + if (!token) + { + DBG1(DBG_CFG, "unknown algorithm: '%s', skipped", value); + continue; + } + keysize = token->keysize; + alg = token->algorithm; + } + proposal->add_algorithm(proposal, type, alg, keysize); + } + algs->destroy(algs); + list->insert_last(list, proposal); + } + props->destroy(props); + return list; +} + +METHOD(listener_t, message, bool, + private_custom_proposal_t *this, ike_sa_t *ike_sa, message_t *message, + bool incoming) +{ + if (!incoming && + message->get_request(message) == this->req && + message->get_message_id(message) == this->id) + { + enumerator_t *enumerator; + payload_t *payload; + sa_payload_t *new, *old = NULL; + linked_list_t *new_props, *old_props; + proposal_t *proposal; + + enumerator = message->create_payload_enumerator(message); + while (enumerator->enumerate(enumerator, &payload)) + { + if (payload->get_type(payload) == SECURITY_ASSOCIATION) + { + old = (sa_payload_t*)payload; + message->remove_payload_at(message, enumerator); + } + } + enumerator->destroy(enumerator); + + if (old) + { + old_props = old->get_proposals(old); + old->destroy(old); + enumerator = old_props->create_enumerator(old_props); + if (enumerator->enumerate(enumerator, &proposal)) + { + new_props = load_proposals(this, + proposal->get_protocol(proposal), + proposal->get_spi(proposal)); + DBG1(DBG_CFG, "injecting custom proposal: %#P", new_props); + new = sa_payload_create_from_proposal_list(new_props); + message->add_payload(message, (payload_t*)new); + new_props->destroy_offset(new_props, offsetof(proposal_t, destroy)); + } + enumerator->destroy(enumerator); + old_props->destroy_offset(old_props, offsetof(proposal_t, destroy)); + } + } + return TRUE; +} + +METHOD(hook_t, destroy, void, + private_custom_proposal_t *this) +{ + free(this->name); + free(this); +} + +/** + * Create the IKE_AUTH fill hook + */ +hook_t *custom_proposal_hook_create(char *name) +{ + private_custom_proposal_t *this; + + INIT(this, + .hook = { + .listener = { + .message = _message, + }, + .destroy = _destroy, + }, + .req = conftest->test->get_bool(conftest->test, + "hooks.%s.request", TRUE, name), + .id = conftest->test->get_int(conftest->test, + "hooks.%s.id", 0, name), + .name = strdup(name), + ); + + return &this->hook; +} diff --git a/src/conftest/hooks/force_cookie.c b/src/conftest/hooks/force_cookie.c new file mode 100644 index 000000000..e34f82851 --- /dev/null +++ b/src/conftest/hooks/force_cookie.c @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * 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 "hook.h" + +#include <encoding/payloads/unknown_payload.h> + +typedef struct private_force_cookie_t private_force_cookie_t; + +/** + * Private data of an force_cookie_t object. + */ +struct private_force_cookie_t { + + /** + * Implements the hook_t interface. + */ + hook_t hook; +}; + +METHOD(listener_t, message, bool, + private_force_cookie_t *this, ike_sa_t *ike_sa, message_t *message, + bool incoming) +{ + if (incoming && message->get_request(message) && + message->get_exchange_type(message) == IKE_SA_INIT) + { + enumerator_t *enumerator; + bool has_cookie = FALSE; + payload_t *payload; + + enumerator = message->create_payload_enumerator(message); + while (enumerator->enumerate(enumerator, &payload)) + { + if (payload->get_type(payload) == NOTIFY) + { + notify_payload_t *notify = (notify_payload_t*)payload; + chunk_t data; + + if (notify->get_notify_type(notify) == COOKIE) + { + data = notify->get_notification_data(notify); + DBG1(DBG_CFG, "received COOKIE: %#B", &data); + has_cookie = TRUE; + break; + } + } + } + enumerator->destroy(enumerator); + if (!has_cookie) + { + message_t *response; + host_t *src, *dst; + packet_t *packet; + ike_sa_id_t *ike_sa_id; + chunk_t data = chunk_from_thing("COOKIE test data"); + + DBG1(DBG_CFG, "sending COOKIE: %#B", &data); + response = message_create(); + dst = message->get_source(message); + src = message->get_destination(message); + response->set_source(response, src->clone(src)); + response->set_destination(response, dst->clone(dst)); + response->set_exchange_type(response, IKE_SA_INIT); + response->set_request(response, FALSE); + response->set_message_id(response, 0); + ike_sa_id = message->get_ike_sa_id(message); + ike_sa_id->switch_initiator(ike_sa_id); + response->set_ike_sa_id(response, ike_sa_id); + response->add_notify(response, FALSE, COOKIE, data); + if (response->generate(response, NULL, &packet) == SUCCESS) + { + charon->sender->send(charon->sender, packet); + response->destroy(response); + } + message->set_exchange_type(message, EXCHANGE_TYPE_UNDEFINED); + } + } + return TRUE; +} + +METHOD(hook_t, destroy, void, + private_force_cookie_t *this) +{ + free(this); +} + +/** + * Create the IKE_AUTH fill hook + */ +hook_t *force_cookie_hook_create(char *name) +{ + private_force_cookie_t *this; + + INIT(this, + .hook = { + .listener = { + .message = _message, + }, + .destroy = _destroy, + }, + ); + + return &this->hook; +} diff --git a/src/conftest/hooks/hook.h b/src/conftest/hooks/hook.h new file mode 100644 index 000000000..39a15f21b --- /dev/null +++ b/src/conftest/hooks/hook.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * 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. + */ + +/** + * @defgroup hook hook + * @{ @ingroup hooks + */ + +#ifndef HOOK_H_ +#define HOOK_H_ + +typedef struct hook_t hook_t; + +#include <daemon.h> +#include <conftest.h> + +/** + * Hook providing interface. + */ +struct hook_t { + + /** + * Implements listener_t. + */ + listener_t listener; + + /** + * Destroy a hook_t. + */ + void (*destroy)(hook_t *this); +}; + +#endif /** HOOK_H_ @}*/ diff --git a/src/conftest/hooks/ignore_message.c b/src/conftest/hooks/ignore_message.c new file mode 100644 index 000000000..210f3ac50 --- /dev/null +++ b/src/conftest/hooks/ignore_message.c @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * 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 "hook.h" + +typedef struct private_ignore_message_t private_ignore_message_t; + +/** + * Private data of an ignore_message_t object. + */ +struct private_ignore_message_t { + + /** + * Implements the hook_t interface. + */ + hook_t hook; + + /** + * Drop incoming or outgoing? + */ + bool in; + + /** + * Drop requests or responses? + */ + bool req; + + /** + * ID of message to drop. + */ + int id; +}; + +METHOD(listener_t, message, bool, + private_ignore_message_t *this, ike_sa_t *ike_sa, message_t *message, + bool incoming) +{ + if (incoming == this->in && + message->get_request(message) == this->req && + message->get_message_id(message) == this->id) + { + DBG1(DBG_CFG, "ignoring message"); + message->set_exchange_type(message, EXCHANGE_TYPE_UNDEFINED); + } + return TRUE; +} + +METHOD(hook_t, destroy, void, + private_ignore_message_t *this) +{ + free(this); +} + +/** + * Create the ignore_message hook + */ +hook_t *ignore_message_hook_create(char *name) +{ + private_ignore_message_t *this; + + INIT(this, + .hook = { + .listener = { + .message = _message, + }, + .destroy = _destroy, + }, + .in = conftest->test->get_bool(conftest->test, + "hooks.%s.inbound", TRUE, name), + .req = conftest->test->get_bool(conftest->test, + "hooks.%s.request", TRUE, name), + .id = conftest->test->get_int(conftest->test, + "hooks.%s.id", 0, name), + ); + + return &this->hook; +} diff --git a/src/conftest/hooks/ike_auth_fill.c b/src/conftest/hooks/ike_auth_fill.c new file mode 100644 index 000000000..2843d60c1 --- /dev/null +++ b/src/conftest/hooks/ike_auth_fill.c @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * 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 "hook.h" + +#include <time.h> +#include <netinet/udp.h> + +#include <encoding/payloads/cert_payload.h> +#include <encoding/payloads/encryption_payload.h> + +typedef struct private_ike_auth_fill_t private_ike_auth_fill_t; + +/** + * Private data of an ike_auth_fill_t object. + */ +struct private_ike_auth_fill_t { + + /** + * Implements the hook_t interface. + */ + hook_t hook; + + /** + * Alter requests or responses? + */ + bool req; + + /** + * ID of message to alter. + */ + int id; + + /** + * Number of bytes to fill IKE_AUTH up + */ + int bytes; +}; + +/** size of non ESP-Marker */ +#define NON_ESP_MARKER_LEN 4 + +/** + * Calculate packet size on wire (without ethernet/IP header) + */ +static size_t calculate_wire_size(message_t *message, ike_sa_t *ike_sa) +{ + enumerator_t *enumerator; + payload_t *payload; + size_t size = 0; + + enumerator = message->create_payload_enumerator(message); + while (enumerator->enumerate(enumerator, &payload)) + { + size += payload->get_length(payload); + } + enumerator->destroy(enumerator); + + if (message->get_exchange_type(message) != IKE_SA_INIT) + { + keymat_t *keymat; + aead_t *aead; + size_t bs; + + keymat = ike_sa->get_keymat(ike_sa); + aead = keymat->get_aead(keymat, FALSE); + if (aead) + { + bs = aead->get_block_size(aead); + size += ENCRYPTION_PAYLOAD_HEADER_LENGTH + NON_ESP_MARKER_LEN + + aead->get_icv_size(aead) + aead->get_iv_size(aead) + + (bs - (size % bs)); + } + } + return sizeof(struct udphdr) + IKE_HEADER_LENGTH + size; +} + +METHOD(listener_t, message, bool, + private_ike_auth_fill_t *this, ike_sa_t *ike_sa, message_t *message, + bool incoming) +{ + if (!incoming && + message->get_request(message) == this->req && + message->get_message_id(message) == this->id) + { + cert_payload_t *pld; + size_t size, diff; + chunk_t data; + + size = calculate_wire_size(message, ike_sa); + if (size < this->bytes - CERT_PAYLOAD_HEADER_LENGTH) + { + diff = this->bytes - size - CERT_PAYLOAD_HEADER_LENGTH; + data = chunk_alloc(diff); + memset(data.ptr, 0x12, data.len); + pld = cert_payload_create_custom(201, data); + message->add_payload(message, &pld->payload_interface); + DBG1(DBG_CFG, "inserting %d dummy bytes certificate payload", diff); + } + } + return TRUE; +} + +METHOD(hook_t, destroy, void, + private_ike_auth_fill_t *this) +{ + free(this); +} + +/** + * Create the IKE_AUTH fill hook + */ +hook_t *ike_auth_fill_hook_create(char *name) +{ + private_ike_auth_fill_t *this; + + INIT(this, + .hook = { + .listener = { + .message = _message, + }, + .destroy = _destroy, + }, + .req = conftest->test->get_bool(conftest->test, + "hooks.%s.request", TRUE, name), + .id = conftest->test->get_int(conftest->test, + "hooks.%s.id", 1, name), + .bytes = conftest->test->get_int(conftest->test, + "hooks.%s.bytes", 0, name), + ); + + return &this->hook; +} diff --git a/src/conftest/hooks/log_id.c b/src/conftest/hooks/log_id.c new file mode 100644 index 000000000..ad14cea10 --- /dev/null +++ b/src/conftest/hooks/log_id.c @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * 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 "hook.h" + +#include <encoding/payloads/id_payload.h> + +typedef struct private_log_id_t private_log_id_t; + +/** + * Private data of an log_id_t object. + */ +struct private_log_id_t { + + /** + * Implements the hook_t interface. + */ + hook_t hook; +}; + +METHOD(listener_t, message, bool, + private_log_id_t *this, ike_sa_t *ike_sa, message_t *message, + bool incoming) +{ + if (incoming) + { + enumerator_t *enumerator; + payload_t *payload; + id_payload_t *id_payload; + identification_t *id; + chunk_t data; + + enumerator = message->create_payload_enumerator(message); + while (enumerator->enumerate(enumerator, &payload)) + { + if (payload->get_type(payload) == ID_INITIATOR || + payload->get_type(payload) == ID_RESPONDER) + { + id_payload = (id_payload_t*)payload; + id = id_payload->get_identification(id_payload); + data = id->get_encoding(id); + + DBG1(DBG_CFG, "%N: %N %B", + payload_type_short_names, payload->get_type(payload), + id_type_names, id->get_type(id), &data); + id->destroy(id); + } + } + enumerator->destroy(enumerator); + } + return TRUE; +} + +METHOD(hook_t, destroy, void, + private_log_id_t *this) +{ + free(this); +} + +/** + * Create the IKE_AUTH fill hook + */ +hook_t *log_id_hook_create(char *name) +{ + private_log_id_t *this; + + INIT(this, + .hook = { + .listener = { + .message = _message, + }, + .destroy = _destroy, + }, + ); + + return &this->hook; +} diff --git a/src/conftest/hooks/log_ke.c b/src/conftest/hooks/log_ke.c new file mode 100644 index 000000000..231c0a8d8 --- /dev/null +++ b/src/conftest/hooks/log_ke.c @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * 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 "hook.h" + +#include <encoding/payloads/ke_payload.h> + +typedef struct private_log_ke_t private_log_ke_t; + +/** + * Private data of an log_ke_t object. + */ +struct private_log_ke_t { + + /** + * Implements the hook_t interface. + */ + hook_t hook; +}; + +METHOD(listener_t, message, bool, + private_log_ke_t *this, ike_sa_t *ike_sa, message_t *message, + bool incoming) +{ + if (incoming) + { + enumerator_t *enumerator; + payload_t *payload; + ke_payload_t *ke; + + enumerator = message->create_payload_enumerator(message); + while (enumerator->enumerate(enumerator, &payload)) + { + if (payload->get_type(payload) == KEY_EXCHANGE) + { + ke = (ke_payload_t*)payload; + DBG1(DBG_CFG, "received DH group %N", + diffie_hellman_group_names, ke->get_dh_group_number(ke)); + } + } + enumerator->destroy(enumerator); + } + return TRUE; +} + +METHOD(hook_t, destroy, void, + private_log_ke_t *this) +{ + free(this); +} + +/** + * Create the IKE_AUTH fill hook + */ +hook_t *log_ke_hook_create(char *name) +{ + private_log_ke_t *this; + + INIT(this, + .hook = { + .listener = { + .message = _message, + }, + .destroy = _destroy, + }, + ); + + return &this->hook; +} diff --git a/src/conftest/hooks/log_proposals.c b/src/conftest/hooks/log_proposals.c new file mode 100644 index 000000000..8c330ab3d --- /dev/null +++ b/src/conftest/hooks/log_proposals.c @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * 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 "hook.h" + +#include <encoding/payloads/sa_payload.h> + +typedef struct private_log_proposals_t private_log_proposals_t; + +/** + * Private data of an log_proposals_t object. + */ +struct private_log_proposals_t { + + /** + * Implements the hook_t interface. + */ + hook_t hook; +}; + +METHOD(listener_t, message, bool, + private_log_proposals_t *this, ike_sa_t *ike_sa, message_t *message, + bool incoming) +{ + if (incoming) + { + enumerator_t *enumerator, *proposals; + payload_t *payload; + linked_list_t *list; + sa_payload_t *sa; + proposal_t *proposal; + + enumerator = message->create_payload_enumerator(message); + while (enumerator->enumerate(enumerator, &payload)) + { + if (payload->get_type(payload) == SECURITY_ASSOCIATION) + { + sa = (sa_payload_t*)payload; + list = sa->get_proposals(sa); + DBG1(DBG_CFG, "received %d proposal%s:", list->get_count(list), + list->get_count(list) == 1 ? "" : "s"); + proposals = list->create_enumerator(list); + while (proposals->enumerate(proposals, &proposal)) + { + u_int64_t spi = proposal->get_spi(proposal); + + if (proposal->get_protocol(proposal) != PROTO_IKE) + { + spi = htonl(spi); + } + DBG1(DBG_CFG, " %d (SPI 0x%llx): %P", + proposal->get_number(proposal), spi, proposal); + } + proposals->destroy(proposals); + list->destroy_offset(list, offsetof(proposal_t, destroy)); + } + } + enumerator->destroy(enumerator); + } + return TRUE; +} + +METHOD(hook_t, destroy, void, + private_log_proposals_t *this) +{ + free(this); +} + +/** + * Create the IKE_AUTH fill hook + */ +hook_t *log_proposals_hook_create(char *name) +{ + private_log_proposals_t *this; + + INIT(this, + .hook = { + .listener = { + .message = _message, + }, + .destroy = _destroy, + }, + ); + + return &this->hook; +} diff --git a/src/conftest/hooks/log_ts.c b/src/conftest/hooks/log_ts.c new file mode 100644 index 000000000..dacc7a58c --- /dev/null +++ b/src/conftest/hooks/log_ts.c @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * 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 "hook.h" + +#include <encoding/payloads/ts_payload.h> + +typedef struct private_log_ts_t private_log_ts_t; + +/** + * Private data of an log_ts_t object. + */ +struct private_log_ts_t { + + /** + * Implements the hook_t interface. + */ + hook_t hook; +}; + +METHOD(listener_t, message, bool, + private_log_ts_t *this, ike_sa_t *ike_sa, message_t *message, + bool incoming) +{ + if (incoming) + { + enumerator_t *enumerator; + payload_t *payload; + linked_list_t *list; + ts_payload_t *ts; + + enumerator = message->create_payload_enumerator(message); + while (enumerator->enumerate(enumerator, &payload)) + { + if (payload->get_type(payload) == TRAFFIC_SELECTOR_INITIATOR || + payload->get_type(payload) == TRAFFIC_SELECTOR_RESPONDER) + { + ts = (ts_payload_t*)payload; + list = ts->get_traffic_selectors(ts); + + DBG1(DBG_CFG, "received %N: %#R", + payload_type_short_names, payload->get_type(payload), list); + list->destroy_offset(list, offsetof(traffic_selector_t, destroy)); + } + } + enumerator->destroy(enumerator); + } + return TRUE; +} + +METHOD(hook_t, destroy, void, + private_log_ts_t *this) +{ + free(this); +} + +/** + * Create the IKE_AUTH fill hook + */ +hook_t *log_ts_hook_create(char *name) +{ + private_log_ts_t *this; + + INIT(this, + .hook = { + .listener = { + .message = _message, + }, + .destroy = _destroy, + }, + ); + + return &this->hook; +} diff --git a/src/conftest/hooks/pretend_auth.c b/src/conftest/hooks/pretend_auth.c new file mode 100644 index 000000000..4b7168cac --- /dev/null +++ b/src/conftest/hooks/pretend_auth.c @@ -0,0 +1,386 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * 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 "hook.h" + +#include <encoding/payloads/nonce_payload.h> +#include <encoding/payloads/cert_payload.h> +#include <encoding/payloads/auth_payload.h> +#include <encoding/payloads/id_payload.h> +#include <encoding/payloads/sa_payload.h> +#include <encoding/payloads/ts_payload.h> + +typedef struct private_pretend_auth_t private_pretend_auth_t; + +/** + * Private data of an pretend_auth_t object. + */ +struct private_pretend_auth_t { + + /** + * Implements the hook_t interface. + */ + hook_t hook; + + /** + * remote peer identity + */ + identification_t *id; + + /** + * reserved bytes of ID payload + */ + char reserved[3]; + + /** + * IKE_SA_INIT data for signature + */ + chunk_t ike_init; + + /** + * Nonce for signature + */ + chunk_t nonce; + + /** + * Selected CHILD_SA proposal + */ + proposal_t *proposal; + + /** + * List of initiators Traffic Selectors + */ + linked_list_t *tsi; + + /** + * List of responders Traffic Selectors + */ + linked_list_t *tsr; +}; + +/** + * Process IKE_SA_INIT request message, outgoing + */ +static void process_init_request(private_pretend_auth_t *this, + ike_sa_t *ike_sa, message_t *message) +{ + nonce_payload_t *nonce; + + nonce = (nonce_payload_t*)message->get_payload(message, NONCE); + if (nonce) + { + free(this->nonce.ptr); + this->nonce = nonce->get_nonce(nonce); + } +} + +/** + * Process IKE_AUTH request message, outgoing + */ +static void process_auth_request(private_pretend_auth_t *this, + ike_sa_t *ike_sa, message_t *message) +{ + id_payload_t *id; + sa_payload_t *sa; + ts_payload_t *tsi, *tsr; + linked_list_t *proposals; + + id = (id_payload_t*)message->get_payload(message, ID_RESPONDER); + if (id) + { + this->id->destroy(this->id); + this->id = id->get_identification(id); + } + sa = (sa_payload_t*)message->get_payload(message, SECURITY_ASSOCIATION); + if (sa) + { + proposals = sa->get_proposals(sa); + proposals->remove_first(proposals, (void**)&this->proposal); + if (this->proposal) + { + this->proposal->set_spi(this->proposal, htonl(0x12345678)); + } + proposals->destroy_offset(proposals, offsetof(proposal_t, destroy)); + } + tsi = (ts_payload_t*)message->get_payload(message, + TRAFFIC_SELECTOR_INITIATOR); + if (tsi) + { + this->tsi = tsi->get_traffic_selectors(tsi); + } + tsr = (ts_payload_t*)message->get_payload(message, + TRAFFIC_SELECTOR_RESPONDER); + if (tsr) + { + this->tsr = tsr->get_traffic_selectors(tsr); + } + +} + +/** + * Process IKE_SA_INIT response message, incoming + */ +static void process_init_response(private_pretend_auth_t *this, + ike_sa_t *ike_sa, message_t *message) +{ + this->ike_init = message->get_packet_data(message); +} + +/** + * Build CERT payloads + */ +static void build_certs(private_pretend_auth_t *this, + ike_sa_t *ike_sa, message_t *message, auth_cfg_t *auth) +{ + enumerator_t *enumerator; + cert_payload_t *payload; + certificate_t *cert; + auth_rule_t type; + + /* get subject cert first, then issuing certificates */ + cert = auth->get(auth, AUTH_RULE_SUBJECT_CERT); + if (cert) + { + payload = cert_payload_create_from_cert(cert); + if (payload) + { + DBG1(DBG_IKE, "pretending end entity cert \"%Y\"", + cert->get_subject(cert)); + message->add_payload(message, (payload_t*)payload); + } + } + enumerator = auth->create_enumerator(auth); + while (enumerator->enumerate(enumerator, &type, &cert)) + { + if (type == AUTH_RULE_IM_CERT) + { + payload = cert_payload_create_from_cert(cert); + if (payload) + { + DBG1(DBG_IKE, "pretending issuer cert \"%Y\"", + cert->get_subject(cert)); + message->add_payload(message, (payload_t*)payload); + } + } + } + enumerator->destroy(enumerator); +} + +/** + * Build faked AUTH payload + */ +static bool build_auth(private_pretend_auth_t *this, + ike_sa_t *ike_sa, message_t *message) +{ + chunk_t octets, auth_data; + private_key_t *private; + auth_cfg_t *auth; + auth_payload_t *auth_payload; + auth_method_t auth_method; + signature_scheme_t scheme; + keymat_t *keymat; + + auth = auth_cfg_create(); + private = lib->credmgr->get_private(lib->credmgr, KEY_ANY, this->id, auth); + build_certs(this, ike_sa, message, auth); + auth->destroy(auth); + if (private == NULL) + { + DBG1(DBG_CFG, "no private key found for '%Y' to pretend AUTH", this->id); + return FALSE; + } + + switch (private->get_type(private)) + { + case KEY_RSA: + scheme = SIGN_RSA_EMSA_PKCS1_SHA1; + auth_method = AUTH_RSA; + break; + case KEY_ECDSA: + /* we try to deduct the signature scheme from the keysize */ + switch (private->get_keysize(private)) + { + case 256: + scheme = SIGN_ECDSA_256; + auth_method = AUTH_ECDSA_256; + break; + case 384: + scheme = SIGN_ECDSA_384; + auth_method = AUTH_ECDSA_384; + break; + case 521: + scheme = SIGN_ECDSA_521; + auth_method = AUTH_ECDSA_521; + break; + default: + DBG1(DBG_CFG, "%d bit ECDSA private key size not supported", + private->get_keysize(private)); + return FALSE; + } + break; + default: + DBG1(DBG_CFG, "private key of type %N not supported", + key_type_names, private->get_type(private)); + return FALSE; + } + keymat = ike_sa->get_keymat(ike_sa); + octets = keymat->get_auth_octets(keymat, TRUE, this->ike_init, + this->nonce, this->id, this->reserved); + if (!private->sign(private, scheme, octets, &auth_data)) + { + chunk_free(&octets); + private->destroy(private); + return FALSE; + } + auth_payload = auth_payload_create(); + auth_payload->set_auth_method(auth_payload, auth_method); + auth_payload->set_data(auth_payload, auth_data); + chunk_free(&auth_data); + chunk_free(&octets); + private->destroy(private); + message->add_payload(message, (payload_t*)auth_payload); + DBG1(DBG_CFG, "pretending AUTH payload for '%Y' with %N", + this->id, auth_method_names, auth_method); + return TRUE; +} + +/** + * Process IKE_AUTH response message, incoming + */ +static void process_auth_response(private_pretend_auth_t *this, + ike_sa_t *ike_sa, message_t *message) +{ + enumerator_t *enumerator; + payload_t *payload; + + /* check for, and remove AUTHENTICATION_FAILED notify */ + enumerator = message->create_payload_enumerator(message); + while (enumerator->enumerate(enumerator, &payload)) + { + notify_payload_t *notify = (notify_payload_t*)payload; + + if (payload->get_type(payload) != NOTIFY || + notify->get_notify_type(notify) != AUTHENTICATION_FAILED) + { + DBG1(DBG_CFG, "no %N notify found, disabling AUTH pretending", + notify_type_names, AUTHENTICATION_FAILED); + enumerator->destroy(enumerator); + return; + } + message->remove_payload_at(message, enumerator); + payload->destroy(payload); + } + enumerator->destroy(enumerator); + + if (!build_auth(this, ike_sa, message)) + { + message->add_notify(message, TRUE, AUTHENTICATION_FAILED, chunk_empty); + return; + } + message->add_payload(message, (payload_t*) + id_payload_create_from_identification(ID_RESPONDER, this->id)); + if (this->proposal) + { + message->add_payload(message, (payload_t*) + sa_payload_create_from_proposal(this->proposal)); + } + if (this->tsi) + { + message->add_payload(message, (payload_t*) + ts_payload_create_from_traffic_selectors(TRUE, this->tsi)); + } + if (this->tsr) + { + message->add_payload(message, (payload_t*) + ts_payload_create_from_traffic_selectors(FALSE, this->tsr)); + } +} + +METHOD(listener_t, message, bool, + private_pretend_auth_t *this, ike_sa_t *ike_sa, message_t *message, + bool incoming) +{ + if (incoming) + { + if (!message->get_request(message)) + { + if (message->get_exchange_type(message) == IKE_SA_INIT) + { + process_init_response(this, ike_sa, message); + } + if (message->get_exchange_type(message) == IKE_AUTH && + message->get_message_id(message) == 1) + { + process_auth_response(this, ike_sa, message); + } + } + } + else + { + if (message->get_request(message)) + { + if (message->get_exchange_type(message) == IKE_SA_INIT) + { + process_init_request(this, ike_sa, message); + } + if (message->get_exchange_type(message) == IKE_AUTH && + message->get_message_id(message) == 1) + { + process_auth_request(this, ike_sa, message); + } + } + } + return TRUE; +} + +METHOD(hook_t, destroy, void, + private_pretend_auth_t *this) +{ + if (this->tsi) + { + this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy)); + } + if (this->tsr) + { + this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy)); + } + DESTROY_IF(this->proposal); + this->id->destroy(this->id); + free(this->ike_init.ptr); + free(this->nonce.ptr); + free(this); +} + +/** + * Create the IKE_AUTH fill hook + */ +hook_t *pretend_auth_hook_create(char *name) +{ + private_pretend_auth_t *this; + + INIT(this, + .hook = { + .listener = { + .message = _message, + }, + .destroy = _destroy, + }, + .id = identification_create_from_string( + conftest->test->get_str(conftest->test, + "hooks.%s.peer", "%any", name)), + ); + + return &this->hook; +} diff --git a/src/conftest/hooks/rebuild_auth.c b/src/conftest/hooks/rebuild_auth.c new file mode 100644 index 000000000..993c952e0 --- /dev/null +++ b/src/conftest/hooks/rebuild_auth.c @@ -0,0 +1,243 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * 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 "hook.h" + +#include <encoding/generator.h> +#include <encoding/payloads/nonce_payload.h> +#include <encoding/payloads/auth_payload.h> +#include <encoding/payloads/id_payload.h> + +typedef struct private_rebuild_auth_t private_rebuild_auth_t; + +/** + * Private data of an rebuild_auth_t object. + */ +struct private_rebuild_auth_t { + + /** + * Implements the hook_t interface. + */ + hook_t hook; + + /** + * Our IKE_SA_INIT data, required to rebuild AUTH + */ + chunk_t ike_init; + + /** + * Received NONCE, required to rebuild AUTH + */ + chunk_t nonce; + + /** + * ID to use for key lookup, if not from IDi + */ + identification_t *id; +}; + +/** + * Rebuild our AUTH data + */ +static bool rebuild_auth(private_rebuild_auth_t *this, ike_sa_t *ike_sa, + message_t *message) +{ + enumerator_t *enumerator; + chunk_t octets, auth_data; + private_key_t *private; + auth_cfg_t *auth; + payload_t *payload; + auth_payload_t *auth_payload; + auth_method_t auth_method; + signature_scheme_t scheme; + keymat_t *keymat; + identification_t *id; + char reserved[3]; + generator_t *generator; + chunk_t data; + u_int32_t *lenpos; + + payload = message->get_payload(message, + message->get_request(message) ? ID_INITIATOR : ID_RESPONDER); + if (!payload) + { + DBG1(DBG_CFG, "ID payload not found to rebuild AUTH"); + return FALSE; + } + + generator = generator_create(); + generator->generate_payload(generator, payload); + data = generator->get_chunk(generator, &lenpos); + if (data.len < 8) + { + DBG1(DBG_CFG, "ID payload invalid to rebuild AUTH"); + generator->destroy(generator); + return FALSE; + } + memcpy(reserved, data.ptr + 5, 3); + id = identification_create_from_encoding(data.ptr[4], chunk_skip(data, 8)); + generator->destroy(generator); + + auth = auth_cfg_create(); + private = lib->credmgr->get_private(lib->credmgr, KEY_ANY, + this->id ?: id, auth); + auth->destroy(auth); + if (private == NULL) + { + DBG1(DBG_CFG, "no private key found for '%Y' to rebuild AUTH", + this->id ?: id); + id->destroy(id); + return FALSE; + } + + switch (private->get_type(private)) + { + case KEY_RSA: + scheme = SIGN_RSA_EMSA_PKCS1_SHA1; + auth_method = AUTH_RSA; + break; + case KEY_ECDSA: + /* we try to deduct the signature scheme from the keysize */ + switch (private->get_keysize(private)) + { + case 256: + scheme = SIGN_ECDSA_256; + auth_method = AUTH_ECDSA_256; + break; + case 384: + scheme = SIGN_ECDSA_384; + auth_method = AUTH_ECDSA_384; + break; + case 521: + scheme = SIGN_ECDSA_521; + auth_method = AUTH_ECDSA_521; + break; + default: + DBG1(DBG_CFG, "%d bit ECDSA private key size not supported", + private->get_keysize(private)); + id->destroy(id); + return FALSE; + } + break; + default: + DBG1(DBG_CFG, "private key of type %N not supported", + key_type_names, private->get_type(private)); + id->destroy(id); + return FALSE; + } + keymat = ike_sa->get_keymat(ike_sa); + octets = keymat->get_auth_octets(keymat, FALSE, this->ike_init, + this->nonce, id, reserved); + if (!private->sign(private, scheme, octets, &auth_data)) + { + chunk_free(&octets); + private->destroy(private); + id->destroy(id); + return FALSE; + } + auth_payload = auth_payload_create(); + auth_payload->set_auth_method(auth_payload, auth_method); + auth_payload->set_data(auth_payload, auth_data); + chunk_free(&auth_data); + chunk_free(&octets); + private->destroy(private); + + enumerator = message->create_payload_enumerator(message); + while (enumerator->enumerate(enumerator, &payload)) + { + if (payload->get_type(payload) == AUTHENTICATION) + { + message->remove_payload_at(message, enumerator); + payload->destroy(payload); + } + } + enumerator->destroy(enumerator); + + message->add_payload(message, (payload_t*)auth_payload); + DBG1(DBG_CFG, "rebuilding AUTH payload for '%Y' with %N", + id, auth_method_names, auth_method); + id->destroy(id); + return TRUE; +} + +METHOD(listener_t, message, bool, + private_rebuild_auth_t *this, ike_sa_t *ike_sa, message_t *message, + bool incoming) +{ + if (!incoming && message->get_message_id(message) == 1) + { + rebuild_auth(this, ike_sa, message); + } + if (message->get_exchange_type(message) == IKE_SA_INIT) + { + if (incoming) + { + nonce_payload_t *nonce; + + nonce = (nonce_payload_t*)message->get_payload(message, NONCE); + if (nonce) + { + free(this->nonce.ptr); + this->nonce = nonce->get_nonce(nonce); + } + } + else + { + packet_t *packet; + + if (message->generate(message, NULL, &packet) == SUCCESS) + { + free(this->ike_init.ptr); + this->ike_init = chunk_clone(packet->get_data(packet)); + packet->destroy(packet); + } + } + } + return TRUE; +} + +METHOD(hook_t, destroy, void, + private_rebuild_auth_t *this) +{ + free(this->ike_init.ptr); + free(this->nonce.ptr); + DESTROY_IF(this->id); + free(this); +} + +/** + * Create the IKE_AUTH fill hook + */ +hook_t *rebuild_auth_hook_create(char *name) +{ + private_rebuild_auth_t *this; + char *id; + + INIT(this, + .hook = { + .listener = { + .message = _message, + }, + .destroy = _destroy, + }, + ); + id = conftest->test->get_str(conftest->test, "hooks.%s.key", NULL, name); + if (id) + { + this->id = identification_create_from_string(id); + } + + return &this->hook; +} diff --git a/src/conftest/hooks/reset_seq.c b/src/conftest/hooks/reset_seq.c new file mode 100644 index 000000000..ccf8e997d --- /dev/null +++ b/src/conftest/hooks/reset_seq.c @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * 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 "hook.h" + +#include <linux/xfrm.h> +#include <unistd.h> +#include <errno.h> + +#include <processing/jobs/callback_job.h> +#include <plugins/kernel_netlink/kernel_netlink_shared.h> + +#define XFRM_RTA(nlh, x) ((struct rtattr*)(NLMSG_DATA(nlh) + NLMSG_ALIGN(sizeof(x)))) + +typedef struct private_reset_seq_t private_reset_seq_t; + +/** + * Private data of an reset_seq_t object. + */ +struct private_reset_seq_t { + + /** + * Implements the hook_t interface. + */ + hook_t hook; + + /** + * Delay for reset + */ + int delay; +}; + +/** + * Callback job + */ +static job_requeue_t reset_cb(struct xfrm_usersa_id *data) +{ + netlink_buf_t request; + struct nlmsghdr *hdr; + struct xfrm_aevent_id *id; + struct rtattr *rthdr; + struct xfrm_replay_state *replay; + struct sockaddr_nl addr; + int s, len; + + DBG1(DBG_CFG, "resetting sequence number of SPI 0x%x", htonl(data->spi)); + + memset(&request, 0, sizeof(request)); + + hdr = (struct nlmsghdr*)request; + hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_REPLACE; + hdr->nlmsg_seq = 201; + hdr->nlmsg_pid = getpid(); + hdr->nlmsg_type = XFRM_MSG_NEWAE; + hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_aevent_id)); + + id = (struct xfrm_aevent_id*)NLMSG_DATA(hdr); + id->sa_id = *data; + + rthdr = XFRM_RTA(hdr, struct xfrm_aevent_id); + rthdr->rta_type = XFRMA_REPLAY_VAL; + rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_replay_state)); + hdr->nlmsg_len += rthdr->rta_len; + + replay = (struct xfrm_replay_state*)RTA_DATA(rthdr); + + s = socket(AF_NETLINK, SOCK_RAW, NETLINK_XFRM); + if (s == -1) + { + DBG1(DBG_CFG, "opening XFRM socket failed: %s", strerror(errno)); + return JOB_REQUEUE_NONE; + } + memset(&addr, 0, sizeof(addr)); + addr.nl_family = AF_NETLINK; + len = sendto(s, hdr, hdr->nlmsg_len, 0, + (struct sockaddr*)&addr, sizeof(addr)); + if (len != hdr->nlmsg_len) + { + DBG1(DBG_CFG, "sending XFRM aevent failed: %s", strerror(errno)); + } + close(s); + return JOB_REQUEUE_NONE; +} + +/** + * Schedule sequence number reset job + */ +static void schedule_reset_job(private_reset_seq_t *this, host_t *dst, + u_int32_t spi) +{ + struct xfrm_usersa_id *data; + chunk_t chunk; + + INIT(data, + .spi = spi, + .family = dst->get_family(dst), + .proto = IPPROTO_ESP, + ); + + chunk = dst->get_address(dst); + memcpy(&data->daddr, chunk.ptr, min(chunk.len, sizeof(xfrm_address_t))); + + lib->scheduler->schedule_job(lib->scheduler, + (job_t*)callback_job_create( + (void*)reset_cb, data, (void*)free, NULL), + this->delay); +} + +METHOD(listener_t, child_updown, bool, + private_reset_seq_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa, + bool up) +{ + if (up) + { + schedule_reset_job(this, ike_sa->get_other_host(ike_sa), + child_sa->get_spi(child_sa, FALSE)); + } + return TRUE; +} + +METHOD(hook_t, destroy, void, + private_reset_seq_t *this) +{ + free(this); +} + +/** + * Create the IKE_AUTH fill hook + */ +hook_t *reset_seq_hook_create(char *name) +{ + private_reset_seq_t *this; + + INIT(this, + .hook = { + .listener = { + .child_updown = _child_updown, + }, + .destroy = _destroy, + }, + .delay = conftest->test->get_int(conftest->test, + "hooks.%s.delay", 10, name), + ); + + return &this->hook; +} diff --git a/src/conftest/hooks/set_critical.c b/src/conftest/hooks/set_critical.c new file mode 100644 index 000000000..caf2215c3 --- /dev/null +++ b/src/conftest/hooks/set_critical.c @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * 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 "hook.h" + +#include <encoding/payloads/unknown_payload.h> + +typedef struct private_set_critical_t private_set_critical_t; + +/** + * Private data of an set_critical_t object. + */ +struct private_set_critical_t { + + /** + * Implements the hook_t interface. + */ + hook_t hook; + + /** + * Alter requests or responses? + */ + bool req; + + /** + * ID of message to alter. + */ + int id; + + /** + * Payload types, space separated + */ + char *payloads; +}; + +METHOD(listener_t, message, bool, + private_set_critical_t *this, ike_sa_t *ike_sa, message_t *message, + bool incoming) +{ + if (!incoming && + message->get_request(message) == this->req && + message->get_message_id(message) == this->id) + { + enumerator_t *msg, *types; + payload_t *payload; + payload_type_t type; + bool *critical; + char *name; + + types = enumerator_create_token(this->payloads, " ", ""); + while (types->enumerate(types, &name)) + { + type = atoi(name); + if (!type) + { + type = enum_from_name(payload_type_short_names, name); + if (type == -1) + { + DBG1(DBG_CFG, "invalid payload name '%s'", name); + break; + } + } + msg = message->create_payload_enumerator(message); + while (msg->enumerate(msg, &payload)) + { + if (type == payload->get_type(payload)) + { + critical = payload_get_field(payload, FLAG, 0); + if (critical) + { + *critical = TRUE; + } + } + } + msg->destroy(msg); + } + types->destroy(types); + } + return TRUE; +} + +METHOD(hook_t, destroy, void, + private_set_critical_t *this) +{ + free(this); +} + +/** + * Create the IKE_AUTH fill hook + */ +hook_t *set_critical_hook_create(char *name) +{ + private_set_critical_t *this; + + INIT(this, + .hook = { + .listener = { + .message = _message, + }, + .destroy = _destroy, + }, + .req = conftest->test->get_bool(conftest->test, + "hooks.%s.request", TRUE, name), + .id = conftest->test->get_int(conftest->test, + "hooks.%s.id", 0, name), + .payloads = conftest->test->get_str(conftest->test, + "hooks.%s.payloads", "", name), + ); + + return &this->hook; +} diff --git a/src/conftest/hooks/set_ike_initiator.c b/src/conftest/hooks/set_ike_initiator.c new file mode 100644 index 000000000..6ba43eaca --- /dev/null +++ b/src/conftest/hooks/set_ike_initiator.c @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * 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 "hook.h" + +#include <encoding/payloads/unknown_payload.h> + +typedef struct private_set_ike_initiator_t private_set_ike_initiator_t; + +/** + * Private data of an set_ike_initiator_t object. + */ +struct private_set_ike_initiator_t { + + /** + * Implements the hook_t interface. + */ + hook_t hook; + + /** + * Alter requests or responses? + */ + bool req; + + /** + * ID of message to alter. + */ + int id; +}; + +METHOD(listener_t, message, bool, + private_set_ike_initiator_t *this, ike_sa_t *ike_sa, message_t *message, + bool incoming) +{ + if (!incoming && + message->get_request(message) == this->req && + message->get_message_id(message) == this->id) + { + ike_sa_id_t *id; + + DBG1(DBG_CFG, "toggling IKE message initiator flag"); + id = message->get_ike_sa_id(message); + id->switch_initiator(id); + } + return TRUE; +} + +METHOD(hook_t, destroy, void, + private_set_ike_initiator_t *this) +{ + free(this); +} + +/** + * Create the IKE_AUTH fill hook + */ +hook_t *set_ike_initiator_hook_create(char *name) +{ + private_set_ike_initiator_t *this; + + INIT(this, + .hook = { + .listener = { + .message = _message, + }, + .destroy = _destroy, + }, + .req = conftest->test->get_bool(conftest->test, + "hooks.%s.request", TRUE, name), + .id = conftest->test->get_int(conftest->test, + "hooks.%s.id", 0, name), + ); + + return &this->hook; +} diff --git a/src/conftest/hooks/set_ike_request.c b/src/conftest/hooks/set_ike_request.c new file mode 100644 index 000000000..baabea66a --- /dev/null +++ b/src/conftest/hooks/set_ike_request.c @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * 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 "hook.h" + +#include <encoding/payloads/unknown_payload.h> + +typedef struct private_set_ike_request_t private_set_ike_request_t; + +/** + * Private data of an set_ike_request_t object. + */ +struct private_set_ike_request_t { + + /** + * Implements the hook_t interface. + */ + hook_t hook; + + /** + * Alter requests or responses? + */ + bool req; + + /** + * ID of message to alter. + */ + int id; +}; + +METHOD(listener_t, message, bool, + private_set_ike_request_t *this, ike_sa_t *ike_sa, message_t *message, + bool incoming) +{ + if (!incoming && + message->get_request(message) == this->req && + message->get_message_id(message) == this->id) + { + DBG1(DBG_CFG, "toggling IKE message request flag"); + message->set_request(message, !this->req); + } + return TRUE; +} + +METHOD(hook_t, destroy, void, + private_set_ike_request_t *this) +{ + free(this); +} + +/** + * Create the IKE_AUTH fill hook + */ +hook_t *set_ike_request_hook_create(char *name) +{ + private_set_ike_request_t *this; + + INIT(this, + .hook = { + .listener = { + .message = _message, + }, + .destroy = _destroy, + }, + .req = conftest->test->get_bool(conftest->test, + "hooks.%s.request", TRUE, name), + .id = conftest->test->get_int(conftest->test, + "hooks.%s.id", 0, name), + ); + + return &this->hook; +} diff --git a/src/conftest/hooks/set_ike_spi.c b/src/conftest/hooks/set_ike_spi.c new file mode 100644 index 000000000..14a0da9cd --- /dev/null +++ b/src/conftest/hooks/set_ike_spi.c @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * 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 "hook.h" + +#include <encoding/payloads/unknown_payload.h> + +typedef struct private_set_ike_spi_t private_set_ike_spi_t; + +/** + * Private data of an set_ike_spi_t object. + */ +struct private_set_ike_spi_t { + + /** + * Implements the hook_t interface. + */ + hook_t hook; + + /** + * Alter requests or responses? + */ + bool req; + + /** + * ID of message to alter. + */ + int id; + + /** + * Initiator SPI + */ + u_int64_t spii; + + /** + * Responder SPI + */ + u_int64_t spir; +}; + +METHOD(listener_t, message, bool, + private_set_ike_spi_t *this, ike_sa_t *ike_sa, message_t *message, + bool incoming) +{ + if (!incoming && + message->get_request(message) == this->req && + message->get_message_id(message) == this->id) + { + ike_sa_id_t *id; + + DBG1(DBG_CFG, "setting IKE SPIs to: 0x%llx/0x%llx", + this->spii, this->spir); + + id = message->get_ike_sa_id(message); + id->set_initiator_spi(id, this->spii); + id->set_responder_spi(id, this->spir); + } + return TRUE; +} + +METHOD(hook_t, destroy, void, + private_set_ike_spi_t *this) +{ + free(this); +} + +/** + * Create the IKE_AUTH fill hook + */ +hook_t *set_ike_spi_hook_create(char *name) +{ + private_set_ike_spi_t *this; + + INIT(this, + .hook = { + .listener = { + .message = _message, + }, + .destroy = _destroy, + }, + .req = conftest->test->get_bool(conftest->test, + "hooks.%s.request", TRUE, name), + .id = conftest->test->get_int(conftest->test, + "hooks.%s.id", 0, name), + .spii = strtoull(conftest->test->get_str(conftest->test, + "hooks.%s.spii", "0", name), NULL, 16), + .spir = strtoull(conftest->test->get_str(conftest->test, + "hooks.%s.spir", "0", name), NULL, 16), + ); + + return &this->hook; +} diff --git a/src/conftest/hooks/set_ike_version.c b/src/conftest/hooks/set_ike_version.c new file mode 100644 index 000000000..d2de9dc81 --- /dev/null +++ b/src/conftest/hooks/set_ike_version.c @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * 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 "hook.h" + +#include <encoding/payloads/unknown_payload.h> + +typedef struct private_set_ike_version_t private_set_ike_version_t; + +/** + * Private data of an set_ike_version_t object. + */ +struct private_set_ike_version_t { + + /** + * Implements the hook_t interface. + */ + hook_t hook; + + /** + * Alter requests or responses? + */ + bool req; + + /** + * ID of message to alter. + */ + int id; + + /** + * Major version to set + */ + int major; + + /** + * Minor version to set + */ + int minor; + + /** + * Higher version supported? + */ + bool higher; +}; + +METHOD(listener_t, message, bool, + private_set_ike_version_t *this, ike_sa_t *ike_sa, message_t *message, + bool incoming) +{ + if (!incoming && + message->get_request(message) == this->req && + message->get_message_id(message) == this->id) + { + DBG1(DBG_CFG, "setting IKE version of message ID %d to %d.%d", + this->id, this->major, this->minor); + message->set_major_version(message, this->major); + message->set_minor_version(message, this->minor); + if (this->higher) + { + message->set_version_flag(message); + } + } + return TRUE; +} + +METHOD(hook_t, destroy, void, + private_set_ike_version_t *this) +{ + free(this); +} + +/** + * Create the IKE_AUTH fill hook + */ +hook_t *set_ike_version_hook_create(char *name) +{ + private_set_ike_version_t *this; + + INIT(this, + .hook = { + .listener = { + .message = _message, + }, + .destroy = _destroy, + }, + .req = conftest->test->get_bool(conftest->test, + "hooks.%s.request", TRUE, name), + .id = conftest->test->get_int(conftest->test, + "hooks.%s.id", 0, name), + .major = conftest->test->get_int(conftest->test, + "hooks.%s.major", 2, name), + .minor = conftest->test->get_int(conftest->test, + "hooks.%s.minor", 0, name), + .higher = conftest->test->get_bool(conftest->test, + "hooks.%s.higher", FALSE, name), + ); + + return &this->hook; +} diff --git a/src/conftest/hooks/set_length.c b/src/conftest/hooks/set_length.c new file mode 100644 index 000000000..0379dcb7c --- /dev/null +++ b/src/conftest/hooks/set_length.c @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * 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 "hook.h" + +typedef struct private_set_length_t private_set_length_t; + +/** + * Private data of an set_length_t object. + */ +struct private_set_length_t { + + /** + * Implements the hook_t interface. + */ + hook_t hook; + + /** + * Alter requests or responses? + */ + bool req; + + /** + * ID of message to alter. + */ + int id; + + /** + * Payload type + */ + char *type; + + /** + * Difference to correct length + */ + int diff; +}; + +METHOD(listener_t, message, bool, + private_set_length_t *this, ike_sa_t *ike_sa, message_t *message, + bool incoming) +{ + if (!incoming && + message->get_request(message) == this->req && + message->get_message_id(message) == this->id) + { + payload_t *payload; + enumerator_t *enumerator; + payload_type_t type; + + type = atoi(this->type); + if (!type) + { + type = enum_from_name(payload_type_short_names, this->type); + if (type == -1) + { + DBG1(DBG_CFG, "unknown payload: '%s', skipped", this->type); + return TRUE; + } + } + enumerator = message->create_payload_enumerator(message); + while (enumerator->enumerate(enumerator, &payload)) + { + if (type == payload->get_type(payload)) + { + encoding_rule_t *rules; + size_t count; + u_int16_t *len; + int i; + + payload->get_encoding_rules(payload, &rules, &count); + for (i = 0; i < count; i++) + { + if (rules[i].type == PAYLOAD_LENGTH) + { + len = (u_int16_t*)(((void*)payload) + rules[i].offset); + DBG1(DBG_CFG, "adjusting length of %N payload " + "from %d to %d", payload_type_short_names, type, + *len, *len + this->diff); + *len = *len + this->diff; + } + } + } + } + enumerator->destroy(enumerator); + } + return TRUE; +} + +METHOD(hook_t, destroy, void, + private_set_length_t *this) +{ + free(this); +} + +/** + * Create the IKE_AUTH fill hook + */ +hook_t *set_length_hook_create(char *name) +{ + private_set_length_t *this; + + INIT(this, + .hook = { + .listener = { + .message = _message, + }, + .destroy = _destroy, + }, + .req = conftest->test->get_bool(conftest->test, + "hooks.%s.request", TRUE, name), + .id = conftest->test->get_int(conftest->test, + "hooks.%s.id", 0, name), + .type = conftest->test->get_str(conftest->test, + "hooks.%s.type", "", name), + .diff = conftest->test->get_int(conftest->test, + "hooks.%s.diff", 0, name), + ); + + return &this->hook; +} diff --git a/src/conftest/hooks/set_proposal_number.c b/src/conftest/hooks/set_proposal_number.c new file mode 100644 index 000000000..a59d96b6d --- /dev/null +++ b/src/conftest/hooks/set_proposal_number.c @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * 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 "hook.h" + +#include <encoding/payloads/sa_payload.h> + +typedef struct private_set_proposal_number_t private_set_proposal_number_t; + +/** + * Private data of an set_proposal_number_t object. + */ +struct private_set_proposal_number_t { + + /** + * Implements the hook_t interface. + */ + hook_t hook; + + /** + * Alter requests or responses? + */ + bool req; + + /** + * ID of message to alter. + */ + int id; + + /** + * Proposal number to modify + */ + int from; + + /** + * Proposal number to set + */ + int to; +}; + +/** + * Copy all algs from given type from one proposal to another + */ +static void copy_proposal_algs(proposal_t *from, proposal_t *to, + transform_type_t type) +{ + enumerator_t *enumerator; + u_int16_t alg, key_size; + + enumerator = from->create_enumerator(from, type); + while (enumerator->enumerate(enumerator, &alg, &key_size)) + { + to->add_algorithm(to, type, alg, key_size); + } + enumerator->destroy(enumerator); +} + +METHOD(listener_t, message, bool, + private_set_proposal_number_t *this, ike_sa_t *ike_sa, message_t *message, + bool incoming) +{ + if (!incoming && + message->get_request(message) == this->req && + message->get_message_id(message) == this->id) + { + enumerator_t *enumerator; + payload_t *payload; + linked_list_t *list = NULL, *updated; + sa_payload_t *sa; + proposal_t *proposal, *new; + + updated = linked_list_create(); + enumerator = message->create_payload_enumerator(message); + while (enumerator->enumerate(enumerator, &payload)) + { + if (payload->get_type(payload) == SECURITY_ASSOCIATION) + { + sa = (sa_payload_t*)payload; + list = sa->get_proposals(sa); + message->remove_payload_at(message, enumerator); + sa->destroy(sa); + } + } + enumerator->destroy(enumerator); + + if (list) + { + enumerator = list->create_enumerator(list); + while (enumerator->enumerate(enumerator, &proposal)) + { + if (proposal->get_number(proposal) == this->from) + { + DBG1(DBG_CFG, "setting proposal number from %d to %d", + this->from, this->to); + new = proposal_create(proposal->get_protocol(proposal), + this->to); + copy_proposal_algs(proposal, new, ENCRYPTION_ALGORITHM); + copy_proposal_algs(proposal, new, INTEGRITY_ALGORITHM); + copy_proposal_algs(proposal, new, PSEUDO_RANDOM_FUNCTION); + copy_proposal_algs(proposal, new, DIFFIE_HELLMAN_GROUP); + copy_proposal_algs(proposal, new, EXTENDED_SEQUENCE_NUMBERS); + updated->insert_last(updated, new); + } + else + { + list->remove_at(list, enumerator); + updated->insert_last(updated, proposal); + } + } + enumerator->destroy(enumerator); + } + sa = sa_payload_create_from_proposal_list(updated); + list->destroy_offset(list, offsetof(proposal_t, destroy)); + updated->destroy_offset(updated, offsetof(proposal_t, destroy)); + message->add_payload(message, (payload_t*)sa); + } + return TRUE; +} + +METHOD(hook_t, destroy, void, + private_set_proposal_number_t *this) +{ + free(this); +} + +/** + * Create the IKE_AUTH fill hook + */ +hook_t *set_proposal_number_hook_create(char *name) +{ + private_set_proposal_number_t *this; + + INIT(this, + .hook = { + .listener = { + .message = _message, + }, + .destroy = _destroy, + }, + .req = conftest->test->get_bool(conftest->test, + "hooks.%s.request", TRUE, name), + .id = conftest->test->get_int(conftest->test, + "hooks.%s.id", 0, name), + .from = conftest->test->get_int(conftest->test, + "hooks.%s.from", 0, name), + .to = conftest->test->get_int(conftest->test, + "hooks.%s.to", 1, name), + ); + + return &this->hook; +} diff --git a/src/conftest/hooks/set_reserved.c b/src/conftest/hooks/set_reserved.c new file mode 100644 index 000000000..77a605d2a --- /dev/null +++ b/src/conftest/hooks/set_reserved.c @@ -0,0 +1,245 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * 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 "hook.h" + +#include <encoding/payloads/sa_payload.h> + +typedef struct private_set_reserved_t private_set_reserved_t; + +/** + * Private data of an set_reserved_t object. + */ +struct private_set_reserved_t { + + /** + * Implements the hook_t interface. + */ + hook_t hook; + + /** + * Alter requests or responses? + */ + bool req; + + /** + * ID of message to alter. + */ + int id; + + /** + * Hook name + */ + char *name; +}; + +/** + * Set reserved bit of a payload + */ +static void set_bit(private_set_reserved_t *this, message_t *message, + payload_type_t type, u_int nr) +{ + enumerator_t *payloads; + payload_t *payload; + bool *bit; + + if (type == HEADER) + { + message->set_reserved_header_bit(message, nr); + DBG1(DBG_CFG, "setting reserved bit %d of %N", + nr, payload_type_short_names, type); + } + else + { + payloads = message->create_payload_enumerator(message); + while (payloads->enumerate(payloads, &payload)) + { + if (payload->get_type(payload) == type) + { + bit = payload_get_field(payload, RESERVED_BIT, nr); + if (bit) + { + DBG1(DBG_CFG, "setting reserved bit %d of %N", + nr, payload_type_short_names, type); + *bit = TRUE; + } + } + } + payloads->destroy(payloads); + } +} + +/** + * Set reserved byte of a payload + */ +static void set_byte(private_set_reserved_t *this, message_t *message, + payload_type_t type, u_int nr, u_int8_t byteval) +{ + enumerator_t *payloads; + payload_t *payload; + u_int8_t *byte; + + if (type == TRANSFORM_SUBSTRUCTURE || type == PROPOSAL_SUBSTRUCTURE) + { + enumerator_t *transforms, *proposals; + transform_substructure_t *transform; + proposal_substructure_t *proposal; + sa_payload_t *sa; + + payloads = message->create_payload_enumerator(message); + while (payloads->enumerate(payloads, &payload)) + { + if (payload->get_type(payload) == SECURITY_ASSOCIATION) + { + sa = (sa_payload_t*)payload; + proposals = sa->create_substructure_enumerator(sa); + while (proposals->enumerate(proposals, &proposal)) + { + if (type == PROPOSAL_SUBSTRUCTURE) + { + byte = payload_get_field(&proposal->payload_interface, + RESERVED_BYTE, nr); + if (byte) + { + DBG1(DBG_CFG, "setting reserved byte %d of %N to %d", + nr, payload_type_short_names, type, byteval); + *byte = byteval; + } + } + else if (type == TRANSFORM_SUBSTRUCTURE) + { + transforms = proposal->create_substructure_enumerator( + proposal); + while (transforms->enumerate(transforms, &transform)) + { + byte = payload_get_field(&transform->payload_interface, + RESERVED_BYTE, nr); + if (byte) + { + DBG1(DBG_CFG, "setting reserved byte %d of %N to %d", + nr, payload_type_short_names, type, byteval); + *byte = byteval; + } + } + transforms->destroy(transforms); + } + } + proposals->destroy(proposals); + } + } + payloads->destroy(payloads); + } + else + { + payloads = message->create_payload_enumerator(message); + while (payloads->enumerate(payloads, &payload)) + { + if (payload->get_type(payload) == type) + { + byte = payload_get_field(payload, RESERVED_BYTE, nr); + if (byte) + { + DBG1(DBG_CFG, "setting reserved byte %d of %N to %d", + nr, payload_type_short_names, type, byteval); + *byte = byteval; + } + } + } + payloads->destroy(payloads); + } +} + +METHOD(listener_t, message, bool, + private_set_reserved_t *this, ike_sa_t *ike_sa, message_t *message, + bool incoming) +{ + if (!incoming && + message->get_request(message) == this->req && + message->get_message_id(message) == this->id) + { + enumerator_t *bits, *bytes, *types; + payload_type_t type; + char *nr, *name; + u_int8_t byteval; + + types = conftest->test->create_section_enumerator(conftest->test, + "hooks.%s", this->name); + while (types->enumerate(types, &name)) + { + type = atoi(name); + if (!type) + { + type = enum_from_name(payload_type_short_names, name); + if (type == -1) + { + DBG1(DBG_CFG, "invalid payload name '%s'", name); + break; + } + } + nr = conftest->test->get_str(conftest->test, + "hooks.%s.%s.bits", "", this->name, name); + bits = enumerator_create_token(nr, ",", " "); + while (bits->enumerate(bits, &nr)) + { + set_bit(this, message, type, atoi(nr)); + } + bits->destroy(bits); + + nr = conftest->test->get_str(conftest->test, + "hooks.%s.%s.bytes", "", this->name, name); + byteval = conftest->test->get_int(conftest->test, + "hooks.%s.%s.byteval", 255, this->name, name); + bytes = enumerator_create_token(nr, ",", " "); + while (bytes->enumerate(bytes, &nr)) + { + set_byte(this, message, type, atoi(nr), byteval); + } + bytes->destroy(bytes); + } + types->destroy(types); + } + return TRUE; +} + +METHOD(hook_t, destroy, void, + private_set_reserved_t *this) +{ + free(this->name); + free(this); +} + +/** + * Create the IKE_AUTH fill hook + */ +hook_t *set_reserved_hook_create(char *name) +{ + private_set_reserved_t *this; + + INIT(this, + .hook = { + .listener = { + .message = _message, + }, + .destroy = _destroy, + }, + .req = conftest->test->get_bool(conftest->test, + "hooks.%s.request", TRUE, name), + .id = conftest->test->get_int(conftest->test, + "hooks.%s.id", 0, name), + .name = strdup(name), + ); + + return &this->hook; +} diff --git a/src/conftest/hooks/unencrypted_notify.c b/src/conftest/hooks/unencrypted_notify.c new file mode 100644 index 000000000..80bdc64b7 --- /dev/null +++ b/src/conftest/hooks/unencrypted_notify.c @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * 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 "hook.h" + +typedef struct private_unencrypted_notify_t private_unencrypted_notify_t; + +/** + * Private data of an unencrypted_notify_t object. + */ +struct private_unencrypted_notify_t { + + /** + * Implements the hook_t interface. + */ + hook_t hook; + + /** + * ID of message send. + */ + int id; + + /** + * Notify type + */ + char *type; + + /** + * Notify data + */ + char *data; + + /** + * SPI of notify + */ + int spi; + + /** + * TRUE for a ESP protocol notify, FALSE for IKE + */ + bool esp; +}; + +METHOD(listener_t, ike_updown, bool, + private_unencrypted_notify_t *this, ike_sa_t *ike_sa, bool up) +{ + if (up) + { + message_t *message; + host_t *host; + notify_type_t type; + notify_payload_t *notify; + chunk_t data = chunk_empty; + packet_t *packet; + + type = atoi(this->type); + if (!type) + { + type = enum_from_name(notify_type_names, this->type); + if (type == -1) + { + DBG1(DBG_CFG, "unknown notify: '%s', skipped", this->type); + return TRUE; + } + } + if (strncaseeq(this->data, "0x", 2)) + { + data = chunk_skip(chunk_create(this->data, strlen(this->data)), 2); + data = chunk_from_hex(data, NULL); + } + else if (this->data && strlen(this->data)) + { + data = chunk_clone(chunk_create(this->data, strlen(this->data))); + } + notify = notify_payload_create_from_protocol_and_type( + this->esp ? PROTO_ESP : PROTO_IKE, type); + notify->set_spi(notify, this->spi); + if (data.len) + { + notify->set_notification_data(notify, data); + free(data.ptr); + } + + DBG1(DBG_CFG, "injecting unencrypted INFORMATIONAL message"); + + message = message_create(); + message->set_message_id(message, this->id); + message->set_ike_sa_id(message, ike_sa->get_id(ike_sa)); + message->set_exchange_type(message, INFORMATIONAL); + message->set_request(message, TRUE); + host = ike_sa->get_my_host(ike_sa); + message->set_source(message, host->clone(host)); + host = ike_sa->get_other_host(ike_sa); + message->set_destination(message, host->clone(host)); + message->add_payload(message, ¬ify->payload_interface); + if (message->generate(message, NULL, &packet) != SUCCESS) + { + DBG1(DBG_CFG, "generating message failed"); + message->destroy(message); + return TRUE; + } + message->destroy(message); + charon->sender->send(charon->sender, packet); + } + return TRUE; +} + +METHOD(hook_t, destroy, void, + private_unencrypted_notify_t *this) +{ + free(this); +} + +/** + * Create the IKE_AUTH fill hook + */ +hook_t *unencrypted_notify_hook_create(char *name) +{ + private_unencrypted_notify_t *this; + + INIT(this, + .hook = { + .listener = { + .ike_updown = _ike_updown, + }, + .destroy = _destroy, + }, + .id = conftest->test->get_int(conftest->test, + "hooks.%s.id", 2, name), + .type = conftest->test->get_str(conftest->test, + "hooks.%s.type", "", name), + .data = conftest->test->get_str(conftest->test, + "hooks.%s.data", "", name), + .spi = conftest->test->get_int(conftest->test, + "hooks.%s.spi", 0, name), + .esp = conftest->test->get_bool(conftest->test, + "hooks.%s.esp", FALSE, name), + ); + + return &this->hook; +} diff --git a/src/conftest/hooks/unsort_message.c b/src/conftest/hooks/unsort_message.c new file mode 100644 index 000000000..b37b261a4 --- /dev/null +++ b/src/conftest/hooks/unsort_message.c @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * 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 "hook.h" + +typedef struct private_unsort_message_t private_unsort_message_t; + +/** + * Private data of an unsort_message_t object. + */ +struct private_unsort_message_t { + + /** + * Implements the hook_t interface. + */ + hook_t hook; + + /** + * Alter requests or responses? + */ + bool req; + + /** + * ID of message to alter. + */ + int id; + + /** + * Order of payloads we want + */ + char *order; +}; + +METHOD(listener_t, message, bool, + private_unsort_message_t *this, ike_sa_t *ike_sa, message_t *message, + bool incoming) +{ + if (!incoming && + message->get_request(message) == this->req && + message->get_message_id(message) == this->id) + { + enumerator_t *enumerator, *order; + linked_list_t *list; + payload_type_t type; + payload_t *payload; + char *name; + + list = linked_list_create(); + enumerator = message->create_payload_enumerator(message); + while (enumerator->enumerate(enumerator, &payload)) + { + message->remove_payload_at(message, enumerator); + list->insert_last(list, payload); + } + enumerator->destroy(enumerator); + + order = enumerator_create_token(this->order, ", ", " "); + while (order->enumerate(order, &name)) + { + type = enum_from_name(payload_type_short_names, name); + if (type != -1) + { + enumerator = list->create_enumerator(list); + while (enumerator->enumerate(enumerator, &payload)) + { + if (payload->get_type(payload) == type) + { + list->remove_at(list, enumerator); + message->add_payload(message, payload); + } + } + enumerator->destroy(enumerator); + } + else + { + DBG1(DBG_CFG, "unknown payload to sort: '%s', skipped", name); + } + } + order->destroy(order); + + while (list->remove_first(list, (void**)&payload) == SUCCESS) + { + message->add_payload(message, payload); + } + list->destroy(list); + + message->disable_sort(message); + } + return TRUE; +} + +METHOD(hook_t, destroy, void, + private_unsort_message_t *this) +{ + free(this); +} + +/** + * Create the IKE_AUTH fill hook + */ +hook_t *unsort_message_hook_create(char *name) +{ + private_unsort_message_t *this; + + INIT(this, + .hook = { + .listener = { + .message = _message, + }, + .destroy = _destroy, + }, + .req = conftest->test->get_bool(conftest->test, + "hooks.%s.request", TRUE, name), + .id = conftest->test->get_int(conftest->test, + "hooks.%s.id", 0, name), + .order = conftest->test->get_str(conftest->test, + "hooks.%s.order", "", name), + ); + + return &this->hook; +} diff --git a/src/dumm/Makefile.in b/src/dumm/Makefile.in index 7c22f5ec5..79961b916 100644 --- a/src/dumm/Makefile.in +++ b/src/dumm/Makefile.in @@ -226,9 +226,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -267,6 +265,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/include/Makefile.in b/src/include/Makefile.in index 498fb17f1..b9b758193 100644 --- a/src/include/Makefile.in +++ b/src/include/Makefile.in @@ -172,9 +172,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -213,6 +211,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/include/linux/xfrm.h b/src/include/linux/xfrm.h index b971e3848..930fdd2de 100644 --- a/src/include/linux/xfrm.h +++ b/src/include/linux/xfrm.h @@ -283,6 +283,7 @@ enum xfrm_attr_type_t { XFRMA_KMADDRESS, /* struct xfrm_user_kmaddress */ XFRMA_ALG_AUTH_TRUNC, /* struct xfrm_algo_auth */ XFRMA_MARK, /* struct xfrm_mark */ + XFRMA_TFCPAD, /* __u32 */ __XFRMA_MAX #define XFRMA_MAX (__XFRMA_MAX - 1) diff --git a/src/ipsec/Makefile.in b/src/ipsec/Makefile.in index 276d9f36d..0b4870e94 100644 --- a/src/ipsec/Makefile.in +++ b/src/ipsec/Makefile.in @@ -200,9 +200,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -241,6 +239,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/ipsec/ipsec.8 b/src/ipsec/ipsec.8 index f995119aa..6f4117be7 100644 --- a/src/ipsec/ipsec.8 +++ b/src/ipsec/ipsec.8 @@ -1,4 +1,4 @@ -.TH IPSEC 8 "2010-05-30" "4.5.0rc1" "strongSwan" +.TH IPSEC 8 "2010-05-30" "4.5.1" "strongSwan" .SH NAME ipsec \- invoke IPsec utilities .SH SYNOPSIS diff --git a/src/ipsec/ipsec.in b/src/ipsec/ipsec.in index 0bddc201a..2ea0ef798 100755 --- a/src/ipsec/ipsec.in +++ b/src/ipsec/ipsec.in @@ -65,7 +65,7 @@ case "$1" in echo " rereadsecrets|rereadgroups" echo " rereadcacerts|rereadaacerts|rereadocspcerts" echo " rereadacerts|rereadcrls|rereadall" - echo " purgeocsp|purgeike" + echo " purgeocsp|purgecrls|purgecerts|purgeike" echo " scencrypt|scdecrypt <value> [--inbase <base>] [--outbase <base>] [--keyid <id>]" echo " openac" echo " pluto" @@ -191,11 +191,11 @@ rereadall|purgeocsp) fi exit "$rc" ;; -purgeike) +purgeike|purgecrls|purgecerts) rc=7 if [ -e $IPSEC_CHARON_PID ] then - $IPSEC_STROKE purgeike + $IPSEC_STROKE "$1" rc="$?" fi exit "$rc" diff --git a/src/libcharon/Makefile.am b/src/libcharon/Makefile.am index 2b7646327..1e78c9d79 100644 --- a/src/libcharon/Makefile.am +++ b/src/libcharon/Makefile.am @@ -53,6 +53,7 @@ processing/jobs/rekey_ike_sa_job.c processing/jobs/rekey_ike_sa_job.h \ processing/jobs/retransmit_job.c processing/jobs/retransmit_job.h \ processing/jobs/send_dpd_job.c processing/jobs/send_dpd_job.h \ processing/jobs/send_keepalive_job.c processing/jobs/send_keepalive_job.h \ +processing/jobs/start_action_job.c processing/jobs/start_action_job.h \ processing/jobs/roam_job.c processing/jobs/roam_job.h \ processing/jobs/update_sa_job.c processing/jobs/update_sa_job.h \ processing/jobs/inactivity_job.c processing/jobs/inactivity_job.h \ @@ -87,8 +88,12 @@ sa/tasks/ike_reauth.c sa/tasks/ike_reauth.h \ sa/tasks/ike_auth_lifetime.c sa/tasks/ike_auth_lifetime.h \ sa/tasks/ike_vendor.c sa/tasks/ike_vendor.h \ sa/tasks/task.c sa/tasks/task.h \ -tnccs/tnccs.c tnccs/tnccs.h \ -tnccs/tnccs_manager.h tnccs/tnccs_manager.c +tnc/tncif.h tnc/tncifimc.h tnc/tncifimv.h tnc/tncifimv.c \ +tnc/imc/imc.h tnc/imc/imc_manager.h \ +tnc/imv/imv.h tnc/imv/imv_manager.h \ +tnc/imv/imv_recommendations.c tnc/imv/imv_recommendations.h \ +tnc/tnccs/tnccs.c tnc/tnccs/tnccs.h \ +tnc/tnccs/tnccs_manager.c tnc/tnccs/tnccs_manager.h daemon.lo : $(top_builddir)/config.status @@ -317,14 +322,14 @@ endif if USE_TNC_IMC SUBDIRS += plugins/tnc_imc if MONOLITHIC - libcharon_la_LIBADD += plugins/tnc_imc/libstrongswan-tnc_imc.la + libcharon_la_LIBADD += plugins/tnc_imc/libstrongswan-tnc-imc.la endif endif if USE_TNC_IMV SUBDIRS += plugins/tnc_imv if MONOLITHIC - libcharon_la_LIBADD += plugins/tnc_imv/libstrongswan-tnc_imv.la + libcharon_la_LIBADD += plugins/tnc_imv/libstrongswan-tnc-imv.la endif endif @@ -342,6 +347,13 @@ if MONOLITHIC endif endif +if USE_TNCCS_DYNAMIC + SUBDIRS += plugins/tnccs_dynamic +if MONOLITHIC + libcharon_la_LIBADD += plugins/tnccs_dynamic/libstrongswan-tnccs-dynamic.la +endif +endif + if USE_MEDSRV SUBDIRS += plugins/medsrv if MONOLITHIC diff --git a/src/libcharon/Makefile.in b/src/libcharon/Makefile.in index 8a7a99ddd..6ec4c6ca5 100644 --- a/src/libcharon/Makefile.in +++ b/src/libcharon/Makefile.in @@ -96,35 +96,37 @@ host_triplet = @host@ @MONOLITHIC_TRUE@@USE_EAP_TNC_TRUE@am__append_51 = plugins/eap_tnc/libstrongswan-eap-tnc.la @MONOLITHIC_TRUE@@USE_TLS_TRUE@am__append_52 = $(top_builddir)/src/libtls/libtls.la @USE_TNC_IMC_TRUE@am__append_53 = plugins/tnc_imc -@MONOLITHIC_TRUE@@USE_TNC_IMC_TRUE@am__append_54 = plugins/tnc_imc/libstrongswan-tnc_imc.la +@MONOLITHIC_TRUE@@USE_TNC_IMC_TRUE@am__append_54 = plugins/tnc_imc/libstrongswan-tnc-imc.la @USE_TNC_IMV_TRUE@am__append_55 = plugins/tnc_imv -@MONOLITHIC_TRUE@@USE_TNC_IMV_TRUE@am__append_56 = plugins/tnc_imv/libstrongswan-tnc_imv.la +@MONOLITHIC_TRUE@@USE_TNC_IMV_TRUE@am__append_56 = plugins/tnc_imv/libstrongswan-tnc-imv.la @USE_TNCCS_11_TRUE@am__append_57 = plugins/tnccs_11 @MONOLITHIC_TRUE@@USE_TNCCS_11_TRUE@am__append_58 = plugins/tnccs_11/libstrongswan-tnccs-11.la @USE_TNCCS_20_TRUE@am__append_59 = plugins/tnccs_20 @MONOLITHIC_TRUE@@USE_TNCCS_20_TRUE@am__append_60 = plugins/tnccs_20/libstrongswan-tnccs-20.la -@USE_MEDSRV_TRUE@am__append_61 = plugins/medsrv -@MONOLITHIC_TRUE@@USE_MEDSRV_TRUE@am__append_62 = plugins/medsrv/libstrongswan-medsrv.la -@USE_MEDCLI_TRUE@am__append_63 = plugins/medcli -@MONOLITHIC_TRUE@@USE_MEDCLI_TRUE@am__append_64 = plugins/medcli/libstrongswan-medcli.la -@USE_NM_TRUE@am__append_65 = plugins/nm -@MONOLITHIC_TRUE@@USE_NM_TRUE@am__append_66 = plugins/nm/libstrongswan-nm.la -@USE_DHCP_TRUE@am__append_67 = plugins/dhcp -@MONOLITHIC_TRUE@@USE_DHCP_TRUE@am__append_68 = plugins/dhcp/libstrongswan-dhcp.la -@USE_ANDROID_TRUE@am__append_69 = plugins/android -@MONOLITHIC_TRUE@@USE_ANDROID_TRUE@am__append_70 = plugins/android/libstrongswan-android.la -@USE_MAEMO_TRUE@am__append_71 = plugins/maemo -@MONOLITHIC_TRUE@@USE_MAEMO_TRUE@am__append_72 = plugins/maemo/libstrongswan-maemo.la -@USE_HA_TRUE@am__append_73 = plugins/ha -@MONOLITHIC_TRUE@@USE_HA_TRUE@am__append_74 = plugins/ha/libstrongswan-ha.la -@USE_LED_TRUE@am__append_75 = plugins/led -@MONOLITHIC_TRUE@@USE_LED_TRUE@am__append_76 = plugins/led/libstrongswan-led.la -@USE_UCI_TRUE@am__append_77 = plugins/uci -@MONOLITHIC_TRUE@@USE_UCI_TRUE@am__append_78 = plugins/uci/libstrongswan-uci.la -@USE_ADDRBLOCK_TRUE@am__append_79 = plugins/addrblock -@MONOLITHIC_TRUE@@USE_ADDRBLOCK_TRUE@am__append_80 = plugins/uci/libstrongswan-addrblock.la -@USE_UNIT_TESTS_TRUE@am__append_81 = plugins/unit_tester -@MONOLITHIC_TRUE@@USE_UNIT_TESTS_TRUE@am__append_82 = plugins/unit_tester/libstrongswan-unit-tester.la +@USE_TNCCS_DYNAMIC_TRUE@am__append_61 = plugins/tnccs_dynamic +@MONOLITHIC_TRUE@@USE_TNCCS_DYNAMIC_TRUE@am__append_62 = plugins/tnccs_dynamic/libstrongswan-tnccs-dynamic.la +@USE_MEDSRV_TRUE@am__append_63 = plugins/medsrv +@MONOLITHIC_TRUE@@USE_MEDSRV_TRUE@am__append_64 = plugins/medsrv/libstrongswan-medsrv.la +@USE_MEDCLI_TRUE@am__append_65 = plugins/medcli +@MONOLITHIC_TRUE@@USE_MEDCLI_TRUE@am__append_66 = plugins/medcli/libstrongswan-medcli.la +@USE_NM_TRUE@am__append_67 = plugins/nm +@MONOLITHIC_TRUE@@USE_NM_TRUE@am__append_68 = plugins/nm/libstrongswan-nm.la +@USE_DHCP_TRUE@am__append_69 = plugins/dhcp +@MONOLITHIC_TRUE@@USE_DHCP_TRUE@am__append_70 = plugins/dhcp/libstrongswan-dhcp.la +@USE_ANDROID_TRUE@am__append_71 = plugins/android +@MONOLITHIC_TRUE@@USE_ANDROID_TRUE@am__append_72 = plugins/android/libstrongswan-android.la +@USE_MAEMO_TRUE@am__append_73 = plugins/maemo +@MONOLITHIC_TRUE@@USE_MAEMO_TRUE@am__append_74 = plugins/maemo/libstrongswan-maemo.la +@USE_HA_TRUE@am__append_75 = plugins/ha +@MONOLITHIC_TRUE@@USE_HA_TRUE@am__append_76 = plugins/ha/libstrongswan-ha.la +@USE_LED_TRUE@am__append_77 = plugins/led +@MONOLITHIC_TRUE@@USE_LED_TRUE@am__append_78 = plugins/led/libstrongswan-led.la +@USE_UCI_TRUE@am__append_79 = plugins/uci +@MONOLITHIC_TRUE@@USE_UCI_TRUE@am__append_80 = plugins/uci/libstrongswan-uci.la +@USE_ADDRBLOCK_TRUE@am__append_81 = plugins/addrblock +@MONOLITHIC_TRUE@@USE_ADDRBLOCK_TRUE@am__append_82 = plugins/uci/libstrongswan-addrblock.la +@USE_UNIT_TESTS_TRUE@am__append_83 = plugins/unit_tester +@MONOLITHIC_TRUE@@USE_UNIT_TESTS_TRUE@am__append_84 = plugins/unit_tester/libstrongswan-unit-tester.la subdir = src/libcharon DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -181,7 +183,8 @@ libcharon_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \ $(am__append_60) $(am__append_62) $(am__append_64) \ $(am__append_66) $(am__append_68) $(am__append_70) \ $(am__append_72) $(am__append_74) $(am__append_76) \ - $(am__append_78) $(am__append_80) $(am__append_82) + $(am__append_78) $(am__append_80) $(am__append_82) \ + $(am__append_84) am__libcharon_la_SOURCES_DIST = bus/bus.c bus/bus.h \ bus/listeners/listener.h bus/listeners/file_logger.c \ bus/listeners/file_logger.h bus/listeners/sys_logger.c \ @@ -251,8 +254,9 @@ am__libcharon_la_SOURCES_DIST = bus/bus.c bus/bus.h \ processing/jobs/send_dpd_job.c processing/jobs/send_dpd_job.h \ processing/jobs/send_keepalive_job.c \ processing/jobs/send_keepalive_job.h \ - processing/jobs/roam_job.c processing/jobs/roam_job.h \ - processing/jobs/update_sa_job.c \ + processing/jobs/start_action_job.c \ + processing/jobs/start_action_job.h processing/jobs/roam_job.c \ + processing/jobs/roam_job.h processing/jobs/update_sa_job.c \ processing/jobs/update_sa_job.h \ processing/jobs/inactivity_job.c \ processing/jobs/inactivity_job.h \ @@ -288,8 +292,12 @@ am__libcharon_la_SOURCES_DIST = bus/bus.c bus/bus.h \ sa/tasks/ike_reauth.h sa/tasks/ike_auth_lifetime.c \ sa/tasks/ike_auth_lifetime.h sa/tasks/ike_vendor.c \ sa/tasks/ike_vendor.h sa/tasks/task.c sa/tasks/task.h \ - tnccs/tnccs.c tnccs/tnccs.h tnccs/tnccs_manager.h \ - tnccs/tnccs_manager.c encoding/payloads/endpoint_notify.c \ + tnc/tncif.h tnc/tncifimc.h tnc/tncifimv.h tnc/tncifimv.c \ + tnc/imc/imc.h tnc/imc/imc_manager.h tnc/imv/imv.h \ + tnc/imv/imv_manager.h tnc/imv/imv_recommendations.c \ + tnc/imv/imv_recommendations.h tnc/tnccs/tnccs.c \ + tnc/tnccs/tnccs.h tnc/tnccs/tnccs_manager.c \ + tnc/tnccs/tnccs_manager.h encoding/payloads/endpoint_notify.c \ encoding/payloads/endpoint_notify.h \ processing/jobs/initiate_mediation_job.c \ processing/jobs/initiate_mediation_job.h \ @@ -315,16 +323,17 @@ am_libcharon_la_OBJECTS = bus.lo file_logger.lo sys_logger.lo \ acquire_job.lo delete_child_sa_job.lo delete_ike_sa_job.lo \ migrate_job.lo process_message_job.lo rekey_child_sa_job.lo \ rekey_ike_sa_job.lo retransmit_job.lo send_dpd_job.lo \ - send_keepalive_job.lo roam_job.lo update_sa_job.lo \ - inactivity_job.lo authenticator.lo eap_authenticator.lo \ - eap_method.lo eap_manager.lo sim_manager.lo \ - psk_authenticator.lo pubkey_authenticator.lo child_sa.lo \ - ike_sa.lo ike_sa_id.lo ike_sa_manager.lo task_manager.lo \ - keymat.lo trap_manager.lo child_create.lo child_delete.lo \ - child_rekey.lo ike_auth.lo ike_cert_pre.lo ike_cert_post.lo \ - ike_config.lo ike_delete.lo ike_dpd.lo ike_init.lo ike_natd.lo \ - ike_mobike.lo ike_rekey.lo ike_reauth.lo ike_auth_lifetime.lo \ - ike_vendor.lo task.lo tnccs.lo tnccs_manager.lo \ + send_keepalive_job.lo start_action_job.lo roam_job.lo \ + update_sa_job.lo inactivity_job.lo authenticator.lo \ + eap_authenticator.lo eap_method.lo eap_manager.lo \ + sim_manager.lo psk_authenticator.lo pubkey_authenticator.lo \ + child_sa.lo ike_sa.lo ike_sa_id.lo ike_sa_manager.lo \ + task_manager.lo keymat.lo trap_manager.lo child_create.lo \ + child_delete.lo child_rekey.lo ike_auth.lo ike_cert_pre.lo \ + ike_cert_post.lo ike_config.lo ike_delete.lo ike_dpd.lo \ + ike_init.lo ike_natd.lo ike_mobike.lo ike_rekey.lo \ + ike_reauth.lo ike_auth_lifetime.lo ike_vendor.lo task.lo \ + tncifimv.lo imv_recommendations.lo tnccs.lo tnccs_manager.lo \ $(am__objects_1) libcharon_la_OBJECTS = $(am_libcharon_la_OBJECTS) DEFAULT_INCLUDES = -I.@am__isrc@ @@ -366,9 +375,9 @@ DIST_SUBDIRS = . plugins/load_tester plugins/socket_default \ plugins/eap_mschapv2 plugins/eap_radius plugins/eap_tls \ plugins/eap_ttls plugins/eap_tnc plugins/tnc_imc \ plugins/tnc_imv plugins/tnccs_11 plugins/tnccs_20 \ - plugins/medsrv plugins/medcli plugins/nm plugins/dhcp \ - plugins/android plugins/maemo plugins/ha plugins/led \ - plugins/uci plugins/addrblock plugins/unit_tester + plugins/tnccs_dynamic plugins/medsrv plugins/medcli plugins/nm \ + plugins/dhcp plugins/android plugins/maemo plugins/ha \ + plugins/led plugins/uci plugins/addrblock plugins/unit_tester DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ @@ -514,9 +523,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -555,6 +562,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ @@ -635,8 +644,9 @@ libcharon_la_SOURCES = bus/bus.c bus/bus.h bus/listeners/listener.h \ processing/jobs/send_dpd_job.c processing/jobs/send_dpd_job.h \ processing/jobs/send_keepalive_job.c \ processing/jobs/send_keepalive_job.h \ - processing/jobs/roam_job.c processing/jobs/roam_job.h \ - processing/jobs/update_sa_job.c \ + processing/jobs/start_action_job.c \ + processing/jobs/start_action_job.h processing/jobs/roam_job.c \ + processing/jobs/roam_job.h processing/jobs/update_sa_job.c \ processing/jobs/update_sa_job.h \ processing/jobs/inactivity_job.c \ processing/jobs/inactivity_job.h \ @@ -672,8 +682,12 @@ libcharon_la_SOURCES = bus/bus.c bus/bus.h bus/listeners/listener.h \ sa/tasks/ike_reauth.h sa/tasks/ike_auth_lifetime.c \ sa/tasks/ike_auth_lifetime.h sa/tasks/ike_vendor.c \ sa/tasks/ike_vendor.h sa/tasks/task.c sa/tasks/task.h \ - tnccs/tnccs.c tnccs/tnccs.h tnccs/tnccs_manager.h \ - tnccs/tnccs_manager.c $(am__append_1) + tnc/tncif.h tnc/tncifimc.h tnc/tncifimv.h tnc/tncifimv.c \ + tnc/imc/imc.h tnc/imc/imc_manager.h tnc/imv/imv.h \ + tnc/imv/imv_manager.h tnc/imv/imv_recommendations.c \ + tnc/imv/imv_recommendations.h tnc/tnccs/tnccs.c \ + tnc/tnccs/tnccs.h tnc/tnccs/tnccs_manager.c \ + tnc/tnccs/tnccs_manager.h $(am__append_1) INCLUDES = \ -I${linux_headers} \ -I$(top_srcdir)/src/libstrongswan \ @@ -699,7 +713,8 @@ libcharon_la_LIBADD = -lm $(PTHREADLIB) $(DLLIB) $(SOCKLIB) \ $(am__append_60) $(am__append_62) $(am__append_64) \ $(am__append_66) $(am__append_68) $(am__append_70) \ $(am__append_72) $(am__append_74) $(am__append_76) \ - $(am__append_78) $(am__append_80) $(am__append_82) + $(am__append_78) $(am__append_80) $(am__append_82) \ + $(am__append_84) EXTRA_DIST = Android.mk @MONOLITHIC_FALSE@SUBDIRS = . $(am__append_3) $(am__append_5) \ @MONOLITHIC_FALSE@ $(am__append_7) $(am__append_9) \ @@ -720,7 +735,7 @@ EXTRA_DIST = Android.mk @MONOLITHIC_FALSE@ $(am__append_69) $(am__append_71) \ @MONOLITHIC_FALSE@ $(am__append_73) $(am__append_75) \ @MONOLITHIC_FALSE@ $(am__append_77) $(am__append_79) \ -@MONOLITHIC_FALSE@ $(am__append_81) +@MONOLITHIC_FALSE@ $(am__append_81) $(am__append_83) # build optional plugins ######################## @@ -743,7 +758,7 @@ EXTRA_DIST = Android.mk @MONOLITHIC_TRUE@ $(am__append_69) $(am__append_71) \ @MONOLITHIC_TRUE@ $(am__append_73) $(am__append_75) \ @MONOLITHIC_TRUE@ $(am__append_77) $(am__append_79) \ -@MONOLITHIC_TRUE@ $(am__append_81) +@MONOLITHIC_TRUE@ $(am__append_81) $(am__append_83) all: all-recursive .SUFFIXES: @@ -867,6 +882,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_sa_id.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_sa_manager.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ike_vendor.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imv_recommendations.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/inactivity_job.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/initiate_mediation_job.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ke_payload.Plo@am__quote@ @@ -898,11 +914,13 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sender.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sim_manager.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socket_manager.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/start_action_job.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sys_logger.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/task.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/task_manager.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnccs.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnccs_manager.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tncifimv.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/traffic_selector_substructure.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/transform_attribute.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/transform_substructure.Plo@am__quote@ @@ -1283,6 +1301,13 @@ send_keepalive_job.lo: processing/jobs/send_keepalive_job.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o send_keepalive_job.lo `test -f 'processing/jobs/send_keepalive_job.c' || echo '$(srcdir)/'`processing/jobs/send_keepalive_job.c +start_action_job.lo: processing/jobs/start_action_job.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT start_action_job.lo -MD -MP -MF $(DEPDIR)/start_action_job.Tpo -c -o start_action_job.lo `test -f 'processing/jobs/start_action_job.c' || echo '$(srcdir)/'`processing/jobs/start_action_job.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/start_action_job.Tpo $(DEPDIR)/start_action_job.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='processing/jobs/start_action_job.c' object='start_action_job.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o start_action_job.lo `test -f 'processing/jobs/start_action_job.c' || echo '$(srcdir)/'`processing/jobs/start_action_job.c + roam_job.lo: processing/jobs/roam_job.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT roam_job.lo -MD -MP -MF $(DEPDIR)/roam_job.Tpo -c -o roam_job.lo `test -f 'processing/jobs/roam_job.c' || echo '$(srcdir)/'`processing/jobs/roam_job.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/roam_job.Tpo $(DEPDIR)/roam_job.Plo @@ -1521,19 +1546,33 @@ task.lo: sa/tasks/task.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o task.lo `test -f 'sa/tasks/task.c' || echo '$(srcdir)/'`sa/tasks/task.c -tnccs.lo: tnccs/tnccs.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tnccs.lo -MD -MP -MF $(DEPDIR)/tnccs.Tpo -c -o tnccs.lo `test -f 'tnccs/tnccs.c' || echo '$(srcdir)/'`tnccs/tnccs.c +tncifimv.lo: tnc/tncifimv.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tncifimv.lo -MD -MP -MF $(DEPDIR)/tncifimv.Tpo -c -o tncifimv.lo `test -f 'tnc/tncifimv.c' || echo '$(srcdir)/'`tnc/tncifimv.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/tncifimv.Tpo $(DEPDIR)/tncifimv.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tnc/tncifimv.c' object='tncifimv.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tncifimv.lo `test -f 'tnc/tncifimv.c' || echo '$(srcdir)/'`tnc/tncifimv.c + +imv_recommendations.lo: tnc/imv/imv_recommendations.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT imv_recommendations.lo -MD -MP -MF $(DEPDIR)/imv_recommendations.Tpo -c -o imv_recommendations.lo `test -f 'tnc/imv/imv_recommendations.c' || echo '$(srcdir)/'`tnc/imv/imv_recommendations.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/imv_recommendations.Tpo $(DEPDIR)/imv_recommendations.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tnc/imv/imv_recommendations.c' object='imv_recommendations.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o imv_recommendations.lo `test -f 'tnc/imv/imv_recommendations.c' || echo '$(srcdir)/'`tnc/imv/imv_recommendations.c + +tnccs.lo: tnc/tnccs/tnccs.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tnccs.lo -MD -MP -MF $(DEPDIR)/tnccs.Tpo -c -o tnccs.lo `test -f 'tnc/tnccs/tnccs.c' || echo '$(srcdir)/'`tnc/tnccs/tnccs.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/tnccs.Tpo $(DEPDIR)/tnccs.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tnccs/tnccs.c' object='tnccs.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tnc/tnccs/tnccs.c' object='tnccs.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tnccs.lo `test -f 'tnccs/tnccs.c' || echo '$(srcdir)/'`tnccs/tnccs.c +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tnccs.lo `test -f 'tnc/tnccs/tnccs.c' || echo '$(srcdir)/'`tnc/tnccs/tnccs.c -tnccs_manager.lo: tnccs/tnccs_manager.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tnccs_manager.lo -MD -MP -MF $(DEPDIR)/tnccs_manager.Tpo -c -o tnccs_manager.lo `test -f 'tnccs/tnccs_manager.c' || echo '$(srcdir)/'`tnccs/tnccs_manager.c +tnccs_manager.lo: tnc/tnccs/tnccs_manager.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tnccs_manager.lo -MD -MP -MF $(DEPDIR)/tnccs_manager.Tpo -c -o tnccs_manager.lo `test -f 'tnc/tnccs/tnccs_manager.c' || echo '$(srcdir)/'`tnc/tnccs/tnccs_manager.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/tnccs_manager.Tpo $(DEPDIR)/tnccs_manager.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tnccs/tnccs_manager.c' object='tnccs_manager.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tnc/tnccs/tnccs_manager.c' object='tnccs_manager.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tnccs_manager.lo `test -f 'tnccs/tnccs_manager.c' || echo '$(srcdir)/'`tnccs/tnccs_manager.c +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tnccs_manager.lo `test -f 'tnc/tnccs/tnccs_manager.c' || echo '$(srcdir)/'`tnc/tnccs/tnccs_manager.c endpoint_notify.lo: encoding/payloads/endpoint_notify.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT endpoint_notify.lo -MD -MP -MF $(DEPDIR)/endpoint_notify.Tpo -c -o endpoint_notify.lo `test -f 'encoding/payloads/endpoint_notify.c' || echo '$(srcdir)/'`encoding/payloads/endpoint_notify.c diff --git a/src/libcharon/bus/bus.c b/src/libcharon/bus/bus.c index ab8d0fc48..23931c47d 100644 --- a/src/libcharon/bus/bus.c +++ b/src/libcharon/bus/bus.c @@ -227,13 +227,13 @@ static bool log_cb(entry_t *entry, log_data_t *data) { entry->blocker = FALSE; entry->condvar->signal(entry->condvar); + entry->calling--; } else { entry_destroy(entry); } va_end(args); - entry->calling--; return TRUE; } va_end(args); diff --git a/src/libcharon/config/backend_manager.c b/src/libcharon/config/backend_manager.c index 90ef58563..e78cb702d 100644 --- a/src/libcharon/config/backend_manager.c +++ b/src/libcharon/config/backend_manager.c @@ -96,6 +96,11 @@ static ike_cfg_match_t get_ike_match(ike_cfg_t *cand, host_t *me, host_t *other) { match += MATCH_ANY; } + else + { + me_cand->destroy(me_cand); + return MATCH_NONE; + } me_cand->destroy(me_cand); } else @@ -119,6 +124,11 @@ static ike_cfg_match_t get_ike_match(ike_cfg_t *cand, host_t *me, host_t *other) { match += MATCH_ANY; } + else + { + other_cand->destroy(other_cand); + return MATCH_NONE; + } other_cand->destroy(other_cand); } else @@ -128,11 +138,8 @@ static ike_cfg_match_t get_ike_match(ike_cfg_t *cand, host_t *me, host_t *other) return match; } -/** - * implements backend_manager_t.get_ike_cfg. - */ -static ike_cfg_t *get_ike_cfg(private_backend_manager_t *this, - host_t *me, host_t *other) +METHOD(backend_manager_t, get_ike_cfg, ike_cfg_t*, + private_backend_manager_t *this, host_t *me, host_t *other) { ike_cfg_t *current, *found = NULL; enumerator_t *enumerator; @@ -308,12 +315,9 @@ static void insert_sorted(match_entry_t *entry, linked_list_t *list, } } -/** - * Implements backend_manager_t.create_peer_cfg_enumerator. - */ -static enumerator_t *create_peer_cfg_enumerator(private_backend_manager_t *this, - host_t *me, host_t *other, identification_t *my_id, - identification_t *other_id) +METHOD(backend_manager_t, create_peer_cfg_enumerator, enumerator_t*, + private_backend_manager_t *this, host_t *me, host_t *other, + identification_t *my_id, identification_t *other_id) { enumerator_t *enumerator; peer_data_t *data; @@ -372,10 +376,8 @@ static enumerator_t *create_peer_cfg_enumerator(private_backend_manager_t *this, (void*)peer_enum_filter_destroy); } -/** - * implements backend_manager_t.get_peer_cfg_by_name. - */ -static peer_cfg_t *get_peer_cfg_by_name(private_backend_manager_t *this, char *name) +METHOD(backend_manager_t, get_peer_cfg_by_name, peer_cfg_t*, + private_backend_manager_t *this, char *name) { backend_t *backend; peer_cfg_t *config = NULL; @@ -392,30 +394,24 @@ static peer_cfg_t *get_peer_cfg_by_name(private_backend_manager_t *this, char *n return config; } -/** - * Implementation of backend_manager_t.remove_backend. - */ -static void remove_backend(private_backend_manager_t *this, backend_t *backend) +METHOD(backend_manager_t, remove_backend, void, + private_backend_manager_t *this, backend_t *backend) { this->lock->write_lock(this->lock); this->backends->remove(this->backends, backend, NULL); this->lock->unlock(this->lock); } -/** - * Implementation of backend_manager_t.add_backend. - */ -static void add_backend(private_backend_manager_t *this, backend_t *backend) +METHOD(backend_manager_t, add_backend, void, + private_backend_manager_t *this, backend_t *backend) { this->lock->write_lock(this->lock); this->backends->insert_last(this->backends, backend); this->lock->unlock(this->lock); } -/** - * Implementation of backend_manager_t.destroy. - */ -static void destroy(private_backend_manager_t *this) +METHOD(backend_manager_t, destroy, void, + private_backend_manager_t *this) { this->backends->destroy(this->backends); this->lock->destroy(this->lock); @@ -424,20 +420,24 @@ static void destroy(private_backend_manager_t *this) /* * Described in header-file + */ backend_manager_t *backend_manager_create() { - private_backend_manager_t *this = malloc_thing(private_backend_manager_t); - - this->public.get_ike_cfg = (ike_cfg_t* (*)(backend_manager_t*, host_t*, host_t*))get_ike_cfg; - this->public.get_peer_cfg_by_name = (peer_cfg_t* (*)(backend_manager_t*,char*))get_peer_cfg_by_name; - this->public.create_peer_cfg_enumerator = (enumerator_t* (*)(backend_manager_t*,host_t*,host_t*,identification_t*,identification_t*))create_peer_cfg_enumerator; - this->public.add_backend = (void(*)(backend_manager_t*, backend_t *backend))add_backend; - this->public.remove_backend = (void(*)(backend_manager_t*, backend_t *backend))remove_backend; - this->public.destroy = (void (*)(backend_manager_t*))destroy; + private_backend_manager_t *this; - this->backends = linked_list_create(); - this->lock = rwlock_create(RWLOCK_TYPE_DEFAULT); + INIT(this, + .public = { + .get_ike_cfg = _get_ike_cfg, + .get_peer_cfg_by_name = _get_peer_cfg_by_name, + .create_peer_cfg_enumerator = _create_peer_cfg_enumerator, + .add_backend = _add_backend, + .remove_backend = _remove_backend, + .destroy = _destroy, + }, + .backends = linked_list_create(), + .lock = rwlock_create(RWLOCK_TYPE_DEFAULT), + ); return &this->public; } diff --git a/src/libcharon/config/child_cfg.c b/src/libcharon/config/child_cfg.c index 1cdfd5949..74949be3c 100644 --- a/src/libcharon/config/child_cfg.c +++ b/src/libcharon/config/child_cfg.c @@ -80,6 +80,11 @@ struct private_child_cfg_t { ipsec_mode_t mode; /** + * action to take to start CHILD_SA + */ + action_t start_action; + + /** * action to take on DPD */ action_t dpd_action; @@ -118,6 +123,12 @@ struct private_child_cfg_t { * Optional mark to install outbound CHILD_SA with */ mark_t mark_out; + + /** + * Traffic Flow Confidentiality padding, if enabled + */ + u_int32_t tfc; + /** * set up IPsec transport SA in MIPv6 proxy mode */ @@ -129,26 +140,20 @@ struct private_child_cfg_t { bool install_policy; }; -/** - * Implementation of child_cfg_t.get_name. - */ -static char *get_name(private_child_cfg_t *this) +METHOD(child_cfg_t, get_name, char*, + private_child_cfg_t *this) { return this->name; } -/** - * Implementation of child_cfg_t.add_proposal. - */ -static void add_proposal(private_child_cfg_t *this, proposal_t *proposal) +METHOD(child_cfg_t, add_proposal, void, + private_child_cfg_t *this, proposal_t *proposal) { this->proposals->insert_last(this->proposals, proposal); } -/** - * Implementation of child_cfg_t.get_proposals. - */ -static linked_list_t* get_proposals(private_child_cfg_t *this, bool strip_dh) +METHOD(child_cfg_t, get_proposals, linked_list_t*, + private_child_cfg_t *this, bool strip_dh) { enumerator_t *enumerator; proposal_t *current; @@ -169,12 +174,9 @@ static linked_list_t* get_proposals(private_child_cfg_t *this, bool strip_dh) return proposals; } -/** - * Implementation of child_cfg_t.select_proposal. - */ -static proposal_t* select_proposal(private_child_cfg_t*this, - linked_list_t *proposals, bool strip_dh, - bool private) +METHOD(child_cfg_t, select_proposal, proposal_t*, + private_child_cfg_t*this, linked_list_t *proposals, bool strip_dh, + bool private) { enumerator_t *stored_enum, *supplied_enum; proposal_t *stored, *supplied, *selected = NULL; @@ -219,11 +221,8 @@ static proposal_t* select_proposal(private_child_cfg_t*this, return selected; } -/** - * Implementation of child_cfg_t.add_traffic_selector. - */ -static void add_traffic_selector(private_child_cfg_t *this, bool local, - traffic_selector_t *ts) +METHOD(child_cfg_t, add_traffic_selector, void, + private_child_cfg_t *this, bool local, traffic_selector_t *ts) { if (local) { @@ -235,12 +234,8 @@ static void add_traffic_selector(private_child_cfg_t *this, bool local, } } -/** - * Implementation of child_cfg_t.get_traffic_selectors. - */ -static linked_list_t* get_traffic_selectors(private_child_cfg_t *this, bool local, - linked_list_t *supplied, - host_t *host) +METHOD(child_cfg_t, get_traffic_selectors, linked_list_t*, + private_child_cfg_t *this, bool local, linked_list_t *supplied, host_t *host) { enumerator_t *e1, *e2; traffic_selector_t *ts1, *ts2, *selected; @@ -346,18 +341,14 @@ static linked_list_t* get_traffic_selectors(private_child_cfg_t *this, bool loca return result; } -/** - * Implementation of child_cfg_t.get_updown. - */ -static char* get_updown(private_child_cfg_t *this) +METHOD(child_cfg_t, get_updown, char*, + private_child_cfg_t *this) { return this->updown; } -/** - * Implementation of child_cfg_t.get_hostaccess. - */ -static bool get_hostaccess(private_child_cfg_t *this) +METHOD(child_cfg_t, get_hostaccess, bool, + private_child_cfg_t *this) { return this->hostaccess; } @@ -378,10 +369,8 @@ static u_int64_t apply_jitter(u_int64_t rekey, u_int64_t jitter) } #define APPLY_JITTER(l) l.rekey = apply_jitter(l.rekey, l.jitter) -/** - * Implementation of child_cfg_t.get_lifetime. - */ -static lifetime_cfg_t *get_lifetime(private_child_cfg_t *this) +METHOD(child_cfg_t, get_lifetime, lifetime_cfg_t*, + private_child_cfg_t *this) { lifetime_cfg_t *lft = malloc_thing(lifetime_cfg_t); memcpy(lft, &this->lifetime, sizeof(lifetime_cfg_t)); @@ -391,34 +380,32 @@ static lifetime_cfg_t *get_lifetime(private_child_cfg_t *this) return lft; } -/** - * Implementation of child_cfg_t.get_mode. - */ -static ipsec_mode_t get_mode(private_child_cfg_t *this) +METHOD(child_cfg_t, get_mode, ipsec_mode_t, + private_child_cfg_t *this) { return this->mode; } -/** - * Implementation of child_cfg_t.get_dpd_action. - */ -static action_t get_dpd_action(private_child_cfg_t *this) +METHOD(child_cfg_t, get_start_action, action_t, + private_child_cfg_t *this) +{ + return this->start_action; +} + +METHOD(child_cfg_t, get_dpd_action, action_t, + private_child_cfg_t *this) { return this->dpd_action; } -/** - * Implementation of child_cfg_t.get_close_action. - */ -static action_t get_close_action(private_child_cfg_t *this) +METHOD(child_cfg_t, get_close_action, action_t, + private_child_cfg_t *this) { return this->close_action; } -/** - * Implementation of child_cfg_t.get_dh_group. - */ -static diffie_hellman_group_t get_dh_group(private_child_cfg_t *this) +METHOD(child_cfg_t, get_dh_group, diffie_hellman_group_t, + private_child_cfg_t *this) { enumerator_t *enumerator; proposal_t *proposal; @@ -436,77 +423,64 @@ static diffie_hellman_group_t get_dh_group(private_child_cfg_t *this) return dh_group; } -/** - * Implementation of child_cfg_t.use_ipcomp. - */ -static bool use_ipcomp(private_child_cfg_t *this) +METHOD(child_cfg_t, use_ipcomp, bool, + private_child_cfg_t *this) { return this->use_ipcomp; } -/** - * Implementation of child_cfg_t.get_inactivity. - */ -static u_int32_t get_inactivity(private_child_cfg_t *this) +METHOD(child_cfg_t, get_inactivity, u_int32_t, + private_child_cfg_t *this) { return this->inactivity; } -/** - * Implementation of child_cfg_t.get_reqid. - */ -static u_int32_t get_reqid(private_child_cfg_t *this) +METHOD(child_cfg_t, get_reqid, u_int32_t, + private_child_cfg_t *this) { return this->reqid; } -/** - * Implementation of child_cfg_t.get_mark. - */ -static mark_t get_mark(private_child_cfg_t *this, bool inbound) +METHOD(child_cfg_t, get_mark, mark_t, + private_child_cfg_t *this, bool inbound) { return inbound ? this->mark_in : this->mark_out; } -/** - * Implementation of child_cfg_t.set_mipv6_options. - */ -static void set_mipv6_options(private_child_cfg_t *this, bool proxy_mode, - bool install_policy) +METHOD(child_cfg_t, get_tfc, u_int32_t, + private_child_cfg_t *this) +{ + return this->tfc; +} + +METHOD(child_cfg_t, set_mipv6_options, void, + private_child_cfg_t *this, bool proxy_mode, bool install_policy) { this->proxy_mode = proxy_mode; this->install_policy = install_policy; } -/** - * Implementation of child_cfg_t.use_proxy_mode. - */ -static bool use_proxy_mode(private_child_cfg_t *this) +METHOD(child_cfg_t, use_proxy_mode, bool, + private_child_cfg_t *this) { return this->proxy_mode; } -/** - * Implementation of child_cfg_t.install_policy. - */ -static bool install_policy(private_child_cfg_t *this) +METHOD(child_cfg_t, install_policy, bool, + private_child_cfg_t *this) { return this->install_policy; } -/** - * Implementation of child_cfg_t.get_ref. - */ -static child_cfg_t* get_ref(private_child_cfg_t *this) +METHOD(child_cfg_t, get_ref, child_cfg_t*, + private_child_cfg_t *this) { ref_get(&this->refcount); return &this->public; } -/** - * Implements child_cfg_t.destroy. - */ -static void destroy(private_child_cfg_t *this) +METHOD(child_cfg_t, destroy, void, + private_child_cfg_t *this) { if (ref_put(&this->refcount)) { @@ -527,71 +501,67 @@ static void destroy(private_child_cfg_t *this) */ child_cfg_t *child_cfg_create(char *name, lifetime_cfg_t *lifetime, char *updown, bool hostaccess, - ipsec_mode_t mode, action_t dpd_action, - action_t close_action, bool ipcomp, - u_int32_t inactivity, u_int32_t reqid, - mark_t *mark_in, mark_t *mark_out) + ipsec_mode_t mode, action_t start_action, + action_t dpd_action, action_t close_action, + bool ipcomp, u_int32_t inactivity, u_int32_t reqid, + mark_t *mark_in, mark_t *mark_out, u_int32_t tfc) { - private_child_cfg_t *this = malloc_thing(private_child_cfg_t); - - this->public.get_name = (char* (*) (child_cfg_t*))get_name; - this->public.add_traffic_selector = (void (*)(child_cfg_t*,bool,traffic_selector_t*))add_traffic_selector; - this->public.get_traffic_selectors = (linked_list_t*(*)(child_cfg_t*,bool,linked_list_t*,host_t*))get_traffic_selectors; - this->public.add_proposal = (void (*) (child_cfg_t*,proposal_t*))add_proposal; - this->public.get_proposals = (linked_list_t* (*) (child_cfg_t*,bool))get_proposals; - this->public.select_proposal = (proposal_t* (*) (child_cfg_t*,linked_list_t*,bool,bool))select_proposal; - this->public.get_updown = (char* (*) (child_cfg_t*))get_updown; - this->public.get_hostaccess = (bool (*) (child_cfg_t*))get_hostaccess; - this->public.get_mode = (ipsec_mode_t (*) (child_cfg_t *))get_mode; - this->public.get_dpd_action = (action_t (*) (child_cfg_t *))get_dpd_action; - this->public.get_close_action = (action_t (*) (child_cfg_t *))get_close_action; - this->public.get_lifetime = (lifetime_cfg_t* (*) (child_cfg_t *))get_lifetime; - this->public.get_dh_group = (diffie_hellman_group_t(*)(child_cfg_t*)) get_dh_group; - this->public.set_mipv6_options = (void (*) (child_cfg_t*,bool,bool))set_mipv6_options; - this->public.use_ipcomp = (bool (*) (child_cfg_t *))use_ipcomp; - this->public.get_inactivity = (u_int32_t (*) (child_cfg_t *))get_inactivity; - this->public.get_reqid = (u_int32_t (*) (child_cfg_t *))get_reqid; - this->public.get_mark = (mark_t (*) (child_cfg_t *,bool))get_mark; - this->public.use_proxy_mode = (bool (*) (child_cfg_t *))use_proxy_mode; - this->public.install_policy = (bool (*) (child_cfg_t *))install_policy; - this->public.get_ref = (child_cfg_t* (*) (child_cfg_t*))get_ref; - this->public.destroy = (void (*) (child_cfg_t*))destroy; - - this->name = strdup(name); - this->updown = updown ? strdup(updown) : NULL; - this->hostaccess = hostaccess; - this->mode = mode; - this->dpd_action = dpd_action; - this->close_action = close_action; - this->use_ipcomp = ipcomp; - this->inactivity = inactivity; - this->reqid = reqid; + private_child_cfg_t *this; + + INIT(this, + .public = { + .get_name = _get_name, + .add_traffic_selector = _add_traffic_selector, + .get_traffic_selectors = _get_traffic_selectors, + .add_proposal = _add_proposal, + .get_proposals = _get_proposals, + .select_proposal = _select_proposal, + .get_updown = _get_updown, + .get_hostaccess = _get_hostaccess, + .get_mode = _get_mode, + .get_start_action = _get_start_action, + .get_dpd_action = _get_dpd_action, + .get_close_action = _get_close_action, + .get_lifetime = _get_lifetime, + .get_dh_group = _get_dh_group, + .set_mipv6_options = _set_mipv6_options, + .use_ipcomp = _use_ipcomp, + .get_inactivity = _get_inactivity, + .get_reqid = _get_reqid, + .get_mark = _get_mark, + .get_tfc = _get_tfc, + .use_proxy_mode = _use_proxy_mode, + .install_policy = _install_policy, + .get_ref = _get_ref, + .destroy = _destroy, + }, + .name = strdup(name), + .updown = strdupnull(updown), + .hostaccess = hostaccess, + .mode = mode, + .start_action = start_action, + .dpd_action = dpd_action, + .close_action = close_action, + .use_ipcomp = ipcomp, + .inactivity = inactivity, + .reqid = reqid, + .proxy_mode = FALSE, + .install_policy = TRUE, + .refcount = 1, + .proposals = linked_list_create(), + .my_ts = linked_list_create(), + .other_ts = linked_list_create(), + .tfc = tfc, + ); if (mark_in) { this->mark_in = *mark_in; } - else - { - this->mark_in.value = 0; - this->mark_in.mask = 0; - } if (mark_out) { this->mark_out = *mark_out; } - else - { - this->mark_out.value = 0; - this->mark_out.mask = 0; - } - - this->proxy_mode = FALSE; - this->install_policy = TRUE; - this->refcount = 1; - this->proposals = linked_list_create(); - this->my_ts = linked_list_create(); - this->other_ts = linked_list_create(); memcpy(&this->lifetime, lifetime, sizeof(lifetime_cfg_t)); return &this->public; diff --git a/src/libcharon/config/child_cfg.h b/src/libcharon/config/child_cfg.h index 1e6fe3fe9..175ced76c 100644 --- a/src/libcharon/config/child_cfg.h +++ b/src/libcharon/config/child_cfg.h @@ -32,14 +32,15 @@ typedef struct child_cfg_t child_cfg_t; #include <kernel/kernel_ipsec.h> /** - * Action to take when DPD detected/connection gets closed by peer. + * Action to take when connection is loaded, DPD is detected or + * connection gets closed by peer. */ enum action_t { /** No action */ ACTION_NONE, - /** Route config to reestablish on demand */ + /** Route config to establish or reestablish on demand */ ACTION_ROUTE, - /** Restart config immediately */ + /** Start or restart config immediately */ ACTION_RESTART, }; @@ -169,6 +170,13 @@ struct child_cfg_t { ipsec_mode_t (*get_mode) (child_cfg_t *this); /** + * Action to take to start CHILD_SA. + * + * @return start action + */ + action_t (*get_start_action) (child_cfg_t *this); + + /** * Action to take on DPD. * * @return DPD action @@ -220,6 +228,13 @@ struct child_cfg_t { mark_t (*get_mark)(child_cfg_t *this, bool inbound); /** + * Get the TFC padding value to use for CHILD_SA. + * + * @return TFC padding, 0 to disable, -1 for MTU + */ + u_int32_t (*get_tfc)(child_cfg_t *this); + + /** * Sets two options needed for Mobile IPv6 interoperability * * @param proxy_mode use IPsec transport proxy mode (default FALSE) @@ -276,6 +291,7 @@ struct child_cfg_t { * @param updown updown script to execute on up/down event * @param hostaccess TRUE to allow access to the local host * @param mode mode to propose for CHILD_SA, transport, tunnel or BEET + * @param start_action start action * @param dpd_action DPD action * @param close_action close action * @param ipcomp use IPComp, if peer supports it @@ -283,13 +299,14 @@ struct child_cfg_t { * @param reqid specific reqid to use for CHILD_SA, 0 for auto assign * @param mark_in optional inbound mark (can be NULL) * @param mark_out optional outbound mark (can be NULL) + * @param tfc TFC padding size, 0 to disable, -1 to pad to PMTU * @return child_cfg_t object */ child_cfg_t *child_cfg_create(char *name, lifetime_cfg_t *lifetime, char *updown, bool hostaccess, - ipsec_mode_t mode, action_t dpd_action, - action_t close_action, bool ipcomp, - u_int32_t inactivity, u_int32_t reqid, - mark_t *mark_in, mark_t *mark_out); + ipsec_mode_t mode, action_t start_action, + action_t dpd_action, action_t close_action, + bool ipcomp, u_int32_t inactivity, u_int32_t reqid, + mark_t *mark_in, mark_t *mark_out, u_int32_t tfc); #endif /** CHILD_CFG_H_ @}*/ diff --git a/src/libcharon/config/peer_cfg.c b/src/libcharon/config/peer_cfg.c index 9df14c9ae..6f0c87279 100644 --- a/src/libcharon/config/peer_cfg.c +++ b/src/libcharon/config/peer_cfg.c @@ -682,7 +682,7 @@ peer_cfg_t *peer_cfg_create(char *name, u_int ike_version, ike_cfg_t *ike_cfg, this->use_mobike = mobike; this->dpd = dpd; this->virtual_ip = virtual_ip; - this->pool = pool ? strdup(pool) : NULL; + this->pool = strdupnull(pool); this->local_auth = linked_list_create(); this->remote_auth = linked_list_create(); this->refcount = 1; diff --git a/src/libcharon/config/proposal.c b/src/libcharon/config/proposal.c index 5b8294599..86a59bc1b 100644 --- a/src/libcharon/config/proposal.c +++ b/src/libcharon/config/proposal.c @@ -560,6 +560,7 @@ static status_t add_string_algo(private_proposal_t *this, chunk_t alg) if (token == NULL) { + DBG1(DBG_CFG, "algorithm '%.*s' not recognized", alg.len, alg.ptr); return FAILED; } @@ -740,9 +741,10 @@ static void proposal_add_supported_ike(private_proposal_t *this) integrity_algorithm_t integrity; pseudo_random_function_t prf; diffie_hellman_group_t group; + const char *plugin_name; enumerator = lib->crypto->create_crypter_enumerator(lib->crypto); - while (enumerator->enumerate(enumerator, &encryption)) + while (enumerator->enumerate(enumerator, &encryption, &plugin_name)) { switch (encryption) { @@ -777,7 +779,7 @@ static void proposal_add_supported_ike(private_proposal_t *this) enumerator->destroy(enumerator); enumerator = lib->crypto->create_signer_enumerator(lib->crypto); - while (enumerator->enumerate(enumerator, &integrity)) + while (enumerator->enumerate(enumerator, &integrity, &plugin_name)) { switch (integrity) { @@ -796,7 +798,7 @@ static void proposal_add_supported_ike(private_proposal_t *this) enumerator->destroy(enumerator); enumerator = lib->crypto->create_prf_enumerator(lib->crypto); - while (enumerator->enumerate(enumerator, &prf)) + while (enumerator->enumerate(enumerator, &prf, &plugin_name)) { switch (prf) { @@ -815,7 +817,7 @@ static void proposal_add_supported_ike(private_proposal_t *this) enumerator->destroy(enumerator); enumerator = lib->crypto->create_dh_enumerator(lib->crypto); - while (enumerator->enumerate(enumerator, &group)) + while (enumerator->enumerate(enumerator, &group, &plugin_name)) { switch (group) { diff --git a/src/libcharon/daemon.c b/src/libcharon/daemon.c index 4b8e1fadd..4f2831e42 100644 --- a/src/libcharon/daemon.c +++ b/src/libcharon/daemon.c @@ -19,14 +19,14 @@ #include <stdio.h> #include <sys/types.h> #include <unistd.h> -#include <syslog.h> #include <time.h> -#include <errno.h> #ifdef CAPABILITIES -#ifdef HAVE_SYS_CAPABILITY_H -#include <sys/capability.h> -#endif /* HAVE_SYS_CAPABILITY_H */ +# ifdef HAVE_SYS_CAPABILITY_H +# include <sys/capability.h> +# elif defined(CAPABILITIES_NATIVE) +# include <linux/capability.h> +# endif /* CAPABILITIES_NATIVE */ #endif /* CAPABILITIES */ #include "daemon.h" @@ -34,10 +34,7 @@ #include <library.h> #include <config/proposal.h> #include <kernel/kernel_handler.h> - -#ifndef LOG_AUTHPRIV /* not defined on OpenSolaris */ -#define LOG_AUTHPRIV LOG_AUTH -#endif +#include <processing/jobs/start_action_job.h> typedef struct private_daemon_t private_daemon_t; @@ -62,7 +59,7 @@ struct private_daemon_t { cap_t caps; #endif /* CAPABILITIES_LIBCAP */ #ifdef CAPABILITIES_NATIVE - struct __user_cap_data_struct caps; + struct __user_cap_data_struct caps[2]; #endif /* CAPABILITIES_NATIVE */ }; @@ -147,9 +144,16 @@ METHOD(daemon_t, keep_cap, void, cap_set_flag(this->caps, CAP_PERMITTED, 1, &cap, CAP_SET); #endif /* CAPABILITIES_LIBCAP */ #ifdef CAPABILITIES_NATIVE - this->caps.effective |= 1 << cap; - this->caps.permitted |= 1 << cap; - this->caps.inheritable |= 1 << cap; + int i = 0; + + if (cap >= 32) + { + i++; + cap -= 32; + } + this->caps[i].effective |= 1 << cap; + this->caps[i].permitted |= 1 << cap; + this->caps[i].inheritable |= 1 << cap; #endif /* CAPABILITIES_NATIVE */ } @@ -164,9 +168,15 @@ METHOD(daemon_t, drop_capabilities, bool, #endif /* CAPABILITIES_LIBCAP */ #ifdef CAPABILITIES_NATIVE struct __user_cap_header_struct header = { - .version = _LINUX_CAPABILITY_VERSION, +#if defined(_LINUX_CAPABILITY_VERSION_3) + .version = _LINUX_CAPABILITY_VERSION_3, +#elif defined(_LINUX_CAPABILITY_VERSION_2) + .version = _LINUX_CAPABILITY_VERSION_2, +#else + .version = _LINUX_CAPABILITY_VERSION_1, +#endif }; - if (capset(&header, &this->caps) != 0) + if (capset(&header, this->caps) != 0) { return FALSE; } @@ -202,155 +212,9 @@ static void print_plugins() DBG1(DBG_DMN, "loaded plugins: %s", buf); } -/** - * Initialize logging - */ -static void initialize_loggers(private_daemon_t *this, bool use_stderr, - level_t levels[]) -{ - sys_logger_t *sys_logger; - file_logger_t *file_logger; - enumerator_t *enumerator; - char *facility, *filename; - int loggers_defined = 0; - debug_t group; - level_t def; - bool append, ike_name; - FILE *file; - - /* setup sysloggers */ - enumerator = lib->settings->create_section_enumerator(lib->settings, - "charon.syslog"); - while (enumerator->enumerate(enumerator, &facility)) - { - loggers_defined++; - - ike_name = lib->settings->get_bool(lib->settings, - "charon.syslog.%s.ike_name", FALSE, facility); - if (streq(facility, "daemon")) - { - sys_logger = sys_logger_create(LOG_DAEMON, ike_name); - } - else if (streq(facility, "auth")) - { - sys_logger = sys_logger_create(LOG_AUTHPRIV, ike_name); - } - else - { - continue; - } - def = lib->settings->get_int(lib->settings, - "charon.syslog.%s.default", 1, facility); - for (group = 0; group < DBG_MAX; group++) - { - sys_logger->set_level(sys_logger, group, - lib->settings->get_int(lib->settings, - "charon.syslog.%s.%N", def, - facility, debug_lower_names, group)); - } - this->public.sys_loggers->insert_last(this->public.sys_loggers, - sys_logger); - this->public.bus->add_listener(this->public.bus, &sys_logger->listener); - } - enumerator->destroy(enumerator); - - /* and file loggers */ - enumerator = lib->settings->create_section_enumerator(lib->settings, - "charon.filelog"); - while (enumerator->enumerate(enumerator, &filename)) - { - loggers_defined++; - if (streq(filename, "stderr")) - { - file = stderr; - } - else if (streq(filename, "stdout")) - { - file = stdout; - } - else - { - append = lib->settings->get_bool(lib->settings, - "charon.filelog.%s.append", TRUE, filename); - file = fopen(filename, append ? "a" : "w"); - if (file == NULL) - { - DBG1(DBG_DMN, "opening file %s for logging failed: %s", - filename, strerror(errno)); - continue; - } - if (lib->settings->get_bool(lib->settings, - "charon.filelog.%s.flush_line", FALSE, filename)) - { - setlinebuf(file); - } - } - file_logger = file_logger_create(file, - lib->settings->get_str(lib->settings, - "charon.filelog.%s.time_format", NULL, filename), - lib->settings->get_bool(lib->settings, - "charon.filelog.%s.ike_name", FALSE, filename)); - def = lib->settings->get_int(lib->settings, - "charon.filelog.%s.default", 1, filename); - for (group = 0; group < DBG_MAX; group++) - { - file_logger->set_level(file_logger, group, - lib->settings->get_int(lib->settings, - "charon.filelog.%s.%N", def, - filename, debug_lower_names, group)); - } - this->public.file_loggers->insert_last(this->public.file_loggers, - file_logger); - this->public.bus->add_listener(this->public.bus, &file_logger->listener); - - } - enumerator->destroy(enumerator); - - /* set up legacy style default loggers provided via command-line */ - if (!loggers_defined) - { - /* set up default stdout file_logger */ - file_logger = file_logger_create(stdout, NULL, FALSE); - this->public.bus->add_listener(this->public.bus, &file_logger->listener); - this->public.file_loggers->insert_last(this->public.file_loggers, - file_logger); - /* set up default daemon sys_logger */ - sys_logger = sys_logger_create(LOG_DAEMON, FALSE); - this->public.bus->add_listener(this->public.bus, &sys_logger->listener); - this->public.sys_loggers->insert_last(this->public.sys_loggers, - sys_logger); - for (group = 0; group < DBG_MAX; group++) - { - sys_logger->set_level(sys_logger, group, levels[group]); - if (use_stderr) - { - file_logger->set_level(file_logger, group, levels[group]); - } - } - - /* set up default auth sys_logger */ - sys_logger = sys_logger_create(LOG_AUTHPRIV, FALSE); - this->public.bus->add_listener(this->public.bus, &sys_logger->listener); - this->public.sys_loggers->insert_last(this->public.sys_loggers, - sys_logger); - sys_logger->set_level(sys_logger, DBG_ANY, LEVEL_AUDIT); - } -} - METHOD(daemon_t, initialize, bool, - private_daemon_t *this, bool syslog, level_t levels[]) + private_daemon_t *this) { - /* for uncritical pseudo random numbers */ - srandom(time(NULL) + getpid()); - - /* setup bus and it's listeners first to enable log output */ - this->public.bus = bus_create(); - /* set up hook to log dbg message in library via charons message bus */ - dbg_old = dbg; - dbg = dbg_bus; - - initialize_loggers(this, !syslog, levels); - DBG1(DBG_DMN, "Starting IKEv2 charon daemon (strongSwan "VERSION")"); if (lib->integrity) @@ -362,16 +226,6 @@ METHOD(daemon_t, initialize, bool, DBG1(DBG_DMN, "daemon 'charon': passed file integrity test"); } - /* load secrets, ca certificates and crls */ - this->public.controller = controller_create(); - this->public.eap = eap_manager_create(); - this->public.sim = sim_manager_create(); - this->public.tnccs = tnccs_manager_create(); - this->public.backends = backend_manager_create(); - this->public.socket = socket_manager_create(); - this->public.traps = trap_manager_create(); - this->kernel_handler = kernel_handler_create(); - /* load plugins, further infrastructure may need it */ if (!lib->plugins->load(lib->plugins, NULL, lib->settings->get_str(lib->settings, "charon.load", PLUGINS))) @@ -393,6 +247,9 @@ METHOD(daemon_t, initialize, bool, return FALSE; } + /* Queue start_action job */ + lib->processor->queue_job(lib->processor, (job_t*)start_action_job_create()); + #ifdef ME this->public.connect_manager = connect_manager_create(); if (this->public.connect_manager == NULL) @@ -418,10 +275,20 @@ private_daemon_t *daemon_create() .drop_capabilities = _drop_capabilities, .initialize = _initialize, .start = _start, + .bus = bus_create(), .file_loggers = linked_list_create(), .sys_loggers = linked_list_create(), }, ); + charon = &this->public; + this->public.controller = controller_create(); + this->public.eap = eap_manager_create(); + this->public.sim = sim_manager_create(); + this->public.tnccs = tnccs_manager_create(); + this->public.backends = backend_manager_create(); + this->public.socket = socket_manager_create(); + this->public.traps = trap_manager_create(); + this->kernel_handler = kernel_handler_create(); #ifdef CAPABILITIES #ifdef CAPABILITIES_LIBCAP @@ -442,7 +309,6 @@ private_daemon_t *daemon_create() */ void libcharon_deinit() { - destroy((private_daemon_t*)charon); charon = NULL; } @@ -455,7 +321,13 @@ bool libcharon_init() private_daemon_t *this; this = daemon_create(); - charon = &this->public; + + /* for uncritical pseudo random numbers */ + srandom(time(NULL) + getpid()); + + /* set up hook to log dbg message in library via charons message bus */ + dbg_old = dbg; + dbg = dbg_bus; lib->printf_hook->add_handler(lib->printf_hook, 'P', proposal_printf_hook, diff --git a/src/libcharon/daemon.h b/src/libcharon/daemon.h index c0c834b43..04f1fc249 100644 --- a/src/libcharon/daemon.h +++ b/src/libcharon/daemon.h @@ -149,7 +149,9 @@ typedef struct daemon_t daemon_t; #include <config/backend_manager.h> #include <sa/authenticators/eap/eap_manager.h> #include <sa/authenticators/eap/sim_manager.h> -#include <tnccs/tnccs_manager.h> +#include <tnc/imc/imc_manager.h> +#include <tnc/imv/imv_manager.h> +#include <tnc/tnccs/tnccs_manager.h> #ifdef ME #include <sa/connect_manager.h> @@ -237,6 +239,16 @@ struct daemon_t { sim_manager_t *sim; /** + * TNC IMC manager controlling Integrity Measurement Collectors + */ + imc_manager_t *imcs; + + /** + * TNC IMV manager controlling Integrity Measurement Verifiers + */ + imv_manager_t *imvs; + + /** * TNCCS manager to maintain registered TNCCS protocols */ tnccs_manager_t *tnccs; @@ -286,7 +298,7 @@ struct daemon_t { /** * Initialize the daemon. */ - bool (*initialize)(daemon_t *this, bool syslog, level_t levels[]); + bool (*initialize)(daemon_t *this); /** * Starts the daemon, i.e. spawns the threads of the thread pool. @@ -305,6 +317,9 @@ extern daemon_t *charon; /** * Initialize libcharon and create the "charon" instance of daemon_t. * + * This function initializes the bus, listeners can be registered before + * calling initialize(). + * * @return FALSE if integrity check failed */ bool libcharon_init(); diff --git a/src/libcharon/encoding/generator.c b/src/libcharon/encoding/generator.c index 224f76fce..ce3844361 100644 --- a/src/libcharon/encoding/generator.c +++ b/src/libcharon/encoding/generator.c @@ -41,6 +41,7 @@ #include <encoding/payloads/cp_payload.h> #include <encoding/payloads/configuration_attribute.h> #include <encoding/payloads/eap_payload.h> +#include <encoding/payloads/unknown_payload.h> /** * Generating is done in a data buffer. @@ -89,20 +90,10 @@ struct private_generator_t { */ void *data_struct; - /* - * Last payload length position offset in the buffer. - */ - u_int32_t last_payload_length_position_offset; - /** * Offset of the header length field in the buffer. */ - u_int32_t header_length_position_offset; - - /** - * Last SPI size. - */ - u_int8_t last_spi_size; + u_int32_t header_length_offset; /** * Attribute format of the last generated transform attribute. @@ -193,33 +184,6 @@ static void write_bytes_to_buffer(private_generator_t *this, void *bytes, } /** - * Writes a specific amount of byte into the buffer at a specific offset. - */ -static void write_bytes_to_buffer_at_offset(private_generator_t *this, - void *bytes, int number_of_bytes, u_int32_t offset) -{ - int i; - u_int8_t *read_position = (u_int8_t *)bytes; - u_int8_t *write_position; - u_int32_t free_space_after_offset = get_size(this) - offset; - - /* check first if enough space for new data is available */ - if (number_of_bytes > free_space_after_offset) - { - make_space_available(this, - (number_of_bytes - free_space_after_offset) * 8); - } - - write_position = this->buffer + offset; - for (i = 0; i < number_of_bytes; i++) - { - *write_position = *read_position; - read_position++; - write_position++; - } -} - -/** * Generates a U_INT-Field type and writes it to buffer. */ static void generate_u_int_type(private_generator_t *this, @@ -234,10 +198,13 @@ static void generate_u_int_type(private_generator_t *this, number_of_bits = 4; break; case TS_TYPE: + case RESERVED_BYTE: + case SPI_SIZE: case U_INT_8: number_of_bits = 8; break; case U_INT_16: + case PAYLOAD_LENGTH: case CONFIGURATION_ATTRIBUTE_LENGTH: number_of_bits = 16; break; @@ -301,6 +268,8 @@ static void generate_u_int_type(private_generator_t *this, break; } case TS_TYPE: + case RESERVED_BYTE: + case SPI_SIZE: case U_INT_8: { /* 8 bit values are written as they are */ @@ -338,6 +307,7 @@ static void generate_u_int_type(private_generator_t *this, } case U_INT_16: + case PAYLOAD_LENGTH: case CONFIGURATION_ATTRIBUTE_LENGTH: { u_int16_t val = htons(*((u_int16_t*)(this->data_struct + offset))); @@ -371,49 +341,6 @@ static void generate_u_int_type(private_generator_t *this, } /** - * Generate a reserved bit or byte - */ -static void generate_reserved_field(private_generator_t *this, int bits) -{ - /* only one bit or 8 bit fields are supported */ - if (bits != 1 && bits != 8) - { - DBG1(DBG_ENC, "reserved field of %d bits cannot be generated", bits); - return ; - } - make_space_available(this, bits); - - if (bits == 1) - { - u_int8_t reserved_bit = ~(1 << (7 - this->current_bit)); - - *(this->out_position) = *(this->out_position) & reserved_bit; - if (this->current_bit == 0) - { - /* memory must be zero */ - *(this->out_position) = 0x00; - } - this->current_bit++; - if (this->current_bit >= 8) - { - this->current_bit = this->current_bit % 8; - this->out_position++; - } - } - else - { - if (this->current_bit > 0) - { - DBG1(DBG_ENC, "reserved field cannot be written cause " - "alignement of current bit is %d", this->current_bit); - return; - } - *(this->out_position) = 0x00; - this->out_position++; - } -} - -/** * Generate a FLAG filed */ static void generate_flag(private_generator_t *this, u_int32_t offset) @@ -468,7 +395,7 @@ METHOD(generator_t, get_chunk, chunk_t, { chunk_t data; - *lenpos = (u_int32_t*)(this->buffer + this->header_length_position_offset); + *lenpos = (u_int32_t*)(this->buffer + this->header_length_offset); data = chunk_create(this->buffer, get_length(this)); DBG3(DBG_ENC, "generated data of this generator %B", &data); return data; @@ -484,8 +411,6 @@ METHOD(generator_t, generate_payload, void, this->data_struct = payload; payload_type = payload->get_type(payload); - /* spi size has to get reseted */ - this->last_spi_size = 0; offset_start = this->out_position - this->buffer; @@ -505,56 +430,25 @@ METHOD(generator_t, generate_payload, void, case U_INT_8: case U_INT_16: case U_INT_32: + case PAYLOAD_LENGTH: case IKE_SPI: + case RESERVED_BYTE: + case SPI_SIZE: case TS_TYPE: case ATTRIBUTE_TYPE: case CONFIGURATION_ATTRIBUTE_LENGTH: - { generate_u_int_type(this, rules[i].type, rules[i].offset); break; - } case RESERVED_BIT: - { - generate_reserved_field(this, 1); - break; - } - case RESERVED_BYTE: - { - generate_reserved_field(this, 8); - break; - } case FLAG: - { generate_flag(this, rules[i].offset); break; - } - case PAYLOAD_LENGTH: - { - this->last_payload_length_position_offset = get_offset(this); - generate_u_int_type(this, U_INT_16,rules[i].offset); - break; - } case HEADER_LENGTH: - { - this->header_length_position_offset = get_offset(this); - generate_u_int_type(this ,U_INT_32, rules[i].offset); - break; - } - case SPI_SIZE: - generate_u_int_type(this, U_INT_8, rules[i].offset); - this->last_spi_size = *((u_int8_t *)(this->data_struct + - rules[i].offset)); + this->header_length_offset = get_offset(this); + generate_u_int_type(this, U_INT_32, rules[i].offset); break; case ADDRESS: - { - generate_from_chunk(this, rules[i].offset); - break; - } case SPI: - { - generate_from_chunk(this, rules[i].offset); - break; - } case KEY_EXCHANGE_DATA: case NOTIFICATION_DATA: case NONCE_DATA: @@ -566,221 +460,52 @@ METHOD(generator_t, generate_payload, void, case CONFIGURATION_ATTRIBUTE_VALUE: case VID_DATA: case EAP_DATA: - { - u_int32_t payload_length_position_offset; - u_int16_t length_of_payload; - u_int16_t header_length = 0; - u_int16_t length_in_network_order; - - switch(rules[i].type) - { - case KEY_EXCHANGE_DATA: - header_length = KE_PAYLOAD_HEADER_LENGTH; - break; - case NOTIFICATION_DATA: - header_length = NOTIFY_PAYLOAD_HEADER_LENGTH + - this->last_spi_size; - break; - case NONCE_DATA: - header_length = NONCE_PAYLOAD_HEADER_LENGTH; - break; - case ID_DATA: - header_length = ID_PAYLOAD_HEADER_LENGTH; - break; - case AUTH_DATA: - header_length = AUTH_PAYLOAD_HEADER_LENGTH; - break; - case CERT_DATA: - header_length = CERT_PAYLOAD_HEADER_LENGTH; - break; - case CERTREQ_DATA: - header_length = CERTREQ_PAYLOAD_HEADER_LENGTH; - break; - case SPIS: - header_length = DELETE_PAYLOAD_HEADER_LENGTH; - break; - case VID_DATA: - header_length = VENDOR_ID_PAYLOAD_HEADER_LENGTH; - break; - case CONFIGURATION_ATTRIBUTE_VALUE: - header_length = CONFIGURATION_ATTRIBUTE_HEADER_LENGTH; - break; - case EAP_DATA: - header_length = EAP_PAYLOAD_HEADER_LENGTH; - break; - default: - break; - } + case ENCRYPTED_DATA: + case UNKNOWN_DATA: generate_from_chunk(this, rules[i].offset); - - payload_length_position_offset = - this->last_payload_length_position_offset; - - length_of_payload = header_length + - ((chunk_t *)(this->data_struct + rules[i].offset))->len; - - length_in_network_order = htons(length_of_payload); - write_bytes_to_buffer_at_offset(this, &length_in_network_order, - sizeof(u_int16_t), payload_length_position_offset); break; - } case PROPOSALS: - { - u_int32_t payload_length_position_offset = - this->last_payload_length_position_offset; - /* Length of SA_PAYLOAD is calculated */ - u_int16_t length_of_sa_payload = SA_PAYLOAD_HEADER_LENGTH; - u_int16_t int16_val; - linked_list_t *proposals = *((linked_list_t **) - (this->data_struct + rules[i].offset)); - iterator_t *iterator; - payload_t *current_proposal; - - iterator = proposals->create_iterator(proposals,TRUE); - while (iterator->iterate(iterator, (void**)¤t_proposal)) - { - u_int32_t before_generate_position_offset; - u_int32_t after_generate_position_offset; - - before_generate_position_offset = get_offset(this); - generate_payload(this, current_proposal); - after_generate_position_offset = get_offset(this); - length_of_sa_payload += (after_generate_position_offset - - before_generate_position_offset); - } - iterator->destroy(iterator); - - int16_val = htons(length_of_sa_payload); - write_bytes_to_buffer_at_offset(this, &int16_val, - sizeof(u_int16_t),payload_length_position_offset); - break; - } case TRANSFORMS: - { - u_int32_t payload_length_position_offset = - this->last_payload_length_position_offset; - u_int16_t length_of_proposal = - PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH + this->last_spi_size; - u_int16_t int16_val; - linked_list_t *transforms = *((linked_list_t **) - (this->data_struct + rules[i].offset)); - iterator_t *iterator; - payload_t *current_transform; - - iterator = transforms->create_iterator(transforms,TRUE); - while (iterator->iterate(iterator, (void**)¤t_transform)) - { - u_int32_t before_generate_position_offset; - u_int32_t after_generate_position_offset; - - before_generate_position_offset = get_offset(this); - generate_payload(this, current_transform); - after_generate_position_offset = get_offset(this); - - length_of_proposal += (after_generate_position_offset - - before_generate_position_offset); - } - iterator->destroy(iterator); - - int16_val = htons(length_of_proposal); - write_bytes_to_buffer_at_offset(this, &int16_val, - sizeof(u_int16_t), payload_length_position_offset); - break; - } case TRANSFORM_ATTRIBUTES: - { - u_int32_t transform_length_position_offset = - this->last_payload_length_position_offset; - u_int16_t length_of_transform = - TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH; - u_int16_t int16_val; - linked_list_t *transform_attributes =*((linked_list_t **) - (this->data_struct + rules[i].offset)); - iterator_t *iterator; - payload_t *current_attribute; - - iterator = transform_attributes->create_iterator( - transform_attributes, TRUE); - while (iterator->iterate(iterator, (void**)¤t_attribute)) - { - u_int32_t before_generate_position_offset; - u_int32_t after_generate_position_offset; - - before_generate_position_offset = get_offset(this); - generate_payload(this, current_attribute); - after_generate_position_offset = get_offset(this); - - length_of_transform += (after_generate_position_offset - - before_generate_position_offset); - } - - iterator->destroy(iterator); - - int16_val = htons(length_of_transform); - write_bytes_to_buffer_at_offset(this, &int16_val, - sizeof(u_int16_t),transform_length_position_offset); - break; - } case CONFIGURATION_ATTRIBUTES: + case TRAFFIC_SELECTORS: { - u_int32_t configurations_length_position_offset = - this->last_payload_length_position_offset; - u_int16_t length_of_configurations = CP_PAYLOAD_HEADER_LENGTH; - u_int16_t int16_val; - linked_list_t *configuration_attributes = *((linked_list_t **) - (this->data_struct + rules[i].offset)); - iterator_t *iterator; - payload_t *current_attribute; + linked_list_t *proposals; + enumerator_t *enumerator; + payload_t *proposal; - iterator = configuration_attributes->create_iterator( - configuration_attributes,TRUE); - while (iterator->iterate(iterator, (void**)¤t_attribute)) + proposals = *((linked_list_t **) + (this->data_struct + rules[i].offset)); + enumerator = proposals->create_enumerator(proposals); + while (enumerator->enumerate(enumerator, &proposal)) { - u_int32_t before_generate_position_offset; - u_int32_t after_generate_position_offset; - - before_generate_position_offset = get_offset(this); - generate_payload(this, current_attribute); - after_generate_position_offset = get_offset(this); - - length_of_configurations += after_generate_position_offset - - before_generate_position_offset; + generate_payload(this, proposal); } - - iterator->destroy(iterator); - - int16_val = htons(length_of_configurations); - write_bytes_to_buffer_at_offset(this, &int16_val, - sizeof(u_int16_t),configurations_length_position_offset); + enumerator->destroy(enumerator); break; } case ATTRIBUTE_FORMAT: - { generate_flag(this, rules[i].offset); /* Attribute format is a flag which is stored in context*/ this->attribute_format = *((bool *)(this->data_struct + rules[i].offset)); break; - } - case ATTRIBUTE_LENGTH_OR_VALUE: - { - if (this->attribute_format == FALSE) + if (this->attribute_format) { generate_u_int_type(this, U_INT_16, rules[i].offset); - /* this field hold the length of the attribute */ - this->attribute_length = - *((u_int16_t *)(this->data_struct + rules[i].offset)); } else { generate_u_int_type(this, U_INT_16, rules[i].offset); + /* this field hold the length of the attribute */ + this->attribute_length = + *((u_int16_t *)(this->data_struct + rules[i].offset)); } break; - } case ATTRIBUTE_VALUE: { - if (this->attribute_format == FALSE) + if (!this->attribute_format) { DBG2(DBG_ENC, "attribute value has not fixed size"); /* the attribute value is generated */ @@ -788,44 +513,6 @@ METHOD(generator_t, generate_payload, void, } break; } - case TRAFFIC_SELECTORS: - { - u_int32_t payload_length_position_offset = - this->last_payload_length_position_offset; - u_int16_t length_of_ts_payload = TS_PAYLOAD_HEADER_LENGTH; - u_int16_t int16_val; - linked_list_t *traffic_selectors = *((linked_list_t **) - (this->data_struct + rules[i].offset)); - iterator_t *iterator; - payload_t *current_tss; - - iterator = traffic_selectors->create_iterator( - traffic_selectors,TRUE); - while (iterator->iterate(iterator, (void **)¤t_tss)) - { - u_int32_t before_generate_position_offset; - u_int32_t after_generate_position_offset; - - before_generate_position_offset = get_offset(this); - generate_payload(this, current_tss); - after_generate_position_offset = get_offset(this); - - length_of_ts_payload += (after_generate_position_offset - - before_generate_position_offset); - } - iterator->destroy(iterator); - - int16_val = htons(length_of_ts_payload); - write_bytes_to_buffer_at_offset(this, &int16_val, - sizeof(u_int16_t),payload_length_position_offset); - break; - } - - case ENCRYPTED_DATA: - { - generate_from_chunk(this, rules[i].offset); - break; - } default: DBG1(DBG_ENC, "field type %N is not supported", encoding_type_names, rules[i].type); diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c index d41ad4697..dbef340ab 100644 --- a/src/libcharon/encoding/message.c +++ b/src/libcharon/encoding/message.c @@ -131,6 +131,7 @@ static payload_rule_t ike_sa_init_r_rules[] = { {SECURITY_ASSOCIATION, 1, 1, FALSE, FALSE}, {KEY_EXCHANGE, 1, 1, FALSE, FALSE}, {NONCE, 1, 1, FALSE, FALSE}, + {CERTIFICATE_REQUEST, 1, 1, FALSE, FALSE}, {VENDOR_ID, 0, 10, FALSE, FALSE}, }; @@ -490,6 +491,21 @@ struct private_message_t { bool is_request; /** + * Higher version supported? + */ + bool version_flag; + + /** + * Reserved bits in IKE header + */ + bool reserved[5]; + + /** + * Sorting of message disabled? + */ + bool sort_disabled; + + /** * Message ID of this message. */ u_int32_t message_id; @@ -647,18 +663,35 @@ METHOD(message_t, get_request, bool, return this->is_request; } -/** - * Is this message in an encoded form? - */ -static bool is_encoded(private_message_t *this) +METHOD(message_t, set_version_flag, void, + private_message_t *this) { - chunk_t data = this->packet->get_data(this->packet); + this->version_flag = TRUE; +} - if (data.ptr == NULL) +METHOD(message_t, get_reserved_header_bit, bool, + private_message_t *this, u_int nr) +{ + if (nr < countof(this->reserved)) { - return FALSE; + return this->reserved[nr]; } - return TRUE; + return FALSE; +} + +METHOD(message_t, set_reserved_header_bit, void, + private_message_t *this, u_int nr) +{ + if (nr < countof(this->reserved)) + { + this->reserved[nr] = TRUE; + } +} + +METHOD(message_t, is_encoded, bool, + private_message_t *this) +{ + return this->packet->get_data(this->packet).ptr != NULL; } METHOD(message_t, add_payload, void, @@ -732,6 +765,12 @@ METHOD(message_t, create_payload_enumerator, enumerator_t*, return this->payloads->create_enumerator(this->payloads); } +METHOD(message_t, remove_payload_at, void, + private_message_t *this, enumerator_t *enumerator) +{ + this->payloads->remove_at(this->payloads, enumerator); +} + METHOD(message_t, get_payload, payload_t*, private_message_t *this, payload_type_t type) { @@ -1001,6 +1040,12 @@ static encryption_payload_t* wrap_payloads(private_message_t *this) return encryption; } +METHOD(message_t, disable_sort, void, + private_message_t *this) +{ + this->sort_disabled = TRUE; +} + METHOD(message_t, generate, status_t, private_message_t *this, aead_t *aead, packet_t **packet) { @@ -1012,12 +1057,8 @@ METHOD(message_t, generate, status_t, chunk_t chunk; char str[256]; u_int32_t *lenpos; - - if (is_encoded(this)) - { /* already generated, return a new packet clone */ - *packet = this->packet->clone(this->packet); - return SUCCESS; - } + bool *reserved; + int i; if (this->exchange_type == EXCHANGE_TYPE_UNDEFINED) { @@ -1039,7 +1080,10 @@ METHOD(message_t, generate, status_t, return NOT_SUPPORTED; } - order_payloads(this); + if (!this->sort_disabled) + { + order_payloads(this); + } DBG1(DBG_ENC, "generating %s", get_string(this, str, sizeof(str))); @@ -1053,9 +1097,12 @@ METHOD(message_t, generate, status_t, } ike_header = ike_header_create(); + ike_header->set_maj_version(ike_header, this->major_version); + ike_header->set_min_version(ike_header, this->minor_version); ike_header->set_exchange_type(ike_header, this->exchange_type); ike_header->set_message_id(ike_header, this->message_id); ike_header->set_response_flag(ike_header, !this->is_request); + ike_header->set_version_flag(ike_header, this->version_flag); ike_header->set_initiator_flag(ike_header, this->ike_sa_id->is_initiator(this->ike_sa_id)); ike_header->set_initiator_spi(ike_header, @@ -1063,6 +1110,16 @@ METHOD(message_t, generate, status_t, ike_header->set_responder_spi(ike_header, this->ike_sa_id->get_responder_spi(this->ike_sa_id)); + for (i = 0; i < countof(this->reserved); i++) + { + reserved = payload_get_field(&ike_header->payload_interface, + RESERVED_BIT, i); + if (reserved) + { + *reserved = this->reserved[i]; + } + } + generator = generator_create(); /* generate all payloads with proper next type */ @@ -1131,6 +1188,8 @@ METHOD(message_t, parse_header, status_t, { ike_header_t *ike_header; status_t status; + bool *reserved; + int i; DBG2(DBG_ENC, "parsing header of message"); @@ -1165,7 +1224,15 @@ METHOD(message_t, parse_header, status_t, this->minor_version = ike_header->get_min_version(ike_header); this->first_payload = ike_header->payload_interface.get_next_type( &ike_header->payload_interface); - + for (i = 0; i < countof(this->reserved); i++) + { + reserved = payload_get_field(&ike_header->payload_interface, + RESERVED_BIT, i); + if (reserved) + { + this->reserved[i] = *reserved; + } + } DBG2(DBG_ENC, "parsed a %N %s", exchange_type_names, this->exchange_type, this->is_request ? "request" : "response"); @@ -1182,6 +1249,31 @@ METHOD(message_t, parse_header, status_t, } /** + * Check if a payload is for a mediation extension connectivity check + */ +static bool is_connectivity_check(private_message_t *this, payload_t *payload) +{ +#ifdef ME + if (this->exchange_type == INFORMATIONAL && + payload->get_type(payload) == NOTIFY) + { + notify_payload_t *notify = (notify_payload_t*)payload; + + switch (notify->get_notify_type(notify)) + { + case ME_CONNECTID: + case ME_ENDPOINT: + case ME_CONNECTAUTH: + return TRUE; + default: + break; + } + } +#endif /* !ME */ + return FALSE; +} + +/** * Decrypt payload from the encryption payload */ static status_t decrypt_payloads(private_message_t *this, aead_t *aead) @@ -1252,14 +1344,15 @@ static status_t decrypt_payloads(private_message_t *this, aead_t *aead) } encryption->destroy(encryption); } - if (type != UNKNOWN_PAYLOAD && !was_encrypted) + if (payload_is_known(type) && !was_encrypted && + !is_connectivity_check(this, payload)) { rule = get_payload_rule(this, type); if (!rule || rule->encrypted) { DBG1(DBG_ENC, "payload type %N was not encrypted", payload_type_names, type); - status = VERIFY_ERROR; + status = FAILED; break; } } @@ -1274,6 +1367,7 @@ static status_t decrypt_payloads(private_message_t *this, aead_t *aead) */ static status_t verify(private_message_t *this) { + bool complete = FALSE; int i; DBG2(DBG_ENC, "verifying message structure"); @@ -1291,22 +1385,9 @@ static status_t verify(private_message_t *this) while (enumerator->enumerate(enumerator, &payload)) { payload_type_t type; - unknown_payload_t *unknown; type = payload->get_type(payload); - if (type == UNKNOWN_PAYLOAD) - { - /* unknown payloads are ignored if they are not critical */ - unknown = (unknown_payload_t*)payload; - if (unknown->is_critical(unknown)) - { - DBG1(DBG_ENC, "%N is not supported, but its critical!", - payload_type_names, type); - enumerator->destroy(enumerator); - return NOT_SUPPORTED; - } - } - else if (type == rule->type) + if (type == rule->type) { found++; DBG2(DBG_ENC, "found payload of type %N", @@ -1323,15 +1404,15 @@ static status_t verify(private_message_t *this) } enumerator->destroy(enumerator); - if (found < rule->min_occurence) + if (!complete && found < rule->min_occurence) { DBG1(DBG_ENC, "payload of type %N not occured %d times (%d)", payload_type_names, rule->type, rule->min_occurence, found); return VERIFY_ERROR; } - if (rule->sufficient) + if (found && rule->sufficient) { - return SUCCESS; + complete = TRUE; } } return SUCCESS; @@ -1360,7 +1441,7 @@ METHOD(message_t, parse_body, status_t, { DBG1(DBG_ENC, "payload type %N could not be parsed", payload_type_names, type); - return PARSE_ERROR; + return this->exchange_type == IKE_SA_INIT ? PARSE_ERROR : FAILED; } DBG2(DBG_ENC, "verifying payload of type %N", payload_type_names, type); @@ -1370,7 +1451,7 @@ METHOD(message_t, parse_body, status_t, DBG1(DBG_ENC, "%N payload verification failed", payload_type_names, type); payload->destroy(payload); - return VERIFY_ERROR; + return this->exchange_type == IKE_SA_INIT ? VERIFY_ERROR : FAILED; } DBG2(DBG_ENC, "%N payload verified. Adding to payload list", @@ -1388,14 +1469,11 @@ METHOD(message_t, parse_body, status_t, type = payload->get_next_type(payload); } - if (type == ENCRYPTED) + status = decrypt_payloads(this, aead); + if (status != SUCCESS) { - status = decrypt_payloads(this, aead); - if (status != SUCCESS) - { - DBG1(DBG_ENC, "could not decrypt payloads"); - return status; - } + DBG1(DBG_ENC, "could not decrypt payloads"); + return status; } status = verify(this); @@ -1443,14 +1521,20 @@ message_t *message_create_from_packet(packet_t *packet) .get_first_payload_type = _get_first_payload_type, .set_request = _set_request, .get_request = _get_request, + .set_version_flag = _set_version_flag, + .get_reserved_header_bit = _get_reserved_header_bit, + .set_reserved_header_bit = _set_reserved_header_bit, .add_payload = _add_payload, .add_notify = _add_notify, + .disable_sort = _disable_sort, .generate = _generate, + .is_encoded = _is_encoded, .set_source = _set_source, .get_source = _get_source, .set_destination = _set_destination, .get_destination = _get_destination, .create_payload_enumerator = _create_payload_enumerator, + .remove_payload_at = _remove_payload_at, .get_payload = _get_payload, .get_notify = _get_notify, .parse_header = _parse_header, @@ -1459,6 +1543,8 @@ message_t *message_create_from_packet(packet_t *packet) .get_packet_data = _get_packet_data, .destroy = _destroy, }, + .major_version = IKE_MAJOR_VERSION, + .minor_version = IKE_MINOR_VERSION, .exchange_type = EXCHANGE_TYPE_UNDEFINED, .is_request = TRUE, .first_payload = NO_PAYLOAD, diff --git a/src/libcharon/encoding/message.h b/src/libcharon/encoding/message.h index 8c1cbcd09..51197308c 100644 --- a/src/libcharon/encoding/message.h +++ b/src/libcharon/encoding/message.h @@ -154,6 +154,26 @@ struct message_t { bool (*get_request) (message_t *this); /** + * Set the version flag in the IKE header. + */ + void (*set_version_flag)(message_t *this); + + /** + * Get a reserved bit in the IKE header. + * + * @param nr reserved bit to get in IKE header, 0-4 + * @return TRUE if bit is set + */ + bool (*get_reserved_header_bit)(message_t *this, u_int nr); + + /** + * Set a reserved bit in the IKE header. + * + * @param nr reserved bit to set in IKE header, 0-4 + */ + void (*set_reserved_header_bit)(message_t *this, u_int nr); + + /** * Append a payload to the message. * * If the payload must be encrypted is not specified here. Encryption @@ -181,6 +201,11 @@ struct message_t { chunk_t data); /** + * Disable automatic payload sorting for this message. + */ + void (*disable_sort)(message_t *this); + + /** * Parses header of message. * * Begins parisng of a message created via message_create_from_packet(). @@ -206,8 +231,6 @@ struct message_t { * @param aead aead transform to verify/decrypt message * @return * - SUCCESS if parsing successful - * - NOT_SUPPORTED if ciritcal unknown payloads found - * - NOT_SUPPORTED if message type is not supported! * - PARSE_ERROR if message parsing failed * - VERIFY_ERROR if message verification failed (bad syntax) * - FAILED if integrity check failed @@ -235,6 +258,13 @@ struct message_t { status_t (*generate) (message_t *this, aead_t *aead, packet_t **packet); /** + * Check if the message has already been encoded using generate(). + * + * @return TRUE if message has been encoded + */ + bool (*is_encoded)(message_t *this); + + /** * Gets the source host informations. * * @warning Returned host_t object is not getting cloned, @@ -282,6 +312,13 @@ struct message_t { enumerator_t * (*create_payload_enumerator) (message_t *this); /** + * Remove the payload at the current enumerator position. + * + * @param enumerator enumerator created by create_payload_enumerator() + */ + void (*remove_payload_at)(message_t *this, enumerator_t *enumerator); + + /** * Find a payload of a specific type. * * Returns the first occurance. diff --git a/src/libcharon/encoding/parser.c b/src/libcharon/encoding/parser.c index 9aa34b1bc..32cefb9e7 100644 --- a/src/libcharon/encoding/parser.c +++ b/src/libcharon/encoding/parser.c @@ -387,12 +387,6 @@ static status_t parse_payload(private_parser_t *this, DBG3(DBG_ENC, "parsing payload from %b", this->byte_pos, this->input_roof - this->byte_pos); - if (pld->get_type(pld) == UNKNOWN_PAYLOAD) - { - DBG1(DBG_ENC, " payload type %d is unknown, handling as %N", - payload_type, payload_type_names, UNKNOWN_PAYLOAD); - } - /* base pointer for output, avoids casting in every rule */ output = pld; @@ -415,6 +409,7 @@ static status_t parse_payload(private_parser_t *this, break; } case U_INT_8: + case RESERVED_BYTE: { if (!parse_uint8(this, rule_number, output + rule->offset)) { @@ -433,6 +428,7 @@ static status_t parse_payload(private_parser_t *this, break; } case U_INT_32: + case HEADER_LENGTH: { if (!parse_uint32(this, rule_number, output + rule->offset)) { @@ -451,23 +447,6 @@ static status_t parse_payload(private_parser_t *this, break; } case RESERVED_BIT: - { - if (!parse_bit(this, rule_number, NULL)) - { - pld->destroy(pld); - return PARSE_ERROR; - } - break; - } - case RESERVED_BYTE: - { - if (!parse_uint8(this, rule_number, NULL)) - { - pld->destroy(pld); - return PARSE_ERROR; - } - break; - } case FLAG: { if (!parse_bit(this, rule_number, output + rule->offset)) @@ -493,15 +472,6 @@ static status_t parse_payload(private_parser_t *this, } break; } - case HEADER_LENGTH: - { - if (!parse_uint32(this, rule_number, output + rule->offset)) - { - pld->destroy(pld); - return PARSE_ERROR; - } - break; - } case SPI_SIZE: { if (!parse_uint8(this, rule_number, output + rule->offset)) diff --git a/src/libcharon/encoding/payloads/auth_payload.c b/src/libcharon/encoding/payloads/auth_payload.c index d31208abb..cb44a997c 100644 --- a/src/libcharon/encoding/payloads/auth_payload.c +++ b/src/libcharon/encoding/payloads/auth_payload.c @@ -1,5 +1,6 @@ /* - * Copyright (C) 2005-2006 Martin Willi + * Copyright (C) 2005-2010 Martin Willi + * Copyright (C) 2010 revosec AG * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil * @@ -18,7 +19,6 @@ #include <encoding/payloads/encodings.h> - typedef struct private_auth_payload_t private_auth_payload_t; /** @@ -43,6 +43,16 @@ struct private_auth_payload_t { bool critical; /** + * Reserved bits + */ + bool reserved_bit[7]; + + /** + * Reserved bytes + */ + u_int8_t reserved_byte[3]; + + /** * Length of this payload. */ u_int16_t payload_length; @@ -66,27 +76,27 @@ struct private_auth_payload_t { */ encoding_rule_t auth_payload_encodings[] = { /* 1 Byte next payload type, stored in the field next_payload */ - { U_INT_8, offsetof(private_auth_payload_t, next_payload) }, + { U_INT_8, offsetof(private_auth_payload_t, next_payload) }, /* the critical bit */ - { FLAG, offsetof(private_auth_payload_t, critical) }, - /* 7 Bit reserved bits, nowhere stored */ - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, + { FLAG, offsetof(private_auth_payload_t, critical) }, + /* 7 Bit reserved bits */ + { RESERVED_BIT, offsetof(private_auth_payload_t, reserved_bit[0]) }, + { RESERVED_BIT, offsetof(private_auth_payload_t, reserved_bit[1]) }, + { RESERVED_BIT, offsetof(private_auth_payload_t, reserved_bit[2]) }, + { RESERVED_BIT, offsetof(private_auth_payload_t, reserved_bit[3]) }, + { RESERVED_BIT, offsetof(private_auth_payload_t, reserved_bit[4]) }, + { RESERVED_BIT, offsetof(private_auth_payload_t, reserved_bit[5]) }, + { RESERVED_BIT, offsetof(private_auth_payload_t, reserved_bit[6]) }, /* Length of the whole payload*/ - { PAYLOAD_LENGTH, offsetof(private_auth_payload_t, payload_length)}, + { PAYLOAD_LENGTH, offsetof(private_auth_payload_t, payload_length) }, /* 1 Byte AUTH type*/ - { U_INT_8, offsetof(private_auth_payload_t, auth_method) }, + { U_INT_8, offsetof(private_auth_payload_t, auth_method) }, /* 3 reserved bytes */ - { RESERVED_BYTE, 0 }, - { RESERVED_BYTE, 0 }, - { RESERVED_BYTE, 0 }, + { RESERVED_BYTE, offsetof(private_auth_payload_t, reserved_byte[0]) }, + { RESERVED_BYTE, offsetof(private_auth_payload_t, reserved_byte[1]) }, + { RESERVED_BYTE, offsetof(private_auth_payload_t, reserved_byte[2]) }, /* some auth data bytes, length is defined in PAYLOAD_LENGTH */ - { AUTH_DATA, offsetof(private_auth_payload_t, auth_data) } + { AUTH_DATA, offsetof(private_auth_payload_t, auth_data) } }; /* @@ -103,125 +113,73 @@ encoding_rule_t auth_payload_encodings[] = { +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ -/** - * Implementation of payload_t.verify. - */ -static status_t verify(private_auth_payload_t *this) +METHOD(payload_t, verify, status_t, + private_auth_payload_t *this) { - if (this->auth_method == 0 || - (this->auth_method >= 4 && this->auth_method <= 8) || - (this->auth_method >= 12 && this->auth_method <= 200)) - { - /* reserved IDs */ - return FAILED; - } return SUCCESS; } -/** - * Implementation of auth_payload_t.get_encoding_rules. - */ -static void get_encoding_rules(private_auth_payload_t *this, encoding_rule_t **rules, size_t *rule_count) +METHOD(payload_t, get_encoding_rules, void, + private_auth_payload_t *this, encoding_rule_t **rules, size_t *rule_count) { *rules = auth_payload_encodings; - *rule_count = sizeof(auth_payload_encodings) / sizeof(encoding_rule_t); + *rule_count = countof(auth_payload_encodings); } -/** - * Implementation of payload_t.get_type. - */ -static payload_type_t get_payload_type(private_auth_payload_t *this) +METHOD(payload_t, get_type, payload_type_t, + private_auth_payload_t *this) { return AUTHENTICATION; } -/** - * Implementation of payload_t.get_next_type. - */ -static payload_type_t get_next_type(private_auth_payload_t *this) +METHOD(payload_t, get_next_type, payload_type_t, + private_auth_payload_t *this) { - return (this->next_payload); + return this->next_payload; } -/** - * Implementation of payload_t.set_next_type. - */ -static void set_next_type(private_auth_payload_t *this,payload_type_t type) +METHOD(payload_t, set_next_type, void, + private_auth_payload_t *this, payload_type_t type) { this->next_payload = type; } -/** - * Implementation of payload_t.get_length. - */ -static size_t get_length(private_auth_payload_t *this) +METHOD(payload_t, get_length, size_t, + private_auth_payload_t *this) { return this->payload_length; } -/** - * Implementation of auth_payload_t.set_auth_method. - */ -static void set_auth_method (private_auth_payload_t *this, auth_method_t method) +METHOD(auth_payload_t, set_auth_method, void, + private_auth_payload_t *this, auth_method_t method) { this->auth_method = method; } -/** - * Implementation of auth_payload_t.get_auth_method. - */ -static auth_method_t get_auth_method (private_auth_payload_t *this) +METHOD(auth_payload_t, get_auth_method, auth_method_t, + private_auth_payload_t *this) { - return (this->auth_method); + return this->auth_method; } -/** - * Implementation of auth_payload_t.set_data. - */ -static void set_data (private_auth_payload_t *this, chunk_t data) +METHOD(auth_payload_t, set_data, void, + private_auth_payload_t *this, chunk_t data) { - if (this->auth_data.ptr != NULL) - { - chunk_free(&(this->auth_data)); - } - this->auth_data.ptr = clalloc(data.ptr,data.len); - this->auth_data.len = data.len; + free(this->auth_data.ptr); + this->auth_data = chunk_clone(data); this->payload_length = AUTH_PAYLOAD_HEADER_LENGTH + this->auth_data.len; } -/** - * Implementation of auth_payload_t.get_data. - */ -static chunk_t get_data (private_auth_payload_t *this) +METHOD(auth_payload_t, get_data, chunk_t, + private_auth_payload_t *this) { - return (this->auth_data); + return this->auth_data; } -/** - * Implementation of auth_payload_t.get_data_clone. - */ -static chunk_t get_data_clone (private_auth_payload_t *this) +METHOD2(payload_t, auth_payload_t, destroy, void, + private_auth_payload_t *this) { - chunk_t cloned_data; - if (this->auth_data.ptr == NULL) - { - return (this->auth_data); - } - cloned_data.ptr = clalloc(this->auth_data.ptr,this->auth_data.len); - cloned_data.len = this->auth_data.len; - return cloned_data; -} - -/** - * Implementation of payload_t.destroy and auth_payload_t.destroy. - */ -static void destroy(private_auth_payload_t *this) -{ - if (this->auth_data.ptr != NULL) - { - chunk_free(&(this->auth_data)); - } - + free(this->auth_data.ptr); free(this); } @@ -230,30 +188,27 @@ static void destroy(private_auth_payload_t *this) */ auth_payload_t *auth_payload_create() { - private_auth_payload_t *this = malloc_thing(private_auth_payload_t); - - /* interface functions */ - this->public.payload_interface.verify = (status_t (*) (payload_t *))verify; - this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules; - this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length; - this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type; - this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type; - this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_payload_type; - this->public.payload_interface.destroy = (void (*) (payload_t *))destroy; - - /* public functions */ - this->public.destroy = (void (*) (auth_payload_t *)) destroy; - this->public.set_auth_method = (void (*) (auth_payload_t *,auth_method_t)) set_auth_method; - this->public.get_auth_method = (auth_method_t (*) (auth_payload_t *)) get_auth_method; - this->public.set_data = (void (*) (auth_payload_t *,chunk_t)) set_data; - this->public.get_data_clone = (chunk_t (*) (auth_payload_t *)) get_data_clone; - this->public.get_data = (chunk_t (*) (auth_payload_t *)) get_data; - - /* private variables */ - this->critical = FALSE; - this->next_payload = NO_PAYLOAD; - this->payload_length =AUTH_PAYLOAD_HEADER_LENGTH; - this->auth_data = chunk_empty; - - return (&(this->public)); + private_auth_payload_t *this; + + INIT(this, + .public = { + .payload_interface = { + .verify = _verify, + .get_encoding_rules = _get_encoding_rules, + .get_length = _get_length, + .get_next_type = _get_next_type, + .set_next_type = _set_next_type, + .get_type = _get_type, + .destroy = _destroy, + }, + .set_auth_method = _set_auth_method, + .get_auth_method = _get_auth_method, + .set_data = _set_data, + .get_data = _get_data, + .destroy = _destroy, + }, + .next_payload = NO_PAYLOAD, + .payload_length = AUTH_PAYLOAD_HEADER_LENGTH, + ); + return &this->public; } diff --git a/src/libcharon/encoding/payloads/auth_payload.h b/src/libcharon/encoding/payloads/auth_payload.h index 37ee149db..e4c4e6ae3 100644 --- a/src/libcharon/encoding/payloads/auth_payload.h +++ b/src/libcharon/encoding/payloads/auth_payload.h @@ -62,29 +62,31 @@ struct auth_payload_t { /** * Set the AUTH data. * - * Data gets cloned. - * - * @param data AUTH data as chunk_t + * @param data AUTH data as chunk_t, gets cloned */ void (*set_data) (auth_payload_t *this, chunk_t data); /** * Get the AUTH data. * - * Returned data are a copy of the internal one. - * - * @return AUTH data as chunk_t + * @return AUTH data as chunk_t, internal data */ - chunk_t (*get_data_clone) (auth_payload_t *this); + chunk_t (*get_data) (auth_payload_t *this); /** - * Get the AUTH data. + * Get the value of a reserved bit. * - * Returned data are NOT copied + * @param nr number of the reserved bit, 0-6 + * @return TRUE if bit was set, FALSE to clear + */ + bool (*get_reserved_bit)(auth_payload_t *this, u_int nr); + + /** + * Set one of the reserved bits. * - * @return AUTH data as chunk_t + * @param nr number of the reserved bit, 0-6 */ - chunk_t (*get_data) (auth_payload_t *this); + void (*set_reserved_bit)(auth_payload_t *this, u_int nr); /** * Destroys an auth_payload_t object. diff --git a/src/libcharon/encoding/payloads/cert_payload.c b/src/libcharon/encoding/payloads/cert_payload.c index 80239f654..c42cec680 100644 --- a/src/libcharon/encoding/payloads/cert_payload.c +++ b/src/libcharon/encoding/payloads/cert_payload.c @@ -1,6 +1,7 @@ /* * Copyright (C) 2008 Tobias Brunner - * Copyright (C) 2005-2007 Martin Willi + * Copyright (C) 2005-2010 Martin Willi + * Copyright (C) 2010 revosec AG * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil * @@ -43,9 +44,9 @@ typedef struct private_cert_payload_t private_cert_payload_t; /** * Private data of an cert_payload_t object. - * */ struct private_cert_payload_t { + /** * Public cert_payload_t interface. */ @@ -62,6 +63,11 @@ struct private_cert_payload_t { bool critical; /** + * reserved bits + */ + bool reserved[7]; + + /** * Length of this payload. */ u_int16_t payload_length; @@ -91,23 +97,23 @@ struct private_cert_payload_t { */ encoding_rule_t cert_payload_encodings[] = { /* 1 Byte next payload type, stored in the field next_payload */ - { U_INT_8, offsetof(private_cert_payload_t, next_payload) }, + { U_INT_8, offsetof(private_cert_payload_t, next_payload) }, /* the critical bit */ - { FLAG, offsetof(private_cert_payload_t, critical) }, + { FLAG, offsetof(private_cert_payload_t, critical) }, /* 7 Bit reserved bits, nowhere stored */ - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, + { RESERVED_BIT, offsetof(private_cert_payload_t, reserved[0]) }, + { RESERVED_BIT, offsetof(private_cert_payload_t, reserved[1]) }, + { RESERVED_BIT, offsetof(private_cert_payload_t, reserved[2]) }, + { RESERVED_BIT, offsetof(private_cert_payload_t, reserved[3]) }, + { RESERVED_BIT, offsetof(private_cert_payload_t, reserved[4]) }, + { RESERVED_BIT, offsetof(private_cert_payload_t, reserved[5]) }, + { RESERVED_BIT, offsetof(private_cert_payload_t, reserved[6]) }, /* Length of the whole payload*/ { PAYLOAD_LENGTH, offsetof(private_cert_payload_t, payload_length)}, /* 1 Byte CERT type*/ { U_INT_8, offsetof(private_cert_payload_t, encoding) }, /* some cert data bytes, length is defined in PAYLOAD_LENGTH */ - { CERT_DATA, offsetof(private_cert_payload_t, data) } + { CERT_DATA, offsetof(private_cert_payload_t, data) } }; /* @@ -123,25 +129,23 @@ encoding_rule_t cert_payload_encodings[] = { +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ -/** - * Implementation of payload_t.verify. - */ -static status_t verify(private_cert_payload_t *this) +METHOD(payload_t, verify, status_t, + private_cert_payload_t *this) { if (this->encoding == ENC_X509_HASH_AND_URL || this->encoding == ENC_X509_HASH_AND_URL_BUNDLE) { + int i; + /* coarse verification of "Hash and URL" encoded certificates */ if (this->data.len <= 20) { DBG1(DBG_ENC, "invalid payload length for hash-and-url (%d), ignore", - this->data.len); + this->data.len); this->invalid_hash_and_url = TRUE; return SUCCESS; } - - int i = 20; /* skipping the hash */ - for (; i < this->data.len; ++i) + for (i = 20; i < this->data.len; ++i) { if (this->data.ptr[i] == '\0') { @@ -151,94 +155,81 @@ static status_t verify(private_cert_payload_t *this) else if (!isprint(this->data.ptr[i])) { DBG1(DBG_ENC, "non printable characters in url of hash-and-url" - " encoded certificate payload, ignore"); + " encoded certificate payload, ignore"); this->invalid_hash_and_url = TRUE; return SUCCESS; } } - /* URL is not null terminated, correct that */ - chunk_t data = chunk_alloc(this->data.len + 1); - memcpy(data.ptr, this->data.ptr, this->data.len); - data.ptr[this->data.len] = '\0'; - chunk_free(&this->data); - this->data = data; + this->data = chunk_cat("mc", this->data, chunk_from_chars(0)); } return SUCCESS; } -/** - * Implementation of cert_payload_t.get_encoding_rules. - */ -static void get_encoding_rules(private_cert_payload_t *this, - encoding_rule_t **rules, size_t *rule_count) +METHOD(payload_t, get_encoding_rules, void, + private_cert_payload_t *this, encoding_rule_t **rules, size_t *rule_count) { *rules = cert_payload_encodings; - *rule_count = sizeof(cert_payload_encodings) / sizeof(encoding_rule_t); + *rule_count = countof(cert_payload_encodings); } -/** - * Implementation of payload_t.get_type. - */ -static payload_type_t get_payload_type(private_cert_payload_t *this) +METHOD(payload_t, get_type, payload_type_t, + private_cert_payload_t *this) { return CERTIFICATE; } -/** - * Implementation of payload_t.get_next_type. - */ -static payload_type_t get_next_type(private_cert_payload_t *this) +METHOD(payload_t, get_next_type, payload_type_t, + private_cert_payload_t *this) { return this->next_payload; } -/** - * Implementation of payload_t.set_next_type. - */ -static void set_next_type(private_cert_payload_t *this,payload_type_t type) +METHOD(payload_t, set_next_type, void, + private_cert_payload_t *this, payload_type_t type) { this->next_payload = type; } -/** - * Implementation of payload_t.get_length. - */ -static size_t get_length(private_cert_payload_t *this) +METHOD(payload_t, get_length, size_t, + private_cert_payload_t *this) { return this->payload_length; } -/** - * Implementation of cert_payload_t.get_cert_encoding. - */ -static cert_encoding_t get_cert_encoding(private_cert_payload_t *this) +METHOD(cert_payload_t, get_cert_encoding, cert_encoding_t, + private_cert_payload_t *this) { return this->encoding; } -/** - * Implementation of cert_payload_t.get_cert. - */ -static certificate_t *get_cert(private_cert_payload_t *this) +METHOD(cert_payload_t, get_cert, certificate_t*, + private_cert_payload_t *this) { - if (this->encoding != ENC_X509_SIGNATURE) + int type; + + switch (this->encoding) { - return NULL; + case ENC_X509_SIGNATURE: + type = CERT_X509; + break; + case ENC_CRL: + type = CERT_X509_CRL; + break; + default: + return NULL; } - return lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, - BUILD_BLOB_ASN1_DER, this->data, - BUILD_END); + return lib->creds->create(lib->creds, CRED_CERTIFICATE, type, + BUILD_BLOB_ASN1_DER, this->data, BUILD_END); } -/** - * Implementation of cert_payload_t.get_hash. - */ -static chunk_t get_hash(private_cert_payload_t *this) +METHOD(cert_payload_t, get_hash, chunk_t, + private_cert_payload_t *this) { chunk_t hash = chunk_empty; + if ((this->encoding != ENC_X509_HASH_AND_URL && - this->encoding != ENC_X509_HASH_AND_URL_BUNDLE) || + this->encoding != ENC_X509_HASH_AND_URL_BUNDLE) || this->invalid_hash_and_url) { return hash; @@ -248,13 +239,11 @@ static chunk_t get_hash(private_cert_payload_t *this) return hash; } -/** - * Implementation of cert_payload_t.get_url. - */ -static char *get_url(private_cert_payload_t *this) +METHOD(cert_payload_t, get_url, char*, + private_cert_payload_t *this) { if ((this->encoding != ENC_X509_HASH_AND_URL && - this->encoding != ENC_X509_HASH_AND_URL_BUNDLE) || + this->encoding != ENC_X509_HASH_AND_URL_BUNDLE) || this->invalid_hash_and_url) { return NULL; @@ -262,12 +251,10 @@ static char *get_url(private_cert_payload_t *this) return (char*)this->data.ptr + 20; } -/** - * Implementation of payload_t.destroy and cert_payload_t.destroy. - */ -static void destroy(private_cert_payload_t *this) +METHOD2(payload_t, cert_payload_t, destroy, void, + private_cert_payload_t *this) { - chunk_free(&this->data); + free(this->data.ptr); free(this); } @@ -276,29 +263,28 @@ static void destroy(private_cert_payload_t *this) */ cert_payload_t *cert_payload_create() { - private_cert_payload_t *this = malloc_thing(private_cert_payload_t); - - this->public.payload_interface.verify = (status_t (*) (payload_t*))verify; - this->public.payload_interface.get_encoding_rules = (void (*) (payload_t*,encoding_rule_t**, size_t*))get_encoding_rules; - this->public.payload_interface.get_length = (size_t (*) (payload_t*))get_length; - this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t*))get_next_type; - this->public.payload_interface.set_next_type = (void (*) (payload_t*,payload_type_t))set_next_type; - this->public.payload_interface.get_type = (payload_type_t (*) (payload_t*))get_payload_type; - this->public.payload_interface.destroy = (void (*) (payload_t*))destroy; - - this->public.destroy = (void (*) (cert_payload_t*))destroy; - this->public.get_cert = (certificate_t* (*) (cert_payload_t*))get_cert; - this->public.get_cert_encoding = (cert_encoding_t (*) (cert_payload_t*))get_cert_encoding; - this->public.get_hash = (chunk_t (*) (cert_payload_t*))get_hash; - this->public.get_url = (char* (*) (cert_payload_t*))get_url; - - this->critical = FALSE; - this->next_payload = NO_PAYLOAD; - this->payload_length = CERT_PAYLOAD_HEADER_LENGTH; - this->data = chunk_empty; - this->encoding = 0; - this->invalid_hash_and_url = FALSE; - + private_cert_payload_t *this; + + INIT(this, + .public = { + .payload_interface = { + .verify = _verify, + .get_encoding_rules = _get_encoding_rules, + .get_length = _get_length, + .get_next_type = _get_next_type, + .set_next_type = _set_next_type, + .get_type = _get_type, + .destroy = _destroy, + }, + .get_cert = _get_cert, + .get_cert_encoding = _get_cert_encoding, + .get_hash = _get_hash, + .get_url = _get_url, + .destroy = _destroy, + }, + .next_payload = NO_PAYLOAD, + .payload_length = CERT_PAYLOAD_HEADER_LENGTH, + ); return &this->public; } @@ -343,3 +329,15 @@ cert_payload_t *cert_payload_create_from_hash_and_url(chunk_t hash, char *url) return &this->public; } +/* + * Described in header + */ +cert_payload_t *cert_payload_create_custom(cert_encoding_t type, chunk_t data) +{ + private_cert_payload_t *this = (private_cert_payload_t*)cert_payload_create(); + + this->encoding = type; + this->data = data; + this->payload_length = CERT_PAYLOAD_HEADER_LENGTH + this->data.len; + return &this->public; +} diff --git a/src/libcharon/encoding/payloads/cert_payload.h b/src/libcharon/encoding/payloads/cert_payload.h index aa1c7bf5a..21b503a40 100644 --- a/src/libcharon/encoding/payloads/cert_payload.h +++ b/src/libcharon/encoding/payloads/cert_payload.h @@ -134,4 +134,13 @@ cert_payload_t *cert_payload_create_from_cert(certificate_t *cert); */ cert_payload_t *cert_payload_create_from_hash_and_url(chunk_t hash, char *url); +/** + * Creates a custom certificate payload using type and associated data. + * + * @param type encoding type of certificate + * @param data associated data (gets owned) + * @return cert_payload_t object + */ +cert_payload_t *cert_payload_create_custom(cert_encoding_t type, chunk_t data); + #endif /** CERT_PAYLOAD_H_ @}*/ diff --git a/src/libcharon/encoding/payloads/certreq_payload.c b/src/libcharon/encoding/payloads/certreq_payload.c index 9ff0bdde0..8e0836f0e 100644 --- a/src/libcharon/encoding/payloads/certreq_payload.c +++ b/src/libcharon/encoding/payloads/certreq_payload.c @@ -1,5 +1,6 @@ /* - * Copyright (C) 2005-2006 Martin Willi + * Copyright (C) 2005-2010 Martin Willi + * Copyright (C) 2010 revosec AG * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil * @@ -22,14 +23,13 @@ #include "certreq_payload.h" - typedef struct private_certreq_payload_t private_certreq_payload_t; /** * Private data of an certreq_payload_t object. - * */ struct private_certreq_payload_t { + /** * Public certreq_payload_t interface. */ @@ -46,6 +46,11 @@ struct private_certreq_payload_t { bool critical; /** + * Reserved bits + */ + bool reserved[7]; + + /** * Length of this payload. */ u_int16_t payload_length; @@ -66,21 +71,20 @@ struct private_certreq_payload_t { * * The defined offsets are the positions in a object of type * private_certreq_payload_t. - * */ encoding_rule_t certreq_payload_encodings[] = { /* 1 Byte next payload type, stored in the field next_payload */ - { U_INT_8, offsetof(private_certreq_payload_t, next_payload) }, + { U_INT_8, offsetof(private_certreq_payload_t, next_payload) }, /* the critical bit */ - { FLAG, offsetof(private_certreq_payload_t, critical) }, - /* 7 Bit reserved bits, nowhere stored */ - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, + { FLAG, offsetof(private_certreq_payload_t, critical) }, + /* 7 Bit reserved bits */ + { RESERVED_BIT, offsetof(private_certreq_payload_t, reserved[0]) }, + { RESERVED_BIT, offsetof(private_certreq_payload_t, reserved[1]) }, + { RESERVED_BIT, offsetof(private_certreq_payload_t, reserved[2]) }, + { RESERVED_BIT, offsetof(private_certreq_payload_t, reserved[3]) }, + { RESERVED_BIT, offsetof(private_certreq_payload_t, reserved[4]) }, + { RESERVED_BIT, offsetof(private_certreq_payload_t, reserved[5]) }, + { RESERVED_BIT, offsetof(private_certreq_payload_t, reserved[6]) }, /* Length of the whole payload*/ { PAYLOAD_LENGTH, offsetof(private_certreq_payload_t, payload_length) }, /* 1 Byte CERTREQ type*/ @@ -102,10 +106,8 @@ encoding_rule_t certreq_payload_encodings[] = { +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ -/** - * Implementation of payload_t.verify. - */ -static status_t verify(private_certreq_payload_t *this) +METHOD(payload_t, verify, status_t, + private_certreq_payload_t *this) { if (this->encoding == ENC_X509_SIGNATURE) { @@ -120,51 +122,39 @@ static status_t verify(private_certreq_payload_t *this) return SUCCESS; } -/** - * Implementation of certreq_payload_t.get_encoding_rules. - */ -static void get_encoding_rules(private_certreq_payload_t *this, encoding_rule_t **rules, size_t *rule_count) +METHOD(payload_t, get_encoding_rules, void, + private_certreq_payload_t *this, encoding_rule_t **rules, size_t *rule_count) { *rules = certreq_payload_encodings; - *rule_count = sizeof(certreq_payload_encodings) / sizeof(encoding_rule_t); + *rule_count = countof(certreq_payload_encodings); } -/** - * Implementation of payload_t.get_type. - */ -static payload_type_t get_payload_type(private_certreq_payload_t *this) +METHOD(payload_t, get_type, payload_type_t, + private_certreq_payload_t *this) { return CERTIFICATE_REQUEST; } -/** - * Implementation of payload_t.get_next_type. - */ -static payload_type_t get_next_type(private_certreq_payload_t *this) +METHOD(payload_t, get_next_type, payload_type_t, + private_certreq_payload_t *this) { - return (this->next_payload); + return this->next_payload; } -/** - * Implementation of payload_t.set_next_type. - */ -static void set_next_type(private_certreq_payload_t *this,payload_type_t type) +METHOD(payload_t, set_next_type, void, + private_certreq_payload_t *this, payload_type_t type) { this->next_payload = type; } -/** - * Implementation of payload_t.get_length. - */ -static size_t get_length(private_certreq_payload_t *this) +METHOD(payload_t, get_length, size_t, + private_certreq_payload_t *this) { return this->payload_length; } -/** - * Implementation of certreq_payload_t.add_keyid. - */ -static void add_keyid(private_certreq_payload_t *this, chunk_t keyid) +METHOD(certreq_payload_t, add_keyid, void, + private_certreq_payload_t *this, chunk_t keyid) { this->data = chunk_cat("mc", this->data, keyid); this->payload_length += keyid.len; @@ -181,10 +171,8 @@ struct keyid_enumerator_t { u_char *pos; }; -/** - * enumerate function for keyid_enumerator - */ -static bool keyid_enumerate(keyid_enumerator_t *this, chunk_t *chunk) +METHOD(enumerator_t, keyid_enumerate, bool, + keyid_enumerator_t *this, chunk_t *chunk) { if (this->pos == NULL) { @@ -207,23 +195,23 @@ static bool keyid_enumerate(keyid_enumerator_t *this, chunk_t *chunk) return FALSE; } -/** - * Implementation of certreq_payload_t.create_keyid_enumerator. - */ -static enumerator_t* create_keyid_enumerator(private_certreq_payload_t *this) +METHOD(certreq_payload_t, create_keyid_enumerator, enumerator_t*, + private_certreq_payload_t *this) { - keyid_enumerator_t *enumerator = malloc_thing(keyid_enumerator_t); - enumerator->public.enumerate = (void*)keyid_enumerate; - enumerator->public.destroy = (void*)free; - enumerator->full = this->data; - enumerator->pos = NULL; + keyid_enumerator_t *enumerator; + + INIT(enumerator, + .public = { + .enumerate = (void*)_keyid_enumerate, + .destroy = (void*)free, + }, + .full = this->data, + ); return &enumerator->public; } -/** - * Implementation of certreq_payload_t.get_cert_type. - */ -static certificate_type_t get_cert_type(private_certreq_payload_t *this) +METHOD(certreq_payload_t, get_cert_type, certificate_type_t, + private_certreq_payload_t *this) { switch (this->encoding) { @@ -234,10 +222,8 @@ static certificate_type_t get_cert_type(private_certreq_payload_t *this) } } -/** - * Implementation of payload_t.destroy and certreq_payload_t.destroy. - */ -static void destroy(private_certreq_payload_t *this) +METHOD2(payload_t, certreq_payload_t, destroy, void, + private_certreq_payload_t *this) { chunk_free(&this->data); free(this); @@ -248,30 +234,27 @@ static void destroy(private_certreq_payload_t *this) */ certreq_payload_t *certreq_payload_create() { - private_certreq_payload_t *this = malloc_thing(private_certreq_payload_t); - - /* interface functions */ - this->public.payload_interface.verify = (status_t (*) (payload_t*))verify; - this->public.payload_interface.get_encoding_rules = (void (*) (payload_t*,encoding_rule_t**,size_t*))get_encoding_rules; - this->public.payload_interface.get_length = (size_t (*) (payload_t*))get_length; - this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t*))get_next_type; - this->public.payload_interface.set_next_type = (void (*) (payload_t*,payload_type_t))set_next_type; - this->public.payload_interface.get_type = (payload_type_t (*) (payload_t*))get_payload_type; - this->public.payload_interface.destroy = (void (*) (payload_t*))destroy; - - /* public functions */ - this->public.destroy = (void (*) (certreq_payload_t*)) destroy; - this->public.create_keyid_enumerator = (enumerator_t*(*)(certreq_payload_t*))create_keyid_enumerator; - this->public.get_cert_type = (certificate_type_t(*)(certreq_payload_t*))get_cert_type; - this->public.add_keyid = (void(*)(certreq_payload_t*, chunk_t keyid))add_keyid; - - /* private variables */ - this->critical = FALSE; - this->next_payload = NO_PAYLOAD; - this->payload_length = CERTREQ_PAYLOAD_HEADER_LENGTH; - this->data = chunk_empty; - this->encoding = 0; - + private_certreq_payload_t *this; + + INIT(this, + .public = { + .payload_interface = { + .verify = _verify, + .get_encoding_rules = _get_encoding_rules, + .get_length = _get_length, + .get_next_type = _get_next_type, + .set_next_type = _set_next_type, + .get_type = _get_type, + .destroy = _destroy, + }, + .create_keyid_enumerator = _create_keyid_enumerator, + .get_cert_type = _get_cert_type, + .add_keyid = _add_keyid, + .destroy = _destroy, + }, + .next_payload = NO_PAYLOAD, + .payload_length = CERTREQ_PAYLOAD_HEADER_LENGTH, + ); return &this->public; } diff --git a/src/libcharon/encoding/payloads/configuration_attribute.c b/src/libcharon/encoding/payloads/configuration_attribute.c index 9094fd44d..e608497bd 100644 --- a/src/libcharon/encoding/payloads/configuration_attribute.c +++ b/src/libcharon/encoding/payloads/configuration_attribute.c @@ -1,5 +1,6 @@ /* - * Copyright (C) 2005-2009 Martin Willi + * Copyright (C) 2005-2010 Martin Willi + * Copyright (C) 2010 revosec AG * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil * @@ -22,20 +23,24 @@ #include <library.h> #include <daemon.h> - typedef struct private_configuration_attribute_t private_configuration_attribute_t; /** * Private data of an configuration_attribute_t object. - * */ struct private_configuration_attribute_t { + /** * Public configuration_attribute_t interface. */ configuration_attribute_t public; /** + * Reserved bit + */ + bool reserved; + + /** * Type of the attribute. */ u_int16_t type; @@ -58,8 +63,8 @@ struct private_configuration_attribute_t { * private_configuration_attribute_t. */ encoding_rule_t configuration_attribute_encodings[] = { - - { RESERVED_BIT, 0 }, + /* 1 reserved bit */ + { RESERVED_BIT, offsetof(private_configuration_attribute_t, reserved)}, /* type of the attribute as 15 bit unsigned integer */ { ATTRIBUTE_TYPE, offsetof(private_configuration_attribute_t, type) }, /* Length of attribute value */ @@ -80,10 +85,8 @@ encoding_rule_t configuration_attribute_encodings[] = { +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ -/** - * Implementation of payload_t.verify. - */ -static status_t verify(private_configuration_attribute_t *this) +METHOD(payload_t, verify, status_t, + private_configuration_attribute_t *this) { bool failed = FALSE; @@ -151,69 +154,51 @@ static status_t verify(private_configuration_attribute_t *this) return SUCCESS; } -/** - * Implementation of payload_t.get_encoding_rules. - */ -static void get_encoding_rules(private_configuration_attribute_t *this, - encoding_rule_t **rules, size_t *rule_count) +METHOD(payload_t, get_encoding_rules, void, + private_configuration_attribute_t *this, encoding_rule_t **rules, + size_t *rule_count) { *rules = configuration_attribute_encodings; - *rule_count = sizeof(configuration_attribute_encodings) / sizeof(encoding_rule_t); + *rule_count = countof(configuration_attribute_encodings); } -/** - * Implementation of payload_t.get_type. - */ -static payload_type_t get_type(private_configuration_attribute_t *this) +METHOD(payload_t, get_type, payload_type_t, + private_configuration_attribute_t *this) { return CONFIGURATION_ATTRIBUTE; } -/** - * Implementation of payload_t.get_next_type. - */ -static payload_type_t get_next_type(private_configuration_attribute_t *this) +METHOD(payload_t, get_next_type, payload_type_t, + private_configuration_attribute_t *this) { return NO_PAYLOAD; } -/** - * Implementation of payload_t.set_next_type. - */ -static void set_next_type(private_configuration_attribute_t *this, - payload_type_t type) +METHOD(payload_t, set_next_type, void, + private_configuration_attribute_t *this, payload_type_t type) { } -/** - * Implementation of configuration_attribute_t.get_length. - */ -static size_t get_length(private_configuration_attribute_t *this) +METHOD(payload_t, get_length, size_t, + private_configuration_attribute_t *this) { return this->value.len + CONFIGURATION_ATTRIBUTE_HEADER_LENGTH; } -/** - * Implementation of configuration_attribute_t.get_type. - */ -static configuration_attribute_type_t get_configuration_attribute_type( - private_configuration_attribute_t *this) +METHOD(configuration_attribute_t, get_cattr_type, configuration_attribute_type_t, + private_configuration_attribute_t *this) { return this->type; } -/** - * Implementation of configuration_attribute_t.get_value. - */ -static chunk_t get_value(private_configuration_attribute_t *this) +METHOD(configuration_attribute_t, get_value, chunk_t, + private_configuration_attribute_t *this) { return this->value; } -/** - * Implementation of configuration_attribute_t.destroy and payload_t.destroy. - */ -static void destroy(private_configuration_attribute_t *this) +METHOD2(payload_t, configuration_attribute_t, destroy, void, + private_configuration_attribute_t *this) { free(this->value.ptr); free(this); @@ -226,23 +211,22 @@ configuration_attribute_t *configuration_attribute_create() { private_configuration_attribute_t *this; - this = malloc_thing(private_configuration_attribute_t); - this->public.payload_interface.verify = (status_t(*)(payload_t *))verify; - this->public.payload_interface.get_encoding_rules = (void(*)(payload_t *, encoding_rule_t **, size_t *) )get_encoding_rules; - this->public.payload_interface.get_length = (size_t(*)(payload_t *))get_length; - this->public.payload_interface.get_next_type = (payload_type_t(*)(payload_t *))get_next_type; - this->public.payload_interface.set_next_type = (void(*)(payload_t *,payload_type_t))set_next_type; - this->public.payload_interface.get_type = (payload_type_t(*)(payload_t *))get_type; - this->public.payload_interface.destroy = (void(*)(payload_t*))destroy; - - this->public.get_value = (chunk_t(*)(configuration_attribute_t *))get_value; - this->public.get_type = (configuration_attribute_type_t(*)(configuration_attribute_t *))get_configuration_attribute_type; - this->public.destroy = (void (*)(configuration_attribute_t*))destroy; - - this->type = 0; - this->value = chunk_empty; - this->length = 0; - + INIT(this, + .public = { + .payload_interface = { + .verify = _verify, + .get_encoding_rules = _get_encoding_rules, + .get_length = _get_length, + .get_next_type = _get_next_type, + .set_next_type = _set_next_type, + .get_type = _get_type, + .destroy = _destroy, + }, + .get_value = _get_value, + .get_type = _get_cattr_type, + .destroy = _destroy, + }, + ); return &this->public; } diff --git a/src/libcharon/encoding/payloads/cp_payload.c b/src/libcharon/encoding/payloads/cp_payload.c index f0a26eee2..82e9e51b7 100644 --- a/src/libcharon/encoding/payloads/cp_payload.c +++ b/src/libcharon/encoding/payloads/cp_payload.c @@ -1,5 +1,6 @@ /* - * Copyright (C) 2005-2009 Martin Willi + * Copyright (C) 2005-2010 Martin Willi + * Copyright (C) 2010 revosec AG * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil * @@ -32,9 +33,9 @@ typedef struct private_cp_payload_t private_cp_payload_t; /** * Private data of an cp_payload_t object. - * */ struct private_cp_payload_t { + /** * Public cp_payload_t interface. */ @@ -51,6 +52,16 @@ struct private_cp_payload_t { bool critical; /** + * Reserved bits + */ + bool reserved_bit[7]; + + /** + * Reserved bytes + */ + u_int8_t reserved_byte[3]; + + /** * Length of this payload. */ u_int16_t payload_length; @@ -71,30 +82,30 @@ struct private_cp_payload_t { * * The defined offsets are the positions in a object of type * private_cp_payload_t. - * */ encoding_rule_t cp_payload_encodings[] = { /* 1 Byte next payload type, stored in the field next_payload */ - { U_INT_8, offsetof(private_cp_payload_t, next_payload) }, + { U_INT_8, offsetof(private_cp_payload_t, next_payload) }, /* the critical bit */ - { FLAG, offsetof(private_cp_payload_t, critical) }, - /* 7 Bit reserved bits, nowhere stored */ - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, + { FLAG, offsetof(private_cp_payload_t, critical) }, + /* 7 Bit reserved bits */ + { RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[0]) }, + { RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[1]) }, + { RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[2]) }, + { RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[3]) }, + { RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[4]) }, + { RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[5]) }, + { RESERVED_BIT, offsetof(private_cp_payload_t, reserved_bit[6]) }, /* Length of the whole CP payload*/ - { PAYLOAD_LENGTH, offsetof(private_cp_payload_t, payload_length) }, + { PAYLOAD_LENGTH, offsetof(private_cp_payload_t, payload_length) }, /* Proposals are stored in a proposal substructure, offset points to a linked_list_t pointer */ - { U_INT_8, offsetof(private_cp_payload_t, type) }, - { RESERVED_BYTE,0 }, - { RESERVED_BYTE,0 }, - { RESERVED_BYTE,0 }, - { CONFIGURATION_ATTRIBUTES, offsetof(private_cp_payload_t, attributes) } + { U_INT_8, offsetof(private_cp_payload_t, type) }, + /* 3 reserved bytes */ + { RESERVED_BYTE, offsetof(private_cp_payload_t, reserved_byte[0])}, + { RESERVED_BYTE, offsetof(private_cp_payload_t, reserved_byte[1])}, + { RESERVED_BYTE, offsetof(private_cp_payload_t, reserved_byte[2])}, + { CONFIGURATION_ATTRIBUTES, offsetof(private_cp_payload_t, attributes) } }; /* @@ -111,10 +122,8 @@ encoding_rule_t cp_payload_encodings[] = { +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ -/** - * Implementation of payload_t.verify. - */ -static status_t verify(private_cp_payload_t *this) +METHOD(payload_t, verify, status_t, + private_cp_payload_t *this) { status_t status = SUCCESS; enumerator_t *enumerator; @@ -133,36 +142,27 @@ static status_t verify(private_cp_payload_t *this) return status; } -/** - * Implementation of payload_t.get_encoding_rules. - */ -static void get_encoding_rules(private_cp_payload_t *this, - encoding_rule_t **rules, size_t *rule_count) +METHOD(payload_t, get_encoding_rules, void, + private_cp_payload_t *this, encoding_rule_t **rules, size_t *rule_count) { *rules = cp_payload_encodings; - *rule_count = sizeof(cp_payload_encodings) / sizeof(encoding_rule_t); + *rule_count = countof(cp_payload_encodings); } -/** - * Implementation of payload_t.get_type. - */ -static payload_type_t get_type(private_cp_payload_t *this) +METHOD(payload_t, get_type, payload_type_t, + private_cp_payload_t *this) { return CONFIGURATION; } -/** - * Implementation of payload_t.get_next_type. - */ -static payload_type_t get_next_type(private_cp_payload_t *this) +METHOD(payload_t, get_next_type, payload_type_t, + private_cp_payload_t *this) { return this->next_payload; } -/** - * Implementation of payload_t.set_next_type. - */ -static void set_next_type(private_cp_payload_t *this,payload_type_t type) +METHOD(payload_t, set_next_type, void, + private_cp_payload_t *this,payload_type_t type) { this->next_payload = type; } @@ -185,44 +185,33 @@ static void compute_length(private_cp_payload_t *this) enumerator->destroy(enumerator); } -/** - * Implementation of payload_t.get_length. - */ -static size_t get_length(private_cp_payload_t *this) +METHOD(payload_t, get_length, size_t, + private_cp_payload_t *this) { return this->payload_length; } -/** - * Implementation of cp_payload_t.create_attribute_enumerator. - */ -static enumerator_t *create_attribute_enumerator(private_cp_payload_t *this) +METHOD(cp_payload_t, create_attribute_enumerator, enumerator_t*, + private_cp_payload_t *this) { return this->attributes->create_enumerator(this->attributes); } -/** - * Implementation of cp_payload_t.add_attribute. - */ -static void add_attribute(private_cp_payload_t *this, - configuration_attribute_t *attribute) +METHOD(cp_payload_t, add_attribute, void, + private_cp_payload_t *this, configuration_attribute_t *attribute) { this->attributes->insert_last(this->attributes, attribute); compute_length(this); } -/** - * Implementation of cp_payload_t.get_type. - */ -static config_type_t get_config_type(private_cp_payload_t *this) +METHOD(cp_payload_t, get_config_type, config_type_t, + private_cp_payload_t *this) { return this->type; } -/** - * Implementation of payload_t.destroy and cp_payload_t.destroy. - */ -static void destroy(private_cp_payload_t *this) +METHOD2(payload_t, cp_payload_t, destroy, void, + private_cp_payload_t *this) { this->attributes->destroy_offset(this->attributes, offsetof(configuration_attribute_t, destroy)); @@ -232,42 +221,38 @@ static void destroy(private_cp_payload_t *this) /* * Described in header. */ -cp_payload_t *cp_payload_create() +cp_payload_t *cp_payload_create_type(config_type_t type) { - private_cp_payload_t *this = malloc_thing(private_cp_payload_t); - - this->public.payload_interface.verify = (status_t (*) (payload_t *))verify; - this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules; - this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length; - this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type; - this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type; - this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type; - this->public.payload_interface.destroy = (void (*) (payload_t *))destroy; - - this->public.create_attribute_enumerator = (enumerator_t*(*)(cp_payload_t *))create_attribute_enumerator; - this->public.add_attribute = (void (*) (cp_payload_t *,configuration_attribute_t*))add_attribute; - this->public.get_type = (config_type_t (*) (cp_payload_t *))get_config_type; - this->public.destroy = (void (*)(cp_payload_t *))destroy; - - /* set default values of the fields */ - this->critical = FALSE; - this->next_payload = NO_PAYLOAD; - this->payload_length = CP_PAYLOAD_HEADER_LENGTH; - this->attributes = linked_list_create(); - this->type = CFG_REQUEST; - + private_cp_payload_t *this; + + INIT(this, + .public = { + .payload_interface = { + .verify = _verify, + .get_encoding_rules = _get_encoding_rules, + .get_length = _get_length, + .get_next_type = _get_next_type, + .set_next_type = _set_next_type, + .get_type = _get_type, + .destroy = _destroy, + }, + .create_attribute_enumerator = _create_attribute_enumerator, + .add_attribute = _add_attribute, + .get_type = _get_config_type, + .destroy = _destroy, + }, + .next_payload = NO_PAYLOAD, + .payload_length = CP_PAYLOAD_HEADER_LENGTH, + .attributes = linked_list_create(), + .type = type, + ); return &this->public; } /* * Described in header. */ -cp_payload_t *cp_payload_create_type(config_type_t type) +cp_payload_t *cp_payload_create() { - private_cp_payload_t *this = (private_cp_payload_t*)cp_payload_create(); - - this->type = type; - - return &this->public; + return cp_payload_create_type(CFG_REQUEST); } - diff --git a/src/libcharon/encoding/payloads/delete_payload.c b/src/libcharon/encoding/payloads/delete_payload.c index 5fc3b7c88..e6ee07d39 100644 --- a/src/libcharon/encoding/payloads/delete_payload.c +++ b/src/libcharon/encoding/payloads/delete_payload.c @@ -43,6 +43,11 @@ struct private_delete_payload_t { bool critical; /** + * reserved bits + */ + bool reserved[7]; + + /** * Length of this payload. */ u_int16_t payload_length; @@ -79,14 +84,14 @@ encoding_rule_t delete_payload_encodings[] = { { U_INT_8, offsetof(private_delete_payload_t, next_payload) }, /* the critical bit */ { FLAG, offsetof(private_delete_payload_t, critical) }, - /* 7 Bit reserved bits, nowhere stored */ - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, + /* 7 Bit reserved bits */ + { RESERVED_BIT, offsetof(private_delete_payload_t, reserved[0]) }, + { RESERVED_BIT, offsetof(private_delete_payload_t, reserved[1]) }, + { RESERVED_BIT, offsetof(private_delete_payload_t, reserved[2]) }, + { RESERVED_BIT, offsetof(private_delete_payload_t, reserved[3]) }, + { RESERVED_BIT, offsetof(private_delete_payload_t, reserved[4]) }, + { RESERVED_BIT, offsetof(private_delete_payload_t, reserved[5]) }, + { RESERVED_BIT, offsetof(private_delete_payload_t, reserved[6]) }, /* Length of the whole payload*/ { PAYLOAD_LENGTH, offsetof(private_delete_payload_t, payload_length) }, { U_INT_8, offsetof(private_delete_payload_t, protocol_id) }, diff --git a/src/libcharon/encoding/payloads/eap_payload.c b/src/libcharon/encoding/payloads/eap_payload.c index 21f34a642..eafb668b6 100644 --- a/src/libcharon/encoding/payloads/eap_payload.c +++ b/src/libcharon/encoding/payloads/eap_payload.c @@ -43,6 +43,11 @@ struct private_eap_payload_t { bool critical; /** + * Reserved bits + */ + bool reserved[7]; + + /** * Length of this payload. */ u_int16_t payload_length; @@ -66,13 +71,13 @@ static encoding_rule_t eap_payload_encodings[] = { /* the critical bit */ { FLAG, offsetof(private_eap_payload_t, critical) }, /* 7 Bit reserved bits, nowhere stored */ - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, + { RESERVED_BIT, offsetof(private_eap_payload_t, reserved[0]) }, + { RESERVED_BIT, offsetof(private_eap_payload_t, reserved[1]) }, + { RESERVED_BIT, offsetof(private_eap_payload_t, reserved[2]) }, + { RESERVED_BIT, offsetof(private_eap_payload_t, reserved[3]) }, + { RESERVED_BIT, offsetof(private_eap_payload_t, reserved[4]) }, + { RESERVED_BIT, offsetof(private_eap_payload_t, reserved[5]) }, + { RESERVED_BIT, offsetof(private_eap_payload_t, reserved[6]) }, /* Length of the whole payload*/ { PAYLOAD_LENGTH, offsetof(private_eap_payload_t, payload_length) }, /* chunt to data, starting at "code" */ diff --git a/src/libcharon/encoding/payloads/id_payload.c b/src/libcharon/encoding/payloads/id_payload.c index 4158c3e07..3befadfe2 100644 --- a/src/libcharon/encoding/payloads/id_payload.c +++ b/src/libcharon/encoding/payloads/id_payload.c @@ -1,6 +1,7 @@ /* + * Copyright (C) 2005-2010 Martin Willi + * Copyright (C) 2010 revosec AG * Copyright (C) 2007 Tobias Brunner - * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter * * Hochschule fuer Technik Rapperswil @@ -51,6 +52,16 @@ struct private_id_payload_t { bool critical; /** + * Reserved bits + */ + bool reserved_bit[7]; + + /** + * Reserved bytes + */ + u_int8_t reserved_byte[3]; + + /** * Length of this payload. */ u_int16_t payload_length; @@ -71,31 +82,30 @@ struct private_id_payload_t { * * The defined offsets are the positions in a object of type * private_id_payload_t. - * */ encoding_rule_t id_payload_encodings[] = { /* 1 Byte next payload type, stored in the field next_payload */ { U_INT_8, offsetof(private_id_payload_t, next_payload) }, /* the critical bit */ { FLAG, offsetof(private_id_payload_t, critical) }, - /* 7 Bit reserved bits, nowhere stored */ - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, + /* 7 Bit reserved bits */ + { RESERVED_BIT, offsetof(private_id_payload_t, reserved_bit[0]) }, + { RESERVED_BIT, offsetof(private_id_payload_t, reserved_bit[1]) }, + { RESERVED_BIT, offsetof(private_id_payload_t, reserved_bit[2]) }, + { RESERVED_BIT, offsetof(private_id_payload_t, reserved_bit[3]) }, + { RESERVED_BIT, offsetof(private_id_payload_t, reserved_bit[4]) }, + { RESERVED_BIT, offsetof(private_id_payload_t, reserved_bit[5]) }, + { RESERVED_BIT, offsetof(private_id_payload_t, reserved_bit[6]) }, /* Length of the whole payload*/ { PAYLOAD_LENGTH, offsetof(private_id_payload_t, payload_length) }, /* 1 Byte ID type*/ { U_INT_8, offsetof(private_id_payload_t, id_type) }, /* 3 reserved bytes */ - { RESERVED_BYTE, 0 }, - { RESERVED_BYTE, 0 }, - { RESERVED_BYTE, 0 }, + { RESERVED_BYTE, offsetof(private_id_payload_t, reserved_byte[0])}, + { RESERVED_BYTE, offsetof(private_id_payload_t, reserved_byte[1])}, + { RESERVED_BYTE, offsetof(private_id_payload_t, reserved_byte[2])}, /* some id data bytes, length is defined in PAYLOAD_LENGTH */ - { ID_DATA, offsetof(private_id_payload_t, id_data) } + { ID_DATA, offsetof(private_id_payload_t, id_data) } }; /* @@ -112,136 +122,59 @@ encoding_rule_t id_payload_encodings[] = { +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ -/** - * Implementation of payload_t.verify. - */ -static status_t verify(private_id_payload_t *this) +METHOD(payload_t, verify, status_t, + private_id_payload_t *this) { - if ((this->id_type == 0) || - (this->id_type == 4) || - ((this->id_type >= 6) && (this->id_type <= 8)) || - ((this->id_type >= 12) && (this->id_type <= 200))) + if (this->id_type == 0 || this->id_type == 4) { /* reserved IDs */ DBG1(DBG_ENC, "received ID with reserved type %d", this->id_type); return FAILED; } - return SUCCESS; } -/** - * Implementation of id_payload_t.get_encoding_rules. - */ -static void get_encoding_rules(private_id_payload_t *this, encoding_rule_t **rules, size_t *rule_count) +METHOD(payload_t, get_encoding_rules, void, + private_id_payload_t *this, encoding_rule_t **rules, size_t *rule_count) { *rules = id_payload_encodings; - *rule_count = sizeof(id_payload_encodings) / sizeof(encoding_rule_t); + *rule_count = countof(id_payload_encodings); } -/** - * Implementation of payload_t.get_type. - */ -static payload_type_t get_payload_type(private_id_payload_t *this) +METHOD(payload_t, get_type, payload_type_t, + private_id_payload_t *this) { return this->payload_type; } -/** - * Implementation of payload_t.get_next_type. - */ -static payload_type_t get_next_type(private_id_payload_t *this) +METHOD(payload_t, get_next_type, payload_type_t, + private_id_payload_t *this) { return this->next_payload; } -/** - * Implementation of payload_t.set_next_type. - */ -static void set_next_type(private_id_payload_t *this,payload_type_t type) +METHOD(payload_t, set_next_type, void, + private_id_payload_t *this, payload_type_t type) { this->next_payload = type; } -/** - * Implementation of payload_t.get_length. - */ -static size_t get_length(private_id_payload_t *this) +METHOD(payload_t, get_length, size_t, + private_id_payload_t *this) { return this->payload_length; } -/** - * Implementation of id_payload_t.set_type. - */ -static void set_id_type (private_id_payload_t *this, id_type_t type) -{ - this->id_type = type; -} - -/** - * Implementation of id_payload_t.get_id_type. - */ -static id_type_t get_id_type (private_id_payload_t *this) +METHOD(id_payload_t, get_identification, identification_t*, + private_id_payload_t *this) { - return (this->id_type); + return identification_create_from_encoding(this->id_type, this->id_data); } -/** - * Implementation of id_payload_t.set_data. - */ -static void set_data (private_id_payload_t *this, chunk_t data) +METHOD2(payload_t, id_payload_t, destroy, void, + private_id_payload_t *this) { - if (this->id_data.ptr != NULL) - { - chunk_free(&(this->id_data)); - } - this->id_data.ptr = clalloc(data.ptr,data.len); - this->id_data.len = data.len; - this->payload_length = ID_PAYLOAD_HEADER_LENGTH + this->id_data.len; -} - - -/** - * Implementation of id_payload_t.get_data_clone. - */ -static chunk_t get_data (private_id_payload_t *this) -{ - return (this->id_data); -} - -/** - * Implementation of id_payload_t.get_data_clone. - */ -static chunk_t get_data_clone (private_id_payload_t *this) -{ - chunk_t cloned_data; - if (this->id_data.ptr == NULL) - { - return (this->id_data); - } - cloned_data.ptr = clalloc(this->id_data.ptr,this->id_data.len); - cloned_data.len = this->id_data.len; - return cloned_data; -} - -/** - * Implementation of id_payload_t.get_identification. - */ -static identification_t *get_identification (private_id_payload_t *this) -{ - return identification_create_from_encoding(this->id_type,this->id_data); -} - -/** - * Implementation of payload_t.destroy and id_payload_t.destroy. - */ -static void destroy(private_id_payload_t *this) -{ - if (this->id_data.ptr != NULL) - { - chunk_free(&(this->id_data)); - } + free(this->id_data.ptr); free(this); } @@ -250,44 +183,41 @@ static void destroy(private_id_payload_t *this) */ id_payload_t *id_payload_create(payload_type_t payload_type) { - private_id_payload_t *this = malloc_thing(private_id_payload_t); - - /* interface functions */ - this->public.payload_interface.verify = (status_t (*) (payload_t *))verify; - this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules; - this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length; - this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type; - this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type; - this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_payload_type; - this->public.payload_interface.destroy = (void (*) (payload_t *))destroy; - - /* public functions */ - this->public.destroy = (void (*) (id_payload_t *)) destroy; - this->public.set_id_type = (void (*) (id_payload_t *,id_type_t)) set_id_type; - this->public.get_id_type = (id_type_t (*) (id_payload_t *)) get_id_type; - this->public.set_data = (void (*) (id_payload_t *,chunk_t)) set_data; - this->public.get_data = (chunk_t (*) (id_payload_t *)) get_data; - this->public.get_data_clone = (chunk_t (*) (id_payload_t *)) get_data_clone; - - this->public.get_identification = (identification_t * (*) (id_payload_t *this)) get_identification; - - /* private variables */ - this->critical = FALSE; - this->next_payload = NO_PAYLOAD; - this->payload_length =ID_PAYLOAD_HEADER_LENGTH; - this->id_data = chunk_empty; - this->payload_type = payload_type; - - return (&(this->public)); + private_id_payload_t *this; + + INIT(this, + .public = { + .payload_interface = { + .verify = _verify, + .get_encoding_rules = _get_encoding_rules, + .get_length = _get_length, + .get_next_type = _get_next_type, + .set_next_type = _set_next_type, + .get_type = _get_type, + .destroy = _destroy, + }, + .get_identification = _get_identification, + .destroy = _destroy, + }, + .next_payload = NO_PAYLOAD, + .payload_length = ID_PAYLOAD_HEADER_LENGTH, + .payload_type = payload_type, + ); + return &this->public; } /* * Described in header. */ -id_payload_t *id_payload_create_from_identification(payload_type_t payload_type, identification_t *identification) +id_payload_t *id_payload_create_from_identification(payload_type_t payload_type, + identification_t *id) { - id_payload_t *this= id_payload_create(payload_type); - this->set_data(this,identification->get_encoding(identification)); - this->set_id_type(this,identification->get_type(identification)); - return this; + private_id_payload_t *this; + + this = (private_id_payload_t*)id_payload_create(payload_type); + this->id_data = chunk_clone(id->get_encoding(id)); + this->id_type = id->get_type(id); + this->payload_length += this->id_data.len; + + return &this->public; } diff --git a/src/libcharon/encoding/payloads/id_payload.h b/src/libcharon/encoding/payloads/id_payload.h index 5502dc961..99831f85f 100644 --- a/src/libcharon/encoding/payloads/id_payload.h +++ b/src/libcharon/encoding/payloads/id_payload.h @@ -40,57 +40,15 @@ typedef struct id_payload_t id_payload_t; * The ID payload format is described in RFC section 3.5. */ struct id_payload_t { + /** * The payload_t interface. */ payload_t payload_interface; /** - * Set the ID type. - * - * @param type Type of ID - */ - void (*set_id_type) (id_payload_t *this, id_type_t type); - - /** - * Get the ID type. - * - * @return type of the ID - */ - id_type_t (*get_id_type) (id_payload_t *this); - - /** - * Set the ID data. - * - * Data are getting cloned. - * - * @param data ID data as chunk_t - */ - void (*set_data) (id_payload_t *this, chunk_t data); - - /** - * Get the ID data. - * - * Returned data are a copy of the internal one - * - * @return ID data as chunk_t - */ - chunk_t (*get_data_clone) (id_payload_t *this); - - /** - * Get the ID data. - * - * Returned data are NOT copied. - * - * @return ID data as chunk_t - */ - chunk_t (*get_data) (id_payload_t *this); - - /** * Creates an identification object of this id payload. * - * Returned object has to get destroyed by the caller. - * * @return identification_t object */ identification_t *(*get_identification) (id_payload_t *this); diff --git a/src/libcharon/encoding/payloads/ike_header.c b/src/libcharon/encoding/payloads/ike_header.c index 735f01304..80dcee0cb 100644 --- a/src/libcharon/encoding/payloads/ike_header.c +++ b/src/libcharon/encoding/payloads/ike_header.c @@ -84,6 +84,11 @@ struct private_ike_header_t { } flags; /** + * Reserved bits of IKE header + */ + bool reserved[5]; + + /** * Associated Message-ID. */ u_int32_t message_id; @@ -119,30 +124,30 @@ encoding_rule_t ike_header_encodings[] = { /* 8 Byte SPI, stored in the field initiator_spi */ { IKE_SPI, offsetof(private_ike_header_t, initiator_spi) }, /* 8 Byte SPI, stored in the field responder_spi */ - { IKE_SPI, offsetof(private_ike_header_t, responder_spi) }, + { IKE_SPI, offsetof(private_ike_header_t, responder_spi) }, /* 1 Byte next payload type, stored in the field next_payload */ - { U_INT_8, offsetof(private_ike_header_t, next_payload) }, + { U_INT_8, offsetof(private_ike_header_t, next_payload) }, /* 4 Bit major version, stored in the field maj_version */ - { U_INT_4, offsetof(private_ike_header_t, maj_version) }, + { U_INT_4, offsetof(private_ike_header_t, maj_version) }, /* 4 Bit minor version, stored in the field min_version */ - { U_INT_4, offsetof(private_ike_header_t, min_version) }, + { U_INT_4, offsetof(private_ike_header_t, min_version) }, /* 8 Bit for the exchange type */ - { U_INT_8, offsetof(private_ike_header_t, exchange_type) }, - /* 2 Bit reserved bits, nowhere stored */ - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, + { U_INT_8, offsetof(private_ike_header_t, exchange_type) }, + /* 2 Bit reserved bits */ + { RESERVED_BIT, offsetof(private_ike_header_t, reserved[0]) }, + { RESERVED_BIT, offsetof(private_ike_header_t, reserved[1]) }, /* 3 Bit flags, stored in the fields response, version and initiator */ - { FLAG, offsetof(private_ike_header_t, flags.response) }, - { FLAG, offsetof(private_ike_header_t, flags.version) }, - { FLAG, offsetof(private_ike_header_t, flags.initiator) }, - /* 3 Bit reserved bits, nowhere stored */ - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, + { FLAG, offsetof(private_ike_header_t, flags.response) }, + { FLAG, offsetof(private_ike_header_t, flags.version) }, + { FLAG, offsetof(private_ike_header_t, flags.initiator) }, + /* 3 Bit reserved bits */ + { RESERVED_BIT, offsetof(private_ike_header_t, reserved[2]) }, + { RESERVED_BIT, offsetof(private_ike_header_t, reserved[3]) }, + { RESERVED_BIT, offsetof(private_ike_header_t, reserved[4]) }, /* 4 Byte message id, stored in the field message_id */ - { U_INT_32, offsetof(private_ike_header_t, message_id) }, + { U_INT_32, offsetof(private_ike_header_t, message_id) }, /* 4 Byte length fied, stored in the field length */ - { HEADER_LENGTH, offsetof(private_ike_header_t, length) } + { HEADER_LENGTH,offsetof(private_ike_header_t, length) }, }; @@ -163,11 +168,8 @@ encoding_rule_t ike_header_encodings[] = { +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ - -/** - * Implementation of payload_t.verify. - */ -static status_t verify(private_ike_header_t *this) +METHOD(payload_t, verify, status_t, + private_ike_header_t *this) { if ((this->exchange_type < IKE_SA_INIT) || ((this->exchange_type > INFORMATIONAL) @@ -179,7 +181,6 @@ static status_t verify(private_ike_header_t *this) /* unsupported exchange type */ return FAILED; } - if (this->initiator_spi == 0 #ifdef ME /* we allow zero spi for INFORMATIONAL exchanges, @@ -191,225 +192,201 @@ static status_t verify(private_ike_header_t *this) /* initiator spi not set */ return FAILED; } + return SUCCESS; +} - /* verification of version is not done in here */ +METHOD(payload_t, get_encoding_rules, void, + private_ike_header_t *this, encoding_rule_t **rules, size_t *rule_count) +{ + *rules = ike_header_encodings; + *rule_count = sizeof(ike_header_encodings) / sizeof(encoding_rule_t); +} - return SUCCESS; +METHOD(payload_t, get_type, payload_type_t, + private_ike_header_t *this) +{ + return HEADER; } -/** - * Implementation of payload_t.set_next_type. - */ -static void set_next_type(payload_t *this,payload_type_t type) +METHOD(payload_t, get_next_type, payload_type_t, + private_ike_header_t *this) { - ((private_ike_header_t *)this)->next_payload = type; + return this->next_payload; } -/** - * Implementation of ike_header_t.get_initiator_spi. - */ -static u_int64_t get_initiator_spi(private_ike_header_t *this) + +METHOD(payload_t, set_next_type, void, + private_ike_header_t *this, payload_type_t type) +{ + this->next_payload = type; +} + +METHOD(payload_t, get_length, size_t, + private_ike_header_t *this) +{ + return this->length; +} + +METHOD(ike_header_t, get_initiator_spi, u_int64_t, + private_ike_header_t *this) { return this->initiator_spi; } -/** - * Implementation of ike_header_t.set_initiator_spi. - */ -static void set_initiator_spi(private_ike_header_t *this, u_int64_t initiator_spi) +METHOD(ike_header_t, set_initiator_spi, void, + private_ike_header_t *this, u_int64_t initiator_spi) { this->initiator_spi = initiator_spi; } -/** - * Implementation of ike_header_t.get_responder_spi. - */ -static u_int64_t get_responder_spi(private_ike_header_t *this) +METHOD(ike_header_t, get_responder_spi, u_int64_t, + private_ike_header_t *this) { return this->responder_spi; } -/** - * Implementation of ike_header_t.set_responder_spi. - */ -static void set_responder_spi(private_ike_header_t *this, u_int64_t responder_spi) +METHOD(ike_header_t, set_responder_spi, void, + private_ike_header_t *this, u_int64_t responder_spi) { this->responder_spi = responder_spi; } -/** - * Implementation of ike_header_t.get_maj_version. - */ -static u_int8_t get_maj_version(private_ike_header_t *this) +METHOD(ike_header_t, get_maj_version, u_int8_t, + private_ike_header_t *this) { return this->maj_version; } -/** - * Implementation of ike_header_t.get_min_version. - */ -static u_int8_t get_min_version(private_ike_header_t *this) +METHOD(ike_header_t, set_maj_version, void, + private_ike_header_t *this, u_int8_t major) +{ + this->maj_version = major; +} + +METHOD(ike_header_t, get_min_version, u_int8_t, + private_ike_header_t *this) { return this->min_version; } -/** - * Implementation of ike_header_t.get_response_flag. - */ -static bool get_response_flag(private_ike_header_t *this) +METHOD(ike_header_t, set_min_version, void, + private_ike_header_t *this, u_int8_t minor) +{ + this->min_version = minor; +} + +METHOD(ike_header_t, get_response_flag, bool, + private_ike_header_t *this) { return this->flags.response; } -/** - * Implementation of ike_header_t.set_response_flag. - */ -static void set_response_flag(private_ike_header_t *this, bool response) +METHOD(ike_header_t, set_response_flag, void, + private_ike_header_t *this, bool response) { this->flags.response = response; } -/** - * Implementation of ike_header_t.get_version_flag. - */ -static bool get_version_flag(private_ike_header_t *this) +METHOD(ike_header_t, get_version_flag, bool, + private_ike_header_t *this) { return this->flags.version; } -/** - * Implementation of ike_header_t.get_initiator_flag. - */ -static bool get_initiator_flag(private_ike_header_t *this) +METHOD(ike_header_t, set_version_flag, void, + private_ike_header_t *this, bool version) +{ + this->flags.version = version; +} + +METHOD(ike_header_t, get_initiator_flag, bool, + private_ike_header_t *this) { return this->flags.initiator; } -/** - * Implementation of ike_header_t.set_initiator_flag. - */ -static void set_initiator_flag(private_ike_header_t *this, bool initiator) +METHOD(ike_header_t, set_initiator_flag, void, + private_ike_header_t *this, bool initiator) { this->flags.initiator = initiator; } -/** - * Implementation of ike_header_t.get_exchange_type. - */ -static u_int8_t get_exchange_type(private_ike_header_t *this) +METHOD(ike_header_t, get_exchange_type, u_int8_t, + private_ike_header_t *this) { return this->exchange_type; } -/** - * Implementation of ike_header_t.set_exchange_type. - */ -static void set_exchange_type(private_ike_header_t *this, u_int8_t exchange_type) +METHOD(ike_header_t, set_exchange_type, void, + private_ike_header_t *this, u_int8_t exchange_type) { this->exchange_type = exchange_type; } -/** - * Implements ike_header_t's get_message_id function. - * See #ike_header_t.get_message_id for description. - */ -static u_int32_t get_message_id(private_ike_header_t *this) +METHOD(ike_header_t, get_message_id, u_int32_t, + private_ike_header_t *this) { return this->message_id; } -/** - * Implementation of ike_header_t.set_message_id. - */ -static void set_message_id(private_ike_header_t *this, u_int32_t message_id) +METHOD(ike_header_t, set_message_id, void, + private_ike_header_t *this, u_int32_t message_id) { this->message_id = message_id; } -/** - * Implementation of ike_header_t.destroy and payload_t.destroy. - */ -static void destroy(ike_header_t *this) +METHOD2(payload_t, ike_header_t, destroy, void, + private_ike_header_t *this) { free(this); } -/** - * Implementation of payload_t.get_encoding_rules. - */ -static void get_encoding_rules(payload_t *this, encoding_rule_t **rules, size_t *rule_count) -{ - *rules = ike_header_encodings; - *rule_count = sizeof(ike_header_encodings) / sizeof(encoding_rule_t); -} - -/** - * Implementation of payload_t.get_type. - */ -static payload_type_t get_type(payload_t *this) -{ - return HEADER; -} - -/** - * Implementation of payload_t.get_next_type. - */ -static payload_type_t get_next_type(payload_t *this) -{ - return (((private_ike_header_t*)this)->next_payload); -} - -/** - * Implementation of payload_t.get_length. - */ -static size_t get_length(payload_t *this) -{ - return (((private_ike_header_t*)this)->length); -} - /* * Described in header. */ ike_header_t *ike_header_create() { - private_ike_header_t *this = malloc_thing(private_ike_header_t); - - this->public.payload_interface.verify = (status_t (*) (payload_t *))verify; - this->public.payload_interface.get_encoding_rules = get_encoding_rules; - this->public.payload_interface.get_length = get_length; - this->public.payload_interface.get_next_type = get_next_type; - this->public.payload_interface.set_next_type = set_next_type; - this->public.payload_interface.get_type = get_type; - this->public.payload_interface.destroy = (void (*) (payload_t *))destroy; - this->public.destroy = destroy; - - this->public.get_initiator_spi = (u_int64_t (*) (ike_header_t*))get_initiator_spi; - this->public.set_initiator_spi = (void (*) (ike_header_t*,u_int64_t))set_initiator_spi; - this->public.get_responder_spi = (u_int64_t (*) (ike_header_t*))get_responder_spi; - this->public.set_responder_spi = (void (*) (ike_header_t *,u_int64_t))set_responder_spi; - this->public.get_maj_version = (u_int8_t (*) (ike_header_t*))get_maj_version; - this->public.get_min_version = (u_int8_t (*) (ike_header_t*))get_min_version; - this->public.get_response_flag = (bool (*) (ike_header_t*))get_response_flag; - this->public.set_response_flag = (void (*) (ike_header_t*,bool))set_response_flag; - this->public.get_version_flag = (bool (*) (ike_header_t*))get_version_flag; - this->public.get_initiator_flag = (bool (*) (ike_header_t*))get_initiator_flag; - this->public.set_initiator_flag = (void (*) (ike_header_t*,bool))set_initiator_flag; - this->public.get_exchange_type = (u_int8_t (*) (ike_header_t*))get_exchange_type; - this->public.set_exchange_type = (void (*) (ike_header_t*,u_int8_t))set_exchange_type; - this->public.get_message_id = (u_int32_t (*) (ike_header_t*))get_message_id; - this->public.set_message_id = (void (*) (ike_header_t*,u_int32_t))set_message_id; - - /* set default values of the fields */ - this->initiator_spi = 0; - this->responder_spi = 0; - this->next_payload = 0; - this->maj_version = IKE_MAJOR_VERSION; - this->min_version = IKE_MINOR_VERSION; - this->exchange_type = EXCHANGE_TYPE_UNDEFINED; - this->flags.initiator = TRUE; - this->flags.version = HIGHER_VERSION_SUPPORTED_FLAG; - this->flags.response = FALSE; - this->message_id = 0; - this->length = IKE_HEADER_LENGTH; - - return (ike_header_t*)this; + private_ike_header_t *this; + + INIT(this, + .public = { + .payload_interface = { + .verify = _verify, + .get_encoding_rules = _get_encoding_rules, + .get_length = _get_length, + .get_next_type = _get_next_type, + .set_next_type = _set_next_type, + .get_type = _get_type, + .destroy = _destroy, + }, + .get_initiator_spi = _get_initiator_spi, + .set_initiator_spi = _set_initiator_spi, + .get_responder_spi = _get_responder_spi, + .set_responder_spi = _set_responder_spi, + .get_maj_version = _get_maj_version, + .set_maj_version = _set_maj_version, + .get_min_version = _get_min_version, + .set_min_version = _set_min_version, + .get_response_flag = _get_response_flag, + .set_response_flag = _set_response_flag, + .get_version_flag = _get_version_flag, + .set_version_flag = _set_version_flag, + .get_initiator_flag = _get_initiator_flag, + .set_initiator_flag = _set_initiator_flag, + .get_exchange_type = _get_exchange_type, + .set_exchange_type = _set_exchange_type, + .get_message_id = _get_message_id, + .set_message_id = _set_message_id, + .destroy = _destroy, + }, + .maj_version = IKE_MAJOR_VERSION, + .min_version = IKE_MINOR_VERSION, + .exchange_type = EXCHANGE_TYPE_UNDEFINED, + .flags = { + .initiator = TRUE, + .version = HIGHER_VERSION_SUPPORTED_FLAG, + }, + .length = IKE_HEADER_LENGTH, + ); + + return &this->public; } diff --git a/src/libcharon/encoding/payloads/ike_header.h b/src/libcharon/encoding/payloads/ike_header.h index e63e8bf06..f52c852c5 100644 --- a/src/libcharon/encoding/payloads/ike_header.h +++ b/src/libcharon/encoding/payloads/ike_header.h @@ -143,6 +143,13 @@ struct ike_header_t { u_int8_t (*get_maj_version) (ike_header_t *this); /** + * Set the major version. + * + * @param major major version + */ + void (*set_maj_version) (ike_header_t *this, u_int8_t major); + + /** * Get the minor version. * * @return minor version @@ -150,6 +157,13 @@ struct ike_header_t { u_int8_t (*get_min_version) (ike_header_t *this); /** + * Set the minor version. + * + * @param minor minor version + */ + void (*set_min_version) (ike_header_t *this, u_int8_t minor); + + /** * Get the response flag. * * @return response flag @@ -162,6 +176,7 @@ struct ike_header_t { * @param response response flag */ void (*set_response_flag) (ike_header_t *this, bool response); + /** * Get "higher version supported"-flag. * @@ -170,6 +185,13 @@ struct ike_header_t { bool (*get_version_flag) (ike_header_t *this); /** + * Set the "higher version supported"-flag. + * + * @param version flag value + */ + void (*set_version_flag)(ike_header_t *this, bool version); + + /** * Get the initiator flag. * * @return initiator flag diff --git a/src/libcharon/encoding/payloads/ke_payload.c b/src/libcharon/encoding/payloads/ke_payload.c index 1bc79f084..999d73192 100644 --- a/src/libcharon/encoding/payloads/ke_payload.c +++ b/src/libcharon/encoding/payloads/ke_payload.c @@ -1,5 +1,6 @@ /* - * Copyright (C) 2005-2006 Martin Willi + * Copyright (C) 2005-2010 Martin Willi + * Copyright (C) 2010 revosec AG * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil * @@ -20,14 +21,13 @@ #include <encoding/payloads/encodings.h> - typedef struct private_ke_payload_t private_ke_payload_t; /** * Private data of an ke_payload_t object. - * */ struct private_ke_payload_t { + /** * Public ke_payload_t interface. */ @@ -44,6 +44,16 @@ struct private_ke_payload_t { bool critical; /** + * Reserved bits + */ + bool reserved_bit[7]; + + /** + * Reserved bytes + */ + u_int8_t reserved_byte[2]; + + /** * Length of this payload. */ u_int16_t payload_length; @@ -64,27 +74,27 @@ struct private_ke_payload_t { * * The defined offsets are the positions in a object of type * private_ke_payload_t. - * */ encoding_rule_t ke_payload_encodings[] = { /* 1 Byte next payload type, stored in the field next_payload */ - { U_INT_8, offsetof(private_ke_payload_t, next_payload) }, + { U_INT_8, offsetof(private_ke_payload_t, next_payload) }, /* the critical bit */ - { FLAG, offsetof(private_ke_payload_t, critical) }, - /* 7 Bit reserved bits, nowhere stored */ - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, + { FLAG, offsetof(private_ke_payload_t, critical) }, + /* 7 Bit reserved bits */ + { RESERVED_BIT, offsetof(private_ke_payload_t, reserved_bit[0]) }, + { RESERVED_BIT, offsetof(private_ke_payload_t, reserved_bit[1]) }, + { RESERVED_BIT, offsetof(private_ke_payload_t, reserved_bit[2]) }, + { RESERVED_BIT, offsetof(private_ke_payload_t, reserved_bit[3]) }, + { RESERVED_BIT, offsetof(private_ke_payload_t, reserved_bit[4]) }, + { RESERVED_BIT, offsetof(private_ke_payload_t, reserved_bit[5]) }, + { RESERVED_BIT, offsetof(private_ke_payload_t, reserved_bit[6]) }, /* Length of the whole payload*/ - { PAYLOAD_LENGTH, offsetof(private_ke_payload_t, payload_length) }, + { PAYLOAD_LENGTH, offsetof(private_ke_payload_t, payload_length) }, /* DH Group number as 16 bit field*/ - { U_INT_16, offsetof(private_ke_payload_t, dh_group_number) }, - { RESERVED_BYTE, 0 }, - { RESERVED_BYTE, 0 }, + { U_INT_16, offsetof(private_ke_payload_t, dh_group_number) }, + /* 2 reserved bytes */ + { RESERVED_BYTE, offsetof(private_ke_payload_t, reserved_byte[0])}, + { RESERVED_BYTE, offsetof(private_ke_payload_t, reserved_byte[1])}, /* Key Exchange Data is from variable size */ { KEY_EXCHANGE_DATA, offsetof(private_ke_payload_t, key_exchange_data)} }; @@ -103,123 +113,60 @@ encoding_rule_t ke_payload_encodings[] = { +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ -/** - * Implementation of payload_t.verify. - */ -static status_t verify(private_ke_payload_t *this) +METHOD(payload_t, verify, status_t, + private_ke_payload_t *this) { - /* dh group is not verified in here */ return SUCCESS; } -/** - * Implementation of payload_t.destroy. - */ -static void destroy(private_ke_payload_t *this) -{ - if (this->key_exchange_data.ptr != NULL) - { - free(this->key_exchange_data.ptr); - } - free(this); -} - -/** - * Implementation of payload_t.get_encoding_rules. - */ -static void get_encoding_rules(private_ke_payload_t *this, encoding_rule_t **rules, size_t *rule_count) +METHOD(payload_t, get_encoding_rules, void, + private_ke_payload_t *this, encoding_rule_t **rules, size_t *rule_count) { *rules = ke_payload_encodings; - *rule_count = sizeof(ke_payload_encodings) / sizeof(encoding_rule_t); + *rule_count = countof(ke_payload_encodings); } -/** - * Implementation of payload_t.get_type. - */ -static payload_type_t get_type(private_ke_payload_t *this) +METHOD(payload_t, get_type, payload_type_t, + private_ke_payload_t *this) { return KEY_EXCHANGE; } -/** - * Implementation of payload_t.get_next_type. - */ -static payload_type_t get_next_type(private_ke_payload_t *this) +METHOD(payload_t, get_next_type, payload_type_t, + private_ke_payload_t *this) { - return (this->next_payload); + return this->next_payload; } -/** - * Implementation of payload_t.set_next_type. - */ -static void set_next_type(private_ke_payload_t *this,payload_type_t type) +METHOD(payload_t, set_next_type, void, + private_ke_payload_t *this,payload_type_t type) { this->next_payload = type; } -/** - * recompute the length of the payload. - */ -static void compute_length(private_ke_payload_t *this) -{ - size_t length = KE_PAYLOAD_HEADER_LENGTH; - if (this->key_exchange_data.ptr != NULL) - { - length += this->key_exchange_data.len; - } - this->payload_length = length; -} - -/** - * Implementation of payload_t.get_length. - */ -static size_t get_length(private_ke_payload_t *this) +METHOD(payload_t, get_length, size_t, + private_ke_payload_t *this) { - compute_length(this); return this->payload_length; } -/** - * Implementation of ke_payload_t.get_key_exchange_data. - */ -static chunk_t get_key_exchange_data(private_ke_payload_t *this) +METHOD(ke_payload_t, get_key_exchange_data, chunk_t, + private_ke_payload_t *this) { - return (this->key_exchange_data); + return this->key_exchange_data; } -/** - * Implementation of ke_payload_t.set_key_exchange_data. - */ -static void set_key_exchange_data(private_ke_payload_t *this, chunk_t key_exchange_data) -{ - /* destroy existing data first */ - if (this->key_exchange_data.ptr != NULL) - { - /* free existing value */ - free(this->key_exchange_data.ptr); - this->key_exchange_data.ptr = NULL; - this->key_exchange_data.len = 0; - - } - - this->key_exchange_data = chunk_clone(key_exchange_data); - compute_length(this); -} - -/** - * Implementation of ke_payload_t.get_dh_group_number. - */ -static diffie_hellman_group_t get_dh_group_number(private_ke_payload_t *this) +METHOD(ke_payload_t, get_dh_group_number, diffie_hellman_group_t, + private_ke_payload_t *this) { return this->dh_group_number; } -/** - * Implementation of ke_payload_t.set_dh_group_number. - */ -static void set_dh_group_number(private_ke_payload_t *this, diffie_hellman_group_t dh_group_number) +METHOD2(payload_t, ke_payload_t, destroy, void, + private_ke_payload_t *this) { - this->dh_group_number = dh_group_number; + free(this->key_exchange_data.ptr); + free(this); } /* @@ -227,31 +174,27 @@ static void set_dh_group_number(private_ke_payload_t *this, diffie_hellman_group */ ke_payload_t *ke_payload_create() { - private_ke_payload_t *this = malloc_thing(private_ke_payload_t); - - /* interface functions */ - this->public.payload_interface.verify = (status_t (*) (payload_t *))verify; - this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules; - this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length; - this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type; - this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type; - this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type; - this->public.payload_interface.destroy = (void (*) (payload_t *))destroy; - - /* public functions */ - this->public.get_key_exchange_data = (chunk_t (*) (ke_payload_t *)) get_key_exchange_data; - this->public.set_key_exchange_data = (void (*) (ke_payload_t *,chunk_t)) set_key_exchange_data; - this->public.get_dh_group_number = (diffie_hellman_group_t (*) (ke_payload_t *)) get_dh_group_number; - this->public.set_dh_group_number =(void (*) (ke_payload_t *,diffie_hellman_group_t)) set_dh_group_number; - this->public.destroy = (void (*) (ke_payload_t *)) destroy; - - /* set default values of the fields */ - this->critical = FALSE; - this->next_payload = NO_PAYLOAD; - this->payload_length = KE_PAYLOAD_HEADER_LENGTH; - this->key_exchange_data = chunk_empty; - this->dh_group_number = MODP_NONE; - + private_ke_payload_t *this; + + INIT(this, + .public = { + .payload_interface = { + .verify = _verify, + .get_encoding_rules = _get_encoding_rules, + .get_length = _get_length, + .get_next_type = _get_next_type, + .set_next_type = _set_next_type, + .get_type = _get_type, + .destroy = _destroy, + }, + .get_key_exchange_data = _get_key_exchange_data, + .get_dh_group_number = _get_dh_group_number, + .destroy = _destroy, + }, + .next_payload = NO_PAYLOAD, + .payload_length = KE_PAYLOAD_HEADER_LENGTH, + .dh_group_number = MODP_NONE, + ); return &this->public; } @@ -264,7 +207,7 @@ ke_payload_t *ke_payload_create_from_diffie_hellman(diffie_hellman_t *dh) dh->get_my_public_value(dh, &this->key_exchange_data); this->dh_group_number = dh->get_dh_group(dh); - compute_length(this); + this->payload_length = this->key_exchange_data.len + KE_PAYLOAD_HEADER_LENGTH; return &this->public; } diff --git a/src/libcharon/encoding/payloads/ke_payload.h b/src/libcharon/encoding/payloads/ke_payload.h index 3ca05009e..65cc11883 100644 --- a/src/libcharon/encoding/payloads/ke_payload.h +++ b/src/libcharon/encoding/payloads/ke_payload.h @@ -47,24 +47,13 @@ struct ke_payload_t { payload_t payload_interface; /** - * Returns the currently set key exchange data of this KE payload. + * Returns the key exchange data of this KE payload. * - * @warning Returned data are not copied. - * - * @return chunk_t pointing to the value + * @return chunk_t pointing to internal data */ chunk_t (*get_key_exchange_data) (ke_payload_t *this); /** - * Sets the key exchange data of this KE payload. - * - * Value is getting copied. - * - * @param key_exchange_data chunk_t pointing to the value to set - */ - void (*set_key_exchange_data) (ke_payload_t *this, chunk_t key_exchange_data); - - /** * Gets the Diffie-Hellman Group Number of this KE payload. * * @return DH Group Number of this payload @@ -72,14 +61,6 @@ struct ke_payload_t { diffie_hellman_group_t (*get_dh_group_number) (ke_payload_t *this); /** - * Sets the Diffie-Hellman Group Number of this KE payload. - * - * @param dh_group_number DH Group to set - */ - void (*set_dh_group_number) (ke_payload_t *this, - diffie_hellman_group_t dh_group_number); - - /** * Destroys an ke_payload_t object. */ void (*destroy) (ke_payload_t *this); diff --git a/src/libcharon/encoding/payloads/nonce_payload.c b/src/libcharon/encoding/payloads/nonce_payload.c index 4ad5ce9dd..78000b8c6 100644 --- a/src/libcharon/encoding/payloads/nonce_payload.c +++ b/src/libcharon/encoding/payloads/nonce_payload.c @@ -1,5 +1,6 @@ /* - * Copyright (C) 2005-2006 Martin Willi + * Copyright (C) 2005-2010 Martin Willi + * Copyright (C) 2010 revosec AG * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil * @@ -14,21 +15,19 @@ * for more details. */ -/* offsetof macro */ #include <stddef.h> #include "nonce_payload.h" #include <encoding/payloads/encodings.h> - typedef struct private_nonce_payload_t private_nonce_payload_t; /** * Private data of an nonce_payload_t object. - * */ struct private_nonce_payload_t { + /** * Public nonce_payload_t interface. */ @@ -45,6 +44,11 @@ struct private_nonce_payload_t { bool critical; /** + * Reserved bits + */ + bool reserved[7]; + + /** * Length of this payload. */ u_int16_t payload_length; @@ -60,25 +64,24 @@ struct private_nonce_payload_t { * * The defined offsets are the positions in a object of type * private_nonce_payload_t. - * */ encoding_rule_t nonce_payload_encodings[] = { /* 1 Byte next payload type, stored in the field next_payload */ - { U_INT_8, offsetof(private_nonce_payload_t, next_payload) }, + { U_INT_8, offsetof(private_nonce_payload_t, next_payload) }, /* the critical bit */ - { FLAG, offsetof(private_nonce_payload_t, critical) }, - /* 7 Bit reserved bits, nowhere stored */ - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, + { FLAG, offsetof(private_nonce_payload_t, critical) }, + /* 7 Bit reserved bits */ + { RESERVED_BIT, offsetof(private_nonce_payload_t, reserved[0]) }, + { RESERVED_BIT, offsetof(private_nonce_payload_t, reserved[1]) }, + { RESERVED_BIT, offsetof(private_nonce_payload_t, reserved[2]) }, + { RESERVED_BIT, offsetof(private_nonce_payload_t, reserved[3]) }, + { RESERVED_BIT, offsetof(private_nonce_payload_t, reserved[4]) }, + { RESERVED_BIT, offsetof(private_nonce_payload_t, reserved[5]) }, + { RESERVED_BIT, offsetof(private_nonce_payload_t, reserved[6]) }, /* Length of the whole nonce payload*/ - { PAYLOAD_LENGTH, offsetof(private_nonce_payload_t, payload_length) }, + { PAYLOAD_LENGTH, offsetof(private_nonce_payload_t, payload_length) }, /* some nonce bytes, lenth is defined in PAYLOAD_LENGTH */ - { NONCE_DATA, offsetof(private_nonce_payload_t, nonce) } + { NONCE_DATA, offsetof(private_nonce_payload_t, nonce) }, }; /* 1 2 3 @@ -92,102 +95,64 @@ encoding_rule_t nonce_payload_encodings[] = { +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ -/** - * Implementation of payload_t.verify. - */ -static status_t verify(private_nonce_payload_t *this) +METHOD(payload_t, verify, status_t, + private_nonce_payload_t *this) { - if ((this->nonce.len < 16) || ((this->nonce.len > 256))) + if (this->nonce.len < 16 || this->nonce.len > 256) { - /* nonce length is wrong */ return FAILED; } - return SUCCESS; } -/** - * Implementation of nonce_payload_t.set_nonce. - */ -static status_t set_nonce(private_nonce_payload_t *this, chunk_t nonce) -{ - this->nonce.ptr = clalloc(nonce.ptr, nonce.len); - this->nonce.len = nonce.len; - this->payload_length = NONCE_PAYLOAD_HEADER_LENGTH + nonce.len; - return SUCCESS; -} - -/** - * Implementation of nonce_payload_t.get_nonce. - */ -static chunk_t get_nonce(private_nonce_payload_t *this) -{ - chunk_t nonce; - nonce.ptr = clalloc(this->nonce.ptr,this->nonce.len); - nonce.len = this->nonce.len; - return nonce; -} - -/** - * Implementation of nonce_payload_t.get_encoding_rules. - */ -static void get_encoding_rules(private_nonce_payload_t *this, encoding_rule_t **rules, size_t *rule_count) +METHOD(payload_t, get_encoding_rules, void, + private_nonce_payload_t *this, encoding_rule_t **rules, size_t *rule_count) { *rules = nonce_payload_encodings; - *rule_count = sizeof(nonce_payload_encodings) / sizeof(encoding_rule_t); + *rule_count = countof(nonce_payload_encodings); } -/** - * Implementation of payload_t.get_type. - */ -static payload_type_t get_type(private_nonce_payload_t *this) +METHOD(payload_t, get_type, payload_type_t, + private_nonce_payload_t *this) { return NONCE; } -/** - * Implementation of payload_t.get_next_type. - */ -static payload_type_t get_next_type(private_nonce_payload_t *this) +METHOD(payload_t, get_next_type, payload_type_t, + private_nonce_payload_t *this) { - return (this->next_payload); + return this->next_payload; } -/** - * Implementation of payload_t.set_next_type. - */ -static void set_next_type(private_nonce_payload_t *this,payload_type_t type) +METHOD(payload_t, set_next_type, void, + private_nonce_payload_t *this, payload_type_t type) { this->next_payload = type; } -/** - * recompute the length of the payload. - */ -static void compute_length(private_nonce_payload_t *this) +METHOD(payload_t, get_length, size_t, + private_nonce_payload_t *this) { - this->payload_length = NONCE_PAYLOAD_HEADER_LENGTH + this->nonce.len; + return this->payload_length; } -/** - * Implementation of payload_t.get_length. - */ -static size_t get_length(private_nonce_payload_t *this) +METHOD(nonce_payload_t, set_nonce, void, + private_nonce_payload_t *this, chunk_t nonce) { - compute_length(this); - return this->payload_length; + this->nonce = chunk_clone(nonce); + this->payload_length = NONCE_PAYLOAD_HEADER_LENGTH + nonce.len; } -/** - * Implementation of payload_t.destroy and nonce_payload_t.destroy. - */ -static void destroy(private_nonce_payload_t *this) +METHOD(nonce_payload_t, get_nonce, chunk_t, + private_nonce_payload_t *this) { - if (this->nonce.ptr != NULL) - { - free(this->nonce.ptr); - } + return chunk_clone(this->nonce); +} +METHOD2(payload_t, nonce_payload_t, destroy, void, + private_nonce_payload_t *this) +{ + free(this->nonce.ptr); free(this); } @@ -196,30 +161,25 @@ static void destroy(private_nonce_payload_t *this) */ nonce_payload_t *nonce_payload_create() { - private_nonce_payload_t *this = malloc_thing(private_nonce_payload_t); - - /* interface functions */ - this->public.payload_interface.verify = (status_t (*) (payload_t *))verify; - this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules; - this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length; - this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type; - this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type; - this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type; - this->public.payload_interface.destroy = (void (*) (payload_t *))destroy; - - /* public functions */ - this->public.destroy = (void (*) (nonce_payload_t *)) destroy; - this->public.set_nonce = (void (*) (nonce_payload_t *,chunk_t)) set_nonce; - this->public.get_nonce = (chunk_t (*) (nonce_payload_t *)) get_nonce; - - /* private variables */ - this->critical = FALSE; - this->next_payload = NO_PAYLOAD; - this->payload_length = NONCE_PAYLOAD_HEADER_LENGTH; - this->nonce.ptr = NULL; - this->nonce.len = 0; - - return (&(this->public)); + private_nonce_payload_t *this; + + INIT(this, + .public = { + .payload_interface = { + .verify = _verify, + .get_encoding_rules = _get_encoding_rules, + .get_length = _get_length, + .get_next_type = _get_next_type, + .set_next_type = _set_next_type, + .get_type = _get_type, + .destroy = _destroy, + }, + .set_nonce = _set_nonce, + .get_nonce = _get_nonce, + .destroy = _destroy, + }, + .next_payload = NO_PAYLOAD, + .payload_length = NONCE_PAYLOAD_HEADER_LENGTH, + ); + return &this->public; } - - diff --git a/src/libcharon/encoding/payloads/notify_payload.c b/src/libcharon/encoding/payloads/notify_payload.c index a56fd1869..77f15ec6d 100644 --- a/src/libcharon/encoding/payloads/notify_payload.c +++ b/src/libcharon/encoding/payloads/notify_payload.c @@ -1,7 +1,8 @@ /* + * Copyright (C) 2005-2010 Martin Willi + * Copyright (C) 2010 revosec AG * Copyright (C) 2006-2008 Tobias Brunner * Copyright (C) 2006 Daniel Roethlisberger - * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil * @@ -186,9 +187,9 @@ typedef struct private_notify_payload_t private_notify_payload_t; /** * Private data of an notify_payload_t object. - * */ struct private_notify_payload_t { + /** * Public notify_payload_t interface. */ @@ -205,6 +206,11 @@ struct private_notify_payload_t { bool critical; /** + * reserved bits + */ + bool reserved[7]; + + /** * Length of this payload. */ u_int16_t payload_length; @@ -240,7 +246,6 @@ struct private_notify_payload_t { * * The defined offsets are the positions in a object of type * private_notify_payload_t. - * */ encoding_rule_t notify_payload_encodings[] = { /* 1 Byte next payload type, stored in the field next_payload */ @@ -248,13 +253,13 @@ encoding_rule_t notify_payload_encodings[] = { /* the critical bit */ { FLAG, offsetof(private_notify_payload_t, critical) }, /* 7 Bit reserved bits, nowhere stored */ - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, + { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[0]) }, + { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[1]) }, + { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[2]) }, + { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[3]) }, + { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[4]) }, + { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[5]) }, + { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[6]) }, /* Length of the whole payload*/ { PAYLOAD_LENGTH, offsetof(private_notify_payload_t, payload_length) }, /* Protocol ID as 8 bit field*/ @@ -262,11 +267,11 @@ encoding_rule_t notify_payload_encodings[] = { /* SPI Size as 8 bit field*/ { SPI_SIZE, offsetof(private_notify_payload_t, spi_size) }, /* Notify message type as 16 bit field*/ - { U_INT_16, offsetof(private_notify_payload_t, notify_type) }, + { U_INT_16, offsetof(private_notify_payload_t, notify_type) }, /* SPI as variable length field*/ { SPI, offsetof(private_notify_payload_t, spi) }, /* Key Exchange Data is from variable size */ - { NOTIFICATION_DATA, offsetof(private_notify_payload_t, notification_data) } + { NOTIFICATION_DATA,offsetof(private_notify_payload_t, notification_data) } }; /* @@ -287,10 +292,8 @@ encoding_rule_t notify_payload_encodings[] = { +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ -/** - * Implementation of payload_t.verify. - */ -static status_t verify(private_notify_payload_t *this) +METHOD(payload_t, verify, status_t, + private_notify_payload_t *this) { bool bad_length = FALSE; @@ -404,35 +407,27 @@ static status_t verify(private_notify_payload_t *this) return SUCCESS; } -/** - * Implementation of payload_t.get_encoding_rules. - */ -static void get_encoding_rules(private_notify_payload_t *this, encoding_rule_t **rules, size_t *rule_count) +METHOD(payload_t, get_encoding_rules, void, + private_notify_payload_t *this, encoding_rule_t **rules, size_t *rule_count) { *rules = notify_payload_encodings; - *rule_count = sizeof(notify_payload_encodings) / sizeof(encoding_rule_t); + *rule_count = countof(notify_payload_encodings); } -/** - * Implementation of payload_t.get_type. - */ -static payload_type_t get_type(private_notify_payload_t *this) +METHOD(payload_t, get_type, payload_type_t, + private_notify_payload_t *this) { return NOTIFY; } -/** - * Implementation of payload_t.get_next_type. - */ -static payload_type_t get_next_type(private_notify_payload_t *this) +METHOD(payload_t, get_next_type, payload_type_t, + private_notify_payload_t *this) { - return (this->next_payload); + return this->next_payload; } -/** - * Implementation of payload_t.set_next_type. - */ -static void set_next_type(private_notify_payload_t *this,payload_type_t type) +METHOD(payload_t, set_next_type, void, + private_notify_payload_t *this, payload_type_t type) { this->next_payload = type; } @@ -443,6 +438,7 @@ static void set_next_type(private_notify_payload_t *this,payload_type_t type) static void compute_length (private_notify_payload_t *this) { size_t length = NOTIFY_PAYLOAD_HEADER_LENGTH; + if (this->notification_data.ptr != NULL) { length += this->notification_data.len; @@ -454,51 +450,38 @@ static void compute_length (private_notify_payload_t *this) this->payload_length = length; } -/** - * Implementation of payload_t.get_length. - */ -static size_t get_length(private_notify_payload_t *this) +METHOD(payload_t, get_length, size_t, + private_notify_payload_t *this) { - compute_length(this); return this->payload_length; } -/** - * Implementation of notify_payload_t.get_protocol_id. - */ -static u_int8_t get_protocol_id(private_notify_payload_t *this) +METHOD(notify_payload_t, get_protocol_id, u_int8_t, + private_notify_payload_t *this) { return this->protocol_id; } -/** - * Implementation of notify_payload_t.set_protocol_id. - */ -static void set_protocol_id(private_notify_payload_t *this, u_int8_t protocol_id) +METHOD(notify_payload_t, set_protocol_id, void, + private_notify_payload_t *this, u_int8_t protocol_id) { this->protocol_id = protocol_id; } -/** - * Implementation of notify_payload_t.get_notify_type. - */ -static notify_type_t get_notify_type(private_notify_payload_t *this) +METHOD(notify_payload_t, get_notify_type, notify_type_t, + private_notify_payload_t *this) { return this->notify_type; } -/** - * Implementation of notify_payload_t.set_notify_type. - */ -static void set_notify_type(private_notify_payload_t *this, u_int16_t notify_type) +METHOD(notify_payload_t, set_notify_type, void, + private_notify_payload_t *this, notify_type_t notify_type) { this->notify_type = notify_type; } -/** - * Implementation of notify_payload_t.get_spi. - */ -static u_int32_t get_spi(private_notify_payload_t *this) +METHOD(notify_payload_t, get_spi, u_int32_t, + private_notify_payload_t *this) { switch (this->protocol_id) { @@ -514,10 +497,8 @@ static u_int32_t get_spi(private_notify_payload_t *this) return 0; } -/** - * Implementation of notify_payload_t.set_spi. - */ -static void set_spi(private_notify_payload_t *this, u_int32_t spi) +METHOD(notify_payload_t, set_spi, void, + private_notify_payload_t *this, u_int32_t spi) { chunk_free(&this->spi); switch (this->protocol_id) @@ -534,37 +515,26 @@ static void set_spi(private_notify_payload_t *this, u_int32_t spi) compute_length(this); } -/** - * Implementation of notify_payload_t.get_notification_data. - */ -static chunk_t get_notification_data(private_notify_payload_t *this) +METHOD(notify_payload_t, get_notification_data, chunk_t, + private_notify_payload_t *this) { - return (this->notification_data); + return this->notification_data; } -/** - * Implementation of notify_payload_t.set_notification_data. - */ -static status_t set_notification_data(private_notify_payload_t *this, chunk_t notification_data) +METHOD(notify_payload_t, set_notification_data, void, + private_notify_payload_t *this, chunk_t data) { - chunk_free(&this->notification_data); - if (notification_data.len > 0) - { - this->notification_data = chunk_clone(notification_data); - } + free(this->notification_data.ptr); + this->notification_data = chunk_clone(data); compute_length(this); - return SUCCESS; } -/** - * Implementation of notify_payload_t.destroy and notify_payload_t.destroy. - */ -static status_t destroy(private_notify_payload_t *this) +METHOD2(payload_t, notify_payload_t, destroy, void, + private_notify_payload_t *this) { - chunk_free(&this->notification_data); - chunk_free(&this->spi); + free(this->notification_data.ptr); + free(this->spi.ptr); free(this); - return SUCCESS; } /* @@ -572,52 +542,45 @@ static status_t destroy(private_notify_payload_t *this) */ notify_payload_t *notify_payload_create() { - private_notify_payload_t *this = malloc_thing(private_notify_payload_t); - - /* interface functions */ - this->public.payload_interface.verify = (status_t (*) (payload_t *))verify; - this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules; - this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length; - this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type; - this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type; - this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type; - this->public.payload_interface.destroy = (void (*) (payload_t *))destroy; - - /* public functions */ - this->public.get_protocol_id = (u_int8_t (*) (notify_payload_t *)) get_protocol_id; - this->public.set_protocol_id = (void (*) (notify_payload_t *,u_int8_t)) set_protocol_id; - this->public.get_notify_type = (notify_type_t (*) (notify_payload_t *)) get_notify_type; - this->public.set_notify_type = (void (*) (notify_payload_t *,notify_type_t)) set_notify_type; - this->public.get_spi = (u_int32_t (*) (notify_payload_t *)) get_spi; - this->public.set_spi = (void (*) (notify_payload_t *,u_int32_t)) set_spi; - this->public.get_notification_data = (chunk_t (*) (notify_payload_t *)) get_notification_data; - this->public.set_notification_data = (void (*) (notify_payload_t *,chunk_t)) set_notification_data; - this->public.destroy = (void (*) (notify_payload_t *)) destroy; - - /* set default values of the fields */ - this->critical = FALSE; - this->next_payload = NO_PAYLOAD; - this->payload_length = NOTIFY_PAYLOAD_HEADER_LENGTH; - this->protocol_id = 0; - this->notify_type = 0; - this->spi.ptr = NULL; - this->spi.len = 0; - this->spi_size = 0; - this->notification_data.ptr = NULL; - this->notification_data.len = 0; - + private_notify_payload_t *this; + + INIT(this, + .public = { + .payload_interface = { + .verify = _verify, + .get_encoding_rules = _get_encoding_rules, + .get_length = _get_length, + .get_next_type = _get_next_type, + .set_next_type = _set_next_type, + .get_type = _get_type, + .destroy = _destroy, + }, + .get_protocol_id = _get_protocol_id, + .set_protocol_id = _set_protocol_id, + .get_notify_type = _get_notify_type, + .set_notify_type = _set_notify_type, + .get_spi = _get_spi, + .set_spi = _set_spi, + .get_notification_data = _get_notification_data, + .set_notification_data = _set_notification_data, + .destroy = _destroy, + }, + .next_payload = NO_PAYLOAD, + .payload_length = NOTIFY_PAYLOAD_HEADER_LENGTH, + ); return &this->public; } /* * Described in header. */ -notify_payload_t *notify_payload_create_from_protocol_and_type(protocol_id_t protocol_id, notify_type_t notify_type) +notify_payload_t *notify_payload_create_from_protocol_and_type( + protocol_id_t protocol_id, notify_type_t notify_type) { notify_payload_t *notify = notify_payload_create(); - notify->set_notify_type(notify,notify_type); - notify->set_protocol_id(notify,protocol_id); + notify->set_notify_type(notify, notify_type); + notify->set_protocol_id(notify, protocol_id); return notify; } diff --git a/src/libcharon/encoding/payloads/payload.c b/src/libcharon/encoding/payloads/payload.c index 1cee6d2aa..d1e677db7 100644 --- a/src/libcharon/encoding/payloads/payload.c +++ b/src/libcharon/encoding/payloads/payload.c @@ -59,25 +59,23 @@ ENUM_NEXT(payload_type_names, SECURITY_ASSOCIATION, EXTENSIBLE_AUTHENTICATION, N #ifdef ME ENUM_NEXT(payload_type_names, ID_PEER, ID_PEER, EXTENSIBLE_AUTHENTICATION, "ID_PEER"); -ENUM_NEXT(payload_type_names, HEADER, UNKNOWN_PAYLOAD, ID_PEER, +ENUM_NEXT(payload_type_names, HEADER, CONFIGURATION_ATTRIBUTE, ID_PEER, "HEADER", "PROPOSAL_SUBSTRUCTURE", "TRANSFORM_SUBSTRUCTURE", "TRANSFORM_ATTRIBUTE", "TRAFFIC_SELECTOR_SUBSTRUCTURE", - "CONFIGURATION_ATTRIBUTE", - "UNKNOWN_PAYLOAD"); + "CONFIGURATION_ATTRIBUTE"); #else -ENUM_NEXT(payload_type_names, HEADER, UNKNOWN_PAYLOAD, EXTENSIBLE_AUTHENTICATION, +ENUM_NEXT(payload_type_names, HEADER, CONFIGURATION_ATTRIBUTE, EXTENSIBLE_AUTHENTICATION, "HEADER", "PROPOSAL_SUBSTRUCTURE", "TRANSFORM_SUBSTRUCTURE", "TRANSFORM_ATTRIBUTE", "TRAFFIC_SELECTOR_SUBSTRUCTURE", - "CONFIGURATION_ATTRIBUTE", - "UNKNOWN_PAYLOAD"); + "CONFIGURATION_ATTRIBUTE"); #endif /* ME */ -ENUM_END(payload_type_names, UNKNOWN_PAYLOAD); +ENUM_END(payload_type_names, CONFIGURATION_ATTRIBUTE); /* short forms of payload names */ ENUM_BEGIN(payload_type_short_names, NO_PAYLOAD, NO_PAYLOAD, @@ -102,25 +100,23 @@ ENUM_NEXT(payload_type_short_names, SECURITY_ASSOCIATION, EXTENSIBLE_AUTHENTICAT #ifdef ME ENUM_NEXT(payload_type_short_names, ID_PEER, ID_PEER, EXTENSIBLE_AUTHENTICATION, "IDp"); -ENUM_NEXT(payload_type_short_names, HEADER, UNKNOWN_PAYLOAD, ID_PEER, +ENUM_NEXT(payload_type_short_names, HEADER, CONFIGURATION_ATTRIBUTE, ID_PEER, "HDR", "PROP", "TRANS", "TRANSATTR", "TSSUB", - "CPATTR", - "??"); + "CPATTR"); #else -ENUM_NEXT(payload_type_short_names, HEADER, UNKNOWN_PAYLOAD, EXTENSIBLE_AUTHENTICATION, +ENUM_NEXT(payload_type_short_names, HEADER, CONFIGURATION_ATTRIBUTE, EXTENSIBLE_AUTHENTICATION, "HDR", "PROP", "TRANS", "TRANSATTR", "TSSUB", - "CPATTR", - "??"); + "CPATTR"); #endif /* ME */ -ENUM_END(payload_type_short_names, UNKNOWN_PAYLOAD); +ENUM_END(payload_type_short_names, CONFIGURATION_ATTRIBUTE); /* * see header @@ -178,7 +174,45 @@ payload_t *payload_create(payload_type_t type) case ENCRYPTED: return (payload_t*)encryption_payload_create(); default: - return (payload_t*)unknown_payload_create(); + return (payload_t*)unknown_payload_create(type); } } +/** + * See header. + */ +bool payload_is_known(payload_type_t type) +{ + if (type == HEADER || + (type >= SECURITY_ASSOCIATION && type <= EXTENSIBLE_AUTHENTICATION)) + { + return TRUE; + } +#ifdef ME + if (type == ID_PEER) + { + return TRUE; + } +#endif + return FALSE; +} + +/** + * See header. + */ +void* payload_get_field(payload_t *payload, encoding_type_t type, u_int skip) +{ + encoding_rule_t *rule; + size_t count; + int i; + + payload->get_encoding_rules(payload, &rule, &count); + for (i = 0; i < count; i++) + { + if (rule[i].type == type && skip-- == 0) + { + return ((char*)payload) + rule[i].offset; + } + } + return NULL; +} diff --git a/src/libcharon/encoding/payloads/payload.h b/src/libcharon/encoding/payloads/payload.h index 2e783cb30..0f407ff42 100644 --- a/src/libcharon/encoding/payloads/payload.h +++ b/src/libcharon/encoding/payloads/payload.h @@ -137,7 +137,7 @@ enum payload_type_t{ * This payload type is not sent over wire and just * used internally to handle IKEv2-Header like a payload. */ - HEADER = 140, + HEADER = 256, /** * PROPOSAL_SUBSTRUCTURE has a value of PRIVATE USE space. @@ -145,7 +145,7 @@ enum payload_type_t{ * This payload type is not sent over wire and just * used internally to handle a proposal substructure like a payload. */ - PROPOSAL_SUBSTRUCTURE = 141, + PROPOSAL_SUBSTRUCTURE = 257, /** * TRANSFORM_SUBSTRUCTURE has a value of PRIVATE USE space. @@ -153,7 +153,7 @@ enum payload_type_t{ * This payload type is not sent over wire and just * used internally to handle a transform substructure like a payload. */ - TRANSFORM_SUBSTRUCTURE = 142, + TRANSFORM_SUBSTRUCTURE = 258, /** * TRANSFORM_ATTRIBUTE has a value of PRIVATE USE space. @@ -161,7 +161,7 @@ enum payload_type_t{ * This payload type is not sent over wire and just * used internally to handle a transform attribute like a payload. */ - TRANSFORM_ATTRIBUTE = 143, + TRANSFORM_ATTRIBUTE = 259, /** * TRAFFIC_SELECTOR_SUBSTRUCTURE has a value of PRIVATE USE space. @@ -169,7 +169,7 @@ enum payload_type_t{ * This payload type is not sent over wire and just * used internally to handle a transform selector like a payload. */ - TRAFFIC_SELECTOR_SUBSTRUCTURE = 144, + TRAFFIC_SELECTOR_SUBSTRUCTURE = 260, /** * CONFIGURATION_ATTRIBUTE has a value of PRIVATE USE space. @@ -177,18 +177,9 @@ enum payload_type_t{ * This payload type is not sent over wire and just * used internally to handle a transform attribute like a payload. */ - CONFIGURATION_ATTRIBUTE = 145, - - /** - * A unknown payload has a value of PRIVATE USE space. - * - * This payload type is not sent over wire and just - * used internally to handle a unknown payload. - */ - UNKNOWN_PAYLOAD = 146, + CONFIGURATION_ATTRIBUTE = 261, }; - /** * enum names for payload_type_t. */ @@ -269,4 +260,22 @@ struct payload_t { */ payload_t *payload_create(payload_type_t type); +/** + * Check if a specific payload is implemented, or handled as unknown payload. + * + * @param type type of the payload to check + * @return FALSE if payload type handled as unknown payload + */ +bool payload_is_known(payload_type_t type); + +/** + * Get the value field in a payload using encoding rules. + * + * @param payload payload to look up a field + * @param type encoding rule type to look up + * @param skip number rules of type to skip, 0 to get first + * @return type specific value pointer, NULL if not found + */ +void* payload_get_field(payload_t *payload, encoding_type_t type, u_int skip); + #endif /** PAYLOAD_H_ @}*/ diff --git a/src/libcharon/encoding/payloads/proposal_substructure.c b/src/libcharon/encoding/payloads/proposal_substructure.c index 985b03255..f39c3b0e6 100644 --- a/src/libcharon/encoding/payloads/proposal_substructure.c +++ b/src/libcharon/encoding/payloads/proposal_substructure.c @@ -47,6 +47,11 @@ struct private_proposal_substructure_t { u_int8_t next_payload; /** + * reserved byte + */ + u_int8_t reserved; + + /** * Length of this payload. */ u_int16_t proposal_length; @@ -91,8 +96,8 @@ struct private_proposal_substructure_t { encoding_rule_t proposal_substructure_encodings[] = { /* 1 Byte next payload type, stored in the field next_payload */ { U_INT_8, offsetof(private_proposal_substructure_t, next_payload) }, - /* Reserved Byte is skipped */ - { RESERVED_BYTE, 0 }, + /* 1 Reserved Byte */ + { RESERVED_BYTE, offsetof(private_proposal_substructure_t, reserved) }, /* Length of the whole proposal substructure payload*/ { PAYLOAD_LENGTH, offsetof(private_proposal_substructure_t, proposal_length) }, /* proposal number is a number of 8 bit */ @@ -213,28 +218,23 @@ METHOD(payload_t, set_next_type, void, */ static void compute_length(private_proposal_substructure_t *this) { - iterator_t *iterator; - payload_t *current_transform; - size_t transforms_count = 0; - size_t length = PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH; + enumerator_t *enumerator; + payload_t *transform; - iterator = this->transforms->create_iterator(this->transforms,TRUE); - while (iterator->iterate(iterator, (void**)¤t_transform)) + this->transforms_count = 0; + this->proposal_length = PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH + this->spi.len; + enumerator = this->transforms->create_enumerator(this->transforms); + while (enumerator->enumerate(enumerator, &transform)) { - length += current_transform->get_length(current_transform); - transforms_count++; + this->proposal_length += transform->get_length(transform); + this->transforms_count++; } - iterator->destroy(iterator); - - length += this->spi.len; - this->transforms_count = transforms_count; - this->proposal_length = length; + enumerator->destroy(enumerator); } METHOD(payload_t, get_length, size_t, private_proposal_substructure_t *this) { - compute_length(this); return this->proposal_length; } @@ -342,32 +342,10 @@ METHOD(proposal_substructure_t, get_proposal, proposal_t*, return proposal; } -METHOD(proposal_substructure_t, clone_, proposal_substructure_t*, +METHOD(proposal_substructure_t, create_substructure_enumerator, enumerator_t*, private_proposal_substructure_t *this) { - private_proposal_substructure_t *clone; - enumerator_t *enumerator; - transform_substructure_t *current; - - clone = (private_proposal_substructure_t*)proposal_substructure_create(); - clone->next_payload = this->next_payload; - clone->proposal_number = this->proposal_number; - clone->protocol_id = this->protocol_id; - clone->spi_size = this->spi_size; - if (this->spi.ptr != NULL) - { - clone->spi.ptr = clalloc(this->spi.ptr, this->spi.len); - clone->spi.len = this->spi.len; - } - enumerator = this->transforms->create_enumerator(this->transforms); - while (enumerator->enumerate(enumerator, ¤t)) - { - current = current->clone(current); - add_transform_substructure(clone, current); - } - enumerator->destroy(enumerator); - - return &clone->public; + return this->transforms->create_enumerator(this->transforms); } METHOD2(payload_t, proposal_substructure_t, destroy, void, @@ -403,12 +381,13 @@ proposal_substructure_t *proposal_substructure_create() .get_protocol_id = _get_protocol_id, .set_is_last_proposal = _set_is_last_proposal, .get_proposal = _get_proposal, + .create_substructure_enumerator = _create_substructure_enumerator, .set_spi = _set_spi, .get_spi = _get_spi, - .clone = _clone_, .destroy = _destroy, }, .next_payload = NO_PAYLOAD, + .proposal_length = PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH, .transforms = linked_list_create(), ); @@ -500,6 +479,7 @@ proposal_substructure_t *proposal_substructure_create_from_proposal( } this->proposal_number = proposal->get_number(proposal); this->protocol_id = proposal->get_protocol(proposal); + compute_length(this); return &this->public; } diff --git a/src/libcharon/encoding/payloads/proposal_substructure.h b/src/libcharon/encoding/payloads/proposal_substructure.h index 56e7184b6..d0ba1fd2a 100644 --- a/src/libcharon/encoding/payloads/proposal_substructure.h +++ b/src/libcharon/encoding/payloads/proposal_substructure.h @@ -111,11 +111,11 @@ struct proposal_substructure_t { proposal_t * (*get_proposal) (proposal_substructure_t *this); /** - * Clones an proposal_substructure_t object. + * Create an enumerator over transform substructures. * - * @return cloned object + * @return enumerator over transform_substructure_t */ - proposal_substructure_t* (*clone) (proposal_substructure_t *this); + enumerator_t* (*create_substructure_enumerator)(proposal_substructure_t *this); /** * Destroys an proposal_substructure_t object. diff --git a/src/libcharon/encoding/payloads/sa_payload.c b/src/libcharon/encoding/payloads/sa_payload.c index 4fbd4cac0..db20d052f 100644 --- a/src/libcharon/encoding/payloads/sa_payload.c +++ b/src/libcharon/encoding/payloads/sa_payload.c @@ -46,6 +46,11 @@ struct private_sa_payload_t { bool critical; /** + * Reserved bits + */ + bool reserved[7]; + + /** * Length of this payload. */ u_int16_t payload_length; @@ -68,13 +73,13 @@ encoding_rule_t sa_payload_encodings[] = { /* the critical bit */ { FLAG, offsetof(private_sa_payload_t, critical) }, /* 7 Bit reserved bits, nowhere stored */ - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, + { RESERVED_BIT, offsetof(private_sa_payload_t, reserved[0]) }, + { RESERVED_BIT, offsetof(private_sa_payload_t, reserved[1]) }, + { RESERVED_BIT, offsetof(private_sa_payload_t, reserved[2]) }, + { RESERVED_BIT, offsetof(private_sa_payload_t, reserved[3]) }, + { RESERVED_BIT, offsetof(private_sa_payload_t, reserved[4]) }, + { RESERVED_BIT, offsetof(private_sa_payload_t, reserved[5]) }, + { RESERVED_BIT, offsetof(private_sa_payload_t, reserved[6]) }, /* Length of the whole SA payload*/ { PAYLOAD_LENGTH, offsetof(private_sa_payload_t, payload_length) }, /* Proposals are stored in a proposal substructure, @@ -185,7 +190,6 @@ static void compute_length(private_sa_payload_t *this) METHOD(payload_t, get_length, size_t, private_sa_payload_t *this) { - compute_length(this); return this->payload_length; } @@ -258,6 +262,12 @@ METHOD(sa_payload_t, get_proposals, linked_list_t*, return list; } +METHOD(sa_payload_t, create_substructure_enumerator, enumerator_t*, + private_sa_payload_t *this) +{ + return this->proposals->create_enumerator(this->proposals); +} + METHOD2(payload_t, sa_payload_t, destroy, void, private_sa_payload_t *this) { @@ -286,6 +296,7 @@ sa_payload_t *sa_payload_create() }, .add_proposal = _add_proposal, .get_proposals = _get_proposals, + .create_substructure_enumerator = _create_substructure_enumerator, .destroy = _destroy, }, .next_payload = NO_PAYLOAD, diff --git a/src/libcharon/encoding/payloads/sa_payload.h b/src/libcharon/encoding/payloads/sa_payload.h index 801a70738..cc8c481c8 100644 --- a/src/libcharon/encoding/payloads/sa_payload.h +++ b/src/libcharon/encoding/payloads/sa_payload.h @@ -61,6 +61,13 @@ struct sa_payload_t { void (*add_proposal) (sa_payload_t *this, proposal_t *proposal); /** + * Create an enumerator over all proposal substructures. + * + * @return enumerator over proposal_substructure_t + */ + enumerator_t* (*create_substructure_enumerator)(sa_payload_t *this); + + /** * Destroys an sa_payload_t object. */ void (*destroy) (sa_payload_t *this); diff --git a/src/libcharon/encoding/payloads/traffic_selector_substructure.c b/src/libcharon/encoding/payloads/traffic_selector_substructure.c index f24857591..df36e4383 100644 --- a/src/libcharon/encoding/payloads/traffic_selector_substructure.c +++ b/src/libcharon/encoding/payloads/traffic_selector_substructure.c @@ -1,5 +1,6 @@ /* - * Copyright (C) 2005-2006 Martin Willi + * Copyright (C) 2005-2010 Martin Willi + * Copyright (C) 2010 revosec AG * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil * @@ -19,14 +20,13 @@ #include <encoding/payloads/encodings.h> #include <utils/linked_list.h> - typedef struct private_traffic_selector_substructure_t private_traffic_selector_substructure_t; /** * Private data of an traffic_selector_substructure_t object. - * */ struct private_traffic_selector_substructure_t { + /** * Public traffic_selector_substructure_t interface. */ @@ -73,24 +73,22 @@ struct private_traffic_selector_substructure_t { * * The defined offsets are the positions in a object of type * private_traffic_selector_substructure_t. - * */ encoding_rule_t traffic_selector_substructure_encodings[] = { /* 1 Byte next ts type*/ - { TS_TYPE, offsetof(private_traffic_selector_substructure_t, ts_type) }, + { TS_TYPE, offsetof(private_traffic_selector_substructure_t, ts_type) }, /* 1 Byte IP protocol id*/ - { U_INT_8, offsetof(private_traffic_selector_substructure_t, ip_protocol_id) }, + { U_INT_8, offsetof(private_traffic_selector_substructure_t, ip_protocol_id) }, /* Length of the whole payload*/ - { PAYLOAD_LENGTH, offsetof(private_traffic_selector_substructure_t, payload_length) }, + { PAYLOAD_LENGTH,offsetof(private_traffic_selector_substructure_t, payload_length) }, /* 2 Byte start port*/ - { U_INT_16, offsetof(private_traffic_selector_substructure_t, start_port) }, + { U_INT_16, offsetof(private_traffic_selector_substructure_t, start_port) }, /* 2 Byte end port*/ { U_INT_16, offsetof(private_traffic_selector_substructure_t, end_port) }, /* starting address is either 4 or 16 byte */ - { ADDRESS, offsetof(private_traffic_selector_substructure_t, starting_address) }, + { ADDRESS, offsetof(private_traffic_selector_substructure_t, starting_address) }, /* ending address is either 4 or 16 byte */ - { ADDRESS, offsetof(private_traffic_selector_substructure_t, ending_address) } - + { ADDRESS, offsetof(private_traffic_selector_substructure_t, ending_address) } }; /* @@ -111,10 +109,8 @@ encoding_rule_t traffic_selector_substructure_encodings[] = { +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ -/** - * Implementation of payload_t.verify. - */ -static status_t verify(private_traffic_selector_substructure_t *this) +METHOD(payload_t, verify, status_t, + private_traffic_selector_substructure_t *this) { if (this->start_port > this->end_port) { @@ -152,72 +148,48 @@ static status_t verify(private_traffic_selector_substructure_t *this) return SUCCESS; } -/** - * Implementation of traffic_selector_substructure_t.get_encoding_rules. - */ -static void get_encoding_rules(private_traffic_selector_substructure_t *this, encoding_rule_t **rules, size_t *rule_count) +METHOD(payload_t, get_encoding_rules, void, + private_traffic_selector_substructure_t *this, encoding_rule_t **rules, + size_t *rule_count) { *rules = traffic_selector_substructure_encodings; - *rule_count = sizeof(traffic_selector_substructure_encodings) / sizeof(encoding_rule_t); + *rule_count = countof(traffic_selector_substructure_encodings); } -/** - * Implementation of payload_t.get_type. - */ -static payload_type_t get_payload_type(private_traffic_selector_substructure_t *this) +METHOD(payload_t, get_type, payload_type_t, + private_traffic_selector_substructure_t *this) { return TRAFFIC_SELECTOR_SUBSTRUCTURE; } -/** - * Implementation of payload_t.get_next_type. - */ -static payload_type_t get_next_type(private_traffic_selector_substructure_t *this) +METHOD(payload_t, get_next_type, payload_type_t, + private_traffic_selector_substructure_t *this) { - return 0; + return NO_PAYLOAD; } -/** - * Implementation of payload_t.set_next_type. - */ -static void set_next_type(private_traffic_selector_substructure_t *this,payload_type_t type) +METHOD(payload_t, set_next_type, void, + private_traffic_selector_substructure_t *this,payload_type_t type) { - } -/** - * Implementation of payload_t.get_length. - */ -static size_t get_length(private_traffic_selector_substructure_t *this) +METHOD(payload_t, get_length, size_t, + private_traffic_selector_substructure_t *this) { return this->payload_length; } -/** - * Implementation of traffic_selector_substructure_t.get_traffic_selector. - */ -static traffic_selector_t *get_traffic_selector(private_traffic_selector_substructure_t *this) +METHOD(traffic_selector_substructure_t, get_traffic_selector, traffic_selector_t*, + private_traffic_selector_substructure_t *this) { - traffic_selector_t *ts; - ts = traffic_selector_create_from_bytes(this->ip_protocol_id, this->ts_type, - this->starting_address, this->start_port, - this->ending_address, this->end_port); - return ts; + return traffic_selector_create_from_bytes( + this->ip_protocol_id, this->ts_type, + this->starting_address, this->start_port, + this->ending_address, this->end_port); } -/** - * recompute length field of the payload - */ -void compute_length(private_traffic_selector_substructure_t *this) -{ - this->payload_length = TRAFFIC_SELECTOR_HEADER_LENGTH + - this->ending_address.len + this->starting_address.len; -} - -/** - * Implementation of payload_t.destroy and traffic_selector_substructure_t.destroy. - */ -static void destroy(private_traffic_selector_substructure_t *this) +METHOD2(payload_t, traffic_selector_substructure_t, destroy, void, + private_traffic_selector_substructure_t *this) { free(this->starting_address.ptr); free(this->ending_address.ptr); @@ -229,48 +201,46 @@ static void destroy(private_traffic_selector_substructure_t *this) */ traffic_selector_substructure_t *traffic_selector_substructure_create() { - private_traffic_selector_substructure_t *this = malloc_thing(private_traffic_selector_substructure_t); - - /* interface functions */ - this->public.payload_interface.verify = (status_t (*) (payload_t *))verify; - this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules; - this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length; - this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type; - this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type; - this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_payload_type; - this->public.payload_interface.destroy = (void (*) (payload_t *))destroy; - - /* public functions */ - this->public.get_traffic_selector = (traffic_selector_t* (*)(traffic_selector_substructure_t*))get_traffic_selector; - this->public.destroy = (void (*) (traffic_selector_substructure_t *)) destroy; - - /* private variables */ - this->payload_length = TRAFFIC_SELECTOR_HEADER_LENGTH; - this->start_port = 0; - this->end_port = 0; - this->starting_address = chunk_empty; - this->ending_address = chunk_empty; - this->ip_protocol_id = 0; - /* must be set to be valid */ - this->ts_type = TS_IPV4_ADDR_RANGE; - - return (&(this->public)); + private_traffic_selector_substructure_t *this; + + INIT(this, + .public = { + .payload_interface = { + .verify = _verify, + .get_encoding_rules = _get_encoding_rules, + .get_length = _get_length, + .get_next_type = _get_next_type, + .set_next_type = _set_next_type, + .get_type = _get_type, + .destroy = _destroy, + }, + .get_traffic_selector = _get_traffic_selector, + .destroy = _destroy, + }, + .payload_length = TRAFFIC_SELECTOR_HEADER_LENGTH, + /* must be set to be valid */ + .ts_type = TS_IPV4_ADDR_RANGE, + ); + return &this->public; } /* * Described in header */ -traffic_selector_substructure_t *traffic_selector_substructure_create_from_traffic_selector(traffic_selector_t *traffic_selector) +traffic_selector_substructure_t *traffic_selector_substructure_create_from_traffic_selector( + traffic_selector_t *ts) { - private_traffic_selector_substructure_t *this = (private_traffic_selector_substructure_t*)traffic_selector_substructure_create(); - this->ts_type = traffic_selector->get_type(traffic_selector); - this->ip_protocol_id = traffic_selector->get_protocol(traffic_selector); - this->start_port = traffic_selector->get_from_port(traffic_selector); - this->end_port = traffic_selector->get_to_port(traffic_selector); - this->starting_address = chunk_clone(traffic_selector->get_from_address(traffic_selector)); - this->ending_address = chunk_clone(traffic_selector->get_to_address(traffic_selector)); - - compute_length(this); + private_traffic_selector_substructure_t *this; + + this = (private_traffic_selector_substructure_t*)traffic_selector_substructure_create(); + this->ts_type = ts->get_type(ts); + this->ip_protocol_id = ts->get_protocol(ts); + this->start_port = ts->get_from_port(ts); + this->end_port = ts->get_to_port(ts); + this->starting_address = chunk_clone(ts->get_from_address(ts)); + this->ending_address = chunk_clone(ts->get_to_address(ts)); + this->payload_length = TRAFFIC_SELECTOR_HEADER_LENGTH + + this->ending_address.len + this->starting_address.len; - return &(this->public); + return &this->public; } diff --git a/src/libcharon/encoding/payloads/transform_attribute.c b/src/libcharon/encoding/payloads/transform_attribute.c index 8bf2ddef4..7d21258b1 100644 --- a/src/libcharon/encoding/payloads/transform_attribute.c +++ b/src/libcharon/encoding/payloads/transform_attribute.c @@ -1,5 +1,6 @@ /* - * Copyright (C) 2005-2006 Martin Willi + * Copyright (C) 2005-2010 Martin Willi + * Copyright (C) 2010 revosec AG * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil * @@ -26,9 +27,9 @@ typedef struct private_transform_attribute_t private_transform_attribute_t; /** * Private data of an transform_attribute_t object. - * */ struct private_transform_attribute_t { + /** * Public transform_attribute_t interface. */ @@ -70,7 +71,6 @@ ENUM_END(transform_attribute_type_name, KEY_LENGTH); * * The defined offsets are the positions in a object of type * private_transform_attribute_t. - * */ encoding_rule_t transform_attribute_encodings[] = { /* Flag defining the format of this payload */ @@ -78,7 +78,7 @@ encoding_rule_t transform_attribute_encodings[] = { /* type of the attribute as 15 bit unsigned integer */ { ATTRIBUTE_TYPE, offsetof(private_transform_attribute_t, attribute_type) }, /* Length or value, depending on the attribute format flag */ - { ATTRIBUTE_LENGTH_OR_VALUE, offsetof(private_transform_attribute_t, attribute_length_or_value) }, + { ATTRIBUTE_LENGTH_OR_VALUE,offsetof(private_transform_attribute_t, attribute_length_or_value) }, /* Value of attribute if attribute format flag is zero */ { ATTRIBUTE_VALUE, offsetof(private_transform_attribute_t, attribute_value) } }; @@ -95,162 +95,106 @@ encoding_rule_t transform_attribute_encodings[] = { +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ -/** - * Implementation of payload_t.verify. - */ -static status_t verify(private_transform_attribute_t *this) +METHOD(payload_t, verify, status_t, + private_transform_attribute_t *this) { - if (this->attribute_type != KEY_LENGTH) - { - return FAILED; - } - return SUCCESS; } -/** - * Implementation of payload_t.get_encoding_rules. - */ -static void get_encoding_rules(private_transform_attribute_t *this, encoding_rule_t **rules, size_t *rule_count) +METHOD(payload_t, get_encoding_rules, void, + private_transform_attribute_t *this, encoding_rule_t **rules, + size_t *rule_count) { *rules = transform_attribute_encodings; - *rule_count = sizeof(transform_attribute_encodings) / sizeof(encoding_rule_t); + *rule_count = countof(transform_attribute_encodings); } -/** - * Implementation of payload_t.get_type. - */ -static payload_type_t get_type(private_transform_attribute_t *this) +METHOD(payload_t, get_type, payload_type_t, + private_transform_attribute_t *this) { return TRANSFORM_ATTRIBUTE; } -/** - * Implementation of payload_t.get_next_type. - */ -static payload_type_t get_next_type(private_transform_attribute_t *this) +METHOD(payload_t, get_next_type, payload_type_t, + private_transform_attribute_t *this) { - return (NO_PAYLOAD); + return NO_PAYLOAD; } -/** - * Implementation of payload_t.set_next_type. - */ -static void set_next_type(private_transform_attribute_t *this,payload_type_t type) +METHOD(payload_t, set_next_type, void, + private_transform_attribute_t *this, payload_type_t type) { } -/** - * Implementation of transform_attribute_t.get_length. - */ -static size_t get_length(private_transform_attribute_t *this) +METHOD(payload_t, get_length, size_t, + private_transform_attribute_t *this) { - if (this->attribute_format == TRUE) + if (this->attribute_format) { - /*Attribute size is only 4 byte */ return 4; } - return (this->attribute_length_or_value + 4); + return this->attribute_length_or_value + 4; } -/** - * Implementation of transform_attribute_t.set_value_chunk. - */ -static void set_value_chunk(private_transform_attribute_t *this, chunk_t value) +METHOD(transform_attribute_t, set_value_chunk, void, + private_transform_attribute_t *this, chunk_t value) { - if (this->attribute_value.ptr != NULL) - { - /* free existing value */ - free(this->attribute_value.ptr); - this->attribute_value.ptr = NULL; - this->attribute_value.len = 0; - - } + chunk_free(&this->attribute_value); - if (value.len > 2) + if (value.len != 2) { - this->attribute_value.ptr = clalloc(value.ptr,value.len); - this->attribute_value.len = value.len; + this->attribute_value = chunk_clone(value); this->attribute_length_or_value = value.len; - /* attribute has not a fixed length */ this->attribute_format = FALSE; } else { - memcpy(&(this->attribute_length_or_value),value.ptr,value.len); + memcpy(&this->attribute_length_or_value, value.ptr, value.len); } } -/** - * Implementation of transform_attribute_t.set_value. - */ -static void set_value(private_transform_attribute_t *this, u_int16_t value) +METHOD(transform_attribute_t, set_value, void, + private_transform_attribute_t *this, u_int16_t value) { - if (this->attribute_value.ptr != NULL) - { - /* free existing value */ - free(this->attribute_value.ptr); - this->attribute_value.ptr = NULL; - this->attribute_value.len = 0; - - } + chunk_free(&this->attribute_value); this->attribute_length_or_value = value; + this->attribute_format = TRUE; } -/** - * Implementation of transform_attribute_t.get_value_chunk. - */ -static chunk_t get_value_chunk (private_transform_attribute_t *this) +METHOD(transform_attribute_t, get_value_chunk, chunk_t, + private_transform_attribute_t *this) { - chunk_t value; - - if (this->attribute_format == FALSE) + if (this->attribute_format) { - value.ptr = this->attribute_value.ptr; - value.len = this->attribute_value.len; + return chunk_from_thing(this->attribute_length_or_value); } - else - { - value.ptr = (void *) &(this->attribute_length_or_value); - value.len = 2; - } - - return value; + return this->attribute_value; } -/** - * Implementation of transform_attribute_t.get_value. - */ -static u_int16_t get_value (private_transform_attribute_t *this) +METHOD(transform_attribute_t, get_value, u_int16_t, + private_transform_attribute_t *this) { return this->attribute_length_or_value; } - -/** - * Implementation of transform_attribute_t.set_attribute_type. - */ -static void set_attribute_type (private_transform_attribute_t *this, u_int16_t type) +METHOD(transform_attribute_t, set_attribute_type, void, + private_transform_attribute_t *this, u_int16_t type) { this->attribute_type = type & 0x7FFF; } -/** - * Implementation of transform_attribute_t.get_attribute_type. - */ -static u_int16_t get_attribute_type (private_transform_attribute_t *this) +METHOD(transform_attribute_t, get_attribute_type, u_int16_t, + private_transform_attribute_t *this) { return this->attribute_type; } -/** - * Implementation of transform_attribute_t.clone. - */ -static transform_attribute_t * _clone(private_transform_attribute_t *this) +METHOD(transform_attribute_t, clone_, transform_attribute_t*, + private_transform_attribute_t *this) { private_transform_attribute_t *new_clone; - new_clone = (private_transform_attribute_t *) transform_attribute_create(); + new_clone = (private_transform_attribute_t *)transform_attribute_create(); new_clone->attribute_format = this->attribute_format; new_clone->attribute_type = this->attribute_type; @@ -258,22 +202,15 @@ static transform_attribute_t * _clone(private_transform_attribute_t *this) if (!new_clone->attribute_format) { - new_clone->attribute_value.ptr = clalloc(this->attribute_value.ptr,this->attribute_value.len); - new_clone->attribute_value.len = this->attribute_value.len; + new_clone->attribute_value = chunk_clone(this->attribute_value); } - - return (transform_attribute_t *) new_clone; + return &new_clone->public; } -/** - * Implementation of transform_attribute_t.destroy and payload_t.destroy. - */ -static void destroy(private_transform_attribute_t *this) +METHOD2(payload_t, transform_attribute_t, destroy, void, + private_transform_attribute_t *this) { - if (this->attribute_value.ptr != NULL) - { - free(this->attribute_value.ptr); - } + free(this->attribute_value.ptr); free(this); } @@ -282,35 +219,31 @@ static void destroy(private_transform_attribute_t *this) */ transform_attribute_t *transform_attribute_create() { - private_transform_attribute_t *this = malloc_thing(private_transform_attribute_t); - - /* payload interface */ - this->public.payload_interface.verify = (status_t (*) (payload_t *))verify; - this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules; - this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length; - this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type; - this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type; - this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type; - this->public.payload_interface.destroy = (void (*) (payload_t *))destroy; - - /* public functions */ - this->public.set_value_chunk = (void (*) (transform_attribute_t *,chunk_t)) set_value_chunk; - this->public.set_value = (void (*) (transform_attribute_t *,u_int16_t)) set_value; - this->public.get_value_chunk = (chunk_t (*) (transform_attribute_t *)) get_value_chunk; - this->public.get_value = (u_int16_t (*) (transform_attribute_t *)) get_value; - this->public.set_attribute_type = (void (*) (transform_attribute_t *,u_int16_t type)) set_attribute_type; - this->public.get_attribute_type = (u_int16_t (*) (transform_attribute_t *)) get_attribute_type; - this->public.clone = (transform_attribute_t * (*) (transform_attribute_t *)) _clone; - this->public.destroy = (void (*) (transform_attribute_t *)) destroy; - - /* set default values of the fields */ - this->attribute_format = TRUE; - this->attribute_type = 0; - this->attribute_length_or_value = 0; - this->attribute_value.ptr = NULL; - this->attribute_value.len = 0; - - return (&(this->public)); + private_transform_attribute_t *this; + + INIT(this, + .public = { + .payload_interface = { + .verify = _verify, + .get_encoding_rules = _get_encoding_rules, + .get_length = _get_length, + .get_next_type = _get_next_type, + .set_next_type = _set_next_type, + .get_type = _get_type, + .destroy = _destroy, + }, + .set_value_chunk = _set_value_chunk, + .set_value = _set_value, + .get_value_chunk = _get_value_chunk, + .get_value = _get_value, + .set_attribute_type = _set_attribute_type, + .get_attribute_type = _get_attribute_type, + .clone = _clone_, + .destroy = _destroy, + }, + .attribute_format = TRUE, + ); + return &this->public; } /* @@ -319,7 +252,7 @@ transform_attribute_t *transform_attribute_create() transform_attribute_t *transform_attribute_create_key_length(u_int16_t key_length) { transform_attribute_t *attribute = transform_attribute_create(); - attribute->set_attribute_type(attribute,KEY_LENGTH); - attribute->set_value(attribute,key_length); + attribute->set_attribute_type(attribute, KEY_LENGTH); + attribute->set_value(attribute, key_length); return attribute; } diff --git a/src/libcharon/encoding/payloads/transform_substructure.c b/src/libcharon/encoding/payloads/transform_substructure.c index c94f6c1a2..0428da726 100644 --- a/src/libcharon/encoding/payloads/transform_substructure.c +++ b/src/libcharon/encoding/payloads/transform_substructure.c @@ -1,5 +1,6 @@ /* - * Copyright (C) 2005-2006 Martin Willi + * Copyright (C) 2005-2010 Martin Willi + * Copyright (C) 2010 revosec AG * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil * @@ -24,14 +25,13 @@ #include <utils/linked_list.h> #include <daemon.h> - typedef struct private_transform_substructure_t private_transform_substructure_t; /** * Private data of an transform_substructure_t object. - * */ struct private_transform_substructure_t { + /** * Public transform_substructure_t interface. */ @@ -41,14 +41,16 @@ struct private_transform_substructure_t { * Next payload type. */ u_int8_t next_payload; - + /** + * Reserved bytes + */ + u_int8_t reserved[2]; /** * Length of this payload. */ u_int16_t transform_length; - /** * Type of the transform. */ @@ -65,30 +67,28 @@ struct private_transform_substructure_t { linked_list_t *attributes; }; - /** * Encoding rules to parse or generate a Transform substructure. * * The defined offsets are the positions in a object of type * private_transform_substructure_t. - * */ encoding_rule_t transform_substructure_encodings[] = { /* 1 Byte next payload type, stored in the field next_payload */ - { U_INT_8, offsetof(private_transform_substructure_t, next_payload) }, - /* Reserved Byte is skipped */ - { RESERVED_BYTE, 0 }, + { U_INT_8, offsetof(private_transform_substructure_t, next_payload) }, + /* 1 Reserved Byte */ + { RESERVED_BYTE, offsetof(private_transform_substructure_t, reserved[0]) }, /* Length of the whole transform substructure*/ - { PAYLOAD_LENGTH, offsetof(private_transform_substructure_t, transform_length) }, + { PAYLOAD_LENGTH, offsetof(private_transform_substructure_t, transform_length)}, /* transform type is a number of 8 bit */ - { U_INT_8, offsetof(private_transform_substructure_t, transform_type) }, - /* Reserved Byte is skipped */ - { RESERVED_BYTE, 0 }, + { U_INT_8, offsetof(private_transform_substructure_t, transform_type) }, + /* 1 Reserved Byte */ + { RESERVED_BYTE, offsetof(private_transform_substructure_t, reserved[1]) }, /* tranform ID is a number of 8 bit */ - { U_INT_16, offsetof(private_transform_substructure_t, transform_id) }, + { U_INT_16, offsetof(private_transform_substructure_t, transform_id) }, /* Attributes are stored in a transform attribute, offset points to a linked_list_t pointer */ - { TRANSFORM_ATTRIBUTES, offsetof(private_transform_substructure_t, attributes) } + { TRANSFORM_ATTRIBUTES, offsetof(private_transform_substructure_t, attributes) } }; /* @@ -105,19 +105,15 @@ encoding_rule_t transform_substructure_encodings[] = { +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ - -/** - * Implementation of payload_t.verify. - */ -static status_t verify(private_transform_substructure_t *this) +METHOD(payload_t, verify, status_t, + private_transform_substructure_t *this) { status_t status = SUCCESS; - iterator_t *iterator; - payload_t *current_attributes; + enumerator_t *enumerator; + payload_t *attribute; - if ((this->next_payload != NO_PAYLOAD) && (this->next_payload != 3)) + if (this->next_payload != NO_PAYLOAD && this->next_payload != 3) { - /* must be 0 or 3 */ DBG1(DBG_ENC, "inconsistent next payload"); return FAILED; } @@ -138,45 +134,41 @@ static status_t verify(private_transform_substructure_t *this) return FAILED; } } - iterator = this->attributes->create_iterator(this->attributes,TRUE); - while(iterator->iterate(iterator, (void**)¤t_attributes)) + enumerator = this->attributes->create_enumerator(this->attributes); + while (enumerator->enumerate(enumerator, &attribute)) { - status = current_attributes->verify(current_attributes); + status = attribute->verify(attribute); if (status != SUCCESS) { DBG1(DBG_ENC, "TRANSFORM_ATTRIBUTE verification failed"); + break; } } - iterator->destroy(iterator); + enumerator->destroy(enumerator); /* proposal number is checked in SA payload */ return status; } -/** - * Implementation of payload_t.get_encoding_rules. - */ -static void get_encoding_rules(private_transform_substructure_t *this, encoding_rule_t **rules, size_t *rule_count) +METHOD(payload_t, get_encoding_rules, void, + private_transform_substructure_t *this, encoding_rule_t **rules, + size_t *rule_count) { *rules = transform_substructure_encodings; - *rule_count = sizeof(transform_substructure_encodings) / sizeof(encoding_rule_t); + *rule_count = countof(transform_substructure_encodings); } -/** - * Implementation of payload_t.get_type. - */ -static payload_type_t get_type(private_transform_substructure_t *this) +METHOD(payload_t, get_type, payload_type_t, + private_transform_substructure_t *this) { return TRANSFORM_SUBSTRUCTURE; } -/** - * Implementation of payload_t.get_next_type. - */ -static payload_type_t get_next_type(private_transform_substructure_t *this) +METHOD(payload_t, get_next_type, payload_type_t, + private_transform_substructure_t *this) { - return (this->next_payload); + return this->next_payload; } /** @@ -184,154 +176,69 @@ static payload_type_t get_next_type(private_transform_substructure_t *this) */ static void compute_length (private_transform_substructure_t *this) { - iterator_t *iterator; - payload_t *current_attribute; - size_t length = TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH; + enumerator_t *enumerator; + payload_t *attribute; - iterator = this->attributes->create_iterator(this->attributes,TRUE); - while (iterator->iterate(iterator, (void**)¤t_attribute)) + this->transform_length = TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH; + enumerator = this->attributes->create_enumerator(this->attributes); + while (enumerator->enumerate(enumerator, &attribute)) { - length += current_attribute->get_length(current_attribute); + this->transform_length += attribute->get_length(attribute); } - iterator->destroy(iterator); - - this->transform_length = length; + enumerator->destroy(enumerator); } -/** - * Implementation of payload_t.get_length. - */ -static size_t get_length(private_transform_substructure_t *this) +METHOD(payload_t, get_length, size_t, + private_transform_substructure_t *this) { - compute_length(this); return this->transform_length; } -/** - * Implementation of transform_substructure_t.create_transform_attribute_iterator. - */ -static iterator_t *create_transform_attribute_iterator (private_transform_substructure_t *this,bool forward) -{ - return this->attributes->create_iterator(this->attributes,forward); -} - -/** - * Implementation of transform_substructure_t.add_transform_attribute. - */ -static void add_transform_attribute (private_transform_substructure_t *this,transform_attribute_t *attribute) -{ - this->attributes->insert_last(this->attributes,(void *) attribute); - compute_length(this); -} - -/** - * Implementation of transform_substructure_t.set_is_last_transform. - */ -static void set_is_last_transform (private_transform_substructure_t *this, bool is_last) -{ - this->next_payload = (is_last) ? 0: TRANSFORM_TYPE_VALUE; -} - -/** - * Implementation of transform_substructure_t.get_is_last_transform. - */ -static bool get_is_last_transform (private_transform_substructure_t *this) -{ - return ((this->next_payload == TRANSFORM_TYPE_VALUE) ? FALSE : TRUE); -} - -/** - * Implementation of payload_t.set_next_type. - */ -static void set_next_type(private_transform_substructure_t *this,payload_type_t type) +METHOD(transform_substructure_t, set_is_last_transform, void, + private_transform_substructure_t *this, bool is_last) { + this->next_payload = is_last ? 0: TRANSFORM_TYPE_VALUE; } -/** - * Implementation of transform_substructure_t.set_transform_type. - */ -static void set_transform_type (private_transform_substructure_t *this,u_int8_t type) +METHOD(payload_t, set_next_type, void, + private_transform_substructure_t *this,payload_type_t type) { - this->transform_type = type; } -/** - * Implementation of transform_substructure_t.get_transform_type. - */ -static u_int8_t get_transform_type (private_transform_substructure_t *this) +METHOD(transform_substructure_t, get_transform_type, u_int8_t, + private_transform_substructure_t *this) { return this->transform_type; } -/** - * Implementation of transform_substructure_t.set_transform_id. - */ -static void set_transform_id (private_transform_substructure_t *this,u_int16_t id) -{ - this->transform_id = id; -} - -/** - * Implementation of transform_substructure_t.get_transform_id. - */ -static u_int16_t get_transform_id (private_transform_substructure_t *this) +METHOD(transform_substructure_t, get_transform_id, u_int16_t, + private_transform_substructure_t *this) { return this->transform_id; } -/** - * Implementation of transform_substructure_t.clone. - */ -static transform_substructure_t *clone_(private_transform_substructure_t *this) -{ - private_transform_substructure_t *clone; - iterator_t *attributes; - transform_attribute_t *current_attribute; - - clone = (private_transform_substructure_t *) transform_substructure_create(); - clone->next_payload = this->next_payload; - clone->transform_type = this->transform_type; - clone->transform_id = this->transform_id; - - attributes = this->attributes->create_iterator(this->attributes, FALSE); - while (attributes->iterate(attributes, (void**)¤t_attribute)) - { - current_attribute = current_attribute->clone(current_attribute); - clone->public.add_transform_attribute(&clone->public, current_attribute); - } - attributes->destroy(attributes); - - return &clone->public; -} - - -/** - * Implementation of transform_substructure_t.get_key_length. - */ -static status_t get_key_length(private_transform_substructure_t *this, u_int16_t *key_length) +METHOD(transform_substructure_t, get_key_length, status_t, + private_transform_substructure_t *this, u_int16_t *key_length) { - iterator_t *attributes; - transform_attribute_t *current_attribute; + enumerator_t *enumerator; + transform_attribute_t *attribute; - attributes = this->attributes->create_iterator(this->attributes, TRUE); - while (attributes->iterate(attributes, (void**)¤t_attribute)) + enumerator = this->attributes->create_enumerator(this->attributes); + while (enumerator->enumerate(enumerator, &attribute)) { - if (current_attribute->get_attribute_type(current_attribute) == KEY_LENGTH) + if (attribute->get_attribute_type(attribute) == KEY_LENGTH) { - *key_length = current_attribute->get_value(current_attribute); - attributes->destroy(attributes); + *key_length = attribute->get_value(attribute); + enumerator->destroy(enumerator); return SUCCESS; } } - attributes->destroy(attributes); + enumerator->destroy(enumerator); return FAILED; } - -/** - * Implementation of transform_substructure_t.destroy and payload_t.destroy. - */ -static void destroy(private_transform_substructure_t *this) +METHOD2(payload_t, transform_substructure_t, destroy, void, + private_transform_substructure_t *this) { this->attributes->destroy_offset(this->attributes, offsetof(transform_attribute_t, destroy)); @@ -343,60 +250,50 @@ static void destroy(private_transform_substructure_t *this) */ transform_substructure_t *transform_substructure_create() { - private_transform_substructure_t *this = malloc_thing(private_transform_substructure_t); - - /* payload interface */ - this->public.payload_interface.verify = (status_t (*) (payload_t *))verify; - this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules; - this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length; - this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type; - this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type; - this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type; - this->public.payload_interface.destroy = (void (*) (payload_t *))destroy; - - /* public functions */ - this->public.create_transform_attribute_iterator = (iterator_t * (*) (transform_substructure_t *,bool)) create_transform_attribute_iterator; - this->public.add_transform_attribute = (void (*) (transform_substructure_t *,transform_attribute_t *)) add_transform_attribute; - this->public.set_is_last_transform = (void (*) (transform_substructure_t *,bool)) set_is_last_transform; - this->public.get_is_last_transform = (bool (*) (transform_substructure_t *)) get_is_last_transform; - this->public.set_transform_type = (void (*) (transform_substructure_t *,u_int8_t)) set_transform_type; - this->public.get_transform_type = (u_int8_t (*) (transform_substructure_t *)) get_transform_type; - this->public.set_transform_id = (void (*) (transform_substructure_t *,u_int16_t)) set_transform_id; - this->public.get_transform_id = (u_int16_t (*) (transform_substructure_t *)) get_transform_id; - this->public.get_key_length = (status_t (*) (transform_substructure_t *,u_int16_t *)) get_key_length; - this->public.clone = (transform_substructure_t* (*) (transform_substructure_t *)) clone_; - this->public.destroy = (void (*) (transform_substructure_t *)) destroy; - - /* set default values of the fields */ - this->next_payload = NO_PAYLOAD; - this->transform_length = TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH; - this->transform_id = 0; - this->transform_type = 0; - this->attributes = linked_list_create(); - - return (&(this->public)); + private_transform_substructure_t *this; + + INIT(this, + .public = { + .payload_interface = { + .verify = _verify, + .get_encoding_rules = _get_encoding_rules, + .get_length = _get_length, + .get_next_type = _get_next_type, + .set_next_type = _set_next_type, + .get_type = _get_type, + .destroy = _destroy, + }, + .set_is_last_transform = _set_is_last_transform, + .get_transform_type = _get_transform_type, + .get_transform_id = _get_transform_id, + .get_key_length = _get_key_length, + .destroy = _destroy, + }, + .next_payload = NO_PAYLOAD, + .transform_length = TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH, + .attributes = linked_list_create(), + ); + return &this->public; } /* * Described in header */ transform_substructure_t *transform_substructure_create_type( - transform_type_t transform_type, - u_int16_t transform_id, u_int16_t key_length) + transform_type_t type, u_int16_t id, u_int16_t key_length) { - transform_substructure_t *transform = transform_substructure_create(); + private_transform_substructure_t *this; - transform->set_transform_type(transform,transform_type); - transform->set_transform_id(transform,transform_id); + this = (private_transform_substructure_t*)transform_substructure_create(); + this->transform_type = type; + this->transform_id = id; if (key_length) { - transform_attribute_t *attribute; - - attribute = transform_attribute_create_key_length(key_length); - transform->add_transform_attribute(transform, attribute); - + this->attributes->insert_last(this->attributes, + (void*)transform_attribute_create_key_length(key_length)); + compute_length(this); } - return transform; + return &this->public; } diff --git a/src/libcharon/encoding/payloads/transform_substructure.h b/src/libcharon/encoding/payloads/transform_substructure.h index 5d31f8c0a..c961700a4 100644 --- a/src/libcharon/encoding/payloads/transform_substructure.h +++ b/src/libcharon/encoding/payloads/transform_substructure.h @@ -34,7 +34,6 @@ typedef struct transform_substructure_t transform_substructure_t; #include <crypto/crypters/crypter.h> #include <config/proposal.h> - /** * IKEv1 Value for a transform payload. */ @@ -45,32 +44,19 @@ typedef struct transform_substructure_t transform_substructure_t; */ #define TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH 8 - /** * Class representing an IKEv2- TRANSFORM SUBSTRUCTURE. * * The TRANSFORM SUBSTRUCTURE format is described in RFC section 3.3.2. */ struct transform_substructure_t { + /** * The payload_t interface. */ payload_t payload_interface; /** - * Creates an iterator of stored transform_attribute_t objects. - * - * When deleting an transform attribute using this iterator, - * the length of this transform substructure has to be refreshed - * by calling get_length(). - * - * @param forward iterator direction (TRUE: front to end) - * @return created iterator_t object. - */ - iterator_t * (*create_transform_attribute_iterator) ( - transform_substructure_t *this, bool forward); - - /** * Adds a transform_attribute_t object to this object. * * @param proposal transform_attribute_t object to add @@ -89,20 +75,6 @@ struct transform_substructure_t { void (*set_is_last_transform) (transform_substructure_t *this, bool is_last); /** - * Checks if this is the last transform. - * - * @return TRUE if this is the last Transform, FALSE otherwise - */ - bool (*get_is_last_transform) (transform_substructure_t *this); - - /** - * Sets transform type of the current transform substructure. - * - * @param type type value to set - */ - void (*set_transform_type) (transform_substructure_t *this, u_int8_t type); - - /** * get transform type of the current transform. * * @return Transform type of current transform substructure. @@ -110,21 +82,14 @@ struct transform_substructure_t { u_int8_t (*get_transform_type) (transform_substructure_t *this); /** - * Sets transform id of the current transform substructure. - * - * @param id transform id to set - */ - void (*set_transform_id) (transform_substructure_t *this, u_int16_t id); - - /** - * get transform id of the current transform. + * Get transform id of the current transform. * * @return Transform id of current transform substructure. */ u_int16_t (*get_transform_id) (transform_substructure_t *this); /** - * get transform id of the current transform. + * Get transform id of the current transform. * * @param key_length The key length is written to this location * @return @@ -136,13 +101,6 @@ struct transform_substructure_t { u_int16_t *key_length); /** - * Clones an transform_substructure_t object. - * - * @return cloned transform_substructure_t object - */ - transform_substructure_t* (*clone) (transform_substructure_t *this); - - /** * Destroys an transform_substructure_t object. */ void (*destroy) (transform_substructure_t *this); @@ -151,24 +109,19 @@ struct transform_substructure_t { /** * Creates an empty transform_substructure_t object. * - * @return created transform_substructure_t object + * @return created transform_substructure_t object */ transform_substructure_t *transform_substructure_create(void); /** * Creates an empty transform_substructure_t object. * - * The key length is used for the transport types ENCRYPTION_ALGORITHM, - * PSEUDO_RANDOM_FUNCTION, INTEGRITY_ALGORITHM. For all - * other transport types the key_length parameter is not used - * - * @param transform_type type of transform to create - * @param transform_id transform id specifying the specific algorithm of a transform type - * @param key_length Key length for key lenght attribute - * @return transform_substructure_t object + * @param type type of transform to create + * @param id transform id specifc for the transform type + * @param key_length key length for key lenght attribute, 0 to omit + * @return transform_substructure_t object */ transform_substructure_t *transform_substructure_create_type( - transform_type_t transform_type, u_int16_t transform_id, - u_int16_t key_length); + transform_type_t type, u_int16_t id, u_int16_t key_length); #endif /** TRANSFORM_SUBSTRUCTURE_H_ @}*/ diff --git a/src/libcharon/encoding/payloads/ts_payload.c b/src/libcharon/encoding/payloads/ts_payload.c index 6bf3e4293..28f760e40 100644 --- a/src/libcharon/encoding/payloads/ts_payload.c +++ b/src/libcharon/encoding/payloads/ts_payload.c @@ -1,5 +1,6 @@ /* - * Copyright (C) 2005-2006 Martin Willi + * Copyright (C) 2005-2010 Martin Willi + * Copyright (C) 2010 revosec AG * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil * @@ -25,9 +26,9 @@ typedef struct private_ts_payload_t private_ts_payload_t; /** * Private data of an ts_payload_t object. - * */ struct private_ts_payload_t { + /** * Public ts_payload_t interface. */ @@ -49,6 +50,16 @@ struct private_ts_payload_t { bool critical; /** + * reserved bits + */ + bool reserved_bit[7]; + + /** + * reserved bytes + */ + bool reserved_byte[3]; + + /** * Length of this payload. */ u_int16_t payload_length; @@ -56,12 +67,12 @@ struct private_ts_payload_t { /** * Number of traffic selectors */ - u_int8_t number_of_traffic_selectors; + u_int8_t ts_num; /** * Contains the traffic selectors of type traffic_selector_substructure_t. */ - linked_list_t *traffic_selectors; + linked_list_t *substrs; }; /** @@ -69,31 +80,30 @@ struct private_ts_payload_t { * * The defined offsets are the positions in a object of type * private_ts_payload_t. - * */ encoding_rule_t ts_payload_encodings[] = { /* 1 Byte next payload type, stored in the field next_payload */ - { U_INT_8, offsetof(private_ts_payload_t, next_payload) }, + { U_INT_8, offsetof(private_ts_payload_t, next_payload) }, /* the critical bit */ - { FLAG, offsetof(private_ts_payload_t, critical) }, - /* 7 Bit reserved bits, nowhere stored */ - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, + { FLAG, offsetof(private_ts_payload_t, critical) }, + /* 7 Bit reserved bits */ + { RESERVED_BIT, offsetof(private_ts_payload_t, reserved_bit[0]) }, + { RESERVED_BIT, offsetof(private_ts_payload_t, reserved_bit[1]) }, + { RESERVED_BIT, offsetof(private_ts_payload_t, reserved_bit[2]) }, + { RESERVED_BIT, offsetof(private_ts_payload_t, reserved_bit[3]) }, + { RESERVED_BIT, offsetof(private_ts_payload_t, reserved_bit[4]) }, + { RESERVED_BIT, offsetof(private_ts_payload_t, reserved_bit[5]) }, + { RESERVED_BIT, offsetof(private_ts_payload_t, reserved_bit[6]) }, /* Length of the whole payload*/ - { PAYLOAD_LENGTH, offsetof(private_ts_payload_t, payload_length)}, + { PAYLOAD_LENGTH, offsetof(private_ts_payload_t, payload_length) }, /* 1 Byte TS type*/ - { U_INT_8, offsetof(private_ts_payload_t, number_of_traffic_selectors) }, + { U_INT_8, offsetof(private_ts_payload_t, ts_num) }, /* 3 reserved bytes */ - { RESERVED_BYTE, 0 }, - { RESERVED_BYTE, 0 }, - { RESERVED_BYTE, 0 }, + { RESERVED_BYTE, offsetof(private_ts_payload_t, reserved_byte[0])}, + { RESERVED_BYTE, offsetof(private_ts_payload_t, reserved_byte[1])}, + { RESERVED_BYTE, offsetof(private_ts_payload_t, reserved_byte[2])}, /* some ts data bytes, length is defined in PAYLOAD_LENGTH */ - { TRAFFIC_SELECTORS, offsetof(private_ts_payload_t, traffic_selectors) } + { TRAFFIC_SELECTORS,offsetof(private_ts_payload_t, substrs) } }; /* @@ -110,71 +120,56 @@ encoding_rule_t ts_payload_encodings[] = { +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ -/** - * Implementation of payload_t.verify. - */ -static status_t verify(private_ts_payload_t *this) +METHOD(payload_t, verify, status_t, + private_ts_payload_t *this) { - iterator_t *iterator; - payload_t *current_traffic_selector; + enumerator_t *enumerator; + payload_t *substr; status_t status = SUCCESS; - if (this->number_of_traffic_selectors != (this->traffic_selectors->get_count(this->traffic_selectors))) + if (this->ts_num != this->substrs->get_count(this->substrs)) { - /* must be the same */ return FAILED; } - - iterator = this->traffic_selectors->create_iterator(this->traffic_selectors,TRUE); - while(iterator->iterate(iterator, (void**)¤t_traffic_selector)) + enumerator = this->substrs->create_enumerator(this->substrs); + while (enumerator->enumerate(enumerator, &substr)) { - status = current_traffic_selector->verify(current_traffic_selector); + status = substr->verify(substr); if (status != SUCCESS) { break; } } - iterator->destroy(iterator); + enumerator->destroy(enumerator); return status; } -/** - * Implementation of ts_payload_t.get_encoding_rules. - */ -static void get_encoding_rules(private_ts_payload_t *this, encoding_rule_t **rules, size_t *rule_count) +METHOD(payload_t, get_encoding_rules, void, + private_ts_payload_t *this, encoding_rule_t **rules, size_t *rule_count) { *rules = ts_payload_encodings; - *rule_count = sizeof(ts_payload_encodings) / sizeof(encoding_rule_t); + *rule_count = countof(ts_payload_encodings); } -/** - * Implementation of payload_t.get_type. - */ -static payload_type_t get_payload_type(private_ts_payload_t *this) +METHOD(payload_t, get_type, payload_type_t, + private_ts_payload_t *this) { if (this->is_initiator) { return TRAFFIC_SELECTOR_INITIATOR; } - else - { - return TRAFFIC_SELECTOR_RESPONDER; - } + return TRAFFIC_SELECTOR_RESPONDER; } -/** - * Implementation of payload_t.get_next_type. - */ -static payload_type_t get_next_type(private_ts_payload_t *this) +METHOD(payload_t, get_next_type, payload_type_t, + private_ts_payload_t *this) { - return (this->next_payload); + return this->next_payload; } -/** - * Implementation of payload_t.set_next_type. - */ -static void set_next_type(private_ts_payload_t *this,payload_type_t type) +METHOD(payload_t, set_next_type, void, + private_ts_payload_t *this,payload_type_t type) { this->next_payload = type; } @@ -182,95 +177,64 @@ static void set_next_type(private_ts_payload_t *this,payload_type_t type) /** * recompute the length of the payload. */ -static void compute_length (private_ts_payload_t *this) +static void compute_length(private_ts_payload_t *this) { - iterator_t *iterator; - size_t ts_count = 0; - size_t length = TS_PAYLOAD_HEADER_LENGTH; - payload_t *current_traffic_selector; + enumerator_t *enumerator; + payload_t *subst; - iterator = this->traffic_selectors->create_iterator(this->traffic_selectors,TRUE); - while (iterator->iterate(iterator, (void**)¤t_traffic_selector)) + this->payload_length = TS_PAYLOAD_HEADER_LENGTH; + this->ts_num = 0; + enumerator = this->substrs->create_enumerator(this->substrs); + while (enumerator->enumerate(enumerator, &subst)) { - length += current_traffic_selector->get_length(current_traffic_selector); - ts_count++; + this->payload_length += subst->get_length(subst); + this->ts_num++; } - iterator->destroy(iterator); - - this->number_of_traffic_selectors= ts_count; - this->payload_length = length; + enumerator->destroy(enumerator); } -/** - * Implementation of payload_t.get_length. - */ -static size_t get_length(private_ts_payload_t *this) +METHOD(payload_t, get_length, size_t, + private_ts_payload_t *this) { - compute_length(this); return this->payload_length; } -/** - * Implementation of ts_payload_t.get_initiator. - */ -static bool get_initiator (private_ts_payload_t *this) +METHOD(ts_payload_t, get_initiator, bool, + private_ts_payload_t *this) { - return (this->is_initiator); + return this->is_initiator; } -/** - * Implementation of ts_payload_t.set_initiator. - */ -static void set_initiator (private_ts_payload_t *this,bool is_initiator) +METHOD(ts_payload_t, set_initiator, void, + private_ts_payload_t *this,bool is_initiator) { this->is_initiator = is_initiator; } -/** - * Implementation of ts_payload_t.add_traffic_selector_substructure. - */ -static void add_traffic_selector_substructure (private_ts_payload_t *this,traffic_selector_substructure_t *traffic_selector) -{ - this->traffic_selectors->insert_last(this->traffic_selectors,traffic_selector); - this->number_of_traffic_selectors = this->traffic_selectors->get_count(this->traffic_selectors); -} - -/** - * Implementation of ts_payload_t.create_traffic_selector_substructure_iterator. - */ -static iterator_t * create_traffic_selector_substructure_iterator (private_ts_payload_t *this, bool forward) -{ - return this->traffic_selectors->create_iterator(this->traffic_selectors,forward); -} - -/** - * Implementation of ts_payload_t.get_traffic_selectors. - */ -static linked_list_t *get_traffic_selectors(private_ts_payload_t *this) +METHOD(ts_payload_t, get_traffic_selectors, linked_list_t*, + private_ts_payload_t *this) { traffic_selector_t *ts; - iterator_t *iterator; - traffic_selector_substructure_t *ts_substructure; - linked_list_t *ts_list = linked_list_create(); + enumerator_t *enumerator; + traffic_selector_substructure_t *subst; + linked_list_t *list; - iterator = this->traffic_selectors->create_iterator(this->traffic_selectors, TRUE); - while (iterator->iterate(iterator, (void**)&ts_substructure)) + list = linked_list_create(); + enumerator = this->substrs->create_enumerator(this->substrs); + while (enumerator->enumerate(enumerator, &subst)) { - ts = ts_substructure->get_traffic_selector(ts_substructure); - ts_list->insert_last(ts_list, (void*)ts); + ts = subst->get_traffic_selector(subst); + list->insert_last(list, ts); } - iterator->destroy(iterator); + enumerator->destroy(enumerator); - return ts_list; + return list; } -/** - * Implementation of payload_t.destroy and ts_payload_t.destroy. - */ -static void destroy(private_ts_payload_t *this) +METHOD2(payload_t, ts_payload_t, destroy, void, + private_ts_payload_t *this) { - this->traffic_selectors->destroy_offset(this->traffic_selectors, - offsetof(payload_t, destroy)); + this->substrs->destroy_offset(this->substrs, offsetof(payload_t, destroy)); free(this); } @@ -279,56 +243,53 @@ static void destroy(private_ts_payload_t *this) */ ts_payload_t *ts_payload_create(bool is_initiator) { - private_ts_payload_t *this = malloc_thing(private_ts_payload_t); - - /* interface functions */ - this->public.payload_interface.verify = (status_t (*) (payload_t *))verify; - this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules; - this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length; - this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type; - this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type; - this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_payload_type; - this->public.payload_interface.destroy = (void (*) (payload_t *))destroy; - - /* public functions */ - this->public.destroy = (void (*) (ts_payload_t *)) destroy; - this->public.get_initiator = (bool (*) (ts_payload_t *)) get_initiator; - this->public.set_initiator = (void (*) (ts_payload_t *,bool)) set_initiator; - this->public.add_traffic_selector_substructure = (void (*) (ts_payload_t *,traffic_selector_substructure_t *)) add_traffic_selector_substructure; - this->public.create_traffic_selector_substructure_iterator = (iterator_t* (*) (ts_payload_t *,bool)) create_traffic_selector_substructure_iterator; - this->public.get_traffic_selectors = (linked_list_t *(*) (ts_payload_t *)) get_traffic_selectors; - - /* private variables */ - this->critical = FALSE; - this->next_payload = NO_PAYLOAD; - this->payload_length =TS_PAYLOAD_HEADER_LENGTH; - this->is_initiator = is_initiator; - this->number_of_traffic_selectors = 0; - this->traffic_selectors = linked_list_create(); + private_ts_payload_t *this; - return &(this->public); + INIT(this, + .public = { + .payload_interface = { + .verify = _verify, + .get_encoding_rules = _get_encoding_rules, + .get_length = _get_length, + .get_next_type = _get_next_type, + .set_next_type = _set_next_type, + .get_type = _get_type, + .destroy = _destroy, + }, + .get_initiator = _get_initiator, + .set_initiator = _set_initiator, + .get_traffic_selectors = _get_traffic_selectors, + .destroy = _destroy, + }, + .next_payload = NO_PAYLOAD, + .payload_length = TS_PAYLOAD_HEADER_LENGTH, + .is_initiator = is_initiator, + .substrs = linked_list_create(), + ); + return &this->public; } /* * Described in header */ -ts_payload_t *ts_payload_create_from_traffic_selectors(bool is_initiator, linked_list_t *traffic_selectors) +ts_payload_t *ts_payload_create_from_traffic_selectors(bool is_initiator, + linked_list_t *traffic_selectors) { - iterator_t *iterator; + enumerator_t *enumerator; traffic_selector_t *ts; - traffic_selector_substructure_t *ts_substructure; + traffic_selector_substructure_t *subst; private_ts_payload_t *this; this = (private_ts_payload_t*)ts_payload_create(is_initiator); - iterator = traffic_selectors->create_iterator(traffic_selectors, TRUE); - while (iterator->iterate(iterator, (void**)&ts)) + enumerator = traffic_selectors->create_enumerator(traffic_selectors); + while (enumerator->enumerate(enumerator, &ts)) { - ts_substructure = traffic_selector_substructure_create_from_traffic_selector(ts); - this->public.add_traffic_selector_substructure(&(this->public), ts_substructure); + subst = traffic_selector_substructure_create_from_traffic_selector(ts); + this->substrs->insert_last(this->substrs, subst); } - iterator->destroy(iterator); + enumerator->destroy(enumerator); + compute_length(this); - return &(this->public); + return &this->public; } - diff --git a/src/libcharon/encoding/payloads/ts_payload.h b/src/libcharon/encoding/payloads/ts_payload.h index d322ff1a8..88ca00bc9 100644 --- a/src/libcharon/encoding/payloads/ts_payload.h +++ b/src/libcharon/encoding/payloads/ts_payload.h @@ -19,7 +19,6 @@ * @{ @ingroup payloads */ - #ifndef TS_PAYLOAD_H_ #define TS_PAYLOAD_H_ @@ -36,13 +35,13 @@ typedef struct ts_payload_t ts_payload_t; */ #define TS_PAYLOAD_HEADER_LENGTH 8 - /** * Class representing an IKEv2 TS payload. * * The TS payload format is described in RFC section 3.13. */ struct ts_payload_t { + /** * The payload_t interface. */ @@ -67,27 +66,6 @@ struct ts_payload_t { void (*set_initiator) (ts_payload_t *this,bool is_initiator); /** - * Adds a traffic_selector_substructure_t object to this object. - * - * @param traffic_selector traffic_selector_substructure_t object to add - */ - void (*add_traffic_selector_substructure) (ts_payload_t *this, - traffic_selector_substructure_t *traffic_selector); - - /** - * Creates an iterator of stored traffic_selector_substructure_t objects. - * - * When removing an traffic_selector_substructure_t object - * using this iterator, the length of this payload - * has to get refreshed by calling payload_t.get_length! - * - * @param forward iterator direction (TRUE: front to end) - * @return created iterator_t object - */ - iterator_t *(*create_traffic_selector_substructure_iterator) ( - ts_payload_t *this, bool forward); - - /** * Get a list of nested traffic selectors as traffic_selector_t. * * Resulting list and its traffic selectors must be destroyed after usage @@ -105,19 +83,15 @@ struct ts_payload_t { /** * Creates an empty ts_payload_t object. * - * @param is_initiator - * - TRUE if this payload is of type TSi - * - FALSE if this payload is of type TSr - * @return ts_payload_t object + * @param is_initiator TRUE for TSi, FALSE for TSr payload type + * @return ts_payload_t object */ ts_payload_t *ts_payload_create(bool is_initiator); /** * Creates ts_payload with a list of traffic_selector_t * - * @param is_initiator - * - TRUE if this payload is of type TSi - * - FALSE if this payload is of type TSr + * @param is_initiator TRUE for TSi, FALSE for TSr payload type * @param traffic_selectors list of traffic selectors to include * @return ts_payload_t object */ diff --git a/src/libcharon/encoding/payloads/unknown_payload.c b/src/libcharon/encoding/payloads/unknown_payload.c index dd5547dc3..27af338b3 100644 --- a/src/libcharon/encoding/payloads/unknown_payload.c +++ b/src/libcharon/encoding/payloads/unknown_payload.c @@ -18,8 +18,6 @@ #include "unknown_payload.h" - - typedef struct private_unknown_payload_t private_unknown_payload_t; /** @@ -33,6 +31,11 @@ struct private_unknown_payload_t { unknown_payload_t public; /** + * Type of this payload + */ + payload_type_t type; + + /** * Next payload type. */ u_int8_t next_payload; @@ -43,6 +46,11 @@ struct private_unknown_payload_t { bool critical; /** + * Reserved bits + */ + bool reserved[7]; + + /** * Length of this payload. */ u_int16_t payload_length; @@ -62,21 +70,21 @@ struct private_unknown_payload_t { */ encoding_rule_t unknown_payload_encodings[] = { /* 1 Byte next payload type, stored in the field next_payload */ - { U_INT_8, offsetof(private_unknown_payload_t, next_payload)}, + { U_INT_8, offsetof(private_unknown_payload_t, next_payload) }, /* the critical bit */ - { FLAG, offsetof(private_unknown_payload_t, critical) }, - /* 7 Bit reserved bits, nowhere stored */ - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, + { FLAG, offsetof(private_unknown_payload_t, critical) }, + /* 7 Bit reserved bits */ + { RESERVED_BIT, offsetof(private_unknown_payload_t, reserved[0]) }, + { RESERVED_BIT, offsetof(private_unknown_payload_t, reserved[1]) }, + { RESERVED_BIT, offsetof(private_unknown_payload_t, reserved[2]) }, + { RESERVED_BIT, offsetof(private_unknown_payload_t, reserved[3]) }, + { RESERVED_BIT, offsetof(private_unknown_payload_t, reserved[4]) }, + { RESERVED_BIT, offsetof(private_unknown_payload_t, reserved[5]) }, + { RESERVED_BIT, offsetof(private_unknown_payload_t, reserved[6]) }, /* Length of the whole payload*/ - { PAYLOAD_LENGTH, offsetof(private_unknown_payload_t, payload_length)}, + { PAYLOAD_LENGTH, offsetof(private_unknown_payload_t, payload_length) }, /* some unknown data bytes, length is defined in PAYLOAD_LENGTH */ - { UNKNOWN_DATA, offsetof(private_unknown_payload_t, data) } + { UNKNOWN_DATA, offsetof(private_unknown_payload_t, data) }, }; /* @@ -91,111 +99,109 @@ encoding_rule_t unknown_payload_encodings[] = { +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ -/** - * Implementation of payload_t.verify. - */ -static status_t verify(private_unknown_payload_t *this) +METHOD(payload_t, verify, status_t, + private_unknown_payload_t *this) { - /* can't do any checks, so we assume its good */ + if (this->payload_length != UNKNOWN_PAYLOAD_HEADER_LENGTH + this->data.len) + { + return FAILED; + } return SUCCESS; } -/** - * Implementation of payload_t.get_encoding_rules. - */ -static void get_encoding_rules(private_unknown_payload_t *this, encoding_rule_t **rules, size_t *rule_count) +METHOD(payload_t, get_encoding_rules, void, + private_unknown_payload_t *this, encoding_rule_t **rules, size_t *rule_count) { *rules = unknown_payload_encodings; *rule_count = sizeof(unknown_payload_encodings) / sizeof(encoding_rule_t); } -/** - * Implementation of payload_t.get_type. - */ -static payload_type_t get_payload_type(private_unknown_payload_t *this) +METHOD(payload_t, get_payload_type, payload_type_t, + private_unknown_payload_t *this) { - return UNKNOWN_PAYLOAD; + return this->type; } -/** - * Implementation of payload_t.get_next_type. - */ -static payload_type_t get_next_type(private_unknown_payload_t *this) +METHOD(payload_t, get_next_type, payload_type_t, + private_unknown_payload_t *this) { - return (this->next_payload); + return this->next_payload; } -/** - * Implementation of payload_t.set_next_type. - */ -static void set_next_type(private_unknown_payload_t *this,payload_type_t type) +METHOD(payload_t, set_next_type, void, + private_unknown_payload_t *this,payload_type_t type) { this->next_payload = type; } -/** - * Implementation of payload_t.get_length. - */ -static size_t get_length(private_unknown_payload_t *this) +METHOD(payload_t, get_length, size_t, + private_unknown_payload_t *this) { return this->payload_length; } -/** - * Implementation of unknown_payload_t.get_data. - */ -static bool is_critical(private_unknown_payload_t *this) +METHOD(unknown_payload_t, is_critical, bool, + private_unknown_payload_t *this) { return this->critical; } -/** - * Implementation of unknown_payload_t.get_data. - */ -static chunk_t get_data (private_unknown_payload_t *this) +METHOD(unknown_payload_t, get_data, chunk_t, + private_unknown_payload_t *this) { - return (this->data); + return this->data; } -/** - * Implementation of payload_t.destroy and unknown_payload_t.destroy. - */ -static void destroy(private_unknown_payload_t *this) +METHOD2(payload_t, unknown_payload_t, destroy, void, + private_unknown_payload_t *this) { - if (this->data.ptr != NULL) - { - chunk_free(&(this->data)); - } - + free(this->data.ptr); free(this); } /* * Described in header */ -unknown_payload_t *unknown_payload_create() +unknown_payload_t *unknown_payload_create(payload_type_t type) +{ + private_unknown_payload_t *this; + + INIT(this, + .public = { + .payload_interface = { + .verify = _verify, + .get_encoding_rules = _get_encoding_rules, + .get_length = _get_length, + .get_next_type = _get_next_type, + .set_next_type = _set_next_type, + .get_type = _get_payload_type, + .destroy = _destroy, + }, + .is_critical = _is_critical, + .get_data = _get_data, + .destroy = _destroy, + }, + .next_payload = NO_PAYLOAD, + .payload_length = UNKNOWN_PAYLOAD_HEADER_LENGTH, + .type = type, + ); + + return &this->public; +} + + +/* + * Described in header + */ +unknown_payload_t *unknown_payload_create_data(payload_type_t type, + bool critical, chunk_t data) { - private_unknown_payload_t *this = malloc_thing(private_unknown_payload_t); - - /* interface functions */ - this->public.payload_interface.verify = (status_t (*) (payload_t *))verify; - this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules; - this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length; - this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type; - this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type; - this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_payload_type; - this->public.payload_interface.destroy = (void (*) (payload_t *))destroy; - - /* public functions */ - this->public.destroy = (void (*) (unknown_payload_t *)) destroy; - this->public.is_critical = (bool (*) (unknown_payload_t *)) is_critical; - this->public.get_data = (chunk_t (*) (unknown_payload_t *)) get_data; - - /* private variables */ - this->critical = FALSE; - this->next_payload = NO_PAYLOAD; - this->payload_length = UNKNOWN_PAYLOAD_HEADER_LENGTH; - this->data = chunk_empty; - - return (&(this->public)); + private_unknown_payload_t *this; + + this = (private_unknown_payload_t*)unknown_payload_create(type); + this->data = data; + this->critical = critical; + this->payload_length = UNKNOWN_PAYLOAD_HEADER_LENGTH + data.len; + + return &this->public; } diff --git a/src/libcharon/encoding/payloads/unknown_payload.h b/src/libcharon/encoding/payloads/unknown_payload.h index c761ed2b6..5ae85331b 100644 --- a/src/libcharon/encoding/payloads/unknown_payload.h +++ b/src/libcharon/encoding/payloads/unknown_payload.h @@ -70,10 +70,22 @@ struct unknown_payload_t { }; /** - * Creates an empty unknown_payload_t object. + * Creates an empty unknown_payload_t. * - * @return unknown_payload_t object + * @param type of the payload + * @return unknown_payload_t object */ -unknown_payload_t *unknown_payload_create(void); +unknown_payload_t *unknown_payload_create(payload_type_t type); + +/** + * Create an unknown payload with data. + * + * @param type type of payload to create + * @param critical TRUE to set critical bit + * @param data data to set for this payload, gets owned by payload + * @return payload object + */ +unknown_payload_t *unknown_payload_create_data(payload_type_t type, + bool critical, chunk_t data); #endif /** UNKNOWN_PAYLOAD_H_ @}*/ diff --git a/src/libcharon/encoding/payloads/vendor_id_payload.c b/src/libcharon/encoding/payloads/vendor_id_payload.c index bf33d2418..e9e80e989 100644 --- a/src/libcharon/encoding/payloads/vendor_id_payload.c +++ b/src/libcharon/encoding/payloads/vendor_id_payload.c @@ -1,5 +1,6 @@ /* - * Copyright (C) 2005-2009 Martin Willi + * Copyright (C) 2005-2010 Martin Willi + * Copyright (C) 2010 revosec AG * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil * @@ -41,6 +42,11 @@ struct private_vendor_id_payload_t { bool critical; /** + * Reserved bits + */ + bool reserved[7]; + + /** * Length of this payload. */ u_int16_t payload_length; @@ -59,21 +65,21 @@ struct private_vendor_id_payload_t { */ encoding_rule_t vendor_id_payload_encodings[] = { /* 1 Byte next payload type, stored in the field next_payload */ - { U_INT_8, offsetof(private_vendor_id_payload_t, next_payload) }, + { U_INT_8, offsetof(private_vendor_id_payload_t, next_payload) }, /* the critical bit */ { FLAG, offsetof(private_vendor_id_payload_t, critical) }, /* 7 Bit reserved bits, nowhere stored */ - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, - { RESERVED_BIT, 0 }, + { RESERVED_BIT, offsetof(private_vendor_id_payload_t, reserved[0]) }, + { RESERVED_BIT, offsetof(private_vendor_id_payload_t, reserved[1]) }, + { RESERVED_BIT, offsetof(private_vendor_id_payload_t, reserved[2]) }, + { RESERVED_BIT, offsetof(private_vendor_id_payload_t, reserved[3]) }, + { RESERVED_BIT, offsetof(private_vendor_id_payload_t, reserved[4]) }, + { RESERVED_BIT, offsetof(private_vendor_id_payload_t, reserved[5]) }, + { RESERVED_BIT, offsetof(private_vendor_id_payload_t, reserved[6]) }, /* Length of the whole payload*/ { PAYLOAD_LENGTH, offsetof(private_vendor_id_payload_t, payload_length)}, /* some vendor_id data bytes, length is defined in PAYLOAD_LENGTH */ - { VID_DATA, offsetof(private_vendor_id_payload_t, data) } + { VID_DATA, offsetof(private_vendor_id_payload_t, data) } }; /* @@ -88,68 +94,52 @@ encoding_rule_t vendor_id_payload_encodings[] = { +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ -/** - * Implementation of payload_t.verify. - */ -static status_t verify(private_vendor_id_payload_t *this) +METHOD(payload_t, verify, status_t, + private_vendor_id_payload_t *this) { return SUCCESS; } -/** - * Implementation of vendor_id_payload_t.get_encoding_rules. - */ -static void get_encoding_rules(private_vendor_id_payload_t *this, - encoding_rule_t **rules, size_t *rule_count) +METHOD(payload_t, get_encoding_rules, void, + private_vendor_id_payload_t *this, encoding_rule_t **rules, + size_t *rule_count) { *rules = vendor_id_payload_encodings; - *rule_count = sizeof(vendor_id_payload_encodings) / sizeof(encoding_rule_t); + *rule_count = countof(vendor_id_payload_encodings); } -/** - * Implementation of payload_t.get_type. - */ -static payload_type_t get_payload_type(private_vendor_id_payload_t *this) +METHOD(payload_t, get_type, payload_type_t, + private_vendor_id_payload_t *this) { return VENDOR_ID; } -/** - * Implementation of payload_t.get_next_type. - */ -static payload_type_t get_next_type(private_vendor_id_payload_t *this) +METHOD(payload_t, get_next_type, payload_type_t, + private_vendor_id_payload_t *this) { return this->next_payload; } -/** - * Implementation of payload_t.set_next_type. - */ -static void set_next_type(private_vendor_id_payload_t *this,payload_type_t type) +METHOD(payload_t, set_next_type, void, + private_vendor_id_payload_t *this, payload_type_t type) { this->next_payload = type; } -/** - * Implementation of payload_t.get_length. - */ -static size_t get_length(private_vendor_id_payload_t *this) +METHOD(payload_t, get_length, size_t, + private_vendor_id_payload_t *this) { return this->payload_length; } -/** - * Implementation of vendor_id_payload_t.get_data. - */ -static chunk_t get_data(private_vendor_id_payload_t *this) +METHOD(vendor_id_payload_t, get_data, chunk_t, + private_vendor_id_payload_t *this) { return this->data; } -/** - * Implementation of payload_t.destroy and vendor_id_payload_t.destroy. - */ -static void destroy(private_vendor_id_payload_t *this) +METHOD2(payload_t, vendor_id_payload_t, destroy, void, + private_vendor_id_payload_t *this) { free(this->data.ptr); free(this); @@ -158,38 +148,35 @@ static void destroy(private_vendor_id_payload_t *this) /* * Described in header */ -vendor_id_payload_t *vendor_id_payload_create() +vendor_id_payload_t *vendor_id_payload_create_data(chunk_t data) { - private_vendor_id_payload_t *this = malloc_thing(private_vendor_id_payload_t); - - this->public.payload_interface.verify = (status_t (*) (payload_t *))verify; - this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules; - this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length; - this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type; - this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type; - this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_payload_type; - this->public.payload_interface.destroy = (void (*) (payload_t *))destroy; - this->public.get_data = (chunk_t (*) (vendor_id_payload_t *)) get_data; - - this->critical = FALSE; - this->next_payload = NO_PAYLOAD; - this->payload_length = VENDOR_ID_PAYLOAD_HEADER_LENGTH; - this->data = chunk_empty; + private_vendor_id_payload_t *this; + INIT(this, + .public = { + .payload_interface = { + .verify = _verify, + .get_encoding_rules = _get_encoding_rules, + .get_length = _get_length, + .get_next_type = _get_next_type, + .set_next_type = _set_next_type, + .get_type = _get_type, + .destroy = _destroy, + }, + .get_data = _get_data, + .destroy = _destroy, + }, + .next_payload = NO_PAYLOAD, + .payload_length = VENDOR_ID_PAYLOAD_HEADER_LENGTH + data.len, + .data = data, + ); return &this->public; } /* * Described in header */ -vendor_id_payload_t *vendor_id_payload_create_data(chunk_t data) +vendor_id_payload_t *vendor_id_payload_create() { - private_vendor_id_payload_t *this; - - this = (private_vendor_id_payload_t*)vendor_id_payload_create(); - this->payload_length += data.len; - this->data = data; - - return &this->public; + return vendor_id_payload_create_data(chunk_empty); } - diff --git a/src/libcharon/encoding/payloads/vendor_id_payload.h b/src/libcharon/encoding/payloads/vendor_id_payload.h index 241535cac..4e4e7d8eb 100644 --- a/src/libcharon/encoding/payloads/vendor_id_payload.h +++ b/src/libcharon/encoding/payloads/vendor_id_payload.h @@ -50,6 +50,11 @@ struct vendor_id_payload_t { * @return VID data, pointing to an internal chunk_t */ chunk_t (*get_data)(vendor_id_payload_t *this); + + /** + * Destroy Vendor ID payload. + */ + void (*destroy)(vendor_id_payload_t *this); }; /** diff --git a/src/libcharon/plugins/addrblock/Makefile.in b/src/libcharon/plugins/addrblock/Makefile.in index 426d1a689..018318a59 100644 --- a/src/libcharon/plugins/addrblock/Makefile.in +++ b/src/libcharon/plugins/addrblock/Makefile.in @@ -223,9 +223,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -264,6 +262,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libcharon/plugins/addrblock/addrblock_validator.c b/src/libcharon/plugins/addrblock/addrblock_validator.c index 44ef38d85..12cf0c941 100644 --- a/src/libcharon/plugins/addrblock/addrblock_validator.c +++ b/src/libcharon/plugins/addrblock/addrblock_validator.c @@ -1,8 +1,6 @@ /* - * Copyright (C) 2010 Martin Willi - * Copyright (C) 2010 revosec AG - * Copyright (C) 2009 Andreas Steffen - * Hochschule fuer Technik Rapperswil + * Copyright (C) 2010 Martin Willi, revosec AG + * Copyright (C) 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 @@ -90,7 +88,8 @@ static bool check_addrblock(x509_t *subject, x509_t *issuer) METHOD(cert_validator_t, validate, bool, private_addrblock_validator_t *this, certificate_t *subject, - certificate_t *issuer, bool online, int pathlen, auth_cfg_t *auth) + certificate_t *issuer, bool online, int pathlen, bool anchor, + auth_cfg_t *auth) { if (subject->get_type(subject) == CERT_X509 && issuer->get_type(issuer) == CERT_X509) diff --git a/src/libcharon/plugins/android/Makefile.in b/src/libcharon/plugins/android/Makefile.in index d80868798..7d6eb2b9c 100644 --- a/src/libcharon/plugins/android/Makefile.in +++ b/src/libcharon/plugins/android/Makefile.in @@ -223,9 +223,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -264,6 +262,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libcharon/plugins/android/android_creds.c b/src/libcharon/plugins/android/android_creds.c index aa7fc6f92..601c91e7b 100644 --- a/src/libcharon/plugins/android/android_creds.c +++ b/src/libcharon/plugins/android/android_creds.c @@ -235,7 +235,7 @@ METHOD(android_creds_t, set_username_password, void, DESTROY_IF(this->user); this->user = id->clone(id); free(this->pass); - this->pass = password ? strdup(password) : NULL; + this->pass = strdupnull(password); this->lock->unlock(this->lock); } diff --git a/src/libcharon/plugins/android/android_service.c b/src/libcharon/plugins/android/android_service.c index f9a8e1ea1..487567f2a 100644 --- a/src/libcharon/plugins/android/android_service.c +++ b/src/libcharon/plugins/android/android_service.c @@ -291,8 +291,8 @@ static job_requeue_t initiate(private_android_service_t *this) peer_cfg->add_auth_cfg(peer_cfg, auth, FALSE); child_cfg = child_cfg_create("android", &lifetime, NULL, TRUE, MODE_TUNNEL, - ACTION_NONE, ACTION_NONE, FALSE, 0, 0, - NULL, NULL); + ACTION_NONE, ACTION_NONE, ACTION_NONE, FALSE, + 0, 0, NULL, NULL, 0); child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP)); ts = traffic_selector_create_dynamic(0, 0, 65535); child_cfg->add_traffic_selector(child_cfg, TRUE, ts); diff --git a/src/libcharon/plugins/dhcp/Makefile.in b/src/libcharon/plugins/dhcp/Makefile.in index e843c42e8..8046fc052 100644 --- a/src/libcharon/plugins/dhcp/Makefile.in +++ b/src/libcharon/plugins/dhcp/Makefile.in @@ -220,9 +220,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -261,6 +259,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libcharon/plugins/dhcp/dhcp_socket.c b/src/libcharon/plugins/dhcp/dhcp_socket.c index e1e83d648..8851c1b79 100644 --- a/src/libcharon/plugins/dhcp/dhcp_socket.c +++ b/src/libcharon/plugins/dhcp/dhcp_socket.c @@ -459,7 +459,7 @@ static void handle_offer(private_dhcp_socket_t *this, dhcp_t *dhcp, int optlen) { dhcp_transaction_t *transaction = NULL; enumerator_t *enumerator; - host_t *offer, *server; + host_t *offer, *server = NULL; offer = host_create_from_chunk(AF_INET, chunk_from_thing(dhcp->your_address), 0); @@ -500,7 +500,7 @@ static void handle_offer(private_dhcp_socket_t *this, dhcp_t *dhcp, int optlen) chunk_create((char*)&option->data[pos], 4)); } } - if (option->type == DHCP_SERVER_ID && option->len == 4) + if (!server && option->type == DHCP_SERVER_ID && option->len == 4) { server = host_create_from_chunk(AF_INET, chunk_create(option->data, 4), DHCP_SERVER_PORT); @@ -515,12 +515,11 @@ static void handle_offer(private_dhcp_socket_t *this, dhcp_t *dhcp, int optlen) } DBG1(DBG_CFG, "received DHCP OFFER %H from %H", offer, server); transaction->set_address(transaction, offer->clone(offer)); - transaction->set_server(transaction, server->clone(server)); + transaction->set_server(transaction, server); } this->mutex->unlock(this->mutex); this->condvar->broadcast(this->condvar); offer->destroy(offer); - server->destroy(server); } /** diff --git a/src/libcharon/plugins/eap_aka/Makefile.in b/src/libcharon/plugins/eap_aka/Makefile.in index c0750786d..4a23f9010 100644 --- a/src/libcharon/plugins/eap_aka/Makefile.in +++ b/src/libcharon/plugins/eap_aka/Makefile.in @@ -223,9 +223,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -264,6 +262,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libcharon/plugins/eap_aka_3gpp2/Makefile.in b/src/libcharon/plugins/eap_aka_3gpp2/Makefile.in index 41f69546e..ad1ae1906 100644 --- a/src/libcharon/plugins/eap_aka_3gpp2/Makefile.in +++ b/src/libcharon/plugins/eap_aka_3gpp2/Makefile.in @@ -224,9 +224,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -265,6 +263,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libcharon/plugins/eap_gtc/Makefile.in b/src/libcharon/plugins/eap_gtc/Makefile.in index 02d659197..142a35e50 100644 --- a/src/libcharon/plugins/eap_gtc/Makefile.in +++ b/src/libcharon/plugins/eap_gtc/Makefile.in @@ -221,9 +221,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -262,6 +260,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libcharon/plugins/eap_identity/Makefile.in b/src/libcharon/plugins/eap_identity/Makefile.in index 46011694a..5c1e07ade 100644 --- a/src/libcharon/plugins/eap_identity/Makefile.in +++ b/src/libcharon/plugins/eap_identity/Makefile.in @@ -223,9 +223,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -264,6 +262,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libcharon/plugins/eap_md5/Makefile.in b/src/libcharon/plugins/eap_md5/Makefile.in index 2e307147f..4e01d96cc 100644 --- a/src/libcharon/plugins/eap_md5/Makefile.in +++ b/src/libcharon/plugins/eap_md5/Makefile.in @@ -221,9 +221,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -262,6 +260,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libcharon/plugins/eap_mschapv2/Makefile.in b/src/libcharon/plugins/eap_mschapv2/Makefile.in index 635cfe6ec..495ccf441 100644 --- a/src/libcharon/plugins/eap_mschapv2/Makefile.in +++ b/src/libcharon/plugins/eap_mschapv2/Makefile.in @@ -223,9 +223,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -264,6 +262,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libcharon/plugins/eap_radius/Makefile.in b/src/libcharon/plugins/eap_radius/Makefile.in index 1d771d9a4..99084e2c1 100644 --- a/src/libcharon/plugins/eap_radius/Makefile.in +++ b/src/libcharon/plugins/eap_radius/Makefile.in @@ -224,9 +224,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -265,6 +263,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libcharon/plugins/eap_sim/Makefile.in b/src/libcharon/plugins/eap_sim/Makefile.in index d05930bbd..90f203f61 100644 --- a/src/libcharon/plugins/eap_sim/Makefile.in +++ b/src/libcharon/plugins/eap_sim/Makefile.in @@ -223,9 +223,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -264,6 +262,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libcharon/plugins/eap_sim_file/Makefile.in b/src/libcharon/plugins/eap_sim_file/Makefile.in index 46a584265..3cd766a75 100644 --- a/src/libcharon/plugins/eap_sim_file/Makefile.in +++ b/src/libcharon/plugins/eap_sim_file/Makefile.in @@ -224,9 +224,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -265,6 +263,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in b/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in index 2d8556a59..a48fb652a 100644 --- a/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in +++ b/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in @@ -225,9 +225,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -266,6 +264,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libcharon/plugins/eap_simaka_reauth/Makefile.in b/src/libcharon/plugins/eap_simaka_reauth/Makefile.in index e59015f82..f2af3ae0d 100644 --- a/src/libcharon/plugins/eap_simaka_reauth/Makefile.in +++ b/src/libcharon/plugins/eap_simaka_reauth/Makefile.in @@ -224,9 +224,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -265,6 +263,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libcharon/plugins/eap_simaka_sql/Makefile.in b/src/libcharon/plugins/eap_simaka_sql/Makefile.in index 3c66d2f36..9a58a6055 100644 --- a/src/libcharon/plugins/eap_simaka_sql/Makefile.in +++ b/src/libcharon/plugins/eap_simaka_sql/Makefile.in @@ -223,9 +223,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -264,6 +262,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libcharon/plugins/eap_tls/Makefile.in b/src/libcharon/plugins/eap_tls/Makefile.in index e4b78faf8..9ebb85be9 100644 --- a/src/libcharon/plugins/eap_tls/Makefile.in +++ b/src/libcharon/plugins/eap_tls/Makefile.in @@ -222,9 +222,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -263,6 +261,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libcharon/plugins/eap_tnc/Makefile.in b/src/libcharon/plugins/eap_tnc/Makefile.in index fb7108a8a..cf75585ef 100644 --- a/src/libcharon/plugins/eap_tnc/Makefile.in +++ b/src/libcharon/plugins/eap_tnc/Makefile.in @@ -222,9 +222,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -263,6 +261,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libcharon/plugins/eap_tnc/eap_tnc.c b/src/libcharon/plugins/eap_tnc/eap_tnc.c index f0bff0e1f..dd4ed5322 100644 --- a/src/libcharon/plugins/eap_tnc/eap_tnc.c +++ b/src/libcharon/plugins/eap_tnc/eap_tnc.c @@ -18,7 +18,7 @@ #include <tls_eap.h> #include <daemon.h> -#include <library.h> +#include <debug.h> typedef struct private_eap_tnc_t private_eap_tnc_t; @@ -114,6 +114,8 @@ static eap_tnc_t *eap_tnc_create(identification_t *server, private_eap_tnc_t *this; size_t frag_size; int max_msg_count; + char* protocol; + tnccs_type_t type; tnccs_t *tnccs; INIT(this, @@ -133,7 +135,27 @@ static eap_tnc_t *eap_tnc_create(identification_t *server, "charon.plugins.eap-tnc.fragment_size", MAX_FRAGMENT_LEN); max_msg_count = lib->settings->get_int(lib->settings, "charon.plugins.eap-tnc.max_message_count", MAX_MESSAGE_COUNT); - tnccs = charon->tnccs->create_instance(charon->tnccs, TNCCS_1_1, is_server); + protocol = lib->settings->get_str(lib->settings, + "charon.plugins.eap-tnc.protocol", "tnccs-1.1"); + if (strcaseeq(protocol, "tnccs-2.0")) + { + type = TNCCS_2_0; + } + else if (strcaseeq(protocol, "tnccs-1.1")) + { + type = TNCCS_1_1; + } + else if (strcaseeq(protocol, "tnccs-dynamic") && is_server) + { + type = TNCCS_DYNAMIC; + } + else + { + DBG1(DBG_TNC, "TNCCS protocol '%s' not supported", protocol); + free(this); + return NULL; + } + tnccs = charon->tnccs->create_instance(charon->tnccs, type, is_server); this->tls_eap = tls_eap_create(EAP_TNC, (tls_t*)tnccs, frag_size, max_msg_count); if (!this->tls_eap) { diff --git a/src/libcharon/plugins/eap_ttls/Makefile.in b/src/libcharon/plugins/eap_ttls/Makefile.in index 2cdd7701d..ff67686b2 100644 --- a/src/libcharon/plugins/eap_ttls/Makefile.in +++ b/src/libcharon/plugins/eap_ttls/Makefile.in @@ -225,9 +225,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -266,6 +264,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libcharon/plugins/eap_ttls/eap_ttls_peer.c b/src/libcharon/plugins/eap_ttls/eap_ttls_peer.c index 10d08ca2a..29b0a9303 100644 --- a/src/libcharon/plugins/eap_ttls/eap_ttls_peer.c +++ b/src/libcharon/plugins/eap_ttls/eap_ttls_peer.c @@ -196,6 +196,7 @@ METHOD(tls_application_t, process, status_t, in->destroy(in); return NEED_MORE; } + this->start_phase2 = FALSE; } type = this->method->get_type(this->method, &vendor); diff --git a/src/libcharon/plugins/farp/Makefile.in b/src/libcharon/plugins/farp/Makefile.in index bfd50d6da..21e8b78db 100644 --- a/src/libcharon/plugins/farp/Makefile.in +++ b/src/libcharon/plugins/farp/Makefile.in @@ -220,9 +220,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -261,6 +259,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libcharon/plugins/ha/Makefile.in b/src/libcharon/plugins/ha/Makefile.in index 3600eb7c6..2fcd7cc82 100644 --- a/src/libcharon/plugins/ha/Makefile.in +++ b/src/libcharon/plugins/ha/Makefile.in @@ -222,9 +222,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -263,6 +261,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libcharon/plugins/ha/ha_ctl.c b/src/libcharon/plugins/ha/ha_ctl.c index 980c0551a..15f7824f9 100644 --- a/src/libcharon/plugins/ha/ha_ctl.c +++ b/src/libcharon/plugins/ha/ha_ctl.c @@ -21,8 +21,8 @@ #include <fcntl.h> #include <unistd.h> #include <errno.h> -#include <pthread.h> +#include <threading/thread.h> #include <processing/jobs/callback_job.h> #define HA_FIFO IPSEC_PIDDIR "/charon.ha" @@ -60,13 +60,14 @@ struct private_ha_ctl_t { */ static job_requeue_t dispatch_fifo(private_ha_ctl_t *this) { - int fifo, old; + int fifo; + bool oldstate; char buf[8]; u_int segment; - pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &old); + oldstate = thread_cancelability(TRUE); fifo = open(HA_FIFO, O_RDONLY); - pthread_setcancelstate(old, NULL); + thread_cancelability(oldstate); if (fifo == -1) { DBG1(DBG_CFG, "opening HA fifo failed: %s", strerror(errno)); diff --git a/src/libcharon/plugins/ha/ha_dispatcher.c b/src/libcharon/plugins/ha/ha_dispatcher.c index b46a221bd..85dc0f4a4 100644 --- a/src/libcharon/plugins/ha/ha_dispatcher.c +++ b/src/libcharon/plugins/ha/ha_dispatcher.c @@ -596,9 +596,9 @@ static void process_child_add(private_ha_dispatcher_t *this, if (initiator) { if (child_sa->install(child_sa, encr_r, integ_r, inbound_spi, - inbound_cpi, TRUE, local_ts, remote_ts) != SUCCESS || + inbound_cpi, TRUE, TRUE, local_ts, remote_ts) != SUCCESS || child_sa->install(child_sa, encr_i, integ_i, outbound_spi, - outbound_cpi, FALSE, local_ts, remote_ts) != SUCCESS) + outbound_cpi, FALSE, TRUE, local_ts, remote_ts) != SUCCESS) { failed = TRUE; } @@ -606,9 +606,9 @@ static void process_child_add(private_ha_dispatcher_t *this, else { if (child_sa->install(child_sa, encr_i, integ_i, inbound_spi, - inbound_cpi, TRUE, local_ts, remote_ts) != SUCCESS || + inbound_cpi, TRUE, TRUE, local_ts, remote_ts) != SUCCESS || child_sa->install(child_sa, encr_r, integ_r, outbound_spi, - outbound_cpi, FALSE, local_ts, remote_ts) != SUCCESS) + outbound_cpi, FALSE, TRUE, local_ts, remote_ts) != SUCCESS) { failed = TRUE; } diff --git a/src/libcharon/plugins/ha/ha_segments.c b/src/libcharon/plugins/ha/ha_segments.c index 19e0f692e..7c7bef851 100644 --- a/src/libcharon/plugins/ha/ha_segments.c +++ b/src/libcharon/plugins/ha/ha_segments.c @@ -15,11 +15,10 @@ #include "ha_segments.h" -#include <pthread.h> - #include <threading/mutex.h> #include <threading/condvar.h> #include <utils/linked_list.h> +#include <threading/thread.h> #include <processing/jobs/callback_job.h> #define DEFAULT_HEARTBEAT_DELAY 1000 @@ -255,16 +254,15 @@ METHOD(listener_t, alert_hook, bool, */ static job_requeue_t watchdog(private_ha_segments_t *this) { - int oldstate; - bool timeout; + bool timeout, oldstate; this->mutex->lock(this->mutex); - pthread_cleanup_push((void*)this->mutex->unlock, this->mutex); - pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); + thread_cleanup_push((void*)this->mutex->unlock, this->mutex); + oldstate = thread_cancelability(TRUE); timeout = this->condvar->timed_wait(this->condvar, this->mutex, this->heartbeat_timeout); - pthread_setcancelstate(oldstate, NULL); - pthread_cleanup_pop(TRUE); + thread_cancelability(oldstate); + thread_cleanup_pop(TRUE); if (timeout) { DBG1(DBG_CFG, "no heartbeat received, taking all segments"); diff --git a/src/libcharon/plugins/ha/ha_socket.c b/src/libcharon/plugins/ha/ha_socket.c index 614c70ed3..086178442 100644 --- a/src/libcharon/plugins/ha/ha_socket.c +++ b/src/libcharon/plugins/ha/ha_socket.c @@ -20,10 +20,10 @@ #include <sys/socket.h> #include <errno.h> #include <unistd.h> -#include <pthread.h> #include <daemon.h> #include <utils/host.h> +#include <threading/thread.h> #include <processing/jobs/callback_job.h> typedef struct private_ha_socket_t private_ha_socket_t; @@ -121,12 +121,12 @@ METHOD(ha_socket_t, pull, ha_message_t*, { ha_message_t *message; char buf[1024]; - int oldstate; + bool oldstate; ssize_t len; - pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); + oldstate = thread_cancelability(TRUE); len = recv(this->fd, buf, sizeof(buf), 0); - pthread_setcancelstate(oldstate, NULL); + thread_cancelability(oldstate); if (len <= 0) { switch (errno) diff --git a/src/libcharon/plugins/ha/ha_tunnel.c b/src/libcharon/plugins/ha/ha_tunnel.c index fef84a430..299053ec1 100644 --- a/src/libcharon/plugins/ha/ha_tunnel.c +++ b/src/libcharon/plugins/ha/ha_tunnel.c @@ -223,8 +223,8 @@ static void setup_tunnel(private_ha_tunnel_t *this, peer_cfg->add_auth_cfg(peer_cfg, auth_cfg, FALSE); child_cfg = child_cfg_create("ha", &lifetime, NULL, TRUE, MODE_TRANSPORT, - ACTION_NONE, ACTION_NONE, FALSE, 0, 0, - NULL, NULL); + ACTION_NONE, ACTION_NONE, ACTION_NONE, FALSE, + 0, 0, NULL, NULL, 0); ts = traffic_selector_create_dynamic(IPPROTO_UDP, HA_PORT, HA_PORT); child_cfg->add_traffic_selector(child_cfg, TRUE, ts); ts = traffic_selector_create_dynamic(IPPROTO_ICMP, 0, 65535); diff --git a/src/libcharon/plugins/led/Makefile.in b/src/libcharon/plugins/led/Makefile.in index a4e529d89..fa1194fd0 100644 --- a/src/libcharon/plugins/led/Makefile.in +++ b/src/libcharon/plugins/led/Makefile.in @@ -219,9 +219,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -260,6 +258,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libcharon/plugins/load_tester/Makefile.in b/src/libcharon/plugins/load_tester/Makefile.in index 85db9a10b..c921ec3db 100644 --- a/src/libcharon/plugins/load_tester/Makefile.in +++ b/src/libcharon/plugins/load_tester/Makefile.in @@ -225,9 +225,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -266,6 +264,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libcharon/plugins/load_tester/load_tester_config.c b/src/libcharon/plugins/load_tester/load_tester_config.c index a230aa3f5..71391d593 100644 --- a/src/libcharon/plugins/load_tester/load_tester_config.c +++ b/src/libcharon/plugins/load_tester/load_tester_config.c @@ -224,8 +224,8 @@ static peer_cfg_t* generate_config(private_load_tester_config_t *this, uint num) } child_cfg = child_cfg_create("load-test", &lifetime, NULL, TRUE, MODE_TUNNEL, - ACTION_NONE, ACTION_NONE, FALSE, 0, 0, - NULL, NULL); + ACTION_NONE, ACTION_NONE, ACTION_NONE, FALSE, + 0, 0, NULL, NULL, 0); proposal = proposal_create_from_string(PROTO_ESP, "aes128-sha1"); child_cfg->add_proposal(child_cfg, proposal); ts = traffic_selector_create_dynamic(0, 0, 65535); diff --git a/src/libcharon/plugins/load_tester/load_tester_ipsec.c b/src/libcharon/plugins/load_tester/load_tester_ipsec.c index aece95e12..ef9d7f9ef 100644 --- a/src/libcharon/plugins/load_tester/load_tester_ipsec.c +++ b/src/libcharon/plugins/load_tester/load_tester_ipsec.c @@ -52,7 +52,7 @@ METHOD(kernel_ipsec_t, get_cpi, status_t, METHOD(kernel_ipsec_t, add_sa, status_t, private_load_tester_ipsec_t *this, host_t *src, host_t *dst, u_int32_t spi, u_int8_t protocol, u_int32_t reqid, mark_t mark, - lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key, + u_int32_t tfc, lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key, u_int16_t int_alg, chunk_t int_key, ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi, bool encap, bool inbound, traffic_selector_t *src_ts, traffic_selector_t *dst_ts) diff --git a/src/libcharon/plugins/load_tester/load_tester_plugin.c b/src/libcharon/plugins/load_tester/load_tester_plugin.c index cb9b80c7f..8fd65adfa 100644 --- a/src/libcharon/plugins/load_tester/load_tester_plugin.c +++ b/src/libcharon/plugins/load_tester/load_tester_plugin.c @@ -28,6 +28,8 @@ #include <threading/condvar.h> #include <threading/mutex.h> +static const char *plugin_name = "load_tester"; + typedef struct private_load_tester_plugin_t private_load_tester_plugin_t; /** @@ -189,7 +191,7 @@ plugin_t *load_tester_plugin_create() this = malloc_thing(private_load_tester_plugin_t); this->public.plugin.destroy = (void(*)(plugin_t*))destroy; - lib->crypto->add_dh(lib->crypto, MODP_NULL, + lib->crypto->add_dh(lib->crypto, MODP_NULL, plugin_name, (dh_constructor_t)load_tester_diffie_hellman_create); this->delay = lib->settings->get_int(lib->settings, diff --git a/src/libcharon/plugins/maemo/Makefile.am b/src/libcharon/plugins/maemo/Makefile.am index ed6c76c0f..0bf7fad5d 100644 --- a/src/libcharon/plugins/maemo/Makefile.am +++ b/src/libcharon/plugins/maemo/Makefile.am @@ -19,5 +19,9 @@ libstrongswan_maemo_la_LIBADD = ${maemo_LIBS} dbusservice_DATA = org.strongswan.charon.service -EXTRA_DIST = $(dbusservice_DATA) +org.strongswan.charon.service: $(srcdir)/org.strongswan.charon.service.in + sed -e 's|[@]LIBEXECDIR[@]|$(libexecdir)|' $< >$@ + +EXTRA_DIST = org.strongswan.charon.service.in +CLEANFILES = $(dbusservice_DATA) diff --git a/src/libcharon/plugins/maemo/Makefile.in b/src/libcharon/plugins/maemo/Makefile.in index 978950d22..0ca1fa436 100644 --- a/src/libcharon/plugins/maemo/Makefile.in +++ b/src/libcharon/plugins/maemo/Makefile.in @@ -224,9 +224,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -265,6 +263,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ @@ -288,7 +288,8 @@ libstrongswan_maemo_la_SOURCES = \ libstrongswan_maemo_la_LDFLAGS = -module -avoid-version libstrongswan_maemo_la_LIBADD = ${maemo_LIBS} dbusservice_DATA = org.strongswan.charon.service -EXTRA_DIST = $(dbusservice_DATA) +EXTRA_DIST = org.strongswan.charon.service.in +CLEANFILES = $(dbusservice_DATA) all: all-am .SUFFIXES: @@ -528,6 +529,7 @@ install-strip: mostlyclean-generic: clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) @@ -626,6 +628,9 @@ uninstall-am: uninstall-dbusserviceDATA uninstall-pluginLTLIBRARIES uninstall-pluginLTLIBRARIES +org.strongswan.charon.service: $(srcdir)/org.strongswan.charon.service.in + sed -e 's|[@]LIBEXECDIR[@]|$(libexecdir)|' $< >$@ + # 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/libcharon/plugins/maemo/maemo_service.c b/src/libcharon/plugins/maemo/maemo_service.c index efd914a00..0e9fd8ccc 100644 --- a/src/libcharon/plugins/maemo/maemo_service.c +++ b/src/libcharon/plugins/maemo/maemo_service.c @@ -115,12 +115,11 @@ METHOD(listener_t, ike_updown, bool, return TRUE; } -METHOD(listener_t, child_state_change, bool, - private_maemo_service_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa, - child_sa_state_t state) +METHOD(listener_t, ike_state_change, bool, + private_maemo_service_t *this, ike_sa_t *ike_sa, ike_sa_state_t state) { /* this call back is only registered during initiation */ - if (this->ike_sa == ike_sa && state == CHILD_DESTROYING) + if (this->ike_sa == ike_sa && state == IKE_DESTROYING) { change_status(this, VPN_STATUS_CONNECTION_FAILED); return FALSE; @@ -138,7 +137,7 @@ METHOD(listener_t, child_updown, bool, { /* disable hooks registered to catch initiation failures */ this->public.listener.ike_updown = NULL; - this->public.listener.child_state_change = NULL; + this->public.listener.ike_state_change = NULL; change_status(this, VPN_STATUS_CONNECTED); } else @@ -347,7 +346,7 @@ static gboolean initiate_connection(private_maemo_service_t *this, child_cfg = child_cfg_create(this->current, &lifetime, NULL /* updown */, TRUE, MODE_TUNNEL, ACTION_NONE, ACTION_NONE, - FALSE, 0, 0, NULL, NULL); + ACTION_NONE, FALSE, 0, 0, NULL, NULL, 0); child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP)); ts = traffic_selector_create_dynamic(0, 0, 65535); child_cfg->add_traffic_selector(child_cfg, TRUE, ts); @@ -371,7 +370,7 @@ static gboolean initiate_connection(private_maemo_service_t *this, this->ike_sa = ike_sa; this->status = VPN_STATUS_CONNECTING; this->public.listener.ike_updown = _ike_updown; - this->public.listener.child_state_change = _child_state_change; + this->public.listener.ike_state_change = _ike_state_change; charon->bus->add_listener(charon->bus, &this->public.listener); if (ike_sa->initiate(ike_sa, child_cfg, 0, NULL, NULL) != SUCCESS) @@ -464,7 +463,7 @@ maemo_service_t *maemo_service_create() .public = { .listener = { .ike_updown = _ike_updown, - .child_state_change = _child_state_change, + .ike_state_change = _ike_state_change, .child_updown = _child_updown, .ike_rekey = _ike_rekey, }, diff --git a/src/libcharon/plugins/maemo/org.strongswan.charon.service b/src/libcharon/plugins/maemo/org.strongswan.charon.service deleted file mode 100644 index 7dd31ed60..000000000 --- a/src/libcharon/plugins/maemo/org.strongswan.charon.service +++ /dev/null @@ -1,4 +0,0 @@ -[D-BUS Service] -Name=org.strongswan.charon -Exec=/usr/bin/run-standalone.sh /usr/libexec/ipsec/charon -User=root diff --git a/src/libcharon/plugins/maemo/org.strongswan.charon.service.in b/src/libcharon/plugins/maemo/org.strongswan.charon.service.in new file mode 100644 index 000000000..8fa83af93 --- /dev/null +++ b/src/libcharon/plugins/maemo/org.strongswan.charon.service.in @@ -0,0 +1,4 @@ +[D-BUS Service] +Name=org.strongswan.charon +Exec=/usr/bin/run-standalone.sh @LIBEXECDIR@/ipsec/charon +User=root diff --git a/src/libcharon/plugins/medcli/Makefile.in b/src/libcharon/plugins/medcli/Makefile.in index 6dcbc99dd..372a436a6 100644 --- a/src/libcharon/plugins/medcli/Makefile.in +++ b/src/libcharon/plugins/medcli/Makefile.in @@ -222,9 +222,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -263,6 +261,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libcharon/plugins/medcli/medcli_config.c b/src/libcharon/plugins/medcli/medcli_config.c index 870d87c7e..b5672dba9 100644 --- a/src/libcharon/plugins/medcli/medcli_config.c +++ b/src/libcharon/plugins/medcli/medcli_config.c @@ -182,8 +182,8 @@ static peer_cfg_t *get_peer_cfg_by_name(private_medcli_config_t *this, char *nam peer_cfg->add_auth_cfg(peer_cfg, auth, FALSE); child_cfg = child_cfg_create(name, &lifetime, NULL, TRUE, MODE_TUNNEL, - ACTION_NONE, ACTION_NONE, FALSE, 0, 0, - NULL, NULL); + ACTION_NONE, ACTION_NONE, ACTION_NONE, FALSE, + 0, 0, NULL, NULL, 0); child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP)); child_cfg->add_traffic_selector(child_cfg, TRUE, ts_from_string(local_net)); child_cfg->add_traffic_selector(child_cfg, FALSE, ts_from_string(remote_net)); @@ -261,8 +261,8 @@ static bool peer_enumerator_enumerate(peer_enumerator_t *this, peer_cfg_t **cfg) this->current->add_auth_cfg(this->current, auth, FALSE); child_cfg = child_cfg_create(name, &lifetime, NULL, TRUE, MODE_TUNNEL, - ACTION_NONE, ACTION_NONE, FALSE, 0, 0, - NULL, NULL); + ACTION_NONE, ACTION_NONE, ACTION_NONE, FALSE, + 0, 0, NULL, NULL, 0); child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP)); child_cfg->add_traffic_selector(child_cfg, TRUE, ts_from_string(local_net)); child_cfg->add_traffic_selector(child_cfg, FALSE, ts_from_string(remote_net)); diff --git a/src/libcharon/plugins/medsrv/Makefile.in b/src/libcharon/plugins/medsrv/Makefile.in index f6db7d834..4bb65bd09 100644 --- a/src/libcharon/plugins/medsrv/Makefile.in +++ b/src/libcharon/plugins/medsrv/Makefile.in @@ -222,9 +222,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -263,6 +261,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libcharon/plugins/nm/Makefile.in b/src/libcharon/plugins/nm/Makefile.in index 2f5c20971..69af7bf83 100644 --- a/src/libcharon/plugins/nm/Makefile.in +++ b/src/libcharon/plugins/nm/Makefile.in @@ -221,9 +221,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -262,6 +260,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libcharon/plugins/nm/nm_creds.c b/src/libcharon/plugins/nm/nm_creds.c index 638787019..ea98c056d 100644 --- a/src/libcharon/plugins/nm/nm_creds.c +++ b/src/libcharon/plugins/nm/nm_creds.c @@ -400,7 +400,7 @@ static void set_username_password(private_nm_creds_t *this, identification_t *id DESTROY_IF(this->user); this->user = id->clone(id); free(this->pass); - this->pass = password ? strdup(password) : NULL; + this->pass = strdupnull(password); this->lock->unlock(this->lock); } @@ -411,7 +411,7 @@ static void set_key_password(private_nm_creds_t *this, char *password) { this->lock->write_lock(this->lock); free(this->keypass); - this->keypass = password ? strdup(password) : NULL; + this->keypass = strdupnull(password); this->lock->unlock(this->lock); } @@ -423,7 +423,7 @@ static void set_pin(private_nm_creds_t *this, chunk_t keyid, char *pin) this->lock->write_lock(this->lock); free(this->keypass); free(this->keyid.ptr); - this->keypass = pin ? strdup(pin) : NULL; + this->keypass = strdupnull(pin); this->keyid = chunk_clone(keyid); this->lock->unlock(this->lock); } diff --git a/src/libcharon/plugins/nm/nm_service.c b/src/libcharon/plugins/nm/nm_service.c index 72c5bbbb5..4300b57cf 100644 --- a/src/libcharon/plugins/nm/nm_service.c +++ b/src/libcharon/plugins/nm/nm_service.c @@ -518,8 +518,8 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection, child_cfg = child_cfg_create(priv->name, &lifetime, NULL, TRUE, MODE_TUNNEL, /* updown, hostaccess */ - ACTION_NONE, ACTION_NONE, ipcomp, 0, 0, - NULL, NULL); + ACTION_NONE, ACTION_NONE, ACTION_NONE, ipcomp, + 0, 0, NULL, NULL, 0); child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP)); ts = traffic_selector_create_dynamic(0, 0, 65535); child_cfg->add_traffic_selector(child_cfg, TRUE, ts); diff --git a/src/libcharon/plugins/smp/Makefile.in b/src/libcharon/plugins/smp/Makefile.in index f24e2d1e7..3d2cef13c 100644 --- a/src/libcharon/plugins/smp/Makefile.in +++ b/src/libcharon/plugins/smp/Makefile.in @@ -220,9 +220,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -261,6 +259,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libcharon/plugins/socket_default/Makefile.in b/src/libcharon/plugins/socket_default/Makefile.in index bd85386b2..b82372e30 100644 --- a/src/libcharon/plugins/socket_default/Makefile.in +++ b/src/libcharon/plugins/socket_default/Makefile.in @@ -223,9 +223,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -264,6 +262,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libcharon/plugins/socket_dynamic/Makefile.in b/src/libcharon/plugins/socket_dynamic/Makefile.in index 8e0790671..7a49088b2 100644 --- a/src/libcharon/plugins/socket_dynamic/Makefile.in +++ b/src/libcharon/plugins/socket_dynamic/Makefile.in @@ -223,9 +223,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -264,6 +262,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libcharon/plugins/socket_raw/Makefile.in b/src/libcharon/plugins/socket_raw/Makefile.in index 5f4cba131..744b12fcf 100644 --- a/src/libcharon/plugins/socket_raw/Makefile.in +++ b/src/libcharon/plugins/socket_raw/Makefile.in @@ -223,9 +223,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -264,6 +262,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libcharon/plugins/sql/Makefile.in b/src/libcharon/plugins/sql/Makefile.in index 7c4521785..4244d3b5e 100644 --- a/src/libcharon/plugins/sql/Makefile.in +++ b/src/libcharon/plugins/sql/Makefile.in @@ -220,9 +220,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -261,6 +259,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libcharon/plugins/sql/sql_config.c b/src/libcharon/plugins/sql/sql_config.c index a47d93f7b..dc016012c 100644 --- a/src/libcharon/plugins/sql/sql_config.c +++ b/src/libcharon/plugins/sql/sql_config.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2006-2008 Martin Willi + * Copyright (C) 2010 Andreas Steffen * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -38,13 +39,13 @@ struct private_sql_config_t { }; /** - * forward declaration + * Forward declaration */ static peer_cfg_t *build_peer_cfg(private_sql_config_t *this, enumerator_t *e, identification_t *me, identification_t *other); /** - * build a traffic selector from a SQL query + * Build a traffic selector from an SQL query */ static traffic_selector_t *build_traffic_selector(private_sql_config_t *this, enumerator_t *e, bool *local) @@ -119,24 +120,62 @@ static void add_traffic_selectors(private_sql_config_t *this, } /** - * build a Child configuration from a SQL query + * Add ESP proposals to a child config + */ +static void add_esp_proposals(private_sql_config_t *this, + child_cfg_t *child, int id) +{ + enumerator_t *e; + proposal_t *proposal; + char *prop; + bool use_default = TRUE; + + e = this->db->query(this->db, + "SELECT proposal " + "FROM proposals JOIN child_config_proposal ON id = prop " + "WHERE child_cfg = ? ORDER BY prio", + DB_INT, id, DB_TEXT); + if (e) + { + while (e->enumerate(e, &prop)) + { + proposal = proposal_create_from_string(PROTO_ESP, prop); + if (!proposal) + { + DBG1(DBG_CFG, "could not create ESP proposal from '%s'", prop); + break; + } + child->add_proposal(child, proposal); + use_default = FALSE; + } + e->destroy(e); + } + if (use_default) + { + child->add_proposal(child, proposal_create_default(PROTO_ESP)); + } +} + +/** + * Build a child config from an SQL query */ static child_cfg_t *build_child_cfg(private_sql_config_t *this, enumerator_t *e) { - int id, lifetime, rekeytime, jitter, hostaccess, mode, dpd, close, ipcomp; + int id, lifetime, rekeytime, jitter, hostaccess, mode, ipcomp, reqid; + int start, dpd, close; char *name, *updown; child_cfg_t *child_cfg; - if (e->enumerate(e, &id, &name, &lifetime, &rekeytime, &jitter, - &updown, &hostaccess, &mode, &dpd, &close, &ipcomp)) + if (e->enumerate(e, &id, &name, &lifetime, &rekeytime, &jitter, &updown, + &hostaccess, &mode, &start, &dpd, &close, &ipcomp, &reqid)) { lifetime_cfg_t lft = { .time = { .life = lifetime, .rekey = rekeytime, .jitter = jitter } }; child_cfg = child_cfg_create(name, &lft, updown, hostaccess, mode, - dpd, close, ipcomp, 0, 0, NULL, NULL); - /* TODO: read proposal from db */ - child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP)); + start, dpd, close, ipcomp, 0, reqid, + NULL, NULL, 0); + add_esp_proposals(this, child_cfg, id); add_traffic_selectors(this, child_cfg, id); return child_cfg; } @@ -152,13 +191,13 @@ static void add_child_cfgs(private_sql_config_t *this, peer_cfg_t *peer, int id) child_cfg_t *child_cfg; e = this->db->query(this->db, - "SELECT id, name, lifetime, rekeytime, jitter, " - "updown, hostaccess, mode, dpd_action, close_action, ipcomp " + "SELECT id, name, lifetime, rekeytime, jitter, updown, hostaccess, " + "mode, start_action, dpd_action, close_action, ipcomp, reqid " "FROM child_configs JOIN peer_config_child_config ON id = child_cfg " "WHERE peer_cfg = ?", DB_INT, id, - DB_INT, DB_TEXT, DB_INT, DB_INT, DB_INT, - DB_TEXT, DB_INT, DB_INT, DB_INT, DB_INT, DB_INT); + DB_INT, DB_TEXT, DB_INT, DB_INT, DB_INT, DB_TEXT, DB_INT, + DB_INT, DB_INT, DB_INT, DB_INT, DB_INT, DB_INT); if (e) { while ((child_cfg = build_child_cfg(this, e))) @@ -170,29 +209,65 @@ static void add_child_cfgs(private_sql_config_t *this, peer_cfg_t *peer, int id) } /** - * build a ike configuration from a SQL query + * Add IKE proposals to an IKE config + */ +static void add_ike_proposals(private_sql_config_t *this, + ike_cfg_t *ike_cfg, int id) +{ + enumerator_t *e; + proposal_t *proposal; + char *prop; + bool use_default = TRUE; + + e = this->db->query(this->db, + "SELECT proposal " + "FROM proposals JOIN ike_config_proposal ON id = prop " + "WHERE ike_cfg = ? ORDER BY prio", + DB_INT, id, DB_TEXT); + if (e) + { + while (e->enumerate(e, &prop)) + { + proposal = proposal_create_from_string(PROTO_IKE, prop); + if (!proposal) + { + DBG1(DBG_CFG, "could not create IKE proposal from '%s'", prop); + break; + } + ike_cfg->add_proposal(ike_cfg, proposal); + use_default = FALSE; + } + e->destroy(e); + } + if (use_default) + { + ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE)); + } +} + +/** + * Build an IKE config from an SQL query */ static ike_cfg_t *build_ike_cfg(private_sql_config_t *this, enumerator_t *e, host_t *my_host, host_t *other_host) { - int certreq, force_encap; + int id, certreq, force_encap; char *local, *remote; - while (e->enumerate(e, &certreq, &force_encap, &local, &remote)) + while (e->enumerate(e, &id, &certreq, &force_encap, &local, &remote)) { ike_cfg_t *ike_cfg; ike_cfg = ike_cfg_create(certreq, force_encap, local, IKEV2_UDP_PORT, remote, IKEV2_UDP_PORT); - /* TODO: read proposal from db */ - ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE)); + add_ike_proposals(this, ike_cfg, id); return ike_cfg; } return NULL; } /** - * Query a IKE config by its id + * Query an IKE config by its id */ static ike_cfg_t* get_ike_cfg_by_id(private_sql_config_t *this, int id) { @@ -200,10 +275,10 @@ static ike_cfg_t* get_ike_cfg_by_id(private_sql_config_t *this, int id) ike_cfg_t *ike_cfg = NULL; e = this->db->query(this->db, - "SELECT certreq, force_encap, local, remote " + "SELECT id, certreq, force_encap, local, remote " "FROM ike_configs WHERE id = ?", DB_INT, id, - DB_INT, DB_INT, DB_TEXT, DB_TEXT); + DB_INT, DB_INT, DB_INT, DB_TEXT, DB_TEXT); if (e) { ike_cfg = build_ike_cfg(this, e, NULL, NULL); @@ -246,7 +321,7 @@ static peer_cfg_t *get_peer_cfg_by_id(private_sql_config_t *this, int id) } /** - * build a peer configuration from a SQL query + * Build a peer config from an SQL query */ static peer_cfg_t *build_peer_cfg(private_sql_config_t *this, enumerator_t *e, identification_t *me, identification_t *other) @@ -325,10 +400,8 @@ static peer_cfg_t *build_peer_cfg(private_sql_config_t *this, enumerator_t *e, return NULL; } -/** - * implements backend_t.get_peer_cfg_by_name. - */ -static peer_cfg_t *get_peer_cfg_by_name(private_sql_config_t *this, char *name) +METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*, + private_sql_config_t *this, char *name) { enumerator_t *e; peer_cfg_t *peer_cfg = NULL; @@ -398,11 +471,8 @@ static void ike_enumerator_destroy(ike_enumerator_t *this) free(this); } -/** - * Implementation of backend_t.create_ike_cfg_enumerator. - */ -static enumerator_t* create_ike_cfg_enumerator(private_sql_config_t *this, - host_t *me, host_t *other) +METHOD(backend_t, create_ike_cfg_enumerator, enumerator_t*, + private_sql_config_t *this, host_t *me, host_t *other) { ike_enumerator_t *e = malloc_thing(ike_enumerator_t); @@ -414,9 +484,9 @@ static enumerator_t* create_ike_cfg_enumerator(private_sql_config_t *this, e->public.destroy = (void*)ike_enumerator_destroy; e->inner = this->db->query(this->db, - "SELECT certreq, force_encap, local, remote " + "SELECT id, certreq, force_encap, local, remote " "FROM ike_configs", - DB_INT, DB_INT, DB_TEXT, DB_TEXT); + DB_INT, DB_INT, DB_INT, DB_TEXT, DB_TEXT); if (!e->inner) { free(e); @@ -466,12 +536,8 @@ static void peer_enumerator_destroy(peer_enumerator_t *this) free(this); } -/** - * Implementation of backend_t.create_peer_cfg_enumerator. - */ -static enumerator_t* create_peer_cfg_enumerator(private_sql_config_t *this, - identification_t *me, - identification_t *other) +METHOD(backend_t, create_peer_cfg_enumerator, enumerator_t*, + private_sql_config_t *this, identification_t *me, identification_t *other) { peer_enumerator_t *e = malloc_thing(peer_enumerator_t); @@ -508,10 +574,8 @@ static enumerator_t* create_peer_cfg_enumerator(private_sql_config_t *this, return &e->public; } -/** - * Implementation of sql_config_t.destroy. - */ -static void destroy(private_sql_config_t *this) +METHOD(sql_config_t, destroy, void, + private_sql_config_t *this) { free(this); } @@ -521,14 +585,19 @@ static void destroy(private_sql_config_t *this) */ sql_config_t *sql_config_create(database_t *db) { - private_sql_config_t *this = malloc_thing(private_sql_config_t); - - this->public.backend.create_peer_cfg_enumerator = (enumerator_t*(*)(backend_t*, identification_t *me, identification_t *other))create_peer_cfg_enumerator; - this->public.backend.create_ike_cfg_enumerator = (enumerator_t*(*)(backend_t*, host_t *me, host_t *other))create_ike_cfg_enumerator; - this->public.backend.get_peer_cfg_by_name = (peer_cfg_t* (*)(backend_t*,char*))get_peer_cfg_by_name; - this->public.destroy = (void(*)(sql_config_t*))destroy; + private_sql_config_t *this; - this->db = db; + INIT(this, + .public = { + .backend = { + .create_peer_cfg_enumerator = _create_peer_cfg_enumerator, + .create_ike_cfg_enumerator = _create_ike_cfg_enumerator, + .get_peer_cfg_by_name = _get_peer_cfg_by_name, + }, + .destroy = _destroy, + }, + .db = db + ); return &this->public; } diff --git a/src/libcharon/plugins/sql/sql_cred.c b/src/libcharon/plugins/sql/sql_cred.c index 12f4ab045..117eec921 100644 --- a/src/libcharon/plugins/sql/sql_cred.c +++ b/src/libcharon/plugins/sql/sql_cred.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2010 Tobias Brunner * Copyright (C) 2008 Martin Willi * Hochschule fuer Technik Rapperswil * @@ -37,6 +38,7 @@ struct private_sql_cred_t { database_t *db; }; + /** * enumerator over private keys */ @@ -49,11 +51,8 @@ typedef struct { private_key_t *current; } private_enumerator_t; -/** - * Implementation of private_enumerator_t.public.enumerate - */ -static bool private_enumerator_enumerate(private_enumerator_t *this, - private_key_t **key) +METHOD(enumerator_t, private_enumerator_enumerate, bool, + private_enumerator_t *this, private_key_t **key) { chunk_t blob; int type; @@ -62,7 +61,7 @@ static bool private_enumerator_enumerate(private_enumerator_t *this, while (this->inner->enumerate(this->inner, &type, &blob)) { this->current = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, type, - BUILD_BLOB_ASN1_DER, blob, + BUILD_BLOB_PEM, blob, BUILD_END); if (this->current) { @@ -74,29 +73,25 @@ static bool private_enumerator_enumerate(private_enumerator_t *this, return FALSE; } -/** - * Implementation of private_enumerator_t.public.destroy - */ -static void private_enumerator_destroy(private_enumerator_t *this) +METHOD(enumerator_t, private_enumerator_destroy, void, + private_enumerator_t *this) { DESTROY_IF(this->current); this->inner->destroy(this->inner); free(this); } -/** - * Implementation of credential_set_t.create_private_enumerator. - */ -static enumerator_t* create_private_enumerator(private_sql_cred_t *this, - key_type_t type, - identification_t *id) +METHOD(credential_set_t, create_private_enumerator, enumerator_t*, + private_sql_cred_t *this, key_type_t type, identification_t *id) { private_enumerator_t *e; - e = malloc_thing(private_enumerator_t); - e->current = NULL; - e->public.enumerate = (void*)private_enumerator_enumerate; - e->public.destroy = (void*)private_enumerator_destroy; + INIT(e, + .public = { + .enumerate = (void*)_private_enumerator_enumerate, + .destroy = _private_enumerator_destroy, + }, + ); if (id && id->get_type(id) != ID_ANY) { e->inner = this->db->query(this->db, @@ -123,6 +118,7 @@ static enumerator_t* create_private_enumerator(private_sql_cred_t *this, return &e->public; } + /** * enumerator over certificates */ @@ -135,11 +131,8 @@ typedef struct { certificate_t *current; } cert_enumerator_t; -/** - * Implementation of cert_enumerator_t.public.enumerate - */ -static bool cert_enumerator_enumerate(cert_enumerator_t *this, - certificate_t **cert) +METHOD(enumerator_t, cert_enumerator_enumerate, bool, + cert_enumerator_t *this, certificate_t **cert) { chunk_t blob; int type; @@ -148,7 +141,7 @@ static bool cert_enumerator_enumerate(cert_enumerator_t *this, while (this->inner->enumerate(this->inner, &type, &blob)) { this->current = lib->creds->create(lib->creds, CRED_CERTIFICATE, type, - BUILD_BLOB_ASN1_DER, blob, + BUILD_BLOB_PEM, blob, BUILD_END); if (this->current) { @@ -160,29 +153,26 @@ static bool cert_enumerator_enumerate(cert_enumerator_t *this, return FALSE; } -/** - * Implementation of cert_enumerator_t.public.destroy - */ -static void cert_enumerator_destroy(cert_enumerator_t *this) +METHOD(enumerator_t, cert_enumerator_destroy, void, + cert_enumerator_t *this) { DESTROY_IF(this->current); this->inner->destroy(this->inner); free(this); } -/** - * Implementation of credential_set_t.create_cert_enumerator. - */ -static enumerator_t* create_cert_enumerator(private_sql_cred_t *this, - certificate_type_t cert, key_type_t key, - identification_t *id, bool trusted) +METHOD(credential_set_t, create_cert_enumerator, enumerator_t*, + private_sql_cred_t *this, certificate_type_t cert, key_type_t key, + identification_t *id, bool trusted) { cert_enumerator_t *e; - e = malloc_thing(cert_enumerator_t); - e->current = NULL; - e->public.enumerate = (void*)cert_enumerator_enumerate; - e->public.destroy = (void*)cert_enumerator_destroy; + INIT(e, + .public = { + .enumerate = (void*)_cert_enumerator_enumerate, + .destroy = _cert_enumerator_destroy, + }, + ); if (id && id->get_type(id) != ID_ANY) { e->inner = this->db->query(this->db, @@ -213,6 +203,7 @@ static enumerator_t* create_cert_enumerator(private_sql_cred_t *this, return &e->public; } + /** * enumerator over shared keys */ @@ -229,12 +220,9 @@ typedef struct { shared_key_t *current; } shared_enumerator_t; -/** - * Implementation of shared_enumerator_t.public.enumerate - */ -static bool shared_enumerator_enumerate(shared_enumerator_t *this, - shared_key_t **shared, - id_match_t *me, id_match_t *other) +METHOD(enumerator_t, shared_enumerator_enumerate, bool, + shared_enumerator_t *this, shared_key_t **shared, + id_match_t *me, id_match_t *other) { chunk_t blob; int type; @@ -261,31 +249,28 @@ static bool shared_enumerator_enumerate(shared_enumerator_t *this, return FALSE; } -/** - * Implementation of shared_enumerator_t.public.destroy - */ -static void shared_enumerator_destroy(shared_enumerator_t *this) +METHOD(enumerator_t, shared_enumerator_destroy, void, + shared_enumerator_t *this) { DESTROY_IF(this->current); this->inner->destroy(this->inner); free(this); } -/** - * Implementation of credential_set_t.create_shared_enumerator. - */ -static enumerator_t* create_shared_enumerator(private_sql_cred_t *this, - shared_key_type_t type, - identification_t *me, identification_t *other) +METHOD(credential_set_t, create_shared_enumerator, enumerator_t*, + private_sql_cred_t *this, shared_key_type_t type, + identification_t *me, identification_t *other) { shared_enumerator_t *e; - e = malloc_thing(shared_enumerator_t); - e->me = me; - e->other = other; - e->current = NULL; - e->public.enumerate = (void*)shared_enumerator_enumerate; - e->public.destroy = (void*)shared_enumerator_destroy; + INIT(e, + .public = { + .enumerate = (void*)_shared_enumerator_enumerate, + .destroy = _shared_enumerator_destroy, + }, + .me = me, + .other = other, + ); if (!me && !other) { e->inner = this->db->query(this->db, @@ -329,36 +314,141 @@ static enumerator_t* create_shared_enumerator(private_sql_cred_t *this, return &e->public; } + /** - * Implementation of credential_set_t.cache_cert. + * enumerator over CDPs */ -static void cache_cert(private_sql_cred_t *this, certificate_t *cert) +typedef struct { + /** implements enumerator_t */ + enumerator_t public; + /** inner SQL enumerator */ + enumerator_t *inner; + /** currently enumerated string */ + char *current; +} cdp_enumerator_t; + +/** + * types of CDPs + */ +typedef enum { + /** any available CDP */ + CDP_TYPE_ANY = 0, + /** CRL */ + CDP_TYPE_CRL, + /** OCSP Responder */ + CDP_TYPE_OCSP, +} cdp_type_t; + +METHOD(enumerator_t, cdp_enumerator_enumerate, bool, + cdp_enumerator_t *this, char **uri) +{ + char *text; + + free(this->current); + while (this->inner->enumerate(this->inner, &text)) + { + *uri = this->current = strdup(text); + return TRUE; + } + this->current = NULL; + return FALSE; +} + +METHOD(enumerator_t, cdp_enumerator_destroy, void, + cdp_enumerator_t *this) +{ + free(this->current); + this->inner->destroy(this->inner); + free(this); +} + +METHOD(credential_set_t, create_cdp_enumerator, enumerator_t*, + private_sql_cred_t *this, certificate_type_t type, identification_t *id) +{ + cdp_enumerator_t *e; + cdp_type_t cdp_type; + + switch (type) + { /* we serve CRLs and OCSP responders */ + case CERT_X509_CRL: + cdp_type = CDP_TYPE_CRL; + break; + case CERT_X509_OCSP_RESPONSE: + cdp_type = CDP_TYPE_OCSP; + break; + case CERT_ANY: + cdp_type = CDP_TYPE_ANY; + break; + default: + return NULL; + } + INIT(e, + .public = { + .enumerate = (void*)_cdp_enumerator_enumerate, + .destroy = _cdp_enumerator_destroy, + }, + ); + if (id && id->get_type(id) != ID_ANY) + { + e->inner = this->db->query(this->db, + "SELECT dp.uri FROM certificate_distribution_points AS dp " + "JOIN certificate_authorities AS ca ON ca.id = dp.ca " + "JOIN certificates AS c ON c.id = ca.certificate " + "JOIN certificate_identity AS ci ON c.id = ci.certificate " + "JOIN identities AS i ON ci.identity = i.id " + "WHERE i.type = ? AND i.data = ? AND (? OR dp.type = ?)", + DB_INT, id->get_type(id), DB_BLOB, id->get_encoding(id), + DB_INT, cdp_type == CDP_TYPE_ANY, DB_INT, cdp_type, + DB_TEXT); + } + else + { + e->inner = this->db->query(this->db, + "SELECT dp.uri FROM certificate_distribution_points AS dp " + "WHERE (? OR dp.type = ?)", + DB_INT, cdp_type == CDP_TYPE_ANY, DB_INT, cdp_type, + DB_TEXT); + } + if (!e->inner) + { + free(e); + return NULL; + } + return &e->public; +} + +METHOD(credential_set_t, cache_cert, void, + private_sql_cred_t *this, certificate_t *cert) { /* TODO: implement CRL caching to database */ } -/** - * Implementation of sql_cred_t.destroy. - */ -static void destroy(private_sql_cred_t *this) +METHOD(sql_cred_t, destroy, void, + private_sql_cred_t *this) { free(this); } + /** * Described in header. */ sql_cred_t *sql_cred_create(database_t *db) { - private_sql_cred_t *this = malloc_thing(private_sql_cred_t); - - this->public.set.create_private_enumerator = (void*)create_private_enumerator; - this->public.set.create_cert_enumerator = (void*)create_cert_enumerator; - this->public.set.create_shared_enumerator = (void*)create_shared_enumerator; - this->public.set.create_cdp_enumerator = (void*)return_null; - this->public.set.cache_cert = (void*)cache_cert; - this->public.destroy = (void(*)(sql_cred_t*))destroy; - - this->db = db; + private_sql_cred_t *this; + + INIT(this, + .public = { + .set = { + .create_private_enumerator = _create_private_enumerator, + .create_cert_enumerator = _create_cert_enumerator, + .create_shared_enumerator = _create_shared_enumerator, + .create_cdp_enumerator = _create_cdp_enumerator, + .cache_cert = _cache_cert, + }, + .destroy = _destroy, + }, + .db = db, + ); return &this->public; } diff --git a/src/libcharon/plugins/sql/sql_plugin.c b/src/libcharon/plugins/sql/sql_plugin.c index 7b0a198d1..ad1eb91b1 100644 --- a/src/libcharon/plugins/sql/sql_plugin.c +++ b/src/libcharon/plugins/sql/sql_plugin.c @@ -53,10 +53,8 @@ struct private_sql_plugin_t { sql_logger_t *logger; }; -/** - * Implementation of plugin_t.destroy - */ -static void destroy(private_sql_plugin_t *this) +METHOD(plugin_t, destroy, void, + private_sql_plugin_t *this) { charon->backends->remove_backend(charon->backends, &this->config->backend); lib->credmgr->remove_set(lib->credmgr, &this->cred->set); @@ -83,11 +81,15 @@ plugin_t *sql_plugin_create() return NULL; } - this = malloc_thing(private_sql_plugin_t); - - this->public.plugin.destroy = (void(*)(plugin_t*))destroy; + INIT(this, + .public = { + .plugin = { + .destroy = _destroy, + }, + }, + .db = lib->db->create(lib->db, uri), + ); - this->db = lib->db->create(lib->db, uri); if (!this->db) { DBG1(DBG_CFG, "sql plugin failed to connect to database"); diff --git a/src/libcharon/plugins/stroke/Makefile.am b/src/libcharon/plugins/stroke/Makefile.am index 40888a40b..e561224e9 100644 --- a/src/libcharon/plugins/stroke/Makefile.am +++ b/src/libcharon/plugins/stroke/Makefile.am @@ -21,7 +21,6 @@ libstrongswan_stroke_la_SOURCES = \ stroke_cred.h stroke_cred.c \ stroke_ca.h stroke_ca.c \ stroke_attribute.h stroke_attribute.c \ - stroke_list.h stroke_list.c \ - stroke_shared_key.h stroke_shared_key.c + stroke_list.h stroke_list.c libstrongswan_stroke_la_LDFLAGS = -module -avoid-version diff --git a/src/libcharon/plugins/stroke/Makefile.in b/src/libcharon/plugins/stroke/Makefile.in index e6e98838b..ccf3eeede 100644 --- a/src/libcharon/plugins/stroke/Makefile.in +++ b/src/libcharon/plugins/stroke/Makefile.in @@ -77,7 +77,7 @@ LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES) libstrongswan_stroke_la_LIBADD = am_libstrongswan_stroke_la_OBJECTS = stroke_plugin.lo stroke_socket.lo \ stroke_config.lo stroke_control.lo stroke_cred.lo stroke_ca.lo \ - stroke_attribute.lo stroke_list.lo stroke_shared_key.lo + stroke_attribute.lo stroke_list.lo libstrongswan_stroke_la_OBJECTS = \ $(am_libstrongswan_stroke_la_OBJECTS) libstrongswan_stroke_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ @@ -223,9 +223,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -264,6 +262,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ @@ -292,8 +292,7 @@ libstrongswan_stroke_la_SOURCES = \ stroke_cred.h stroke_cred.c \ stroke_ca.h stroke_ca.c \ stroke_attribute.h stroke_attribute.c \ - stroke_list.h stroke_list.c \ - stroke_shared_key.h stroke_shared_key.c + stroke_list.h stroke_list.c libstrongswan_stroke_la_LDFLAGS = -module -avoid-version all: all-am @@ -386,7 +385,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stroke_cred.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stroke_list.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stroke_plugin.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stroke_shared_key.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stroke_socket.Plo@am__quote@ .c.o: diff --git a/src/libcharon/plugins/stroke/stroke_ca.c b/src/libcharon/plugins/stroke/stroke_ca.c index 9a3ae0ab9..69e13deb9 100644 --- a/src/libcharon/plugins/stroke/stroke_ca.c +++ b/src/libcharon/plugins/stroke/stroke_ca.c @@ -113,6 +113,7 @@ static void ca_section_destroy(ca_section_t *this) this->crl->destroy_function(this->crl, free); this->ocsp->destroy_function(this->ocsp, free); this->hashes->destroy_offset(this->hashes, offsetof(identification_t, destroy)); + this->cert->destroy(this->cert); free(this->certuribase); free(this->name); free(this); @@ -207,11 +208,8 @@ static enumerator_t *create_inner_cdp_hashandurl(ca_section_t *section, cdp_data return enumerator; } -/** - * Implementation of credential_set_t.create_cdp_enumerator. - */ -static enumerator_t *create_cdp_enumerator(private_stroke_ca_t *this, - certificate_type_t type, identification_t *id) +METHOD(credential_set_t, create_cdp_enumerator, enumerator_t*, + private_stroke_ca_t *this, certificate_type_t type, identification_t *id) { cdp_data_t *data; @@ -235,10 +233,9 @@ static enumerator_t *create_cdp_enumerator(private_stroke_ca_t *this, (type == CERT_X509) ? (void*)create_inner_cdp_hashandurl : (void*)create_inner_cdp, data, (void*)cdp_data_destroy); } -/** - * Implementation of stroke_ca_t.add. - */ -static void add(private_stroke_ca_t *this, stroke_msg_t *msg) + +METHOD(stroke_ca_t, add, void, + private_stroke_ca_t *this, stroke_msg_t *msg) { certificate_t *cert; ca_section_t *ca; @@ -279,10 +276,8 @@ static void add(private_stroke_ca_t *this, stroke_msg_t *msg) } } -/** - * Implementation of stroke_ca_t.del. - */ -static void del(private_stroke_ca_t *this, stroke_msg_t *msg) +METHOD(stroke_ca_t, del, void, + private_stroke_ca_t *this, stroke_msg_t *msg) { enumerator_t *enumerator; ca_section_t *ca = NULL; @@ -336,10 +331,8 @@ static void list_uris(linked_list_t *list, char *label, FILE *out) enumerator->destroy(enumerator); } -/** - * Implementation of stroke_ca_t.check_for_hash_and_url. - */ -static void check_for_hash_and_url(private_stroke_ca_t *this, certificate_t* cert) +METHOD(stroke_ca_t, check_for_hash_and_url, void, + private_stroke_ca_t *this, certificate_t* cert) { ca_section_t *section; enumerator_t *enumerator; @@ -376,10 +369,8 @@ static void check_for_hash_and_url(private_stroke_ca_t *this, certificate_t* cer hasher->destroy(hasher); } -/** - * Implementation of stroke_ca_t.list. - */ -static void list(private_stroke_ca_t *this, stroke_msg_t *msg, FILE *out) +METHOD(stroke_ca_t, list, void, + private_stroke_ca_t *this, stroke_msg_t *msg, FILE *out) { bool first = TRUE; ca_section_t *section; @@ -426,10 +417,8 @@ static void list(private_stroke_ca_t *this, stroke_msg_t *msg, FILE *out) this->lock->unlock(this->lock); } -/** - * Implementation of stroke_ca_t.destroy - */ -static void destroy(private_stroke_ca_t *this) +METHOD(stroke_ca_t, destroy, void, + private_stroke_ca_t *this) { this->sections->destroy_function(this->sections, (void*)ca_section_destroy); this->lock->destroy(this->lock); @@ -441,22 +430,27 @@ static void destroy(private_stroke_ca_t *this) */ stroke_ca_t *stroke_ca_create(stroke_cred_t *cred) { - private_stroke_ca_t *this = malloc_thing(private_stroke_ca_t); - - this->public.set.create_private_enumerator = (void*)return_null; - this->public.set.create_cert_enumerator = (void*)return_null; - this->public.set.create_shared_enumerator = (void*)return_null; - this->public.set.create_cdp_enumerator = (void*)create_cdp_enumerator; - this->public.set.cache_cert = (void*)nop; - this->public.add = (void(*)(stroke_ca_t*, stroke_msg_t *msg))add; - this->public.del = (void(*)(stroke_ca_t*, stroke_msg_t *msg))del; - this->public.list = (void(*)(stroke_ca_t*, stroke_msg_t *msg, FILE *out))list; - this->public.check_for_hash_and_url = (void(*)(stroke_ca_t*, certificate_t*))check_for_hash_and_url; - this->public.destroy = (void(*)(stroke_ca_t*))destroy; - - this->sections = linked_list_create(); - this->lock = rwlock_create(RWLOCK_TYPE_DEFAULT); - this->cred = cred; + private_stroke_ca_t *this; + + INIT(this, + .public = { + .set = { + .create_private_enumerator = (void*)return_null, + .create_cert_enumerator = (void*)return_null, + .create_shared_enumerator = (void*)return_null, + .create_cdp_enumerator = _create_cdp_enumerator, + .cache_cert = (void*)nop, + }, + .add = _add, + .del = _del, + .list = _list, + .check_for_hash_and_url = _check_for_hash_and_url, + .destroy = _destroy, + }, + .sections = linked_list_create(), + .lock = rwlock_create(RWLOCK_TYPE_DEFAULT), + .cred = cred, + ); return &this->public; } diff --git a/src/libcharon/plugins/stroke/stroke_config.c b/src/libcharon/plugins/stroke/stroke_config.c index 165212a5e..ea7d17592 100644 --- a/src/libcharon/plugins/stroke/stroke_config.c +++ b/src/libcharon/plugins/stroke/stroke_config.c @@ -53,12 +53,8 @@ struct private_stroke_config_t { stroke_cred_t *cred; }; -/** - * Implementation of backend_t.create_peer_cfg_enumerator. - */ -static enumerator_t* create_peer_cfg_enumerator(private_stroke_config_t *this, - identification_t *me, - identification_t *other) +METHOD(backend_t, create_peer_cfg_enumerator, enumerator_t*, + private_stroke_config_t *this, identification_t *me, identification_t *other) { this->mutex->lock(this->mutex); return enumerator_create_cleaner(this->list->create_enumerator(this->list), @@ -74,11 +70,8 @@ static bool ike_filter(void *data, peer_cfg_t **in, ike_cfg_t **out) return TRUE; } -/** - * Implementation of backend_t.create_ike_cfg_enumerator. - */ -static enumerator_t* create_ike_cfg_enumerator(private_stroke_config_t *this, - host_t *me, host_t *other) +METHOD(backend_t, create_ike_cfg_enumerator, enumerator_t*, + private_stroke_config_t *this, host_t *me, host_t *other) { this->mutex->lock(this->mutex); return enumerator_create_filter(this->list->create_enumerator(this->list), @@ -86,10 +79,8 @@ static enumerator_t* create_ike_cfg_enumerator(private_stroke_config_t *this, (void*)this->mutex->unlock); } -/** - * implements backend_t.get_peer_cfg_by_name. - */ -static peer_cfg_t *get_peer_cfg_by_name(private_stroke_config_t *this, char *name) +METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*, + private_stroke_config_t *this, char *name) { enumerator_t *e1, *e2; peer_cfg_t *current, *found = NULL; @@ -438,13 +429,38 @@ static auth_cfg_t *build_auth_cfg(private_stroke_config_t *this, enumerator->destroy(enumerator); } + /* certificatePolicies */ + if (end->cert_policy) + { + enumerator_t *enumerator; + char *policy; + + enumerator = enumerator_create_token(end->cert_policy, ",", " "); + while (enumerator->enumerate(enumerator, &policy)) + { + cfg->add(cfg, AUTH_RULE_CERT_POLICY, strdup(policy)); + } + enumerator->destroy(enumerator); + } + /* authentication metod (class, actually) */ if (streq(auth, "pubkey") || - streq(auth, "rsasig") || streq(auth, "rsa") || - streq(auth, "ecdsasig") || streq(auth, "ecdsa")) + strneq(auth, "rsa", strlen("rsa")) || + strneq(auth, "ecdsa", strlen("ecdsa"))) { + u_int strength; + cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY); build_crl_policy(cfg, local, msg->add_conn.crl_policy); + + if (sscanf(auth, "rsa-%d", &strength) == 1) + { + cfg->add(cfg, AUTH_RULE_RSA_STRENGTH, (uintptr_t)strength); + } + if (sscanf(auth, "ecdsa-%d", &strength) == 1) + { + cfg->add(cfg, AUTH_RULE_ECDSA_STRENGTH, (uintptr_t)strength); + } } else if (streq(auth, "psk") || streq(auth, "secret")) { @@ -808,9 +824,9 @@ static child_cfg_t *build_child_cfg(private_stroke_config_t *this, child_cfg = child_cfg_create( msg->add_conn.name, &lifetime, msg->add_conn.me.updown, msg->add_conn.me.hostaccess, - msg->add_conn.mode, dpd, dpd, msg->add_conn.ipcomp, + msg->add_conn.mode, ACTION_NONE, dpd, dpd, msg->add_conn.ipcomp, msg->add_conn.inactivity, msg->add_conn.reqid, - &mark_in, &mark_out); + &mark_in, &mark_out, msg->add_conn.tfc); child_cfg->set_mipv6_options(child_cfg, msg->add_conn.proxy_mode, msg->add_conn.install_policy); add_ts(this, &msg->add_conn.me, child_cfg, TRUE); @@ -821,10 +837,8 @@ static child_cfg_t *build_child_cfg(private_stroke_config_t *this, return child_cfg; } -/** - * Implementation of stroke_config_t.add. - */ -static void add(private_stroke_config_t *this, stroke_msg_t *msg) +METHOD(stroke_config_t, add, void, + private_stroke_config_t *this, stroke_msg_t *msg) { ike_cfg_t *ike_cfg, *existing_ike; peer_cfg_t *peer_cfg, *existing; @@ -884,10 +898,8 @@ static void add(private_stroke_config_t *this, stroke_msg_t *msg) } } -/** - * Implementation of stroke_config_t.del. - */ -static void del(private_stroke_config_t *this, stroke_msg_t *msg) +METHOD(stroke_config_t, del, void, + private_stroke_config_t *this, stroke_msg_t *msg) { enumerator_t *enumerator, *children; peer_cfg_t *peer; @@ -938,10 +950,8 @@ static void del(private_stroke_config_t *this, stroke_msg_t *msg) } } -/** - * Implementation of stroke_config_t.destroy - */ -static void destroy(private_stroke_config_t *this) +METHOD(stroke_config_t, destroy, void, + private_stroke_config_t *this) { this->list->destroy_offset(this->list, offsetof(peer_cfg_t, destroy)); this->mutex->destroy(this->mutex); @@ -953,19 +963,24 @@ static void destroy(private_stroke_config_t *this) */ stroke_config_t *stroke_config_create(stroke_ca_t *ca, stroke_cred_t *cred) { - private_stroke_config_t *this = malloc_thing(private_stroke_config_t); - - this->public.backend.create_peer_cfg_enumerator = (enumerator_t*(*)(backend_t*, identification_t *me, identification_t *other))create_peer_cfg_enumerator; - this->public.backend.create_ike_cfg_enumerator = (enumerator_t*(*)(backend_t*, host_t *me, host_t *other))create_ike_cfg_enumerator; - this->public.backend.get_peer_cfg_by_name = (peer_cfg_t* (*)(backend_t*,char*))get_peer_cfg_by_name; - this->public.add = (void(*)(stroke_config_t*, stroke_msg_t *msg))add; - this->public.del = (void(*)(stroke_config_t*, stroke_msg_t *msg))del; - this->public.destroy = (void(*)(stroke_config_t*))destroy; - - this->list = linked_list_create(); - this->mutex = mutex_create(MUTEX_TYPE_RECURSIVE); - this->ca = ca; - this->cred = cred; + private_stroke_config_t *this; + + INIT(this, + .public = { + .backend = { + .create_peer_cfg_enumerator = _create_peer_cfg_enumerator, + .create_ike_cfg_enumerator = _create_ike_cfg_enumerator, + .get_peer_cfg_by_name = _get_peer_cfg_by_name, + }, + .add = _add, + .del = _del, + .destroy = _destroy, + }, + .list = linked_list_create(), + .mutex = mutex_create(MUTEX_TYPE_RECURSIVE), + .ca = ca, + .cred = cred, + ); return &this->public; } diff --git a/src/libcharon/plugins/stroke/stroke_control.c b/src/libcharon/plugins/stroke/stroke_control.c index e0398ba78..3541ab8f9 100644 --- a/src/libcharon/plugins/stroke/stroke_control.c +++ b/src/libcharon/plugins/stroke/stroke_control.c @@ -17,6 +17,8 @@ #include <daemon.h> #include <processing/jobs/delete_ike_sa_job.h> +#include <processing/jobs/rekey_ike_sa_job.h> +#include <processing/jobs/rekey_child_sa_job.h> typedef struct private_stroke_control_t private_stroke_control_t; @@ -90,10 +92,8 @@ static child_cfg_t* get_child_from_peer(peer_cfg_t *peer_cfg, char *name) return found; } -/** - * Implementation of stroke_control_t.initiate. - */ -static void initiate(private_stroke_control_t *this, stroke_msg_t *msg, FILE *out) +METHOD(stroke_control_t, initiate, void, + private_stroke_control_t *this, stroke_msg_t *msg, FILE *out) { peer_cfg_t *peer_cfg; child_cfg_t *child_cfg; @@ -137,76 +137,89 @@ static void initiate(private_stroke_control_t *this, stroke_msg_t *msg, FILE *ou } /** - * Implementation of stroke_control_t.terminate. + * Parse a terminate/rekey specifier */ -static void terminate(private_stroke_control_t *this, stroke_msg_t *msg, FILE *out) +static bool parse_specifier(char *string, u_int32_t *id, + char **name, bool *child, bool *all) { - char *string, *pos = NULL, *name = NULL; - u_int32_t id = 0; - bool child, all = FALSE; int len; - ike_sa_t *ike_sa; - enumerator_t *enumerator; - linked_list_t *ike_list, *child_list; - stroke_log_info_t info; - uintptr_t del; + char *pos = NULL; - string = msg->terminate.name; + *id = 0; + *name = NULL; + *all = FALSE; len = strlen(string); if (len < 1) { - DBG1(DBG_CFG, "error parsing string"); - return; + return FALSE; } switch (string[len-1]) { case '}': - child = TRUE; + *child = TRUE; pos = strchr(string, '{'); break; case ']': - child = FALSE; + *child = FALSE; pos = strchr(string, '['); break; default: - name = string; - child = FALSE; + *name = string; + *child = FALSE; break; } - if (name) + if (*name) { /* is a single name */ } else if (pos == string + len - 2) { /* is name[] or name{} */ string[len-2] = '\0'; - name = string; + *name = string; } else { if (!pos) { - DBG1(DBG_CFG, "error parsing string"); - return; + return FALSE; } if (*(pos + 1) == '*') { /* is name[*] */ - all = TRUE; + *all = TRUE; *pos = '\0'; - name = string; + *name = string; } else { /* is name[123] or name{23} */ - id = atoi(pos + 1); - if (id == 0) + *id = atoi(pos + 1); + if (*id == 0) { - DBG1(DBG_CFG, "error parsing string"); - return; + return FALSE; } } } + return TRUE; +} + +METHOD(stroke_control_t, terminate, void, + private_stroke_control_t *this, stroke_msg_t *msg, FILE *out) +{ + char *name; + u_int32_t id; + bool child, all; + ike_sa_t *ike_sa; + enumerator_t *enumerator; + linked_list_t *ike_list, *child_list; + stroke_log_info_t info; + uintptr_t del; + + if (!parse_specifier(msg->terminate.name, &id, &name, &child, &all)) + { + DBG1(DBG_CFG, "error parsing specifier string"); + return; + } info.out = out; info.level = msg->output_verbosity; @@ -293,11 +306,68 @@ static void terminate(private_stroke_control_t *this, stroke_msg_t *msg, FILE *o child_list->destroy(child_list); } -/** - * Implementation of stroke_control_t.terminate_srcip. - */ -static void terminate_srcip(private_stroke_control_t *this, - stroke_msg_t *msg, FILE *out) +METHOD(stroke_control_t, rekey, void, + private_stroke_control_t *this, stroke_msg_t *msg, FILE *out) +{ + char *name; + u_int32_t id; + bool child, all, finished = FALSE; + ike_sa_t *ike_sa; + enumerator_t *enumerator; + + if (!parse_specifier(msg->terminate.name, &id, &name, &child, &all)) + { + DBG1(DBG_CFG, "error parsing specifier string"); + return; + } + enumerator = charon->controller->create_ike_sa_enumerator(charon->controller); + while (enumerator->enumerate(enumerator, &ike_sa)) + { + child_sa_t *child_sa; + iterator_t *children; + + if (child) + { + children = ike_sa->create_child_sa_iterator(ike_sa); + while (children->iterate(children, (void**)&child_sa)) + { + if ((name && streq(name, child_sa->get_name(child_sa))) || + (id && id == child_sa->get_reqid(child_sa))) + { + lib->processor->queue_job(lib->processor, + (job_t*)rekey_child_sa_job_create( + child_sa->get_reqid(child_sa), + child_sa->get_protocol(child_sa), + child_sa->get_spi(child_sa, TRUE))); + if (!all) + { + finished = TRUE; + break; + } + } + } + children->destroy(children); + } + else if ((name && streq(name, ike_sa->get_name(ike_sa))) || + (id && id == ike_sa->get_unique_id(ike_sa))) + { + lib->processor->queue_job(lib->processor, + (job_t*)rekey_ike_sa_job_create(ike_sa->get_id(ike_sa), FALSE)); + if (!all) + { + finished = TRUE; + } + } + if (finished) + { + break; + } + } + enumerator->destroy(enumerator); +} + +METHOD(stroke_control_t, terminate_srcip, void, + private_stroke_control_t *this, stroke_msg_t *msg, FILE *out) { enumerator_t *enumerator; ike_sa_t *ike_sa; @@ -362,10 +432,8 @@ static void terminate_srcip(private_stroke_control_t *this, DESTROY_IF(end); } -/** - * Implementation of stroke_control_t.purge_ike - */ -static void purge_ike(private_stroke_control_t *this, stroke_msg_t *msg, FILE *out) +METHOD(stroke_control_t, purge_ike, void, + private_stroke_control_t *this, stroke_msg_t *msg, FILE *out) { enumerator_t *enumerator; iterator_t *iterator; @@ -402,10 +470,8 @@ static void purge_ike(private_stroke_control_t *this, stroke_msg_t *msg, FILE *o list->destroy(list); } -/** - * Implementation of stroke_control_t.route. - */ -static void route(private_stroke_control_t *this, stroke_msg_t *msg, FILE *out) +METHOD(stroke_control_t, route, void, + private_stroke_control_t *this, stroke_msg_t *msg, FILE *out) { peer_cfg_t *peer_cfg; child_cfg_t *child_cfg; @@ -443,10 +509,8 @@ static void route(private_stroke_control_t *this, stroke_msg_t *msg, FILE *out) child_cfg->destroy(child_cfg); } -/** - * Implementation of stroke_control_t.unroute. - */ -static void unroute(private_stroke_control_t *this, stroke_msg_t *msg, FILE *out) +METHOD(stroke_control_t, unroute, void, + private_stroke_control_t *this, stroke_msg_t *msg, FILE *out) { child_sa_t *child_sa; enumerator_t *enumerator; @@ -468,10 +532,8 @@ static void unroute(private_stroke_control_t *this, stroke_msg_t *msg, FILE *out fprintf(out, "configuration '%s' not found\n", msg->unroute.name); } -/** - * Implementation of stroke_control_t.destroy - */ -static void destroy(private_stroke_control_t *this) +METHOD(stroke_control_t, destroy, void, + private_stroke_control_t *this) { free(this); } @@ -481,15 +543,20 @@ static void destroy(private_stroke_control_t *this) */ stroke_control_t *stroke_control_create() { - private_stroke_control_t *this = malloc_thing(private_stroke_control_t); - - this->public.initiate = (void(*)(stroke_control_t*, stroke_msg_t *msg, FILE *out))initiate; - this->public.terminate = (void(*)(stroke_control_t*, stroke_msg_t *msg, FILE *out))terminate; - this->public.terminate_srcip = (void(*)(stroke_control_t*, stroke_msg_t *msg, FILE *out))terminate_srcip; - this->public.purge_ike = (void(*)(stroke_control_t*, stroke_msg_t *msg, FILE *out))purge_ike; - this->public.route = (void(*)(stroke_control_t*, stroke_msg_t *msg, FILE *out))route; - this->public.unroute = (void(*)(stroke_control_t*, stroke_msg_t *msg, FILE *out))unroute; - this->public.destroy = (void(*)(stroke_control_t*))destroy; + private_stroke_control_t *this; + + INIT(this, + .public = { + .initiate = _initiate, + .terminate = _terminate, + .terminate_srcip = _terminate_srcip, + .rekey = _rekey, + .purge_ike = _purge_ike, + .route = _route, + .unroute = _unroute, + .destroy = _destroy, + }, + ); return &this->public; } diff --git a/src/libcharon/plugins/stroke/stroke_control.h b/src/libcharon/plugins/stroke/stroke_control.h index 9b49bdc31..869aab3d3 100644 --- a/src/libcharon/plugins/stroke/stroke_control.h +++ b/src/libcharon/plugins/stroke/stroke_control.h @@ -54,6 +54,13 @@ struct stroke_control_t { void (*terminate_srcip)(stroke_control_t *this, stroke_msg_t *msg, FILE *out); /** + * Rekey a connection. + * + * @param msg stroke message + */ + void (*rekey)(stroke_control_t *this, stroke_msg_t *msg, FILE *out); + + /** * Delete IKE_SAs without a CHILD_SA. * * @param msg stroke message diff --git a/src/libcharon/plugins/stroke/stroke_cred.c b/src/libcharon/plugins/stroke/stroke_cred.c index 91e71f1f4..83e5a9ad6 100644 --- a/src/libcharon/plugins/stroke/stroke_cred.c +++ b/src/libcharon/plugins/stroke/stroke_cred.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Tobias Brunner + * Copyright (C) 2008-2010 Tobias Brunner * Copyright (C) 2008 Martin Willi * Hochschule fuer Technik Rapperswil * @@ -25,7 +25,6 @@ #include <unistd.h> #include "stroke_cred.h" -#include "stroke_shared_key.h" #include <credentials/certificates/x509.h> #include <credentials/certificates/crl.h> @@ -64,24 +63,9 @@ struct private_stroke_cred_t { stroke_cred_t public; /** - * list of trusted peer/signer/CA certificates (certificate_t) + * credentials */ - linked_list_t *certs; - - /** - * list of shared secrets (private_shared_key_t) - */ - linked_list_t *shared; - - /** - * list of private keys (private_key_t) - */ - linked_list_t *private; - - /** - * read-write lock to lists - */ - rwlock_t *lock; + mem_cred_t *creds; /** * cache CRLs to disk? @@ -90,237 +74,6 @@ struct private_stroke_cred_t { }; /** - * data to pass to various filters - */ -typedef struct { - private_stroke_cred_t *this; - identification_t *id; - certificate_type_t cert; - key_type_t key; -} id_data_t; - -/** - * destroy id enumerator data and unlock list - */ -static void id_data_destroy(id_data_t *data) -{ - data->this->lock->unlock(data->this->lock); - free(data); -} - -/** - * filter function for private key enumerator - */ -static bool private_filter(id_data_t *data, - private_key_t **in, private_key_t **out) -{ - private_key_t *key; - - key = *in; - if (data->key == KEY_ANY || data->key == key->get_type(key)) - { - if (data->id == NULL) - { - *out = key; - return TRUE; - } - if (key->has_fingerprint(key, data->id->get_encoding(data->id))) - { - *out = key; - return TRUE; - } - } - return FALSE; -} - -/** - * Implements credential_set_t.create_private_enumerator - */ -static enumerator_t* create_private_enumerator(private_stroke_cred_t *this, - key_type_t type, identification_t *id) -{ - id_data_t *data; - - data = malloc_thing(id_data_t); - data->this = this; - data->id = id; - data->key = type; - - this->lock->read_lock(this->lock); - return enumerator_create_filter(this->private->create_enumerator(this->private), - (void*)private_filter, data, - (void*)id_data_destroy); -} - -/** - * filter function for certs enumerator - */ -static bool certs_filter(id_data_t *data, certificate_t **in, certificate_t **out) -{ - public_key_t *public; - certificate_t *cert = *in; - - if (data->cert != CERT_ANY && data->cert != cert->get_type(cert)) - { - return FALSE; - } - if (data->id == NULL || cert->has_subject(cert, data->id)) - { - *out = *in; - return TRUE; - } - - public = cert->get_public_key(cert); - if (public) - { - if (data->key == KEY_ANY || data->key != public->get_type(public)) - { - if (public->has_fingerprint(public, data->id->get_encoding(data->id))) - { - public->destroy(public); - *out = *in; - return TRUE; - } - } - public->destroy(public); - } - return FALSE; -} - -/** - * Implements credential_set_t.create_cert_enumerator - */ -static enumerator_t* create_cert_enumerator(private_stroke_cred_t *this, - certificate_type_t cert, key_type_t key, - identification_t *id, bool trusted) -{ - id_data_t *data; - - if (trusted && (cert == CERT_X509_CRL || cert == CERT_X509_AC)) - { - return NULL; - } - data = malloc_thing(id_data_t); - data->this = this; - data->id = id; - data->cert = cert; - data->key = key; - - this->lock->read_lock(this->lock); - return enumerator_create_filter(this->certs->create_enumerator(this->certs), - (void*)certs_filter, data, - (void*)id_data_destroy); -} - -typedef struct { - private_stroke_cred_t *this; - identification_t *me; - identification_t *other; - shared_key_type_t type; -} shared_data_t; - -/** - * free shared key enumerator data and unlock list - */ -static void shared_data_destroy(shared_data_t *data) -{ - data->this->lock->unlock(data->this->lock); - free(data); -} - -/** - * filter function for certs enumerator - */ -static bool shared_filter(shared_data_t *data, - stroke_shared_key_t **in, shared_key_t **out, - void **unused1, id_match_t *me, - void **unused2, id_match_t *other) -{ - id_match_t my_match = ID_MATCH_NONE, other_match = ID_MATCH_NONE; - stroke_shared_key_t *stroke = *in; - shared_key_t *shared = &stroke->shared; - - if (data->type != SHARED_ANY && shared->get_type(shared) != data->type) - { - return FALSE; - } - - if (data->me) - { - my_match = stroke->has_owner(stroke, data->me); - } - if (data->other) - { - other_match = stroke->has_owner(stroke, data->other); - } - if ((data->me || data->other) && (!my_match && !other_match)) - { - return FALSE; - } - *out = shared; - if (me) - { - *me = my_match; - } - if (other) - { - *other = other_match; - } - return TRUE; -} - -/** - * Implements credential_set_t.create_shared_enumerator - */ -static enumerator_t* create_shared_enumerator(private_stroke_cred_t *this, - shared_key_type_t type, identification_t *me, - identification_t *other) -{ - shared_data_t *data = malloc_thing(shared_data_t); - - data->this = this; - data->me = me; - data->other = other; - data->type = type; - this->lock->read_lock(this->lock); - return enumerator_create_filter(this->shared->create_enumerator(this->shared), - (void*)shared_filter, data, - (void*)shared_data_destroy); -} - -/** - * Add a certificate to chain - */ -static certificate_t* add_cert(private_stroke_cred_t *this, certificate_t *cert) -{ - certificate_t *current; - enumerator_t *enumerator; - bool new = TRUE; - - this->lock->read_lock(this->lock); - enumerator = this->certs->create_enumerator(this->certs); - while (enumerator->enumerate(enumerator, (void**)¤t)) - { - if (current->equals(current, cert)) - { - /* cert already in queue */ - cert->destroy(cert); - cert = current; - new = FALSE; - break; - } - } - enumerator->destroy(enumerator); - - if (new) - { - this->certs->insert_last(this->certs, cert); - } - this->lock->unlock(this->lock); - return cert; -} - -/** * Implementation of stroke_cred_t.load_ca. */ static certificate_t* load_ca(private_stroke_cred_t *this, char *filename) @@ -352,85 +105,12 @@ static certificate_t* load_ca(private_stroke_cred_t *this, char *filename) cert->destroy(cert); return NULL; } - return (certificate_t*)add_cert(this, cert); + return this->creds->add_cert_ref(this->creds, TRUE, cert); } return NULL; } /** - * Add X.509 CRL to chain - */ -static bool add_crl(private_stroke_cred_t *this, crl_t* crl) -{ - certificate_t *current, *cert = &crl->certificate; - enumerator_t *enumerator; - bool new = TRUE, found = FALSE; - - this->lock->write_lock(this->lock); - enumerator = this->certs->create_enumerator(this->certs); - while (enumerator->enumerate(enumerator, (void**)¤t)) - { - if (current->get_type(current) == CERT_X509_CRL) - { - crl_t *crl_c = (crl_t*)current; - chunk_t authkey = crl->get_authKeyIdentifier(crl); - chunk_t authkey_c = crl_c->get_authKeyIdentifier(crl_c); - - /* if compare authorityKeyIdentifiers if available */ - if (authkey.ptr && authkey_c.ptr && chunk_equals(authkey, authkey_c)) - { - found = TRUE; - } - else - { - identification_t *issuer = cert->get_issuer(cert); - identification_t *issuer_c = current->get_issuer(current); - - /* otherwise compare issuer distinguished names */ - if (issuer->equals(issuer, issuer_c)) - { - found = TRUE; - } - } - if (found) - { - new = crl_is_newer(crl, crl_c); - if (new) - { - this->certs->remove_at(this->certs, enumerator); - } - else - { - cert->destroy(cert); - } - break; - } - } - } - enumerator->destroy(enumerator); - - if (new) - { - this->certs->insert_last(this->certs, cert); - } - this->lock->unlock(this->lock); - return new; -} - -/** - * Add X.509 attribute certificate to chain - */ -static bool add_ac(private_stroke_cred_t *this, ac_t* ac) -{ - certificate_t *cert = &ac->certificate; - - this->lock->write_lock(this->lock); - this->certs->insert_last(this->certs, cert); - this->lock->unlock(this->lock); - return TRUE; -} - -/** * Implementation of stroke_cred_t.load_peer. */ static certificate_t* load_peer(private_stroke_cred_t *this, char *filename) @@ -453,10 +133,10 @@ static certificate_t* load_peer(private_stroke_cred_t *this, char *filename) BUILD_END); if (cert) { - cert = add_cert(this, cert); + cert = this->creds->add_cert_ref(this->creds, TRUE, cert); DBG1(DBG_CFG, " loaded certificate \"%Y\" from '%s'", cert->get_subject(cert), filename); - return cert->get_ref(cert); + return cert; } DBG1(DBG_CFG, " loading certificate from '%s' failed", filename); return NULL; @@ -511,8 +191,8 @@ static void load_certdir(private_stroke_cred_t *this, char *path, } else { - DBG1(DBG_CFG, " loaded ca certificate \"%Y\" from '%s'", - cert->get_subject(cert), file); + DBG1(DBG_CFG, " loaded ca certificate \"%Y\" " + "from '%s'", cert->get_subject(cert), file); } } else @@ -540,7 +220,7 @@ static void load_certdir(private_stroke_cred_t *this, char *path, } if (cert) { - add_cert(this, cert); + this->creds->add_cert(this->creds, TRUE, cert); } break; case CERT_X509_CRL: @@ -550,7 +230,7 @@ static void load_certdir(private_stroke_cred_t *this, char *path, BUILD_END); if (cert) { - add_crl(this, (crl_t*)cert); + this->creds->add_crl(this->creds, (crl_t*)cert); DBG1(DBG_CFG, " loaded crl from '%s'", file); } else @@ -565,7 +245,7 @@ static void load_certdir(private_stroke_cred_t *this, char *path, BUILD_END); if (cert) { - add_ac(this, (ac_t*)cert); + this->creds->add_cert(this->creds, FALSE, cert); DBG1(DBG_CFG, " loaded attribute certificate from '%s'", file); } @@ -593,7 +273,7 @@ static void cache_cert(private_stroke_cred_t *this, certificate_t *cert) crl_t *crl = (crl_t*)cert; cert->get_ref(cert); - if (add_crl(this, crl)) + if (this->creds->add_crl(this->creds, crl)) { char buf[BUF_LEN]; chunk_t chunk, hex; @@ -914,7 +594,6 @@ static bool load_pin(private_stroke_cred_t *this, chunk_t line, int line_nr, } /* unlock: smartcard needs the pin and potentially calls public set */ - this->lock->unlock(this->lock); switch (format) { case SC_FORMAT_SLOT_MODULE_KEYID: @@ -936,7 +615,6 @@ static bool load_pin(private_stroke_cred_t *this, chunk_t line, int line_nr, BUILD_PKCS11_KEYID, chunk, BUILD_END); break; } - this->lock->write_lock(this->lock); if (mem) { lib->credmgr->remove_local_set(lib->credmgr, &mem->set); @@ -951,7 +629,7 @@ static bool load_pin(private_stroke_cred_t *this, chunk_t line, int line_nr, if (key) { DBG1(DBG_CFG, " loaded private key from %.*s", sc.len, sc.ptr); - this->private->insert_last(this->private, key); + this->creds->add_key(this->creds, key); } return TRUE; } @@ -1022,11 +700,8 @@ static bool load_private(private_stroke_cred_t *this, chunk_t line, int line_nr, cb = callback_cred_create_shared((void*)passphrase_cb, &pp_data); lib->credmgr->add_local_set(lib->credmgr, &cb->set); - /* unlock, as the builder might ask for a secret */ - this->lock->unlock(this->lock); key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, key_type, BUILD_FROM_FILE, path, BUILD_END); - this->lock->write_lock(this->lock); lib->credmgr->remove_local_set(lib->credmgr, &cb->set); cb->destroy(cb); @@ -1042,11 +717,8 @@ static bool load_private(private_stroke_cred_t *this, chunk_t line, int line_nr, mem->add_shared(mem, shared, NULL); lib->credmgr->add_local_set(lib->credmgr, &mem->set); - /* unlock, as the builder might ask for a secret */ - this->lock->unlock(this->lock); key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, key_type, BUILD_FROM_FILE, path, BUILD_END); - this->lock->write_lock(this->lock); lib->credmgr->remove_local_set(lib->credmgr, &mem->set); mem->destroy(mem); @@ -1055,7 +727,7 @@ static bool load_private(private_stroke_cred_t *this, chunk_t line, int line_nr, { DBG1(DBG_CFG, " loaded %N private key from '%s'", key_type_names, key->get_type(key), path); - this->private->insert_last(this->private, key); + this->creds->add_key(this->creds, key); } else { @@ -1070,7 +742,8 @@ static bool load_private(private_stroke_cred_t *this, chunk_t line, int line_nr, static bool load_shared(private_stroke_cred_t *this, chunk_t line, int line_nr, shared_key_type_t type, chunk_t ids) { - stroke_shared_key_t *shared_key; + shared_key_t *shared_key; + linked_list_t *owners; chunk_t secret = chunk_empty; bool any = TRUE; @@ -1080,12 +753,12 @@ static bool load_shared(private_stroke_cred_t *this, chunk_t line, int line_nr, DBG1(DBG_CFG, "line %d: malformed secret: %s", line_nr, ugh); return FALSE; } - shared_key = stroke_shared_key_create(type, secret); + shared_key = shared_key_create(type, secret); DBG1(DBG_CFG, " loaded %N secret for %s", shared_key_type_names, type, ids.len > 0 ? (char*)ids.ptr : "%any"); DBG4(DBG_CFG, " secret: %#B", &secret); - this->shared->insert_last(this->shared, shared_key); + owners = linked_list_create(); while (ids.len > 0) { chunk_t id; @@ -1111,14 +784,15 @@ static bool load_shared(private_stroke_cred_t *this, chunk_t line, int line_nr, continue; } - shared_key->add_owner(shared_key, peer_id); + owners->insert_last(owners, peer_id); any = FALSE; } if (any) { - shared_key->add_owner(shared_key, + owners->insert_last(owners, identification_create_from_encoding(ID_ANY, chunk_empty)); } + this->creds->add_shared_list(this->creds, shared_key, owners); return TRUE; } @@ -1130,8 +804,6 @@ static void load_secrets(private_stroke_cred_t *this, char *file, int level, { int line_nr = 0, fd; chunk_t src, line; - private_key_t *private; - shared_key_t *shared; struct stat sb; void *addr; @@ -1160,20 +832,8 @@ static void load_secrets(private_stroke_cred_t *this, char *file, int level, src = chunk_create(addr, sb.st_size); if (level == 0) - { - this->lock->write_lock(this->lock); - - /* flush secrets on non-recursive invocation */ - while (this->shared->remove_last(this->shared, - (void**)&shared) == SUCCESS) - { - shared->destroy(shared); - } - while (this->private->remove_last(this->private, - (void**)&private) == SUCCESS) - { - private->destroy(private); - } + { /* flush secrets on non-recursive invocation */ + this->creds->clear_secrets(this->creds); } while (fetchline(&src, &line)) @@ -1234,7 +894,6 @@ static void load_secrets(private_stroke_cred_t *this, char *file, int level, if (glob(pattern, GLOB_ERR, NULL, &buf) != 0) { DBG1(DBG_CFG, "expanding file expression '%s' failed", pattern); - globfree(&buf); } else { @@ -1302,10 +961,6 @@ static void load_secrets(private_stroke_cred_t *this, char *file, int level, break; } } - if (level == 0) - { - this->lock->unlock(this->lock); - } munmap(addr, sb.st_size); close(fd); } @@ -1384,10 +1039,8 @@ static void reread(private_stroke_cred_t *this, stroke_msg_t *msg, FILE *prompt) */ static void destroy(private_stroke_cred_t *this) { - this->certs->destroy_offset(this->certs, offsetof(certificate_t, destroy)); - this->shared->destroy_offset(this->shared, offsetof(shared_key_t, destroy)); - this->private->destroy_offset(this->private, offsetof(private_key_t, destroy)); - this->lock->destroy(this->lock); + lib->credmgr->remove_set(lib->credmgr, &this->creds->set); + this->creds->destroy(this->creds); free(this); } @@ -1398,9 +1051,9 @@ stroke_cred_t *stroke_cred_create() { private_stroke_cred_t *this = malloc_thing(private_stroke_cred_t); - this->public.set.create_private_enumerator = (void*)create_private_enumerator; - this->public.set.create_cert_enumerator = (void*)create_cert_enumerator; - this->public.set.create_shared_enumerator = (void*)create_shared_enumerator; + this->public.set.create_private_enumerator = (void*)return_null; + this->public.set.create_cert_enumerator = (void*)return_null; + this->public.set.create_shared_enumerator = (void*)return_null; this->public.set.create_cdp_enumerator = (void*)return_null; this->public.set.cache_cert = (void*)cache_cert; this->public.reread = (void(*)(stroke_cred_t*, stroke_msg_t *msg, FILE*))reread; @@ -1409,10 +1062,8 @@ stroke_cred_t *stroke_cred_create() this->public.cachecrl = (void(*)(stroke_cred_t*, bool enabled))cachecrl; this->public.destroy = (void(*)(stroke_cred_t*))destroy; - this->certs = linked_list_create(); - this->shared = linked_list_create(); - this->private = linked_list_create(); - this->lock = rwlock_create(RWLOCK_TYPE_DEFAULT); + this->creds = mem_cred_create(); + lib->credmgr->add_set(lib->credmgr, &this->creds->set); load_certs(this); load_secrets(this, SECRETS_FILE, 0, NULL); diff --git a/src/libcharon/plugins/stroke/stroke_list.c b/src/libcharon/plugins/stroke/stroke_list.c index 86deea490..36311f092 100644 --- a/src/libcharon/plugins/stroke/stroke_list.c +++ b/src/libcharon/plugins/stroke/stroke_list.c @@ -388,10 +388,8 @@ static void log_auth_cfgs(FILE *out, peer_cfg_t *peer_cfg, bool local) enumerator->destroy(enumerator); } -/** - * Implementation of stroke_list_t.status. - */ -static void status(private_stroke_list_t *this, stroke_msg_t *msg, FILE *out, bool all) +METHOD(stroke_list_t, status, void, + private_stroke_list_t *this, stroke_msg_t *msg, FILE *out, bool all) { enumerator_t *enumerator, *children; ike_cfg_t *ike_cfg; @@ -756,7 +754,7 @@ static void stroke_list_certs(linked_list_t *list, char *label, enumerator_t *enumerator; identification_t *altName; bool first_altName = TRUE; - int pathlen; + u_int pathlen; chunk_t serial, authkey; time_t notBefore, notAfter; public_key_t *public; @@ -836,10 +834,10 @@ static void stroke_list_certs(linked_list_t *list, char *label, } /* list optional pathLenConstraint */ - pathlen = x509->get_pathLenConstraint(x509); - if (pathlen != X509_NO_PATH_LEN_CONSTRAINT) + pathlen = x509->get_constraint(x509, X509_PATH_LEN); + if (pathlen != X509_NO_CONSTRAINT) { - fprintf(out, " pathlen: %d\n", pathlen); + fprintf(out, " pathlen: %u\n", pathlen); } /* list optional ipAddrBlocks */ @@ -979,6 +977,10 @@ static void stroke_list_crls(linked_list_t *list, bool utc, FILE *out) { fprintf(out, " serial: %#B\n", &chunk); } + if (crl->is_delta_crl(crl, &chunk)) + { + fprintf(out, " delta for: %#B\n", &chunk); + } /* count the number of revoked certificates */ { @@ -1060,6 +1062,25 @@ static void stroke_list_ocsp(linked_list_t* list, bool utc, FILE *out) } /** + * Print the name of an algorithm plus the name of the plugin that registered it + */ +static void print_alg(FILE *out, int *len, enum_name_t *alg_names, int alg_type, + const char *plugin_name) +{ + char alg_name[BUF_LEN]; + int alg_name_len; + + alg_name_len = sprintf(alg_name, " %N[%s]", alg_names, alg_type, plugin_name); + if (*len + alg_name_len > CRYPTO_MAX_ALG_LINE) + { + fprintf(out, "\n "); + *len = 13; + } + fprintf(out, "%s", alg_name); + *len += alg_name_len; +} + +/** * List of registered cryptographical algorithms */ static void list_algs(FILE *out) @@ -1070,58 +1091,73 @@ static void list_algs(FILE *out) hash_algorithm_t hash; pseudo_random_function_t prf; diffie_hellman_group_t group; + rng_quality_t quality; + const char *plugin_name; + int len; fprintf(out, "\n"); fprintf(out, "List of registered IKEv2 Algorithms:\n"); - fprintf(out, "\n encryption: "); + fprintf(out, "\n encryption:"); + len = 13; enumerator = lib->crypto->create_crypter_enumerator(lib->crypto); - while (enumerator->enumerate(enumerator, &encryption)) + while (enumerator->enumerate(enumerator, &encryption, &plugin_name)) { - fprintf(out, "%N ", encryption_algorithm_names, encryption); + print_alg(out, &len, encryption_algorithm_names, encryption, plugin_name); } enumerator->destroy(enumerator); - fprintf(out, "\n integrity: "); + fprintf(out, "\n integrity: "); + len = 13; enumerator = lib->crypto->create_signer_enumerator(lib->crypto); - while (enumerator->enumerate(enumerator, &integrity)) + while (enumerator->enumerate(enumerator, &integrity, &plugin_name)) { - fprintf(out, "%N ", integrity_algorithm_names, integrity); + print_alg(out, &len, integrity_algorithm_names, integrity, plugin_name); } enumerator->destroy(enumerator); - fprintf(out, "\n aead: "); + fprintf(out, "\n aead: "); + len = 13; enumerator = lib->crypto->create_aead_enumerator(lib->crypto); - while (enumerator->enumerate(enumerator, &encryption)) + while (enumerator->enumerate(enumerator, &encryption, &plugin_name)) { - fprintf(out, "%N ", encryption_algorithm_names, encryption); + print_alg(out, &len, encryption_algorithm_names, encryption, plugin_name); } enumerator->destroy(enumerator); - fprintf(out, "\n hasher: "); + fprintf(out, "\n hasher: "); + len = 13; enumerator = lib->crypto->create_hasher_enumerator(lib->crypto); - while (enumerator->enumerate(enumerator, &hash)) + while (enumerator->enumerate(enumerator, &hash, &plugin_name)) { - fprintf(out, "%N ", hash_algorithm_names, hash); + print_alg(out, &len, hash_algorithm_names, hash, plugin_name); } enumerator->destroy(enumerator); - fprintf(out, "\n prf: "); + fprintf(out, "\n prf: "); + len = 13; enumerator = lib->crypto->create_prf_enumerator(lib->crypto); - while (enumerator->enumerate(enumerator, &prf)) + while (enumerator->enumerate(enumerator, &prf, &plugin_name)) { - fprintf(out, "%N ", pseudo_random_function_names, prf); + print_alg(out, &len, pseudo_random_function_names, prf, plugin_name); } enumerator->destroy(enumerator); - fprintf(out, "\n dh-group: "); + fprintf(out, "\n dh-group: "); + len = 13; enumerator = lib->crypto->create_dh_enumerator(lib->crypto); - while (enumerator->enumerate(enumerator, &group)) + while (enumerator->enumerate(enumerator, &group, &plugin_name)) { - fprintf(out, "%N ", diffie_hellman_group_names, group); + print_alg(out, &len, diffie_hellman_group_names, group, plugin_name); + } + enumerator->destroy(enumerator); + fprintf(out, "\n random-gen:"); + len = 13; + enumerator = lib->crypto->create_rng_enumerator(lib->crypto); + while (enumerator->enumerate(enumerator, &quality, &plugin_name)) + { + print_alg(out, &len, rng_quality_names, quality, plugin_name); } enumerator->destroy(enumerator); fprintf(out, "\n"); } -/** - * Implementation of stroke_list_t.list. - */ -static void list(private_stroke_list_t *this, stroke_msg_t *msg, FILE *out) +METHOD(stroke_list_t, list, void, + private_stroke_list_t *this, stroke_msg_t *msg, FILE *out) { linked_list_t *cert_list = NULL; @@ -1224,10 +1260,8 @@ static void pool_leases(private_stroke_list_t *this, FILE *out, char *pool, } } -/** - * Implementation of stroke_list_t.leases - */ -static void leases(private_stroke_list_t *this, stroke_msg_t *msg, FILE *out) +METHOD(stroke_list_t, leases, void, + private_stroke_list_t *this, stroke_msg_t *msg, FILE *out) { enumerator_t *enumerator; u_int size, offline, online; @@ -1264,10 +1298,8 @@ static void leases(private_stroke_list_t *this, stroke_msg_t *msg, FILE *out) DESTROY_IF(address); } -/** - * Implementation of stroke_list_t.destroy - */ -static void destroy(private_stroke_list_t *this) +METHOD(stroke_list_t, destroy, void, + private_stroke_list_t *this) { free(this); } @@ -1277,15 +1309,19 @@ static void destroy(private_stroke_list_t *this) */ stroke_list_t *stroke_list_create(stroke_attribute_t *attribute) { - private_stroke_list_t *this = malloc_thing(private_stroke_list_t); - - this->public.list = (void(*)(stroke_list_t*, stroke_msg_t *msg, FILE *out))list; - this->public.status = (void(*)(stroke_list_t*, stroke_msg_t *msg, FILE *out,bool))status; - this->public.leases = (void(*)(stroke_list_t*, stroke_msg_t *msg, FILE *out))leases; - this->public.destroy = (void(*)(stroke_list_t*))destroy; - - this->uptime = time_monotonic(NULL); - this->attribute = attribute; + private_stroke_list_t *this; + + INIT(this, + .public = { + + .list = _list, + .status = _status, + .leases = _leases, + .destroy = _destroy, + }, + .uptime = time_monotonic(NULL), + .attribute = attribute, + ); return &this->public; } diff --git a/src/libcharon/plugins/stroke/stroke_plugin.c b/src/libcharon/plugins/stroke/stroke_plugin.c index 4361e5050..2e83d0d28 100644 --- a/src/libcharon/plugins/stroke/stroke_plugin.c +++ b/src/libcharon/plugins/stroke/stroke_plugin.c @@ -36,10 +36,8 @@ struct private_stroke_plugin_t { stroke_socket_t *socket; }; -/** - * Implementation of stroke_plugin_t.destroy - */ -static void destroy(private_stroke_plugin_t *this) +METHOD(plugin_t, destroy, void, + private_stroke_plugin_t *this) { this->socket->destroy(this->socket); free(this); @@ -50,11 +48,17 @@ static void destroy(private_stroke_plugin_t *this) */ plugin_t *stroke_plugin_create() { - private_stroke_plugin_t *this = malloc_thing(private_stroke_plugin_t); + private_stroke_plugin_t *this; - this->public.plugin.destroy = (void(*)(plugin_t*))destroy; + INIT(this, + .public = { + .plugin = { + .destroy = _destroy, + }, + }, + .socket = stroke_socket_create(), + ); - this->socket = stroke_socket_create(); if (this->socket == NULL) { free(this); diff --git a/src/libcharon/plugins/stroke/stroke_shared_key.c b/src/libcharon/plugins/stroke/stroke_shared_key.c deleted file mode 100644 index 4f716e83a..000000000 --- a/src/libcharon/plugins/stroke/stroke_shared_key.c +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (C) 2008 Martin Willi - * 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 "stroke_shared_key.h" - -#include <utils/linked_list.h> - -typedef struct private_stroke_shared_key_t private_stroke_shared_key_t; - -/** - * private data of shared_key - */ -struct private_stroke_shared_key_t { - - /** - * implements shared_key_t - */ - stroke_shared_key_t public; - - /** - * type of this key - */ - shared_key_type_t type; - - /** - * data of the key - */ - chunk_t key; - - /** - * list of key owners, as identification_t - */ - linked_list_t *owners; - - /** - * reference counter - */ - refcount_t ref; -}; - -/** - * Implementation of shared_key_t.get_type. - */ -static shared_key_type_t get_type(private_stroke_shared_key_t *this) -{ - return this->type; -} - -/** - * Implementation of shared_key_t.get_ref. - */ -static private_stroke_shared_key_t* get_ref(private_stroke_shared_key_t *this) -{ - ref_get(&this->ref); - return this; -} - -/** - * Implementation of shared_key_t.get_key. - */ -static chunk_t get_key(private_stroke_shared_key_t *this) -{ - return this->key; -} - -/** - * Implementation of stroke_shared_key_t.has_owner. - */ -static id_match_t has_owner(private_stroke_shared_key_t *this, identification_t *owner) -{ - enumerator_t *enumerator; - id_match_t match, best = ID_MATCH_NONE; - identification_t *current; - - enumerator = this->owners->create_enumerator(this->owners); - while (enumerator->enumerate(enumerator, ¤t)) - { - match = owner->matches(owner, current); - if (match > best) - { - best = match; - } - } - enumerator->destroy(enumerator); - return best; -} -/** - * Implementation of stroke_shared_key_t.add_owner. - */ -static void add_owner(private_stroke_shared_key_t *this, identification_t *owner) -{ - this->owners->insert_last(this->owners, owner); -} - -/** - * Implementation of stroke_shared_key_t.destroy - */ -static void destroy(private_stroke_shared_key_t *this) -{ - if (ref_put(&this->ref)) - { - this->owners->destroy_offset(this->owners, offsetof(identification_t, destroy)); - chunk_free(&this->key); - free(this); - } -} - -/** - * create a shared key - */ -stroke_shared_key_t *stroke_shared_key_create(shared_key_type_t type, chunk_t key) -{ - private_stroke_shared_key_t *this = malloc_thing(private_stroke_shared_key_t); - - this->public.shared.get_type = (shared_key_type_t(*)(shared_key_t*))get_type; - this->public.shared.get_key = (chunk_t(*)(shared_key_t*))get_key; - this->public.shared.get_ref = (shared_key_t*(*)(shared_key_t*))get_ref; - this->public.shared.destroy = (void(*)(shared_key_t*))destroy; - this->public.add_owner = (void(*)(stroke_shared_key_t*, identification_t *owner))add_owner; - this->public.has_owner = (id_match_t(*)(stroke_shared_key_t*, identification_t *owner))has_owner; - - this->owners = linked_list_create(); - this->type = type; - this->key = key; - this->ref = 1; - - return &this->public; -} diff --git a/src/libcharon/plugins/stroke/stroke_shared_key.h b/src/libcharon/plugins/stroke/stroke_shared_key.h deleted file mode 100644 index 05ad55083..000000000 --- a/src/libcharon/plugins/stroke/stroke_shared_key.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2008 Martin Willi - * 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. - */ - -/** - * @defgroup stroke_shared_key stroke_shared_key - * @{ @ingroup stroke - */ - -#ifndef STROKE_SHARED_KEY_H_ -#define STROKE_SHARED_KEY_H_ - -#include <utils/identification.h> -#include <credentials/keys/shared_key.h> - -typedef struct stroke_shared_key_t stroke_shared_key_t; - -/** - * Shared key implementation for keys read from ipsec.secrets - */ -struct stroke_shared_key_t { - - /** - * Implements the shared_key_t interface. - */ - shared_key_t shared; - - /** - * Add an owner to the key. - * - * @param owner owner to add - */ - void (*add_owner)(stroke_shared_key_t *this, identification_t *owner); - - /** - * Check if a key has a specific owner. - * - * @param owner owner to check - * @return best match found - */ - id_match_t (*has_owner)(stroke_shared_key_t *this, identification_t *owner); -}; - -/** - * Create a stroke_shared_key instance. - */ -stroke_shared_key_t *stroke_shared_key_create(shared_key_type_t type, chunk_t key); - -#endif /** STROKE_SHARED_KEY_H_ @}*/ diff --git a/src/libcharon/plugins/stroke/stroke_socket.c b/src/libcharon/plugins/stroke/stroke_socket.c index 0a5110fd3..18e77905d 100644 --- a/src/libcharon/plugins/stroke/stroke_socket.c +++ b/src/libcharon/plugins/stroke/stroke_socket.c @@ -151,6 +151,7 @@ static void pop_end(stroke_msg_t *msg, const char* label, stroke_end_t *end) pop_string(msg, &end->ca); pop_string(msg, &end->ca2); pop_string(msg, &end->groups); + pop_string(msg, &end->cert_policy); pop_string(msg, &end->updown); DBG2(DBG_CFG, " %s=%s", label, end->address); @@ -246,6 +247,17 @@ static void stroke_terminate_srcip(private_stroke_socket_t *this, } /** + * rekey a connection by name/id + */ +static void stroke_rekey(private_stroke_socket_t *this, stroke_msg_t *msg, FILE *out) +{ + pop_string(msg, &msg->terminate.name); + DBG1(DBG_CFG, "received stroke: rekey '%s'", msg->rekey.name); + + this->control->rekey(this->control, msg, out); +} + +/** * route a policy (install SPD entries) */ static void stroke_route(private_stroke_socket_t *this, stroke_msg_t *msg, FILE *out) @@ -348,6 +360,14 @@ static void stroke_purge(private_stroke_socket_t *this, { lib->credmgr->flush_cache(lib->credmgr, CERT_X509_OCSP_RESPONSE); } + if (msg->purge.flags & PURGE_CRLS) + { + lib->credmgr->flush_cache(lib->credmgr, CERT_X509_CRL); + } + if (msg->purge.flags & PURGE_CERTS) + { + lib->credmgr->flush_cache(lib->credmgr, CERT_X509); + } if (msg->purge.flags & PURGE_IKE) { this->control->purge_ike(this->control, msg, out); @@ -510,6 +530,9 @@ static job_requeue_t process(stroke_job_context_t *ctx) case STR_TERMINATE_SRCIP: stroke_terminate_srcip(this, msg, out); break; + case STR_REKEY: + stroke_rekey(this, msg, out); + break; case STR_STATUS: stroke_status(this, msg, out, FALSE); break; diff --git a/src/libcharon/plugins/tnc_imc/Makefile.am b/src/libcharon/plugins/tnc_imc/Makefile.am index ca8869460..2c551813e 100644 --- a/src/libcharon/plugins/tnc_imc/Makefile.am +++ b/src/libcharon/plugins/tnc_imc/Makefile.am @@ -1,11 +1,9 @@ INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ - -I$(top_srcdir)/src/libcharon `xml2-config --cflags` + -I$(top_srcdir)/src/libcharon AM_CFLAGS = -rdynamic -libstrongswan_tnc_imc_la_LIBADD = -ltnc - if MONOLITHIC noinst_LTLIBRARIES = libstrongswan-tnc-imc.la else @@ -13,7 +11,8 @@ plugin_LTLIBRARIES = libstrongswan-tnc-imc.la endif libstrongswan_tnc_imc_la_SOURCES = \ - tnc_imc_plugin.h tnc_imc_plugin.c + tnc_imc_plugin.h tnc_imc_plugin.c tnc_imc.h tnc_imc.c \ + tnc_imc_manager.h tnc_imc_manager.c tnc_imc_bind_function.c libstrongswan_tnc_imc_la_LDFLAGS = -module -avoid-version diff --git a/src/libcharon/plugins/tnc_imc/Makefile.in b/src/libcharon/plugins/tnc_imc/Makefile.in index 9a8794e93..dc44408ff 100644 --- a/src/libcharon/plugins/tnc_imc/Makefile.in +++ b/src/libcharon/plugins/tnc_imc/Makefile.in @@ -74,8 +74,9 @@ am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__installdirs = "$(DESTDIR)$(plugindir)" LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES) -libstrongswan_tnc_imc_la_DEPENDENCIES = -am_libstrongswan_tnc_imc_la_OBJECTS = tnc_imc_plugin.lo +libstrongswan_tnc_imc_la_LIBADD = +am_libstrongswan_tnc_imc_la_OBJECTS = tnc_imc_plugin.lo tnc_imc.lo \ + tnc_imc_manager.lo tnc_imc_bind_function.lo libstrongswan_tnc_imc_la_OBJECTS = \ $(am_libstrongswan_tnc_imc_la_OBJECTS) libstrongswan_tnc_imc_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ @@ -221,9 +222,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -262,6 +261,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ @@ -273,14 +274,14 @@ urandom_device = @urandom_device@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ - -I$(top_srcdir)/src/libcharon `xml2-config --cflags` + -I$(top_srcdir)/src/libcharon AM_CFLAGS = -rdynamic -libstrongswan_tnc_imc_la_LIBADD = -ltnc @MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-tnc-imc.la @MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-tnc-imc.la libstrongswan_tnc_imc_la_SOURCES = \ - tnc_imc_plugin.h tnc_imc_plugin.c + tnc_imc_plugin.h tnc_imc_plugin.c tnc_imc.h tnc_imc.c \ + tnc_imc_manager.h tnc_imc_manager.c tnc_imc_bind_function.c libstrongswan_tnc_imc_la_LDFLAGS = -module -avoid-version all: all-am @@ -366,6 +367,9 @@ mostlyclean-compile: distclean-compile: -rm -f *.tab.c +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnc_imc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnc_imc_bind_function.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnc_imc_manager.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnc_imc_plugin.Plo@am__quote@ .c.o: diff --git a/src/libcharon/plugins/tnc_imc/tnc_imc.c b/src/libcharon/plugins/tnc_imc/tnc_imc.c new file mode 100644 index 000000000..174084436 --- /dev/null +++ b/src/libcharon/plugins/tnc_imc/tnc_imc.c @@ -0,0 +1,207 @@ +/* + * Copyright (C) 2006 Mike McCauley + * Copyright (C) 2010 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 "tnc_imc.h" + +#include <dlfcn.h> + +#include <debug.h> +#include <library.h> + +typedef struct private_tnc_imc_t private_tnc_imc_t; + +/** + * Private data of an imv_t object. + */ +struct private_tnc_imc_t { + + /** + * Public members of imc_t. + */ + imc_t public; + + /** + * Path of loaded IMC + */ + char *path; + + /** + * Name of loaded IMC + */ + char *name; + + /** + * Handle of loaded IMC + */ + void *handle; + + /** + * ID of loaded IMC + */ + TNC_IMCID id; + + /** + * List of message types supported by IMC + */ + TNC_MessageTypeList supported_types; + + /** + * Number of supported message types + */ + TNC_UInt32 type_count; +}; + +METHOD(imc_t, set_id, void, + private_tnc_imc_t *this, TNC_IMCID id) +{ + this->id = id; +} + +METHOD(imc_t, get_id, TNC_IMCID, + private_tnc_imc_t *this) +{ + return this->id; +} + +METHOD(imc_t, get_name, char*, + private_tnc_imc_t *this) +{ + return this->name; +} + +METHOD(imc_t, set_message_types, void, + private_tnc_imc_t *this, TNC_MessageTypeList supported_types, + TNC_UInt32 type_count) +{ + /* Free an existing MessageType list */ + free(this->supported_types); + this->supported_types = NULL; + + /* Store the new MessageType list */ + this->type_count = type_count; + if (type_count && supported_types) + { + size_t size = type_count * sizeof(TNC_MessageType); + + this->supported_types = malloc(size); + memcpy(this->supported_types, supported_types, size); + } + DBG2(DBG_TNC, "IMC %u supports %u message types", this->id, type_count); +} + +METHOD(imc_t, type_supported, bool, + private_tnc_imc_t *this, TNC_MessageType message_type) +{ + TNC_VendorID msg_vid, vid; + TNC_MessageSubtype msg_subtype, subtype; + int i; + + msg_vid = (message_type >> 8) & TNC_VENDORID_ANY; + msg_subtype = message_type & TNC_SUBTYPE_ANY; + + for (i = 0; i < this->type_count; i++) + { + vid = (this->supported_types[i] >> 8) & TNC_VENDORID_ANY; + subtype = this->supported_types[i] & TNC_SUBTYPE_ANY; + + if (this->supported_types[i] == message_type + || (subtype == TNC_SUBTYPE_ANY + && (msg_vid == vid || vid == TNC_VENDORID_ANY)) + || (vid == TNC_VENDORID_ANY + && (msg_subtype == subtype || subtype == TNC_SUBTYPE_ANY))) + { + return TRUE; + } + } + return FALSE; +} + +METHOD(imc_t, destroy, void, + private_tnc_imc_t *this) +{ + dlclose(this->handle); + free(this->supported_types); + free(this->name); + free(this->path); + free(this); +} + +/** + * Described in header. + */ +imc_t* tnc_imc_create(char *name, char *path) +{ + private_tnc_imc_t *this; + + INIT(this, + .public = { + .set_id = _set_id, + .get_id = _get_id, + .get_name = _get_name, + .set_message_types = _set_message_types, + .type_supported = _type_supported, + .destroy = _destroy, + }, + .name = name, + .path = path, + ); + + this->handle = dlopen(path, RTLD_LAZY); + if (!this->handle) + { + DBG1(DBG_TNC, "IMC \"%s\" failed to load: %s", name, dlerror()); + free(this); + return NULL; + } + + this->public.initialize = dlsym(this->handle, "TNC_IMC_Initialize"); + if (!this->public.initialize) + { + DBG1(DBG_TNC, "could not resolve TNC_IMC_Initialize in %s: %s\n", + path, dlerror()); + dlclose(this->handle); + free(this); + return NULL; + } + this->public.notify_connection_change = + dlsym(this->handle, "TNC_IMC_NotifyConnectionChange"); + this->public.begin_handshake = dlsym(this->handle, "TNC_IMC_BeginHandshake"); + if (!this->public.begin_handshake) + { + DBG1(DBG_TNC, "could not resolve TNC_IMC_BeginHandshake in %s: %s\n", + path, dlerror()); + dlclose(this->handle); + free(this); + return NULL; + } + this->public.receive_message = + dlsym(this->handle, "TNC_IMC_ReceiveMessage"); + this->public.batch_ending = + dlsym(this->handle, "TNC_IMC_BatchEnding"); + this->public.terminate = + dlsym(this->handle, "TNC_IMC_Terminate"); + this->public.provide_bind_function = + dlsym(this->handle, "TNC_IMC_ProvideBindFunction"); + if (!this->public.provide_bind_function) + { + DBG1(DBG_TNC, "could not resolve TNC_IMC_ProvideBindFunction in %s: %s\n", + path, dlerror()); + dlclose(this->handle); + free(this); + return NULL; + } + + return &this->public; +} diff --git a/src/libcharon/plugins/tnc_imc/tnc_imc.h b/src/libcharon/plugins/tnc_imc/tnc_imc.h new file mode 100644 index 000000000..10a67f90b --- /dev/null +++ b/src/libcharon/plugins/tnc_imc/tnc_imc.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2010 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. + */ + +/** + * + * @defgroup tnc_imc_t tnc_imc + * @{ @ingroup tnc_imc + */ + +#ifndef TNC_IMC_H_ +#define TNC_IMC_H_ + +#include <tnc/imc/imc.h> + +/** + * Create an Integrity Measurement Collector. + * + * @param name name of the IMC + * @param filename path to the dynamic IMC library + * @return instance of the imc_t interface + */ +imc_t* tnc_imc_create(char *name, char *filename); + +#endif /** TNC_IMC_H_ @}*/ diff --git a/src/libcharon/plugins/tnc_imc/tnc_imc_bind_function.c b/src/libcharon/plugins/tnc_imc/tnc_imc_bind_function.c new file mode 100644 index 000000000..e18f1b006 --- /dev/null +++ b/src/libcharon/plugins/tnc_imc/tnc_imc_bind_function.c @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2006 Mike McCauley + * Copyright (C) 2010 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 "tnc_imc.h" + +#include <debug.h> +#include <daemon.h> + +#define TNC_IMVID_ANY 0xffff + +/** + * Called by the IMC to inform a TNCC about the set of message types the IMC + * is able to receive + */ +TNC_Result TNC_TNCC_ReportMessageTypes(TNC_IMCID imc_id, + TNC_MessageTypeList supported_types, + TNC_UInt32 type_count) +{ + return charon->imcs->set_message_types(charon->imcs, imc_id, + supported_types, type_count); +} + +/** + * Called by the IMC to ask a TNCC to retry an Integrity Check Handshake + */ +TNC_Result TNC_TNCC_RequestHandshakeRetry(TNC_IMCID imc_id, + TNC_ConnectionID connection_id, + TNC_RetryReason reason) +{ + return charon->tnccs->request_handshake_retry(charon->tnccs, TRUE, imc_id, + connection_id, reason); +} + +/** + * Called by the IMC when an IMC-IMV message is to be sent + */ +TNC_Result TNC_TNCC_SendMessage(TNC_IMCID imc_id, + TNC_ConnectionID connection_id, + TNC_BufferReference msg, + TNC_UInt32 msg_len, + TNC_MessageType msg_type) +{ + return charon->tnccs->send_message(charon->tnccs, imc_id, TNC_IMVID_ANY, + connection_id, msg, msg_len, msg_type); +} + +/** + * Called by the IMC when it needs a function pointer + */ +TNC_Result TNC_TNCC_BindFunction(TNC_IMCID id, + char *function_name, + void **function_pointer) +{ + if (streq(function_name, "TNC_TNCC_ReportMessageTypes")) + { + *function_pointer = (void*)TNC_TNCC_ReportMessageTypes; + } + else if (streq(function_name, "TNC_TNCC_RequestHandshakeRetry")) + { + *function_pointer = (void*)TNC_TNCC_RequestHandshakeRetry; + } + else if (streq(function_name, "TNC_TNCC_SendMessage")) + { + *function_pointer = (void*)TNC_TNCC_SendMessage; + } + else + { + return TNC_RESULT_INVALID_PARAMETER; + } + return TNC_RESULT_SUCCESS; +} diff --git a/src/libcharon/plugins/tnc_imc/tnc_imc_manager.c b/src/libcharon/plugins/tnc_imc/tnc_imc_manager.c new file mode 100644 index 000000000..aa20534f5 --- /dev/null +++ b/src/libcharon/plugins/tnc_imc/tnc_imc_manager.c @@ -0,0 +1,238 @@ +/* + * Copyright (C) 2006 Mike McCauley + * Copyright (C) 2010 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 "tnc_imc_manager.h" + +#include <tnc/imc/imc_manager.h> +#include <tnc/tncifimc.h> + +#include <debug.h> +#include <library.h> +#include <utils/linked_list.h> + +typedef struct private_tnc_imc_manager_t private_tnc_imc_manager_t; + +/** + * Private data of an imc_manager_t object. + */ +struct private_tnc_imc_manager_t { + + /** + * Public members of imc_manager_t. + */ + imc_manager_t public; + + /** + * Linked list of IMCs + */ + linked_list_t *imcs; + + /** + * Next IMC ID to be assigned + */ + TNC_IMCID next_imc_id; +}; + +METHOD(imc_manager_t, add, bool, + private_tnc_imc_manager_t *this, imc_t *imc) +{ + TNC_Version version; + + /* Initialize the module */ + imc->set_id(imc, this->next_imc_id); + if (imc->initialize(imc->get_id(imc), TNC_IFIMC_VERSION_1, + TNC_IFIMC_VERSION_1, &version) != TNC_RESULT_SUCCESS) + { + DBG1(DBG_TNC, "IMC \"%s\" failed to initialize", imc->get_name(imc)); + return FALSE; + } + this->imcs->insert_last(this->imcs, imc); + this->next_imc_id++; + + if (imc->provide_bind_function(imc->get_id(imc), TNC_TNCC_BindFunction) + != TNC_RESULT_SUCCESS) + { + DBG1(DBG_TNC, "IMC \"%s\" failed to obtain bind function", + imc->get_name(imc)); + this->imcs->remove_last(this->imcs, (void**)&imc); + return FALSE; + } + + return TRUE; +} + +METHOD(imc_manager_t, remove_, imc_t*, + private_tnc_imc_manager_t *this, TNC_IMCID id) +{ + enumerator_t *enumerator; + imc_t *imc; + + enumerator = this->imcs->create_enumerator(this->imcs); + while (enumerator->enumerate(enumerator, &imc)) + { + if (id == imc->get_id(imc)) + { + this->imcs->remove_at(this->imcs, enumerator); + return imc; + } + } + enumerator->destroy(enumerator); + return NULL; +} + +METHOD(imc_manager_t, get_preferred_language, char*, + private_tnc_imc_manager_t *this) +{ + return lib->settings->get_str(lib->settings, + "charon.plugins.tnc-imc.preferred_language", "en"); +} + +METHOD(imc_manager_t, notify_connection_change, void, + private_tnc_imc_manager_t *this, TNC_ConnectionID id, + TNC_ConnectionState state) +{ + enumerator_t *enumerator; + imc_t *imc; + + enumerator = this->imcs->create_enumerator(this->imcs); + while (enumerator->enumerate(enumerator, &imc)) + { + if (imc->notify_connection_change) + { + imc->notify_connection_change(imc->get_id(imc), id, state); + } + } + enumerator->destroy(enumerator); +} + +METHOD(imc_manager_t, begin_handshake, void, + private_tnc_imc_manager_t *this, TNC_ConnectionID id) +{ + enumerator_t *enumerator; + imc_t *imc; + + enumerator = this->imcs->create_enumerator(this->imcs); + while (enumerator->enumerate(enumerator, &imc)) + { + imc->begin_handshake(imc->get_id(imc), id); + } + enumerator->destroy(enumerator); +} + +METHOD(imc_manager_t, set_message_types, TNC_Result, + private_tnc_imc_manager_t *this, TNC_IMCID id, + TNC_MessageTypeList supported_types, + TNC_UInt32 type_count) +{ + enumerator_t *enumerator; + imc_t *imc; + TNC_Result result = TNC_RESULT_FATAL; + + enumerator = this->imcs->create_enumerator(this->imcs); + while (enumerator->enumerate(enumerator, &imc)) + { + if (id == imc->get_id(imc)) + { + imc->set_message_types(imc, supported_types, type_count); + result = TNC_RESULT_SUCCESS; + break; + } + } + enumerator->destroy(enumerator); + return result; +} + +METHOD(imc_manager_t, receive_message, void, + private_tnc_imc_manager_t *this, TNC_ConnectionID connection_id, + TNC_BufferReference message, + TNC_UInt32 message_len, + TNC_MessageType message_type) +{ + enumerator_t *enumerator; + imc_t *imc; + + enumerator = this->imcs->create_enumerator(this->imcs); + while (enumerator->enumerate(enumerator, &imc)) + { + if (imc->receive_message && imc->type_supported(imc, message_type)) + { + imc->receive_message(imc->get_id(imc), connection_id, + message, message_len, message_type); + } + } + enumerator->destroy(enumerator); +} + +METHOD(imc_manager_t, batch_ending, void, + private_tnc_imc_manager_t *this, TNC_ConnectionID id) +{ + enumerator_t *enumerator; + imc_t *imc; + + enumerator = this->imcs->create_enumerator(this->imcs); + while (enumerator->enumerate(enumerator, &imc)) + { + if (imc->batch_ending) + { + imc->batch_ending(imc->get_id(imc), id); + } + } + enumerator->destroy(enumerator); +} + +METHOD(imc_manager_t, destroy, void, + private_tnc_imc_manager_t *this) +{ + imc_t *imc; + + while (this->imcs->remove_last(this->imcs, (void**)&imc) == SUCCESS) + { + if (imc->terminate && + imc->terminate(imc->get_id(imc)) != TNC_RESULT_SUCCESS) + { + DBG1(DBG_TNC, "IMC \"%s\" not terminated successfully", + imc->get_name(imc)); + } + imc->destroy(imc); + } + this->imcs->destroy(this->imcs); + free(this); +} + +/** + * Described in header. + */ +imc_manager_t* tnc_imc_manager_create(void) +{ + private_tnc_imc_manager_t *this; + + INIT(this, + .public = { + .add = _add, + .remove = _remove_, /* avoid name conflict with stdio.h */ + .get_preferred_language = _get_preferred_language, + .notify_connection_change = _notify_connection_change, + .begin_handshake = _begin_handshake, + .set_message_types = _set_message_types, + .receive_message = _receive_message, + .batch_ending = _batch_ending, + .destroy = _destroy, + }, + .imcs = linked_list_create(), + .next_imc_id = 1, + ); + + return &this->public; +} diff --git a/src/libcharon/plugins/tnc_imc/tnc_imc_manager.h b/src/libcharon/plugins/tnc_imc/tnc_imc_manager.h new file mode 100644 index 000000000..ed490293b --- /dev/null +++ b/src/libcharon/plugins/tnc_imc/tnc_imc_manager.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2010 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. + */ + +/** + * + * @defgroup tnc_imc_manager tnc_imc_manager + * @{ @ingroup tnc_imc + */ + +#ifndef TNC_IMC_MANAGER_H_ +#define TNC_IMC_MANAGER_H_ + +#include <tnc/imc/imc_manager.h> + +/** + * Create an IMC manager instance. + */ +imc_manager_t *tnc_imc_manager_create(); + +#endif /** TNC_IMC_MANAGER_H_ @}*/ diff --git a/src/libcharon/plugins/tnc_imc/tnc_imc_plugin.c b/src/libcharon/plugins/tnc_imc/tnc_imc_plugin.c index 0ce930ba3..89888040a 100644 --- a/src/libcharon/plugins/tnc_imc/tnc_imc_plugin.c +++ b/src/libcharon/plugins/tnc_imc/tnc_imc_plugin.c @@ -14,15 +14,137 @@ */ #include "tnc_imc_plugin.h" +#include "tnc_imc_manager.h" +#include "tnc_imc.h" -#include <libtnctncc.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/mman.h> +#include <unistd.h> +#include <errno.h> +#include <fcntl.h> #include <daemon.h> +#include <utils/lexparser.h> + +/** + * load IMCs from a configuration file + */ +static bool load_imcs(char *filename) +{ + int fd, line_nr = 0; + chunk_t src, line; + struct stat sb; + void *addr; + + DBG1(DBG_TNC, "loading IMCs from '%s'", filename); + fd = open(filename, O_RDONLY); + if (fd == -1) + { + DBG1(DBG_TNC, "opening configuration file '%s' failed: %s", filename, + strerror(errno)); + return FALSE; + } + if (fstat(fd, &sb) == -1) + { + DBG1(DBG_LIB, "getting file size of '%s' failed: %s", filename, + strerror(errno)); + close(fd); + return FALSE; + } + addr = mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); + if (addr == MAP_FAILED) + { + DBG1(DBG_LIB, "mapping '%s' failed: %s", filename, strerror(errno)); + close(fd); + return FALSE; + } + src = chunk_create(addr, sb.st_size); + + while (fetchline(&src, &line)) + { + char *name, *path; + chunk_t token; + imc_t *imc; + + line_nr++; + + /* skip comments or empty lines */ + if (*line.ptr == '#' || !eat_whitespace(&line)) + { + continue; + } + + /* determine keyword */ + if (!extract_token(&token, ' ', &line)) + { + DBG1(DBG_TNC, "line %d: keyword must be followed by a space", + line_nr); + return FALSE; + } + + /* only interested in IMCs */ + if (!match("IMC", &token)) + { + continue; + } + + /* advance to the IMC name and extract it */ + if (!extract_token(&token, '"', &line) || + !extract_token(&token, '"', &line)) + { + DBG1(DBG_TNC, "line %d: IMC name must be set in double quotes", + line_nr); + return FALSE; + } + + /* copy the IMC name */ + name = malloc(token.len + 1); + memcpy(name, token.ptr, token.len); + name[token.len] = '\0'; + + /* advance to the IMC path and extract it */ + if (!eat_whitespace(&line)) + { + DBG1(DBG_TNC, "line %d: IMC path is missing", line_nr); + free(name); + return FALSE; + } + if (!extract_token(&token, ' ', &line)) + { + token = line; + } + + /* copy the IMC path */ + path = malloc(token.len + 1); + memcpy(path, token.ptr, token.len); + path[token.len] = '\0'; + + /* load and register IMC instance */ + imc = tnc_imc_create(name, path); + if (!imc) + { + free(name); + free(path); + return FALSE; + } + if (!charon->imcs->add(charon->imcs, imc)) + { + imc->destroy(imc); + return FALSE; + } + DBG1(DBG_TNC, "IMC %u \"%s\" loaded from '%s'", imc->get_id(imc), + name, path); + } + munmap(addr, sb.st_size); + close(fd); + return TRUE; +} METHOD(plugin_t, destroy, void, tnc_imc_plugin_t *this) { - libtnc_tncc_Terminate(); + charon->imcs->destroy(charon->imcs); free(this); } @@ -31,7 +153,7 @@ METHOD(plugin_t, destroy, void, */ plugin_t *tnc_imc_plugin_create() { - char *tnc_config, *pref_lang; + char *tnc_config; tnc_imc_plugin_t *this; INIT(this, @@ -40,18 +162,19 @@ plugin_t *tnc_imc_plugin_create() }, ); - pref_lang = lib->settings->get_str(lib->settings, - "charon.plugins.tnc-imc.preferred_language", "en"); + /* Create IMC manager */ + charon->imcs = tnc_imc_manager_create(); + + /* Load IMCs and abort if not all instances initalize successfully */ tnc_config = lib->settings->get_str(lib->settings, "charon.plugins.tnc-imc.tnc_config", "/etc/tnc_config"); - - if (libtnc_tncc_Initialize(tnc_config) != TNC_RESULT_SUCCESS) + if (!load_imcs(tnc_config)) { + charon->imcs->destroy(charon->imcs); + charon->imcs = NULL; free(this); - DBG1(DBG_TNC, "TNC IMC initialization failed"); return NULL; } - return &this->plugin; } diff --git a/src/libcharon/plugins/tnc_imv/Makefile.am b/src/libcharon/plugins/tnc_imv/Makefile.am index 9c3b47364..3ba283bb7 100644 --- a/src/libcharon/plugins/tnc_imv/Makefile.am +++ b/src/libcharon/plugins/tnc_imv/Makefile.am @@ -1,11 +1,9 @@ INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ - -I$(top_srcdir)/src/libcharon `xml2-config --cflags` + -I$(top_srcdir)/src/libcharon AM_CFLAGS = -rdynamic -libstrongswan_tnc_imv_la_LIBADD = -ltnc - if MONOLITHIC noinst_LTLIBRARIES = libstrongswan-tnc-imv.la else @@ -13,7 +11,9 @@ plugin_LTLIBRARIES = libstrongswan-tnc-imv.la endif libstrongswan_tnc_imv_la_SOURCES = \ - tnc_imv_plugin.h tnc_imv_plugin.c + tnc_imv_plugin.h tnc_imv_plugin.c tnc_imv.h tnc_imv.c \ + tnc_imv_manager.h tnc_imv_manager.c tnc_imv_bind_function.c \ + tnc_imv_recommendations.h tnc_imv_recommendations.c libstrongswan_tnc_imv_la_LDFLAGS = -module -avoid-version diff --git a/src/libcharon/plugins/tnc_imv/Makefile.in b/src/libcharon/plugins/tnc_imv/Makefile.in index f89b5e03b..0324d2eb9 100644 --- a/src/libcharon/plugins/tnc_imv/Makefile.in +++ b/src/libcharon/plugins/tnc_imv/Makefile.in @@ -74,8 +74,10 @@ am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__installdirs = "$(DESTDIR)$(plugindir)" LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES) -libstrongswan_tnc_imv_la_DEPENDENCIES = -am_libstrongswan_tnc_imv_la_OBJECTS = tnc_imv_plugin.lo +libstrongswan_tnc_imv_la_LIBADD = +am_libstrongswan_tnc_imv_la_OBJECTS = tnc_imv_plugin.lo tnc_imv.lo \ + tnc_imv_manager.lo tnc_imv_bind_function.lo \ + tnc_imv_recommendations.lo libstrongswan_tnc_imv_la_OBJECTS = \ $(am_libstrongswan_tnc_imv_la_OBJECTS) libstrongswan_tnc_imv_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ @@ -221,9 +223,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -262,6 +262,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ @@ -273,14 +275,15 @@ urandom_device = @urandom_device@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ - -I$(top_srcdir)/src/libcharon `xml2-config --cflags` + -I$(top_srcdir)/src/libcharon AM_CFLAGS = -rdynamic -libstrongswan_tnc_imv_la_LIBADD = -ltnc @MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-tnc-imv.la @MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-tnc-imv.la libstrongswan_tnc_imv_la_SOURCES = \ - tnc_imv_plugin.h tnc_imv_plugin.c + tnc_imv_plugin.h tnc_imv_plugin.c tnc_imv.h tnc_imv.c \ + tnc_imv_manager.h tnc_imv_manager.c tnc_imv_bind_function.c \ + tnc_imv_recommendations.h tnc_imv_recommendations.c libstrongswan_tnc_imv_la_LDFLAGS = -module -avoid-version all: all-am @@ -366,7 +369,11 @@ mostlyclean-compile: distclean-compile: -rm -f *.tab.c +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnc_imv.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnc_imv_bind_function.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnc_imv_manager.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnc_imv_plugin.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnc_imv_recommendations.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< diff --git a/src/libcharon/plugins/tnc_imv/tnc_imv.c b/src/libcharon/plugins/tnc_imv/tnc_imv.c new file mode 100644 index 000000000..f88b645d6 --- /dev/null +++ b/src/libcharon/plugins/tnc_imv/tnc_imv.c @@ -0,0 +1,208 @@ +/* + * Copyright (C) 2006 Mike McCauley + * Copyright (C) 2010 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 "tnc_imv.h" + +#include <dlfcn.h> + +#include <debug.h> +#include <library.h> + +typedef struct private_tnc_imv_t private_tnc_imv_t; + +/** + * Private data of an imv_t object. + */ +struct private_tnc_imv_t { + + /** + * Public members of imv_t. + */ + imv_t public; + + /** + * Path of loaded IMV + */ + char *path; + + /** + * Name of loaded IMV + */ + char *name; + + /** + * Handle of loaded IMV + */ + void *handle; + + /** + * ID of loaded IMV + */ + TNC_IMVID id; + + /** + * List of message types supported by IMC + */ + TNC_MessageTypeList supported_types; + + /** + * Number of supported message types + */ + TNC_UInt32 type_count; +}; + +METHOD(imv_t, set_id, void, + private_tnc_imv_t *this, TNC_IMVID id) +{ + this->id = id; +} + +METHOD(imv_t, get_id, TNC_IMVID, + private_tnc_imv_t *this) +{ + return this->id; +} + +METHOD(imv_t, get_name, char*, + private_tnc_imv_t *this) +{ + return this->name; +} + +METHOD(imv_t, set_message_types, void, + private_tnc_imv_t *this, TNC_MessageTypeList supported_types, + TNC_UInt32 type_count) +{ + /* Free an existing MessageType list */ + free(this->supported_types); + this->supported_types = NULL; + + /* Store the new MessageType list */ + this->type_count = type_count; + if (type_count && supported_types) + { + size_t size = type_count * sizeof(TNC_MessageType); + + this->supported_types = malloc(size); + memcpy(this->supported_types, supported_types, size); + } + DBG2(DBG_TNC, "IMV %u supports %u message types", this->id, type_count); +} + +METHOD(imv_t, type_supported, bool, + private_tnc_imv_t *this, TNC_MessageType message_type) +{ + TNC_VendorID msg_vid, vid; + TNC_MessageSubtype msg_subtype, subtype; + int i; + + msg_vid = (message_type >> 8) & TNC_VENDORID_ANY; + msg_subtype = message_type & TNC_SUBTYPE_ANY; + + for (i = 0; i < this->type_count; i++) + { + vid = (this->supported_types[i] >> 8) & TNC_VENDORID_ANY; + subtype = this->supported_types[i] & TNC_SUBTYPE_ANY; + + if (this->supported_types[i] == message_type + || (subtype == TNC_SUBTYPE_ANY + && (msg_vid == vid || vid == TNC_VENDORID_ANY)) + || (vid == TNC_VENDORID_ANY + && (msg_subtype == subtype || subtype == TNC_SUBTYPE_ANY))) + { + return TRUE; + } + } + return FALSE; +} + +METHOD(imv_t, destroy, void, + private_tnc_imv_t *this) +{ + dlclose(this->handle); + free(this->supported_types); + free(this->name); + free(this->path); + free(this); +} + +/** + * Described in header. + */ +imv_t* tnc_imv_create(char *name, char *path) +{ + private_tnc_imv_t *this; + + INIT(this, + .public = { + .set_id = _set_id, + .get_id = _get_id, + .get_name = _get_name, + .set_message_types = _set_message_types, + .type_supported = _type_supported, + .destroy = _destroy, + }, + .name = name, + .path = path, + ); + + this->handle = dlopen(path, RTLD_LAZY); + if (!this->handle) + { + DBG1(DBG_TNC, "IMV \"%s\" failed to load: %s", name, dlerror()); + free(this); + return NULL; + } + + this->public.initialize = dlsym(this->handle, "TNC_IMV_Initialize"); + if (!this->public.initialize) + { + DBG1(DBG_TNC, "could not resolve TNC_IMV_Initialize in %s: %s\n", + path, dlerror()); + dlclose(this->handle); + free(this); + return NULL; + } + this->public.notify_connection_change = + dlsym(this->handle, "TNC_IMV_NotifyConnectionChange"); + this->public.solicit_recommendation = + dlsym(this->handle, "TNC_IMV_SolicitRecommendation"); + if (!this->public.solicit_recommendation) + { + DBG1(DBG_TNC, "could not resolve TNC_IMV_SolicitRecommendation in %s: %s\n", + path, dlerror()); + dlclose(this->handle); + free(this); + return NULL; + } + this->public.receive_message = + dlsym(this->handle, "TNC_IMV_ReceiveMessage"); + this->public.batch_ending = + dlsym(this->handle, "TNC_IMV_BatchEnding"); + this->public.terminate = + dlsym(this->handle, "TNC_IMV_Terminate"); + this->public.provide_bind_function = + dlsym(this->handle, "TNC_IMV_ProvideBindFunction"); + if (!this->public.provide_bind_function) + { + DBG1(DBG_TNC, "could not resolve TNC_IMV_ProvideBindFunction in %s: %s\n", + path, dlerror()); + dlclose(this->handle); + free(this); + return NULL; + } + + return &this->public; +} diff --git a/src/libcharon/plugins/tnc_imv/tnc_imv.h b/src/libcharon/plugins/tnc_imv/tnc_imv.h new file mode 100644 index 000000000..75939e54c --- /dev/null +++ b/src/libcharon/plugins/tnc_imv/tnc_imv.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2010 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. + */ + +/** + * + * @defgroup tnc_imv_t tnc_imv + * @{ @ingroup tnc_imv + */ + +#ifndef TNC_IMV_H_ +#define TNC_IMV_H_ + +#include <tnc/imv/imv.h> + +/** + * Create an Integrity Measurement Verifier. + * + * @param name name of the IMV + * @param filename path to the dynamic IMV library + * @return instance of the imv_t interface + */ +imv_t* tnc_imv_create(char *name, char *filename); + +#endif /** TNC_IMV_H_ @}*/ diff --git a/src/libcharon/plugins/tnc_imv/tnc_imv_bind_function.c b/src/libcharon/plugins/tnc_imv/tnc_imv_bind_function.c new file mode 100644 index 000000000..0ea52f08e --- /dev/null +++ b/src/libcharon/plugins/tnc_imv/tnc_imv_bind_function.c @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2006 Mike McCauley + * Copyright (C) 2010 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 "tnc_imv.h" + +#include <debug.h> +#include <daemon.h> + +#define TNC_IMCID_ANY 0xffff + +/** + * Called by the IMV to inform a TNCS about the set of message types the IMV + * is able to receive + */ +TNC_Result TNC_TNCS_ReportMessageTypes(TNC_IMVID imv_id, + TNC_MessageTypeList supported_types, + TNC_UInt32 type_count) +{ + return charon->imvs->set_message_types(charon->imvs, imv_id, + supported_types, type_count); +} + +/** + * Called by the IMV to ask a TNCS to retry an Integrity Check Handshake + */ +TNC_Result TNC_TNCS_RequestHandshakeRetry(TNC_IMVID imv_id, + TNC_ConnectionID connection_id, + TNC_RetryReason reason) +{ + return charon->tnccs->request_handshake_retry(charon->tnccs, FALSE, imv_id, + connection_id, reason); +} + +/** + * Called by the IMV when an IMV-IMC message is to be sent + */ +TNC_Result TNC_TNCS_SendMessage(TNC_IMVID imv_id, + TNC_ConnectionID connection_id, + TNC_BufferReference msg, + TNC_UInt32 msg_len, + TNC_MessageType msg_type) +{ + return charon->tnccs->send_message(charon->tnccs, TNC_IMCID_ANY, imv_id, + connection_id, msg, msg_len, msg_type); +} + +/** + * Called by the IMV to deliver its IMV Action Recommendation and IMV Evaluation + * Result to the TNCS + */ +TNC_Result TNC_TNCS_ProvideRecommendation(TNC_IMVID imv_id, + TNC_ConnectionID connection_id, + TNC_IMV_Action_Recommendation recommendation, + TNC_IMV_Evaluation_Result evaluation) +{ + return charon->tnccs->provide_recommendation(charon->tnccs, imv_id, + connection_id, recommendation, evaluation); +} + +/** + * Called by the IMV to get the value of an attribute associated with a + * connection or with the TNCS as a whole. + */ +TNC_Result TNC_TNCS_GetAttribute(TNC_IMVID imv_id, + TNC_ConnectionID connection_id, + TNC_AttributeID attribute_id, + TNC_UInt32 buffer_len, + TNC_BufferReference buffer, + TNC_UInt32 *out_value_len) +{ + return charon->tnccs->get_attribute(charon->tnccs, imv_id, connection_id, + attribute_id, buffer_len, buffer, out_value_len); +} + +/** + * Called by the IMV to set the value of an attribute associated with a + * connection or with the TNCS as a whole. + */ +TNC_Result TNC_TNCS_SetAttribute(TNC_IMVID imv_id, + TNC_ConnectionID connection_id, + TNC_AttributeID attribute_id, + TNC_UInt32 buffer_len, + TNC_BufferReference buffer) +{ + return charon->tnccs->set_attribute(charon->tnccs, imv_id, connection_id, + attribute_id, buffer_len, buffer); +} + +/** + * Called by the IMV when it needs a function pointer + */ +TNC_Result TNC_TNCS_BindFunction(TNC_IMVID id, + char *function_name, + void **function_pointer) +{ + if (streq(function_name, "TNC_TNCS_ReportMessageTypes")) + { + *function_pointer = (void*)TNC_TNCS_ReportMessageTypes; + } + else if (streq(function_name, "TNC_TNCS_RequestHandshakeRetry")) + { + *function_pointer = (void*)TNC_TNCS_RequestHandshakeRetry; + } + else if (streq(function_name, "TNC_TNCS_SendMessage")) + { + *function_pointer = (void*)TNC_TNCS_SendMessage; + } + else if (streq(function_name, "TNC_TNCS_ProvideRecommendation")) + { + *function_pointer = (void*)TNC_TNCS_ProvideRecommendation; + } + else if (streq(function_name, "TNC_TNCS_GetAttribute")) + { + *function_pointer = (void*)TNC_TNCS_GetAttribute; + } + else if (streq(function_name, "TNC_TNCS_SetAttribute")) + { + *function_pointer = (void*)TNC_TNCS_SetAttribute; + } + else + { + return TNC_RESULT_INVALID_PARAMETER; + } + return TNC_RESULT_SUCCESS; +} diff --git a/src/libcharon/plugins/tnc_imv/tnc_imv_manager.c b/src/libcharon/plugins/tnc_imv/tnc_imv_manager.c new file mode 100644 index 000000000..559de86d0 --- /dev/null +++ b/src/libcharon/plugins/tnc_imv/tnc_imv_manager.c @@ -0,0 +1,295 @@ +/* + * Copyright (C) 2006 Mike McCauley + * Copyright (C) 2010 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 "tnc_imv_manager.h" +#include "tnc_imv_recommendations.h" + +#include <tnc/imv/imv_manager.h> +#include <tnc/tncifimv.h> + +#include <debug.h> +#include <daemon.h> +#include <threading/mutex.h> + +typedef struct private_tnc_imv_manager_t private_tnc_imv_manager_t; + + +/** + * Private data of an imv_manager_t object. + */ +struct private_tnc_imv_manager_t { + + /** + * Public members of imv_manager_t. + */ + imv_manager_t public; + + /** + * Linked list of IMVs + */ + linked_list_t *imvs; + + /** + * Next IMV ID to be assigned + */ + TNC_IMVID next_imv_id; + + /** + * Policy defining how to derive final recommendation from individual ones + */ + recommendation_policy_t policy; +}; + +METHOD(imv_manager_t, add, bool, + private_tnc_imv_manager_t *this, imv_t *imv) +{ + TNC_Version version; + + /* Initialize the IMV module */ + imv->set_id(imv, this->next_imv_id); + if (imv->initialize(imv->get_id(imv), TNC_IFIMV_VERSION_1, + TNC_IFIMV_VERSION_1, &version) != TNC_RESULT_SUCCESS) + { + DBG1(DBG_TNC, "IMV \"%s\" failed to initialize", imv->get_name(imv)); + return FALSE; + } + this->imvs->insert_last(this->imvs, imv); + this->next_imv_id++; + + if (imv->provide_bind_function(imv->get_id(imv), TNC_TNCS_BindFunction) + != TNC_RESULT_SUCCESS) + { + DBG1(DBG_TNC, "IMV \"%s\" could failed to obtain bind function", + imv->get_name(imv)); + this->imvs->remove_last(this->imvs, (void**)&imv); + return FALSE; + } + + return TRUE; +} + +METHOD(imv_manager_t, remove_, imv_t*, + private_tnc_imv_manager_t *this, TNC_IMVID id) +{ + enumerator_t *enumerator; + imv_t *imv; + + enumerator = this->imvs->create_enumerator(this->imvs); + while (enumerator->enumerate(enumerator, &imv)) + { + if (id == imv->get_id(imv)) + { + this->imvs->remove_at(this->imvs, enumerator); + return imv; + } + } + enumerator->destroy(enumerator); + return NULL; +} + +METHOD(imv_manager_t, get_recommendation_policy, recommendation_policy_t, + private_tnc_imv_manager_t *this) +{ + return this->policy; +} + +METHOD(imv_manager_t, create_recommendations, recommendations_t*, + private_tnc_imv_manager_t *this) +{ + return tnc_imv_recommendations_create(this->imvs); +} + +METHOD(imv_manager_t, enforce_recommendation, bool, + private_tnc_imv_manager_t *this, TNC_IMV_Action_Recommendation rec) +{ + char *group; + identification_t *id; + ike_sa_t *ike_sa; + auth_cfg_t *auth; + + switch (rec) + { + case TNC_IMV_ACTION_RECOMMENDATION_ALLOW: + DBG1(DBG_TNC, "TNC recommendation is allow"); + group = "allow"; + break; + case TNC_IMV_ACTION_RECOMMENDATION_ISOLATE: + DBG1(DBG_TNC, "TNC recommendation is isolate"); + group = "isolate"; + break; + case TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS: + case TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION: + default: + DBG1(DBG_TNC, "TNC recommendation is none"); + return FALSE; + } + ike_sa = charon->bus->get_sa(charon->bus); + if (ike_sa) + { + auth = ike_sa->get_auth_cfg(ike_sa, FALSE); + id = identification_create_from_string(group); + auth->add(auth, AUTH_RULE_GROUP, id); + DBG1(DBG_TNC, "TNC added group membership '%s'", group); + } + return TRUE; +} + + +METHOD(imv_manager_t, notify_connection_change, void, + private_tnc_imv_manager_t *this, TNC_ConnectionID id, + TNC_ConnectionState state) +{ + enumerator_t *enumerator; + imv_t *imv; + + enumerator = this->imvs->create_enumerator(this->imvs); + while (enumerator->enumerate(enumerator, &imv)) + { + if (imv->notify_connection_change) + { + imv->notify_connection_change(imv->get_id(imv), id, state); + } + } + enumerator->destroy(enumerator); +} + +METHOD(imv_manager_t, set_message_types, TNC_Result, + private_tnc_imv_manager_t *this, TNC_IMVID id, + TNC_MessageTypeList supported_types, + TNC_UInt32 type_count) +{ + enumerator_t *enumerator; + imv_t *imv; + TNC_Result result = TNC_RESULT_FATAL; + + enumerator = this->imvs->create_enumerator(this->imvs); + while (enumerator->enumerate(enumerator, &imv)) + { + if (id == imv->get_id(imv)) + { + imv->set_message_types(imv, supported_types, type_count); + result = TNC_RESULT_SUCCESS; + break; + } + } + enumerator->destroy(enumerator); + return result; +} + +METHOD(imv_manager_t, solicit_recommendation, void, + private_tnc_imv_manager_t *this, TNC_ConnectionID id) +{ + enumerator_t *enumerator; + imv_t *imv; + + enumerator = this->imvs->create_enumerator(this->imvs); + while (enumerator->enumerate(enumerator, &imv)) + { + imv->solicit_recommendation(imv->get_id(imv), id); + } + enumerator->destroy(enumerator); +} + +METHOD(imv_manager_t, receive_message, void, + private_tnc_imv_manager_t *this, TNC_ConnectionID connection_id, + TNC_BufferReference message, + TNC_UInt32 message_len, + TNC_MessageType message_type) +{ + enumerator_t *enumerator; + imv_t *imv; + + enumerator = this->imvs->create_enumerator(this->imvs); + while (enumerator->enumerate(enumerator, &imv)) + { + if (imv->receive_message && imv->type_supported(imv, message_type)) + { + imv->receive_message(imv->get_id(imv), connection_id, + message, message_len, message_type); + } + } + enumerator->destroy(enumerator); +} + +METHOD(imv_manager_t, batch_ending, void, + private_tnc_imv_manager_t *this, TNC_ConnectionID id) +{ + enumerator_t *enumerator; + imv_t *imv; + + enumerator = this->imvs->create_enumerator(this->imvs); + while (enumerator->enumerate(enumerator, &imv)) + { + if (imv->batch_ending) + { + imv->batch_ending(imv->get_id(imv), id); + } + } + enumerator->destroy(enumerator); +} + +METHOD(imv_manager_t, destroy, void, + private_tnc_imv_manager_t *this) +{ + imv_t *imv; + + while (this->imvs->remove_last(this->imvs, (void**)&imv) == SUCCESS) + { + if (imv->terminate && + imv->terminate(imv->get_id(imv)) != TNC_RESULT_SUCCESS) + { + DBG1(DBG_TNC, "IMV \"%s\" not terminated successfully", + imv->get_name(imv)); + } + imv->destroy(imv); + } + this->imvs->destroy(this->imvs); + free(this); +} + +/** + * Described in header. + */ +imv_manager_t* tnc_imv_manager_create(void) +{ + private_tnc_imv_manager_t *this; + recommendation_policy_t policy; + + INIT(this, + .public = { + .add = _add, + .remove = _remove_, /* avoid name conflict with stdio.h */ + .get_recommendation_policy = _get_recommendation_policy, + .create_recommendations = _create_recommendations, + .enforce_recommendation = _enforce_recommendation, + .notify_connection_change = _notify_connection_change, + .set_message_types = _set_message_types, + .solicit_recommendation = _solicit_recommendation, + .receive_message = _receive_message, + .batch_ending = _batch_ending, + .destroy = _destroy, + }, + .imvs = linked_list_create(), + .next_imv_id = 1, + ); + policy = enum_from_name(recommendation_policy_names, + lib->settings->get_str(lib->settings, + "charon.plugins.tnc-imv.recommendation_policy", "default")); + this->policy = (policy != -1) ? policy : RECOMMENDATION_POLICY_DEFAULT; + DBG1(DBG_TNC, "TNC recommendation policy is '%N'", + recommendation_policy_names, this->policy); + + return &this->public; +} diff --git a/src/libcharon/plugins/tnc_imv/tnc_imv_manager.h b/src/libcharon/plugins/tnc_imv/tnc_imv_manager.h new file mode 100644 index 000000000..2fe9e7ae3 --- /dev/null +++ b/src/libcharon/plugins/tnc_imv/tnc_imv_manager.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2010 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. + */ + +/** + * + * @defgroup tnc_imv_manager tnc_imv_manager + * @{ @ingroup tnc_imv + */ + +#ifndef TNC_IMV_MANAGER_H_ +#define TNC_IMV_MANAGER_H_ + +#include <tnc/imv/imv_manager.h> + +/** + * Create an IMV manager instance. + */ +imv_manager_t *tnc_imv_manager_create(); + +#endif /** TNC_IMV_MANAGER_H_ @}*/ diff --git a/src/libcharon/plugins/tnc_imv/tnc_imv_plugin.c b/src/libcharon/plugins/tnc_imv/tnc_imv_plugin.c index 5b3d3892d..f238f01ea 100644 --- a/src/libcharon/plugins/tnc_imv/tnc_imv_plugin.c +++ b/src/libcharon/plugins/tnc_imv/tnc_imv_plugin.c @@ -14,15 +14,137 @@ */ #include "tnc_imv_plugin.h" +#include "tnc_imv_manager.h" +#include "tnc_imv.h" -#include <libtnctncs.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/mman.h> +#include <unistd.h> +#include <errno.h> +#include <fcntl.h> #include <daemon.h> +#include <utils/lexparser.h> + +/** + * load IMVs from a configuration file + */ +static bool load_imvs(char *filename) +{ + int fd, line_nr = 0; + chunk_t src, line; + struct stat sb; + void *addr; + + DBG1(DBG_TNC, "loading IMVs from '%s'", filename); + fd = open(filename, O_RDONLY); + if (fd == -1) + { + DBG1(DBG_TNC, "opening configuration file '%s' failed: %s", filename, + strerror(errno)); + return FALSE; + } + if (fstat(fd, &sb) == -1) + { + DBG1(DBG_LIB, "getting file size of '%s' failed: %s", filename, + strerror(errno)); + close(fd); + return FALSE; + } + addr = mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); + if (addr == MAP_FAILED) + { + DBG1(DBG_LIB, "mapping '%s' failed: %s", filename, strerror(errno)); + close(fd); + return FALSE; + } + src = chunk_create(addr, sb.st_size); + + while (fetchline(&src, &line)) + { + char *name, *path; + chunk_t token; + imv_t *imv; + + line_nr++; + + /* skip comments or empty lines */ + if (*line.ptr == '#' || !eat_whitespace(&line)) + { + continue; + } + + /* determine keyword */ + if (!extract_token(&token, ' ', &line)) + { + DBG1(DBG_TNC, "line %d: keyword must be followed by a space", + line_nr); + return FALSE; + } + + /* only interested in IMVs */ + if (!match("IMV", &token)) + { + continue; + } + + /* advance to the IMV name and extract it */ + if (!extract_token(&token, '"', &line) || + !extract_token(&token, '"', &line)) + { + DBG1(DBG_TNC, "line %d: IMV name must be set in double quotes", + line_nr); + return FALSE; + } + + /* copy the IMV name */ + name = malloc(token.len + 1); + memcpy(name, token.ptr, token.len); + name[token.len] = '\0'; + + /* advance to the IMV path and extract it */ + if (!eat_whitespace(&line)) + { + DBG1(DBG_TNC, "line %d: IMV path is missing", line_nr); + free(name); + return FALSE; + } + if (!extract_token(&token, ' ', &line)) + { + token = line; + } + + /* copy the IMV path */ + path = malloc(token.len + 1); + memcpy(path, token.ptr, token.len); + path[token.len] = '\0'; + + /* load and register IMV instance */ + imv = tnc_imv_create(name, path); + if (!imv) + { + free(name); + free(path); + return FALSE; + } + if (!charon->imvs->add(charon->imvs, imv)) + { + imv->destroy(imv); + return FALSE; + } + DBG1(DBG_TNC, "IMV %u \"%s\" loaded from '%s'", imv->get_id(imv), + name, path); + } + munmap(addr, sb.st_size); + close(fd); + return TRUE; +} METHOD(plugin_t, destroy, void, tnc_imv_plugin_t *this) { - libtnc_tncs_Terminate(); + charon->imvs->destroy(charon->imvs); free(this); } @@ -42,13 +164,18 @@ plugin_t *tnc_imv_plugin_create() tnc_config = lib->settings->get_str(lib->settings, "charon.plugins.tnc-imv.tnc_config", "/etc/tnc_config"); - if (libtnc_tncs_Initialize(tnc_config) != TNC_RESULT_SUCCESS) + + /* Create IMV manager */ + charon->imvs = tnc_imv_manager_create(); + + /* Load IMVs and abort if not all instances initalize successfully */ + if (!load_imvs(tnc_config)) { + charon->imvs->destroy(charon->imvs); + charon->imvs = NULL; free(this); - DBG1(DBG_TNC, "TNC IMV initialization failed"); return NULL; } - return &this->plugin; } diff --git a/src/libcharon/plugins/tnc_imv/tnc_imv_recommendations.c b/src/libcharon/plugins/tnc_imv/tnc_imv_recommendations.c new file mode 100644 index 000000000..5cc6b0ced --- /dev/null +++ b/src/libcharon/plugins/tnc_imv/tnc_imv_recommendations.c @@ -0,0 +1,415 @@ +/* + * Copyright (C) 2010 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 <debug.h> +#include <daemon.h> +#include <tnc/tncifimv.h> +#include <tnc/imv/imv.h> +#include <tnc/imv/imv_recommendations.h> + +typedef struct private_tnc_imv_recommendations_t private_tnc_imv_recommendations_t; +typedef struct recommendation_entry_t recommendation_entry_t; + +/** + * Recommendation entry + */ +struct recommendation_entry_t { + + /** + * IMV ID + */ + TNC_IMVID id; + + /** + * Received a recommendation message from this IMV? + */ + bool have_recommendation; + + /** + * Action Recommendation provided by IMV instance + */ + TNC_IMV_Action_Recommendation rec; + + /** + * Evaluation Result provided by IMV instance + */ + TNC_IMV_Evaluation_Result eval; + + /** + * Reason string provided by IMV instance + */ + chunk_t reason; + + /** + * Reason language provided by IMV instance + */ + chunk_t reason_language; +}; + +/** + * Private data of a recommendations_t object. + */ +struct private_tnc_imv_recommendations_t { + + /** + * Public members of recommendations_t. + */ + recommendations_t public; + + /** + * list of recommendations and evaluations provided by IMVs + */ + linked_list_t *recs; + + /** + * Preferred language for remediation messages + */ + chunk_t preferred_language; +}; + +METHOD(recommendations_t, provide_recommendation, TNC_Result, + private_tnc_imv_recommendations_t* this, TNC_IMVID id, + TNC_IMV_Action_Recommendation rec, + TNC_IMV_Evaluation_Result eval) +{ + enumerator_t *enumerator; + recommendation_entry_t *entry; + bool found = FALSE; + + DBG2(DBG_TNC, "IMV %u provides recommendation '%N' and evaluation '%N'", id, + TNC_IMV_Action_Recommendation_names, rec, + TNC_IMV_Evaluation_Result_names, eval); + + enumerator = this->recs->create_enumerator(this->recs); + while (enumerator->enumerate(enumerator, &entry)) + { + if (entry->id == id) + { + found = TRUE; + entry->have_recommendation = TRUE; + entry->rec = rec; + entry->eval = eval; + break; + } + } + enumerator->destroy(enumerator); + return found ? TNC_RESULT_SUCCESS : TNC_RESULT_FATAL; +} + +METHOD(recommendations_t, have_recommendation, bool, + private_tnc_imv_recommendations_t *this, TNC_IMV_Action_Recommendation *rec, + TNC_IMV_Evaluation_Result *eval) +{ + enumerator_t *enumerator; + recommendation_entry_t *entry; + recommendation_policy_t policy; + TNC_IMV_Action_Recommendation final_rec; + TNC_IMV_Evaluation_Result final_eval; + bool first = TRUE, incomplete = FALSE; + + *rec = final_rec = TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION; + *eval = final_eval = TNC_IMV_EVALUATION_RESULT_DONT_KNOW; + + if (this->recs->get_count(this->recs) == 0) + { + DBG1(DBG_TNC, "there are no IMVs to make a recommendation"); + return TRUE; + } + policy = charon->imvs->get_recommendation_policy(charon->imvs); + + enumerator = this->recs->create_enumerator(this->recs); + while (enumerator->enumerate(enumerator, &entry)) + { + if (!entry->have_recommendation) + { + incomplete = TRUE; + break; + } + if (first) + { + final_rec = entry->rec; + final_eval = entry->eval; + first = FALSE; + continue; + } + switch (policy) + { + case RECOMMENDATION_POLICY_DEFAULT: + switch (entry->rec) + { + case TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS: + final_rec = entry->rec; + break; + case TNC_IMV_ACTION_RECOMMENDATION_ISOLATE: + if (final_rec != TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS) + { + final_rec = entry->rec; + }; + break; + case TNC_IMV_ACTION_RECOMMENDATION_ALLOW: + if (final_rec == TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION) + { + final_rec = entry->rec; + }; + break; + case TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION: + break; + } + switch (entry->eval) + { + case TNC_IMV_EVALUATION_RESULT_ERROR: + final_eval = entry->eval; + break; + case TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MAJOR: + if (final_eval != TNC_IMV_EVALUATION_RESULT_ERROR) + { + final_eval = entry->eval; + } + break; + case TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MINOR: + if (final_eval != TNC_IMV_EVALUATION_RESULT_ERROR && + final_eval != TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MAJOR) + { + final_eval = entry->eval; + } + break; + case TNC_IMV_EVALUATION_RESULT_COMPLIANT: + if (final_eval == TNC_IMV_EVALUATION_RESULT_DONT_KNOW) + { + final_eval = entry->eval; + } + break; + case TNC_IMV_EVALUATION_RESULT_DONT_KNOW: + break; + } + break; + + case RECOMMENDATION_POLICY_ALL: + if (entry->rec != final_rec) + { + final_rec = TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION; + } + if (entry->eval != final_eval) + { + final_eval = TNC_IMV_EVALUATION_RESULT_DONT_KNOW; + } + break; + + case RECOMMENDATION_POLICY_ANY: + switch (entry->rec) + { + case TNC_IMV_ACTION_RECOMMENDATION_ALLOW: + final_rec = entry->rec; + break; + case TNC_IMV_ACTION_RECOMMENDATION_ISOLATE: + if (final_rec != TNC_IMV_ACTION_RECOMMENDATION_ALLOW) + { + final_rec = entry->rec; + }; + break; + case TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS: + if (final_rec == TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION) + { + final_rec = entry->rec; + }; + break; + case TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION: + break; + } + switch (entry->eval) + { + case TNC_IMV_EVALUATION_RESULT_COMPLIANT: + final_eval = entry->eval; + break; + case TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MINOR: + if (final_eval != TNC_IMV_EVALUATION_RESULT_COMPLIANT) + { + final_eval = entry->eval; + } + break; + case TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MAJOR: + if (final_eval != TNC_IMV_EVALUATION_RESULT_COMPLIANT && + final_eval != TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MINOR) + { + final_eval = entry->eval; + } + break; + case TNC_IMV_EVALUATION_RESULT_ERROR: + if (final_eval == TNC_IMV_EVALUATION_RESULT_DONT_KNOW) + { + final_eval = entry->eval; + } + break; + case TNC_IMV_EVALUATION_RESULT_DONT_KNOW: + break; + } + } + } + enumerator->destroy(enumerator); + + if (incomplete) + { + return FALSE; + } + *rec = final_rec; + *eval = final_eval; + return TRUE; +} + +METHOD(recommendations_t, get_preferred_language, chunk_t, + private_tnc_imv_recommendations_t *this) +{ + return this->preferred_language; +} + +METHOD(recommendations_t, set_preferred_language, void, + private_tnc_imv_recommendations_t *this, chunk_t pref_lang) +{ + free(this->preferred_language.ptr); + this->preferred_language = chunk_clone(pref_lang); +} + +METHOD(recommendations_t, set_reason_string, TNC_Result, + private_tnc_imv_recommendations_t *this, TNC_IMVID id, chunk_t reason) +{ + enumerator_t *enumerator; + recommendation_entry_t *entry; + bool found = FALSE; + + DBG2(DBG_TNC, "IMV %u is setting reason string to '%.*s'", + id, reason.len, reason.ptr); + + enumerator = this->recs->create_enumerator(this->recs); + while (enumerator->enumerate(enumerator, &entry)) + { + if (entry->id == id) + { + found = TRUE; + free(entry->reason.ptr); + entry->reason = chunk_clone(reason); + break; + } + } + enumerator->destroy(enumerator); + return found ? TNC_RESULT_SUCCESS : TNC_RESULT_INVALID_PARAMETER; +} + +METHOD(recommendations_t, set_reason_language, TNC_Result, + private_tnc_imv_recommendations_t *this, TNC_IMVID id, chunk_t reason_lang) +{ + enumerator_t *enumerator; + recommendation_entry_t *entry; + bool found = FALSE; + + DBG2(DBG_TNC, "IMV %u is setting reason language to '%.*s'", + id, reason_lang.len, reason_lang.ptr); + + enumerator = this->recs->create_enumerator(this->recs); + while (enumerator->enumerate(enumerator, &entry)) + { + if (entry->id == id) + { + found = TRUE; + free(entry->reason_language.ptr); + entry->reason_language = chunk_clone(reason_lang); + break; + } + } + enumerator->destroy(enumerator); + return found ? TNC_RESULT_SUCCESS : TNC_RESULT_INVALID_PARAMETER; +} + +/** + * Enumerate reason and reason_language, not recommendation entries + */ +static bool reason_filter(void *null, recommendation_entry_t **entry, + TNC_IMVID *id, void *i2, chunk_t *reason, void *i3, + chunk_t *reason_language) +{ + if ((*entry)->reason.len) + { + *id = (*entry)->id; + *reason = (*entry)->reason; + *reason_language = (*entry)->reason_language; + return TRUE; + } + else + { + return FALSE; + } +} + +METHOD(recommendations_t, create_reason_enumerator, enumerator_t*, + private_tnc_imv_recommendations_t *this) +{ + return enumerator_create_filter(this->recs->create_enumerator(this->recs), + (void*)reason_filter, NULL, NULL); +} + +METHOD(recommendations_t, destroy, void, + private_tnc_imv_recommendations_t *this) +{ + recommendation_entry_t *entry; + + while (this->recs->remove_last(this->recs, (void**)&entry) == SUCCESS) + { + free(entry->reason.ptr); + free(entry->reason_language.ptr); + free(entry); + } + this->recs->destroy(this->recs); + free(this->preferred_language.ptr); + free(this); +} + +/** + * Described in header. + */ +recommendations_t* tnc_imv_recommendations_create(linked_list_t *imv_list) +{ + private_tnc_imv_recommendations_t *this; + recommendation_entry_t *entry; + enumerator_t *enumerator; + imv_t *imv; + + INIT(this, + .public = { + .provide_recommendation = _provide_recommendation, + .have_recommendation = _have_recommendation, + .get_preferred_language = _get_preferred_language, + .set_preferred_language = _set_preferred_language, + .set_reason_string = _set_reason_string, + .set_reason_language = _set_reason_language, + .create_reason_enumerator = _create_reason_enumerator, + .destroy = _destroy, + }, + .recs = linked_list_create(), + ); + + enumerator = imv_list->create_enumerator(imv_list); + while (enumerator->enumerate(enumerator, &imv)) + { + entry = malloc_thing(recommendation_entry_t); + entry->id = imv->get_id(imv); + entry->have_recommendation = FALSE; + entry->rec = TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION; + entry->eval = TNC_IMV_EVALUATION_RESULT_DONT_KNOW; + entry->reason = chunk_empty; + entry->reason_language = chunk_empty; + this->recs->insert_last(this->recs, entry); + } + enumerator->destroy(enumerator); + + return &this->public; +} diff --git a/src/libcharon/plugins/tnc_imv/tnc_imv_recommendations.h b/src/libcharon/plugins/tnc_imv/tnc_imv_recommendations.h new file mode 100644 index 000000000..6d65a2521 --- /dev/null +++ b/src/libcharon/plugins/tnc_imv/tnc_imv_recommendations.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2010 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. + */ + +/** + * + * @defgroup tnc_imv_manager tnc_imv_manager + * @{ @ingroup tnc_imv + */ + +#ifndef TNC_IMV_RECOMMENDATIONS_H_ +#define TNC_IMV_RECOMMENDATIONS_H_ + +#include <tnc/imv/imv_recommendations.h> +#include <utils/linked_list.h> + +/** + * Create an IMV empty recommendations instance + */ +recommendations_t *tnc_imv_recommendations_create(); + +#endif /** TNC_IMV_RECOMMENDATIONS_H_ @}*/ diff --git a/src/libcharon/plugins/tnccs_11/Makefile.am b/src/libcharon/plugins/tnccs_11/Makefile.am index 7ccd0dfee..1042c3514 100644 --- a/src/libcharon/plugins/tnccs_11/Makefile.am +++ b/src/libcharon/plugins/tnccs_11/Makefile.am @@ -1,21 +1,27 @@ INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ - -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/libtls \ - `xml2-config --cflags` + -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/libtls ${xml_CFLAGS} AM_CFLAGS = -rdynamic -libstrongswan_tnccs_11_la_LIBADD = -ltnc +libstrongswan_tnccs_11_la_LIBADD = ${xml_LIBS} if MONOLITHIC noinst_LTLIBRARIES = libstrongswan-tnccs-11.la else plugin_LTLIBRARIES = libstrongswan-tnccs-11.la -libstrongswan_tnccs_11_la_LIBADD += $(top_builddir)/src/libtls/libtls.la endif libstrongswan_tnccs_11_la_SOURCES = \ - tnccs_11_plugin.h tnccs_11_plugin.c tnccs_11.h tnccs_11.c + tnccs_11_plugin.h tnccs_11_plugin.c tnccs_11.h tnccs_11.c \ + batch/tnccs_batch.h batch/tnccs_batch.c \ + messages/tnccs_msg.h messages/tnccs_msg.c \ + messages/imc_imv_msg.h messages/imc_imv_msg.c \ + messages/tnccs_error_msg.h messages/tnccs_error_msg.c \ + messages/tnccs_preferred_language_msg.h messages/tnccs_preferred_language_msg.c \ + messages/tnccs_reason_strings_msg.h messages/tnccs_reason_strings_msg.c \ + messages/tnccs_recommendation_msg.h messages/tnccs_recommendation_msg.c \ + messages/tnccs_tncs_contact_info_msg.h messages/tnccs_tncs_contact_info_msg.c libstrongswan_tnccs_11_la_LDFLAGS = -module -avoid-version diff --git a/src/libcharon/plugins/tnccs_11/Makefile.in b/src/libcharon/plugins/tnccs_11/Makefile.in index 200ff7a0a..5ab7ccbca 100644 --- a/src/libcharon/plugins/tnccs_11/Makefile.in +++ b/src/libcharon/plugins/tnccs_11/Makefile.in @@ -34,7 +34,6 @@ PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ -@MONOLITHIC_FALSE@am__append_1 = $(top_builddir)/src/libtls/libtls.la subdir = src/libcharon/plugins/tnccs_11 DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -75,8 +74,12 @@ am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__installdirs = "$(DESTDIR)$(plugindir)" LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES) -libstrongswan_tnccs_11_la_DEPENDENCIES = $(am__append_1) -am_libstrongswan_tnccs_11_la_OBJECTS = tnccs_11_plugin.lo tnccs_11.lo +am__DEPENDENCIES_1 = +libstrongswan_tnccs_11_la_DEPENDENCIES = $(am__DEPENDENCIES_1) +am_libstrongswan_tnccs_11_la_OBJECTS = tnccs_11_plugin.lo tnccs_11.lo \ + tnccs_batch.lo tnccs_msg.lo imc_imv_msg.lo tnccs_error_msg.lo \ + tnccs_preferred_language_msg.lo tnccs_reason_strings_msg.lo \ + tnccs_recommendation_msg.lo tnccs_tncs_contact_info_msg.lo libstrongswan_tnccs_11_la_OBJECTS = \ $(am_libstrongswan_tnccs_11_la_OBJECTS) libstrongswan_tnccs_11_la_LINK = $(LIBTOOL) --tag=CC \ @@ -223,9 +226,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -264,6 +265,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ @@ -275,15 +278,22 @@ urandom_device = @urandom_device@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ - -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/libtls \ - `xml2-config --cflags` + -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/libtls ${xml_CFLAGS} AM_CFLAGS = -rdynamic -libstrongswan_tnccs_11_la_LIBADD = -ltnc $(am__append_1) +libstrongswan_tnccs_11_la_LIBADD = ${xml_LIBS} @MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-tnccs-11.la @MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-tnccs-11.la libstrongswan_tnccs_11_la_SOURCES = \ - tnccs_11_plugin.h tnccs_11_plugin.c tnccs_11.h tnccs_11.c + tnccs_11_plugin.h tnccs_11_plugin.c tnccs_11.h tnccs_11.c \ + batch/tnccs_batch.h batch/tnccs_batch.c \ + messages/tnccs_msg.h messages/tnccs_msg.c \ + messages/imc_imv_msg.h messages/imc_imv_msg.c \ + messages/tnccs_error_msg.h messages/tnccs_error_msg.c \ + messages/tnccs_preferred_language_msg.h messages/tnccs_preferred_language_msg.c \ + messages/tnccs_reason_strings_msg.h messages/tnccs_reason_strings_msg.c \ + messages/tnccs_recommendation_msg.h messages/tnccs_recommendation_msg.c \ + messages/tnccs_tncs_contact_info_msg.h messages/tnccs_tncs_contact_info_msg.c libstrongswan_tnccs_11_la_LDFLAGS = -module -avoid-version all: all-am @@ -369,8 +379,16 @@ mostlyclean-compile: distclean-compile: -rm -f *.tab.c +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imc_imv_msg.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnccs_11.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnccs_11_plugin.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnccs_batch.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnccs_error_msg.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnccs_msg.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnccs_preferred_language_msg.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnccs_reason_strings_msg.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnccs_recommendation_msg.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnccs_tncs_contact_info_msg.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @@ -393,6 +411,62 @@ distclean-compile: @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< +tnccs_batch.lo: batch/tnccs_batch.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tnccs_batch.lo -MD -MP -MF $(DEPDIR)/tnccs_batch.Tpo -c -o tnccs_batch.lo `test -f 'batch/tnccs_batch.c' || echo '$(srcdir)/'`batch/tnccs_batch.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/tnccs_batch.Tpo $(DEPDIR)/tnccs_batch.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='batch/tnccs_batch.c' object='tnccs_batch.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tnccs_batch.lo `test -f 'batch/tnccs_batch.c' || echo '$(srcdir)/'`batch/tnccs_batch.c + +tnccs_msg.lo: messages/tnccs_msg.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tnccs_msg.lo -MD -MP -MF $(DEPDIR)/tnccs_msg.Tpo -c -o tnccs_msg.lo `test -f 'messages/tnccs_msg.c' || echo '$(srcdir)/'`messages/tnccs_msg.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/tnccs_msg.Tpo $(DEPDIR)/tnccs_msg.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='messages/tnccs_msg.c' object='tnccs_msg.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tnccs_msg.lo `test -f 'messages/tnccs_msg.c' || echo '$(srcdir)/'`messages/tnccs_msg.c + +imc_imv_msg.lo: messages/imc_imv_msg.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT imc_imv_msg.lo -MD -MP -MF $(DEPDIR)/imc_imv_msg.Tpo -c -o imc_imv_msg.lo `test -f 'messages/imc_imv_msg.c' || echo '$(srcdir)/'`messages/imc_imv_msg.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/imc_imv_msg.Tpo $(DEPDIR)/imc_imv_msg.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='messages/imc_imv_msg.c' object='imc_imv_msg.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o imc_imv_msg.lo `test -f 'messages/imc_imv_msg.c' || echo '$(srcdir)/'`messages/imc_imv_msg.c + +tnccs_error_msg.lo: messages/tnccs_error_msg.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tnccs_error_msg.lo -MD -MP -MF $(DEPDIR)/tnccs_error_msg.Tpo -c -o tnccs_error_msg.lo `test -f 'messages/tnccs_error_msg.c' || echo '$(srcdir)/'`messages/tnccs_error_msg.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/tnccs_error_msg.Tpo $(DEPDIR)/tnccs_error_msg.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='messages/tnccs_error_msg.c' object='tnccs_error_msg.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tnccs_error_msg.lo `test -f 'messages/tnccs_error_msg.c' || echo '$(srcdir)/'`messages/tnccs_error_msg.c + +tnccs_preferred_language_msg.lo: messages/tnccs_preferred_language_msg.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tnccs_preferred_language_msg.lo -MD -MP -MF $(DEPDIR)/tnccs_preferred_language_msg.Tpo -c -o tnccs_preferred_language_msg.lo `test -f 'messages/tnccs_preferred_language_msg.c' || echo '$(srcdir)/'`messages/tnccs_preferred_language_msg.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/tnccs_preferred_language_msg.Tpo $(DEPDIR)/tnccs_preferred_language_msg.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='messages/tnccs_preferred_language_msg.c' object='tnccs_preferred_language_msg.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tnccs_preferred_language_msg.lo `test -f 'messages/tnccs_preferred_language_msg.c' || echo '$(srcdir)/'`messages/tnccs_preferred_language_msg.c + +tnccs_reason_strings_msg.lo: messages/tnccs_reason_strings_msg.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tnccs_reason_strings_msg.lo -MD -MP -MF $(DEPDIR)/tnccs_reason_strings_msg.Tpo -c -o tnccs_reason_strings_msg.lo `test -f 'messages/tnccs_reason_strings_msg.c' || echo '$(srcdir)/'`messages/tnccs_reason_strings_msg.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/tnccs_reason_strings_msg.Tpo $(DEPDIR)/tnccs_reason_strings_msg.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='messages/tnccs_reason_strings_msg.c' object='tnccs_reason_strings_msg.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tnccs_reason_strings_msg.lo `test -f 'messages/tnccs_reason_strings_msg.c' || echo '$(srcdir)/'`messages/tnccs_reason_strings_msg.c + +tnccs_recommendation_msg.lo: messages/tnccs_recommendation_msg.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tnccs_recommendation_msg.lo -MD -MP -MF $(DEPDIR)/tnccs_recommendation_msg.Tpo -c -o tnccs_recommendation_msg.lo `test -f 'messages/tnccs_recommendation_msg.c' || echo '$(srcdir)/'`messages/tnccs_recommendation_msg.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/tnccs_recommendation_msg.Tpo $(DEPDIR)/tnccs_recommendation_msg.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='messages/tnccs_recommendation_msg.c' object='tnccs_recommendation_msg.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tnccs_recommendation_msg.lo `test -f 'messages/tnccs_recommendation_msg.c' || echo '$(srcdir)/'`messages/tnccs_recommendation_msg.c + +tnccs_tncs_contact_info_msg.lo: messages/tnccs_tncs_contact_info_msg.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tnccs_tncs_contact_info_msg.lo -MD -MP -MF $(DEPDIR)/tnccs_tncs_contact_info_msg.Tpo -c -o tnccs_tncs_contact_info_msg.lo `test -f 'messages/tnccs_tncs_contact_info_msg.c' || echo '$(srcdir)/'`messages/tnccs_tncs_contact_info_msg.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/tnccs_tncs_contact_info_msg.Tpo $(DEPDIR)/tnccs_tncs_contact_info_msg.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='messages/tnccs_tncs_contact_info_msg.c' object='tnccs_tncs_contact_info_msg.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tnccs_tncs_contact_info_msg.lo `test -f 'messages/tnccs_tncs_contact_info_msg.c' || echo '$(srcdir)/'`messages/tnccs_tncs_contact_info_msg.c + mostlyclean-libtool: -rm -f *.lo diff --git a/src/libcharon/plugins/tnccs_11/batch/tnccs_batch.c b/src/libcharon/plugins/tnccs_11/batch/tnccs_batch.c new file mode 100644 index 000000000..0f6f3a675 --- /dev/null +++ b/src/libcharon/plugins/tnccs_11/batch/tnccs_batch.c @@ -0,0 +1,323 @@ +/* + * Copyright (C) 2006 Mike McCauley (mikem@open.com.au) + * Copyright (C) 2010 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 "tnccs_batch.h" +#include "messages/tnccs_error_msg.h" + +#include <debug.h> +#include <utils/linked_list.h> +#include <tnc/tnccs/tnccs.h> + +#include <libxml/parser.h> + +typedef struct private_tnccs_batch_t private_tnccs_batch_t; + +/** + * Private data of a tnccs_batch_t object. + * + */ +struct private_tnccs_batch_t { + /** + * Public tnccs_batch_t interface. + */ + tnccs_batch_t public; + + /** + * Batch ID + */ + int batch_id; + + /** + * TNCC if TRUE, TNCS if FALSE + */ + bool is_server; + + /** + * linked list of TNCCS messages + */ + linked_list_t *messages; + + /** + * linked list of TNCCS error messages + */ + linked_list_t *errors; + + /** + * XML document + */ + xmlDocPtr doc; + + /** + * Encoded message + */ + chunk_t encoding; +}; + +METHOD(tnccs_batch_t, get_encoding, chunk_t, + private_tnccs_batch_t *this) +{ + return this->encoding; +} + +METHOD(tnccs_batch_t, add_msg, void, + private_tnccs_batch_t *this, tnccs_msg_t* msg) +{ + xmlNodePtr root; + + DBG2(DBG_TNC, "adding %N message", tnccs_msg_type_names, + msg->get_type(msg)); + this->messages->insert_last(this->messages, msg); + root = xmlDocGetRootElement(this->doc); + xmlAddChild(root, msg->get_node(msg)); +} + +METHOD(tnccs_batch_t, build, void, + private_tnccs_batch_t *this) +{ + xmlChar *xmlbuf; + int buf_size; + + xmlDocDumpFormatMemory(this->doc, &xmlbuf, &buf_size, 1); + this->encoding = chunk_create((u_char*)xmlbuf, buf_size); + this->encoding = chunk_clone(this->encoding); + xmlFree(xmlbuf); +} + +METHOD(tnccs_batch_t, process, status_t, + private_tnccs_batch_t *this) +{ + tnccs_msg_t *tnccs_msg, *msg; + tnccs_error_type_t error_type = TNCCS_ERROR_OTHER; + char *error_msg, buf[BUF_LEN]; + xmlNodePtr cur; + xmlNsPtr ns; + xmlChar *batchid, *recipient; + int batch_id; + + this->doc = xmlParseMemory(this->encoding.ptr, this->encoding.len); + if (!this->doc) + { + error_type = TNCCS_ERROR_MALFORMED_BATCH; + error_msg = "failed to parse XML message"; + goto fatal; + } + + /* check out the XML document */ + cur = xmlDocGetRootElement(this->doc); + if (!cur) + { + error_type = TNCCS_ERROR_MALFORMED_BATCH; + error_msg = "empty XML document"; + goto fatal; + } + + /* check TNCCS namespace */ + ns = xmlSearchNsByHref(this->doc, cur, (const xmlChar*) + "http://www.trustedcomputinggroup.org/IWG/TNC/1_0/IF_TNCCS#"); + if (!ns) + { + error_type = TNCCS_ERROR_MALFORMED_BATCH; + error_msg = "TNCCS namespace not found"; + goto fatal; + } + + /* check XML document type */ + if (xmlStrcmp(cur->name, (const xmlChar*)"TNCCS-Batch")) + { + error_type = TNCCS_ERROR_MALFORMED_BATCH; + error_msg = buf; + snprintf(buf, BUF_LEN, "wrong XML document type '%s', expected TNCCS-Batch", + cur->name); + goto fatal; + } + + /* check presence of BatchID property */ + batchid = xmlGetProp(cur, (const xmlChar*)"BatchId"); + if (!batchid) + { + error_type = TNCCS_ERROR_INVALID_BATCH_ID; + error_msg = "BatchId is missing"; + goto fatal; + } + + /* check BatchID */ + batch_id = atoi((char*)batchid); + xmlFree(batchid); + if (batch_id != this->batch_id) + { + error_type = TNCCS_ERROR_INVALID_BATCH_ID; + error_msg = buf; + snprintf(buf, BUF_LEN, "BatchId %d expected, got %d", this->batch_id, + batch_id); + goto fatal; + } + + /* check presence of Recipient property */ + recipient = xmlGetProp(cur, (const xmlChar*)"Recipient"); + if (!recipient) + { + error_type = TNCCS_ERROR_INVALID_RECIPIENT_TYPE; + error_msg = "Recipient is missing"; + goto fatal; + } + + /* check recipient */ + if (!streq((char*)recipient, this->is_server ? "TNCS" : "TNCC")) + { + error_type = TNCCS_ERROR_INVALID_RECIPIENT_TYPE; + error_msg = buf; + snprintf(buf, BUF_LEN, "message recipient expected '%s', got '%s'", + this->is_server ? "TNCS" : "TNCC", (char*)recipient); + xmlFree(recipient); + goto fatal; + } + xmlFree(recipient); + + DBG2(DBG_TNC, "processing TNCCS Batch #%d", batch_id); + + /* Now walk the tree, handling message nodes as we go */ + for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) + { + /* ignore empty or blank nodes */ + if (xmlIsBlankNode(cur)) + { + continue; + } + + /* ignore nodes with wrong namespace */ + if (cur->ns != ns) + { + DBG1(DBG_TNC, "ignoring message node '%s' having wrong namespace", + (char*)cur->name); + continue; + } + + tnccs_msg = tnccs_msg_create_from_node(cur, this->errors); + + /* exit if a message parsing error occurred */ + if (this->errors->get_count(this->errors) > 0) + { + return FAILED; + } + + /* ignore unrecognized messages */ + if (!tnccs_msg) + { + continue; + } + + this->messages->insert_last(this->messages, tnccs_msg); + } + return SUCCESS; + +fatal: + msg = tnccs_error_msg_create(error_type, error_msg); + this->errors->insert_last(this->errors, msg); + return FAILED; +} + +METHOD(tnccs_batch_t, create_msg_enumerator, enumerator_t*, + private_tnccs_batch_t *this) +{ + return this->messages->create_enumerator(this->messages); +} + +METHOD(tnccs_batch_t, create_error_enumerator, enumerator_t*, + private_tnccs_batch_t *this) +{ + return this->errors->create_enumerator(this->errors); +} + +METHOD(tnccs_batch_t, destroy, void, + private_tnccs_batch_t *this) +{ + this->messages->destroy_offset(this->messages, + offsetof(tnccs_msg_t, destroy)); + this->errors->destroy_offset(this->errors, + offsetof(tnccs_msg_t, destroy)); + xmlFreeDoc(this->doc); + free(this->encoding.ptr); + free(this); +} + +/** + * See header + */ +tnccs_batch_t* tnccs_batch_create(bool is_server, int batch_id) +{ + private_tnccs_batch_t *this; + xmlNodePtr n; + char buf[12]; + const char *recipient; + + INIT(this, + .public = { + .get_encoding = _get_encoding, + .add_msg = _add_msg, + .build = _build, + .process = _process, + .create_msg_enumerator = _create_msg_enumerator, + .create_error_enumerator = _create_error_enumerator, + .destroy = _destroy, + }, + .is_server = is_server, + .messages = linked_list_create(), + .errors = linked_list_create(), + .batch_id = batch_id, + .doc = xmlNewDoc(BAD_CAST "1.0"), + ); + + DBG2(DBG_TNC, "creating TNCCS Batch #%d", this->batch_id); + n = xmlNewNode(NULL, BAD_CAST "TNCCS-Batch"); + snprintf(buf, sizeof(buf), "%d", batch_id); + recipient = this->is_server ? "TNCC" : "TNCS"; + xmlNewProp(n, BAD_CAST "BatchId", BAD_CAST buf); + xmlNewProp(n, BAD_CAST "Recipient", BAD_CAST recipient); + xmlNewProp(n, BAD_CAST "xmlns", BAD_CAST "http://www.trustedcomputinggroup.org/IWG/TNC/1_0/IF_TNCCS#"); + xmlNewProp(n, BAD_CAST "xmlns:xsi", BAD_CAST "http://www.w3.org/2001/XMLSchema-instance"); + xmlNewProp(n, BAD_CAST "xsi:schemaLocation", BAD_CAST "http://www.trustedcomputinggroup.org/IWG/TNC/1_0/IF_TNCCS# " + "https://www.trustedcomputinggroup.org/XML/SCHEMA/TNCCS_1.0.xsd"); + xmlDocSetRootElement(this->doc, n); + + return &this->public; +} + +/** + * See header + */ +tnccs_batch_t* tnccs_batch_create_from_data(bool is_server, int batch_id, chunk_t data) +{ + private_tnccs_batch_t *this; + + INIT(this, + .public = { + .get_encoding = _get_encoding, + .add_msg = _add_msg, + .build = _build, + .process = _process, + .create_msg_enumerator = _create_msg_enumerator, + .create_error_enumerator = _create_error_enumerator, + .destroy = _destroy, + }, + .is_server = is_server, + .batch_id = batch_id, + .messages = linked_list_create(), + .errors = linked_list_create(), + .encoding = chunk_clone(data), + ); + + return &this->public; +} + diff --git a/src/libcharon/plugins/tnccs_11/batch/tnccs_batch.h b/src/libcharon/plugins/tnccs_11/batch/tnccs_batch.h new file mode 100644 index 000000000..25301f763 --- /dev/null +++ b/src/libcharon/plugins/tnccs_11/batch/tnccs_batch.h @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2010 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. + */ + +/** + * @defgroup tnccs_batch tnccs_batch + * @{ @ingroup tnccs_11 + */ + +#ifndef TNCCS_BATCH_H_ +#define TNCCS_BATCH_H_ + +typedef enum tnccs_batch_type_t tnccs_batch_type_t; +typedef struct tnccs_batch_t tnccs_batch_t; + +#include "messages/tnccs_msg.h" + +#include <library.h> + +/** + * Interface for a TNCCS 1.x Batch. + */ +struct tnccs_batch_t { + + /** + * Get the encoding of the TNCCS 1.x Batch + * + * @return encoded TNCCS 1.x batch + */ + chunk_t (*get_encoding)(tnccs_batch_t *this); + + /** + * Add TNCCS message + * + * @param msg TNCCS message to be addedd + */ + void (*add_msg)(tnccs_batch_t *this, tnccs_msg_t* msg); + + /** + * Build the TNCCS 1.x Batch + */ + void (*build)(tnccs_batch_t *this); + + /** + * Process the TNCCS 1.x Batch + * + * @return return processing status + */ + status_t (*process)(tnccs_batch_t *this); + + /** + * Enumerates over all TNCCS Messages + * + * @return return message enumerator + */ + enumerator_t* (*create_msg_enumerator)(tnccs_batch_t *this); + + /** + * Enumerates over all parsing errors + * + * @return return error enumerator + */ + enumerator_t* (*create_error_enumerator)(tnccs_batch_t *this); + + /** + * Destroys a tnccs_batch_t object. + */ + void (*destroy)(tnccs_batch_t *this); +}; + +/** + * Create an empty TNCCS 1.x Batch + * + * @param is_server TRUE if server, FALSE if client + * @param batch_id number of the batch to be sent + */ +tnccs_batch_t* tnccs_batch_create(bool is_server, int batch_id); + +/** + * Create an unprocessed TNCCS 1.x Batch from data + * + * @param is_server TRUE if server, FALSE if client + * @param batch_id current Batch ID + * @param data encoded PB-TNC batch + */ +tnccs_batch_t* tnccs_batch_create_from_data(bool is_server, int batch_id, + chunk_t data); + +#endif /** TNCCS_BATCH_H_ @}*/ diff --git a/src/libcharon/plugins/tnccs_11/messages/imc_imv_msg.c b/src/libcharon/plugins/tnccs_11/messages/imc_imv_msg.c new file mode 100644 index 000000000..f24c0dac9 --- /dev/null +++ b/src/libcharon/plugins/tnccs_11/messages/imc_imv_msg.c @@ -0,0 +1,242 @@ +/* + * Copyright (C) 2006 Mike McCauley (mikem@open.com.au) + * Copyright (C) 2010 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 "imc_imv_msg.h" + +#include <tnc/tnccs/tnccs.h> +#include <debug.h> +#include <utils/lexparser.h> + +typedef struct private_imc_imv_msg_t private_imc_imv_msg_t; + +#define BYTES_PER_LINE 57 + +/** + * Private data of a imc_imv_msg_t object. + * + */ +struct private_imc_imv_msg_t { + /** + * Public imc_imv_msg_t interface. + */ + imc_imv_msg_t public; + + /** + * TNCCS message type + */ + tnccs_msg_type_t type; + + /** + * XML-encoded message node + */ + xmlNodePtr node; + + /** + * IMC-IMV message type + */ + TNC_MessageType msg_type; + + /** + * IMC-IMV message body + */ + chunk_t msg_body; + +}; + +/** + * Encodes message data into multiple base64-encoded lines + */ +static chunk_t encode_base64(chunk_t data) +{ + chunk_t encoding; + u_char *pos; + size_t b64_chars, b64_lines; + + /* handle empty message data object */ + if (data.len == 0) + { + encoding = chunk_alloc(1); + *encoding.ptr = '\0'; + return encoding; + } + + /* compute and allocate maximum size of base64 object */ + b64_chars = 4 * ((data.len + 2) / 3); + b64_lines = (data.len + BYTES_PER_LINE - 1) / BYTES_PER_LINE; + encoding = chunk_alloc(b64_chars + b64_lines); + pos = encoding.ptr; + + /* encode lines */ + while (b64_lines--) + { + chunk_t data_line, b64_line; + + data_line = chunk_create(data.ptr, min(data.len, BYTES_PER_LINE)); + data.ptr += data_line.len; + data.len -= data_line.len; + b64_line = chunk_to_base64(data_line, pos); + pos += b64_line.len; + *pos = '\n'; + pos++; + } + /* terminate last line with NULL character instead of newline */ + *(pos-1) = '\0'; + + return encoding; +} + +/** + * Decodes message data from multiple base64-encoded lines + */ +static chunk_t decode_base64(chunk_t data) +{ + chunk_t decoding, data_line, b64_line; + u_char *pos; + + /* compute and allocate maximum size of decoded message data */ + decoding = chunk_alloc(3 * ((data.len + 3) / 4)); + pos = decoding.ptr; + decoding.len = 0; + + while (fetchline(&data, &b64_line)) + { + data_line = chunk_from_base64(b64_line, pos); + pos += data_line.len; + decoding.len += data_line.len; + } + + return decoding; +} + +METHOD(tnccs_msg_t, get_type, tnccs_msg_type_t, + private_imc_imv_msg_t *this) +{ + return this->type; +} + +METHOD(tnccs_msg_t, get_node, xmlNodePtr, + private_imc_imv_msg_t *this) +{ + return this->node; +} + +METHOD(tnccs_msg_t, destroy, void, + private_imc_imv_msg_t *this) +{ + free(this->msg_body.ptr); + free(this); +} + +METHOD(imc_imv_msg_t, get_msg_type, TNC_MessageType, + private_imc_imv_msg_t *this) +{ + return this->msg_type; +} + +METHOD(imc_imv_msg_t, get_msg_body, chunk_t, + private_imc_imv_msg_t *this) +{ + return this->msg_body; +} + +/** + * See header + */ +tnccs_msg_t *imc_imv_msg_create_from_node(xmlNodePtr node, linked_list_t *errors) +{ + private_imc_imv_msg_t *this; + xmlNsPtr ns; + xmlNodePtr cur; + xmlChar *content; + chunk_t b64_body; + + INIT(this, + .public = { + .tnccs_msg_interface = { + .get_type = _get_type, + .get_node = _get_node, + .destroy = _destroy, + }, + .get_msg_type = _get_msg_type, + .get_msg_body = _get_msg_body, + }, + .type = IMC_IMV_MSG, + .node = node, + ); + + ns = node->ns; + cur = node->xmlChildrenNode; + while (cur) + { + if (streq((char*)cur->name, "Type") && cur->ns == ns) + { + content = xmlNodeGetContent(cur); + this->msg_type = strtoul((char*)content, NULL, 16); + xmlFree(content); + } + else if (streq((char*)cur->name, "Base64") && cur->ns == ns) + { + content = xmlNodeGetContent(cur); + b64_body = chunk_create((char*)content, strlen((char*)content)); + this->msg_body = decode_base64(b64_body); + xmlFree(content); + } + cur = cur->next; + } + + return &this->public.tnccs_msg_interface; +} + +/** + * See header + */ +tnccs_msg_t *imc_imv_msg_create(TNC_MessageType msg_type, chunk_t msg_body) +{ + private_imc_imv_msg_t *this; + chunk_t b64_body; + char buf[10]; /* big enough for hex-encoded message type */ + xmlNodePtr n; + + INIT(this, + .public = { + .tnccs_msg_interface = { + .get_type = _get_type, + .get_node = _get_node, + .destroy = _destroy, + }, + .get_msg_type = _get_msg_type, + .get_msg_body = _get_msg_body, + }, + .type = IMC_IMV_MSG, + .node = xmlNewNode(NULL, BAD_CAST "IMC-IMV-Message"), + .msg_type = msg_type, + .msg_body = chunk_clone(msg_body), + ); + + /* add the message type number in hex */ + n = xmlNewNode(NULL, BAD_CAST "Type"); + snprintf(buf, 10, "%08x", this->msg_type); + xmlNodeSetContent(n, BAD_CAST buf); + xmlAddChild(this->node, n); + + /* encode the message as a Base64 node */ + n = xmlNewNode(NULL, BAD_CAST "Base64"); + b64_body = encode_base64(this->msg_body); + xmlNodeSetContent(n, BAD_CAST b64_body.ptr); + xmlAddChild(this->node, n); + free(b64_body.ptr); + + return &this->public.tnccs_msg_interface; +} diff --git a/src/libcharon/plugins/tnccs_11/messages/imc_imv_msg.h b/src/libcharon/plugins/tnccs_11/messages/imc_imv_msg.h new file mode 100644 index 000000000..02f07199f --- /dev/null +++ b/src/libcharon/plugins/tnccs_11/messages/imc_imv_msg.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2010 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. + */ + +/** + * @defgroup imc_imv_msg imc_imv_msg + * @{ @ingroup tnccs_11 + */ + +#ifndef IMC_IMV_MSG_H_ +#define IMC_IMV_MSG_H_ + +typedef struct imc_imv_msg_t imc_imv_msg_t; + +#include "tnccs_msg.h" + +#include <tnc/tncif.h> + +/** + * Classs representing the PB-PA message type. + */ +struct imc_imv_msg_t { + + /** + * TNCCS Message interface + */ + tnccs_msg_t tnccs_msg_interface; + + /** + * Get IMC-IMV message type + * + * @return IMC-IMV message type + */ + TNC_MessageType (*get_msg_type)(imc_imv_msg_t *this); + + /** + * Get IMC-IMV message body + * + * @return IMC-IMV message body + */ + chunk_t (*get_msg_body)(imc_imv_msg_t *this); +}; + +/** + * Create an IMC-IMV message from XML-encoded message node + * + * @param node XML-encoded message node + * @param errors linked list of TNCCS error messages +*/ +tnccs_msg_t *imc_imv_msg_create_from_node(xmlNodePtr node, linked_list_t *errors); + +/** + * Create an IMC-IMV message from parameters + * + * @param msg_type IMC-IMV message type + * @param msg_body IMC-IMV message body + */ +tnccs_msg_t *imc_imv_msg_create(TNC_MessageType msg_type, chunk_t msg_body); + +#endif /** IMC_IMV_MSG_H_ @}*/ diff --git a/src/libcharon/plugins/tnccs_11/messages/tnccs_error_msg.c b/src/libcharon/plugins/tnccs_11/messages/tnccs_error_msg.c new file mode 100644 index 000000000..d0df4e7ca --- /dev/null +++ b/src/libcharon/plugins/tnccs_11/messages/tnccs_error_msg.c @@ -0,0 +1,191 @@ +/* + * Copyright (C) 2006 Mike McCauley (mikem@open.com.au) + * Copyright (C) 2010 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 "tnccs_error_msg.h" + +#include <debug.h> + +ENUM(tnccs_error_type_names, TNCCS_ERROR_BATCH_TOO_LONG, TNCCS_ERROR_OTHER, + "batch-too-long", + "malformed-batch", + "invalid-batch-id", + "invalid-recipient-type", + "internal-error", + "other" +); + +typedef struct private_tnccs_error_msg_t private_tnccs_error_msg_t; + +/** + * Private data of a tnccs_error_msg_t object. + * + */ +struct private_tnccs_error_msg_t { + /** + * Public tnccs_error_msg_t interface. + */ + tnccs_error_msg_t public; + + /** + * TNCCS message type + */ + tnccs_msg_type_t type; + + /** + * XML-encoded message node + */ + xmlNodePtr node; + + /** + * Error type + */ + tnccs_error_type_t error_type; + + /** + * Error message + */ + char *error_msg; + + /** + * reference count + */ + refcount_t ref; +}; + +METHOD(tnccs_msg_t, get_type, tnccs_msg_type_t, + private_tnccs_error_msg_t *this) +{ + return this->type; +} + +METHOD(tnccs_msg_t, get_node, xmlNodePtr, + private_tnccs_error_msg_t *this) +{ + return this->node; +} + +METHOD(tnccs_msg_t, get_ref, tnccs_msg_t*, + private_tnccs_error_msg_t *this) +{ + ref_get(&this->ref); + return &this->public.tnccs_msg_interface; +} + +METHOD(tnccs_msg_t, destroy, void, + private_tnccs_error_msg_t *this) +{ + if (ref_put(&this->ref)) + { + free(this->error_msg); + free(this); + } +} + +METHOD(tnccs_error_msg_t, get_message, char*, + private_tnccs_error_msg_t *this, tnccs_error_type_t *type) +{ + *type = this->error_type; + + return this->error_msg; +} + +/** + * See header + */ +tnccs_msg_t *tnccs_error_msg_create_from_node(xmlNodePtr node) +{ + private_tnccs_error_msg_t *this; + xmlChar *error_type_name, *error_msg; + + INIT(this, + .public = { + .tnccs_msg_interface = { + .get_type = _get_type, + .get_node = _get_node, + .get_ref = _get_ref, + .destroy = _destroy, + }, + .get_message = _get_message, + }, + .type = TNCCS_MSG_ERROR, + .ref = 1, + .node = node, + .error_type = TNCCS_ERROR_OTHER, + ); + + error_type_name = xmlGetProp(node, (const xmlChar*)"type"); + if (error_type_name) + { + this->error_type = enum_from_name(tnccs_error_type_names, + (char*)error_type_name); + if (this->error_type == -1) + { + this->error_type = TNCCS_ERROR_OTHER; + } + xmlFree(error_type_name); + } + + error_msg = xmlNodeGetContent(node); + if (error_msg) + { + this->error_msg = strdup((char*)error_msg); + xmlFree(error_msg); + } + + return &this->public.tnccs_msg_interface; +} + +/** + * See header + */ +tnccs_msg_t *tnccs_error_msg_create(tnccs_error_type_t type, char *msg) +{ + private_tnccs_error_msg_t *this; + xmlNodePtr n, n2; + + INIT(this, + .public = { + .tnccs_msg_interface = { + .get_type = _get_type, + .get_node = _get_node, + .get_ref = _get_ref, + .destroy = _destroy, + }, + .get_message = _get_message, + }, + .type = TNCCS_MSG_ERROR, + .ref = 1, + .node = xmlNewNode(NULL, BAD_CAST "TNCC-TNCS-Message"), + .error_type = type, + .error_msg = strdup(msg), + ); + + DBG1(DBG_TNC, "%s", msg); + + n = xmlNewNode(NULL, BAD_CAST "Type"); + xmlNodeSetContent(n, BAD_CAST "00000002"); + xmlAddChild(this->node, n); + + n = xmlNewNode(NULL, BAD_CAST "XML"); + xmlAddChild(this->node, n); + + n2 = xmlNewNode(NULL, BAD_CAST enum_to_name(tnccs_msg_type_names, this->type)); + xmlNewProp(n2, BAD_CAST "type", + BAD_CAST enum_to_name(tnccs_error_type_names, type)); + xmlNodeSetContent(n2, BAD_CAST msg); + xmlAddChild(n, n2); + + return &this->public.tnccs_msg_interface; +} diff --git a/src/libcharon/plugins/tnccs_11/messages/tnccs_error_msg.h b/src/libcharon/plugins/tnccs_11/messages/tnccs_error_msg.h new file mode 100644 index 000000000..ce2ce9755 --- /dev/null +++ b/src/libcharon/plugins/tnccs_11/messages/tnccs_error_msg.h @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2010 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. + */ + +/** + * @defgroup tnccs_error_msg tnccs_error_msg + * @{ @ingroup tnccs_11 + */ + +#ifndef TNCCS_ERROR_MSG_H_ +#define TNCCS_ERROR_MSG_H_ + +typedef enum tnccs_error_type_t tnccs_error_type_t; +typedef struct tnccs_error_msg_t tnccs_error_msg_t; + +#include "tnccs_msg.h" + +/** + * TNCCS error types as defined in section 8.1.4 of TCG TNC IF-TNCCS v1.2 + */ +enum tnccs_error_type_t { + TNCCS_ERROR_BATCH_TOO_LONG, + TNCCS_ERROR_MALFORMED_BATCH, + TNCCS_ERROR_INVALID_BATCH_ID, + TNCCS_ERROR_INVALID_RECIPIENT_TYPE, + TNCCS_ERROR_INTERNAL_ERROR, + TNCCS_ERROR_OTHER +}; + +/** + * enum name for tnccs_error_type_t. + */ +extern enum_name_t *tnccs_error_type_names; + +/** + * Class representing the TNCCS-Error message type + */ +struct tnccs_error_msg_t { + + /** + * TNCCS Message interface + */ + tnccs_msg_t tnccs_msg_interface; + + /** + * Get error message and type + * + * @param type TNCCS error type + * @return arbitrary error message + */ + char* (*get_message)(tnccs_error_msg_t *this, tnccs_error_type_t *type); +}; + +/** + * Create a TNCCS-Error message from XML-encoded message node + * + * @param node XML-encoded message node + */ +tnccs_msg_t *tnccs_error_msg_create_from_node(xmlNodePtr node); + +/** + * Create a TNCCS-Error message from parameters + * + * @param type TNCCS error type + * @param msg arbitrary error message + */ +tnccs_msg_t *tnccs_error_msg_create(tnccs_error_type_t type, char *msg); + +#endif /** TNCCS_ERROR_MSG_H_ @}*/ diff --git a/src/libcharon/plugins/tnccs_11/messages/tnccs_msg.c b/src/libcharon/plugins/tnccs_11/messages/tnccs_msg.c new file mode 100644 index 000000000..5a050393a --- /dev/null +++ b/src/libcharon/plugins/tnccs_11/messages/tnccs_msg.c @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2006 Mike McCauley (mikem@open.com.au) + * Copyright (C) 2010 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 "tnccs_msg.h" +#include "imc_imv_msg.h" +#include "tnccs_error_msg.h" +#include "tnccs_preferred_language_msg.h" +#include "tnccs_reason_strings_msg.h" +#include "tnccs_recommendation_msg.h" +#include "tnccs_tncs_contact_info_msg.h" + +#include <library.h> +#include <debug.h> + +ENUM(tnccs_msg_type_names, IMC_IMV_MSG, TNCCS_MSG_ROOF, + "IMC-IMV", + "TNCCS-Recommendation", + "TNCCS-Error", + "TNCCS-PreferredLanguage", + "TNCCS-ReasonStrings", + "TNCCS-TNCSContactInfo" +); + +/** + * See header + */ +tnccs_msg_t* tnccs_msg_create_from_node(xmlNodePtr node, linked_list_t *errors) +{ + char *error_msg, buf[BUF_LEN]; + tnccs_error_type_t error_type = TNCCS_ERROR_MALFORMED_BATCH; + tnccs_msg_t *msg; + tnccs_msg_type_t type = IMC_IMV_MSG; + + if (streq((char*)node->name, "IMC-IMV-Message")) + { + DBG2(DBG_TNC, "processing %N message", tnccs_msg_type_names, type); + return imc_imv_msg_create_from_node(node, errors); + } + else if (streq((char*)node->name, "TNCC-TNCS-Message")) + { + bool found = FALSE; + xmlNsPtr ns = node->ns; + xmlNodePtr cur = node->xmlChildrenNode; + xmlNodePtr xml_msg_node = NULL; + + while (cur) + { + if (streq((char*)cur->name, "Type") && cur->ns == ns) + { + xmlChar *content = xmlNodeGetContent(cur); + + type = strtol((char*)content, NULL, 16); + xmlFree(content); + found = TRUE; + } + else if (streq((char*)cur->name, "XML") && cur->ns == ns) + { + xml_msg_node = cur->xmlChildrenNode; + } + cur = cur->next; + } + if (!found) + { + error_msg = "Type is missing in TNCC-TNCS-Message"; + goto fatal; + } + if (!xml_msg_node) + { + error_msg = "XML node is missing in TNCC-TNCS-Message"; + goto fatal; + } + cur = xml_msg_node; + + /* skip empty and blank nodes */ + while (cur && xmlIsBlankNode(cur)) + { + cur = cur->next; + } + if (!cur) + { + error_msg = "XML node is empty"; + goto fatal; + } + + /* check if TNCCS message type and node name agree */ + if (type >= TNCCS_MSG_RECOMMENDATION && type <= TNCCS_MSG_ROOF) + { + DBG2(DBG_TNC, "processing %N message", tnccs_msg_type_names, type); + if (cur->ns != ns) + { + error_msg = "node is not in the TNCCS message namespace"; + goto fatal; + } + if (type != enum_from_name(tnccs_msg_type_names, (char*)cur->name)) + { + error_msg = buf; + snprintf(buf, BUF_LEN, "expected '%N' node but was '%s'", + tnccs_msg_type_names, type, (char*)cur->name); + goto fatal; + } + } + + switch (type) + { + case TNCCS_MSG_RECOMMENDATION: + return tnccs_recommendation_msg_create_from_node(cur, errors); + case TNCCS_MSG_ERROR: + return tnccs_error_msg_create_from_node(cur); + case TNCCS_MSG_PREFERRED_LANGUAGE: + return tnccs_preferred_language_msg_create_from_node(cur, errors); + case TNCCS_MSG_REASON_STRINGS: + return tnccs_reason_strings_msg_create_from_node(cur, errors); + case TNCCS_MSG_TNCS_CONTACT_INFO: + return tnccs_tncs_contact_info_msg_create_from_node(cur, errors); + default: + DBG1(DBG_TNC, "ignoring TNCC-TNCS-Message with type %d", type); + return NULL; + } + } + DBG1(DBG_TNC, "ignoring unknown message node '%s'", (char*)node->name); + return NULL; + +fatal: + msg = tnccs_error_msg_create(error_type, error_msg); + errors->insert_last(errors, msg); + return NULL; +} + diff --git a/src/libcharon/plugins/tnccs_11/messages/tnccs_msg.h b/src/libcharon/plugins/tnccs_11/messages/tnccs_msg.h new file mode 100644 index 000000000..e0b54449a --- /dev/null +++ b/src/libcharon/plugins/tnccs_11/messages/tnccs_msg.h @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2010 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. + */ + +/** + * @defgroup tnccs_msg tnccs_msg + * @{ @ingroup tnccs_11 + */ + +#ifndef TNCCS_MSG_H_ +#define TNCCS_MSG_H_ + +typedef enum tnccs_msg_type_t tnccs_msg_type_t; +typedef struct tnccs_msg_t tnccs_msg_t; + +#include <library.h> +#include <utils/linked_list.h> +#include <libxml/parser.h> + +/** + * TNCC-TNCS messages as defined in section 2.8.5 of TCG TNC IF-TNCCS v1.2 + */ +enum tnccs_msg_type_t { + IMC_IMV_MSG = 0, + TNCCS_MSG_RECOMMENDATION = 1, + TNCCS_MSG_ERROR = 2, + TNCCS_MSG_PREFERRED_LANGUAGE = 3, + TNCCS_MSG_REASON_STRINGS = 4, + TNCCS_MSG_TNCS_CONTACT_INFO = 5, + TNCCS_MSG_ROOF = 5 +}; + +/** + * enum name for tnccs_msg_type_t. + */ +extern enum_name_t *tnccs_msg_type_names; + +/** + * Generic interface for all TNCCS message types. + * + * To handle all messages in a generic way, this interface + * must be implemented by each message type. + */ +struct tnccs_msg_t { + + /** + * Get the TNCCS Message Type + * + * @return TNCCS Message Type + */ + tnccs_msg_type_t (*get_type)(tnccs_msg_t *this); + + /** + * Get the XML-encoded Message Node + * + * @return Message Node + */ + xmlNodePtr (*get_node)(tnccs_msg_t *this); + + /** + * Process the TNCCS Message + * + * @return return processing status + */ + status_t (*process)(tnccs_msg_t *this); + + /** + * Get a new reference to the message. + * + * @return this, with an increased refcount + */ + tnccs_msg_t* (*get_ref)(tnccs_msg_t *this); + + /** + * Destroys a tnccs_msg_t object. + */ + void (*destroy)(tnccs_msg_t *this); +}; + +/** + * Create a pre-processed TNCCS message + * + * Useful for the parser which wants a generic constructor for all + * tnccs_msg_t types. + * + * @param node TNCCS message node + * @param errors linked list of TNCCS error messages + */ +tnccs_msg_t* tnccs_msg_create_from_node(xmlNodePtr node, linked_list_t *errors); + +#endif /** TNCCS_MSG_H_ @}*/ diff --git a/src/libcharon/plugins/tnccs_11/messages/tnccs_preferred_language_msg.c b/src/libcharon/plugins/tnccs_11/messages/tnccs_preferred_language_msg.c new file mode 100644 index 000000000..fd85350b5 --- /dev/null +++ b/src/libcharon/plugins/tnccs_11/messages/tnccs_preferred_language_msg.c @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2006 Mike McCauley (mikem@open.com.au) + * Copyright (C) 2010 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 "tnccs_preferred_language_msg.h" + +#include <debug.h> + +typedef struct private_tnccs_preferred_language_msg_t private_tnccs_preferred_language_msg_t; + +/** + * Private data of a tnccs_preferred_language_msg_t object. + * + */ +struct private_tnccs_preferred_language_msg_t { + /** + * Public tnccs_preferred_language_msg_t interface. + */ + tnccs_preferred_language_msg_t public; + + /** + * TNCCS message type + */ + tnccs_msg_type_t type; + + /** + * XML-encoded message node + */ + xmlNodePtr node; + + /** + * Preferred language + */ + char *preferred_language; +}; + +METHOD(tnccs_msg_t, get_type, tnccs_msg_type_t, + private_tnccs_preferred_language_msg_t *this) +{ + return this->type; +} + +METHOD(tnccs_msg_t, get_node, xmlNodePtr, + private_tnccs_preferred_language_msg_t *this) +{ + return this->node; +} + +METHOD(tnccs_msg_t, destroy, void, + private_tnccs_preferred_language_msg_t *this) +{ + free(this->preferred_language); + free(this); +} + +METHOD(tnccs_preferred_language_msg_t, get_preferred_language, char*, + private_tnccs_preferred_language_msg_t *this) +{ + return this->preferred_language; +} + +/** + * See header + */ +tnccs_msg_t *tnccs_preferred_language_msg_create_from_node(xmlNodePtr node, + linked_list_t *errors) +{ + private_tnccs_preferred_language_msg_t *this; + xmlChar *language; + + INIT(this, + .public = { + .tnccs_msg_interface = { + .get_type = _get_type, + .get_node = _get_node, + .destroy = _destroy, + }, + .get_preferred_language = _get_preferred_language, + }, + .type = TNCCS_MSG_PREFERRED_LANGUAGE, + .node = node, + ); + + language = xmlNodeGetContent(node); + this->preferred_language = strdup((char*)language); + xmlFree(language); + + return &this->public.tnccs_msg_interface; +} + +/** + * See header + */ +tnccs_msg_t *tnccs_preferred_language_msg_create(char *language) +{ + private_tnccs_preferred_language_msg_t *this; + xmlNodePtr n, n2; + + INIT(this, + .public = { + .tnccs_msg_interface = { + .get_type = _get_type, + .get_node = _get_node, + .destroy = _destroy, + }, + .get_preferred_language = _get_preferred_language, + }, + .type = TNCCS_MSG_PREFERRED_LANGUAGE, + .node = xmlNewNode(NULL, BAD_CAST "TNCC-TNCS-Message"), + .preferred_language = strdup(language), + ); + + /* add the message type number in hex */ + n = xmlNewNode(NULL, BAD_CAST "Type"); + xmlNodeSetContent(n, BAD_CAST "00000003"); + xmlAddChild(this->node, n); + + n = xmlNewNode(NULL, BAD_CAST "XML"); + xmlAddChild(this->node, n); + + n2 = xmlNewNode(NULL, BAD_CAST enum_to_name(tnccs_msg_type_names, this->type)); + xmlNodeSetContent(n2, BAD_CAST language); + xmlAddChild(n, n2); + + return &this->public.tnccs_msg_interface; +} diff --git a/src/libcharon/plugins/tnccs_11/messages/tnccs_preferred_language_msg.h b/src/libcharon/plugins/tnccs_11/messages/tnccs_preferred_language_msg.h new file mode 100644 index 000000000..d301ab2bb --- /dev/null +++ b/src/libcharon/plugins/tnccs_11/messages/tnccs_preferred_language_msg.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2010 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. + */ + +/** + * @defgroup tnccs_preferred_language_msg tnccs_preferred_language_msg + * @{ @ingroup tnccs_11 + */ + +#ifndef TNCCS_PREFERRED_LANGUAGE_MSG_H_ +#define TNCCS_PREFERRED_LANGUAGE_MSG_H_ + +typedef struct tnccs_preferred_language_msg_t tnccs_preferred_language_msg_t; + +#include "tnccs_msg.h" + +#include <tnc/tncif.h> + +/** + * Class representing the TNCCS-PreferredLanguage message type + */ +struct tnccs_preferred_language_msg_t { + + /** + * TNCCS Message interface + */ + tnccs_msg_t tnccs_msg_interface; + + /** + * Get preferred language string + * + * @return preferred language string + */ + char* (*get_preferred_language)(tnccs_preferred_language_msg_t *this); +}; + +/** + * Create a TNCCS-PreferredLanguage message from XML-encoded message node + * + * @param node XML-encoded message node + * @param errors linked list of TNCCS error messages + */ +tnccs_msg_t *tnccs_preferred_language_msg_create_from_node(xmlNodePtr node, + linked_list_t *errors); + +/** + * Create a TNCCS-PreferredLanguage message from parameters + * + * @param language preferred language string + */ +tnccs_msg_t *tnccs_preferred_language_msg_create(char *language); + +#endif /** TNCCS_PREFERRED_LANGUAGE_MSG_H_ @}*/ diff --git a/src/libcharon/plugins/tnccs_11/messages/tnccs_reason_strings_msg.c b/src/libcharon/plugins/tnccs_11/messages/tnccs_reason_strings_msg.c new file mode 100644 index 000000000..d4b5d9bf9 --- /dev/null +++ b/src/libcharon/plugins/tnccs_11/messages/tnccs_reason_strings_msg.c @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2006 Mike McCauley (mikem@open.com.au) + * Copyright (C) 2010 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 "tnccs_reason_strings_msg.h" + +#include <debug.h> + +typedef struct private_tnccs_reason_strings_msg_t private_tnccs_reason_strings_msg_t; + +/** + * Private data of a tnccs_reason_strings_msg_t object. + * + */ +struct private_tnccs_reason_strings_msg_t { + /** + * Public tnccs_reason_strings_msg_t interface. + */ + tnccs_reason_strings_msg_t public; + + /** + * TNCCS message type + */ + tnccs_msg_type_t type; + + /** + * XML-encoded message node + */ + xmlNodePtr node; + + /** + * Reason String + */ + chunk_t reason; + + /** + * Reason Language + */ + chunk_t language; +}; + +METHOD(tnccs_msg_t, get_type, tnccs_msg_type_t, + private_tnccs_reason_strings_msg_t *this) +{ + return this->type; +} + +METHOD(tnccs_msg_t, get_node, xmlNodePtr, + private_tnccs_reason_strings_msg_t *this) +{ + return this->node; +} + +METHOD(tnccs_msg_t, destroy, void, + private_tnccs_reason_strings_msg_t *this) +{ + free(this->reason.ptr); + free(this->language.ptr); + free(this); +} + +METHOD(tnccs_reason_strings_msg_t, get_reason, chunk_t, + private_tnccs_reason_strings_msg_t *this, chunk_t *language) +{ + *language = this->language; + + return this->reason; +} + +/** + * See header + */ +tnccs_msg_t *tnccs_reason_strings_msg_create_from_node(xmlNodePtr node, + linked_list_t *errors) +{ + private_tnccs_reason_strings_msg_t *this; + + INIT(this, + .public = { + .tnccs_msg_interface = { + .get_type = _get_type, + .get_node = _get_node, + .destroy = _destroy, + }, + .get_reason = _get_reason, + }, + .type = TNCCS_MSG_REASON_STRINGS, + .node = node, + ); + + return &this->public.tnccs_msg_interface; +} + +/** + * See header + */ +tnccs_msg_t *tnccs_reason_strings_msg_create(chunk_t reason, chunk_t language) +{ + private_tnccs_reason_strings_msg_t *this; + xmlNodePtr n, n2, n3; + + INIT(this, + .public = { + .tnccs_msg_interface = { + .get_type = _get_type, + .get_node = _get_node, + .destroy = _destroy, + }, + .get_reason = _get_reason, + }, + .type = TNCCS_MSG_REASON_STRINGS, + .node = xmlNewNode(NULL, BAD_CAST "TNCC-TNCS-Message"), + .reason = chunk_create_clone(malloc(reason.len + 1), reason), + .language = chunk_create_clone(malloc(language.len + 1), language), + ); + + /* add NULL termination for XML string representation */ + this->reason.ptr[this->reason.len] = '\0'; + this->language.ptr[this->language.len] = '\0'; + + /* add the message type number in hex */ + n = xmlNewNode(NULL, BAD_CAST "Type"); + xmlNodeSetContent(n, BAD_CAST "00000004"); + xmlAddChild(this->node, n); + + n = xmlNewNode(NULL, BAD_CAST "XML"); + xmlAddChild(this->node, n); + + n2 = xmlNewNode(NULL, BAD_CAST enum_to_name(tnccs_msg_type_names, this->type)); + + /* could add multiple reasons here, if we had them */ + n3 = xmlNewNode(NULL, BAD_CAST "ReasonString"); + xmlNewProp(n3, BAD_CAST "xml:lang", BAD_CAST this->language.ptr); + xmlNodeSetContent(n3, BAD_CAST this->reason.ptr); + xmlAddChild(n2, n3); + + return &this->public.tnccs_msg_interface; +} diff --git a/src/libcharon/plugins/tnccs_11/messages/tnccs_reason_strings_msg.h b/src/libcharon/plugins/tnccs_11/messages/tnccs_reason_strings_msg.h new file mode 100644 index 000000000..0046a5789 --- /dev/null +++ b/src/libcharon/plugins/tnccs_11/messages/tnccs_reason_strings_msg.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2010 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. + */ + +/** + * @defgroup tnccs_reason_strings_msg tnccs_reason_strings_msg + * @{ @ingroup tnccs_11 + */ + +#ifndef TNCCS_REASON_STRINGS_MSG_H_ +#define TNCCS_REASON_STRINGS_MSG_H_ + +typedef struct tnccs_reason_strings_msg_t tnccs_reason_strings_msg_t; + +#include "tnccs_msg.h" + +/** + * Class representing the TNCCS-ReasonStrings message type + */ +struct tnccs_reason_strings_msg_t { + + /** + * TNCCS Message interface + */ + tnccs_msg_t tnccs_msg_interface; + + /** + * Get reason string and language + * + * @param language reason language + * @return reason string + */ + chunk_t (*get_reason)(tnccs_reason_strings_msg_t *this, chunk_t *language); +}; + +/** + * Create a TNCCS-ReasonStrings message from XML-encoded message node + * + * @param node XML-encoded message node + * @param errors linked list of TNCCS error messages + */ +tnccs_msg_t *tnccs_reason_strings_msg_create_from_node(xmlNodePtr node, + linked_list_t *errors); + +/** + * Create a TNCCS-ReasonStrings message from parameters + * + * @param reason reason string + * @param language reason language + */ +tnccs_msg_t *tnccs_reason_strings_msg_create(chunk_t reason, chunk_t language); + +#endif /** TNCCS_REASON_STRINGS_MSG_H_ @}*/ diff --git a/src/libcharon/plugins/tnccs_11/messages/tnccs_recommendation_msg.c b/src/libcharon/plugins/tnccs_11/messages/tnccs_recommendation_msg.c new file mode 100644 index 000000000..adc7b54b9 --- /dev/null +++ b/src/libcharon/plugins/tnccs_11/messages/tnccs_recommendation_msg.c @@ -0,0 +1,186 @@ +/* + * Copyright (C) 2006 Mike McCauley (mikem@open.com.au) + * Copyright (C) 2010 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 "tnccs_recommendation_msg.h" +#include "tnccs_error_msg.h" + +#include <debug.h> + +typedef struct private_tnccs_recommendation_msg_t private_tnccs_recommendation_msg_t; + +/** + * Private data of a tnccs_recommendation_msg_t object. + * + */ +struct private_tnccs_recommendation_msg_t { + /** + * Public tnccs_recommendation_msg_t interface. + */ + tnccs_recommendation_msg_t public; + + /** + * TNCCS message type + */ + tnccs_msg_type_t type; + + /** + * XML-encoded message node + */ + xmlNodePtr node; + + /** + * Action Recommendation + */ + TNC_IMV_Action_Recommendation rec; +}; + +METHOD(tnccs_msg_t, get_type, tnccs_msg_type_t, + private_tnccs_recommendation_msg_t *this) +{ + return this->type; +} + +METHOD(tnccs_msg_t, get_node, xmlNodePtr, + private_tnccs_recommendation_msg_t *this) +{ + return this->node; +} + +METHOD(tnccs_msg_t, destroy, void, + private_tnccs_recommendation_msg_t *this) +{ + free(this); +} + +METHOD(tnccs_recommendation_msg_t, get_recommendation, TNC_IMV_Action_Recommendation, + private_tnccs_recommendation_msg_t *this) +{ + return this->rec; +} + +/** + * See header + */ +tnccs_msg_t *tnccs_recommendation_msg_create_from_node(xmlNodePtr node, + linked_list_t *errors) +{ + private_tnccs_recommendation_msg_t *this; + xmlChar *rec_string; + char *error_msg, buf[BUF_LEN]; + tnccs_error_type_t error_type = TNCCS_ERROR_MALFORMED_BATCH; + tnccs_msg_t *msg; + + INIT(this, + .public = { + .tnccs_msg_interface = { + .get_type = _get_type, + .get_node = _get_node, + .destroy = _destroy, + }, + .get_recommendation = _get_recommendation, + }, + .type = TNCCS_MSG_RECOMMENDATION, + .node = node, + ); + + rec_string = xmlGetProp(node, (const xmlChar*)"type"); + if (!rec_string) + { + error_msg = "type property in TNCCS-Recommendation is missing"; + goto fatal; + } + else if (streq((char*)rec_string, "allow")) + { + this->rec = TNC_IMV_ACTION_RECOMMENDATION_ALLOW; + } + else if (streq((char*)rec_string, "isolate")) + { + this->rec = TNC_IMV_ACTION_RECOMMENDATION_ISOLATE; + } + else if (streq((char*)rec_string, "none")) + { + this->rec = TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS; + } + else + { + error_msg = buf; + snprintf(buf, BUF_LEN, "unsupported type property value '%s' " + "in TNCCS-Recommendation", rec_string); + xmlFree(rec_string); + goto fatal; + } + xmlFree(rec_string); + + return &this->public.tnccs_msg_interface; + +fatal: + msg = tnccs_error_msg_create(error_type, error_msg); + errors->insert_last(errors, msg); + _destroy(this); + return NULL; +} + +/** + * See header + */ +tnccs_msg_t *tnccs_recommendation_msg_create(TNC_IMV_Action_Recommendation rec) +{ + private_tnccs_recommendation_msg_t *this; + xmlNodePtr n, n2; + char *rec_string; + + INIT(this, + .public = { + .tnccs_msg_interface = { + .get_type = _get_type, + .get_node = _get_node, + .destroy = _destroy, + }, + .get_recommendation = _get_recommendation, + }, + .type = TNCCS_MSG_RECOMMENDATION, + .node = xmlNewNode(NULL, BAD_CAST "TNCC-TNCS-Message"), + .rec = rec, + ); + + /* add the message type number in hex */ + n = xmlNewNode(NULL, BAD_CAST "Type"); + xmlNodeSetContent(n, BAD_CAST "00000001"); + xmlAddChild(this->node, n); + + n = xmlNewNode(NULL, BAD_CAST "XML"); + xmlAddChild(this->node, n); + + switch (rec) + { + case TNC_IMV_ACTION_RECOMMENDATION_ALLOW: + rec_string = "allow"; + break; + case TNC_IMV_ACTION_RECOMMENDATION_ISOLATE: + rec_string = "isolate"; + break; + case TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS: + case TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION: + default: + rec_string = "none"; + } + + n2 = xmlNewNode(NULL, BAD_CAST enum_to_name(tnccs_msg_type_names, this->type)); + xmlNewProp(n2, BAD_CAST "type", BAD_CAST rec_string); + xmlNodeSetContent(n2, ""); + xmlAddChild(n, n2); + + return &this->public.tnccs_msg_interface; +} diff --git a/src/libcharon/plugins/tnccs_11/messages/tnccs_recommendation_msg.h b/src/libcharon/plugins/tnccs_11/messages/tnccs_recommendation_msg.h new file mode 100644 index 000000000..685049e95 --- /dev/null +++ b/src/libcharon/plugins/tnccs_11/messages/tnccs_recommendation_msg.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2010 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. + */ + +/** + * @defgroup tnccs_recommendation_msg tnccs_recommendation_msg + * @{ @ingroup tnccs_11 + */ + +#ifndef TNCCS_RECOMMENDATION_MSG_H_ +#define TNCCS_RECOMMENDATION_MSG_H_ + +typedef struct tnccs_recommendation_msg_t tnccs_recommendation_msg_t; + +#include "tnccs_msg.h" + +#include <tnc/tncifimv.h> + +/** + * Class representing the TNCCS-Recommendation message type + */ +struct tnccs_recommendation_msg_t { + + /** + * TNCCS Message interface + */ + tnccs_msg_t tnccs_msg_interface; + + /** + * Get Action Recommendation + * + * @return Action Recommendation + */ + TNC_IMV_Action_Recommendation (*get_recommendation)(tnccs_recommendation_msg_t *this); +}; + +/** + * Create a TNCCS-Recommendation message from XML-encoded message node + * + * @param node XML-encoded message node + * @param errors linked list of TNCCS error messages + */ +tnccs_msg_t *tnccs_recommendation_msg_create_from_node(xmlNodePtr node, + linked_list_t *errors); + +/** + * Create a TNCCS-Recommendation message from parameters + * + * @param rec Action Recommendation + */ +tnccs_msg_t *tnccs_recommendation_msg_create(TNC_IMV_Action_Recommendation rec); + +#endif /** TNCCS_RECOMMENDATION_MSG_H_ @}*/ diff --git a/src/libcharon/plugins/tnccs_11/messages/tnccs_tncs_contact_info_msg.c b/src/libcharon/plugins/tnccs_11/messages/tnccs_tncs_contact_info_msg.c new file mode 100644 index 000000000..b8aac30fa --- /dev/null +++ b/src/libcharon/plugins/tnccs_11/messages/tnccs_tncs_contact_info_msg.c @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2010 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 "tnccs_tncs_contact_info_msg.h" + +#include <debug.h> + +typedef struct private_tnccs_tncs_contact_info_msg_t private_tnccs_tncs_contact_info_msg_t; + +/** + * Private data of a tnccs_tncs_contact_info_msg_t object. + * + */ +struct private_tnccs_tncs_contact_info_msg_t { + /** + * Public tnccs_tncs_contact_info_msg_t interface. + */ + tnccs_tncs_contact_info_msg_t public; + + /** + * TNCCS message type + */ + tnccs_msg_type_t type; + + /** + * XML-encoded message node + */ + xmlNodePtr node; +}; + +METHOD(tnccs_msg_t, get_type, tnccs_msg_type_t, + private_tnccs_tncs_contact_info_msg_t *this) +{ + return this->type; +} + +METHOD(tnccs_msg_t, get_node, xmlNodePtr, + private_tnccs_tncs_contact_info_msg_t *this) +{ + return this->node; +} + +METHOD(tnccs_msg_t, destroy, void, + private_tnccs_tncs_contact_info_msg_t *this) +{ + free(this); +} + +/** + * See header + */ +tnccs_msg_t *tnccs_tncs_contact_info_msg_create_from_node(xmlNodePtr node, + linked_list_t *errors) +{ + private_tnccs_tncs_contact_info_msg_t *this; + + INIT(this, + .public = { + .tnccs_msg_interface = { + .get_type = _get_type, + .get_node = _get_node, + .destroy = _destroy, + }, + }, + .type = TNCCS_MSG_TNCS_CONTACT_INFO, + .node = node, + ); + + return &this->public.tnccs_msg_interface; +} + +/** + * See header + */ +tnccs_msg_t *tnccs_tncs_contact_info_msg_create(void) +{ + private_tnccs_tncs_contact_info_msg_t *this; + xmlNodePtr n /*, n2 */; + + INIT(this, + .public = { + .tnccs_msg_interface = { + .get_type = _get_type, + .get_node = _get_node, + .destroy = _destroy, + }, + }, + .type = TNCCS_MSG_TNCS_CONTACT_INFO, + .node = xmlNewNode(NULL, BAD_CAST "TNCC-TNCS-Message"), + ); + + /* add the message type number in hex */ + n = xmlNewNode(NULL, BAD_CAST "Type"); + xmlNodeSetContent(n, BAD_CAST "00000005"); + xmlAddChild(this->node, n); + + n = xmlNewNode(NULL, BAD_CAST "XML"); + xmlAddChild(this->node, n); + +/* TODO + n2 = xmlNewNode(NULL, BAD_CAST enum_to_name(tnccs_msg_type_names, this->type)); + xmlNodeSetContent(n2, BAD_CAST language); + xmlAddChild(n, n2); +*/ + + return &this->public.tnccs_msg_interface; +} diff --git a/src/libcharon/plugins/tnccs_11/messages/tnccs_tncs_contact_info_msg.h b/src/libcharon/plugins/tnccs_11/messages/tnccs_tncs_contact_info_msg.h new file mode 100644 index 000000000..8ed210a57 --- /dev/null +++ b/src/libcharon/plugins/tnccs_11/messages/tnccs_tncs_contact_info_msg.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2010 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. + */ + +/** + * @defgroup tnccs_tncs_contact_info_msg tnccs_tncs_contact_info_msg + * @{ @ingroup tnccs_11 + */ + +#ifndef TNCCS_TNCS_CONTACT_INFO_MSG_H_ +#define TNCCS_TNCS_CONTACT_INFO_MSG_H_ + +typedef struct tnccs_tncs_contact_info_msg_t tnccs_tncs_contact_info_msg_t; + +#include "tnccs_msg.h" + +/** + * Class representing the TNCCS-TNCSContactInfo message type + */ +struct tnccs_tncs_contact_info_msg_t { + + /** + * TNCCS Message interface + */ + tnccs_msg_t tnccs_msg_interface; +}; + +/** + * Create a TNCCS-TNCSContactInfo message from XML-encoded message node + * + * @param node XML-encoded message node + * @param errors linked list of TNCCS error messages + */ +tnccs_msg_t *tnccs_tncs_contact_info_msg_create_from_node(xmlNodePtr node, + linked_list_t *errors); + +/** + * Create a TNCCS-TNCSContactInfo message from parameters + * + */ +tnccs_msg_t *tnccs_tncs_contact_info_msg_create(void); + +#endif /** TNCCS_TNCS_CONTACT_INFO_MSG_H_ @}*/ diff --git a/src/libcharon/plugins/tnccs_11/tnccs_11.c b/src/libcharon/plugins/tnccs_11/tnccs_11.c index 704bf64ed..2104bf401 100644 --- a/src/libcharon/plugins/tnccs_11/tnccs_11.c +++ b/src/libcharon/plugins/tnccs_11/tnccs_11.c @@ -14,81 +14,20 @@ */ #include "tnccs_11.h" - -#include <libtnctncc.h> -#include <libtnctncs.h> +#include "batch/tnccs_batch.h" +#include "messages/tnccs_msg.h" +#include "messages/imc_imv_msg.h" +#include "messages/tnccs_error_msg.h" +#include "messages/tnccs_preferred_language_msg.h" +#include "messages/tnccs_reason_strings_msg.h" +#include "messages/tnccs_recommendation_msg.h" #include <daemon.h> #include <debug.h> - -#define TNC_SEND_BUFFER_SIZE 32 - -static chunk_t tnc_send_buffer[TNC_SEND_BUFFER_SIZE]; - -/** - * Buffers TNCCS batch to be sent (TODO make the buffer scalable) - */ -static TNC_Result buffer_batch(u_int32_t id, const char *data, size_t len) -{ - if (id >= TNC_SEND_BUFFER_SIZE) - { - DBG1(DBG_TNC, "TNCCS Batch for Connection ID %u cannot be stored in " - "send buffer with size %d", id, TNC_SEND_BUFFER_SIZE); - return TNC_RESULT_FATAL; - } - if (tnc_send_buffer[id].ptr) - { - DBG1(DBG_TNC, "send buffer slot for Connection ID %u is already " - "occupied", id); - return TNC_RESULT_FATAL; - } - tnc_send_buffer[id] = chunk_alloc(len); - memcpy(tnc_send_buffer[id].ptr, data, len); - - return TNC_RESULT_SUCCESS; -} - -/** - * Retrieves TNCCS batch to be sent - */ -static bool retrieve_batch(u_int32_t id, chunk_t *batch) -{ - if (id >= TNC_SEND_BUFFER_SIZE) - { - DBG1(DBG_TNC, "TNCCS Batch for Connection ID %u cannot be retrieved from " - "send buffer with size %d", id, TNC_SEND_BUFFER_SIZE); - return FALSE; - } - - *batch = tnc_send_buffer[id]; - return TRUE; -} - -/** - * Frees TNCCS batch that was sent - */ -static void free_batch(u_int32_t id) -{ - if (id < TNC_SEND_BUFFER_SIZE) - { - chunk_free(&tnc_send_buffer[id]); - } -} - -/** - * Define callback functions called by the libtnc library - */ -TNC_Result TNC_TNCC_SendBatch(libtnc_tncc_connection* conn, - const char* messageBuffer, size_t messageLength) -{ - return buffer_batch(conn->connectionID, messageBuffer, messageLength); -} - -TNC_Result TNC_TNCS_SendBatch(libtnc_tncs_connection* conn, - const char* messageBuffer, size_t messageLength) -{ - return buffer_batch(conn->connectionID, messageBuffer, messageLength); -} +#include <threading/mutex.h> +#include <tnc/tncif.h> +#include <tnc/tncifimv.h> +#include <tnc/tnccs/tnccs.h> typedef struct private_tnccs_11_t private_tnccs_11_t; @@ -108,116 +47,372 @@ struct private_tnccs_11_t { bool is_server; /** - * TNCC Connection to IMCs + * Connection ID assigned to this TNCCS connection + */ + TNC_ConnectionID connection_id; + + /** + * Last TNCCS batch ID + */ + int batch_id; + + /** + * TNCCS batch being constructed + */ + tnccs_batch_t *batch; + + /** + * Mutex locking the batch in construction */ - libtnc_tncc_connection* tncc_connection; + mutex_t *mutex; /** - * TNCS Connection to IMVs + * Flag set while processing */ - libtnc_tncs_connection* tncs_connection; + bool fatal_error; + + /** + * Flag set by TNCCS-Recommendation message + */ + bool delete_state; + + /** + * Flag set by IMC/IMV RequestHandshakeRetry() function + */ + bool request_handshake_retry; + + /** + * Set of IMV recommendations (TNC Server only) + */ + recommendations_t *recs; }; -METHOD(tls_t, process, status_t, - private_tnccs_11_t *this, void *buf, size_t buflen) +METHOD(tnccs_t, send_msg, void, + private_tnccs_11_t* this, TNC_IMCID imc_id, TNC_IMVID imv_id, + TNC_BufferReference msg, + TNC_UInt32 msg_len, + TNC_MessageType msg_type) { - u_int32_t conn_id; + tnccs_msg_t *tnccs_msg; - if (this->is_server && !this->tncs_connection) + tnccs_msg = imc_imv_msg_create(msg_type, chunk_create(msg, msg_len)); + + /* adding an IMC-IMV Message to TNCCS batch */ + this->mutex->lock(this->mutex); + if (!this->batch) { - this->tncs_connection = libtnc_tncs_CreateConnection(NULL); - if (!this->tncs_connection) + this->batch = tnccs_batch_create(this->is_server, ++this->batch_id); + } + this->batch->add_msg(this->batch, tnccs_msg); + this->mutex->unlock(this->mutex); +} + +/** + * Handle a single TNCCS message according to its type + */ +static void handle_message(private_tnccs_11_t *this, tnccs_msg_t *msg) +{ + switch (msg->get_type(msg)) + { + case IMC_IMV_MSG: { - DBG1(DBG_TNC, "TNCS CreateConnection failed"); - return FAILED; + imc_imv_msg_t *imc_imv_msg; + TNC_MessageType msg_type; + chunk_t msg_body; + + imc_imv_msg = (imc_imv_msg_t*)msg; + msg_type = imc_imv_msg->get_msg_type(imc_imv_msg); + msg_body = imc_imv_msg->get_msg_body(imc_imv_msg); + + DBG2(DBG_TNC, "handling IMC_IMV message type 0x%08x", msg_type); + + if (this->is_server) + { + charon->imvs->receive_message(charon->imvs, + this->connection_id, msg_body.ptr, msg_body.len, msg_type); + } + else + { + charon->imcs->receive_message(charon->imcs, + this->connection_id, msg_body.ptr, msg_body.len,msg_type); + } + break; + } + case TNCCS_MSG_RECOMMENDATION: + { + tnccs_recommendation_msg_t *rec_msg; + TNC_IMV_Action_Recommendation rec; + TNC_ConnectionState state = TNC_CONNECTION_STATE_ACCESS_NONE; + + rec_msg = (tnccs_recommendation_msg_t*)msg; + rec = rec_msg->get_recommendation(rec_msg); + if (this->is_server) + { + DBG1(DBG_TNC, "ignoring NCCS-Recommendation message from " + " TNC client"); + break; + } + DBG1(DBG_TNC, "TNC recommendation is '%N'", + TNC_IMV_Action_Recommendation_names, rec); + switch (rec) + { + case TNC_IMV_ACTION_RECOMMENDATION_ALLOW: + state = TNC_CONNECTION_STATE_ACCESS_ALLOWED; + break; + case TNC_IMV_ACTION_RECOMMENDATION_ISOLATE: + state = TNC_CONNECTION_STATE_ACCESS_ISOLATED; + break; + case TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS: + default: + state = TNC_CONNECTION_STATE_ACCESS_NONE; + } + charon->imcs->notify_connection_change(charon->imcs, + this->connection_id, state); + this->delete_state = TRUE; + break; + } + case TNCCS_MSG_ERROR: + { + tnccs_error_msg_t *err_msg; + tnccs_error_type_t error_type; + char *error_msg; + + err_msg = (tnccs_error_msg_t*)msg; + error_msg = err_msg->get_message(err_msg, &error_type); + DBG1(DBG_TNC, "received '%N' TNCCS-Error: %s", + tnccs_error_type_names, error_type, error_msg); + + /* we assume that all errors are fatal */ + this->fatal_error = TRUE; + break; } - DBG1(DBG_TNC, "assigned TNCS Connection ID %u", - this->tncs_connection->connectionID); - if (libtnc_tncs_BeginSession(this->tncs_connection) != TNC_RESULT_SUCCESS) + case TNCCS_MSG_PREFERRED_LANGUAGE: + { + tnccs_preferred_language_msg_t *lang_msg; + char *lang; + + lang_msg = (tnccs_preferred_language_msg_t*)msg; + lang = lang_msg->get_preferred_language(lang_msg); + + DBG2(DBG_TNC, "setting preferred language to '%s'", lang); + this->recs->set_preferred_language(this->recs, + chunk_create(lang, strlen(lang))); + break; + } + case TNCCS_MSG_REASON_STRINGS: + { + tnccs_reason_strings_msg_t *reason_msg; + chunk_t reason_string, reason_lang; + + reason_msg = (tnccs_reason_strings_msg_t*)msg; + reason_string = reason_msg->get_reason(reason_msg, &reason_lang); + DBG2(DBG_TNC, "reason string is '%.*s", reason_string.len, + reason_string.ptr); + DBG2(DBG_TNC, "reason language is '%.*s", reason_lang.len, + reason_lang.ptr); + break; + } + default: + break; + } +} + +METHOD(tls_t, process, status_t, + private_tnccs_11_t *this, void *buf, size_t buflen) +{ + chunk_t data; + tnccs_batch_t *batch; + tnccs_msg_t *msg; + enumerator_t *enumerator; + status_t status; + + if (this->is_server && !this->connection_id) + { + this->connection_id = charon->tnccs->create_connection(charon->tnccs, + (tnccs_t*)this, _send_msg, + &this->request_handshake_retry, &this->recs); + if (!this->connection_id) { - DBG1(DBG_TNC, "TNCS BeginSession failed"); return FAILED; } + charon->imvs->notify_connection_change(charon->imvs, + this->connection_id, TNC_CONNECTION_STATE_CREATE); } - conn_id = this->is_server ? this->tncs_connection->connectionID - : this->tncc_connection->connectionID; + data = chunk_create(buf, buflen); DBG1(DBG_TNC, "received TNCCS Batch (%u bytes) for Connection ID %u", - buflen, conn_id); - DBG3(DBG_TNC, "%.*s", buflen, buf); + data.len, this->connection_id); + DBG3(DBG_TNC, "%.*s", data.len, data.ptr); + batch = tnccs_batch_create_from_data(this->is_server, ++this->batch_id, data); + status = batch->process(batch); - if (this->is_server) + if (status == FAILED) { - if (libtnc_tncs_ReceiveBatch(this->tncs_connection, buf, buflen) != - TNC_RESULT_SUCCESS) + this->fatal_error = TRUE; + this->mutex->lock(this->mutex); + if (this->batch) { - DBG1(DBG_TNC, "TNCS ReceiveBatch failed"); - return FAILED; + DBG1(DBG_TNC, "cancelling TNCCS batch"); + this->batch->destroy(this->batch); + this->batch_id--; + } + this->batch = tnccs_batch_create(this->is_server, ++this->batch_id); + + /* add error messages to outbound batch */ + enumerator = batch->create_error_enumerator(batch); + while (enumerator->enumerate(enumerator, &msg)) + { + this->batch->add_msg(this->batch, msg->get_ref(msg)); } + enumerator->destroy(enumerator); + this->mutex->unlock(this->mutex); } else { - if (libtnc_tncc_ReceiveBatch(this->tncc_connection, buf, buflen) != - TNC_RESULT_SUCCESS) + enumerator = batch->create_msg_enumerator(batch); + while (enumerator->enumerate(enumerator, &msg)) { - DBG1(DBG_TNC, "TNCC ReceiveBatch failed"); + handle_message(this, msg); + } + enumerator->destroy(enumerator); + + /* received any TNCCS-Error messages */ + if (this->fatal_error) + { + DBG1(DBG_TNC, "a fatal TNCCS-Error occurred, terminating connection"); + batch->destroy(batch); return FAILED; } + + if (this->is_server) + { + charon->imvs->batch_ending(charon->imvs, this->connection_id); + } + else + { + charon->imcs->batch_ending(charon->imcs, this->connection_id); + } } + batch->destroy(batch); + return NEED_MORE; } -METHOD(tls_t, build, status_t, - private_tnccs_11_t *this, void *buf, size_t *buflen, size_t *msglen) +/** + * Add a recommendation message if a final recommendation is available + */ +static void check_and_build_recommendation(private_tnccs_11_t *this) { - chunk_t batch; - u_int32_t conn_id; - size_t len; + TNC_IMV_Action_Recommendation rec; + TNC_IMV_Evaluation_Result eval; + TNC_IMVID id; + chunk_t reason, language; + enumerator_t *enumerator; + tnccs_msg_t *msg; - if (!this->is_server && !this->tncc_connection) + if (!this->recs->have_recommendation(this->recs, &rec, &eval)) + { + charon->imvs->solicit_recommendation(charon->imvs, this->connection_id); + } + if (this->recs->have_recommendation(this->recs, &rec, &eval)) { - this->tncc_connection = libtnc_tncc_CreateConnection(NULL); - if (!this->tncc_connection) + if (!this->batch) { - DBG1(DBG_TNC, "TNCC CreateConnection failed"); - return FAILED; + this->batch = tnccs_batch_create(this->is_server, ++this->batch_id); } - DBG1(DBG_TNC, "assigned TNCC Connection ID %u", - this->tncc_connection->connectionID); - if (libtnc_tncc_BeginSession(this->tncc_connection) != TNC_RESULT_SUCCESS) + + msg = tnccs_recommendation_msg_create(rec); + this->batch->add_msg(this->batch, msg); + + /* currently we just send the first Reason String */ + enumerator = this->recs->create_reason_enumerator(this->recs); + if (enumerator->enumerate(enumerator, &id, &reason, &language)) { - DBG1(DBG_TNC, "TNCC BeginSession failed"); - return FAILED; + msg = tnccs_reason_strings_msg_create(reason, language); + this->batch->add_msg(this->batch, msg); } + enumerator->destroy(enumerator); + + /* we have reache the final state */ + this->delete_state = TRUE; } - conn_id = this->is_server ? this->tncs_connection->connectionID - : this->tncc_connection->connectionID; - - if (!retrieve_batch(conn_id, &batch)) +} + +METHOD(tls_t, build, status_t, + private_tnccs_11_t *this, void *buf, size_t *buflen, size_t *msglen) +{ + status_t status; + + /* Initialize the connection */ + if (!this->is_server && !this->connection_id) { - return FAILED; + tnccs_msg_t *msg; + char *pref_lang; + + this->connection_id = charon->tnccs->create_connection(charon->tnccs, + (tnccs_t*)this, _send_msg, + &this->request_handshake_retry, NULL); + if (!this->connection_id) + { + return FAILED; + } + + /* Create TNCCS-PreferredLanguage message */ + pref_lang = charon->imcs->get_preferred_language(charon->imcs); + msg = tnccs_preferred_language_msg_create(pref_lang); + this->mutex->lock(this->mutex); + this->batch = tnccs_batch_create(this->is_server, ++this->batch_id); + this->batch->add_msg(this->batch, msg); + this->mutex->unlock(this->mutex); + + charon->imcs->notify_connection_change(charon->imcs, + this->connection_id, TNC_CONNECTION_STATE_CREATE); + charon->imcs->notify_connection_change(charon->imcs, + this->connection_id, TNC_CONNECTION_STATE_HANDSHAKE); + charon->imcs->begin_handshake(charon->imcs, this->connection_id); } - len = *buflen; - len = min(len, batch.len); - *buflen = len; - if (msglen) + + /* Do not allow any asynchronous IMCs or IMVs to add additional messages */ + this->mutex->lock(this->mutex); + + if (this->is_server && !this->delete_state && + (!this->batch || this->fatal_error)) { - *msglen = batch.len; + check_and_build_recommendation(this); } - if (batch.len) + if (this->batch) { + chunk_t data; + + this->batch->build(this->batch); + data = this->batch->get_encoding(this->batch); DBG1(DBG_TNC, "sending TNCCS Batch (%d bytes) for Connection ID %u", - batch.len, conn_id); - DBG3(DBG_TNC, "%.*s", batch.len, batch.ptr); - memcpy(buf, batch.ptr, len); - free_batch(conn_id); - return ALREADY_DONE; + data.len, this->connection_id); + DBG3(DBG_TNC, "%.*s", data.len, data.ptr); + *msglen = data.len; + + if (data.len > *buflen) + { + DBG1(DBG_TNC, "fragmentation of TNCCS batch not supported yet"); + } + else + { + *buflen = data.len; + } + memcpy(buf, data.ptr, *buflen); + this->batch->destroy(this->batch); + this->batch = NULL; + status = ALREADY_DONE; } else { - return INVALID_STATE; + DBG1(DBG_TNC, "no TNCCS Batch to send"); + status = INVALID_STATE; } + this->mutex->unlock(this->mutex); + + return status; } METHOD(tls_t, is_server, bool, @@ -237,39 +432,14 @@ METHOD(tls_t, is_complete, bool, { TNC_IMV_Action_Recommendation rec; TNC_IMV_Evaluation_Result eval; - char *group; - identification_t *id; - ike_sa_t *ike_sa; - auth_cfg_t *auth; - - if (libtnc_tncs_HaveRecommendation(this->tncs_connection, &rec, &eval) == - TNC_RESULT_SUCCESS) + + if (this->recs && this->recs->have_recommendation(this->recs, &rec, &eval)) { - switch (rec) - { - case TNC_IMV_ACTION_RECOMMENDATION_ALLOW: - DBG1(DBG_TNC, "TNC recommendation is allow"); - group = "allow"; - break; - case TNC_IMV_ACTION_RECOMMENDATION_ISOLATE: - DBG1(DBG_TNC, "TNC recommendation is isolate"); - group = "isolate"; - break; - case TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS: - case TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION: - default: - DBG1(DBG_TNC, "TNC recommendation is none"); - return FALSE; - } - ike_sa = charon->bus->get_sa(charon->bus); - if (ike_sa) - { - auth = ike_sa->get_auth_cfg(ike_sa, FALSE); - id = identification_create_from_string(group); - auth->add(auth, AUTH_RULE_GROUP, id); - DBG1(DBG_TNC, "added group membership '%s' based on TNC recommendation", group); - } - return TRUE; + DBG2(DBG_TNC, "Final recommendation is '%N' and evaluation is '%N'", + TNC_IMV_Action_Recommendation_names, rec, + TNC_IMV_Evaluation_Result_names, eval); + + return charon->imvs->enforce_recommendation(charon->imvs, rec); } else { @@ -288,19 +458,17 @@ METHOD(tls_t, destroy, void, { if (this->is_server) { - if (this->tncs_connection) - { - libtnc_tncs_DeleteConnection(this->tncs_connection); - } + charon->imvs->notify_connection_change(charon->imvs, + this->connection_id, TNC_CONNECTION_STATE_DELETE); } else { - if (this->tncc_connection) - { - libtnc_tncc_DeleteConnection(this->tncc_connection); - } - libtnc_tncc_Terminate(); + charon->imcs->notify_connection_change(charon->imcs, + this->connection_id, TNC_CONNECTION_STATE_DELETE); } + charon->tnccs->remove_connection(charon->tnccs, this->connection_id); + this->mutex->destroy(this->mutex); + DESTROY_IF(this->batch); free(this); } @@ -322,6 +490,7 @@ tls_t *tnccs_11_create(bool is_server) .destroy = _destroy, }, .is_server = is_server, + .mutex = mutex_create(MUTEX_TYPE_DEFAULT), ); return &this->public; diff --git a/src/libcharon/plugins/tnccs_20/Makefile.am b/src/libcharon/plugins/tnccs_20/Makefile.am index 3018121e3..d72fd3e34 100644 --- a/src/libcharon/plugins/tnccs_20/Makefile.am +++ b/src/libcharon/plugins/tnccs_20/Makefile.am @@ -1,21 +1,28 @@ INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ - -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/libtls \ - `xml2-config --cflags` + -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/libtls AM_CFLAGS = -rdynamic -libstrongswan_tnccs_20_la_LIBADD = -ltnc - if MONOLITHIC noinst_LTLIBRARIES = libstrongswan-tnccs-20.la else plugin_LTLIBRARIES = libstrongswan-tnccs-20.la -libstrongswan_tnccs_20_la_LIBADD += $(top_builddir)/src/libtls/libtls.la +libstrongswan_tnccs_20_la_LIBADD = $(top_builddir)/src/libtls/libtls.la endif libstrongswan_tnccs_20_la_SOURCES = \ - tnccs_20_plugin.h tnccs_20_plugin.c tnccs_20.h tnccs_20.c + tnccs_20_plugin.h tnccs_20_plugin.c tnccs_20.h tnccs_20.c \ + batch/pb_tnc_batch.h batch/pb_tnc_batch.c \ + messages/pb_tnc_msg.h messages/pb_tnc_msg.c \ + messages/pb_experimental_msg.h messages/pb_experimental_msg.c \ + messages/pb_pa_msg.h messages/pb_pa_msg.c \ + messages/pb_assessment_result_msg.h messages/pb_assessment_result_msg.c \ + messages/pb_access_recommendation_msg.h messages/pb_access_recommendation_msg.c \ + messages/pb_error_msg.h messages/pb_error_msg.c \ + messages/pb_language_preference_msg.h messages/pb_language_preference_msg.c \ + messages/pb_reason_string_msg.h messages/pb_reason_string_msg.c \ + messages/pb_remediation_parameters_msg.h messages/pb_remediation_parameters_msg.c \ + state_machine/pb_tnc_state_machine.h state_machine/pb_tnc_state_machine.c libstrongswan_tnccs_20_la_LDFLAGS = -module -avoid-version - diff --git a/src/libcharon/plugins/tnccs_20/Makefile.in b/src/libcharon/plugins/tnccs_20/Makefile.in index 6101f91df..9853be338 100644 --- a/src/libcharon/plugins/tnccs_20/Makefile.in +++ b/src/libcharon/plugins/tnccs_20/Makefile.in @@ -34,7 +34,6 @@ PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ -@MONOLITHIC_FALSE@am__append_1 = $(top_builddir)/src/libtls/libtls.la subdir = src/libcharon/plugins/tnccs_20 DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -75,8 +74,14 @@ am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__installdirs = "$(DESTDIR)$(plugindir)" LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES) -libstrongswan_tnccs_20_la_DEPENDENCIES = $(am__append_1) -am_libstrongswan_tnccs_20_la_OBJECTS = tnccs_20_plugin.lo tnccs_20.lo +@MONOLITHIC_FALSE@libstrongswan_tnccs_20_la_DEPENDENCIES = \ +@MONOLITHIC_FALSE@ $(top_builddir)/src/libtls/libtls.la +am_libstrongswan_tnccs_20_la_OBJECTS = tnccs_20_plugin.lo tnccs_20.lo \ + pb_tnc_batch.lo pb_tnc_msg.lo pb_experimental_msg.lo \ + pb_pa_msg.lo pb_assessment_result_msg.lo \ + pb_access_recommendation_msg.lo pb_error_msg.lo \ + pb_language_preference_msg.lo pb_reason_string_msg.lo \ + pb_remediation_parameters_msg.lo pb_tnc_state_machine.lo libstrongswan_tnccs_20_la_OBJECTS = \ $(am_libstrongswan_tnccs_20_la_OBJECTS) libstrongswan_tnccs_20_la_LINK = $(LIBTOOL) --tag=CC \ @@ -223,9 +228,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -264,6 +267,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ @@ -275,15 +280,25 @@ urandom_device = @urandom_device@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ - -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/libtls \ - `xml2-config --cflags` + -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/libtls AM_CFLAGS = -rdynamic -libstrongswan_tnccs_20_la_LIBADD = -ltnc $(am__append_1) @MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-tnccs-20.la @MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-tnccs-20.la +@MONOLITHIC_FALSE@libstrongswan_tnccs_20_la_LIBADD = $(top_builddir)/src/libtls/libtls.la libstrongswan_tnccs_20_la_SOURCES = \ - tnccs_20_plugin.h tnccs_20_plugin.c tnccs_20.h tnccs_20.c + tnccs_20_plugin.h tnccs_20_plugin.c tnccs_20.h tnccs_20.c \ + batch/pb_tnc_batch.h batch/pb_tnc_batch.c \ + messages/pb_tnc_msg.h messages/pb_tnc_msg.c \ + messages/pb_experimental_msg.h messages/pb_experimental_msg.c \ + messages/pb_pa_msg.h messages/pb_pa_msg.c \ + messages/pb_assessment_result_msg.h messages/pb_assessment_result_msg.c \ + messages/pb_access_recommendation_msg.h messages/pb_access_recommendation_msg.c \ + messages/pb_error_msg.h messages/pb_error_msg.c \ + messages/pb_language_preference_msg.h messages/pb_language_preference_msg.c \ + messages/pb_reason_string_msg.h messages/pb_reason_string_msg.c \ + messages/pb_remediation_parameters_msg.h messages/pb_remediation_parameters_msg.c \ + state_machine/pb_tnc_state_machine.h state_machine/pb_tnc_state_machine.c libstrongswan_tnccs_20_la_LDFLAGS = -module -avoid-version all: all-am @@ -369,6 +384,17 @@ mostlyclean-compile: distclean-compile: -rm -f *.tab.c +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pb_access_recommendation_msg.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pb_assessment_result_msg.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pb_error_msg.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pb_experimental_msg.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pb_language_preference_msg.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pb_pa_msg.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pb_reason_string_msg.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pb_remediation_parameters_msg.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pb_tnc_batch.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pb_tnc_msg.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pb_tnc_state_machine.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnccs_20.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnccs_20_plugin.Plo@am__quote@ @@ -393,6 +419,83 @@ distclean-compile: @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< +pb_tnc_batch.lo: batch/pb_tnc_batch.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pb_tnc_batch.lo -MD -MP -MF $(DEPDIR)/pb_tnc_batch.Tpo -c -o pb_tnc_batch.lo `test -f 'batch/pb_tnc_batch.c' || echo '$(srcdir)/'`batch/pb_tnc_batch.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pb_tnc_batch.Tpo $(DEPDIR)/pb_tnc_batch.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='batch/pb_tnc_batch.c' object='pb_tnc_batch.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o pb_tnc_batch.lo `test -f 'batch/pb_tnc_batch.c' || echo '$(srcdir)/'`batch/pb_tnc_batch.c + +pb_tnc_msg.lo: messages/pb_tnc_msg.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pb_tnc_msg.lo -MD -MP -MF $(DEPDIR)/pb_tnc_msg.Tpo -c -o pb_tnc_msg.lo `test -f 'messages/pb_tnc_msg.c' || echo '$(srcdir)/'`messages/pb_tnc_msg.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pb_tnc_msg.Tpo $(DEPDIR)/pb_tnc_msg.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='messages/pb_tnc_msg.c' object='pb_tnc_msg.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o pb_tnc_msg.lo `test -f 'messages/pb_tnc_msg.c' || echo '$(srcdir)/'`messages/pb_tnc_msg.c + +pb_experimental_msg.lo: messages/pb_experimental_msg.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pb_experimental_msg.lo -MD -MP -MF $(DEPDIR)/pb_experimental_msg.Tpo -c -o pb_experimental_msg.lo `test -f 'messages/pb_experimental_msg.c' || echo '$(srcdir)/'`messages/pb_experimental_msg.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pb_experimental_msg.Tpo $(DEPDIR)/pb_experimental_msg.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='messages/pb_experimental_msg.c' object='pb_experimental_msg.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o pb_experimental_msg.lo `test -f 'messages/pb_experimental_msg.c' || echo '$(srcdir)/'`messages/pb_experimental_msg.c + +pb_pa_msg.lo: messages/pb_pa_msg.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pb_pa_msg.lo -MD -MP -MF $(DEPDIR)/pb_pa_msg.Tpo -c -o pb_pa_msg.lo `test -f 'messages/pb_pa_msg.c' || echo '$(srcdir)/'`messages/pb_pa_msg.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pb_pa_msg.Tpo $(DEPDIR)/pb_pa_msg.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='messages/pb_pa_msg.c' object='pb_pa_msg.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o pb_pa_msg.lo `test -f 'messages/pb_pa_msg.c' || echo '$(srcdir)/'`messages/pb_pa_msg.c + +pb_assessment_result_msg.lo: messages/pb_assessment_result_msg.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pb_assessment_result_msg.lo -MD -MP -MF $(DEPDIR)/pb_assessment_result_msg.Tpo -c -o pb_assessment_result_msg.lo `test -f 'messages/pb_assessment_result_msg.c' || echo '$(srcdir)/'`messages/pb_assessment_result_msg.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pb_assessment_result_msg.Tpo $(DEPDIR)/pb_assessment_result_msg.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='messages/pb_assessment_result_msg.c' object='pb_assessment_result_msg.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o pb_assessment_result_msg.lo `test -f 'messages/pb_assessment_result_msg.c' || echo '$(srcdir)/'`messages/pb_assessment_result_msg.c + +pb_access_recommendation_msg.lo: messages/pb_access_recommendation_msg.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pb_access_recommendation_msg.lo -MD -MP -MF $(DEPDIR)/pb_access_recommendation_msg.Tpo -c -o pb_access_recommendation_msg.lo `test -f 'messages/pb_access_recommendation_msg.c' || echo '$(srcdir)/'`messages/pb_access_recommendation_msg.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pb_access_recommendation_msg.Tpo $(DEPDIR)/pb_access_recommendation_msg.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='messages/pb_access_recommendation_msg.c' object='pb_access_recommendation_msg.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o pb_access_recommendation_msg.lo `test -f 'messages/pb_access_recommendation_msg.c' || echo '$(srcdir)/'`messages/pb_access_recommendation_msg.c + +pb_error_msg.lo: messages/pb_error_msg.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pb_error_msg.lo -MD -MP -MF $(DEPDIR)/pb_error_msg.Tpo -c -o pb_error_msg.lo `test -f 'messages/pb_error_msg.c' || echo '$(srcdir)/'`messages/pb_error_msg.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pb_error_msg.Tpo $(DEPDIR)/pb_error_msg.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='messages/pb_error_msg.c' object='pb_error_msg.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o pb_error_msg.lo `test -f 'messages/pb_error_msg.c' || echo '$(srcdir)/'`messages/pb_error_msg.c + +pb_language_preference_msg.lo: messages/pb_language_preference_msg.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pb_language_preference_msg.lo -MD -MP -MF $(DEPDIR)/pb_language_preference_msg.Tpo -c -o pb_language_preference_msg.lo `test -f 'messages/pb_language_preference_msg.c' || echo '$(srcdir)/'`messages/pb_language_preference_msg.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pb_language_preference_msg.Tpo $(DEPDIR)/pb_language_preference_msg.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='messages/pb_language_preference_msg.c' object='pb_language_preference_msg.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o pb_language_preference_msg.lo `test -f 'messages/pb_language_preference_msg.c' || echo '$(srcdir)/'`messages/pb_language_preference_msg.c + +pb_reason_string_msg.lo: messages/pb_reason_string_msg.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pb_reason_string_msg.lo -MD -MP -MF $(DEPDIR)/pb_reason_string_msg.Tpo -c -o pb_reason_string_msg.lo `test -f 'messages/pb_reason_string_msg.c' || echo '$(srcdir)/'`messages/pb_reason_string_msg.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pb_reason_string_msg.Tpo $(DEPDIR)/pb_reason_string_msg.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='messages/pb_reason_string_msg.c' object='pb_reason_string_msg.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o pb_reason_string_msg.lo `test -f 'messages/pb_reason_string_msg.c' || echo '$(srcdir)/'`messages/pb_reason_string_msg.c + +pb_remediation_parameters_msg.lo: messages/pb_remediation_parameters_msg.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pb_remediation_parameters_msg.lo -MD -MP -MF $(DEPDIR)/pb_remediation_parameters_msg.Tpo -c -o pb_remediation_parameters_msg.lo `test -f 'messages/pb_remediation_parameters_msg.c' || echo '$(srcdir)/'`messages/pb_remediation_parameters_msg.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pb_remediation_parameters_msg.Tpo $(DEPDIR)/pb_remediation_parameters_msg.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='messages/pb_remediation_parameters_msg.c' object='pb_remediation_parameters_msg.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o pb_remediation_parameters_msg.lo `test -f 'messages/pb_remediation_parameters_msg.c' || echo '$(srcdir)/'`messages/pb_remediation_parameters_msg.c + +pb_tnc_state_machine.lo: state_machine/pb_tnc_state_machine.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pb_tnc_state_machine.lo -MD -MP -MF $(DEPDIR)/pb_tnc_state_machine.Tpo -c -o pb_tnc_state_machine.lo `test -f 'state_machine/pb_tnc_state_machine.c' || echo '$(srcdir)/'`state_machine/pb_tnc_state_machine.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pb_tnc_state_machine.Tpo $(DEPDIR)/pb_tnc_state_machine.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='state_machine/pb_tnc_state_machine.c' object='pb_tnc_state_machine.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o pb_tnc_state_machine.lo `test -f 'state_machine/pb_tnc_state_machine.c' || echo '$(srcdir)/'`state_machine/pb_tnc_state_machine.c + mostlyclean-libtool: -rm -f *.lo diff --git a/src/libcharon/plugins/tnccs_20/batch/pb_tnc_batch.c b/src/libcharon/plugins/tnccs_20/batch/pb_tnc_batch.c new file mode 100644 index 000000000..3f38543ed --- /dev/null +++ b/src/libcharon/plugins/tnccs_20/batch/pb_tnc_batch.c @@ -0,0 +1,543 @@ +/* + * Copyright (C) 2010 Sansar Choinyanbuu + * Copyright (C) 2010 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 "pb_tnc_batch.h" +#include "messages/pb_error_msg.h" +#include "state_machine/pb_tnc_state_machine.h" + +#include <debug.h> +#include <utils/linked_list.h> +#include <tls_writer.h> +#include <tls_reader.h> +#include <tnc/tnccs/tnccs.h> + +ENUM(pb_tnc_batch_type_names, PB_BATCH_CDATA, PB_BATCH_CLOSE, + "CDATA", + "SDATA", + "RESULT", + "CRETRY", + "SRETRY", + "CLOSE" +); + +typedef struct private_pb_tnc_batch_t private_pb_tnc_batch_t; + +/** + * PB-Batch Header (see section 4.1 of RFC 5793) + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Version |D| Reserved | B-Type| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Batch Length | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define PB_TNC_BATCH_FLAG_NONE 0x00 +#define PB_TNC_BATCH_FLAG_D (1<<7) +#define PB_TNC_BATCH_HEADER_SIZE 8 + +/** + * PB-TNC Message (see section 4.2 of RFC 5793) + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Flags | PB-TNC Vendor ID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | PB-TNC Message Type | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | PB-TNC Message Length | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | PB-TNC Message Value (Variable Length) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define PB_TNC_FLAG_NONE 0x00 +#define PB_TNC_FLAG_NOSKIP (1<<7) +#define PB_TNC_HEADER_SIZE 12 + +#define PB_TNC_RESERVED_MSG_TYPE 0xffffffff + +/** + * Private data of a pb_tnc_batch_t object. + * + */ +struct private_pb_tnc_batch_t { + /** + * Public pb_pa_msg_t interface. + */ + pb_tnc_batch_t public; + + /** + * TNCC if TRUE, TNCS if FALSE + */ + bool is_server; + + /** + * PB-TNC Batch type + */ + pb_tnc_batch_type_t type; + + /** + * linked list of PB-TNC messages + */ + linked_list_t *messages; + + /** + * linked list of PB-TNC error messages + */ + linked_list_t *errors; + + /** + * Encoded message + */ + chunk_t encoding; + + /** + * Offset into encoding (used for error reporting) + */ + u_int32_t offset; +}; + +METHOD(pb_tnc_batch_t, get_type, pb_tnc_batch_type_t, + private_pb_tnc_batch_t *this) +{ + return this->type; +} + +METHOD(pb_tnc_batch_t, get_encoding, chunk_t, + private_pb_tnc_batch_t *this) +{ + return this->encoding; +} + +METHOD(pb_tnc_batch_t, add_msg, void, + private_pb_tnc_batch_t *this, pb_tnc_msg_t* msg) +{ + DBG2(DBG_TNC, "adding %N message", pb_tnc_msg_type_names, + msg->get_type(msg)); + this->messages->insert_last(this->messages, msg); +} + +METHOD(pb_tnc_batch_t, build, void, + private_pb_tnc_batch_t *this) +{ + u_int32_t batch_len, msg_len; + chunk_t msg_value; + enumerator_t *enumerator; + pb_tnc_msg_type_t msg_type; + pb_tnc_msg_t *msg; + tls_writer_t *writer; + + /* compute total PB-TNC batch size by summing over all messages */ + batch_len = PB_TNC_BATCH_HEADER_SIZE; + enumerator = this->messages->create_enumerator(this->messages); + while (enumerator->enumerate(enumerator, &msg)) + { + msg->build(msg); + msg_value = msg->get_encoding(msg); + batch_len += PB_TNC_HEADER_SIZE + msg_value.len; + } + enumerator->destroy(enumerator); + + /* build PB-TNC batch header */ + writer = tls_writer_create(batch_len); + writer->write_uint8 (writer, PB_TNC_VERSION); + writer->write_uint8 (writer, this->is_server ? + PB_TNC_BATCH_FLAG_D : PB_TNC_BATCH_FLAG_NONE); + writer->write_uint16(writer, this->type); + writer->write_uint32(writer, batch_len); + + /* build PB-TNC messages */ + enumerator = this->messages->create_enumerator(this->messages); + while (enumerator->enumerate(enumerator, &msg)) + { + u_int8_t flags = PB_TNC_FLAG_NONE; + + /* build PB-TNC message */ + msg_value = msg->get_encoding(msg); + msg_len = PB_TNC_HEADER_SIZE + msg_value.len; + msg_type = msg->get_type(msg); + if (pb_tnc_msg_infos[msg_type].has_noskip_flag) + { + flags |= PB_TNC_FLAG_NOSKIP; + } + writer->write_uint8 (writer, flags); + writer->write_uint24(writer, IETF_VENDOR_ID); + writer->write_uint32(writer, msg_type); + writer->write_uint32(writer, msg_len); + writer->write_data (writer, msg_value); + } + enumerator->destroy(enumerator); + + this->encoding = chunk_clone(writer->get_buf(writer)); + writer->destroy(writer); +} + +static status_t process_batch_header(private_pb_tnc_batch_t *this, + pb_tnc_state_machine_t *state_machine) +{ + tls_reader_t *reader; + pb_tnc_msg_t *msg; + pb_error_msg_t *err_msg; + u_int8_t version, flags, reserved, type; + u_int32_t batch_len; + bool directionality; + + if (this->encoding.len < PB_TNC_BATCH_HEADER_SIZE) + { + DBG1(DBG_TNC, "%u bytes insufficient to parse PB-TNC batch header", + this->encoding.len); + msg = pb_error_msg_create_with_offset(TRUE, IETF_VENDOR_ID, + PB_ERROR_INVALID_PARAMETER, 0); + goto fatal; + } + + reader = tls_reader_create(this->encoding); + reader->read_uint8 (reader, &version); + reader->read_uint8 (reader, &flags); + reader->read_uint8 (reader, &reserved); + reader->read_uint8 (reader, &type); + reader->read_uint32(reader, &batch_len); + reader->destroy(reader); + + /* Version */ + if (version != PB_TNC_VERSION) + { + DBG1(DBG_TNC, "unsupported TNCCS batch version 0x%01x", version); + msg = pb_error_msg_create(TRUE, IETF_VENDOR_ID, + PB_ERROR_VERSION_NOT_SUPPORTED); + err_msg = (pb_error_msg_t*)msg; + err_msg->set_bad_version(err_msg, version); + goto fatal; + } + + /* Directionality */ + directionality = (flags & PB_TNC_BATCH_FLAG_D) != PB_TNC_BATCH_FLAG_NONE; + if (directionality == this->is_server) + { + DBG1(DBG_TNC, "wrong Directionality: batch is from a PB %s", + directionality ? "server" : "client"); + msg = pb_error_msg_create_with_offset(TRUE, IETF_VENDOR_ID, + PB_ERROR_INVALID_PARAMETER, 1); + goto fatal; + } + + /* Batch Type */ + this->type = type & 0x0F; + if (this->type > PB_BATCH_ROOF) + { + DBG1(DBG_TNC, "unknown PB-TNC batch type: %d", this->type); + msg = pb_error_msg_create_with_offset(TRUE, IETF_VENDOR_ID, + PB_ERROR_INVALID_PARAMETER, 3); + goto fatal; + } + + if (!state_machine->receive_batch(state_machine, this->type)) + { + DBG1(DBG_TNC, "unexpected PB-TNC batch type: %N", + pb_tnc_batch_type_names, this->type); + msg = pb_error_msg_create(TRUE, IETF_VENDOR_ID, + PB_ERROR_UNEXPECTED_BATCH_TYPE); + goto fatal; + } + + /* Batch Length */ + if (this->encoding.len != batch_len) + { + DBG1(DBG_TNC, "%u bytes of data is not equal to batch length of %u bytes", + this->encoding.len, batch_len); + msg = pb_error_msg_create_with_offset(TRUE, IETF_VENDOR_ID, + PB_ERROR_INVALID_PARAMETER, 4); + goto fatal; + } + + this->offset = PB_TNC_BATCH_HEADER_SIZE; + return SUCCESS; + +fatal: + this->errors->insert_last(this->errors, msg); + return FAILED; +} + +static status_t process_tnc_msg(private_pb_tnc_batch_t *this) +{ + tls_reader_t *reader; + pb_tnc_msg_t *pb_tnc_msg, *msg; + u_int8_t flags; + u_int32_t vendor_id, msg_type, msg_len, offset; + chunk_t data, msg_value; + bool noskip_flag; + status_t status; + + data = chunk_skip(this->encoding, this->offset); + + if (data.len < PB_TNC_HEADER_SIZE) + { + DBG1(DBG_TNC, "%u bytes insufficient to parse PB-TNC message header", + data.len); + msg = pb_error_msg_create_with_offset(TRUE, IETF_VENDOR_ID, + PB_ERROR_INVALID_PARAMETER, this->offset); + goto fatal; + } + + reader = tls_reader_create(data); + reader->read_uint8 (reader, &flags); + reader->read_uint24(reader, &vendor_id); + reader->read_uint32(reader, &msg_type); + reader->read_uint32(reader, &msg_len); + reader->destroy(reader); + + noskip_flag = (flags & PB_TNC_FLAG_NOSKIP) != PB_TNC_FLAG_NONE; + + if (msg_len > data.len) + { + DBG1(DBG_TNC, "%u bytes insufficient to parse PB-TNC message", data.len); + msg = pb_error_msg_create_with_offset(TRUE, IETF_VENDOR_ID, + PB_ERROR_INVALID_PARAMETER, this->offset + 8); + goto fatal; + } + + if (vendor_id == RESERVED_VENDOR_ID) + { + DBG1(DBG_TNC, "Vendor ID 0x%06x is reserved", RESERVED_VENDOR_ID); + msg = pb_error_msg_create_with_offset(TRUE, IETF_VENDOR_ID, + PB_ERROR_INVALID_PARAMETER, this->offset + 1); + goto fatal; + + } + + if (msg_type == PB_TNC_RESERVED_MSG_TYPE) + { + DBG1(DBG_TNC, "PB-TNC message Type 0x%08x is reserved", + PB_TNC_RESERVED_MSG_TYPE); + msg = pb_error_msg_create_with_offset(TRUE, IETF_VENDOR_ID, + PB_ERROR_INVALID_PARAMETER, this->offset + 4); + goto fatal; + } + + + if (vendor_id != IETF_VENDOR_ID || msg_type > PB_MSG_ROOF) + { + if (msg_len < PB_TNC_HEADER_SIZE) + { + DBG1(DBG_TNC, "%u bytes too small for PB-TNC message length", + msg_len); + msg = pb_error_msg_create_with_offset(TRUE, IETF_VENDOR_ID, + PB_ERROR_INVALID_PARAMETER, this->offset + 8); + goto fatal; + } + + if (noskip_flag) + { + DBG1(DBG_TNC, "reject PB-TNC message (Vendor ID 0x%06x / " + "Type 0x%08x)", vendor_id, msg_type); + msg = pb_error_msg_create_with_offset(TRUE, IETF_VENDOR_ID, + PB_ERROR_UNSUPPORTED_MANDATORY_MSG, this->offset); + goto fatal; + } + else + { + DBG1(DBG_TNC, "ignore PB-TNC message (Vendor ID 0x%06x / " + "Type 0x%08x)", vendor_id, msg_type); + this->offset += msg_len; + return SUCCESS; + } + } + else + { + if (pb_tnc_msg_infos[msg_type].has_noskip_flag != TRUE_OR_FALSE && + pb_tnc_msg_infos[msg_type].has_noskip_flag != noskip_flag) + { + DBG1(DBG_TNC, "%N message must%s have NOSKIP flag set", + pb_tnc_msg_type_names, msg_type, + pb_tnc_msg_infos[msg_type].has_noskip_flag ? "" : " not"); + msg = pb_error_msg_create_with_offset(TRUE, IETF_VENDOR_ID, + PB_ERROR_INVALID_PARAMETER, this->offset); + goto fatal; + } + + if (msg_len < pb_tnc_msg_infos[msg_type].min_size || + (pb_tnc_msg_infos[msg_type].exact_size && + msg_len != pb_tnc_msg_infos[msg_type].min_size)) + { + DBG1(DBG_TNC, "%N message length must be %s %u bytes but is %u bytes", + pb_tnc_msg_type_names, msg_type, + pb_tnc_msg_infos[msg_type].exact_size ? "exactly" : "at least", + pb_tnc_msg_infos[msg_type].min_size, msg_len); + msg = pb_error_msg_create_with_offset(TRUE, IETF_VENDOR_ID, + PB_ERROR_INVALID_PARAMETER, this->offset); + goto fatal; + } + } + + if (pb_tnc_msg_infos[msg_type].in_result_batch && + this->type != PB_BATCH_RESULT) + { + if (this->is_server) + { + DBG1(DBG_TNC,"reject %N message received from a PB-TNC client", + pb_tnc_msg_type_names, msg_type); + msg = pb_error_msg_create_with_offset(TRUE, IETF_VENDOR_ID, + PB_ERROR_INVALID_PARAMETER, this->offset); + goto fatal; + } + else + { + DBG1(DBG_TNC,"ignore %N message not received within RESULT batch", + pb_tnc_msg_type_names, msg_type); + this->offset += msg_len; + return SUCCESS; + } + } + + DBG2(DBG_TNC, "processing %N message (%u bytes)", pb_tnc_msg_type_names, + msg_type, msg_len); + data.len = msg_len; + msg_value = chunk_skip(data, PB_TNC_HEADER_SIZE); + pb_tnc_msg = pb_tnc_msg_create_from_data(msg_type, msg_value); + + status = pb_tnc_msg->process(pb_tnc_msg, &offset); + if (status == FAILED || status == VERIFY_ERROR) + { + msg = pb_error_msg_create_with_offset(TRUE, IETF_VENDOR_ID, + PB_ERROR_INVALID_PARAMETER, this->offset); + this->errors->insert_last(this->errors, msg); + } + if (status == FAILED) + { + pb_tnc_msg->destroy(pb_tnc_msg); + return FAILED; + } + this->messages->insert_last(this->messages, pb_tnc_msg); + this->offset += msg_len; + return status; + +fatal: + this->errors->insert_last(this->errors, msg); + return FAILED; +} + +METHOD(pb_tnc_batch_t, process, status_t, + private_pb_tnc_batch_t *this, pb_tnc_state_machine_t *state_machine) +{ + status_t status; + + status = process_batch_header(this, state_machine); + if (status != SUCCESS) + { + return FAILED; + } + DBG1(DBG_TNC, "processing PB-TNC %N batch", pb_tnc_batch_type_names, + this->type); + while (this->offset < this->encoding.len) + { + switch (process_tnc_msg(this)) + { + case FAILED: + return FAILED; + case VERIFY_ERROR: + status = VERIFY_ERROR; + break; + case SUCCESS: + default: + break; + } + } + return status; +} + +METHOD(pb_tnc_batch_t, create_msg_enumerator, enumerator_t*, + private_pb_tnc_batch_t *this) +{ + return this->messages->create_enumerator(this->messages); +} + +METHOD(pb_tnc_batch_t, create_error_enumerator, enumerator_t*, + private_pb_tnc_batch_t *this) +{ + return this->errors->create_enumerator(this->errors); +} + +METHOD(pb_tnc_batch_t, destroy, void, + private_pb_tnc_batch_t *this) +{ + this->messages->destroy_offset(this->messages, + offsetof(pb_tnc_msg_t, destroy)); + this->errors->destroy_offset(this->errors, + offsetof(pb_tnc_msg_t, destroy)); + free(this->encoding.ptr); + free(this); +} + +/** + * See header + */ +pb_tnc_batch_t* pb_tnc_batch_create(bool is_server, pb_tnc_batch_type_t type) +{ + private_pb_tnc_batch_t *this; + + INIT(this, + .public = { + .get_type = _get_type, + .get_encoding = _get_encoding, + .add_msg = _add_msg, + .build = _build, + .process = _process, + .create_msg_enumerator = _create_msg_enumerator, + .create_error_enumerator = _create_error_enumerator, + .destroy = _destroy, + }, + .is_server = is_server, + .type = type, + .messages = linked_list_create(), + .errors = linked_list_create(), + ); + + DBG2(DBG_TNC, "creating PB-TNC %N batch", pb_tnc_batch_type_names, type); + + return &this->public; +} + +/** + * See header + */ +pb_tnc_batch_t* pb_tnc_batch_create_from_data(bool is_server, chunk_t data) +{ + private_pb_tnc_batch_t *this; + + INIT(this, + .public = { + .get_type = _get_type, + .get_encoding = _get_encoding, + .add_msg = _add_msg, + .build = _build, + .process = _process, + .create_msg_enumerator = _create_msg_enumerator, + .create_error_enumerator = _create_error_enumerator, + .destroy = _destroy, + }, + .is_server = is_server, + .messages = linked_list_create(), + .errors = linked_list_create(), + .encoding = chunk_clone(data), + ); + + return &this->public; +} + diff --git a/src/libcharon/plugins/tnccs_20/batch/pb_tnc_batch.h b/src/libcharon/plugins/tnccs_20/batch/pb_tnc_batch.h new file mode 100644 index 000000000..17e5fff4c --- /dev/null +++ b/src/libcharon/plugins/tnccs_20/batch/pb_tnc_batch.h @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2010 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. + */ + +/** + * @defgroup pb_tnc_batch pb_tnc_batch + * @{ @ingroup tnccs_20 + */ + +#ifndef PB_TNC_BATCH_H_ +#define PB_TNC_BATCH_H_ + +typedef enum pb_tnc_batch_type_t pb_tnc_batch_type_t; +typedef struct pb_tnc_batch_t pb_tnc_batch_t; + +#include "messages/pb_tnc_msg.h" +#include "state_machine/pb_tnc_state_machine.h" + +#include <library.h> + +/** + * PB-TNC Batch Types as defined in section 4.1 of RFC 5793 + */ +enum pb_tnc_batch_type_t { + PB_BATCH_CDATA = 1, + PB_BATCH_SDATA = 2, + PB_BATCH_RESULT = 3, + PB_BATCH_CRETRY = 4, + PB_BATCH_SRETRY = 5, + PB_BATCH_CLOSE = 6, + PB_BATCH_ROOF = 6 +}; + +/** + * enum name for pb_tnc_batch_type_t. + */ +extern enum_name_t *pb_tnc_batch_type_names; + +/** + * Interface for all PB-TNC Batch Types. + */ +struct pb_tnc_batch_t { + + /** + * Get the PB-TNC Message Type + * + * @return PB-TNC batch type + */ + pb_tnc_batch_type_t (*get_type)(pb_tnc_batch_t *this); + + /** + * Get the encoding of the PB-TNC Batch + * + * @return encoded PB-TNC batch + */ + chunk_t (*get_encoding)(pb_tnc_batch_t *this); + + /** + * Add a PB-TNC Message + * + * @param msg PB-TNC message to be addedd + */ + void (*add_msg)(pb_tnc_batch_t *this, pb_tnc_msg_t* msg); + + /** + * Build the PB-TNC Batch + */ + void (*build)(pb_tnc_batch_t *this); + + /** + * Process the PB-TNC Batch + * + * @param PB-TNC state machine + * @return return processing status + */ + status_t (*process)(pb_tnc_batch_t *this, + pb_tnc_state_machine_t *state_machine); + + /** + * Enumerates over all PB-TNC Messages + * + * @return return message enumerator + */ + enumerator_t* (*create_msg_enumerator)(pb_tnc_batch_t *this); + + /** + * Enumerates over all parsing errors + * + * @return return error enumerator + */ + enumerator_t* (*create_error_enumerator)(pb_tnc_batch_t *this); + + /** + * Destroys a pb_tnc_batch_t object. + */ + void (*destroy)(pb_tnc_batch_t *this); +}; + +/** + * Create an empty PB-TNC Batch of a given type + * + * @param is_server TRUE if server, FALSE if client + * @param type PB-TNC batch type + */ +pb_tnc_batch_t* pb_tnc_batch_create(bool is_server, pb_tnc_batch_type_t type); + +/** + * Create an unprocessed PB-TNC Batch from data + * + * @param is_server TRUE if server, FALSE if client + * @param data encoded PB-TNC batch + */ +pb_tnc_batch_t* pb_tnc_batch_create_from_data(bool is_server, chunk_t data); + +#endif /** PB_TNC_BATCH_H_ @}*/ diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_access_recommendation_msg.c b/src/libcharon/plugins/tnccs_20/messages/pb_access_recommendation_msg.c new file mode 100644 index 000000000..41b9e31f6 --- /dev/null +++ b/src/libcharon/plugins/tnccs_20/messages/pb_access_recommendation_msg.c @@ -0,0 +1,180 @@ +/* + * Copyright (C) 2010 Sansar Choinyambuu + * 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 "pb_access_recommendation_msg.h" + +#include <tls_writer.h> +#include <tls_reader.h> +#include <debug.h> + +ENUM(pb_access_recommendation_code_names, PB_REC_ACCESS_ALLOWED, PB_REC_QUARANTINED, + "Access Allowed", + "Access Denied", + "Quarantined" +); + +typedef struct private_pb_access_recommendation_msg_t private_pb_access_recommendation_msg_t; + +/** + * PB-Access-Recommendation message (see section 4.7 of RFC 5793) + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Reserved | Access Recommendation Code | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define ACCESS_RECOMMENDATION_RESERVED 0x0000 +#define ACCESS_RECOMMENDATION_MSG_SIZE 4 +/** + * Private data of a pb_access_recommendation_msg_t object. + * + */ +struct private_pb_access_recommendation_msg_t { + /** + * Public pb_access_recommendation_msg_t interface. + */ + pb_access_recommendation_msg_t public; + + /** + * PB-TNC message type + */ + pb_tnc_msg_type_t type; + + /** + * Access recommendation code + */ + u_int16_t recommendation; + + /** + * Encoded message + */ + chunk_t encoding; +}; + +METHOD(pb_tnc_msg_t, get_type, pb_tnc_msg_type_t, + private_pb_access_recommendation_msg_t *this) +{ + return this->type; +} + +METHOD(pb_tnc_msg_t, get_encoding, chunk_t, + private_pb_access_recommendation_msg_t *this) +{ + return this->encoding; +} + +METHOD(pb_tnc_msg_t, build, void, + private_pb_access_recommendation_msg_t *this) +{ + tls_writer_t *writer; + + /* build message */ + writer = tls_writer_create(ACCESS_RECOMMENDATION_MSG_SIZE); + writer->write_uint16(writer, ACCESS_RECOMMENDATION_RESERVED); + writer->write_uint16(writer, this->recommendation); + free(this->encoding.ptr); + this->encoding = writer->get_buf(writer); + this->encoding = chunk_clone(this->encoding); + writer->destroy(writer); +} + +METHOD(pb_tnc_msg_t, process, status_t, + private_pb_access_recommendation_msg_t *this, u_int32_t *offset) +{ + tls_reader_t *reader; + u_int16_t reserved; + + /* process message */ + reader = tls_reader_create(this->encoding); + reader->read_uint16(reader, &reserved); + reader->read_uint16(reader, &this->recommendation); + reader->destroy(reader); + + if (this->recommendation < PB_REC_ACCESS_ALLOWED || + this->recommendation > PB_REC_QUARANTINED) + { + DBG1(DBG_TNC, "invalid access recommendation code (%u)", + this->recommendation); + *offset = 2; + return FAILED; + } + + return SUCCESS; +} + +METHOD(pb_tnc_msg_t, destroy, void, + private_pb_access_recommendation_msg_t *this) +{ + free(this->encoding.ptr); + free(this); +} + +METHOD(pb_access_recommendation_msg_t, get_access_recommendation, u_int16_t, + private_pb_access_recommendation_msg_t *this) +{ + return this->recommendation; +} + +/** + * See header + */ +pb_tnc_msg_t *pb_access_recommendation_msg_create_from_data(chunk_t data) +{ + private_pb_access_recommendation_msg_t *this; + + INIT(this, + .public = { + .pb_interface = { + .get_type = _get_type, + .get_encoding = _get_encoding, + .build = _build, + .process = _process, + .destroy = _destroy, + }, + .get_access_recommendation = _get_access_recommendation, + }, + .type = PB_MSG_ACCESS_RECOMMENDATION, + .encoding = chunk_clone(data), + ); + + return &this->public.pb_interface; +} + +/** + * See header + */ +pb_tnc_msg_t *pb_access_recommendation_msg_create(u_int16_t recommendation) +{ + private_pb_access_recommendation_msg_t *this; + + INIT(this, + .public = { + .pb_interface = { + .get_type = _get_type, + .get_encoding = _get_encoding, + .build = _build, + .process = _process, + .destroy = _destroy, + }, + .get_access_recommendation = _get_access_recommendation, + }, + .type = PB_MSG_ACCESS_RECOMMENDATION, + .recommendation = recommendation, + ); + + return &this->public.pb_interface; +} diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_access_recommendation_msg.h b/src/libcharon/plugins/tnccs_20/messages/pb_access_recommendation_msg.h new file mode 100644 index 000000000..01b83cfd7 --- /dev/null +++ b/src/libcharon/plugins/tnccs_20/messages/pb_access_recommendation_msg.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2010 Sansar Choinyambuu + * 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. + */ + +/** + * @defgroup pb_access_recommendation_msg pb_access_recommendation_msg + * @{ @ingroup tnccs_20 + */ + +#ifndef PB_ACCESS_RECOMMENDATION_MSG_H_ +#define PB_ACCESS_RECOMMENDATION_MSG_H_ + +typedef enum pb_access_recommendation_code_t pb_access_recommendation_code_t; +typedef struct pb_access_recommendation_msg_t pb_access_recommendation_msg_t; + +#include "pb_tnc_msg.h" + +/** + * PB Access Recommendation Codes as defined in section 4.7 of RFC 5793 + */ +enum pb_access_recommendation_code_t { + PB_REC_ACCESS_ALLOWED = 1, + PB_REC_ACCESS_DENIED = 2, + PB_REC_QUARANTINED = 3, +}; + +/** + * enum name for pb_access_recommendation_code_t. + */ +extern enum_name_t *pb_access_recommendation_code_names; + + +/** + * Class representing the PB-Access-Recommendation message type. + */ +struct pb_access_recommendation_msg_t { + + /** + * PB-TNC Message interface + */ + pb_tnc_msg_t pb_interface; + + /** + * Get PB Access Recommendation + * + * @return PB Access Recommendation + */ + u_int16_t (*get_access_recommendation)(pb_access_recommendation_msg_t *this); +}; + +/** + * Create a PB-Access-Recommendation message from parameters + * + * @param recommendation Access Recommendation code + */ +pb_tnc_msg_t* pb_access_recommendation_msg_create(u_int16_t recommendation); + +/** + * Create an unprocessed PB-Access-Recommendation message from raw data + * + * @param data PB-Access-Recommendation message data + */ +pb_tnc_msg_t* pb_access_recommendation_msg_create_from_data(chunk_t data); + +#endif /** PB_PA_MSG_H_ @}*/ diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_assessment_result_msg.c b/src/libcharon/plugins/tnccs_20/messages/pb_assessment_result_msg.c new file mode 100644 index 000000000..c91e54176 --- /dev/null +++ b/src/libcharon/plugins/tnccs_20/messages/pb_assessment_result_msg.c @@ -0,0 +1,172 @@ +/* + * Copyright (C) 2010 Sansar Choinyambuu + * 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 "pb_assessment_result_msg.h" + +#include <tls_writer.h> +#include <tls_reader.h> +#include <tnc/tncifimv.h> +#include <debug.h> + +typedef struct private_pb_assessment_result_msg_t private_pb_assessment_result_msg_t; + +/** + * PB-Assessment-Result message (see section 4.6 of RFC 5793) + * + * 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Assessment Result | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define ASSESSMENT_RESULT_MSG_SIZE 4 + +/** + * Private data of a pb_assessment_result_msg_t object. + * + */ +struct private_pb_assessment_result_msg_t { + /** + * Public pb_assessment_result_msg_t interface. + */ + pb_assessment_result_msg_t public; + + /** + * PB-TNC message type + */ + pb_tnc_msg_type_t type; + + /** + * Assessment result code + */ + u_int32_t assessment_result; + + /** + * Encoded message + */ + chunk_t encoding; +}; + +METHOD(pb_tnc_msg_t, get_type, pb_tnc_msg_type_t, + private_pb_assessment_result_msg_t *this) +{ + return this->type; +} + +METHOD(pb_tnc_msg_t, get_encoding, chunk_t, + private_pb_assessment_result_msg_t *this) +{ + return this->encoding; +} + +METHOD(pb_tnc_msg_t, build, void, + private_pb_assessment_result_msg_t *this) +{ + tls_writer_t *writer; + + /* build message */ + writer = tls_writer_create(ASSESSMENT_RESULT_MSG_SIZE); + writer->write_uint32(writer, this->assessment_result); + free(this->encoding.ptr); + this->encoding = writer->get_buf(writer); + this->encoding = chunk_clone(this->encoding); + writer->destroy(writer); +} + +METHOD(pb_tnc_msg_t, process, status_t, + private_pb_assessment_result_msg_t *this, u_int32_t *offset) +{ + tls_reader_t *reader; + + /* process message */ + reader = tls_reader_create(this->encoding); + reader->read_uint32(reader, &this->assessment_result); + reader->destroy(reader); + + if (this->assessment_result < TNC_IMV_EVALUATION_RESULT_COMPLIANT || + this->assessment_result > TNC_IMV_EVALUATION_RESULT_DONT_KNOW) + { + DBG1(DBG_TNC, "invalid assessment result (%u)", + this->assessment_result); + *offset = 0; + return FAILED; + } + + return SUCCESS; +} + +METHOD(pb_tnc_msg_t, destroy, void, + private_pb_assessment_result_msg_t *this) +{ + free(this->encoding.ptr); + free(this); +} + +METHOD(pb_assessment_result_msg_t, get_assessment_result, u_int32_t, + private_pb_assessment_result_msg_t *this) +{ + return this->assessment_result; +} + +/** + * See header + */ +pb_tnc_msg_t *pb_assessment_result_msg_create_from_data(chunk_t data) +{ + private_pb_assessment_result_msg_t *this; + + INIT(this, + .public = { + .pb_interface = { + .get_type = _get_type, + .get_encoding = _get_encoding, + .build = _build, + .process = _process, + .destroy = _destroy, + }, + .get_assessment_result = _get_assessment_result, + }, + .type = PB_MSG_ASSESSMENT_RESULT, + .encoding = chunk_clone(data), + ); + + return &this->public.pb_interface; +} + +/** + * See header + */ +pb_tnc_msg_t *pb_assessment_result_msg_create(u_int32_t assessment_result) +{ + private_pb_assessment_result_msg_t *this; + + INIT(this, + .public = { + .pb_interface = { + .get_type = _get_type, + .get_encoding = _get_encoding, + .build = _build, + .process = _process, + .destroy = _destroy, + }, + .get_assessment_result = _get_assessment_result, + }, + .type = PB_MSG_ASSESSMENT_RESULT, + .assessment_result = assessment_result, + ); + + return &this->public.pb_interface; +} diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_assessment_result_msg.h b/src/libcharon/plugins/tnccs_20/messages/pb_assessment_result_msg.h new file mode 100644 index 000000000..d2b005114 --- /dev/null +++ b/src/libcharon/plugins/tnccs_20/messages/pb_assessment_result_msg.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2010 Sansar Choinyambuu + * 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. + */ + +/** + * @defgroup pb_assessment_result_msg pb_assessment_result_msg + * @{ @ingroup tnccs_20 + */ + +#ifndef PB_ASSESSMENT_RESULT_MSG_H_ +#define PB_ASSESSMENT_RESULT_MSG_H_ + +typedef struct pb_assessment_result_msg_t pb_assessment_result_msg_t; + +#include "pb_tnc_msg.h" + +/** + * Class representing the PB-Assessment-Result message type. + */ +struct pb_assessment_result_msg_t { + + /** + * PB-TNC Message interface + */ + pb_tnc_msg_t pb_interface; + + /** + * Get PB Assessment result + * + * @return PB Assessment result + */ + u_int32_t (*get_assessment_result)(pb_assessment_result_msg_t *this); +}; + +/** + * Create a PB-Assessment-Result message from parameters + * + * @param assessment_result Assessment result code + */ +pb_tnc_msg_t* pb_assessment_result_msg_create(u_int32_t assessment_result); + +/** + * Create an unprocessed PB-Assessment-Result message from raw data + * + * @param data PB-Assessment-Result message data + */ +pb_tnc_msg_t* pb_assessment_result_msg_create_from_data(chunk_t data); + +#endif /** PB_PA_MSG_H_ @}*/ diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_error_msg.c b/src/libcharon/plugins/tnccs_20/messages/pb_error_msg.c new file mode 100644 index 000000000..e1755c512 --- /dev/null +++ b/src/libcharon/plugins/tnccs_20/messages/pb_error_msg.c @@ -0,0 +1,346 @@ +/* + * Copyright (C) 2010 Sansar Choinyambuu + * 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 "pb_error_msg.h" + +#include <debug.h> +#include <tls_writer.h> +#include <tls_reader.h> +#include <tnc/tnccs/tnccs.h> + +ENUM(pb_tnc_error_code_names, PB_ERROR_UNEXPECTED_BATCH_TYPE, + PB_ERROR_VERSION_NOT_SUPPORTED, + "Unexpected Batch Type", + "Invalid Parameter", + "Local Error", + "Unsupported Mandatory Message", + "Version Not Supported" +); + +typedef struct private_pb_error_msg_t private_pb_error_msg_t; + +/** + * PB-Error message (see section 4.9 of RFC 5793) + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Flags | Error Code Vendor ID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Error Code | Reserved | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Error Parameters (Variable Length) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define ERROR_FLAG_NONE 0x00 +#define ERROR_FLAG_FATAL (1<<7) +#define ERROR_RESERVED 0x0000 +#define ERROR_HEADER_SIZE 8 + +/** + * Private data of a pb_error_msg_t object. + * + */ +struct private_pb_error_msg_t { + /** + * Public pb_error_msg_t interface. + */ + pb_error_msg_t public; + + /** + * PB-TNC message type + */ + pb_tnc_msg_type_t type; + + /** + * Fatal flag + */ + bool fatal; + + /** + * PB Error Code Vendor ID + */ + u_int32_t vendor_id; + + /** + * PB Error Code + */ + u_int16_t error_code; + + /** + * PB Error Offset + */ + u_int32_t error_offset; + + /** + * Bad PB-TNC version received + */ + u_int8_t bad_version; + + /** + * Encoded message + */ + chunk_t encoding; + + /** + * reference count + */ + refcount_t ref; +}; + +METHOD(pb_tnc_msg_t, get_type, pb_tnc_msg_type_t, + private_pb_error_msg_t *this) +{ + return this->type; +} + +METHOD(pb_tnc_msg_t, get_encoding, chunk_t, + private_pb_error_msg_t *this) +{ + return this->encoding; +} + +METHOD(pb_tnc_msg_t, build, void, + private_pb_error_msg_t *this) +{ + tls_writer_t *writer; + + /* build message header */ + writer = tls_writer_create(ERROR_HEADER_SIZE); + writer->write_uint8 (writer, this->fatal ? + ERROR_FLAG_FATAL : ERROR_FLAG_NONE); + writer->write_uint24(writer, this->vendor_id); + writer->write_uint16(writer, this->error_code); + writer->write_uint16(writer, ERROR_RESERVED); + + /* build message body */ + if (this->error_code == PB_ERROR_VERSION_NOT_SUPPORTED) + { + /* Bad version */ + writer->write_uint8(writer, this->bad_version); + writer->write_uint8(writer, PB_TNC_VERSION); /* Max version */ + writer->write_uint8(writer, PB_TNC_VERSION); /* Min version */ + writer->write_uint8(writer, 0x00); /* Reserved */ + } + else + { + /* Error Offset */ + writer->write_uint32(writer, this->error_offset); + } + + free(this->encoding.ptr); + this->encoding = writer->get_buf(writer); + this->encoding = chunk_clone(this->encoding); + writer->destroy(writer); +} + +METHOD(pb_tnc_msg_t, process, status_t, + private_pb_error_msg_t *this, u_int32_t *offset) +{ + u_int8_t flags, max_version, min_version; + u_int16_t reserved; + tls_reader_t *reader; + + if (this->encoding.len < ERROR_HEADER_SIZE) + { + DBG1(DBG_TNC,"%N message is shorter than header size of %u bytes", + pb_tnc_msg_type_names, PB_MSG_ERROR, ERROR_HEADER_SIZE); + return FAILED; + } + + /* process message header */ + reader = tls_reader_create(this->encoding); + reader->read_uint8 (reader, &flags); + reader->read_uint24(reader, &this->vendor_id); + reader->read_uint16(reader, &this->error_code); + reader->read_uint16(reader, &reserved); + this->fatal = (flags & ERROR_FLAG_FATAL) != ERROR_FLAG_NONE; + + if (this->vendor_id == IETF_VENDOR_ID && reader->remaining(reader) == 4) + { + if (this->error_code == PB_ERROR_VERSION_NOT_SUPPORTED) + { + reader->read_uint8(reader, &this->bad_version); + reader->read_uint8(reader, &max_version); + reader->read_uint8(reader, &min_version); + } + else + { + reader->read_uint32(reader, &this->error_offset); + } + } + reader->destroy(reader); + + return SUCCESS; +} + +METHOD(pb_tnc_msg_t, get_ref, pb_tnc_msg_t*, + private_pb_error_msg_t *this) +{ + ref_get(&this->ref); + return &this->public.pb_interface; +} + +METHOD(pb_tnc_msg_t, destroy, void, + private_pb_error_msg_t *this) +{ + if (ref_put(&this->ref)) + { + free(this->encoding.ptr); + free(this); + } +} + +METHOD(pb_error_msg_t, get_fatal_flag, bool, + private_pb_error_msg_t *this) +{ + return this->fatal; +} + +METHOD(pb_error_msg_t, get_vendor_id, u_int32_t, + private_pb_error_msg_t *this) +{ + return this->vendor_id; +} + +METHOD(pb_error_msg_t, get_error_code, u_int16_t, + private_pb_error_msg_t *this) +{ + return this->error_code; +} + +METHOD(pb_error_msg_t, get_offset, u_int32_t, + private_pb_error_msg_t *this) +{ + return this->error_offset; +} + +METHOD(pb_error_msg_t, get_bad_version, u_int8_t, + private_pb_error_msg_t *this) +{ + return this->bad_version; +} + +METHOD(pb_error_msg_t, set_bad_version, void, + private_pb_error_msg_t *this, u_int8_t version) +{ + this->bad_version = version; +} + +/** + * See header + */ +pb_tnc_msg_t* pb_error_msg_create(bool fatal, u_int32_t vendor_id, + pb_tnc_error_code_t error_code) +{ + private_pb_error_msg_t *this; + + INIT(this, + .public = { + .pb_interface = { + .get_type = _get_type, + .get_encoding = _get_encoding, + .build = _build, + .process = _process, + .get_ref = _get_ref, + .destroy = _destroy, + }, + .get_fatal_flag = _get_fatal_flag, + .get_vendor_id = _get_vendor_id, + .get_error_code = _get_error_code, + .get_offset = _get_offset, + .get_bad_version = _get_bad_version, + .set_bad_version = _set_bad_version, + }, + .type = PB_MSG_ERROR, + .ref = 1, + .fatal = fatal, + .vendor_id = vendor_id, + .error_code = error_code, + ); + + return &this->public.pb_interface; +} + +/** + * See header + */ +pb_tnc_msg_t* pb_error_msg_create_with_offset(bool fatal, u_int32_t vendor_id, + pb_tnc_error_code_t error_code, + u_int32_t error_offset) +{ + private_pb_error_msg_t *this; + + INIT(this, + .public = { + .pb_interface = { + .get_type = _get_type, + .get_encoding = _get_encoding, + .build = _build, + .process = _process, + .get_ref = _get_ref, + .destroy = _destroy, + }, + .get_fatal_flag = _get_fatal_flag, + .get_vendor_id = _get_vendor_id, + .get_error_code = _get_error_code, + .get_offset = _get_offset, + .get_bad_version = _get_bad_version, + .set_bad_version = _set_bad_version, + }, + .type = PB_MSG_ERROR, + .ref = 1, + .fatal = fatal, + .vendor_id = vendor_id, + .error_code = error_code, + .error_offset = error_offset, + ); + + return &this->public.pb_interface; +} + +/** + * See header + */ +pb_tnc_msg_t *pb_error_msg_create_from_data(chunk_t data) +{ + private_pb_error_msg_t *this; + + INIT(this, + .public = { + .pb_interface = { + .get_type = _get_type, + .get_encoding = _get_encoding, + .build = _build, + .process = _process, + .get_ref = _get_ref, + .destroy = _destroy, + }, + .get_fatal_flag = _get_fatal_flag, + .get_vendor_id = _get_vendor_id, + .get_error_code = _get_error_code, + .get_offset = _get_offset, + .get_bad_version = _get_bad_version, + .set_bad_version = _set_bad_version, + }, + .type = PB_MSG_ERROR, + .ref = 1, + .encoding = chunk_clone(data), + ); + + return &this->public.pb_interface; +} + diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_error_msg.h b/src/libcharon/plugins/tnccs_20/messages/pb_error_msg.h new file mode 100644 index 000000000..8b92742b5 --- /dev/null +++ b/src/libcharon/plugins/tnccs_20/messages/pb_error_msg.h @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2010 Sansar Choinyambuu + * 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. + */ + +/** + * @defgroup pb_error_msg pb_error_msg + * @{ @ingroup tnccs_20 + */ + +#ifndef PB_ERROR_MSG_H_ +#define PB_ERROR_MSG_H_ + +typedef enum pb_tnc_error_code_t pb_tnc_error_code_t; +typedef struct pb_error_msg_t pb_error_msg_t; + +#include "pb_tnc_msg.h" + +/** + * PB-TNC Error Codes as defined in section 4.9.1 of RFC 5793 + */ +enum pb_tnc_error_code_t { + PB_ERROR_UNEXPECTED_BATCH_TYPE = 0, + PB_ERROR_INVALID_PARAMETER = 1, + PB_ERROR_LOCAL_ERROR = 2, + PB_ERROR_UNSUPPORTED_MANDATORY_MSG = 3, + PB_ERROR_VERSION_NOT_SUPPORTED = 4 +}; + +/** + * enum name for pb_tnc_error_code_t. + */ +extern enum_name_t *pb_tnc_error_code_names; + +/** + * Class representing the PB-Error message type. + */ +struct pb_error_msg_t { + + /** + * PB-TNC Message interface + */ + pb_tnc_msg_t pb_interface; + + /** + * Get the fatal flag + * + * @return fatal flag + */ + bool (*get_fatal_flag)(pb_error_msg_t *this); + + /** + * Get PB Error code Vendor ID + * + * @return PB Error Code Vendor ID + */ + u_int32_t (*get_vendor_id)(pb_error_msg_t *this); + + /** + * Get PB Error Code + * + * @return PB Error Code + */ + u_int16_t (*get_error_code)(pb_error_msg_t *this); + + /** + * Get the PB Error Offset + * + * @return PB Error Offset + */ + u_int32_t (*get_offset)(pb_error_msg_t *this); + + /** + * Get the PB Bad Version + * + * @return PB Bad Version + */ + u_int8_t (*get_bad_version)(pb_error_msg_t *this); + + /** + * Set the PB Bad Version + * + * @param version PB Bad Version + */ + void (*set_bad_version)(pb_error_msg_t *this, u_int8_t version); +}; + +/** + * Create a PB-Error message from parameters + * + * @param fatal fatal flag + * @param vendor_id Error Code Vendor ID + * @param error_code Error Code + */ +pb_tnc_msg_t* pb_error_msg_create(bool fatal, u_int32_t vendor_id, + pb_tnc_error_code_t error_code); + +/** + * Create a PB-Error message from parameters with offset field + * + * @param fatal fatal flag + * @param vendor_id Error Code Vendor ID + * @param error_code Error Code + * @param error_offset Error Offset + */ +pb_tnc_msg_t* pb_error_msg_create_with_offset(bool fatal, u_int32_t vendor_id, + pb_tnc_error_code_t error_code, + u_int32_t error_offset); + +/** + * Create an unprocessed PB-Error message from raw data + * + * @param data PB-Error message data + */ +pb_tnc_msg_t* pb_error_msg_create_from_data(chunk_t data); + +#endif /** PB_PA_MSG_H_ @}*/ diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_experimental_msg.c b/src/libcharon/plugins/tnccs_20/messages/pb_experimental_msg.c new file mode 100644 index 000000000..7dfba136f --- /dev/null +++ b/src/libcharon/plugins/tnccs_20/messages/pb_experimental_msg.c @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2010 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 "pb_experimental_msg.h" + +typedef struct private_pb_experimental_msg_t private_pb_experimental_msg_t; + +/** + * Private data of a pb_experimental_msg_t object. + * + */ +struct private_pb_experimental_msg_t { + /** + * Public pb_experimental_msg_t interface. + */ + pb_experimental_msg_t public; + + /** + * PB-TNC message type + */ + pb_tnc_msg_type_t type; + + /** + * Encoded message + */ + chunk_t encoding; +}; + +METHOD(pb_tnc_msg_t, get_type, pb_tnc_msg_type_t, + private_pb_experimental_msg_t *this) +{ + return this->type; +} + +METHOD(pb_tnc_msg_t, get_encoding, chunk_t, + private_pb_experimental_msg_t *this) +{ + return this->encoding; +} + +METHOD(pb_tnc_msg_t, build, void, + private_pb_experimental_msg_t *this) +{ + /* nothing to do since message contents equal encoding */ +} + +METHOD(pb_tnc_msg_t, process, status_t, + private_pb_experimental_msg_t *this, u_int32_t *offset) +{ + return SUCCESS; +} + +METHOD(pb_tnc_msg_t, destroy, void, + private_pb_experimental_msg_t *this) +{ + free(this->encoding.ptr); + free(this); +} + +/** + * See header + */ +pb_tnc_msg_t *pb_experimental_msg_create_from_data(chunk_t data) +{ + private_pb_experimental_msg_t *this; + + INIT(this, + .public = { + .pb_interface = { + .get_type = _get_type, + .get_encoding = _get_encoding, + .build = _build, + .process = _process, + .destroy = _destroy, + }, + }, + .type = PB_MSG_EXPERIMENTAL, + .encoding = chunk_clone(data), + ); + + return &this->public.pb_interface; +} + +/** + * See header + */ +pb_tnc_msg_t *pb_experimental_msg_create(chunk_t body) +{ + return pb_experimental_msg_create_from_data(body); +} diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_experimental_msg.h b/src/libcharon/plugins/tnccs_20/messages/pb_experimental_msg.h new file mode 100644 index 000000000..b1cc4f46e --- /dev/null +++ b/src/libcharon/plugins/tnccs_20/messages/pb_experimental_msg.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2010 Sansar Choinyambuu + * 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. + */ + +/** + * @defgroup pb_experimental_msg pb_experimental_msg + * @{ @ingroup tnccs_20 + */ + +#ifndef PB_EXPERIMENTAL_MSG_H_ +#define PB_EXPERIMENTAL_MSG_H_ + +typedef struct pb_experimental_msg_t pb_experimental_msg_t; + +#include "pb_tnc_msg.h" + +/** + * Class representing the PB-Experimental message type. + */ +struct pb_experimental_msg_t { + + /** + * PB-TNC Message interface + */ + pb_tnc_msg_t pb_interface; +}; + +/** + * Create a PB-Experimental message from parameters + * + * @param body message body + */ +pb_tnc_msg_t* pb_experimental_msg_create(chunk_t body); + +/** + * Create an unprocessed PB-Experimental message from raw data + * + * @param data PB-Experimental message data + */ +pb_tnc_msg_t* pb_experimental_msg_create_from_data(chunk_t data); + +#endif /** PB_EXPERIMENTAL_MSG_H_ @}*/ diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_language_preference_msg.c b/src/libcharon/plugins/tnccs_20/messages/pb_language_preference_msg.c new file mode 100644 index 000000000..9a94edf30 --- /dev/null +++ b/src/libcharon/plugins/tnccs_20/messages/pb_language_preference_msg.c @@ -0,0 +1,175 @@ +/* + * Copyright (C) 2010 Sansar Choinyambuu + * 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 "pb_language_preference_msg.h" + +#include <tls_writer.h> +#include <tls_reader.h> +#include <debug.h> + +typedef struct private_pb_language_preference_msg_t private_pb_language_preference_msg_t; + +/** + * PB-Language-Preference message (see section 4.10 of RFC 5793) + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Language Preference (Variable Length) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define PB_LANG_PREFIX "Accept-Language: " +#define PB_LANG_PREFIX_LEN strlen(PB_LANG_PREFIX) + +/** + * Private data of a pb_language_preference_msg_t object. + * + */ +struct private_pb_language_preference_msg_t { + /** + * Public pb_access_recommendation_msg_t interface. + */ + pb_language_preference_msg_t public; + + /** + * PB-TNC message type + */ + pb_tnc_msg_type_t type; + + /** + * Language preference + */ + chunk_t language_preference; + + /** + * Encoded message + */ + chunk_t encoding; +}; + +METHOD(pb_tnc_msg_t, get_type, pb_tnc_msg_type_t, + private_pb_language_preference_msg_t *this) +{ + return this->type; +} + +METHOD(pb_tnc_msg_t, get_encoding, chunk_t, + private_pb_language_preference_msg_t *this) +{ + return this->encoding; +} + +METHOD(pb_tnc_msg_t, build, void, + private_pb_language_preference_msg_t *this) +{ + this->encoding = chunk_cat("cc", + chunk_create(PB_LANG_PREFIX, PB_LANG_PREFIX_LEN), + this->language_preference); +} + +METHOD(pb_tnc_msg_t, process, status_t, + private_pb_language_preference_msg_t *this, u_int32_t *offset) +{ + chunk_t lang; + + if (this->encoding.len >= PB_LANG_PREFIX_LEN && + memeq(this->encoding.ptr, PB_LANG_PREFIX, PB_LANG_PREFIX_LEN)) + { + lang = chunk_skip(this->encoding, PB_LANG_PREFIX_LEN); + this->language_preference = lang.len ? chunk_clone(lang) : chunk_empty; + } + else + { + DBG1(DBG_TNC, "language preference must be preceded by '%s'", + PB_LANG_PREFIX); + *offset = 0; + return FAILED; + } + + if (this->language_preference.len && + this->language_preference.ptr[this->language_preference.len-1] == '\0') + { + DBG1(DBG_TNC, "language preference must not be null terminated"); + *offset = PB_LANG_PREFIX_LEN + this->language_preference.len - 1; + return FAILED; + } + + return SUCCESS; +} + +METHOD(pb_tnc_msg_t, destroy, void, + private_pb_language_preference_msg_t *this) +{ + free(this->encoding.ptr); + free(this->language_preference.ptr); + free(this); +} + +METHOD(pb_language_preference_msg_t, get_language_preference, chunk_t, + private_pb_language_preference_msg_t *this) +{ + return this->language_preference; +} + +/** + * See header + */ +pb_tnc_msg_t *pb_language_preference_msg_create_from_data(chunk_t data) +{ + private_pb_language_preference_msg_t *this; + + INIT(this, + .public = { + .pb_interface = { + .get_type = _get_type, + .get_encoding = _get_encoding, + .build = _build, + .process = _process, + .destroy = _destroy, + }, + .get_language_preference = _get_language_preference, + }, + .type = PB_MSG_LANGUAGE_PREFERENCE, + .encoding = chunk_clone(data), + ); + + return &this->public.pb_interface; +} + +/** + * See header + */ +pb_tnc_msg_t *pb_language_preference_msg_create(chunk_t language_preference) +{ + private_pb_language_preference_msg_t *this; + + INIT(this, + .public = { + .pb_interface = { + .get_type = _get_type, + .get_encoding = _get_encoding, + .build = _build, + .process = _process, + .destroy = _destroy, + }, + .get_language_preference = _get_language_preference, + }, + .type = PB_MSG_LANGUAGE_PREFERENCE, + .language_preference = chunk_clone(language_preference), + ); + + return &this->public.pb_interface; +} diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_language_preference_msg.h b/src/libcharon/plugins/tnccs_20/messages/pb_language_preference_msg.h new file mode 100644 index 000000000..17106f6fa --- /dev/null +++ b/src/libcharon/plugins/tnccs_20/messages/pb_language_preference_msg.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2010 Sansar Choinyambuu + * 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. + */ + +/** + * @defgroup pb_language_preference_msg pb_language_preference_msg + * @{ @ingroup tnccs_20 + */ + +#ifndef PB_LANGUAGE_PREFERENCE_MSG_H_ +#define PB_LANGUAGE_PREFERENCE_MSG_H_ + +typedef struct pb_language_preference_msg_t pb_language_preference_msg_t; + +#include "pb_tnc_msg.h" + +/** + * Class representing the PB-Language-Preference message type. + */ +struct pb_language_preference_msg_t { + + /** + * PB-TNC Message interface + */ + pb_tnc_msg_t pb_interface; + + /** + * Get PB Language Preference + * + * @return Language preference + */ + chunk_t (*get_language_preference)(pb_language_preference_msg_t *this); +}; + +/** + * Create a PB-Language-Preference message from parameters + * + * @param language_preference Preferred language(s) + */ +pb_tnc_msg_t* pb_language_preference_msg_create(chunk_t language_preference); + +/** + * Create an unprocessed PB-Language-Preference message from raw data + * + * @param data PB-Language-Preference message data + */ +pb_tnc_msg_t* pb_language_preference_msg_create_from_data(chunk_t data); + +#endif /** PB_PA_MSG_H_ @}*/ diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_pa_msg.c b/src/libcharon/plugins/tnccs_20/messages/pb_pa_msg.c new file mode 100644 index 000000000..8315bfb76 --- /dev/null +++ b/src/libcharon/plugins/tnccs_20/messages/pb_pa_msg.c @@ -0,0 +1,293 @@ +/* + * Copyright (C) 2010 Sansar Choinyanbuu + * Copyright (C) 2010 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 "pb_pa_msg.h" + +#include <tls_writer.h> +#include <tls_reader.h> +#include <tnc/tnccs/tnccs.h> +#include <debug.h> + +ENUM(pa_tnc_subtype_names, PA_SUBTYPE_TESTING, PA_SUBTYPE_NEA_CLIENT, + "Testing", + "Operating System", + "Anti-Virus", + "Anti-Spyware", + "Anti-Malware", + "Firewall", + "IDPS", + "VPN", + "NEA Client" +); + +typedef struct private_pb_pa_msg_t private_pb_pa_msg_t; + +/** + * PB-PA message + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Flags | PA Message Vendor ID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | PA Subtype | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Posture Collector Identifier | Posture Validator Identifier | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | PA Message Body (Variable Length) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +#define PA_FLAG_NONE 0x00 +#define PA_FLAG_EXCL (1<<7) +#define PA_RESERVED_SUBTYPE 0xffffffff + + +/** + * Private data of a pb_pa_msg_t object. + * + */ +struct private_pb_pa_msg_t { + /** + * Public pb_pa_msg_t interface. + */ + pb_pa_msg_t public; + + /** + * PB-TNC message type + */ + pb_tnc_msg_type_t type; + + /** + * Exclusive flag + */ + bool excl; + + /** + * PA Message Vendor ID + */ + u_int32_t vendor_id; + + /** + * PA Subtype + */ + u_int32_t subtype; + + /** + * Posture Validator Identifier + */ + u_int16_t collector_id; + + /** + * Posture Validator Identifier + */ + u_int16_t validator_id; + + /** + * PA Message Body + */ + chunk_t msg_body; + + /** + * Encoded message + */ + chunk_t encoding; +}; + +METHOD(pb_tnc_msg_t, get_type, pb_tnc_msg_type_t, + private_pb_pa_msg_t *this) +{ + return this->type; +} + +METHOD(pb_tnc_msg_t, get_encoding, chunk_t, + private_pb_pa_msg_t *this) +{ + return this->encoding; +} + +METHOD(pb_tnc_msg_t, build, void, + private_pb_pa_msg_t *this) +{ + chunk_t msg_header; + tls_writer_t *writer; + + /* build message header */ + writer = tls_writer_create(64); + writer->write_uint8 (writer, this->excl ? PA_FLAG_EXCL : PA_FLAG_NONE); + writer->write_uint24(writer, this->vendor_id); + writer->write_uint32(writer, this->subtype); + writer->write_uint16(writer, this->collector_id); + writer->write_uint16(writer, this->validator_id); + msg_header = writer->get_buf(writer); + + /* create encoding by concatenating message header and message body */ + free(this->encoding.ptr); + this->encoding = chunk_cat("cc", msg_header, this->msg_body); + writer->destroy(writer); +} + +METHOD(pb_tnc_msg_t, process, status_t, + private_pb_pa_msg_t *this, u_int32_t *offset) +{ + u_int8_t flags; + size_t msg_body_len; + tls_reader_t *reader; + + /* process message header */ + reader = tls_reader_create(this->encoding); + reader->read_uint8 (reader, &flags); + reader->read_uint24(reader, &this->vendor_id); + reader->read_uint32(reader, &this->subtype); + reader->read_uint16(reader, &this->collector_id); + reader->read_uint16(reader, &this->validator_id); + this->excl = ((flags & PA_FLAG_EXCL) != PA_FLAG_NONE); + + /* process message body */ + msg_body_len = reader->remaining(reader); + if (msg_body_len) + { + reader->read_data(reader, msg_body_len, &this->msg_body); + this->msg_body = chunk_clone(this->msg_body); + } + reader->destroy(reader); + + if (this->vendor_id == RESERVED_VENDOR_ID) + { + DBG1(DBG_TNC, "Vendor ID 0x%06x is reserved", RESERVED_VENDOR_ID); + *offset = 1; + return FAILED; + } + + if (this->subtype == PA_RESERVED_SUBTYPE) + { + DBG1(DBG_TNC, "PA Subtype 0x%08x is reserved", PA_RESERVED_SUBTYPE); + *offset = 4; + } + + return SUCCESS; +} + +METHOD(pb_tnc_msg_t, destroy, void, + private_pb_pa_msg_t *this) +{ + free(this->encoding.ptr); + free(this->msg_body.ptr); + free(this); +} + +METHOD(pb_pa_msg_t, get_vendor_id, u_int32_t, + private_pb_pa_msg_t *this, u_int32_t *subtype) +{ + *subtype = this->subtype; + return this->vendor_id; +} + +METHOD(pb_pa_msg_t, get_collector_id, u_int16_t, + private_pb_pa_msg_t *this) +{ + return this->collector_id; +} + +METHOD(pb_pa_msg_t, get_validator_id, u_int16_t, + private_pb_pa_msg_t *this) +{ + return this->validator_id; +} + +METHOD(pb_pa_msg_t, get_body, chunk_t, + private_pb_pa_msg_t *this) +{ + return this->msg_body; +} + +METHOD(pb_pa_msg_t, get_exclusive_flag, bool, + private_pb_pa_msg_t *this) +{ + return this->excl; +} + +METHOD(pb_pa_msg_t, set_exclusive_flag, void, + private_pb_pa_msg_t *this, bool excl) +{ + this->excl = excl; +} + +/** + * See header + */ +pb_tnc_msg_t *pb_pa_msg_create_from_data(chunk_t data) +{ + private_pb_pa_msg_t *this; + + INIT(this, + .public = { + .pb_interface = { + .get_type = _get_type, + .get_encoding = _get_encoding, + .process = _process, + .destroy = _destroy, + }, + .get_vendor_id = _get_vendor_id, + .get_collector_id = _get_collector_id, + .get_validator_id = _get_validator_id, + .get_body = _get_body, + .get_exclusive_flag = _get_exclusive_flag, + .set_exclusive_flag = _set_exclusive_flag, + }, + .type = PB_MSG_PA, + .encoding = chunk_clone(data), + ); + + return &this->public.pb_interface; +} + +/** + * See header + */ +pb_tnc_msg_t *pb_pa_msg_create(u_int32_t vendor_id, u_int32_t subtype, + u_int16_t collector_id, u_int16_t validator_id, + chunk_t msg_body) +{ + private_pb_pa_msg_t *this; + + INIT(this, + .public = { + .pb_interface = { + .get_type = _get_type, + .get_encoding = _get_encoding, + .build = _build, + .process = _process, + .destroy = _destroy, + }, + .get_vendor_id = _get_vendor_id, + .get_collector_id = _get_collector_id, + .get_validator_id = _get_validator_id, + .get_body = _get_body, + .get_exclusive_flag = _get_exclusive_flag, + .set_exclusive_flag = _set_exclusive_flag, + }, + .type = PB_MSG_PA, + .vendor_id = vendor_id, + .subtype = subtype, + .collector_id = collector_id, + .validator_id = validator_id, + .msg_body = chunk_clone(msg_body), + ); + + return &this->public.pb_interface; +} diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_pa_msg.h b/src/libcharon/plugins/tnccs_20/messages/pb_pa_msg.h new file mode 100644 index 000000000..366d790f6 --- /dev/null +++ b/src/libcharon/plugins/tnccs_20/messages/pb_pa_msg.h @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2010 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. + */ + +/** + * @defgroup pb_pa_msg pb_pa_msg + * @{ @ingroup tnccs_20 + */ + +#ifndef PB_PA_MSG_H_ +#define PB_PA_MSG_H_ + +typedef enum pa_tnc_subtype_t pa_tnc_subtype_t; +typedef struct pb_pa_msg_t pb_pa_msg_t; + +#include "pb_tnc_msg.h" + +/** + * PA-TNC Subtypes as defined in section 3.5 of RFC 5792 + */ + enum pa_tnc_subtype_t { + PA_SUBTYPE_TESTING = 0, + PA_SUBTYPE_OPERATING_SYSTEM = 1, + PA_SUBTYPE_ANTI_VIRUS = 2, + PA_SUBTYPE_ANTI_SPYWARE = 3, + PA_SUBTYPE_ANTI_MALWARE = 4, + PA_SUBTYPE_FIREWALL = 5, + PA_SUBTYPE_IDPS = 6, + PA_SUBTYPE_VPN = 7, + PA_SUBTYPE_NEA_CLIENT = 8 +}; + +/** + * enum name for pa_tnc_subtype_t. + */ +extern enum_name_t *pa_tnc_subtype_names; + +/** + * Class representing the PB-PA message type. + */ +struct pb_pa_msg_t { + + /** + * PB-TNC Message interface + */ + pb_tnc_msg_t pb_interface; + + /** + * Get PA Message Vendor ID and Subtype + * + * @param subtype PA Subtype + * @return PA Message Vendor ID + */ + u_int32_t (*get_vendor_id)(pb_pa_msg_t *this, u_int32_t *subtype); + + /** + * Get Posture Collector ID + * + * @return Posture Collector ID + */ + u_int16_t (*get_collector_id)(pb_pa_msg_t *this); + + /** + * Get Posture Validator ID + * + * @return Posture Validator ID + */ + u_int16_t (*get_validator_id)(pb_pa_msg_t *this); + + /** + * Get the PA Message Body + * + * @return PA Message Body + */ + chunk_t (*get_body)(pb_pa_msg_t *this); + + /** + * Get the exclusive flag + * + * @return exclusive flag + */ + bool (*get_exclusive_flag)(pb_pa_msg_t *this); + + /** + * Set the exclusive flag + * + * @param excl vexclusive flag + */ + void (*set_exclusive_flag)(pb_pa_msg_t *this, bool excl); +}; + +/** + * Create a PB-PA message from parameters + * + * @param vendor_id PA Message Vendor ID + * @param subtype PA Subtype + * @param collector_id Posture Collector ID + * @param validator_id Posture Validator ID + * @param msg_body PA Message Body + */ +pb_tnc_msg_t *pb_pa_msg_create(u_int32_t vendor_id, u_int32_t subtype, + u_int16_t collector_id, u_int16_t validator_id, + chunk_t msg_body); + +/** + * Create an unprocessed PB-PA message from raw data + * + * @param data PB-PA message data + */ +pb_tnc_msg_t* pb_pa_msg_create_from_data(chunk_t data); + +#endif /** PB_PA_MSG_H_ @}*/ diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_reason_string_msg.c b/src/libcharon/plugins/tnccs_20/messages/pb_reason_string_msg.c new file mode 100644 index 000000000..e361cf2b2 --- /dev/null +++ b/src/libcharon/plugins/tnccs_20/messages/pb_reason_string_msg.c @@ -0,0 +1,216 @@ +/* + * Copyright (C) 2010 Sansar Choinyambuu + * 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 "pb_reason_string_msg.h" + +#include <tls_writer.h> +#include <tls_reader.h> +#include <debug.h> + +typedef struct private_pb_reason_string_msg_t private_pb_reason_string_msg_t; + +/** + * PB-Language-Preference message (see section 4.11 of RFC 5793) + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Reason String Length | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Reason String (Variable Length) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Lang Code Len | Reason String Language Code (Variable Length) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +/** + * Private data of a pb_reason_string_msg_t object. + * + */ +struct private_pb_reason_string_msg_t { + /** + * Public pb_reason_string_msg_t interface. + */ + pb_reason_string_msg_t public; + + /** + * PB-TNC message type + */ + pb_tnc_msg_type_t type; + + /** + * Reason string + */ + chunk_t reason_string; + + /** + * Language code + */ + chunk_t language_code; + + /** + * Encoded message + */ + chunk_t encoding; +}; + +METHOD(pb_tnc_msg_t, get_type, pb_tnc_msg_type_t, + private_pb_reason_string_msg_t *this) +{ + return this->type; +} + +METHOD(pb_tnc_msg_t, get_encoding, chunk_t, + private_pb_reason_string_msg_t *this) +{ + return this->encoding; +} + +METHOD(pb_tnc_msg_t, build, void, + private_pb_reason_string_msg_t *this) +{ + tls_writer_t *writer; + + /* build message */ + writer = tls_writer_create(64); + writer->write_data32(writer, this->reason_string); + writer->write_data8 (writer, this->language_code); + + free(this->encoding.ptr); + this->encoding = writer->get_buf(writer); + this->encoding = chunk_clone(this->encoding); + writer->destroy(writer); +} + +METHOD(pb_tnc_msg_t, process, status_t, + private_pb_reason_string_msg_t *this, u_int32_t *offset) +{ + tls_reader_t *reader; + + /* process message */ + reader = tls_reader_create(this->encoding); + if (!reader->read_data32(reader, &this->reason_string)) + { + DBG1(DBG_TNC, "could not parse reason string"); + reader->destroy(reader); + *offset = 0; + return FAILED; + }; + this->reason_string = chunk_clone(this->reason_string); + + if (this->reason_string.len && + this->reason_string.ptr[this->reason_string.len-1] == '\0') + { + DBG1(DBG_TNC, "reason string must not be null terminated"); + reader->destroy(reader); + *offset = 3 + this->reason_string.len; + return FAILED; + } + + if (!reader->read_data8(reader, &this->language_code)) + { + DBG1(DBG_TNC, "could not parse language code"); + reader->destroy(reader); + *offset = 4 + this->reason_string.len; + return FAILED; + }; + this->language_code = chunk_clone(this->language_code); + reader->destroy(reader); + + if (this->language_code.len && + this->language_code.ptr[this->language_code.len-1] == '\0') + { + DBG1(DBG_TNC, "language code must not be null terminated"); + *offset = 4 + this->reason_string.len + this->language_code.len; + return FAILED; + } + + return SUCCESS; +} + +METHOD(pb_tnc_msg_t, destroy, void, + private_pb_reason_string_msg_t *this) +{ + free(this->encoding.ptr); + free(this->reason_string.ptr); + free(this->language_code.ptr); + free(this); +} + +METHOD(pb_reason_string_msg_t, get_reason_string, chunk_t, + private_pb_reason_string_msg_t *this) +{ + return this->reason_string; +} + +METHOD(pb_reason_string_msg_t, get_language_code, chunk_t, + private_pb_reason_string_msg_t *this) +{ + return this->language_code; +} + +/** + * See header + */ +pb_tnc_msg_t *pb_reason_string_msg_create_from_data(chunk_t data) +{ + private_pb_reason_string_msg_t *this; + + INIT(this, + .public = { + .pb_interface = { + .get_type = _get_type, + .get_encoding = _get_encoding, + .build = _build, + .process = _process, + .destroy = _destroy, + }, + .get_reason_string = _get_reason_string, + .get_language_code = _get_language_code, + }, + .type = PB_MSG_REASON_STRING, + .encoding = chunk_clone(data), + ); + + return &this->public.pb_interface; +} + +/** + * See header + */ +pb_tnc_msg_t *pb_reason_string_msg_create(chunk_t reason_string, + chunk_t language_code) +{ + private_pb_reason_string_msg_t *this; + + INIT(this, + .public = { + .pb_interface = { + .get_type = _get_type, + .get_encoding = _get_encoding, + .build = _build, + .process = _process, + .destroy = _destroy, + }, + .get_reason_string = _get_reason_string, + .get_language_code = _get_language_code, + }, + .type = PB_MSG_REASON_STRING, + .reason_string = chunk_clone(reason_string), + .language_code = chunk_clone(language_code), + ); + + return &this->public.pb_interface; +} diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_reason_string_msg.h b/src/libcharon/plugins/tnccs_20/messages/pb_reason_string_msg.h new file mode 100644 index 000000000..bb296a90c --- /dev/null +++ b/src/libcharon/plugins/tnccs_20/messages/pb_reason_string_msg.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2010 Sansar Choinyambuu + * 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. + */ + +/** + * @defgroup pb_reason_string_msg pb_reason_string_msg + * @{ @ingroup tnccs_20 + */ + +#ifndef PB_REASON_STRING_MSG_H_ +#define PB_REASON_STRING_MSG_H_ + +typedef struct pb_reason_string_msg_t pb_reason_string_msg_t; + +#include "pb_tnc_msg.h" + +/** + * Class representing the PB-Reason-String message type. + */ +struct pb_reason_string_msg_t { + + /** + * PB-TNC Message interface + */ + pb_tnc_msg_t pb_interface; + + /** + * Get Reason String + * + * @return Reason string + */ + chunk_t (*get_reason_string)(pb_reason_string_msg_t *this); + + /** + * Get Reason String Language Code + * + * @return Language code + */ + chunk_t (*get_language_code)(pb_reason_string_msg_t *this); +}; + +/** + * Create a PB-Reason-String message from parameters + * + * @param reason_string Reason string + * @param language_code Language code + */ +pb_tnc_msg_t* pb_reason_string_msg_create(chunk_t reason_string, + chunk_t language_code); + +/** + * Create an unprocessed PB-Reason-String message from raw data + * + * @param data PB-Reason-String message data + */ +pb_tnc_msg_t* pb_reason_string_msg_create_from_data(chunk_t data); + +#endif /** PB_PA_MSG_H_ @}*/ diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_remediation_parameters_msg.c b/src/libcharon/plugins/tnccs_20/messages/pb_remediation_parameters_msg.c new file mode 100644 index 000000000..79381a7b1 --- /dev/null +++ b/src/libcharon/plugins/tnccs_20/messages/pb_remediation_parameters_msg.c @@ -0,0 +1,259 @@ +/* + * Copyright (C) 2010 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 "pb_remediation_parameters_msg.h" + +#include <tls_writer.h> +#include <tls_reader.h> +#include <debug.h> + +ENUM(pb_tnc_remed_param_type_names, PB_REMEDIATION_URI, PB_REMEDIATION_STRING, + "Remediation-URI", + "Remediation-String" +); + +typedef struct private_pb_remediation_parameters_msg_t private_pb_remediation_parameters_msg_t; + +/** + * PB-Remediation-Parameters message (see section 4.8 of RFC 5793) + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Reserved | Remediation Parameters Vendor ID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Remediation Parameters Type | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Remediation Parameters (Variable Length) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Remediation String Length | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Remediation String (Variable Length) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Lang Code Len | Remediation String Lang Code (Variable Len) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +/** + * Private data of a pb_remediation_parameters_msg_t object. + * + */ +struct private_pb_remediation_parameters_msg_t { + /** + * Public pb_remediation_parameters_msg_t interface. + */ + pb_remediation_parameters_msg_t public; + + /** + * PB-TNC message type + */ + pb_tnc_msg_type_t type; + + /** + * Remediation Parameters Vendor ID + */ + u_int32_t vendor_id; + + /** + * Remediation Parameters Type + */ + u_int32_t parameters_type; + + /** + * Remediation Parameters string + */ + chunk_t remediation_string; + + /** + * Language code + */ + chunk_t language_code; + + /** + * Encoded message + */ + chunk_t encoding; +}; + +METHOD(pb_tnc_msg_t, get_type, pb_tnc_msg_type_t, + private_pb_remediation_parameters_msg_t *this) +{ + return this->type; +} + +METHOD(pb_tnc_msg_t, get_encoding, chunk_t, + private_pb_remediation_parameters_msg_t *this) +{ + return this->encoding; +} + +METHOD(pb_tnc_msg_t, build, void, + private_pb_remediation_parameters_msg_t *this) +{ + tls_writer_t *writer; + + /* build message */ + writer = tls_writer_create(64); + writer->write_uint32(writer, this->vendor_id); + writer->write_uint32(writer, this->parameters_type); + writer->write_data32(writer, this->remediation_string); + writer->write_data8 (writer, this->language_code); + + free(this->encoding.ptr); + this->encoding = writer->get_buf(writer); + this->encoding = chunk_clone(this->encoding); + writer->destroy(writer); +} + +METHOD(pb_tnc_msg_t, process, status_t, + private_pb_remediation_parameters_msg_t *this, u_int32_t *offset) +{ + tls_reader_t *reader; + + /* process message */ + reader = tls_reader_create(this->encoding); + reader->read_uint32(reader, &this->vendor_id); + reader->read_uint32(reader, &this->parameters_type); + + if (!reader->read_data32(reader, &this->remediation_string)) + { + DBG1(DBG_TNC, "could not parse remediation string"); + reader->destroy(reader); + *offset = 8; + return FAILED; + }; + this->remediation_string = chunk_clone(this->remediation_string); + + if (this->remediation_string.len && + this->remediation_string.ptr[this->remediation_string.len-1] == '\0') + { + DBG1(DBG_TNC, "remediation string must not be null terminated"); + reader->destroy(reader); + *offset = 11 + this->remediation_string.len; + return FAILED; + } + + if (!reader->read_data8(reader, &this->language_code)) + { + DBG1(DBG_TNC, "could not parse language code"); + reader->destroy(reader); + *offset = 12 + this->remediation_string.len; + return FAILED; + }; + this->language_code = chunk_clone(this->language_code); + reader->destroy(reader); + + if (this->language_code.len && + this->language_code.ptr[this->language_code.len-1] == '\0') + { + DBG1(DBG_TNC, "language code must not be null terminated"); + *offset = 12 + this->remediation_string.len + this->language_code.len; + return FAILED; + } + + return SUCCESS; +} + +METHOD(pb_tnc_msg_t, destroy, void, + private_pb_remediation_parameters_msg_t *this) +{ + free(this->encoding.ptr); + free(this->remediation_string.ptr); + free(this->language_code.ptr); + free(this); +} + +METHOD(pb_remediation_parameters_msg_t, get_vendor_id, u_int32_t, + private_pb_remediation_parameters_msg_t *this, u_int32_t *type) +{ + *type = this->parameters_type; + return this->vendor_id; +} + +METHOD(pb_remediation_parameters_msg_t, get_remediation_string, chunk_t, + private_pb_remediation_parameters_msg_t *this) +{ + return this->remediation_string; +} + +METHOD(pb_remediation_parameters_msg_t, get_language_code, chunk_t, + private_pb_remediation_parameters_msg_t *this) +{ + return this->language_code; +} + +/** + * See header + */ +pb_tnc_msg_t *pb_remediation_parameters_msg_create_from_data(chunk_t data) +{ + private_pb_remediation_parameters_msg_t *this; + + INIT(this, + .public = { + .pb_interface = { + .get_type = _get_type, + .get_encoding = _get_encoding, + .build = _build, + .process = _process, + .destroy = _destroy, + }, + .get_vendor_id = _get_vendor_id, + .get_remediation_string = _get_remediation_string, + .get_language_code = _get_language_code, + }, + .type = PB_MSG_REASON_STRING, + .encoding = chunk_clone(data), + ); + + return &this->public.pb_interface; +} + +/** + * See header + */ +pb_tnc_msg_t* pb_remediation_parameters_msg_create(u_int32_t vendor_id, + u_int32_t type, + chunk_t remediation_string, + chunk_t language_code) +{ + private_pb_remediation_parameters_msg_t *this; + + INIT(this, + .public = { + .pb_interface = { + .get_type = _get_type, + .get_encoding = _get_encoding, + .build = _build, + .process = _process, + .destroy = _destroy, + }, + .get_vendor_id = _get_vendor_id, + .get_remediation_string = _get_remediation_string, + .get_language_code = _get_language_code, + }, + .type = PB_MSG_REASON_STRING, + .vendor_id = vendor_id, + .parameters_type = type, + .remediation_string = chunk_clone(remediation_string), + .language_code = chunk_clone(language_code), + ); + + return &this->public.pb_interface; +} diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_remediation_parameters_msg.h b/src/libcharon/plugins/tnccs_20/messages/pb_remediation_parameters_msg.h new file mode 100644 index 000000000..258d495ec --- /dev/null +++ b/src/libcharon/plugins/tnccs_20/messages/pb_remediation_parameters_msg.h @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2010 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. + */ + +/** + * @defgroup pb_remediation_parameters_msg pb_remediation_parameters_msg + * @{ @ingroup tnccs_20 + */ + +#ifndef PB_REMEDIATION_PARAMETERS_MSG_H_ +#define PB_REMEDIATION_PARAMETERS_MSG_H_ + +typedef enum pb_tnc_remed_param_type_t pb_tnc_remed_param_type_t; +typedef struct pb_remediation_parameters_msg_t pb_remediation_parameters_msg_t; + +#include "pb_tnc_msg.h" + +/** + * PB-TNC Remediation Parameter Types as defined in section 4.8.1 of RFC 5793 + */ +enum pb_tnc_remed_param_type_t { + PB_REMEDIATION_URI = 1, + PB_REMEDIATION_STRING = 2, +}; + +/** + * enum name for pb_tnc_remed_param_type_t. + */ +extern enum_name_t *pb_tnc_remed_param_type_names; + +/** + * Class representing the PB-Remediation-Parameters message type. + */ +struct pb_remediation_parameters_msg_t { + + /** + * PB-TNC Message interface + */ + pb_tnc_msg_t pb_interface; + + /** + * Get Remediation Parameters Vendor ID and Type + * + * @param type Remediation Parameters Type + * @return Remediation Parameters Vendor ID + */ + u_int32_t (*get_vendor_id)(pb_remediation_parameters_msg_t *this, + u_int32_t *type); + + /** + * Get Remediation String + * + * @return Remediation String + */ + chunk_t (*get_remediation_string)(pb_remediation_parameters_msg_t *this); + + /** + * Get Reason String Language Code + * + * @return Language Code + */ + chunk_t (*get_language_code)(pb_remediation_parameters_msg_t *this); +}; + +/** + * Create a PB-Remediation-Parameters message from parameters + * + * @param vendor_id Remediation Parameters Vendor ID + * @param type Remediation Parameters Type + * @param remediation_string Remediation String + * @param language_code Language Code + */ +pb_tnc_msg_t* pb_remediation_parameters_msg_create(u_int32_t vendor_id, + u_int32_t type, + chunk_t remediation_string, + chunk_t language_code); + +/** + * Create an unprocessed PB-Remediation-Parameters message from raw data + * + * @param data PB-Remediation-Parameters message data + */ +pb_tnc_msg_t* pb_remediation_parameters_msg_create_from_data(chunk_t data); + +#endif /** PB_PA_MSG_H_ @}*/ diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_tnc_msg.c b/src/libcharon/plugins/tnccs_20/messages/pb_tnc_msg.c new file mode 100644 index 000000000..3565c2d84 --- /dev/null +++ b/src/libcharon/plugins/tnccs_20/messages/pb_tnc_msg.c @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2010 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 "pb_tnc_msg.h" +#include "pb_experimental_msg.h" +#include "pb_pa_msg.h" +#include "pb_error_msg.h" +#include "pb_language_preference_msg.h" +#include "pb_assessment_result_msg.h" +#include "pb_access_recommendation_msg.h" +#include "pb_remediation_parameters_msg.h" +#include "pb_reason_string_msg.h" + +#include <library.h> + +ENUM(pb_tnc_msg_type_names, PB_MSG_EXPERIMENTAL, PB_MSG_REASON_STRING, + "PB-Experimental", + "PB-PA", + "PB-Assessment-Result", + "PB-Access-Recommendation", + "PB-Remediation-Parameters", + "PB-Error", + "PB-Language-Preference", + "PB-Reason-String" +); + +pb_tnc_msg_info_t pb_tnc_msg_infos[] = { + { 12, FALSE, FALSE, TRUE_OR_FALSE }, + { 24, FALSE, FALSE, TRUE }, + { 16, TRUE, TRUE, TRUE }, + { 16, TRUE, TRUE, FALSE }, + { 20, FALSE, TRUE, FALSE }, + { 20, FALSE, FALSE, TRUE }, + { 12, FALSE, FALSE, FALSE }, + { 17, FALSE, TRUE, FALSE }, +}; + +/** + * See header + */ +pb_tnc_msg_t* pb_tnc_msg_create_from_data(pb_tnc_msg_type_t type, chunk_t value) +{ + switch (type) + { + case PB_MSG_PA: + return pb_pa_msg_create_from_data(value); + case PB_MSG_ERROR: + return pb_error_msg_create_from_data(value); + case PB_MSG_EXPERIMENTAL: + return pb_experimental_msg_create_from_data(value); + case PB_MSG_LANGUAGE_PREFERENCE: + return pb_language_preference_msg_create_from_data(value); + case PB_MSG_ASSESSMENT_RESULT: + return pb_assessment_result_msg_create_from_data(value); + case PB_MSG_ACCESS_RECOMMENDATION: + return pb_access_recommendation_msg_create_from_data(value); + case PB_MSG_REMEDIATION_PARAMETERS: + return pb_remediation_parameters_msg_create_from_data(value); + case PB_MSG_REASON_STRING: + return pb_reason_string_msg_create_from_data(value); + } + return NULL; +} diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_tnc_msg.h b/src/libcharon/plugins/tnccs_20/messages/pb_tnc_msg.h new file mode 100644 index 000000000..e20c8d8ff --- /dev/null +++ b/src/libcharon/plugins/tnccs_20/messages/pb_tnc_msg.h @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2010 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. + */ + +/** + * @defgroup pb_tnc_msg pb_tnc_msg + * @{ @ingroup tnccs_20 + */ + +#ifndef PB_TNC_MSG_H_ +#define PB_TNC_MSG_H_ + +typedef enum pb_tnc_msg_type_t pb_tnc_msg_type_t; +typedef struct pb_tnc_msg_info_t pb_tnc_msg_info_t; +typedef struct pb_tnc_msg_t pb_tnc_msg_t; + +#include <library.h> + +#define PB_TNC_VERSION 2 + +/** + * PB-TNC Message Types as defined in section 4.3 of RFC 5793 + */ +enum pb_tnc_msg_type_t { + PB_MSG_EXPERIMENTAL = 0, + PB_MSG_PA = 1, + PB_MSG_ASSESSMENT_RESULT = 2, + PB_MSG_ACCESS_RECOMMENDATION = 3, + PB_MSG_REMEDIATION_PARAMETERS = 4, + PB_MSG_ERROR = 5, + PB_MSG_LANGUAGE_PREFERENCE = 6, + PB_MSG_REASON_STRING = 7, + PB_MSG_ROOF = 7 +}; + +/** + * enum name for pb_tnc_msg_type_t. + */ +extern enum_name_t *pb_tnc_msg_type_names; + +/** + * Information entry describing a PB-TNC Message Type + */ +struct pb_tnc_msg_info_t { + u_int32_t min_size; + bool exact_size; + bool in_result_batch; + bool has_noskip_flag; +}; + +#define TRUE_OR_FALSE 2 + +/** + * Information on PB-TNC Message Types + */ +extern pb_tnc_msg_info_t pb_tnc_msg_infos[]; + +/** + * Generic interface for all PB-TNC message types. + * + * To handle all messages in a generic way, this interface + * must be implemented by each message type. + */ +struct pb_tnc_msg_t { + + /** + * Get the PB-TNC Message Type + * + * @return PB-TNC Message Type + */ + pb_tnc_msg_type_t (*get_type)(pb_tnc_msg_t *this); + + /** + * Get the encoding of the PB-TNC Message Value + * + * @return encoded PB-TNC Message Value + */ + chunk_t (*get_encoding)(pb_tnc_msg_t *this); + + /** + * Build the PB-TNC Message Value + */ + void (*build)(pb_tnc_msg_t *this); + + /** + * Process the PB-TNC Message Value + * + * @param relative offset where an error occurred + * @return return processing status + */ + status_t (*process)(pb_tnc_msg_t *this, u_int32_t *offset); + + /** + * Get a new reference to the message. + * + * @return this, with an increased refcount + */ + pb_tnc_msg_t* (*get_ref)(pb_tnc_msg_t *this); + + /** + * Destroys a pb_tnc_msg_t object. + */ + void (*destroy)(pb_tnc_msg_t *this); +}; + +/** + * Create an unprocessed PB-TNC message + * + * Useful for the parser which wants a generic constructor for all + * pb_tnc_message_t types. + * + * @param type PB-TNC message type + * @param value PB-TNC message value + */ +pb_tnc_msg_t* pb_tnc_msg_create_from_data(pb_tnc_msg_type_t type, chunk_t value); + +#endif /** PB_TNC_MSG_H_ @}*/ diff --git a/src/libcharon/plugins/tnccs_20/state_machine/pb_tnc_state_machine.c b/src/libcharon/plugins/tnccs_20/state_machine/pb_tnc_state_machine.c new file mode 100644 index 000000000..a46dc0ab9 --- /dev/null +++ b/src/libcharon/plugins/tnccs_20/state_machine/pb_tnc_state_machine.c @@ -0,0 +1,287 @@ +/* + * Copyright (C) 2010 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 "pb_tnc_state_machine.h" + +#include <debug.h> + +ENUM(pb_tnc_state_names, PB_STATE_INIT, PB_STATE_END, + "Init", + "Server Working", + "Client Working", + "Decided", + "End" +); + +/** + * PB-TNC State Machine (see section 3.2 of RFC 5793) + * + * Receive CRETRY SRETRY + * or SRETRY +----------------+ + * +--+ | | + * v | v | + * +---------+ CRETRY +---------+ + * CDATA | Server |<---------| Decided | CLOSE + * +----------->| Working |--------->| |-------+ + * | +---------+ RESULT +---------+ | + * | ^ | | v + * | | | +---------------------->======= + * ======== | | CLOSE " End " + * " Init " CDATA| |SDATA ======= + * ======== | | ^ ^ + * | | | v | | + * | | SDATA +---------+ CLOSE | | + * | +-------->| Client |----------------------+ | + * | | Working | | + * | +---------+ | + * | | ^ | + * | +--+ | + * | Receive CRETRY | + * | CLOSE | + * +--------------------------------------------------+ + */ + +typedef struct private_pb_tnc_state_machine_t private_pb_tnc_state_machine_t; + +/** + * Private data of a pb_tnc_state_machine_t object. + * + */ +struct private_pb_tnc_state_machine_t { + /** + * Public pb_pa_message_t interface. + */ + pb_tnc_state_machine_t public; + + /** + * PB-TNC Server if TRUE, PB-TNC Client if FALSE + */ + bool is_server; + + /** + * Current PB-TNC state + */ + pb_tnc_state_t state; +}; + +METHOD(pb_tnc_state_machine_t, get_state, pb_tnc_state_t, + private_pb_tnc_state_machine_t *this) +{ + return this->state; +} + +METHOD(pb_tnc_state_machine_t, receive_batch, bool, + private_pb_tnc_state_machine_t *this, pb_tnc_batch_type_t type) +{ + pb_tnc_state_t old_state = this->state; + + switch (this->state) + { + case PB_STATE_INIT: + if (this->is_server && type == PB_BATCH_CDATA) + { + this->state = PB_STATE_SERVER_WORKING; + break; + } + if (!this->is_server && type == PB_BATCH_SDATA) + { + this->state = PB_STATE_CLIENT_WORKING; + break; + } + if (type == PB_BATCH_CLOSE) + { + this->state = PB_STATE_END; + break; + } + return FALSE; + case PB_STATE_SERVER_WORKING: + if (!this->is_server && type == PB_BATCH_SDATA) + { + this->state = PB_STATE_CLIENT_WORKING; + break; + } + if (!this->is_server && type == PB_BATCH_RESULT) + { + this->state = PB_STATE_DECIDED; + break; + } + if ((this->is_server && type == PB_BATCH_CRETRY) || + (!this->is_server && type == PB_BATCH_SRETRY)) + { + break; + } + if (type == PB_BATCH_CLOSE) + { + this->state = PB_STATE_END; + break; + } + return FALSE; + case PB_STATE_CLIENT_WORKING: + if (this->is_server && type == PB_BATCH_CDATA) + { + this->state = PB_STATE_SERVER_WORKING; + break; + } + if (this->is_server && type == PB_BATCH_CRETRY) + { + break; + } + if (type == PB_BATCH_CLOSE) + { + this->state = PB_STATE_END; + break; + } + return FALSE; + case PB_STATE_DECIDED: + if ((this->is_server && type == PB_BATCH_CRETRY) || + (!this->is_server && type == PB_BATCH_SRETRY)) + { + this->state = PB_STATE_SERVER_WORKING; + break; + } + if (type == PB_BATCH_CLOSE) + { + this->state = PB_STATE_END; + break; + } + return FALSE; + case PB_STATE_END: + if (type == PB_BATCH_CLOSE) + { + break; + } + return FALSE; + } + + if (this->state != old_state) + { + DBG2(DBG_TNC, "PB-TNC state transition from '%N' to '%N'", + pb_tnc_state_names, old_state, pb_tnc_state_names, this->state); + } + return TRUE; +} + +METHOD(pb_tnc_state_machine_t, send_batch, bool, + private_pb_tnc_state_machine_t *this, pb_tnc_batch_type_t type) +{ + pb_tnc_state_t old_state = this->state; + + switch (this->state) + { + case PB_STATE_INIT: + if (!this->is_server && type == PB_BATCH_CDATA) + { + this->state = PB_STATE_SERVER_WORKING; + break; + } + if (this->is_server && type == PB_BATCH_SDATA) + { + this->state = PB_STATE_CLIENT_WORKING; + break; + } + if (type == PB_BATCH_CLOSE) + { + this->state = PB_STATE_END; + break; + } + return FALSE; + case PB_STATE_SERVER_WORKING: + if (this->is_server && type == PB_BATCH_SDATA) + { + this->state = PB_STATE_CLIENT_WORKING; + break; + } + if (this->is_server && type == PB_BATCH_RESULT) + { + this->state = PB_STATE_DECIDED; + break; + } + if (this->is_server && type == PB_BATCH_SRETRY) + { + break; + } + if (type == PB_BATCH_CLOSE) + { + this->state = PB_STATE_END; + break; + } + return FALSE; + case PB_STATE_CLIENT_WORKING: + if (!this->is_server && type == PB_BATCH_CDATA) + { + this->state = PB_STATE_SERVER_WORKING; + break; + } + if (type == PB_BATCH_CLOSE) + { + this->state = PB_STATE_END; + break; + } + return FALSE; + case PB_STATE_DECIDED: + if ((this->is_server && type == PB_BATCH_SRETRY) || + (!this->is_server && type == PB_BATCH_CRETRY)) + { + this->state = PB_STATE_SERVER_WORKING; + break; + } + if (type == PB_BATCH_CLOSE) + { + this->state = PB_STATE_END; + break; + } + return FALSE; + case PB_STATE_END: + if (type == PB_BATCH_CLOSE) + { + break; + } + return FALSE; + } + + if (this->state != old_state) + { + DBG2(DBG_TNC, "PB-TNC state transition from '%N' to '%N'", + pb_tnc_state_names, old_state, pb_tnc_state_names, this->state); + } + return TRUE; +} + +METHOD(pb_tnc_state_machine_t, destroy, void, + private_pb_tnc_state_machine_t *this) +{ + free(this); +} + +/** + * See header + */ +pb_tnc_state_machine_t* pb_tnc_state_machine_create(bool is_server) +{ + private_pb_tnc_state_machine_t *this; + + INIT(this, + .public = { + .get_state = _get_state, + .receive_batch = _receive_batch, + .send_batch = _send_batch, + .destroy = _destroy, + }, + .is_server = is_server, + .state = PB_STATE_INIT, + ); + + return &this->public; +} diff --git a/src/libcharon/plugins/tnccs_20/state_machine/pb_tnc_state_machine.h b/src/libcharon/plugins/tnccs_20/state_machine/pb_tnc_state_machine.h new file mode 100644 index 000000000..8076b6ded --- /dev/null +++ b/src/libcharon/plugins/tnccs_20/state_machine/pb_tnc_state_machine.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2010 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. + */ + +/** + * @defgroup pb_tnc_state_machine pb_tnc_state_machine + * @{ @ingroup tnccs_20 + */ + +#ifndef PB_TNC_STATE_MACHINE_H_ +#define PB_TNC_STATE_MACHINE_H_ + +typedef struct pb_tnc_state_machine_t pb_tnc_state_machine_t; +typedef enum pb_tnc_state_t pb_tnc_state_t; + +#include "batch/pb_tnc_batch.h" + +#include <library.h> + +/** + * PB-TNC States (state machine) as defined in section 3.2 of RFC 5793 + */ +enum pb_tnc_state_t { + PB_STATE_INIT, + PB_STATE_SERVER_WORKING, + PB_STATE_CLIENT_WORKING, + PB_STATE_DECIDED, + PB_STATE_END, +}; + +/** + * enum name for pb_tnc_state_t. + */ +extern enum_name_t *pb_tnc_state_names; + +/** + * Interface for the PB-TNC state machine. + */ +struct pb_tnc_state_machine_t { + + /** + * Get the current PB-TNC STATE + * + * @return current state + */ + pb_tnc_state_t (*get_state)(pb_tnc_state_machine_t *this); + + /** + * Compute state transition due to received PB-TNC Batch + * + * @param type type of received batch + * @result TRUE if a valid transition was found, FALSE otherwise + */ + bool (*receive_batch)(pb_tnc_state_machine_t *this, pb_tnc_batch_type_t type); + + /** + * Compute state transition due to sent PB-TNC Batch + * + * @param type type of sent batch + * @result TRUE if a valid transition was found, FALSE otherwise + */ + bool (*send_batch)(pb_tnc_state_machine_t *this, pb_tnc_batch_type_t type); + + /** + * Destroys a pb_tnc_state_machine_t object. + */ + void (*destroy)(pb_tnc_state_machine_t *this); +}; + +/** + * Create and initialize a PB-TNC state machine + * + * @param is_server TRUE if PB-TNC server, FALSE if PB-TNC client + */ +pb_tnc_state_machine_t* pb_tnc_state_machine_create(bool is_server); + +#endif /** PB_TNC_STATE_MACHINE_H_ @}*/ diff --git a/src/libcharon/plugins/tnccs_20/tnccs_20.c b/src/libcharon/plugins/tnccs_20/tnccs_20.c index 2bd1bc476..d53fd8eb7 100644 --- a/src/libcharon/plugins/tnccs_20/tnccs_20.c +++ b/src/libcharon/plugins/tnccs_20/tnccs_20.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2010 Sansar Choinyanbuu * Copyright (C) 2010 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * @@ -14,10 +15,23 @@ */ #include "tnccs_20.h" +#include "batch/pb_tnc_batch.h" +#include "messages/pb_tnc_msg.h" +#include "messages/pb_pa_msg.h" +#include "messages/pb_error_msg.h" +#include "messages/pb_assessment_result_msg.h" +#include "messages/pb_access_recommendation_msg.h" +#include "messages/pb_remediation_parameters_msg.h" +#include "messages/pb_reason_string_msg.h" +#include "messages/pb_language_preference_msg.h" +#include "state_machine/pb_tnc_state_machine.h" #include <debug.h> - -static chunk_t tncc_output; +#include <daemon.h> +#include <threading/mutex.h> +#include <tnc/tncif.h> +#include <tnc/tncifimv.h> +#include <tnc/tnccs/tnccs.h> typedef struct private_tnccs_20_t private_tnccs_20_t; @@ -35,18 +49,541 @@ struct private_tnccs_20_t { * TNCC if TRUE, TNCS if FALSE */ bool is_server; + + /** + * PB-TNC State Machine + */ + pb_tnc_state_machine_t *state_machine; + + /** + * Connection ID assigned to this TNCCS connection + */ + TNC_ConnectionID connection_id; + + /** + * PB-TNC batch being constructed + */ + pb_tnc_batch_t *batch; + + /** + * Mutex locking the batch in construction + */ + mutex_t *mutex; + + /** + * Flag set while processing + */ + bool fatal_error; + + /** + * Flag set by IMC/IMV RequestHandshakeRetry() function + */ + bool request_handshake_retry; + + /** + * Set of IMV recommendations (TNC Server only) + */ + recommendations_t *recs; }; +METHOD(tnccs_t, send_msg, void, + private_tnccs_20_t* this, TNC_IMCID imc_id, TNC_IMVID imv_id, + TNC_BufferReference msg, + TNC_UInt32 msg_len, + TNC_MessageType msg_type) +{ + TNC_MessageSubtype msg_sub_type; + TNC_VendorID msg_vendor_id; + pb_tnc_msg_t *pb_tnc_msg; + pb_tnc_batch_type_t batch_type; + + msg_sub_type = msg_type & TNC_SUBTYPE_ANY; + msg_vendor_id = (msg_type >> 8) & TNC_VENDORID_ANY; + + pb_tnc_msg = pb_pa_msg_create(msg_vendor_id, msg_sub_type, imc_id, imv_id, + chunk_create(msg, msg_len)); + + /* adding PA message to SDATA or CDATA batch only */ + batch_type = this->is_server ? PB_BATCH_SDATA : PB_BATCH_CDATA; + this->mutex->lock(this->mutex); + if (!this->batch) + { + this->batch = pb_tnc_batch_create(this->is_server, batch_type); + } + if (this->batch->get_type(this->batch) == batch_type) + { + this->batch->add_msg(this->batch, pb_tnc_msg); + } + else + { + pb_tnc_msg->destroy(pb_tnc_msg); + } + this->mutex->unlock(this->mutex); +} + +/** + * Handle a single PB-TNC message according to its type + */ +static void handle_message(private_tnccs_20_t *this, pb_tnc_msg_t *msg) +{ + switch (msg->get_type(msg)) + { + case PB_MSG_EXPERIMENTAL: + /* nothing to do */ + break; + case PB_MSG_PA: + { + pb_pa_msg_t *pa_msg; + TNC_MessageType msg_type; + u_int32_t vendor_id, subtype; + chunk_t msg_body; + + pa_msg = (pb_pa_msg_t*)msg; + vendor_id = pa_msg->get_vendor_id(pa_msg, &subtype); + msg_type = (vendor_id << 8) | (subtype & 0xff); + msg_body = pa_msg->get_body(pa_msg); + + DBG2(DBG_TNC, "handling PB-PA message type 0x%08x", msg_type); + + if (this->is_server) + { + charon->imvs->receive_message(charon->imvs, + this->connection_id, msg_body.ptr, msg_body.len, msg_type); + } + else + { + charon->imcs->receive_message(charon->imcs, + this->connection_id, msg_body.ptr, msg_body.len,msg_type); + } + break; + } + case PB_MSG_ASSESSMENT_RESULT: + { + pb_assessment_result_msg_t *assess_msg; + u_int32_t result; + + assess_msg = (pb_assessment_result_msg_t*)msg; + result = assess_msg->get_assessment_result(assess_msg); + DBG1(DBG_TNC, "PB-TNC assessment result is '%N'", + TNC_IMV_Evaluation_Result_names, result); + break; + } + case PB_MSG_ACCESS_RECOMMENDATION: + { + pb_access_recommendation_msg_t *rec_msg; + pb_access_recommendation_code_t rec; + TNC_ConnectionState state = TNC_CONNECTION_STATE_ACCESS_NONE; + + rec_msg = (pb_access_recommendation_msg_t*)msg; + rec = rec_msg->get_access_recommendation(rec_msg); + DBG1(DBG_TNC, "PB-TNC access recommendation is '%N'", + pb_access_recommendation_code_names, rec); + switch (rec) + { + case PB_REC_ACCESS_ALLOWED: + state = TNC_CONNECTION_STATE_ACCESS_ALLOWED; + break; + case PB_REC_ACCESS_DENIED: + state = TNC_CONNECTION_STATE_ACCESS_NONE; + break; + case PB_REC_QUARANTINED: + state = TNC_CONNECTION_STATE_ACCESS_ISOLATED; + } + charon->imcs->notify_connection_change(charon->imcs, + this->connection_id, state); + break; + } + case PB_MSG_REMEDIATION_PARAMETERS: + { + /* TODO : Remediation parameters message processing */ + break; + } + case PB_MSG_ERROR: + { + pb_error_msg_t *err_msg; + bool fatal; + u_int32_t vendor_id; + u_int16_t error_code; + + err_msg = (pb_error_msg_t*)msg; + fatal = err_msg->get_fatal_flag(err_msg); + vendor_id = err_msg->get_vendor_id(err_msg); + error_code = err_msg->get_error_code(err_msg); + + if (fatal) + { + this->fatal_error = TRUE; + } + + if (vendor_id == IETF_VENDOR_ID) + { + switch (error_code) + { + case PB_ERROR_INVALID_PARAMETER: + case PB_ERROR_UNSUPPORTED_MANDATORY_MSG: + DBG1(DBG_TNC, "received %s PB-TNC error '%N' " + "(offset %u bytes)", + fatal ? "fatal" : "non-fatal", + pb_tnc_error_code_names, error_code, + err_msg->get_offset(err_msg)); + break; + case PB_ERROR_VERSION_NOT_SUPPORTED: + DBG1(DBG_TNC, "received %s PB-TNC error '%N' " + "caused by bad version 0x%02x", + fatal ? "fatal" : "non-fatal", + pb_tnc_error_code_names, error_code, + err_msg->get_bad_version(err_msg)); + break; + case PB_ERROR_UNEXPECTED_BATCH_TYPE: + case PB_ERROR_LOCAL_ERROR: + default: + DBG1(DBG_TNC, "received %s PB-TNC error '%N'", + fatal ? "fatal" : "non-fatal", + pb_tnc_error_code_names, error_code); + break; + } + } + else + { + DBG1(DBG_TNC, "received %s PB-TNC error (%u) " + "with Vendor ID 0x%06x", + fatal ? "fatal" : "non-fatal", + error_code, vendor_id); + } + break; + } + case PB_MSG_LANGUAGE_PREFERENCE: + { + pb_language_preference_msg_t *lang_msg; + chunk_t lang; + + lang_msg = (pb_language_preference_msg_t*)msg; + lang = lang_msg->get_language_preference(lang_msg); + + DBG2(DBG_TNC, "setting language preference to '%.*s'", + lang.len, lang.ptr); + this->recs->set_preferred_language(this->recs, lang); + break; + } + case PB_MSG_REASON_STRING: + { + pb_reason_string_msg_t *reason_msg; + chunk_t reason_string, language_code; + + reason_msg = (pb_reason_string_msg_t*)msg; + reason_string = reason_msg->get_reason_string(reason_msg); + language_code = reason_msg->get_language_code(reason_msg); + DBG2(DBG_TNC, "reason string is '%.*s", reason_string.len, + reason_string.ptr); + DBG2(DBG_TNC, "language code is '%.*s", language_code.len, + language_code.ptr); + break; + } + default: + break; + } +} + +/** + * Build a CRETRY or SRETRY batch + */ +static void build_retry_batch(private_tnccs_20_t *this) +{ + if (this->batch) + { + DBG1(DBG_TNC, "cancelling PB-TNC %N batch", + pb_tnc_batch_type_names, this->batch->get_type(this->batch)); + this->batch->destroy(this->batch); + } + this->batch = pb_tnc_batch_create(this->is_server, + this->is_server ? PB_BATCH_SRETRY : PB_BATCH_CRETRY); +} + METHOD(tls_t, process, status_t, private_tnccs_20_t *this, void *buf, size_t buflen) { + chunk_t data; + pb_tnc_batch_t *batch; + pb_tnc_msg_t *msg; + enumerator_t *enumerator; + status_t status; + + if (this->is_server && !this->connection_id) + { + this->connection_id = charon->tnccs->create_connection(charon->tnccs, + (tnccs_t*)this, _send_msg, + &this->request_handshake_retry, &this->recs); + if (!this->connection_id) + { + return FAILED; + } + charon->imvs->notify_connection_change(charon->imvs, + this->connection_id, TNC_CONNECTION_STATE_CREATE); + } + + data = chunk_create(buf, buflen); + DBG1(DBG_TNC, "received TNCCS batch (%u bytes) for Connection ID %u", + data.len, this->connection_id); + DBG3(DBG_TNC, "%B", &data); + batch = pb_tnc_batch_create_from_data(this->is_server, data); + status = batch->process(batch, this->state_machine); + + if (status != FAILED) + { + enumerator_t *enumerator; + pb_tnc_msg_t *msg; + pb_tnc_batch_type_t batch_type; + bool empty = TRUE; + + batch_type = batch->get_type(batch); + + if (batch_type == PB_BATCH_CRETRY) + { + /* Send an SRETRY batch in response */ + this->mutex->lock(this->mutex); + build_retry_batch(this); + this->mutex->unlock(this->mutex); + } + else if (batch_type == PB_BATCH_SRETRY) + { + /* Restart the measurements */ + charon->imcs->notify_connection_change(charon->imcs, + this->connection_id, TNC_CONNECTION_STATE_HANDSHAKE); + charon->imcs->begin_handshake(charon->imcs, this->connection_id); + } + + enumerator = batch->create_msg_enumerator(batch); + while (enumerator->enumerate(enumerator, &msg)) + { + handle_message(this, msg); + empty = FALSE; + } + enumerator->destroy(enumerator); + + /* received an empty CLOSE batch from PB-TNC client */ + if (this->is_server && batch_type == PB_BATCH_CLOSE && empty) + { + batch->destroy(batch); + if (this->fatal_error) + { + DBG1(DBG_TNC, "a fatal PB-TNC error occurred, " + "terminating connection"); + return FAILED; + } + else + { + return SUCCESS; + } + } + + if (this->is_server) + { + charon->imvs->batch_ending(charon->imvs, this->connection_id); + } + else + { + charon->imcs->batch_ending(charon->imcs, this->connection_id); + } + } + + switch (status) + { + case FAILED: + this->fatal_error = TRUE; + this->mutex->lock(this->mutex); + if (this->batch) + { + DBG1(DBG_TNC, "cancelling PB-TNC %N batch", + pb_tnc_batch_type_names, this->batch->get_type(this->batch)); + this->batch->destroy(this->batch); + } + this->batch = pb_tnc_batch_create(this->is_server, PB_BATCH_CLOSE); + this->mutex->unlock(this->mutex); + /* fall through to add error messages to outbound batch */ + case VERIFY_ERROR: + enumerator = batch->create_error_enumerator(batch); + while (enumerator->enumerate(enumerator, &msg)) + { + this->mutex->lock(this->mutex); + this->batch->add_msg(this->batch, msg->get_ref(msg)); + this->mutex->unlock(this->mutex); + } + enumerator->destroy(enumerator); + break; + case SUCCESS: + default: + break; + } + batch->destroy(batch); + return NEED_MORE; } +/** + * Build a RESULT batch if a final recommendation is available + */ +static void check_and_build_recommendation(private_tnccs_20_t *this) +{ + TNC_IMV_Action_Recommendation rec; + TNC_IMV_Evaluation_Result eval; + TNC_IMVID id; + chunk_t reason, language; + enumerator_t *enumerator; + pb_tnc_msg_t *msg; + + if (!this->recs->have_recommendation(this->recs, &rec, &eval)) + { + charon->imvs->solicit_recommendation(charon->imvs, this->connection_id); + } + if (this->recs->have_recommendation(this->recs, &rec, &eval)) + { + this->batch = pb_tnc_batch_create(this->is_server, PB_BATCH_RESULT); + + msg = pb_assessment_result_msg_create(eval); + this->batch->add_msg(this->batch, msg); + + /** + * IMV Action Recommendation and PB Access Recommendation codes + * are shifted by one. + */ + msg = pb_access_recommendation_msg_create(rec + 1); + this->batch->add_msg(this->batch, msg); + + enumerator = this->recs->create_reason_enumerator(this->recs); + while (enumerator->enumerate(enumerator, &id, &reason, &language)) + { + msg = pb_reason_string_msg_create(reason, language); + this->batch->add_msg(this->batch, msg); + } + enumerator->destroy(enumerator); + } +} + METHOD(tls_t, build, status_t, private_tnccs_20_t *this, void *buf, size_t *buflen, size_t *msglen) { - return ALREADY_DONE; + status_t status; + + /* Initialize the connection */ + if (!this->is_server && !this->connection_id) + { + pb_tnc_msg_t *msg; + char *pref_lang; + + this->connection_id = charon->tnccs->create_connection(charon->tnccs, + (tnccs_t*)this, _send_msg, + &this->request_handshake_retry, NULL); + if (!this->connection_id) + { + return FAILED; + } + + /* Create PB-TNC Language Preference message */ + pref_lang = charon->imcs->get_preferred_language(charon->imcs); + msg = pb_language_preference_msg_create(chunk_create(pref_lang, + strlen(pref_lang))); + this->mutex->lock(this->mutex); + this->batch = pb_tnc_batch_create(this->is_server, PB_BATCH_CDATA); + this->batch->add_msg(this->batch, msg); + this->mutex->unlock(this->mutex); + + charon->imcs->notify_connection_change(charon->imcs, + this->connection_id, TNC_CONNECTION_STATE_CREATE); + charon->imcs->notify_connection_change(charon->imcs, + this->connection_id, TNC_CONNECTION_STATE_HANDSHAKE); + charon->imcs->begin_handshake(charon->imcs, this->connection_id); + } + + if (this->is_server && this->fatal_error && + this->state_machine->get_state(this->state_machine) == PB_STATE_END) + { + DBG1(DBG_TNC, "a fatal PB-TNC error occurred, terminating connection"); + return FAILED; + } + + /* Do not allow any asynchronous IMCs or IMVs to add additional messages */ + this->mutex->lock(this->mutex); + + if (this->request_handshake_retry) + { + build_retry_batch(this); + + /* Reset the flag for the next handshake retry request */ + this->request_handshake_retry = FALSE; + } + + if (!this->batch) + { + pb_tnc_state_t state; + + state = this->state_machine->get_state(this->state_machine); + if (this->is_server) + { + if (state == PB_STATE_SERVER_WORKING) + { + check_and_build_recommendation(this); + } + } + else + { + /** + * if the DECIDED state has been reached and no CRETRY is under way + * or if a CLOSE batch with error messages has been received, + * a PB-TNC client replies with an empty CLOSE batch. + */ + if (state == PB_STATE_DECIDED || state == PB_STATE_END) + { + this->batch = pb_tnc_batch_create(this->is_server, PB_BATCH_CLOSE); + } + } + } + + if (this->batch) + { + pb_tnc_batch_type_t batch_type; + chunk_t data; + + batch_type = this->batch->get_type(this->batch); + + if (this->state_machine->send_batch(this->state_machine, batch_type)) + { + this->batch->build(this->batch); + data = this->batch->get_encoding(this->batch); + DBG1(DBG_TNC, "sending PB-TNC %N batch (%d bytes) for Connection ID %u", + pb_tnc_batch_type_names, batch_type, data.len, + this->connection_id); + DBG3(DBG_TNC, "%B", &data); + *msglen = data.len; + + if (data.len > *buflen) + { + DBG1(DBG_TNC, "fragmentation of PB-TNC batch not supported yet"); + } + else + { + *buflen = data.len; + } + memcpy(buf, data.ptr, *buflen); + status = ALREADY_DONE; + } + else + { + DBG1(DBG_TNC, "cancelling unexpected PB-TNC batch type: %N", + pb_tnc_batch_type_names, batch_type); + status = INVALID_STATE; + } + + this->batch->destroy(this->batch); + this->batch = NULL; + } + else + { + DBG1(DBG_TNC, "no PB-TNC batch to send"); + status = INVALID_STATE; + } + this->mutex->unlock(this->mutex); + + return status; } METHOD(tls_t, is_server, bool, @@ -64,7 +601,21 @@ METHOD(tls_t, get_purpose, tls_purpose_t, METHOD(tls_t, is_complete, bool, private_tnccs_20_t *this) { - return FALSE; + TNC_IMV_Action_Recommendation rec; + TNC_IMV_Evaluation_Result eval; + + if (this->recs && this->recs->have_recommendation(this->recs, &rec, &eval)) + { + DBG2(DBG_TNC, "Final recommendation is '%N' and evaluation is '%N'", + TNC_IMV_Action_Recommendation_names, rec, + TNC_IMV_Evaluation_Result_names, eval); + + return charon->imvs->enforce_recommendation(charon->imvs, rec); + } + else + { + return FALSE; + } } METHOD(tls_t, get_eap_msk, chunk_t, @@ -76,6 +627,20 @@ METHOD(tls_t, get_eap_msk, chunk_t, METHOD(tls_t, destroy, void, private_tnccs_20_t *this) { + if (this->is_server) + { + charon->imvs->notify_connection_change(charon->imvs, + this->connection_id, TNC_CONNECTION_STATE_DELETE); + } + else + { + charon->imcs->notify_connection_change(charon->imcs, + this->connection_id, TNC_CONNECTION_STATE_DELETE); + } + charon->tnccs->remove_connection(charon->tnccs, this->connection_id); + this->state_machine->destroy(this->state_machine); + this->mutex->destroy(this->mutex); + DESTROY_IF(this->batch); free(this); } @@ -97,6 +662,8 @@ tls_t *tnccs_20_create(bool is_server) .destroy = _destroy, }, .is_server = is_server, + .state_machine = pb_tnc_state_machine_create(is_server), + .mutex = mutex_create(MUTEX_TYPE_DEFAULT), ); return &this->public; diff --git a/src/libcharon/plugins/tnccs_dynamic/Makefile.am b/src/libcharon/plugins/tnccs_dynamic/Makefile.am new file mode 100644 index 000000000..9a81d065f --- /dev/null +++ b/src/libcharon/plugins/tnccs_dynamic/Makefile.am @@ -0,0 +1,17 @@ + +INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/libtls + +AM_CFLAGS = -rdynamic + +if MONOLITHIC +noinst_LTLIBRARIES = libstrongswan-tnccs-dynamic.la +else +plugin_LTLIBRARIES = libstrongswan-tnccs-dynamic.la +libstrongswan_tnccs_dynamic_la_LIBADD = $(top_builddir)/src/libtls/libtls.la +endif + +libstrongswan_tnccs_dynamic_la_SOURCES = \ + tnccs_dynamic_plugin.h tnccs_dynamic_plugin.c tnccs_dynamic.h tnccs_dynamic.c + +libstrongswan_tnccs_dynamic_la_LDFLAGS = -module -avoid-version diff --git a/src/libcharon/plugins/tnccs_dynamic/Makefile.in b/src/libcharon/plugins/tnccs_dynamic/Makefile.in new file mode 100644 index 000000000..722da2830 --- /dev/null +++ b/src/libcharon/plugins/tnccs_dynamic/Makefile.in @@ -0,0 +1,607 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 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. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@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 +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/libcharon/plugins/tnccs_dynamic +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +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)/m4/macros/add-plugin.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__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' +am__installdirs = "$(DESTDIR)$(plugindir)" +LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES) +@MONOLITHIC_FALSE@libstrongswan_tnccs_dynamic_la_DEPENDENCIES = \ +@MONOLITHIC_FALSE@ $(top_builddir)/src/libtls/libtls.la +am_libstrongswan_tnccs_dynamic_la_OBJECTS = tnccs_dynamic_plugin.lo \ + tnccs_dynamic.lo +libstrongswan_tnccs_dynamic_la_OBJECTS = \ + $(am_libstrongswan_tnccs_dynamic_la_OBJECTS) +libstrongswan_tnccs_dynamic_la_LINK = $(LIBTOOL) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) \ + $(libstrongswan_tnccs_dynamic_la_LDFLAGS) $(LDFLAGS) -o $@ +@MONOLITHIC_FALSE@am_libstrongswan_tnccs_dynamic_la_rpath = -rpath \ +@MONOLITHIC_FALSE@ $(plugindir) +@MONOLITHIC_TRUE@am_libstrongswan_tnccs_dynamic_la_rpath = +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) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libstrongswan_tnccs_dynamic_la_SOURCES) +DIST_SOURCES = $(libstrongswan_tnccs_dynamic_la_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BTLIB = @BTLIB@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLIB = @DLLIB@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GPERF = @GPERF@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +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@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +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@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PTHREADLIB = @PTHREADLIB@ +RANLIB = @RANLIB@ +RTLIB = @RTLIB@ +RUBY = @RUBY@ +RUBYINCLUDE = @RUBYINCLUDE@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKLIB = @SOCKLIB@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +c_plugins = @c_plugins@ +datadir = @datadir@ +datarootdir = @datarootdir@ +dbusservicedir = @dbusservicedir@ +default_pkcs11 = @default_pkcs11@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +gtk_CFLAGS = @gtk_CFLAGS@ +gtk_LIBS = @gtk_LIBS@ +h_plugins = @h_plugins@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +ipsecdir = @ipsecdir@ +ipsecgroup = @ipsecgroup@ +ipsecuser = @ipsecuser@ +libcharon_plugins = @libcharon_plugins@ +libdir = @libdir@ +libexecdir = @libexecdir@ +linux_headers = @linux_headers@ +localedir = @localedir@ +localstatedir = @localstatedir@ +lt_ECHO = @lt_ECHO@ +maemo_CFLAGS = @maemo_CFLAGS@ +maemo_LIBS = @maemo_LIBS@ +manager_plugins = @manager_plugins@ +mandir = @mandir@ +medsrv_plugins = @medsrv_plugins@ +mkdir_p = @mkdir_p@ +nm_CFLAGS = @nm_CFLAGS@ +nm_LIBS = @nm_LIBS@ +nm_ca_dir = @nm_ca_dir@ +oldincludedir = @oldincludedir@ +openac_plugins = @openac_plugins@ +p_plugins = @p_plugins@ +pdfdir = @pdfdir@ +piddir = @piddir@ +pki_plugins = @pki_plugins@ +plugindir = @plugindir@ +pluto_plugins = @pluto_plugins@ +pool_plugins = @pool_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@ +s_plugins = @s_plugins@ +sbindir = @sbindir@ +scepclient_plugins = @scepclient_plugins@ +scripts_plugins = @scripts_plugins@ +sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ +srcdir = @srcdir@ +strongswan_conf = @strongswan_conf@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +urandom_device = @urandom_device@ +xml_CFLAGS = @xml_CFLAGS@ +xml_LIBS = @xml_LIBS@ +INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/libtls + +AM_CFLAGS = -rdynamic +@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-tnccs-dynamic.la +@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-tnccs-dynamic.la +@MONOLITHIC_FALSE@libstrongswan_tnccs_dynamic_la_LIBADD = $(top_builddir)/src/libtls/libtls.la +libstrongswan_tnccs_dynamic_la_SOURCES = \ + tnccs_dynamic_plugin.h tnccs_dynamic_plugin.c tnccs_dynamic.h tnccs_dynamic.c + +libstrongswan_tnccs_dynamic_la_LDFLAGS = -module -avoid-version +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/tnccs_dynamic/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/libcharon/plugins/tnccs_dynamic/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(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): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)" + @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \ + } + +uninstall-pluginLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \ + done + +clean-pluginLTLIBRARIES: + -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES) + @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libstrongswan-tnccs-dynamic.la: $(libstrongswan_tnccs_dynamic_la_OBJECTS) $(libstrongswan_tnccs_dynamic_la_DEPENDENCIES) + $(libstrongswan_tnccs_dynamic_la_LINK) $(am_libstrongswan_tnccs_dynamic_la_rpath) $(libstrongswan_tnccs_dynamic_la_OBJECTS) $(libstrongswan_tnccs_dynamic_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnccs_dynamic.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnccs_dynamic_plugin.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@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@ $(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@ $(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 $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + 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; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + 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; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + 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) + 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)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + 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 -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(plugindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +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" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + clean-pluginLTLIBRARIES mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-pluginLTLIBRARIES + +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-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pluginLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \ + ctags distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-pluginLTLIBRARIES install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags uninstall uninstall-am \ + uninstall-pluginLTLIBRARIES + + +# 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/libcharon/plugins/tnccs_dynamic/tnccs_dynamic.c b/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic.c new file mode 100644 index 000000000..b7985fa51 --- /dev/null +++ b/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic.c @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2011 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 "tnccs_dynamic.h" + +#include <tnc/tnccs/tnccs.h> +#include <daemon.h> + +typedef struct private_tnccs_dynamic_t private_tnccs_dynamic_t; + +/** + * Private data of a tnccs_dynamic_t object. + */ +struct private_tnccs_dynamic_t { + + /** + * Public tls_t interface. + */ + tls_t public; + + /** + * Detected TNC IF-TNCCS stack + */ + tls_t *tls; +}; + +/** + * Determine the version of the IF-TNCCS protocol used by analyzing the first + * byte of the TNCCS batch received from a TNC Client according to the rules + * defined by section 3.5 "Interoperability with older IF-TNCCS versions" of + * the TCG TNC IF-TNCCS TLV Bindings Version 2.0 standard. + */ +tnccs_type_t determine_tnccs_protocol(char version) +{ + switch (version) + { + case '\t': + case '\n': + case '\r': + case ' ': + case '<': + return TNCCS_1_1; + case 0x00: + return TNCCS_SOH; + case 0x02: + return TNCCS_2_0; + default: + return TNCCS_UNKNOWN; + } +} + +METHOD(tls_t, process, status_t, + private_tnccs_dynamic_t *this, void *buf, size_t buflen) +{ + tnccs_type_t type; + + if (!this->tls) + { + if (buflen == 0) + { + return FAILED; + } + type = determine_tnccs_protocol(*(char*)buf); + DBG1(DBG_TNC, "%N protocol detected dynamically", + tnccs_type_names, type); + this->tls = (tls_t*)charon->tnccs->create_instance(charon->tnccs, + type, TRUE); + if (!this->tls) + { + DBG1(DBG_TNC, "N% protocol not supported", tnccs_type_names, type); + return FAILED; + } + } + return this->tls->process(this->tls, buf, buflen); +} + +METHOD(tls_t, build, status_t, + private_tnccs_dynamic_t *this, void *buf, size_t *buflen, size_t *msglen) +{ + return this->tls->build(this->tls, buf, buflen, msglen); +} + +METHOD(tls_t, is_server, bool, + private_tnccs_dynamic_t *this) +{ + return TRUE; +} + +METHOD(tls_t, get_purpose, tls_purpose_t, + private_tnccs_dynamic_t *this) +{ + return TLS_PURPOSE_EAP_TNC; +} + +METHOD(tls_t, is_complete, bool, + private_tnccs_dynamic_t *this) +{ + return this->tls ? this->tls->is_complete(this->tls) : FALSE; +} + +METHOD(tls_t, get_eap_msk, chunk_t, + private_tnccs_dynamic_t *this) +{ + return chunk_empty; +} + +METHOD(tls_t, destroy, void, + private_tnccs_dynamic_t *this) +{ + DESTROY_IF(this->tls); + free(this); +} + +/** + * See header + */ +tls_t *tnccs_dynamic_create(bool is_server) +{ + private_tnccs_dynamic_t *this; + + INIT(this, + .public = { + .process = _process, + .build = _build, + .is_server = _is_server, + .get_purpose = _get_purpose, + .is_complete = _is_complete, + .get_eap_msk = _get_eap_msk, + .destroy = _destroy, + }, + ); + + return &this->public; +} diff --git a/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic.h b/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic.h new file mode 100644 index 000000000..42410b17f --- /dev/null +++ b/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2011 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. + */ + +/** + * @defgroup tnccs_dynamic_h tnccs_dynamic + * @{ @ingroup tnccs_dynamic + */ + +#ifndef TNCCS_DYNAMIC_H_ +#define TNCCS_DYNAMIC_H_ + +#include <library.h> + +#include <tls.h> + +/** + * Create an instance of a dynamic TNC IF-TNCCS protocol handler. + * + * @param is_server TRUE to act as TNC Server, FALSE for TNC Client + * @return dynamic TNC IF-TNCCS protocol stack + */ +tls_t *tnccs_dynamic_create(bool is_server); + +#endif /** TNCCS_DYNAMIC_H_ @}*/ diff --git a/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic_plugin.c b/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic_plugin.c new file mode 100644 index 000000000..dbbf222e0 --- /dev/null +++ b/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic_plugin.c @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2011 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 "tnccs_dynamic_plugin.h" +#include "tnccs_dynamic.h" + +#include <daemon.h> + +METHOD(plugin_t, destroy, void, + tnccs_dynamic_plugin_t *this) +{ + charon->tnccs->remove_method(charon->tnccs, + (tnccs_constructor_t)tnccs_dynamic_create); + free(this); +} + +/* + * see header file + */ +plugin_t *tnccs_dynamic_plugin_create() +{ + tnccs_dynamic_plugin_t *this; + + INIT(this, + .plugin = { + .destroy = _destroy, + }, + ); + + charon->tnccs->add_method(charon->tnccs, TNCCS_DYNAMIC, + (tnccs_constructor_t)tnccs_dynamic_create); + + return &this->plugin; +} + diff --git a/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic_plugin.h b/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic_plugin.h new file mode 100644 index 000000000..b518e1278 --- /dev/null +++ b/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic_plugin.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2011 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. + */ + +/** + * @defgroup tnccs_dynamic tnccs_dynamic + * @ingroup cplugins + * + * @defgroup tnccs_dynamic_plugin tnccs_dynamic_plugin + * @{ @ingroup tnccs_dynamic + */ + +#ifndef TNCCS_DYNAMIC_PLUGIN_H_ +#define TNCCS_DYNAMIC_PLUGIN_H_ + +#include <plugins/plugin.h> + +typedef struct tnccs_dynamic_plugin_t tnccs_dynamic_plugin_t; + +/** + * EAP-TNC plugin + */ +struct tnccs_dynamic_plugin_t { + + /** + * implements plugin interface + */ + plugin_t plugin; +}; + +#endif /** TNCCS_DYNAMIC_PLUGIN_H_ @}*/ diff --git a/src/libcharon/plugins/uci/Makefile.in b/src/libcharon/plugins/uci/Makefile.in index 9cb5f794a..f7162d800 100644 --- a/src/libcharon/plugins/uci/Makefile.in +++ b/src/libcharon/plugins/uci/Makefile.in @@ -220,9 +220,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -261,6 +259,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libcharon/plugins/uci/uci_config.c b/src/libcharon/plugins/uci/uci_config.c index ddddae782..4e43388ec 100644 --- a/src/libcharon/plugins/uci/uci_config.c +++ b/src/libcharon/plugins/uci/uci_config.c @@ -196,8 +196,8 @@ static bool peer_enumerator_enumerate(peer_enumerator_t *this, peer_cfg_t **cfg) this->peer_cfg->add_auth_cfg(this->peer_cfg, auth, FALSE); child_cfg = child_cfg_create(name, &lifetime, NULL, TRUE, MODE_TUNNEL, - ACTION_NONE, ACTION_NONE, FALSE, 0, 0, - NULL, NULL); + ACTION_NONE, ACTION_NONE, ACTION_NONE, + FALSE, 0, 0, NULL, NULL, 0); child_cfg->add_proposal(child_cfg, create_proposal(esp_proposal, PROTO_ESP)); child_cfg->add_traffic_selector(child_cfg, TRUE, create_ts(local_net)); child_cfg->add_traffic_selector(child_cfg, FALSE, create_ts(remote_net)); diff --git a/src/libcharon/plugins/unit_tester/Makefile.in b/src/libcharon/plugins/unit_tester/Makefile.in index 47fff7e1d..5fa749e56 100644 --- a/src/libcharon/plugins/unit_tester/Makefile.in +++ b/src/libcharon/plugins/unit_tester/Makefile.in @@ -226,9 +226,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -267,6 +265,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libcharon/plugins/updown/Makefile.in b/src/libcharon/plugins/updown/Makefile.in index e93955d71..5dd2dc843 100644 --- a/src/libcharon/plugins/updown/Makefile.in +++ b/src/libcharon/plugins/updown/Makefile.in @@ -222,9 +222,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -263,6 +261,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libcharon/processing/jobs/acquire_job.c b/src/libcharon/processing/jobs/acquire_job.c index 45ace9312..3544dd332 100644 --- a/src/libcharon/processing/jobs/acquire_job.c +++ b/src/libcharon/processing/jobs/acquire_job.c @@ -45,20 +45,16 @@ struct private_acquire_job_t { traffic_selector_t *dst_ts; }; -/** - * Implementation of job_t.destroy. - */ -static void destroy(private_acquire_job_t *this) +METHOD(job_t, destroy, void, + private_acquire_job_t *this) { DESTROY_IF(this->src_ts); DESTROY_IF(this->dst_ts); free(this); } -/** - * Implementation of job_t.execute. - */ -static void execute(private_acquire_job_t *this) +METHOD(job_t, execute, void, + private_acquire_job_t *this) { charon->traps->acquire(charon->traps, this->reqid, this->src_ts, this->dst_ts); @@ -72,14 +68,19 @@ acquire_job_t *acquire_job_create(u_int32_t reqid, traffic_selector_t *src_ts, traffic_selector_t *dst_ts) { - private_acquire_job_t *this = malloc_thing(private_acquire_job_t); - - this->public.job_interface.execute = (void (*) (job_t *)) execute; - this->public.job_interface.destroy = (void (*)(job_t*)) destroy; + private_acquire_job_t *this; - this->reqid = reqid; - this->src_ts = src_ts; - this->dst_ts = dst_ts; + INIT(this, + .public = { + .job_interface = { + .execute = _execute, + .destroy = _destroy, + }, + }, + .reqid = reqid, + .src_ts = src_ts, + .dst_ts = dst_ts, + ); return &this->public; } diff --git a/src/libcharon/processing/jobs/delete_child_sa_job.c b/src/libcharon/processing/jobs/delete_child_sa_job.c index ca55721f2..29122cd03 100644 --- a/src/libcharon/processing/jobs/delete_child_sa_job.c +++ b/src/libcharon/processing/jobs/delete_child_sa_job.c @@ -46,18 +46,14 @@ struct private_delete_child_sa_job_t { u_int32_t spi; }; -/** - * Implementation of job_t.destroy. - */ -static void destroy(private_delete_child_sa_job_t *this) +METHOD(job_t, destroy, void, + private_delete_child_sa_job_t *this) { free(this); } -/** - * Implementation of job_t.execute. - */ -static void execute(private_delete_child_sa_job_t *this) +METHOD(job_t, execute, void, + private_delete_child_sa_job_t *this) { ike_sa_t *ike_sa; @@ -84,16 +80,19 @@ delete_child_sa_job_t *delete_child_sa_job_create(u_int32_t reqid, protocol_id_t protocol, u_int32_t spi) { - private_delete_child_sa_job_t *this = malloc_thing(private_delete_child_sa_job_t); - - /* interface functions */ - this->public.job_interface.execute = (void (*) (job_t *)) execute; - this->public.job_interface.destroy = (void (*)(job_t*)) destroy; - - /* private variables */ - this->reqid = reqid; - this->protocol = protocol; - this->spi = spi; + private_delete_child_sa_job_t *this; + + INIT(this, + .public = { + .job_interface = { + .execute = _execute, + .destroy = _destroy, + }, + }, + .reqid = reqid, + .protocol = protocol, + .spi = spi, + ); return &this->public; } diff --git a/src/libcharon/processing/jobs/delete_ike_sa_job.c b/src/libcharon/processing/jobs/delete_ike_sa_job.c index dffd08ba3..da3ecf06f 100644 --- a/src/libcharon/processing/jobs/delete_ike_sa_job.c +++ b/src/libcharon/processing/jobs/delete_ike_sa_job.c @@ -41,19 +41,15 @@ struct private_delete_ike_sa_job_t { }; -/** - * Implements job_t.destroy. - */ -static void destroy(private_delete_ike_sa_job_t *this) +METHOD(job_t, destroy, void, + private_delete_ike_sa_job_t *this) { this->ike_sa_id->destroy(this->ike_sa_id); free(this); } -/** - * Implementation of job_t.execute. - */ -static void execute(private_delete_ike_sa_job_t *this) +METHOD(job_t, execute, void, + private_delete_ike_sa_job_t *this) { ike_sa_t *ike_sa; @@ -102,15 +98,18 @@ static void execute(private_delete_ike_sa_job_t *this) delete_ike_sa_job_t *delete_ike_sa_job_create(ike_sa_id_t *ike_sa_id, bool delete_if_established) { - private_delete_ike_sa_job_t *this = malloc_thing(private_delete_ike_sa_job_t); - - /* interface functions */ - this->public.job_interface.execute = (void (*) (job_t *)) execute; - this->public.job_interface.destroy = (void (*)(job_t *)) destroy;; + private_delete_ike_sa_job_t *this; - /* private variables */ - this->ike_sa_id = ike_sa_id->clone(ike_sa_id); - this->delete_if_established = delete_if_established; + INIT(this, + .public = { + .job_interface = { + .execute = _execute, + .destroy = _destroy, + }, + }, + .ike_sa_id = ike_sa_id->clone(ike_sa_id), + .delete_if_established = delete_if_established, + ); return &(this->public); } diff --git a/src/libcharon/processing/jobs/migrate_job.c b/src/libcharon/processing/jobs/migrate_job.c index 05f47340c..5e7c7ae88 100644 --- a/src/libcharon/processing/jobs/migrate_job.c +++ b/src/libcharon/processing/jobs/migrate_job.c @@ -57,10 +57,8 @@ struct private_migrate_job_t { host_t *remote; }; -/** - * Implementation of job_t.destroy. - */ -static void destroy(private_migrate_job_t *this) +METHOD(job_t, destroy, void, + private_migrate_job_t *this) { DESTROY_IF(this->src_ts); DESTROY_IF(this->dst_ts); @@ -69,10 +67,8 @@ static void destroy(private_migrate_job_t *this) free(this); } -/** - * Implementation of job_t.execute. - */ -static void execute(private_migrate_job_t *this) +METHOD(job_t, execute, void, + private_migrate_job_t *this) { ike_sa_t *ike_sa = NULL; @@ -133,18 +129,21 @@ migrate_job_t *migrate_job_create(u_int32_t reqid, policy_dir_t dir, host_t *local, host_t *remote) { - private_migrate_job_t *this = malloc_thing(private_migrate_job_t); - - /* interface functions */ - this->public.job_interface.execute = (void (*) (job_t *)) execute; - this->public.job_interface.destroy = (void (*)(job_t*)) destroy; - - /* private variables */ - this->reqid = reqid; - this->src_ts = (dir == POLICY_OUT) ? src_ts : dst_ts; - this->dst_ts = (dir == POLICY_OUT) ? dst_ts : src_ts; - this->local = local; - this->remote = remote; + private_migrate_job_t *this; + + INIT(this, + .public = { + .job_interface = { + .execute = _execute, + .destroy = _destroy, + }, + }, + .reqid = reqid, + .src_ts = (dir == POLICY_OUT) ? src_ts : dst_ts, + .dst_ts = (dir == POLICY_OUT) ? dst_ts : src_ts, + .local = local, + .remote = remote, + ); return &this->public; } diff --git a/src/libcharon/processing/jobs/process_message_job.c b/src/libcharon/processing/jobs/process_message_job.c index a47d48e38..b6de4fc0f 100644 --- a/src/libcharon/processing/jobs/process_message_job.c +++ b/src/libcharon/processing/jobs/process_message_job.c @@ -35,19 +35,15 @@ struct private_process_message_job_t { message_t *message; }; -/** - * Implements job_t.destroy. - */ -static void destroy(private_process_message_job_t *this) +METHOD(job_t, destroy, void, + private_process_message_job_t *this) { this->message->destroy(this->message); free(this); } -/** - * Implementation of job_t.execute. - */ -static void execute(private_process_message_job_t *this) +METHOD(job_t, execute, void, + private_process_message_job_t *this) { ike_sa_t *ike_sa; @@ -93,14 +89,17 @@ static void execute(private_process_message_job_t *this) */ process_message_job_t *process_message_job_create(message_t *message) { - private_process_message_job_t *this = malloc_thing(private_process_message_job_t); - - /* interface functions */ - this->public.job_interface.execute = (void (*) (job_t *)) execute; - this->public.job_interface.destroy = (void(*)(job_t*))destroy; + private_process_message_job_t *this; - /* private variables */ - this->message = message; + INIT(this, + .public = { + .job_interface = { + .execute = _execute, + .destroy = _destroy, + }, + }, + .message = message, + ); return &(this->public); } diff --git a/src/libcharon/processing/jobs/rekey_child_sa_job.c b/src/libcharon/processing/jobs/rekey_child_sa_job.c index b797d181e..2bcee2ddf 100644 --- a/src/libcharon/processing/jobs/rekey_child_sa_job.c +++ b/src/libcharon/processing/jobs/rekey_child_sa_job.c @@ -45,18 +45,14 @@ struct private_rekey_child_sa_job_t { u_int32_t spi; }; -/** - * Implementation of job_t.destroy. - */ -static void destroy(private_rekey_child_sa_job_t *this) +METHOD(job_t, destroy, void, + private_rekey_child_sa_job_t *this) { free(this); } -/** - * Implementation of job_t.execute. - */ -static void execute(private_rekey_child_sa_job_t *this) +METHOD(job_t, execute, void, + private_rekey_child_sa_job_t *this) { ike_sa_t *ike_sa; @@ -82,16 +78,19 @@ rekey_child_sa_job_t *rekey_child_sa_job_create(u_int32_t reqid, protocol_id_t protocol, u_int32_t spi) { - private_rekey_child_sa_job_t *this = malloc_thing(private_rekey_child_sa_job_t); - - /* interface functions */ - this->public.job_interface.execute = (void (*) (job_t *)) execute; - this->public.job_interface.destroy = (void (*)(job_t*)) destroy; + private_rekey_child_sa_job_t *this; - /* private variables */ - this->reqid = reqid; - this->protocol = protocol; - this->spi = spi; + INIT(this, + .public = { + .job_interface = { + .execute = _execute, + .destroy = _destroy, + }, + }, + .reqid = reqid, + .protocol = protocol, + .spi = spi, + ); return &this->public; } diff --git a/src/libcharon/processing/jobs/rekey_ike_sa_job.c b/src/libcharon/processing/jobs/rekey_ike_sa_job.c index 5ec0b1b88..dc86ba9b3 100644 --- a/src/libcharon/processing/jobs/rekey_ike_sa_job.c +++ b/src/libcharon/processing/jobs/rekey_ike_sa_job.c @@ -39,19 +39,15 @@ struct private_rekey_ike_sa_job_t { bool reauth; }; -/** - * Implementation of job_t.destroy. - */ -static void destroy(private_rekey_ike_sa_job_t *this) +METHOD(job_t, destroy, void, + private_rekey_ike_sa_job_t *this) { this->ike_sa_id->destroy(this->ike_sa_id); free(this); } -/** - * Implementation of job_t.execute. - */ -static void execute(private_rekey_ike_sa_job_t *this) +METHOD(job_t, execute, void, + private_rekey_ike_sa_job_t *this) { ike_sa_t *ike_sa; status_t status = SUCCESS; @@ -90,15 +86,18 @@ static void execute(private_rekey_ike_sa_job_t *this) */ rekey_ike_sa_job_t *rekey_ike_sa_job_create(ike_sa_id_t *ike_sa_id, bool reauth) { - private_rekey_ike_sa_job_t *this = malloc_thing(private_rekey_ike_sa_job_t); - - /* interface functions */ - this->public.job_interface.execute = (void (*) (job_t *)) execute; - this->public.job_interface.destroy = (void (*)(job_t*)) destroy; + private_rekey_ike_sa_job_t *this; - /* private variables */ - this->ike_sa_id = ike_sa_id->clone(ike_sa_id); - this->reauth = reauth; + INIT(this, + .public = { + .job_interface = { + .execute = _execute, + .destroy = _destroy, + }, + }, + .ike_sa_id = ike_sa_id->clone(ike_sa_id), + .reauth = reauth, + ); return &(this->public); } diff --git a/src/libcharon/processing/jobs/retransmit_job.c b/src/libcharon/processing/jobs/retransmit_job.c index fc787f208..1c78abd27 100644 --- a/src/libcharon/processing/jobs/retransmit_job.c +++ b/src/libcharon/processing/jobs/retransmit_job.c @@ -40,19 +40,15 @@ struct private_retransmit_job_t { ike_sa_id_t *ike_sa_id; }; -/** - * Implements job_t.destroy. - */ -static void destroy(private_retransmit_job_t *this) +METHOD(job_t, destroy, void, + private_retransmit_job_t *this) { this->ike_sa_id->destroy(this->ike_sa_id); free(this); } -/** - * Implementation of job_t.execute. - */ -static void execute(private_retransmit_job_t *this) +METHOD(job_t, execute, void, + private_retransmit_job_t *this) { ike_sa_t *ike_sa; @@ -79,15 +75,18 @@ static void execute(private_retransmit_job_t *this) */ retransmit_job_t *retransmit_job_create(u_int32_t message_id,ike_sa_id_t *ike_sa_id) { - private_retransmit_job_t *this = malloc_thing(private_retransmit_job_t); - - /* interface functions */ - this->public.job_interface.execute = (void (*) (job_t *)) execute; - this->public.job_interface.destroy = (void (*) (job_t *)) destroy; + private_retransmit_job_t *this; - /* private variables */ - this->message_id = message_id; - this->ike_sa_id = ike_sa_id->clone(ike_sa_id); + INIT(this, + .public = { + .job_interface = { + .execute = _execute, + .destroy = _destroy, + }, + }, + .message_id = message_id, + .ike_sa_id = ike_sa_id->clone(ike_sa_id), + ); return &this->public; } diff --git a/src/libcharon/processing/jobs/roam_job.c b/src/libcharon/processing/jobs/roam_job.c index adc884a8a..74ef8bd6d 100644 --- a/src/libcharon/processing/jobs/roam_job.c +++ b/src/libcharon/processing/jobs/roam_job.c @@ -38,18 +38,14 @@ struct private_roam_job_t { bool address; }; -/** - * Implements job_t.destroy. - */ -static void destroy(private_roam_job_t *this) +METHOD(job_t, destroy, void, + private_roam_job_t *this) { free(this); } -/** - * Implementation of job_t.execute. - */ -static void execute(private_roam_job_t *this) +METHOD(job_t, execute, void, + private_roam_job_t *this) { ike_sa_t *ike_sa; linked_list_t *list; @@ -94,12 +90,17 @@ static void execute(private_roam_job_t *this) */ roam_job_t *roam_job_create(bool address) { - private_roam_job_t *this = malloc_thing(private_roam_job_t); - - this->public.job_interface.execute = (void (*) (job_t *)) execute; - this->public.job_interface.destroy = (void (*) (job_t *)) destroy; - - this->address = address; + private_roam_job_t *this; + + INIT(this, + .public = { + .job_interface = { + .execute = _execute, + .destroy = _destroy, + }, + }, + .address = address, + ); return &this->public; } diff --git a/src/libcharon/processing/jobs/send_dpd_job.c b/src/libcharon/processing/jobs/send_dpd_job.c index 1c2da52b8..47b525363 100644 --- a/src/libcharon/processing/jobs/send_dpd_job.c +++ b/src/libcharon/processing/jobs/send_dpd_job.c @@ -38,19 +38,15 @@ struct private_send_dpd_job_t { ike_sa_id_t *ike_sa_id; }; -/** - * Implements job_t.destroy. - */ -static void destroy(private_send_dpd_job_t *this) +METHOD(job_t, destroy, void, + private_send_dpd_job_t *this) { this->ike_sa_id->destroy(this->ike_sa_id); free(this); } -/** - * Implementation of job_t.execute. - */ -static void execute(private_send_dpd_job_t *this) +METHOD(job_t, execute, void, + private_send_dpd_job_t *this) { ike_sa_t *ike_sa; @@ -75,14 +71,17 @@ static void execute(private_send_dpd_job_t *this) */ send_dpd_job_t *send_dpd_job_create(ike_sa_id_t *ike_sa_id) { - private_send_dpd_job_t *this = malloc_thing(private_send_dpd_job_t); - - /* interface functions */ - this->public.job_interface.execute = (void (*) (job_t *)) execute; - this->public.job_interface.destroy = (void (*) (job_t *)) destroy; + private_send_dpd_job_t *this; - /* private variables */ - this->ike_sa_id = ike_sa_id->clone(ike_sa_id); + INIT(this, + .public = { + .job_interface = { + .execute = _execute, + .destroy = _destroy, + }, + }, + .ike_sa_id = ike_sa_id->clone(ike_sa_id), + ); return &this->public; } diff --git a/src/libcharon/processing/jobs/send_keepalive_job.c b/src/libcharon/processing/jobs/send_keepalive_job.c index 3d02cea2e..8d98aad7e 100644 --- a/src/libcharon/processing/jobs/send_keepalive_job.c +++ b/src/libcharon/processing/jobs/send_keepalive_job.c @@ -38,19 +38,15 @@ struct private_send_keepalive_job_t { ike_sa_id_t *ike_sa_id; }; -/** - * Implements job_t.destroy. - */ -static void destroy(private_send_keepalive_job_t *this) +METHOD(job_t, destroy, void, + private_send_keepalive_job_t *this) { this->ike_sa_id->destroy(this->ike_sa_id); free(this); } -/** - * Implementation of job_t.execute. - */ -static void execute(private_send_keepalive_job_t *this) +METHOD(job_t, execute, void, + private_send_keepalive_job_t *this) { ike_sa_t *ike_sa; @@ -69,14 +65,17 @@ static void execute(private_send_keepalive_job_t *this) */ send_keepalive_job_t *send_keepalive_job_create(ike_sa_id_t *ike_sa_id) { - private_send_keepalive_job_t *this = malloc_thing(private_send_keepalive_job_t); - - /* interface functions */ - this->public.job_interface.execute = (void (*) (job_t *)) execute; - this->public.job_interface.destroy = (void (*) (job_t *)) destroy; + private_send_keepalive_job_t *this; - /* private variables */ - this->ike_sa_id = ike_sa_id->clone(ike_sa_id); + INIT(this, + .public = { + .job_interface = { + .execute = _execute, + .destroy = _destroy, + }, + }, + .ike_sa_id = ike_sa_id->clone(ike_sa_id), + ); return &this->public; } diff --git a/src/libcharon/processing/jobs/start_action_job.c b/src/libcharon/processing/jobs/start_action_job.c new file mode 100644 index 000000000..5dda18be2 --- /dev/null +++ b/src/libcharon/processing/jobs/start_action_job.c @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2011 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 "start_action_job.h" + +#include <daemon.h> + + +typedef struct private_start_action_job_t private_start_action_job_t; + +/** + * Private data of an start_action_job_t object. + */ +struct private_start_action_job_t { + /** + * Public start_action_job_t interface. + */ + start_action_job_t public; +}; + +METHOD(job_t, destroy, void, + private_start_action_job_t *this) +{ + free(this); +} + +METHOD(job_t, execute, void, + private_start_action_job_t *this) +{ + enumerator_t *enumerator, *children; + peer_cfg_t *peer_cfg; + child_cfg_t *child_cfg; + char *name; + + enumerator = charon->backends->create_peer_cfg_enumerator(charon->backends, + NULL, NULL, NULL, NULL); + while (enumerator->enumerate(enumerator, &peer_cfg)) + { + if (peer_cfg->get_ike_version(peer_cfg) != 2) + { + continue; + } + + children = peer_cfg->create_child_cfg_enumerator(peer_cfg); + while (children->enumerate(children, &child_cfg)) + { + name = child_cfg->get_name(child_cfg); + + switch (child_cfg->get_start_action(child_cfg)) + { + case ACTION_RESTART: + DBG1(DBG_JOB, "start action: initiate '%s'", name); + charon->controller->initiate(charon->controller, + peer_cfg->get_ref(peer_cfg), + child_cfg->get_ref(child_cfg), + NULL, NULL); + break; + case ACTION_ROUTE: + DBG1(DBG_JOB, "start action: route '%s'", name); + charon->traps->install(charon->traps, peer_cfg, child_cfg); + break; + case ACTION_NONE: + break; + } + } + children->destroy(children); + } + enumerator->destroy(enumerator); + destroy(this); +} + +/* + * Described in header + */ +start_action_job_t *start_action_job_create(void) +{ + private_start_action_job_t *this; + + INIT(this, + .public = { + .job_interface = { + .execute = _execute, + .destroy = _destroy, + }, + }, + ) + return &this->public; +} + diff --git a/src/libcharon/processing/jobs/start_action_job.h b/src/libcharon/processing/jobs/start_action_job.h new file mode 100644 index 000000000..ffc167c05 --- /dev/null +++ b/src/libcharon/processing/jobs/start_action_job.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2011 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. + */ + +/** + * @defgroup start_action_job start_action_job + * @{ @ingroup cjobs + */ + +#ifndef START_ACTION_JOB_H_ +#define START_ACTION_JOB_H_ + +typedef struct start_action_job_t start_action_job_t; + +#include <library.h> +#include <processing/jobs/job.h> + +/** + * Class representing a start_action Job. + * + * This job handles all child configurations stored in an [SQL database] + * backend according to their start_action field (start, route, none). + */ +struct start_action_job_t { + /** + * The job_t interface. + */ + job_t job_interface; +}; + +/** + * Creates a job of type start_action. + * + * @return start_action_job_t object + */ +start_action_job_t *start_action_job_create(void); + +#endif /** START_ACTION_JOB_H_ @}*/ diff --git a/src/libcharon/processing/jobs/update_sa_job.c b/src/libcharon/processing/jobs/update_sa_job.c index 17dce2548..3b4e9949f 100644 --- a/src/libcharon/processing/jobs/update_sa_job.c +++ b/src/libcharon/processing/jobs/update_sa_job.c @@ -43,19 +43,15 @@ struct private_update_sa_job_t { host_t *new; }; -/** - * Implements job_t.destroy. - */ -static void destroy(private_update_sa_job_t *this) +METHOD(job_t, destroy, void, + private_update_sa_job_t *this) { this->new->destroy(this->new); free(this); } -/** - * Implementation of job_t.execute. - */ -static void execute(private_update_sa_job_t *this) +METHOD(job_t, execute, void, + private_update_sa_job_t *this) { ike_sa_t *ike_sa; @@ -71,7 +67,7 @@ static void execute(private_update_sa_job_t *this) if (ike_sa->has_condition(ike_sa, COND_NAT_THERE) && !ike_sa->has_condition(ike_sa, COND_NAT_HERE)) { - ike_sa->update_hosts(ike_sa, NULL, this->new); + ike_sa->update_hosts(ike_sa, NULL, this->new, FALSE); } charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); } @@ -83,13 +79,18 @@ static void execute(private_update_sa_job_t *this) */ update_sa_job_t *update_sa_job_create(u_int32_t reqid, host_t *new) { - private_update_sa_job_t *this = malloc_thing(private_update_sa_job_t); - - this->public.job_interface.execute = (void (*) (job_t *)) execute; - this->public.job_interface.destroy = (void (*) (job_t *)) destroy; - - this->reqid = reqid; - this->new = new; + private_update_sa_job_t *this; + + INIT(this, + .public = { + .job_interface = { + .execute = _execute, + .destroy = _destroy, + }, + }, + .reqid = reqid, + .new = new, + ); return &this->public; } diff --git a/src/libcharon/sa/authenticators/authenticator.c b/src/libcharon/sa/authenticators/authenticator.c index cd340e53e..83f5fbaad 100644 --- a/src/libcharon/sa/authenticators/authenticator.c +++ b/src/libcharon/sa/authenticators/authenticator.c @@ -39,7 +39,8 @@ ENUM_END(auth_method_names, AUTH_ECDSA_521); */ authenticator_t *authenticator_create_builder(ike_sa_t *ike_sa, auth_cfg_t *cfg, chunk_t received_nonce, chunk_t sent_nonce, - chunk_t received_init, chunk_t sent_init) + chunk_t received_init, chunk_t sent_init, + char reserved[3]) { switch ((uintptr_t)cfg->get(cfg, AUTH_RULE_AUTH_CLASS)) { @@ -47,13 +48,14 @@ authenticator_t *authenticator_create_builder(ike_sa_t *ike_sa, auth_cfg_t *cfg, /* defaults to PUBKEY */ case AUTH_CLASS_PUBKEY: return (authenticator_t*)pubkey_authenticator_create_builder(ike_sa, - received_nonce, sent_init); + received_nonce, sent_init, reserved); case AUTH_CLASS_PSK: return (authenticator_t*)psk_authenticator_create_builder(ike_sa, - received_nonce, sent_init); + received_nonce, sent_init, reserved); case AUTH_CLASS_EAP: return (authenticator_t*)eap_authenticator_create_builder(ike_sa, - received_nonce, sent_nonce, received_init, sent_init); + received_nonce, sent_nonce, + received_init, sent_init, reserved); default: return NULL; } @@ -65,7 +67,8 @@ authenticator_t *authenticator_create_builder(ike_sa_t *ike_sa, auth_cfg_t *cfg, authenticator_t *authenticator_create_verifier( ike_sa_t *ike_sa, message_t *message, chunk_t received_nonce, chunk_t sent_nonce, - chunk_t received_init, chunk_t sent_init) + chunk_t received_init, chunk_t sent_init, + char reserved[3]) { auth_payload_t *auth_payload; @@ -73,7 +76,8 @@ authenticator_t *authenticator_create_verifier( if (auth_payload == NULL) { return (authenticator_t*)eap_authenticator_create_verifier(ike_sa, - received_nonce, sent_nonce, received_init, sent_init); + received_nonce, sent_nonce, + received_init, sent_init, reserved); } switch (auth_payload->get_auth_method(auth_payload)) { @@ -82,10 +86,10 @@ authenticator_t *authenticator_create_verifier( case AUTH_ECDSA_384: case AUTH_ECDSA_521: return (authenticator_t*)pubkey_authenticator_create_verifier(ike_sa, - sent_nonce, received_init); + sent_nonce, received_init, reserved); case AUTH_PSK: return (authenticator_t*)psk_authenticator_create_verifier(ike_sa, - sent_nonce, received_init); + sent_nonce, received_init, reserved); default: return NULL; } diff --git a/src/libcharon/sa/authenticators/authenticator.h b/src/libcharon/sa/authenticators/authenticator.h index 89178b5cf..d27e006a3 100644 --- a/src/libcharon/sa/authenticators/authenticator.h +++ b/src/libcharon/sa/authenticators/authenticator.h @@ -130,12 +130,14 @@ struct authenticator_t { * @param sent_nonce nonce sent in IKE_SA_INIT * @param received_init received IKE_SA_INIT message data * @param sent_init sent IKE_SA_INIT message data + * @param reserved reserved bytes of the ID payload * @return authenticator, NULL if not supported */ authenticator_t *authenticator_create_builder( ike_sa_t *ike_sa, auth_cfg_t *cfg, chunk_t received_nonce, chunk_t sent_nonce, - chunk_t received_init, chunk_t sent_init); + chunk_t received_init, chunk_t sent_init, + char reserved[3]); /** * Create an authenticator to verify signatures. @@ -146,11 +148,13 @@ authenticator_t *authenticator_create_builder( * @param sent_nonce nonce sent in IKE_SA_INIT * @param received_init received IKE_SA_INIT message data * @param sent_init sent IKE_SA_INIT message data + * @param reserved reserved bytes of the ID payload * @return authenticator, NULL if not supported */ authenticator_t *authenticator_create_verifier( ike_sa_t *ike_sa, message_t *message, chunk_t received_nonce, chunk_t sent_nonce, - chunk_t received_init, chunk_t sent_init); + chunk_t received_init, chunk_t sent_init, + char reserved[3]); #endif /** AUTHENTICATOR_H_ @}*/ diff --git a/src/libcharon/sa/authenticators/eap_authenticator.c b/src/libcharon/sa/authenticators/eap_authenticator.c index 8b22fd1d7..dea02755d 100644 --- a/src/libcharon/sa/authenticators/eap_authenticator.c +++ b/src/libcharon/sa/authenticators/eap_authenticator.c @@ -58,6 +58,11 @@ struct private_eap_authenticator_t { chunk_t sent_init; /** + * Reserved bytes of ID payload + */ + char reserved[3]; + + /** * Current EAP method processing */ eap_method_t *method; @@ -422,7 +427,7 @@ static bool verify_auth(private_eap_authenticator_t *this, message_t *message, other_id = this->ike_sa->get_other_id(this->ike_sa); keymat = this->ike_sa->get_keymat(this->ike_sa); auth_data = keymat->get_psk_sig(keymat, TRUE, init, nonce, - this->msk, other_id); + this->msk, other_id, this->reserved); recv_auth_data = auth_payload->get_data(auth_payload); if (!auth_data.len || !chunk_equals(auth_data, recv_auth_data)) { @@ -458,7 +463,8 @@ static void build_auth(private_eap_authenticator_t *this, message_t *message, DBG1(DBG_IKE, "authentication of '%Y' (myself) with %N", my_id, auth_class_names, AUTH_CLASS_EAP); - auth_data = keymat->get_psk_sig(keymat, FALSE, init, nonce, this->msk, my_id); + auth_data = keymat->get_psk_sig(keymat, FALSE, init, nonce, + this->msk, my_id, this->reserved); auth_payload = auth_payload_create(); auth_payload->set_auth_method(auth_payload, AUTH_PSK); auth_payload->set_data(auth_payload, auth_data); @@ -642,7 +648,8 @@ METHOD(authenticator_t, destroy, void, */ eap_authenticator_t *eap_authenticator_create_builder(ike_sa_t *ike_sa, chunk_t received_nonce, chunk_t sent_nonce, - chunk_t received_init, chunk_t sent_init) + chunk_t received_init, chunk_t sent_init, + char reserved[3]) { private_eap_authenticator_t *this; @@ -661,6 +668,7 @@ eap_authenticator_t *eap_authenticator_create_builder(ike_sa_t *ike_sa, .sent_init = sent_init, .sent_nonce = sent_nonce, ); + memcpy(this->reserved, reserved, sizeof(this->reserved)); return &this->public; } @@ -670,7 +678,8 @@ eap_authenticator_t *eap_authenticator_create_builder(ike_sa_t *ike_sa, */ eap_authenticator_t *eap_authenticator_create_verifier(ike_sa_t *ike_sa, chunk_t received_nonce, chunk_t sent_nonce, - chunk_t received_init, chunk_t sent_init) + chunk_t received_init, chunk_t sent_init, + char reserved[3]) { private_eap_authenticator_t *this; @@ -689,6 +698,7 @@ eap_authenticator_t *eap_authenticator_create_verifier(ike_sa_t *ike_sa, .sent_init = sent_init, .sent_nonce = sent_nonce, ); + memcpy(this->reserved, reserved, sizeof(this->reserved)); return &this->public; } diff --git a/src/libcharon/sa/authenticators/eap_authenticator.h b/src/libcharon/sa/authenticators/eap_authenticator.h index 41eb6a8c9..726411a18 100644 --- a/src/libcharon/sa/authenticators/eap_authenticator.h +++ b/src/libcharon/sa/authenticators/eap_authenticator.h @@ -75,11 +75,13 @@ struct eap_authenticator_t { * @param sent_nonce nonce sent in IKE_SA_INIT * @param received_init received IKE_SA_INIT message data * @param sent_init sent IKE_SA_INIT message data + * @param reserved reserved bytes of ID payload * @return EAP authenticator */ eap_authenticator_t *eap_authenticator_create_builder(ike_sa_t *ike_sa, chunk_t received_nonce, chunk_t sent_nonce, - chunk_t received_init, chunk_t sent_init); + chunk_t received_init, chunk_t sent_init, + char reserved[3]); /** * Create an authenticator to authenticate EAP clients. @@ -89,10 +91,12 @@ eap_authenticator_t *eap_authenticator_create_builder(ike_sa_t *ike_sa, * @param sent_nonce nonce sent in IKE_SA_INIT * @param received_init received IKE_SA_INIT message data * @param sent_init sent IKE_SA_INIT message data + * @param reserved reserved bytes of ID payload * @return EAP authenticator */ eap_authenticator_t *eap_authenticator_create_verifier(ike_sa_t *ike_sa, chunk_t received_nonce, chunk_t sent_nonce, - chunk_t received_init, chunk_t sent_init); + chunk_t received_init, chunk_t sent_init, + char reserved[3]); #endif /** EAP_AUTHENTICATOR_H_ @}*/ diff --git a/src/libcharon/sa/authenticators/psk_authenticator.c b/src/libcharon/sa/authenticators/psk_authenticator.c index e69f30dcf..21fc0f9b8 100644 --- a/src/libcharon/sa/authenticators/psk_authenticator.c +++ b/src/libcharon/sa/authenticators/psk_authenticator.c @@ -45,12 +45,15 @@ struct private_psk_authenticator_t { * IKE_SA_INIT message data to include in AUTH calculation */ chunk_t ike_sa_init; + + /** + * Reserved bytes of ID payload + */ + char reserved[3]; }; -/* - * Implementation of authenticator_t.build for builder - */ -static status_t build(private_psk_authenticator_t *this, message_t *message) +METHOD(authenticator_t, build, status_t, + private_psk_authenticator_t *this, message_t *message) { identification_t *my_id, *other_id; auth_payload_t *auth_payload; @@ -70,7 +73,7 @@ static status_t build(private_psk_authenticator_t *this, message_t *message) return NOT_FOUND; } auth_data = keymat->get_psk_sig(keymat, FALSE, this->ike_sa_init, - this->nonce, key->get_key(key), my_id); + this->nonce, key->get_key(key), my_id, this->reserved); key->destroy(key); DBG2(DBG_IKE, "successfully created shared key MAC"); auth_payload = auth_payload_create(); @@ -82,10 +85,8 @@ static status_t build(private_psk_authenticator_t *this, message_t *message) return SUCCESS; } -/** - * Implementation of authenticator_t.process for verifier - */ -static status_t process(private_psk_authenticator_t *this, message_t *message) +METHOD(authenticator_t, process, status_t, + private_psk_authenticator_t *this, message_t *message) { chunk_t auth_data, recv_auth_data; identification_t *my_id, *other_id; @@ -113,7 +114,7 @@ static status_t process(private_psk_authenticator_t *this, message_t *message) keys_found++; auth_data = keymat->get_psk_sig(keymat, TRUE, this->ike_sa_init, - this->nonce, key->get_key(key), other_id); + this->nonce, key->get_key(key), other_id, this->reserved); if (auth_data.len && chunk_equals(auth_data, recv_auth_data)) { DBG1(DBG_IKE, "authentication of '%Y' with %N successful", @@ -141,19 +142,8 @@ static status_t process(private_psk_authenticator_t *this, message_t *message) return SUCCESS; } -/** - * Implementation of authenticator_t.process for builder - * Implementation of authenticator_t.build for verifier - */ -static status_t return_failed() -{ - return FAILED; -} - -/** - * Implementation of authenticator_t.destroy. - */ -static void destroy(private_psk_authenticator_t *this) +METHOD(authenticator_t, destroy, void, + private_psk_authenticator_t *this) { free(this); } @@ -162,18 +152,25 @@ static void destroy(private_psk_authenticator_t *this) * Described in header. */ psk_authenticator_t *psk_authenticator_create_builder(ike_sa_t *ike_sa, - chunk_t received_nonce, chunk_t sent_init) + chunk_t received_nonce, chunk_t sent_init, + char reserved[3]) { - private_psk_authenticator_t *this = malloc_thing(private_psk_authenticator_t); - - this->public.authenticator.build = (status_t(*)(authenticator_t*, message_t *message))build; - this->public.authenticator.process = (status_t(*)(authenticator_t*, message_t *message))return_failed; - this->public.authenticator.is_mutual = (bool(*)(authenticator_t*))return_false; - this->public.authenticator.destroy = (void(*)(authenticator_t*))destroy; - - this->ike_sa = ike_sa; - this->ike_sa_init = sent_init; - this->nonce = received_nonce; + private_psk_authenticator_t *this; + + INIT(this, + .public = { + .authenticator = { + .build = _build, + .process = (void*)return_failed, + .is_mutual = (void*)return_false, + .destroy = _destroy, + }, + }, + .ike_sa = ike_sa, + .ike_sa_init = sent_init, + .nonce = received_nonce, + ); + memcpy(this->reserved, reserved, sizeof(this->reserved)); return &this->public; } @@ -182,18 +179,25 @@ psk_authenticator_t *psk_authenticator_create_builder(ike_sa_t *ike_sa, * Described in header. */ psk_authenticator_t *psk_authenticator_create_verifier(ike_sa_t *ike_sa, - chunk_t sent_nonce, chunk_t received_init) + chunk_t sent_nonce, chunk_t received_init, + char reserved[3]) { - private_psk_authenticator_t *this = malloc_thing(private_psk_authenticator_t); - - this->public.authenticator.build = (status_t(*)(authenticator_t*, message_t *messageh))return_failed; - this->public.authenticator.process = (status_t(*)(authenticator_t*, message_t *message))process; - this->public.authenticator.is_mutual = (bool(*)(authenticator_t*))return_false; - this->public.authenticator.destroy = (void(*)(authenticator_t*))destroy; - - this->ike_sa = ike_sa; - this->ike_sa_init = received_init; - this->nonce = sent_nonce; + private_psk_authenticator_t *this; + + INIT(this, + .public = { + .authenticator = { + .build = (void*)return_failed, + .process = _process, + .is_mutual = (void*)return_false, + .destroy = _destroy, + }, + }, + .ike_sa = ike_sa, + .ike_sa_init = received_init, + .nonce = sent_nonce, + ); + memcpy(this->reserved, reserved, sizeof(this->reserved)); return &this->public; } diff --git a/src/libcharon/sa/authenticators/psk_authenticator.h b/src/libcharon/sa/authenticators/psk_authenticator.h index 0fab11095..8cf1a0f98 100644 --- a/src/libcharon/sa/authenticators/psk_authenticator.h +++ b/src/libcharon/sa/authenticators/psk_authenticator.h @@ -42,10 +42,12 @@ struct psk_authenticator_t { * @param ike_sa associated ike_sa * @param received_nonce nonce received in IKE_SA_INIT * @param sent_init sent IKE_SA_INIT message data + * @param reserved reserved bytes of ID payload * @return PSK authenticator */ psk_authenticator_t *psk_authenticator_create_builder(ike_sa_t *ike_sa, - chunk_t received_nonce, chunk_t sent_init); + chunk_t received_nonce, chunk_t sent_init, + char reserved[3]); /** * Create an authenticator to verify PSK signatures. @@ -53,9 +55,11 @@ psk_authenticator_t *psk_authenticator_create_builder(ike_sa_t *ike_sa, * @param ike_sa associated ike_sa * @param sent_nonce nonce sent in IKE_SA_INIT * @param received_init received IKE_SA_INIT message data + * @param reserved reserved bytes of ID payload * @return PSK authenticator */ psk_authenticator_t *psk_authenticator_create_verifier(ike_sa_t *ike_sa, - chunk_t sent_nonce, chunk_t received_init); + chunk_t sent_nonce, chunk_t received_init, + char reserved[3]); #endif /** PSK_AUTHENTICATOR_H_ @}*/ diff --git a/src/libcharon/sa/authenticators/pubkey_authenticator.c b/src/libcharon/sa/authenticators/pubkey_authenticator.c index 54b4338bb..247891670 100644 --- a/src/libcharon/sa/authenticators/pubkey_authenticator.c +++ b/src/libcharon/sa/authenticators/pubkey_authenticator.c @@ -46,12 +46,15 @@ struct private_pubkey_authenticator_t { * IKE_SA_INIT message data to include in AUTH calculation */ chunk_t ike_sa_init; + + /** + * Reserved bytes of ID payload + */ + char reserved[3]; }; -/** - * Implementation of authenticator_t.build for builder - */ -static status_t build(private_pubkey_authenticator_t *this, message_t *message) +METHOD(authenticator_t, build, status_t, + private_pubkey_authenticator_t *this, message_t *message) { chunk_t octets, auth_data; status_t status = FAILED; @@ -109,7 +112,7 @@ static status_t build(private_pubkey_authenticator_t *this, message_t *message) } keymat = this->ike_sa->get_keymat(this->ike_sa); octets = keymat->get_auth_octets(keymat, FALSE, this->ike_sa_init, - this->nonce, id); + this->nonce, id, this->reserved); if (private->sign(private, scheme, octets, &auth_data)) { auth_payload = auth_payload_create(); @@ -128,10 +131,8 @@ static status_t build(private_pubkey_authenticator_t *this, message_t *message) return status; } -/** - * Implementation of authenticator_t.process for verifier - */ -static status_t process(private_pubkey_authenticator_t *this, message_t *message) +METHOD(authenticator_t, process, status_t, + private_pubkey_authenticator_t *this, message_t *message) { public_key_t *public; auth_method_t auth_method; @@ -175,7 +176,7 @@ static status_t process(private_pubkey_authenticator_t *this, message_t *message id = this->ike_sa->get_other_id(this->ike_sa); keymat = this->ike_sa->get_keymat(this->ike_sa); octets = keymat->get_auth_octets(keymat, TRUE, this->ike_sa_init, - this->nonce, id); + this->nonce, id, this->reserved); auth = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE); enumerator = lib->credmgr->create_public_enumerator(lib->credmgr, key_type, id, auth); @@ -206,19 +207,8 @@ static status_t process(private_pubkey_authenticator_t *this, message_t *message return status; } -/** - * Implementation of authenticator_t.process for builder - * Implementation of authenticator_t.build for verifier - */ -static status_t return_failed() -{ - return FAILED; -} - -/** - * Implementation of authenticator_t.destroy. - */ -static void destroy(private_pubkey_authenticator_t *this) +METHOD(authenticator_t, destroy, void, + private_pubkey_authenticator_t *this) { free(this); } @@ -227,18 +217,25 @@ static void destroy(private_pubkey_authenticator_t *this) * Described in header. */ pubkey_authenticator_t *pubkey_authenticator_create_builder(ike_sa_t *ike_sa, - chunk_t received_nonce, chunk_t sent_init) + chunk_t received_nonce, chunk_t sent_init, + char reserved[3]) { - private_pubkey_authenticator_t *this = malloc_thing(private_pubkey_authenticator_t); + private_pubkey_authenticator_t *this; - this->public.authenticator.build = (status_t(*)(authenticator_t*, message_t *message))build; - this->public.authenticator.process = (status_t(*)(authenticator_t*, message_t *message))return_failed; - this->public.authenticator.is_mutual = (bool(*)(authenticator_t*))return_false; - this->public.authenticator.destroy = (void(*)(authenticator_t*))destroy; - - this->ike_sa = ike_sa; - this->ike_sa_init = sent_init; - this->nonce = received_nonce; + INIT(this, + .public = { + .authenticator = { + .build = _build, + .process = (void*)return_failed, + .is_mutual = (void*)return_false, + .destroy = _destroy, + }, + }, + .ike_sa = ike_sa, + .ike_sa_init = sent_init, + .nonce = received_nonce, + ); + memcpy(this->reserved, reserved, sizeof(this->reserved)); return &this->public; } @@ -247,18 +244,25 @@ pubkey_authenticator_t *pubkey_authenticator_create_builder(ike_sa_t *ike_sa, * Described in header. */ pubkey_authenticator_t *pubkey_authenticator_create_verifier(ike_sa_t *ike_sa, - chunk_t sent_nonce, chunk_t received_init) + chunk_t sent_nonce, chunk_t received_init, + char reserved[3]) { - private_pubkey_authenticator_t *this = malloc_thing(private_pubkey_authenticator_t); - - this->public.authenticator.build = (status_t(*)(authenticator_t*, message_t *message))return_failed; - this->public.authenticator.process = (status_t(*)(authenticator_t*, message_t *message))process; - this->public.authenticator.is_mutual = (bool(*)(authenticator_t*))return_false; - this->public.authenticator.destroy = (void(*)(authenticator_t*))destroy; + private_pubkey_authenticator_t *this; - this->ike_sa = ike_sa; - this->ike_sa_init = received_init; - this->nonce = sent_nonce; + INIT(this, + .public = { + .authenticator = { + .build = (void*)return_failed, + .process = _process, + .is_mutual = (void*)return_false, + .destroy = _destroy, + }, + }, + .ike_sa = ike_sa, + .ike_sa_init = received_init, + .nonce = sent_nonce, + ); + memcpy(this->reserved, reserved, sizeof(this->reserved)); return &this->public; } diff --git a/src/libcharon/sa/authenticators/pubkey_authenticator.h b/src/libcharon/sa/authenticators/pubkey_authenticator.h index be369cb89..4c3937ecc 100644 --- a/src/libcharon/sa/authenticators/pubkey_authenticator.h +++ b/src/libcharon/sa/authenticators/pubkey_authenticator.h @@ -43,10 +43,12 @@ struct pubkey_authenticator_t { * @param ike_sa associated ike_sa * @param received_nonce nonce received in IKE_SA_INIT * @param sent_init sent IKE_SA_INIT message data + * @param reserved reserved bytes of ID payload * @return public key authenticator */ pubkey_authenticator_t *pubkey_authenticator_create_builder(ike_sa_t *ike_sa, - chunk_t received_nonce, chunk_t sent_init); + chunk_t received_nonce, chunk_t sent_init, + char reserved[3]); /** * Create an authenticator to verify public key signatures. @@ -54,9 +56,11 @@ pubkey_authenticator_t *pubkey_authenticator_create_builder(ike_sa_t *ike_sa, * @param ike_sa associated ike_sa * @param sent_nonce nonce sent in IKE_SA_INIT * @param received_init received IKE_SA_INIT message data + * @param reserved reserved bytes of ID payload * @return public key authenticator */ pubkey_authenticator_t *pubkey_authenticator_create_verifier(ike_sa_t *ike_sa, - chunk_t sent_nonce, chunk_t received_init); + chunk_t sent_nonce, chunk_t received_init, + char reserved[3]); #endif /** PUBKEY_AUTHENTICATOR_H_ @}*/ diff --git a/src/libcharon/sa/child_sa.c b/src/libcharon/sa/child_sa.c index b6ef31da0..495929965 100644 --- a/src/libcharon/sa/child_sa.c +++ b/src/libcharon/sa/child_sa.c @@ -559,13 +559,14 @@ METHOD(child_sa_t, alloc_cpi, u_int16_t, METHOD(child_sa_t, install, status_t, private_child_sa_t *this, chunk_t encr, chunk_t integ, u_int32_t spi, - u_int16_t cpi, bool inbound, linked_list_t *my_ts, + u_int16_t cpi, bool inbound, bool tfcv3, linked_list_t *my_ts, linked_list_t *other_ts) { u_int16_t enc_alg = ENCR_UNDEFINED, int_alg = AUTH_UNDEFINED, size; traffic_selector_t *src_ts = NULL, *dst_ts = NULL; time_t now; lifetime_cfg_t *lifetime; + u_int32_t tfc = 0; host_t *src, *dst; status_t status; bool update = FALSE; @@ -590,6 +591,11 @@ METHOD(child_sa_t, install, status_t, dst = this->other_addr; this->other_spi = spi; this->other_cpi = cpi; + + if (tfcv3) + { + tfc = this->config->get_tfc(this->config); + } } DBG2(DBG_CHD, "adding %s %N SA", inbound ? "inbound" : "outbound", @@ -620,7 +626,7 @@ METHOD(child_sa_t, install, status_t, lifetime->time.rekey = 0; } - if (this->mode == MODE_BEET) + if (this->mode == MODE_BEET || this->mode == MODE_TRANSPORT) { /* BEET requires the bound address from the traffic selectors. * TODO: We add just the first traffic selector for now, as the @@ -639,7 +645,7 @@ METHOD(child_sa_t, install, status_t, status = hydra->kernel_interface->add_sa(hydra->kernel_interface, src, dst, spi, proto_ike2ip(this->protocol), this->reqid, - inbound ? this->mark_in : this->mark_out, + inbound ? this->mark_in : this->mark_out, tfc, lifetime, enc_alg, encr, int_alg, integ, this->mode, this->ipcomp, cpi, this->encap, update, src_ts, dst_ts); diff --git a/src/libcharon/sa/child_sa.h b/src/libcharon/sa/child_sa.h index 95bc297b0..f17ef01ac 100644 --- a/src/libcharon/sa/child_sa.h +++ b/src/libcharon/sa/child_sa.h @@ -313,12 +313,13 @@ struct child_sa_t { * @param spi SPI to use, allocated for inbound * @param cpi CPI to use, allocated for outbound * @param inbound TRUE to install an inbound SA, FALSE for outbound + * @param tfcv3 TRUE if peer supports ESPv3 TFC * @param my_ts negotiated local traffic selector list * @param other_ts negotiated remote traffic selector list * @return SUCCESS or FAILED */ status_t (*install)(child_sa_t *this, chunk_t encr, chunk_t integ, - u_int32_t spi, u_int16_t cpi, bool inbound, + u_int32_t spi, u_int16_t cpi, bool inbound, bool tfcv3, linked_list_t *my_ts, linked_list_t *other_ts); /** * Install the policies using some traffic selectors. diff --git a/src/libcharon/sa/connect_manager.c b/src/libcharon/sa/connect_manager.c index 1fb286863..972cc98ad 100644 --- a/src/libcharon/sa/connect_manager.c +++ b/src/libcharon/sa/connect_manager.c @@ -1194,7 +1194,10 @@ static job_requeue_t initiate_mediated(initiate_data_t *data) DBG1(DBG_IKE, "establishing mediated connection failed"); charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, sa); } - charon->ike_sa_manager->checkin(charon->ike_sa_manager, sa); + else + { + charon->ike_sa_manager->checkin(charon->ike_sa_manager, sa); + } } iterator->destroy(iterator); } diff --git a/src/libcharon/sa/ike_sa.c b/src/libcharon/sa/ike_sa.c index a4e4028ab..9b6f9d06d 100644 --- a/src/libcharon/sa/ike_sa.c +++ b/src/libcharon/sa/ike_sa.c @@ -50,6 +50,7 @@ #include <processing/jobs/send_dpd_job.h> #include <processing/jobs/send_keepalive_job.h> #include <processing/jobs/rekey_ike_sa_job.h> +#include <encoding/payloads/unknown_payload.h> #ifdef ME #include <sa/tasks/ike_me.h> @@ -559,13 +560,6 @@ METHOD(ike_sa_t, send_dpd, status_t, time_t diff, delay; delay = this->peer_cfg->get_dpd(this->peer_cfg); - - if (delay == 0) - { - /* DPD disabled */ - return SUCCESS; - } - if (this->task_manager->busy(this->task_manager)) { /* an exchange is in the air, no need to start a DPD check */ @@ -578,7 +572,7 @@ METHOD(ike_sa_t, send_dpd, status_t, last_in = get_use_time(this, TRUE); now = time_monotonic(NULL); diff = now - last_in; - if (diff >= delay) + if (!delay || diff >= delay) { /* to long ago, initiate dead peer detection */ task_t *task; @@ -604,8 +598,11 @@ METHOD(ike_sa_t, send_dpd, status_t, } } /* recheck in "interval" seconds */ - job = (job_t*)send_dpd_job_create(this->ike_sa_id); - lib->scheduler->schedule_job(lib->scheduler, job, delay - diff); + if (delay) + { + job = (job_t*)send_dpd_job_create(this->ike_sa_id); + lib->scheduler->schedule_job(lib->scheduler, job, delay - diff); + } return SUCCESS; } @@ -680,7 +677,10 @@ METHOD(ike_sa_t, set_state, void, } /* start DPD checks */ - send_dpd(this); + if (this->peer_cfg->get_dpd(this->peer_cfg)) + { + send_dpd(this); + } } break; } @@ -825,7 +825,7 @@ METHOD(ike_sa_t, float_ports, void, } METHOD(ike_sa_t, update_hosts, void, - private_ike_sa_t *this, host_t *me, host_t *other) + private_ike_sa_t *this, host_t *me, host_t *other, bool force) { bool update = FALSE; @@ -858,7 +858,7 @@ METHOD(ike_sa_t, update_hosts, void, if (!other->equals(other, this->other_host)) { /* update others adress if we are NOT NATed */ - if (!has_condition(this, COND_NAT_HERE)) + if (force || !has_condition(this, COND_NAT_HERE)) { set_other_host(this, other->clone(other)); update = TRUE; @@ -891,8 +891,14 @@ METHOD(ike_sa_t, update_hosts, void, METHOD(ike_sa_t, generate_message, status_t, private_ike_sa_t *this, message_t *message, packet_t **packet) { + if (message->is_encoded(message)) + { /* already done */ + *packet = message->get_packet(message); + return SUCCESS; + } this->stats[STAT_OUTBOUND] = time_monotonic(NULL); message->set_ike_sa_id(message, this->ike_sa_id); + charon->bus->message(charon->bus, message, FALSE); return message->generate(message, this->keymat->get_aead(this->keymat, FALSE), packet); } @@ -901,7 +907,7 @@ METHOD(ike_sa_t, generate_message, status_t, * send a notify back to the sender */ static void send_notify_response(private_ike_sa_t *this, message_t *request, - notify_type_t type) + notify_type_t type, chunk_t data) { message_t *response; packet_t *packet; @@ -910,7 +916,7 @@ static void send_notify_response(private_ike_sa_t *this, message_t *request, response->set_exchange_type(response, request->get_exchange_type(request)); response->set_request(response, FALSE); response->set_message_id(response, request->get_message_id(request)); - response->add_notify(response, FALSE, type, chunk_empty); + response->add_notify(response, FALSE, type, data); if (this->my_host->is_anyaddr(this->my_host)) { this->my_host->destroy(this->my_host); @@ -1175,6 +1181,7 @@ METHOD(ike_sa_t, process_message, status_t, { status_t status; bool is_request; + u_int8_t type = 0; if (this->state == IKE_PASSIVE) { /* do not handle messages in passive state */ @@ -1185,9 +1192,29 @@ METHOD(ike_sa_t, process_message, status_t, status = message->parse_body(message, this->keymat->get_aead(this->keymat, TRUE)); + if (status == SUCCESS) + { /* check for unsupported critical payloads */ + enumerator_t *enumerator; + unknown_payload_t *unknown; + payload_t *payload; + + enumerator = message->create_payload_enumerator(message); + while (enumerator->enumerate(enumerator, &payload)) + { + unknown = (unknown_payload_t*)payload; + type = payload->get_type(payload); + if (!payload_is_known(type) && + unknown->is_critical(unknown)) + { + DBG1(DBG_ENC, "payload type %N is not supported, " + "but its critical!", payload_type_names, type); + status = NOT_SUPPORTED; + } + } + enumerator->destroy(enumerator); + } if (status != SUCCESS) { - if (is_request) { switch (status) @@ -1196,21 +1223,28 @@ METHOD(ike_sa_t, process_message, status_t, DBG1(DBG_IKE, "critical unknown payloads found"); if (is_request) { - send_notify_response(this, message, UNSUPPORTED_CRITICAL_PAYLOAD); + send_notify_response(this, message, + UNSUPPORTED_CRITICAL_PAYLOAD, + chunk_from_thing(type)); + this->task_manager->incr_mid(this->task_manager, FALSE); } break; case PARSE_ERROR: DBG1(DBG_IKE, "message parsing failed"); if (is_request) { - send_notify_response(this, message, INVALID_SYNTAX); + send_notify_response(this, message, + INVALID_SYNTAX, chunk_empty); + this->task_manager->incr_mid(this->task_manager, FALSE); } break; case VERIFY_ERROR: DBG1(DBG_IKE, "message verification failed"); if (is_request) { - send_notify_response(this, message, INVALID_SYNTAX); + send_notify_response(this, message, + INVALID_SYNTAX, chunk_empty); + this->task_manager->incr_mid(this->task_manager, FALSE); } break; case FAILED: @@ -1219,10 +1253,6 @@ METHOD(ike_sa_t, process_message, status_t, break; case INVALID_STATE: DBG1(DBG_IKE, "found encrypted message, but no keys available"); - if (is_request) - { - send_notify_response(this, message, INVALID_SYNTAX); - } default: break; } @@ -1252,7 +1282,8 @@ METHOD(ike_sa_t, process_message, status_t, /* no config found for these hosts, destroy */ DBG1(DBG_IKE, "no IKE config found for %H...%H, sending %N", me, other, notify_type_names, NO_PROPOSAL_CHOSEN); - send_notify_response(this, message, NO_PROPOSAL_CHOSEN); + send_notify_response(this, message, + NO_PROPOSAL_CHOSEN, chunk_empty); return DESTROY_ME; } /* add a timeout if peer does not establish it completely */ diff --git a/src/libcharon/sa/ike_sa.h b/src/libcharon/sa/ike_sa.h index c0007e27d..988100bcc 100644 --- a/src/libcharon/sa/ike_sa.h +++ b/src/libcharon/sa/ike_sa.h @@ -343,8 +343,9 @@ struct ike_sa_t { * * @param me new local host address, or NULL * @param other new remote host address, or NULL + * @param force force update */ - void (*update_hosts)(ike_sa_t *this, host_t *me, host_t *other); + void (*update_hosts)(ike_sa_t *this, host_t *me, host_t *other, bool force); /** * Get the own identification. diff --git a/src/libcharon/sa/ike_sa_manager.c b/src/libcharon/sa/ike_sa_manager.c index fa94bb86d..d695c7f7c 100644 --- a/src/libcharon/sa/ike_sa_manager.c +++ b/src/libcharon/sa/ike_sa_manager.c @@ -1,6 +1,7 @@ /* + * Copyright (C) 2005-2011 Martin Willi + * Copyright (C) 2011 revosec AG * Copyright (C) 2008 Tobias Brunner - * Copyright (C) 2005-2008 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil * @@ -85,7 +86,9 @@ struct entry_t { chunk_t init_hash; /** - * remote host address, required for DoS detection + * remote host address, required for DoS detection and duplicate + * checking (host with same my_id and other_id is *not* considered + * a duplicate if the address family differs) */ host_t *other; @@ -241,6 +244,9 @@ struct connected_peers_t { /** remote identity */ identification_t *other_id; + /** ip address family of peer */ + int family; + /** list of ike_sa_id_t objects of IKE_SAs between the two identities */ linked_list_t *sas; }; @@ -257,10 +263,12 @@ static void connected_peers_destroy(connected_peers_t *this) * Function that matches connected_peers_t objects by the given ids. */ static bool connected_peers_match(connected_peers_t *connected_peers, - identification_t *my_id, identification_t *other_id) + identification_t *my_id, identification_t *other_id, + uintptr_t family) { return my_id->equals(my_id, connected_peers->my_id) && - other_id->equals(other_id, connected_peers->other_id); + other_id->equals(other_id, connected_peers->other_id) && + family == connected_peers->family; } typedef struct segment_t segment_t; @@ -396,7 +404,7 @@ static void lock_all_segments(private_ike_sa_manager_t *this) { u_int i; - for (i = 0; i < this->segment_count; ++i) + for (i = 0; i < this->segment_count; i++) { this->segments[i].mutex->lock(this->segments[i].mutex); } @@ -409,7 +417,7 @@ static void unlock_all_segments(private_ike_sa_manager_t *this) { u_int i; - for (i = 0; i < this->segment_count; ++i) + for (i = 0; i < this->segment_count; i++) { this->segments[i].mutex->unlock(this->segments[i].mutex); } @@ -453,10 +461,8 @@ struct private_enumerator_t { enumerator_t *current; }; -/** - * Implementation of private_enumerator_t.enumerator.enumerate. - */ -static bool enumerate(private_enumerator_t *this, entry_t **entry, u_int *segment) +METHOD(enumerator_t, enumerate, bool, + private_enumerator_t *this, entry_t **entry, u_int *segment) { if (this->entry) { @@ -502,10 +508,8 @@ static bool enumerate(private_enumerator_t *this, entry_t **entry, u_int *segmen return FALSE; } -/** - * Implementation of private_enumerator_t.enumerator.destroy. - */ -static void enumerator_destroy(private_enumerator_t *this) +METHOD(enumerator_t, enumerator_destroy, void, + private_enumerator_t *this) { if (this->entry) { @@ -524,16 +528,15 @@ static void enumerator_destroy(private_enumerator_t *this) */ static enumerator_t* create_table_enumerator(private_ike_sa_manager_t *this) { - private_enumerator_t *enumerator = malloc_thing(private_enumerator_t); - - enumerator->enumerator.enumerate = (void*)enumerate; - enumerator->enumerator.destroy = (void*)enumerator_destroy; - enumerator->manager = this; - enumerator->segment = 0; - enumerator->entry = NULL; - enumerator->row = 0; - enumerator->current = NULL; - + private_enumerator_t *enumerator; + + INIT(enumerator, + .enumerator = { + .enumerate = (void*)_enumerate, + .destroy = _enumerator_destroy, + }, + .manager = this, + ); return &enumerator->enumerator; } @@ -544,11 +547,14 @@ static enumerator_t* create_table_enumerator(private_ike_sa_manager_t *this) static u_int put_entry(private_ike_sa_manager_t *this, entry_t *entry) { linked_list_t *list; - u_int row = ike_sa_id_hash(entry->ike_sa_id) & this->table_mask; - u_int segment = row & this->segment_mask; + u_int row, segment; + + row = ike_sa_id_hash(entry->ike_sa_id) & this->table_mask; + segment = row & this->segment_mask; lock_single_segment(this, segment); - if ((list = this->ike_sa_table[row]) == NULL) + list = this->ike_sa_table[row]; + if (!list) { list = this->ike_sa_table[row] = linked_list_create(); } @@ -564,14 +570,17 @@ static u_int put_entry(private_ike_sa_manager_t *this, entry_t *entry) static void remove_entry(private_ike_sa_manager_t *this, entry_t *entry) { linked_list_t *list; - u_int row = ike_sa_id_hash(entry->ike_sa_id) & this->table_mask; - u_int segment = row & this->segment_mask; + u_int row, segment; - if ((list = this->ike_sa_table[row]) != NULL) + row = ike_sa_id_hash(entry->ike_sa_id) & this->table_mask; + segment = row & this->segment_mask; + list = this->ike_sa_table[row]; + if (list) { entry_t *current; + enumerator_t *enumerator; - enumerator_t *enumerator = list->create_enumerator(list); + enumerator = list->create_enumerator(list); while (enumerator->enumerate(enumerator, ¤t)) { if (current == entry) @@ -609,11 +618,14 @@ static status_t get_entry_by_match_function(private_ike_sa_manager_t *this, { entry_t *current; linked_list_t *list; - u_int row = ike_sa_id_hash(ike_sa_id) & this->table_mask; - u_int seg = row & this->segment_mask; + u_int row, seg; + + row = ike_sa_id_hash(ike_sa_id) & this->table_mask; + seg = row & this->segment_mask; lock_single_segment(this, seg); - if ((list = this->ike_sa_table[row]) != NULL) + list = this->ike_sa_table[row]; + if (list) { if (list->find_first(list, match, (void**)¤t, p1, p2) == SUCCESS) { @@ -697,19 +709,20 @@ static void put_half_open(private_ike_sa_manager_t *this, entry_t *entry) { half_open_t *half_open = NULL; linked_list_t *list; - chunk_t addr = entry->other->get_address(entry->other); - u_int row = chunk_hash(addr) & this->table_mask; - u_int segment = row & this->segment_mask; + chunk_t addr; + u_int row, segment; + rwlock_t *lock; - rwlock_t *lock = this->half_open_segments[segment].lock; + addr = entry->other->get_address(entry->other); + row = chunk_hash(addr) & this->table_mask; + segment = row & this->segment_mask; + lock = this->half_open_segments[segment].lock; lock->write_lock(lock); - if ((list = this->half_open_table[row]) == NULL) - { - list = this->half_open_table[row] = linked_list_create(); - } - else + list = this->half_open_table[row]; + if (list) { half_open_t *current; + if (list->find_first(list, (linked_list_match_t)half_open_match, (void**)¤t, &addr) == SUCCESS) { @@ -718,12 +731,17 @@ static void put_half_open(private_ike_sa_manager_t *this, entry_t *entry) this->half_open_segments[segment].count++; } } + else + { + list = this->half_open_table[row] = linked_list_create(); + } if (!half_open) { - half_open = malloc_thing(half_open_t); - half_open->other = chunk_clone(addr); - half_open->count = 1; + INIT(half_open, + .other = chunk_clone(addr), + .count = 1, + ); list->insert_last(list, half_open); this->half_open_segments[segment].count++; } @@ -736,16 +754,22 @@ static void put_half_open(private_ike_sa_manager_t *this, entry_t *entry) static void remove_half_open(private_ike_sa_manager_t *this, entry_t *entry) { linked_list_t *list; - chunk_t addr = entry->other->get_address(entry->other); - u_int row = chunk_hash(addr) & this->table_mask; - u_int segment = row & this->segment_mask; + chunk_t addr; + u_int row, segment; + rwlock_t *lock; - rwlock_t *lock = this->half_open_segments[segment].lock; + addr = entry->other->get_address(entry->other); + row = chunk_hash(addr) & this->table_mask; + segment = row & this->segment_mask; + lock = this->half_open_segments[segment].lock; lock->write_lock(lock); - if ((list = this->half_open_table[row]) != NULL) + list = this->half_open_table[row]; + if (list) { half_open_t *current; - enumerator_t *enumerator = list->create_enumerator(list); + enumerator_t *enumerator; + + enumerator = list->create_enumerator(list); while (enumerator->enumerate(enumerator, ¤t)) { if (half_open_match(current, &addr)) @@ -769,24 +793,26 @@ static void remove_half_open(private_ike_sa_manager_t *this, entry_t *entry) */ static void put_connected_peers(private_ike_sa_manager_t *this, entry_t *entry) { - linked_list_t *list; connected_peers_t *connected_peers = NULL; - chunk_t my_id = entry->my_id->get_encoding(entry->my_id), - other_id = entry->other_id->get_encoding(entry->other_id); - u_int row = chunk_hash_inc(other_id, chunk_hash(my_id)) & this->table_mask; - u_int segment = row & this->segment_mask; + chunk_t my_id, other_id; + linked_list_t *list; + u_int row, segment; + rwlock_t *lock; - rwlock_t *lock = this->connected_peers_segments[segment].lock; + my_id = entry->my_id->get_encoding(entry->my_id); + other_id = entry->other_id->get_encoding(entry->other_id); + row = chunk_hash_inc(other_id, chunk_hash(my_id)) & this->table_mask; + segment = row & this->segment_mask; + lock = this->connected_peers_segments[segment].lock; lock->write_lock(lock); - if ((list = this->connected_peers_table[row]) == NULL) - { - list = this->connected_peers_table[row] = linked_list_create(); - } - else + list = this->connected_peers_table[row]; + if (list) { connected_peers_t *current; + if (list->find_first(list, (linked_list_match_t)connected_peers_match, - (void**)¤t, entry->my_id, entry->other_id) == SUCCESS) + (void**)¤t, entry->my_id, entry->other_id, + (uintptr_t)entry->other->get_family(entry->other)) == SUCCESS) { connected_peers = current; if (connected_peers->sas->find_first(connected_peers->sas, @@ -798,13 +824,19 @@ static void put_connected_peers(private_ike_sa_manager_t *this, entry_t *entry) } } } + else + { + list = this->connected_peers_table[row] = linked_list_create(); + } if (!connected_peers) { - connected_peers = malloc_thing(connected_peers_t); - connected_peers->my_id = entry->my_id->clone(entry->my_id); - connected_peers->other_id = entry->other_id->clone(entry->other_id); - connected_peers->sas = linked_list_create(); + INIT(connected_peers, + .my_id = entry->my_id->clone(entry->my_id), + .other_id = entry->other_id->clone(entry->other_id), + .family = entry->other->get_family(entry->other), + .sas = linked_list_create(), + ); list->insert_last(list, connected_peers); } connected_peers->sas->insert_last(connected_peers->sas, @@ -818,24 +850,34 @@ static void put_connected_peers(private_ike_sa_manager_t *this, entry_t *entry) */ static void remove_connected_peers(private_ike_sa_manager_t *this, entry_t *entry) { + chunk_t my_id, other_id; linked_list_t *list; - chunk_t my_id = entry->my_id->get_encoding(entry->my_id), - other_id = entry->other_id->get_encoding(entry->other_id); - u_int row = chunk_hash_inc(other_id, chunk_hash(my_id)) & this->table_mask; - u_int segment = row & this->segment_mask; + u_int row, segment; + rwlock_t *lock; + + my_id = entry->my_id->get_encoding(entry->my_id); + other_id = entry->other_id->get_encoding(entry->other_id); + row = chunk_hash_inc(other_id, chunk_hash(my_id)) & this->table_mask; + segment = row & this->segment_mask; - rwlock_t *lock = this->connected_peers_segments[segment].lock; + lock = this->connected_peers_segments[segment].lock; lock->write_lock(lock); - if ((list = this->connected_peers_table[row]) != NULL) + list = this->connected_peers_table[row]; + if (list) { connected_peers_t *current; - enumerator_t *enumerator = list->create_enumerator(list); + enumerator_t *enumerator; + + enumerator = list->create_enumerator(list); while (enumerator->enumerate(enumerator, ¤t)) { - if (connected_peers_match(current, entry->my_id, entry->other_id)) + if (connected_peers_match(current, entry->my_id, entry->other_id, + (uintptr_t)entry->other->get_family(entry->other))) { ike_sa_id_t *ike_sa_id; - enumerator_t *inner = current->sas->create_enumerator(current->sas); + enumerator_t *inner; + + inner = current->sas->create_enumerator(current->sas); while (inner->enumerate(inner, &ike_sa_id)) { if (ike_sa_id->equals(ike_sa_id, entry->ike_sa_id)) @@ -861,20 +903,21 @@ static void remove_connected_peers(private_ike_sa_manager_t *this, entry_t *entr } /** - * Implementation of private_ike_sa_manager_t.get_next_spi. + * Get a random SPI for new IKE_SAs */ -static u_int64_t get_next_spi(private_ike_sa_manager_t *this) +static u_int64_t get_spi(private_ike_sa_manager_t *this) { - u_int64_t spi; + u_int64_t spi = 0; - this->rng->get_bytes(this->rng, sizeof(spi), (u_int8_t*)&spi); + if (this->rng) + { + this->rng->get_bytes(this->rng, sizeof(spi), (u_int8_t*)&spi); + } return spi; } -/** - * Implementation of of ike_sa_manager.checkout. - */ -static ike_sa_t* checkout(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id) +METHOD(ike_sa_manager_t, checkout, ike_sa_t*, + private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id) { ike_sa_t *ike_sa = NULL; entry_t *entry; @@ -897,62 +940,46 @@ static ike_sa_t* checkout(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id return ike_sa; } -/** - * Implementation of of ike_sa_manager.checkout_new. - */ -static ike_sa_t *checkout_new(private_ike_sa_manager_t* this, bool initiator) +METHOD(ike_sa_manager_t, checkout_new, ike_sa_t*, + private_ike_sa_manager_t* this, bool initiator) { ike_sa_id_t *ike_sa_id; ike_sa_t *ike_sa; - entry_t *entry; - u_int segment; if (initiator) { - ike_sa_id = ike_sa_id_create(get_next_spi(this), 0, TRUE); + ike_sa_id = ike_sa_id_create(get_spi(this), 0, TRUE); } else { - ike_sa_id = ike_sa_id_create(0, get_next_spi(this), FALSE); + ike_sa_id = ike_sa_id_create(0, get_spi(this), FALSE); } ike_sa = ike_sa_create(ike_sa_id); + ike_sa_id->destroy(ike_sa_id); DBG2(DBG_MGR, "created IKE_SA %s[%u]", ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa)); - if (!initiator) - { - ike_sa_id->destroy(ike_sa_id); - return ike_sa; - } - - entry = entry_create(); - entry->ike_sa_id = ike_sa_id; - entry->ike_sa = ike_sa; - segment = put_entry(this, entry); - entry->checked_out = TRUE; - unlock_single_segment(this, segment); - return entry->ike_sa; + return ike_sa; } -/** - * Implementation of of ike_sa_manager.checkout_by_message. - */ -static ike_sa_t* checkout_by_message(private_ike_sa_manager_t* this, - message_t *message) +METHOD(ike_sa_manager_t, checkout_by_message, ike_sa_t*, + private_ike_sa_manager_t* this, message_t *message) { u_int segment; entry_t *entry; ike_sa_t *ike_sa = NULL; - ike_sa_id_t *id = message->get_ike_sa_id(message); + ike_sa_id_t *id; + id = message->get_ike_sa_id(message); id = id->clone(id); id->switch_initiator(id); DBG2(DBG_MGR, "checkout IKE_SA by message"); if (message->get_request(message) && - message->get_exchange_type(message) == IKE_SA_INIT) + message->get_exchange_type(message) == IKE_SA_INIT && + this->hasher) { /* IKE_SA_INIT request. Check for an IKE_SA with such a message hash. */ chunk_t data, hash; @@ -988,7 +1015,7 @@ static ike_sa_t* checkout_by_message(private_ike_sa_manager_t* this, message->get_exchange_type(message) == IKE_SA_INIT) { /* no IKE_SA found, create a new one */ - id->set_responder_spi(id, get_next_spi(this)); + id->set_responder_spi(id, get_spi(this)); entry = entry_create(); entry->ike_sa = ike_sa_create(id); entry->ike_sa_id = id->clone(id); @@ -1048,11 +1075,8 @@ static ike_sa_t* checkout_by_message(private_ike_sa_manager_t* this, return ike_sa; } -/** - * Implementation of of ike_sa_manager.checkout_by_config. - */ -static ike_sa_t* checkout_by_config(private_ike_sa_manager_t *this, - peer_cfg_t *peer_cfg) +METHOD(ike_sa_manager_t, checkout_by_config, ike_sa_t*, + private_ike_sa_manager_t *this, peer_cfg_t *peer_cfg) { enumerator_t *enumerator; entry_t *entry; @@ -1107,11 +1131,8 @@ static ike_sa_t* checkout_by_config(private_ike_sa_manager_t *this, return ike_sa; } -/** - * Implementation of of ike_sa_manager.checkout_by_id. - */ -static ike_sa_t* checkout_by_id(private_ike_sa_manager_t *this, u_int32_t id, - bool child) +METHOD(ike_sa_manager_t, checkout_by_id, ike_sa_t*, + private_ike_sa_manager_t *this, u_int32_t id, bool child) { enumerator_t *enumerator; iterator_t *children; @@ -1164,11 +1185,8 @@ static ike_sa_t* checkout_by_id(private_ike_sa_manager_t *this, u_int32_t id, return ike_sa; } -/** - * Implementation of of ike_sa_manager.checkout_by_name. - */ -static ike_sa_t* checkout_by_name(private_ike_sa_manager_t *this, char *name, - bool child) +METHOD(ike_sa_manager_t, checkout_by_name, ike_sa_t*, + private_ike_sa_manager_t *this, char *name, bool child) { enumerator_t *enumerator; iterator_t *children; @@ -1233,20 +1251,15 @@ static bool enumerator_filter(private_ike_sa_manager_t *this, return FALSE; } -/** - * Implementation of ike_sa_manager_t.create_enumerator. - */ -static enumerator_t *create_enumerator(private_ike_sa_manager_t* this) +METHOD(ike_sa_manager_t, create_enumerator, enumerator_t*, + private_ike_sa_manager_t* this) { - return enumerator_create_filter( - create_table_enumerator(this), - (void*)enumerator_filter, this, NULL); + return enumerator_create_filter(create_table_enumerator(this), + (void*)enumerator_filter, this, NULL); } -/** - * Implementation of ike_sa_manager_t.checkin. - */ -static void checkin(private_ike_sa_manager_t *this, ike_sa_t *ike_sa) +METHOD(ike_sa_manager_t, checkin, void, + private_ike_sa_manager_t *this, ike_sa_t *ike_sa) { /* to check the SA back in, we look for the pointer of the ike_sa * in all entries. @@ -1311,13 +1324,16 @@ static void checkin(private_ike_sa_manager_t *this, ike_sa_t *ike_sa) segment = put_entry(this, entry); } - /* apply identities for duplicate test (only as responder) */ - if (!entry->ike_sa_id->is_initiator(entry->ike_sa_id) && - ike_sa->get_state(ike_sa) == IKE_ESTABLISHED && + /* apply identities for duplicate test */ + if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED && entry->my_id == NULL && entry->other_id == NULL) { entry->my_id = my_id->clone(my_id); entry->other_id = other_id->clone(other_id); + if (!entry->other) + { + entry->other = other->clone(other); + } put_connected_peers(this, entry); } @@ -1326,10 +1342,8 @@ static void checkin(private_ike_sa_manager_t *this, ike_sa_t *ike_sa) charon->bus->set_sa(charon->bus, NULL); } -/** - * Implementation of ike_sa_manager_t.checkin_and_destroy. - */ -static void checkin_and_destroy(private_ike_sa_manager_t *this, ike_sa_t *ike_sa) +METHOD(ike_sa_manager_t, checkin_and_destroy, void, + private_ike_sa_manager_t *this, ike_sa_t *ike_sa) { /* deletion is a bit complex, we must ensure that no thread is waiting for * this SA. @@ -1366,8 +1380,7 @@ static void checkin_and_destroy(private_ike_sa_manager_t *this, ike_sa_t *ike_sa { remove_half_open(this, entry); } - if (!entry->ike_sa_id->is_initiator(entry->ike_sa_id) && - entry->my_id && entry->other_id) + if (entry->my_id && entry->other_id) { remove_connected_peers(this, entry); } @@ -1384,11 +1397,8 @@ static void checkin_and_destroy(private_ike_sa_manager_t *this, ike_sa_t *ike_sa charon->bus->set_sa(charon->bus, NULL); } - -/** - * Implementation of ike_sa_manager_t.check_uniqueness. - */ -static bool check_uniqueness(private_ike_sa_manager_t *this, ike_sa_t *ike_sa) +METHOD(ike_sa_manager_t, check_uniqueness, bool, + private_ike_sa_manager_t *this, ike_sa_t *ike_sa, bool force_replace) { bool cancel = FALSE; peer_cfg_t *peer_cfg; @@ -1402,7 +1412,7 @@ static bool check_uniqueness(private_ike_sa_manager_t *this, ike_sa_t *ike_sa) peer_cfg = ike_sa->get_peer_cfg(ike_sa); policy = peer_cfg->get_unique_policy(peer_cfg); - if (policy == UNIQUE_NO) + if (policy == UNIQUE_NO && !force_replace) { return FALSE; } @@ -1416,12 +1426,16 @@ static bool check_uniqueness(private_ike_sa_manager_t *this, ike_sa_t *ike_sa) lock = this->connected_peers_segments[segment & this->segment_mask].lock; lock->read_lock(lock); - if ((list = this->connected_peers_table[row]) != NULL) + list = this->connected_peers_table[row]; + if (list) { connected_peers_t *current; + host_t *other_host; + other_host = ike_sa->get_other_host(ike_sa); if (list->find_first(list, (linked_list_match_t)connected_peers_match, - (void**)¤t, me, other) == SUCCESS) + (void**)¤t, me, other, + (uintptr_t)other_host->get_family(other_host)) == SUCCESS) { /* clone the list, so we can release the lock */ duplicate_ids = current->sas->clone_offset(current->sas, @@ -1446,6 +1460,13 @@ static bool check_uniqueness(private_ike_sa_manager_t *this, ike_sa_t *ike_sa) { continue; } + if (force_replace) + { + DBG1(DBG_IKE, "destroying duplicate IKE_SA for peer '%Y', " + "received INITIAL_CONTACT", other); + checkin_and_destroy(this, duplicate); + continue; + } peer_cfg = duplicate->get_peer_cfg(duplicate); if (peer_cfg && peer_cfg->equals(peer_cfg, ike_sa->get_peer_cfg(ike_sa))) { @@ -1490,21 +1511,49 @@ static bool check_uniqueness(private_ike_sa_manager_t *this, ike_sa_t *ike_sa) return cancel; } -/** - * Implementation of ike_sa_manager_t.get_half_open_count. - */ -static int get_half_open_count(private_ike_sa_manager_t *this, host_t *ip) +METHOD(ike_sa_manager_t, has_contact, bool, + private_ike_sa_manager_t *this, identification_t *me, + identification_t *other, int family) +{ + linked_list_t *list; + u_int row, segment; + rwlock_t *lock; + bool found = FALSE; + + row = chunk_hash_inc(other->get_encoding(other), + chunk_hash(me->get_encoding(me))) & this->table_mask; + segment = row & this->segment_mask; + lock = this->connected_peers_segments[segment & this->segment_mask].lock; + lock->read_lock(lock); + list = this->connected_peers_table[row]; + if (list) + { + if (list->find_first(list, (linked_list_match_t)connected_peers_match, + NULL, me, other, family) == SUCCESS) + { + found = TRUE; + } + } + lock->unlock(lock); + + return found; +} + +METHOD(ike_sa_manager_t, get_half_open_count, int, + private_ike_sa_manager_t *this, host_t *ip) { + linked_list_t *list; + u_int segment, row; + rwlock_t *lock; + chunk_t addr; int count = 0; if (ip) { - linked_list_t *list; - chunk_t addr = ip->get_address(ip); - u_int row = chunk_hash(addr) & this->table_mask; - u_int segment = row & this->segment_mask; - - rwlock_t *lock = this->half_open_segments[segment & this->segment_mask].lock; + addr = ip->get_address(ip); + row = chunk_hash(addr) & this->table_mask; + segment = row & this->segment_mask; + lock = this->half_open_segments[segment & this->segment_mask].lock; lock->read_lock(lock); if ((list = this->half_open_table[row]) != NULL) { @@ -1520,25 +1569,19 @@ static int get_half_open_count(private_ike_sa_manager_t *this, host_t *ip) } else { - u_int segment; - - for (segment = 0; segment < this->segment_count; ++segment) + for (segment = 0; segment < this->segment_count; segment++) { - rwlock_t *lock; lock = this->half_open_segments[segment & this->segment_mask].lock; lock->read_lock(lock); count += this->half_open_segments[segment].count; lock->unlock(lock); } } - return count; } -/** - * Implementation of ike_sa_manager_t.flush. - */ -static void flush(private_ike_sa_manager_t *this) +METHOD(ike_sa_manager_t, flush, void, + private_ike_sa_manager_t *this) { /* destroy all list entries */ enumerator_t *enumerator; @@ -1602,8 +1645,7 @@ static void flush(private_ike_sa_manager_t *this) { remove_half_open(this, entry); } - if (!entry->ike_sa_id->is_initiator(entry->ike_sa_id) && - entry->my_id && entry->other_id) + if (entry->my_id && entry->other_id) { remove_connected_peers(this, entry); } @@ -1615,37 +1657,26 @@ static void flush(private_ike_sa_manager_t *this) unlock_all_segments(this); this->rng->destroy(this->rng); + this->rng = NULL; this->hasher->destroy(this->hasher); + this->hasher = NULL; } -/** - * Implementation of ike_sa_manager_t.destroy. - */ -static void destroy(private_ike_sa_manager_t *this) +METHOD(ike_sa_manager_t, destroy, void, + private_ike_sa_manager_t *this) { u_int i; - for (i = 0; i < this->table_size; ++i) + for (i = 0; i < this->table_size; i++) { - linked_list_t *list; - - if ((list = this->ike_sa_table[i]) != NULL) - { - list->destroy(list); - } - if ((list = this->half_open_table[i]) != NULL) - { - list->destroy(list); - } - if ((list = this->connected_peers_table[i]) != NULL) - { - list->destroy(list); - } + DESTROY_IF(this->ike_sa_table[i]); + DESTROY_IF(this->half_open_table[i]); + DESTROY_IF(this->connected_peers_table[i]); } free(this->ike_sa_table); free(this->half_open_table); free(this->connected_peers_table); - for (i = 0; i < this->segment_count; ++i) + for (i = 0; i < this->segment_count; i++) { this->segments[i].mutex->destroy(this->segments[i].mutex); this->half_open_segments[i].lock->destroy(this->half_open_segments[i].lock); @@ -1681,25 +1712,28 @@ static u_int get_nearest_powerof2(u_int n) */ ike_sa_manager_t *ike_sa_manager_create() { + private_ike_sa_manager_t *this; u_int i; - private_ike_sa_manager_t *this = malloc_thing(private_ike_sa_manager_t); - - /* assign public functions */ - this->public.flush = (void(*)(ike_sa_manager_t*))flush; - this->public.destroy = (void(*)(ike_sa_manager_t*))destroy; - this->public.checkout = (ike_sa_t*(*)(ike_sa_manager_t*, ike_sa_id_t*))checkout; - this->public.checkout_new = (ike_sa_t*(*)(ike_sa_manager_t*,bool))checkout_new; - this->public.checkout_by_message = (ike_sa_t*(*)(ike_sa_manager_t*,message_t*))checkout_by_message; - this->public.checkout_by_config = (ike_sa_t*(*)(ike_sa_manager_t*,peer_cfg_t*))checkout_by_config; - this->public.checkout_by_id = (ike_sa_t*(*)(ike_sa_manager_t*,u_int32_t,bool))checkout_by_id; - this->public.checkout_by_name = (ike_sa_t*(*)(ike_sa_manager_t*,char*,bool))checkout_by_name; - this->public.check_uniqueness = (bool(*)(ike_sa_manager_t*, ike_sa_t *ike_sa))check_uniqueness; - this->public.create_enumerator = (enumerator_t*(*)(ike_sa_manager_t*))create_enumerator; - this->public.checkin = (void(*)(ike_sa_manager_t*,ike_sa_t*))checkin; - this->public.checkin_and_destroy = (void(*)(ike_sa_manager_t*,ike_sa_t*))checkin_and_destroy; - this->public.get_half_open_count = (int(*)(ike_sa_manager_t*,host_t*))get_half_open_count; - - /* initialize private variables */ + + INIT(this, + .public = { + .checkout = _checkout, + .checkout_new = _checkout_new, + .checkout_by_message = _checkout_by_message, + .checkout_by_config = _checkout_by_config, + .checkout_by_id = _checkout_by_id, + .checkout_by_name = _checkout_by_name, + .check_uniqueness = _check_uniqueness, + .has_contact = _has_contact, + .create_enumerator = _create_enumerator, + .checkin = _checkin, + .checkin_and_destroy = _checkin_and_destroy, + .get_half_open_count = _get_half_open_count, + .flush = _flush, + .destroy = _destroy, + }, + ); + this->hasher = lib->crypto->create_hasher(lib->crypto, HASH_PREFERRED); if (this->hasher == NULL) { @@ -1715,6 +1749,7 @@ ike_sa_manager_t *ike_sa_manager_create() free(this); return NULL; } + this->table_size = get_nearest_powerof2(lib->settings->get_int(lib->settings, "charon.ikesa_table_size", DEFAULT_HASHTABLE_SIZE)); this->table_size = max(1, min(this->table_size, MAX_HASHTABLE_SIZE)); @@ -1724,11 +1759,10 @@ ike_sa_manager_t *ike_sa_manager_create() "charon.ikesa_table_segments", DEFAULT_SEGMENT_COUNT)); this->segment_count = max(1, min(this->segment_count, this->table_size)); this->segment_mask = this->segment_count - 1; - this->ike_sa_table = calloc(this->table_size, sizeof(linked_list_t*)); this->segments = (segment_t*)calloc(this->segment_count, sizeof(segment_t)); - for (i = 0; i < this->segment_count; ++i) + for (i = 0; i < this->segment_count; i++) { this->segments[i].mutex = mutex_create(MUTEX_TYPE_RECURSIVE); this->segments[i].count = 0; @@ -1737,7 +1771,7 @@ ike_sa_manager_t *ike_sa_manager_create() /* we use the same table parameters for the table to track half-open SAs */ this->half_open_table = calloc(this->table_size, sizeof(linked_list_t*)); this->half_open_segments = calloc(this->segment_count, sizeof(shareable_segment_t)); - for (i = 0; i < this->segment_count; ++i) + for (i = 0; i < this->segment_count; i++) { this->half_open_segments[i].lock = rwlock_create(RWLOCK_TYPE_DEFAULT); this->half_open_segments[i].count = 0; @@ -1746,7 +1780,7 @@ ike_sa_manager_t *ike_sa_manager_create() /* also for the hash table used for duplicate tests */ this->connected_peers_table = calloc(this->table_size, sizeof(linked_list_t*)); this->connected_peers_segments = calloc(this->segment_count, sizeof(shareable_segment_t)); - for (i = 0; i < this->segment_count; ++i) + for (i = 0; i < this->segment_count; i++) { this->connected_peers_segments[i].lock = rwlock_create(RWLOCK_TYPE_DEFAULT); this->connected_peers_segments[i].count = 0; diff --git a/src/libcharon/sa/ike_sa_manager.h b/src/libcharon/sa/ike_sa_manager.h index f4eabf808..ec157ab3a 100644 --- a/src/libcharon/sa/ike_sa_manager.h +++ b/src/libcharon/sa/ike_sa_manager.h @@ -52,9 +52,6 @@ struct ike_sa_manager_t { /** * Create and check out a new IKE_SA. * - * @note If initiator equals FALSE, the returned IKE_SA is not registered - * in the manager. - * * @param initiator TRUE for initiator, FALSE otherwise * @returns created and checked out IKE_SA */ @@ -109,10 +106,23 @@ struct ike_sa_manager_t { * deadlocks occur otherwise. * * @param ike_sa ike_sa to check + * @param force_replace replace existing SAs, regardless of unique policy * @return TRUE, if the given IKE_SA has duplicates and * should be deleted */ - bool (*check_uniqueness)(ike_sa_manager_t *this, ike_sa_t *ike_sa); + bool (*check_uniqueness)(ike_sa_manager_t *this, ike_sa_t *ike_sa, + bool force_replace); + + /** + * Check if we already have a connected IKE_SA between two identities. + * + * @param me own identity + * @param other remote identity + * @param family address family to include in uniqueness check + * @return TRUE if we have a connected IKE_SA + */ + bool (*has_contact)(ike_sa_manager_t *this, identification_t *me, + identification_t *other, int family); /** * Check out an IKE_SA a unique ID. diff --git a/src/libcharon/sa/keymat.c b/src/libcharon/sa/keymat.c index 878ad124f..33ece24b2 100644 --- a/src/libcharon/sa/keymat.c +++ b/src/libcharon/sa/keymat.c @@ -214,7 +214,7 @@ static bool derive_ike_traditional(private_keymat_t *this, u_int16_t enc_alg, { DBG1(DBG_IKE, "%N %N (key size %d) not supported!", transform_type_names, ENCRYPTION_ALGORITHM, - encryption_algorithm_names, enc_alg, key_size); + encryption_algorithm_names, enc_alg, enc_size); signer_i->destroy(signer_i); signer_r->destroy(signer_r); return FALSE; @@ -540,7 +540,7 @@ METHOD(keymat_t, get_aead, aead_t*, METHOD(keymat_t, get_auth_octets, chunk_t, private_keymat_t *this, bool verify, chunk_t ike_sa_init, - chunk_t nonce, identification_t *id) + chunk_t nonce, identification_t *id, char reserved[3]) { chunk_t chunk, idx, octets; chunk_t skp; @@ -548,8 +548,8 @@ METHOD(keymat_t, get_auth_octets, chunk_t, skp = verify ? this->skp_verify : this->skp_build; chunk = chunk_alloca(4); - memset(chunk.ptr, 0, chunk.len); chunk.ptr[0] = id->get_type(id); + memcpy(chunk.ptr + 1, reserved, 3); idx = chunk_cata("cc", chunk, id->get_encoding(id)); DBG3(DBG_IKE, "IDx' %B", &idx); @@ -570,7 +570,7 @@ METHOD(keymat_t, get_auth_octets, chunk_t, METHOD(keymat_t, get_psk_sig, chunk_t, private_keymat_t *this, bool verify, chunk_t ike_sa_init, - chunk_t nonce, chunk_t secret, identification_t *id) + chunk_t nonce, chunk_t secret, identification_t *id, char reserved[3]) { chunk_t key_pad, key, sig, octets; @@ -578,7 +578,7 @@ METHOD(keymat_t, get_psk_sig, chunk_t, { /* EAP uses SK_p if no MSK has been established */ secret = verify ? this->skp_verify : this->skp_build; } - octets = get_auth_octets(this, verify, ike_sa_init, nonce, id); + octets = get_auth_octets(this, verify, ike_sa_init, nonce, id, reserved); /* AUTH = prf(prf(Shared Secret,"Key Pad for IKEv2"), <msg octets>) */ key_pad = chunk_create(IKEV2_KEY_PAD, IKEV2_KEY_PAD_LENGTH); this->prf->set_key(this->prf, secret); diff --git a/src/libcharon/sa/keymat.h b/src/libcharon/sa/keymat.h index 4f01aa411..11e0fa79a 100644 --- a/src/libcharon/sa/keymat.h +++ b/src/libcharon/sa/keymat.h @@ -117,10 +117,12 @@ struct keymat_t { * @param ike_sa_init encoded ike_sa_init message * @param nonce nonce value * @param id identity + * @param reserved reserved bytes of id_payload * @return authentication octets */ chunk_t (*get_auth_octets)(keymat_t *this, bool verify, chunk_t ike_sa_init, - chunk_t nonce, identification_t *id); + chunk_t nonce, identification_t *id, + char reserved[3]); /** * Build the shared secret signature used for PSK and EAP authentication. * @@ -133,10 +135,12 @@ struct keymat_t { * @param nonce nonce value * @param secret optional secret to include into signature * @param id identity + * @param reserved reserved bytes of id_payload * @return signature octets */ chunk_t (*get_psk_sig)(keymat_t *this, bool verify, chunk_t ike_sa_init, - chunk_t nonce, chunk_t secret, identification_t *id); + chunk_t nonce, chunk_t secret, + identification_t *id, char reserved[3]); /** * Destroy a keymat_t. */ diff --git a/src/libcharon/sa/task_manager.c b/src/libcharon/sa/task_manager.c index 18703ce36..9467d1586 100644 --- a/src/libcharon/sa/task_manager.c +++ b/src/libcharon/sa/task_manager.c @@ -465,7 +465,6 @@ METHOD(task_manager_t, initiate, status_t, /* update exchange type if a task changed it */ this->initiating.type = message->get_exchange_type(message); - charon->bus->message(charon->bus, message, FALSE); status = this->ike_sa->generate_message(this->ike_sa, message, &this->initiating.packet); if (status != SUCCESS) @@ -654,7 +653,6 @@ static status_t build_response(private_task_manager_t *this, message_t *request) /* message complete, send it */ DESTROY_IF(this->responding.packet); this->responding.packet = NULL; - charon->bus->message(charon->bus, message, FALSE); status = this->ike_sa->generate_message(this->ike_sa, message, &this->responding.packet); message->destroy(message); @@ -882,8 +880,12 @@ static status_t process_request(private_task_manager_t *this, METHOD(task_manager_t, process_message, status_t, private_task_manager_t *this, message_t *msg) { - u_int32_t mid = msg->get_message_id(msg); - host_t *me = msg->get_destination(msg), *other = msg->get_source(msg); + host_t *me, *other; + u_int32_t mid; + + mid = msg->get_message_id(msg); + me = msg->get_destination(msg); + other = msg->get_source(msg); if (msg->get_request(msg)) { @@ -895,10 +897,14 @@ METHOD(task_manager_t, process_message, status_t, { /* only do host updates based on verified messages */ if (!this->ike_sa->supports_extension(this->ike_sa, EXT_MOBIKE)) { /* with MOBIKE, we do no implicit updates */ - this->ike_sa->update_hosts(this->ike_sa, me, other); + this->ike_sa->update_hosts(this->ike_sa, me, other, mid == 1); } } charon->bus->message(charon->bus, msg, TRUE); + if (msg->get_exchange_type(msg) == EXCHANGE_TYPE_UNDEFINED) + { /* ignore messages altered to EXCHANGE_TYPE_UNDEFINED */ + return SUCCESS; + } if (process_request(this, msg) != SUCCESS) { flush(this); @@ -909,15 +915,15 @@ METHOD(task_manager_t, process_message, status_t, else if ((mid == this->responding.mid - 1) && this->responding.packet) { packet_t *clone; - host_t *me, *other; + host_t *host; DBG1(DBG_IKE, "received retransmit of request with ID %d, " "retransmitting response", mid); clone = this->responding.packet->clone(this->responding.packet); - me = msg->get_destination(msg); - other = msg->get_source(msg); - clone->set_source(clone, me->clone(me)); - clone->set_destination(clone, other->clone(other)); + host = msg->get_destination(msg); + clone->set_source(clone, host->clone(host)); + host = msg->get_source(msg); + clone->set_destination(clone, host->clone(host)); charon->sender->send(charon->sender, clone); } else @@ -936,10 +942,14 @@ METHOD(task_manager_t, process_message, status_t, { /* only do host updates based on verified messages */ if (!this->ike_sa->supports_extension(this->ike_sa, EXT_MOBIKE)) { /* with MOBIKE, we do no implicit updates */ - this->ike_sa->update_hosts(this->ike_sa, me, other); + this->ike_sa->update_hosts(this->ike_sa, me, other, FALSE); } } charon->bus->message(charon->bus, msg, TRUE); + if (msg->get_exchange_type(msg) == EXCHANGE_TYPE_UNDEFINED) + { /* ignore messages altered to EXCHANGE_TYPE_UNDEFINED */ + return SUCCESS; + } if (process_response(this, msg) != SUCCESS) { flush(this); @@ -1002,6 +1012,19 @@ METHOD(task_manager_t, busy, bool, return (this->active_tasks->get_count(this->active_tasks) > 0); } +METHOD(task_manager_t, incr_mid, void, + private_task_manager_t *this, bool initiate) +{ + if (initiate) + { + this->initiating.mid++; + } + else + { + this->responding.mid++; + } +} + METHOD(task_manager_t, reset, void, private_task_manager_t *this, u_int32_t initiate, u_int32_t respond) { @@ -1085,6 +1108,7 @@ task_manager_t *task_manager_create(ike_sa_t *ike_sa) .queue_task = _queue_task, .initiate = _initiate, .retransmit = _retransmit, + .incr_mid = _incr_mid, .reset = _reset, .adopt_tasks = _adopt_tasks, .busy = _busy, diff --git a/src/libcharon/sa/task_manager.h b/src/libcharon/sa/task_manager.h index 14fccd5f9..5bc6c80c4 100644 --- a/src/libcharon/sa/task_manager.h +++ b/src/libcharon/sa/task_manager.h @@ -149,6 +149,16 @@ struct task_manager_t { void (*adopt_tasks) (task_manager_t *this, task_manager_t *other); /** + * Increment a message ID counter, in- or outbound. + * + * If a message is processed outside of the manager, this call increments + * the message ID counters of the task manager. + * + * @param inititate TRUE to increment the initiating ID + */ + void (*incr_mid)(task_manager_t *this, bool initiate); + + /** * Reset message ID counters of the task manager. * * The IKEv2 protocol requires to restart exchanges with message IDs diff --git a/src/libcharon/sa/tasks/child_create.c b/src/libcharon/sa/tasks/child_create.c index 57beedba9..fc02a334b 100644 --- a/src/libcharon/sa/tasks/child_create.c +++ b/src/libcharon/sa/tasks/child_create.c @@ -117,6 +117,11 @@ struct private_child_create_t { ipsec_mode_t mode; /** + * peer accepts TFC padding for this SA + */ + bool tfcv3; + + /** * IPComp transform to use */ ipcomp_transform_t ipcomp; @@ -455,17 +460,21 @@ static status_t select_and_install(private_child_create_t *this, { if (this->initiator) { - status_i = this->child_sa->install(this->child_sa, encr_r, integ_r, - this->my_spi, this->my_cpi, TRUE, my_ts, other_ts); - status_o = this->child_sa->install(this->child_sa, encr_i, integ_i, - this->other_spi, this->other_cpi, FALSE, my_ts, other_ts); + status_i = this->child_sa->install(this->child_sa, + encr_r, integ_r, this->my_spi, this->my_cpi, + TRUE, this->tfcv3, my_ts, other_ts); + status_o = this->child_sa->install(this->child_sa, + encr_i, integ_i, this->other_spi, this->other_cpi, + FALSE, this->tfcv3, my_ts, other_ts); } else { - status_i = this->child_sa->install(this->child_sa, encr_i, integ_i, - this->my_spi, this->my_cpi, TRUE, my_ts, other_ts); - status_o = this->child_sa->install(this->child_sa, encr_r, integ_r, - this->other_spi, this->other_cpi, FALSE, my_ts, other_ts); + status_i = this->child_sa->install(this->child_sa, + encr_i, integ_i, this->my_spi, this->my_cpi, + TRUE, this->tfcv3, my_ts, other_ts); + status_o = this->child_sa->install(this->child_sa, + encr_r, integ_r, this->other_spi, this->other_cpi, + FALSE, this->tfcv3, my_ts, other_ts); } } chunk_clear(&integ_i); @@ -631,7 +640,13 @@ static void handle_notify(private_child_create_t *this, notify_payload_t *notify ipcomp_transform_names, ipcomp); break; } + break; } + case ESP_TFC_PADDING_NOT_SUPPORTED: + DBG1(DBG_IKE, "received %N, not using ESPv3 TFC padding", + notify_type_names, notify->get_notify_type(notify)); + this->tfcv3 = FALSE; + break; default: break; } @@ -691,10 +706,8 @@ static void process_payloads(private_child_create_t *this, message_t *message) enumerator->destroy(enumerator); } -/** - * Implementation of task_t.build for initiator - */ -static status_t build_i(private_child_create_t *this, message_t *message) +METHOD(task_t, build_i, status_t, + private_child_create_t *this, message_t *message) { host_t *me, *other, *vip; peer_cfg_t *peer_cfg; @@ -831,10 +844,8 @@ static status_t build_i(private_child_create_t *this, message_t *message) return NEED_MORE; } -/** - * Implementation of task_t.process for responder - */ -static status_t process_r(private_child_create_t *this, message_t *message) +METHOD(task_t, process_r, status_t, + private_child_create_t *this, message_t *message) { switch (message->get_exchange_type(message)) { @@ -877,10 +888,8 @@ static void handle_child_sa_failure(private_child_create_t *this, } } -/** - * Implementation of task_t.build for responder - */ -static status_t build_r(private_child_create_t *this, message_t *message) +METHOD(task_t, build_r, status_t, + private_child_create_t *this, message_t *message) { peer_cfg_t *peer_cfg; payload_t *payload; @@ -958,7 +967,7 @@ static status_t build_r(private_child_create_t *this, message_t *message) case INTERNAL_ADDRESS_FAILURE: case FAILED_CP_REQUIRED: { - DBG1(DBG_IKE,"configuration payload negotation " + DBG1(DBG_IKE,"configuration payload negotiation " "failed, no CHILD_SA built"); enumerator->destroy(enumerator); handle_child_sa_failure(this, message); @@ -1029,10 +1038,8 @@ static status_t build_r(private_child_create_t *this, message_t *message) return SUCCESS; } -/** - * Implementation of task_t.process for initiator - */ -static status_t process_i(private_child_create_t *this, message_t *message) +METHOD(task_t, process_i, status_t, + private_child_create_t *this, message_t *message) { enumerator_t *enumerator; payload_t *payload; @@ -1103,7 +1110,21 @@ static status_t process_i(private_child_create_t *this, message_t *message) return NEED_MORE; } default: + { + if (message->get_exchange_type(message) == CREATE_CHILD_SA) + { /* handle notifies if not handled in IKE_AUTH */ + if (type <= 16383) + { + DBG1(DBG_IKE, "received %N notify error", + notify_type_names, type); + enumerator->destroy(enumerator); + return SUCCESS; + } + DBG2(DBG_IKE, "received %N notify", + notify_type_names, type); + } break; + } } } } @@ -1155,34 +1176,20 @@ static status_t process_i(private_child_create_t *this, message_t *message) return SUCCESS; } -/** - * Implementation of task_t.get_type - */ -static task_type_t get_type(private_child_create_t *this) -{ - return CHILD_CREATE; -} - -/** - * Implementation of child_create_t.use_reqid - */ -static void use_reqid(private_child_create_t *this, u_int32_t reqid) +METHOD(child_create_t, use_reqid, void, + private_child_create_t *this, u_int32_t reqid) { this->reqid = reqid; } -/** - * Implementation of child_create_t.get_child - */ -static child_sa_t* get_child(private_child_create_t *this) +METHOD(child_create_t, get_child, child_sa_t*, + private_child_create_t *this) { return this->child_sa; } -/** - * Implementation of child_create_t.get_lower_nonce - */ -static chunk_t get_lower_nonce(private_child_create_t *this) +METHOD(child_create_t, get_lower_nonce, chunk_t, + private_child_create_t *this) { if (memcmp(this->my_nonce.ptr, this->other_nonce.ptr, min(this->my_nonce.len, this->other_nonce.len)) < 0) @@ -1195,10 +1202,14 @@ static chunk_t get_lower_nonce(private_child_create_t *this) } } -/** - * Implementation of task_t.migrate - */ -static void migrate(private_child_create_t *this, ike_sa_t *ike_sa) +METHOD(task_t, get_type, task_type_t, + private_child_create_t *this) +{ + return CHILD_CREATE; +} + +METHOD(task_t, migrate, void, + private_child_create_t *this, ike_sa_t *ike_sa) { chunk_free(&this->my_nonce); chunk_free(&this->other_nonce); @@ -1234,10 +1245,8 @@ static void migrate(private_child_create_t *this, ike_sa_t *ike_sa) this->established = FALSE; } -/** - * Implementation of task_t.destroy - */ -static void destroy(private_child_create_t *this) +METHOD(task_t, destroy, void, + private_child_create_t *this) { chunk_free(&this->my_nonce); chunk_free(&this->other_nonce); @@ -1273,52 +1282,45 @@ child_create_t *child_create_create(ike_sa_t *ike_sa, child_cfg_t *config, bool rekey, traffic_selector_t *tsi, traffic_selector_t *tsr) { - private_child_create_t *this = malloc_thing(private_child_create_t); - - this->public.get_child = (child_sa_t*(*)(child_create_t*))get_child; - this->public.get_lower_nonce = (chunk_t(*)(child_create_t*))get_lower_nonce; - this->public.use_reqid = (void(*)(child_create_t*,u_int32_t))use_reqid; - this->public.task.get_type = (task_type_t(*)(task_t*))get_type; - this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate; - this->public.task.destroy = (void(*)(task_t*))destroy; + private_child_create_t *this; + + INIT(this, + .public = { + .get_child = _get_child, + .get_lower_nonce = _get_lower_nonce, + .use_reqid = _use_reqid, + .task = { + .get_type = _get_type, + .migrate = _migrate, + .destroy = _destroy, + }, + }, + .ike_sa = ike_sa, + .config = config, + .packet_tsi = tsi ? tsi->clone(tsi) : NULL, + .packet_tsr = tsr ? tsr->clone(tsr) : NULL, + .dh_group = MODP_NONE, + .keymat = ike_sa->get_keymat(ike_sa), + .mode = MODE_TUNNEL, + .tfcv3 = TRUE, + .ipcomp = IPCOMP_NONE, + .ipcomp_received = IPCOMP_NONE, + .rekey = rekey, + ); + if (config) { - this->public.task.build = (status_t(*)(task_t*,message_t*))build_i; - this->public.task.process = (status_t(*)(task_t*,message_t*))process_i; + this->public.task.build = _build_i; + this->public.task.process = _process_i; this->initiator = TRUE; config->get_ref(config); } else { - this->public.task.build = (status_t(*)(task_t*,message_t*))build_r; - this->public.task.process = (status_t(*)(task_t*,message_t*))process_r; + this->public.task.build = _build_r; + this->public.task.process = _process_r; this->initiator = FALSE; } - this->ike_sa = ike_sa; - this->config = config; - this->my_nonce = chunk_empty; - this->other_nonce = chunk_empty; - this->proposals = NULL; - this->proposal = NULL; - this->tsi = NULL; - this->tsr = NULL; - this->packet_tsi = tsi ? tsi->clone(tsi) : NULL; - this->packet_tsr = tsr ? tsr->clone(tsr) : NULL; - this->dh = NULL; - this->dh_group = MODP_NONE; - this->keymat = ike_sa->get_keymat(ike_sa); - this->child_sa = NULL; - this->mode = MODE_TUNNEL; - this->ipcomp = IPCOMP_NONE; - this->ipcomp_received = IPCOMP_NONE; - this->my_spi = 0; - this->other_spi = 0; - this->my_cpi = 0; - this->other_cpi = 0; - this->reqid = 0; - this->established = FALSE; - this->rekey = rekey; - return &this->public; } diff --git a/src/libcharon/sa/tasks/child_rekey.c b/src/libcharon/sa/tasks/child_rekey.c index fdaaea4b8..e74ca4eef 100644 --- a/src/libcharon/sa/tasks/child_rekey.c +++ b/src/libcharon/sa/tasks/child_rekey.c @@ -241,12 +241,11 @@ static child_sa_t *handle_collision(private_child_rekey_t *this) /* if we have the lower nonce, delete rekeyed SA. If not, delete * the redundant. */ if (memcmp(this_nonce.ptr, other_nonce.ptr, - min(this_nonce.len, other_nonce.len)) < 0) + min(this_nonce.len, other_nonce.len)) > 0) { child_sa_t *child_sa; - DBG1(DBG_IKE, "CHILD_SA rekey collision won, " - "deleting rekeyed child"); + DBG1(DBG_IKE, "CHILD_SA rekey collision won, deleting old child"); to_delete = this->child_sa; /* don't touch child other created, it has already been deleted */ if (!this->other_child_destroyed) @@ -259,7 +258,7 @@ static child_sa_t *handle_collision(private_child_rekey_t *this) else { DBG1(DBG_IKE, "CHILD_SA rekey collision lost, " - "deleting redundant child"); + "deleting rekeyed child"); to_delete = this->child_create->get_child(this->child_create); } } diff --git a/src/libcharon/sa/tasks/ike_auth.c b/src/libcharon/sa/tasks/ike_auth.c index b440ec811..0756c7d60 100644 --- a/src/libcharon/sa/tasks/ike_auth.c +++ b/src/libcharon/sa/tasks/ike_auth.c @@ -68,6 +68,11 @@ struct private_ike_auth_t { packet_t *other_packet; /** + * Reserved bytes of ID payload + */ + char reserved[3]; + + /** * currently active authenticator, to authenticate us */ authenticator_t *my_auth; @@ -101,6 +106,11 @@ struct private_ike_auth_t { * should we send a AUTHENTICATION_FAILED notify? */ bool authentication_failed; + + /** + * received an INITIAL_CONTACT? + */ + bool initial_contact; }; /** @@ -160,6 +170,24 @@ static status_t collect_other_init_data(private_ike_auth_t *this, } /** + * Get and store reserved bytes of id_payload, required for AUTH payload + */ +static void get_reserved_id_bytes(private_ike_auth_t *this, id_payload_t *id) +{ + u_int8_t *byte; + int i; + + for (i = 0; i < countof(this->reserved); i++) + { + byte = payload_get_field(&id->payload_interface, RESERVED_BYTE, i); + if (byte) + { + this->reserved[i] = *byte; + } + } +} + +/** * Get the next authentication configuration */ static auth_cfg_t *get_auth_cfg(private_ike_auth_t *this, bool local) @@ -329,10 +357,8 @@ static bool update_cfg_candidates(private_ike_auth_t *this, bool strict) return this->peer_cfg != NULL; } -/** - * Implementation of task_t.build for initiator - */ -static status_t build_i(private_ike_auth_t *this, message_t *message) +METHOD(task_t, build_i, status_t, + private_ike_auth_t *this, message_t *message) { auth_cfg_t *cfg; @@ -367,7 +393,7 @@ static status_t build_i(private_ike_auth_t *this, message_t *message) /* check if an authenticator is in progress */ if (this->my_auth == NULL) { - identification_t *id; + identification_t *idi, *idr = NULL; id_payload_t *id_payload; /* clean up authentication config from a previous round */ @@ -378,33 +404,48 @@ static status_t build_i(private_ike_auth_t *this, message_t *message) cfg = get_auth_cfg(this, FALSE); if (cfg) { - id = cfg->get(cfg, AUTH_RULE_IDENTITY); - if (id && !id->contains_wildcards(id)) + idr = cfg->get(cfg, AUTH_RULE_IDENTITY); + if (idr && !idr->contains_wildcards(idr)) { - this->ike_sa->set_other_id(this->ike_sa, id->clone(id)); + this->ike_sa->set_other_id(this->ike_sa, idr->clone(idr)); id_payload = id_payload_create_from_identification( - ID_RESPONDER, id); + ID_RESPONDER, idr); message->add_payload(message, (payload_t*)id_payload); } } /* add IDi */ cfg = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE); cfg->merge(cfg, get_auth_cfg(this, TRUE), TRUE); - id = cfg->get(cfg, AUTH_RULE_IDENTITY); - if (!id) + idi = cfg->get(cfg, AUTH_RULE_IDENTITY); + if (!idi) { DBG1(DBG_CFG, "configuration misses IDi"); return FAILED; } - this->ike_sa->set_my_id(this->ike_sa, id->clone(id)); - id_payload = id_payload_create_from_identification(ID_INITIATOR, id); + this->ike_sa->set_my_id(this->ike_sa, idi->clone(idi)); + id_payload = id_payload_create_from_identification(ID_INITIATOR, idi); + get_reserved_id_bytes(this, id_payload); message->add_payload(message, (payload_t*)id_payload); + if (idr && message->get_message_id(message) == 1 && + this->peer_cfg->get_unique_policy(this->peer_cfg) != UNIQUE_NO) + { + host_t *host; + + host = this->ike_sa->get_other_host(this->ike_sa); + if (!charon->ike_sa_manager->has_contact(charon->ike_sa_manager, + idi, idr, host->get_family(host))) + { + message->add_notify(message, FALSE, INITIAL_CONTACT, chunk_empty); + } + } + /* build authentication data */ this->my_auth = authenticator_create_builder(this->ike_sa, cfg, this->other_nonce, this->my_nonce, this->other_packet->get_data(this->other_packet), - this->my_packet->get_data(this->my_packet)); + this->my_packet->get_data(this->my_packet), + this->reserved); if (!this->my_auth) { return FAILED; @@ -441,10 +482,8 @@ static status_t build_i(private_ike_auth_t *this, message_t *message) return NEED_MORE; } -/** - * Implementation of task_t.process for responder - */ -static status_t process_r(private_ike_auth_t *this, message_t *message) +METHOD(task_t, process_r, status_t, + private_ike_auth_t *this, message_t *message) { auth_cfg_t *cfg, *cand; id_payload_t *id_payload; @@ -498,6 +537,7 @@ static status_t process_r(private_ike_auth_t *this, message_t *message) return FAILED; } id = id_payload->get_identification(id_payload); + get_reserved_id_bytes(this, id_payload); this->ike_sa->set_other_id(this->ike_sa, id); cfg = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE); cfg->add(cfg, AUTH_RULE_IDENTITY, id->clone(id)); @@ -548,7 +588,8 @@ static status_t process_r(private_ike_auth_t *this, message_t *message) this->other_auth = authenticator_create_verifier(this->ike_sa, message, this->other_nonce, this->my_nonce, this->other_packet->get_data(this->other_packet), - this->my_packet->get_data(this->my_packet)); + this->my_packet->get_data(this->my_packet), + this->reserved); if (!this->other_auth) { this->authentication_failed = TRUE; @@ -572,10 +613,13 @@ static status_t process_r(private_ike_auth_t *this, message_t *message) return NEED_MORE; } - /* store authentication information */ - cfg = auth_cfg_create(); - cfg->merge(cfg, this->ike_sa->get_auth_cfg(this->ike_sa, FALSE), FALSE); - this->ike_sa->add_auth_cfg(this->ike_sa, FALSE, cfg); + /* If authenticated (with non-EAP) and received INITIAL_CONTACT, + * delete any existing IKE_SAs with that peer. */ + if (message->get_message_id(message) == 1 && + message->get_notify(message, INITIAL_CONTACT)) + { + this->initial_contact = TRUE; + } /* another auth round done, invoke authorize hook */ if (!charon->bus->authorize(charon->bus, FALSE)) @@ -585,6 +629,11 @@ static status_t process_r(private_ike_auth_t *this, message_t *message) return NEED_MORE; } + /* store authentication information */ + cfg = auth_cfg_create(); + cfg->merge(cfg, this->ike_sa->get_auth_cfg(this->ike_sa, FALSE), FALSE); + this->ike_sa->add_auth_cfg(this->ike_sa, FALSE, cfg); + if (!update_cfg_candidates(this, FALSE)) { this->authentication_failed = TRUE; @@ -603,10 +652,8 @@ static status_t process_r(private_ike_auth_t *this, message_t *message) return NEED_MORE; } -/** - * Implementation of task_t.build for responder - */ -static status_t build_r(private_ike_auth_t *this, message_t *message) +METHOD(task_t, build_r, status_t, + private_ike_auth_t *this, message_t *message) { auth_cfg_t *cfg; @@ -662,8 +709,16 @@ static status_t build_r(private_ike_auth_t *this, message_t *message) } id_payload = id_payload_create_from_identification(ID_RESPONDER, id); + get_reserved_id_bytes(this, id_payload); message->add_payload(message, (payload_t*)id_payload); + if (this->initial_contact) + { + charon->ike_sa_manager->check_uniqueness(charon->ike_sa_manager, + this->ike_sa, TRUE); + this->initial_contact = FALSE; + } + if ((uintptr_t)cfg->get(cfg, AUTH_RULE_AUTH_CLASS) == AUTH_CLASS_EAP) { /* EAP-only authentication */ if (!this->ike_sa->supports_extension(this->ike_sa, @@ -682,7 +737,8 @@ static status_t build_r(private_ike_auth_t *this, message_t *message) this->my_auth = authenticator_create_builder(this->ike_sa, cfg, this->other_nonce, this->my_nonce, this->other_packet->get_data(this->other_packet), - this->my_packet->get_data(this->my_packet)); + this->my_packet->get_data(this->my_packet), + this->reserved); if (!this->my_auth) { message->add_notify(message, TRUE, AUTHENTICATION_FAILED, @@ -744,7 +800,7 @@ static status_t build_r(private_ike_auth_t *this, message_t *message) if (!this->do_another_auth && !this->expect_another_auth) { if (charon->ike_sa_manager->check_uniqueness(charon->ike_sa_manager, - this->ike_sa)) + this->ike_sa, FALSE)) { DBG1(DBG_IKE, "cancelling IKE_SA setup due uniqueness policy"); message->add_notify(message, TRUE, AUTHENTICATION_FAILED, @@ -772,10 +828,8 @@ static status_t build_r(private_ike_auth_t *this, message_t *message) return NEED_MORE; } -/** - * Implementation of task_t.process for initiator - */ -static status_t process_i(private_ike_auth_t *this, message_t *message) +METHOD(task_t, process_i, status_t, + private_ike_auth_t *this, message_t *message) { enumerator_t *enumerator; payload_t *payload; @@ -857,6 +911,7 @@ static status_t process_i(private_ike_auth_t *this, message_t *message) return FAILED; } id = id_payload->get_identification(id_payload); + get_reserved_id_bytes(this, id_payload); this->ike_sa->set_other_id(this->ike_sa, id); cfg = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE); cfg->add(cfg, AUTH_RULE_IDENTITY, id->clone(id)); @@ -867,7 +922,8 @@ static status_t process_i(private_ike_auth_t *this, message_t *message) this->other_auth = authenticator_create_verifier(this->ike_sa, message, this->other_nonce, this->my_nonce, this->other_packet->get_data(this->other_packet), - this->my_packet->get_data(this->my_packet)); + this->my_packet->get_data(this->my_packet), + this->reserved); if (!this->other_auth) { return FAILED; @@ -893,17 +949,17 @@ static status_t process_i(private_ike_auth_t *this, message_t *message) this->other_auth->destroy(this->other_auth); this->other_auth = NULL; } - /* store authentication information, reset authenticator */ - cfg = auth_cfg_create(); - cfg->merge(cfg, this->ike_sa->get_auth_cfg(this->ike_sa, FALSE), FALSE); - this->ike_sa->add_auth_cfg(this->ike_sa, FALSE, cfg); - /* another auth round done, invoke authorize hook */ if (!charon->bus->authorize(charon->bus, FALSE)) { DBG1(DBG_IKE, "authorization forbids IKE_SA, cancelling"); return FAILED; } + + /* store authentication information, reset authenticator */ + cfg = auth_cfg_create(); + cfg->merge(cfg, this->ike_sa->get_auth_cfg(this->ike_sa, FALSE), FALSE); + this->ike_sa->add_auth_cfg(this->ike_sa, FALSE, cfg); } if (this->my_auth) @@ -964,18 +1020,14 @@ static status_t process_i(private_ike_auth_t *this, message_t *message) return NEED_MORE; } -/** - * Implementation of task_t.get_type - */ -static task_type_t get_type(private_ike_auth_t *this) +METHOD(task_t, get_type, task_type_t, + private_ike_auth_t *this) { return IKE_AUTHENTICATE; } -/** - * Implementation of task_t.migrate - */ -static void migrate(private_ike_auth_t *this, ike_sa_t *ike_sa) +METHOD(task_t, migrate, void, + private_ike_auth_t *this, ike_sa_t *ike_sa) { chunk_free(&this->my_nonce); chunk_free(&this->other_nonce); @@ -998,10 +1050,8 @@ static void migrate(private_ike_auth_t *this, ike_sa_t *ike_sa) this->candidates = linked_list_create(); } -/** - * Implementation of task_t.destroy - */ -static void destroy(private_ike_auth_t *this) +METHOD(task_t, destroy, void, + private_ike_auth_t *this) { chunk_free(&this->my_nonce); chunk_free(&this->other_nonce); @@ -1019,37 +1069,29 @@ static void destroy(private_ike_auth_t *this) */ ike_auth_t *ike_auth_create(ike_sa_t *ike_sa, bool initiator) { - private_ike_auth_t *this = malloc_thing(private_ike_auth_t); - - this->public.task.get_type = (task_type_t(*)(task_t*))get_type; - this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate; - this->public.task.destroy = (void(*)(task_t*))destroy; - + private_ike_auth_t *this; + + INIT(this, + .public = { + .task = { + .get_type = _get_type, + .migrate = _migrate, + .build = _build_r, + .process = _process_r, + .destroy = _destroy, + }, + }, + .ike_sa = ike_sa, + .initiator = initiator, + .candidates = linked_list_create(), + .do_another_auth = TRUE, + .expect_another_auth = TRUE, + ); if (initiator) { - this->public.task.build = (status_t(*)(task_t*,message_t*))build_i; - this->public.task.process = (status_t(*)(task_t*,message_t*))process_i; - } - else - { - this->public.task.build = (status_t(*)(task_t*,message_t*))build_r; - this->public.task.process = (status_t(*)(task_t*,message_t*))process_r; + this->public.task.build = _build_i; + this->public.task.process = _process_i; } - - this->ike_sa = ike_sa; - this->initiator = initiator; - this->my_nonce = chunk_empty; - this->other_nonce = chunk_empty; - this->my_packet = NULL; - this->other_packet = NULL; - this->peer_cfg = NULL; - this->candidates = linked_list_create(); - this->my_auth = NULL; - this->other_auth = NULL; - this->do_another_auth = TRUE; - this->expect_another_auth = TRUE; - this->authentication_failed = FALSE; - return &this->public; } diff --git a/src/libcharon/sa/tasks/ike_cert_pre.c b/src/libcharon/sa/tasks/ike_cert_pre.c index 1c0c54727..a59b8dcce 100644 --- a/src/libcharon/sa/tasks/ike_cert_pre.c +++ b/src/libcharon/sa/tasks/ike_cert_pre.c @@ -76,6 +76,7 @@ static void process_certreqs(private_ike_cert_pre_t *this, message_t *message) { certreq_payload_t *certreq = (certreq_payload_t*)payload; enumerator_t *enumerator; + u_int unknown = 0; chunk_t keyid; this->ike_sa->set_condition(this->ike_sa, COND_CERTREQ_SEEN, TRUE); @@ -103,12 +104,18 @@ static void process_certreqs(private_ike_cert_pre_t *this, message_t *message) } else { - DBG1(DBG_IKE, "received cert request for unknown ca " + DBG2(DBG_IKE, "received cert request for unknown ca " "with keyid %Y", id); + unknown++; } id->destroy(id); } enumerator->destroy(enumerator); + if (unknown) + { + DBG1(DBG_IKE, "received %u cert requests for an unknown ca", + unknown); + } break; } case NOTIFY: @@ -253,11 +260,19 @@ static void process_certs(private_ike_cert_pre_t *this, message_t *message) } break; } + case ENC_CRL: + cert = cert_payload->get_cert(cert_payload); + if (cert) + { + DBG1(DBG_IKE, "received CRL \"%Y\"", + cert->get_subject(cert)); + auth->add(auth, AUTH_HELPER_REVOCATION_CERT, cert); + } + break; case ENC_PKCS7_WRAPPED_X509: case ENC_PGP: case ENC_DNS_SIGNED_KEY: case ENC_KERBEROS_TOKEN: - case ENC_CRL: case ENC_ARL: case ENC_SPKI: case ENC_X509_ATTRIBUTE: diff --git a/src/libcharon/sa/tasks/ike_rekey.c b/src/libcharon/sa/tasks/ike_rekey.c index 1a6c140c4..44c55036e 100644 --- a/src/libcharon/sa/tasks/ike_rekey.c +++ b/src/libcharon/sa/tasks/ike_rekey.c @@ -255,19 +255,20 @@ static status_t process_i(private_ike_rekey_t *this, message_t *message) /* if we have the lower nonce, delete rekeyed SA. If not, delete * the redundant. */ if (memcmp(this_nonce.ptr, other_nonce.ptr, - min(this_nonce.len, other_nonce.len)) < 0) + min(this_nonce.len, other_nonce.len)) > 0) { /* peer should delete this SA. Add a timeout just in case. */ job_t *job = (job_t*)delete_ike_sa_job_create( other->new_sa->get_id(other->new_sa), TRUE); lib->scheduler->schedule_job(lib->scheduler, job, 10); - DBG1(DBG_IKE, "IKE_SA rekey collision won, deleting rekeyed IKE_SA"); + DBG1(DBG_IKE, "IKE_SA rekey collision won, waiting for delete"); charon->ike_sa_manager->checkin(charon->ike_sa_manager, other->new_sa); other->new_sa = NULL; } else { - DBG1(DBG_IKE, "IKE_SA rekey collision lost, deleting redundant IKE_SA"); + DBG1(DBG_IKE, "IKE_SA rekey collision lost, " + "deleting redundant IKE_SA"); /* apply host for a proper delete */ host = this->ike_sa->get_my_host(this->ike_sa); this->new_sa->set_my_host(this->new_sa, host->clone(host)); diff --git a/src/libcharon/tnc/imc/imc.h b/src/libcharon/tnc/imc/imc.h new file mode 100644 index 000000000..fe8f25b0f --- /dev/null +++ b/src/libcharon/tnc/imc/imc.h @@ -0,0 +1,175 @@ +/* + * Copyright (C) 2010 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. + */ + +/** + * @defgroup imc imc + * @ingroup tnc + * + * @defgroup imct imc + * @{ @ingroup imc + */ + +#ifndef IMC_H_ +#define IMC_H_ + +#include <tnc/tncifimc.h> +#include <library.h> + +typedef struct imc_t imc_t; + +/** + * Controls a single Integrity Measurement Collector (IMC) + */ +struct imc_t { + + /** + * The TNC Client calls this function to initialize the IMC and agree on + * the API version number to be used. It also supplies the IMC ID, an IMC + * identifier that the IMC must use when calling TNC Client callback functions. + * + * @param imcID IMC ID assigned by TNCC + * @param minVersion minimum API version supported by TNCC + * @param maxVersion maximum API version supported by TNCC + * @param OutActualVersion mutually supported API version number + * @return TNC result code + */ + TNC_Result (*initialize)(TNC_IMCID imcID, + TNC_Version minVersion, + TNC_Version maxVersion, + TNC_Version *OutActualVersion); + + /** + * The TNC Client calls this function to inform the IMC that the state of + * the network connection identified by connectionID has changed to newState. + * + * @param imcID IMC ID assigned by TNCC + * @param connectionID network connection ID assigned by TNCC + * @param newState new network connection state + * @return TNC result code + */ + TNC_Result (*notify_connection_change)(TNC_IMCID imcID, + TNC_ConnectionID connectionID, + TNC_ConnectionState newState); + + /** + * The TNC Client calls this function to indicate that an Integrity Check + * Handshake is beginning and solicit messages from IMCs for the first batch. + * + * @param imcID IMC ID assigned by TNCC + * @param connectionID network connection ID assigned by TNCC + * @return TNC result code + */ + TNC_Result (*begin_handshake)(TNC_IMCID imcID, + TNC_ConnectionID connectionID); + + /** + * The TNC Client calls this function to deliver a message to the IMC. + * The message is contained in the buffer referenced by message and contains + * the number of octets indicated by messageLength. The type of the message + * is indicated by messageType. + * + * @param imcID IMC ID assigned by TNCS + * @param connectionID network connection ID assigned by TNCC + * @param message reference to buffer containing message + * @param messageLength number of octets in message + * @param messageType message type of message + * @return TNC result code + */ + TNC_Result (*receive_message)(TNC_IMCID imcID, + TNC_ConnectionID connectionID, + TNC_BufferReference message, + TNC_UInt32 messageLength, + TNC_MessageType messageType); + + /** + * The TNC Client calls this function to notify IMCs that all IMV messages + * received in a batch have been delivered and this is the IMC’s last chance + * to send a message in the batch of IMC messages currently being collected. + * + * @param imcID IMC ID assigned by TNCC + * @param connectionID network connection ID assigned by TNCC + * @return TNC result code + */ + TNC_Result (*batch_ending)(TNC_IMCID imcID, + TNC_ConnectionID connectionID); + + /** + * The TNC Client calls this function to close down the IMC when all work is + * complete or the IMC reports TNC_RESULT_FATAL. + * + * @param imcID IMC ID assigned by TNCC + * @return TNC result code + */ + TNC_Result (*terminate)(TNC_IMCID imcID); + + /** + * IMVs implementing the UNIX/Linux Dynamic Linkage platform binding MUST + * define this additional function. The TNC Server MUST call the function + * immediately after calling TNC_IMV_Initialize to provide a pointer to the + * TNCS bind function. The IMV can then use the TNCS bind function to obtain + * pointers to any other TNCS functions. + * + * @param imcID IMC ID assigned by TNCC + * @param bindFunction pointer to TNC_TNCC_BindFunction + * @return TNC result code + */ + TNC_Result (*provide_bind_function)(TNC_IMCID imcID, + TNC_TNCC_BindFunctionPointer bindFunction); + + /** + * Sets the ID of an imc_t object. + * + * @param id IMC ID to be assigned + */ + void (*set_id)(imc_t *this, TNC_IMCID id); + + /** + * Returns the ID of an imc_t object. + * + * @return assigned IMC ID + */ + TNC_IMCID (*get_id)(imc_t *this); + + /** + * Returns the name of an imc_t object. + * + * @return name of IMC + */ + char* (*get_name)(imc_t *this); + + /** + * Sets the supported message types of an imc_t object. + * + * @param supported_types list of messages type supported by IMC + * @param type_count number of supported message types + */ + void (*set_message_types)(imc_t *this, TNC_MessageTypeList supported_types, + TNC_UInt32 type_count); + + /** + * Check if the IMC supports a given message type. + * + * @param message_type message type + * @return TRUE if supported + */ + bool (*type_supported)(imc_t *this, TNC_MessageType message_type); + + /** + * Destroys an imc_t object. + */ + void (*destroy)(imc_t *this); +}; + +#endif /** IMC_H_ @}*/ diff --git a/src/libcharon/tnc/imc/imc_manager.h b/src/libcharon/tnc/imc/imc_manager.h new file mode 100644 index 000000000..634afdbe8 --- /dev/null +++ b/src/libcharon/tnc/imc/imc_manager.h @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2010 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. + */ + +/** + * @defgroup imc_manager imc_manager + * @{ @ingroup imc + */ + +#ifndef IMC_MANAGER_H_ +#define IMC_MANAGER_H_ + +#include "imc.h" + +#include <library.h> + +typedef struct imc_manager_t imc_manager_t; + +/** + * The IMC manager controls all IMC instances. + */ +struct imc_manager_t { + + /** + * Add an IMC instance + * + * @param imc IMC instance + * @return TRUE if initialization successful + */ + bool (*add)(imc_manager_t *this, imc_t *imc); + + /** + * Remove an IMC instance from the list and return it + * + * @param id ID of IMC instance + * @return removed IMC instance + */ + imc_t* (*remove)(imc_manager_t *this, TNC_IMCID id); + + /** + * Return the preferred language for recommendations + * + * @return preferred language string + */ + char* (*get_preferred_language)(imc_manager_t *this); + + /** + * Notify all IMC instances + * + * @param state communicate the state a connection has reached + */ + void (*notify_connection_change)(imc_manager_t *this, + TNC_ConnectionID id, + TNC_ConnectionState state); + + /** + * Begin a handshake between the IMCs and a connection + * + * @param id connection ID + */ + void (*begin_handshake)(imc_manager_t *this, TNC_ConnectionID id); + + /** + * Sets the supported message types reported by a given IMC + * + * @param id ID of reporting IMC + * @param supported_types list of messages type supported by IMC + * @param type_count number of supported message types + * @return TNC result code + */ + TNC_Result (*set_message_types)(imc_manager_t *this, + TNC_IMCID id, + TNC_MessageTypeList supported_types, + TNC_UInt32 type_count); + + /** + * Delivers a message to interested IMCs. + * + * @param connection_id ID of connection over which message was received + * @param message message + * @param message_len message length + * @param message_type message type + */ + void (*receive_message)(imc_manager_t *this, + TNC_ConnectionID connection_id, + TNC_BufferReference message, + TNC_UInt32 message_len, + TNC_MessageType message_type); + + /** + * Notify all IMCs that all IMV messages received in a batch have been + * delivered and this is the IMCs last chance to send a message in the + * batch of IMC messages currently being collected. + * + * @param id connection ID + */ + void (*batch_ending)(imc_manager_t *this, TNC_ConnectionID id); + + /** + * Destroy an IMC manager and all its controlled instances. + */ + void (*destroy)(imc_manager_t *this); +}; + +#endif /** IMC_MANAGER_H_ @}*/ diff --git a/src/libcharon/tnc/imv/imv.h b/src/libcharon/tnc/imv/imv.h new file mode 100644 index 000000000..26874ab0b --- /dev/null +++ b/src/libcharon/tnc/imv/imv.h @@ -0,0 +1,175 @@ +/* + * Copyright (C) 2010 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. + */ + +/** + * @defgroup imv imv + * @ingroup tnc + * + * @defgroup imvt imv + * @{ @ingroup imv + */ + +#ifndef IMV_H_ +#define IMV_H_ + +#include <tnc/tncifimv.h> +#include <library.h> + +typedef struct imv_t imv_t; + +/** + * Controls a single Integrity Measurement Verifier (IMV) + */ +struct imv_t { + + /** + * The TNC Server calls this function to initialize the IMV and agree on + * the API version number to be used. It also supplies the IMV ID, an IMV + * identifier that the IMV must use when calling TNC Server callback functions. + * + * @param imvID IMV ID assigned by TNCS + * @param minVersion minimum API version supported + * @param maxVersion maximum API version supported by TNCS + * @param OutActualVersion mutually supported API version number + * @return TNC result code + */ + TNC_Result (*initialize)(TNC_IMVID imvID, + TNC_Version minVersion, + TNC_Version maxVersion, + TNC_Version *OutActualVersion); + + /** + * The TNC Server calls this function to inform the IMV that the state of + * the network connection identified by connectionID has changed to newState. + * + * @param imvID IMV ID assigned by TNCS + * @param connectionID network connection ID assigned by TNCS + * @param newState new network connection state + * @return TNC result code + */ + TNC_Result (*notify_connection_change)(TNC_IMVID imvID, + TNC_ConnectionID connectionID, + TNC_ConnectionState newState); + + /** + * The TNC Server calls this function at the end of an Integrity Check + * Handshake (after all IMC-IMV messages have been delivered) to solicit + * recommendations from IMVs that have not yet provided a recommendation. + * + * @param imvID IMV ID assigned by TNCS + * @param connectionID network connection ID assigned by TNCS + * @return TNC result code + */ + TNC_Result (*solicit_recommendation)(TNC_IMVID imvID, + TNC_ConnectionID connectionID); + + /** + * The TNC Server calls this function to deliver a message to the IMV. + * The message is contained in the buffer referenced by message and contains + * the number of octets indicated by messageLength. The type of the message + * is indicated by messageType. + * + * @param imvID IMV ID assigned by TNCS + * @param connectionID network connection ID assigned by TNCS + * @param message reference to buffer containing message + * @param messageLength number of octets in message + * @param messageType message type of message + * @return TNC result code + */ + TNC_Result (*receive_message)(TNC_IMVID imvID, + TNC_ConnectionID connectionID, + TNC_BufferReference message, + TNC_UInt32 messageLength, + TNC_MessageType messageType); + + /** + * The TNC Server calls this function to notify IMVs that all IMC messages + * received in a batch have been delivered and this is the IMV’s last chance + * to send a message in the batch of IMV messages currently being collected. + * + * @param imvID IMV ID assigned by TNCS + * @param connectionID network connection ID assigned by TNCS + * @return TNC result code + */ + TNC_Result (*batch_ending)(TNC_IMVID imvID, + TNC_ConnectionID connectionID); + + /** + * The TNC Server calls this function to close down the IMV. + * + * @param imvID IMV ID assigned by TNCS + * @return TNC result code + */ + TNC_Result (*terminate)(TNC_IMVID imvID); + + /** + * IMVs implementing the UNIX/Linux Dynamic Linkage platform binding MUST + * define this additional function. The TNC Server MUST call the function + * immediately after calling TNC_IMV_Initialize to provide a pointer to the + * TNCS bind function. The IMV can then use the TNCS bind function to obtain + * pointers to any other TNCS functions. + * + * @param imvID IMV ID assigned by TNCS + * @param bindFunction pointer to TNC_TNCS_BindFunction + * @return TNC result code + */ + TNC_Result (*provide_bind_function)(TNC_IMVID imvID, + TNC_TNCS_BindFunctionPointer bindFunction); + + /** + * Sets the ID of an imv_t object. + * + * @param id IMV ID to be assigned + */ + void (*set_id)(imv_t *this, TNC_IMVID id); + + /** + * Returns the ID of an imv_t object. + * + * @return IMV ID assigned by TNCS + */ + TNC_IMVID (*get_id)(imv_t *this); + + /** + * Returns the name of an imv_t object. + * + * @return name of IMV + */ + char* (*get_name)(imv_t *this); + + /** + * Sets the supported message types of an imv_t object. + * + * @param supported_types list of messages type supported by IMV + * @param type_count number of supported message types + */ + void (*set_message_types)(imv_t *this, TNC_MessageTypeList supported_types, + TNC_UInt32 type_count); + + /** + * Check if the IMV supports a given message type. + * + * @param message_type message type + * @return TRUE if supported + */ + bool (*type_supported)(imv_t *this, TNC_MessageType message_type); + + /** + * Destroys an imv_t object. + */ + void (*destroy)(imv_t *this); +}; + +#endif /** IMV_H_ @}*/ diff --git a/src/libcharon/tnc/imv/imv_manager.h b/src/libcharon/tnc/imv/imv_manager.h new file mode 100644 index 000000000..b5c581a75 --- /dev/null +++ b/src/libcharon/tnc/imv/imv_manager.h @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2010 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. + */ + +/** + * @defgroup imv_manager imv_manager + * @{ @ingroup imv + */ + +#ifndef IMV_MANAGER_H_ +#define IMV_MANAGER_H_ + +#include "imv.h" +#include "imv_recommendations.h" + +#include <library.h> + +typedef struct imv_manager_t imv_manager_t; + +/** + * The IMV manager controls all IMV instances. + */ +struct imv_manager_t { + + /** + * Add an IMV instance + * + * @param imv IMV instance + * @return TRUE if initialization successful + */ + bool (*add)(imv_manager_t *this, imv_t *imv); + + /** + * Remove an IMV instance from the list and return it + * + * @param id ID of IMV instance + * @return removed IMC instance + */ + imv_t* (*remove)(imv_manager_t *this, TNC_IMVID id); + + /** + * Get the configured recommendation policy + * + * @return configured recommendation policy + */ + recommendation_policy_t (*get_recommendation_policy)(imv_manager_t *this); + + /** + * Create an empty set of IMV recommendations and evaluations + * + * @return instance of a recommendations_t list + */ + recommendations_t* (*create_recommendations)(imv_manager_t *this); + + /** + * Enforce the TNC recommendation on the IKE_SA by either inserting an + * allow|isolate group membership rule (TRUE) or by blocking access (FALSE) + * + * @param void TNC action recommendation + * @return TRUE for allow|isolate, FALSE for none + */ + bool (*enforce_recommendation)(imv_manager_t *this, + TNC_IMV_Action_Recommendation rec); + + /** + * Notify all IMV instances + * + * @param state communicate the state a connection has reached + */ + void (*notify_connection_change)(imv_manager_t *this, + TNC_ConnectionID id, + TNC_ConnectionState state); + + /** + * Sets the supported message types reported by a given IMV + * + * @param id ID of reporting IMV + * @param supported_types list of messages type supported by IMV + * @param type_count number of supported message types + * @return TNC result code + */ + TNC_Result (*set_message_types)(imv_manager_t *this, + TNC_IMVID id, + TNC_MessageTypeList supported_types, + TNC_UInt32 type_count); + + /** + * Solicit recommendations from IMVs that have not yet provided one + * + * @param id connection ID + */ + void (*solicit_recommendation)(imv_manager_t *this, TNC_ConnectionID id); + + /** + * Delivers a message to interested IMVs. + * + * @param connection_id ID of connection over which message was received + * @param message message + * @param message_len message length + * @param message_type message type + */ + void (*receive_message)(imv_manager_t *this, + TNC_ConnectionID connection_id, + TNC_BufferReference message, + TNC_UInt32 message_len, + TNC_MessageType message_type); + + /** + * Notify all IMVs that all IMC messages received in a batch have been + * delivered and this is the IMVs last chance to send a message in the + * batch of IMV messages currently being collected. + * + * @param id connection ID + */ + void (*batch_ending)(imv_manager_t *this, TNC_ConnectionID id); + + /** + * Destroy an IMV manager and all its controlled instances. + */ + void (*destroy)(imv_manager_t *this); +}; + +#endif /** IMV_MANAGER_H_ @}*/ diff --git a/src/libstrongswan/credentials/certificates/x509.c b/src/libcharon/tnc/imv/imv_recommendations.c index 66dc192c1..9daaca16c 100644 --- a/src/libstrongswan/credentials/certificates/x509.c +++ b/src/libcharon/tnc/imv/imv_recommendations.c @@ -1,6 +1,6 @@ /* - * Copyright (C) 2008 Martin Willi - * Hochschule fuer Technik Rapperswil + * Copyright (C) 2010 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 @@ -13,16 +13,12 @@ * for more details. */ -#include "x509.h" +#include "imv_recommendations.h" -ENUM(x509_flag_names, X509_NONE, X509_IP_ADDR_BLOCKS, - "X509_NONE", - "X509_CA", - "X509_AA", - "X509_OCSP_SIGNER", - "X509_SERVER_AUTH", - "X509_CLIENT_AUTH", - "X509_SELF_SIGNED", - "X509_IP_ADDR_BLOCKS", +ENUM(recommendation_policy_names, RECOMMENDATION_POLICY_DEFAULT, + RECOMMENDATION_POLICY_ALL, + "default", + "any", + "all" ); diff --git a/src/libcharon/tnc/imv/imv_recommendations.h b/src/libcharon/tnc/imv/imv_recommendations.h new file mode 100644 index 000000000..3a6e25c9f --- /dev/null +++ b/src/libcharon/tnc/imv/imv_recommendations.h @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2010 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. + */ + +/** + * @defgroup imv_recommendations imv_recommendations + * @{ @ingroup imv + */ + +#ifndef IMV_RECOMMENDATIONS_H_ +#define IMV_RECOMMENDATIONS_H_ + +#include <tnc/tncifimv.h> +#include <library.h> + +typedef enum recommendation_policy_t recommendation_policy_t; + +enum recommendation_policy_t { + RECOMMENDATION_POLICY_DEFAULT, + RECOMMENDATION_POLICY_ANY, + RECOMMENDATION_POLICY_ALL +}; + +extern enum_name_t *recommendation_policy_names; + + +typedef struct recommendations_t recommendations_t; + +/** + * Collection of all IMV action recommendations and evaluation results + */ +struct recommendations_t { + + /** + * Deliver an IMV action recommendation and IMV evaluation result to the TNCS + * + * @param imv_id ID of the IMV providing the recommendation + * @param rec action recommendation + * @param eval evaluation result + * @return return code + */ + TNC_Result (*provide_recommendation)(recommendations_t *this, + TNC_IMVID imv_id, + TNC_IMV_Action_Recommendation rec, + TNC_IMV_Evaluation_Result eval); + + /** + * If all IMVs provided a recommendation, derive a consolidated action + * recommendation and evaluation result based on a configured policy + * + * @param rec action recommendation + * @param eval evaluation result + * @return TRUE if all IMVs provided a recommendation + */ + bool (*have_recommendation)(recommendations_t *this, + TNC_IMV_Action_Recommendation *rec, + TNC_IMV_Evaluation_Result *eval); + + /** + * Get the preferred language for remediation messages + * + * @return preferred language + */ + chunk_t (*get_preferred_language)(recommendations_t *this); + + /** + * Set the preferred language for remediation messages + * + * @param pref_lang preferred language + */ + void (*set_preferred_language)(recommendations_t *this, chunk_t pref_lang); + + /** + * Set the reason string + * + * @param id ID of IMV setting the reason string + * @param reason reason string + * @result return code + */ + TNC_Result (*set_reason_string)(recommendations_t *this, TNC_IMVID id, + chunk_t reason); + + /** + * Set the language for reason strings + * + * @param id ID of IMV setting the reason language + * @param reason_lang reason language + * @result return code + */ + TNC_Result (*set_reason_language)(recommendations_t *this, TNC_IMVID id, + chunk_t reason_lang); + + /** + * Enumerates over all IMVs sending a reason string. + * Format: TNC_IMVID *id, chunk_t *reason, chunk_t *reason_language + * + * @return enumerator + */ + enumerator_t* (*create_reason_enumerator)(recommendations_t *this); + /** + * Destroys an imv_t object. + */ + void (*destroy)(recommendations_t *this); +}; + +#endif /** IMV_RECOMMENDATIONS_H_ @}*/ diff --git a/src/libcharon/tnccs/tnccs.c b/src/libcharon/tnc/tnccs/tnccs.c index 2facf02c8..575b850f5 100644 --- a/src/libcharon/tnccs/tnccs.c +++ b/src/libcharon/tnc/tnccs/tnccs.c @@ -15,7 +15,8 @@ #include "tnccs.h" -ENUM(eap_type_names, TNCCS_1_1, TNCCS_2_0, +ENUM(tnccs_type_names, TNCCS_UNKNOWN, TNCCS_2_0, + "unknown TNCCS", "TNCCS 1.1", "TNCCS SOH", "TNCCS 2.0", diff --git a/src/libcharon/tnccs/tnccs.h b/src/libcharon/tnc/tnccs/tnccs.h index 583512e82..c5d6f5ef0 100644 --- a/src/libcharon/tnccs/tnccs.h +++ b/src/libcharon/tnc/tnccs/tnccs.h @@ -15,23 +15,38 @@ /** * @defgroup tnccs tnccs - * @{ @ingroup libcharon + * @ingroup tnc + * + * @defgroup tnccst tnccs + * @{ @ingroup tnccs */ #ifndef TNCCS_H_ #define TNCCS_H_ -typedef enum tnccs_type_t tnccs_type_t; - +#include <tnc/tncif.h> +#include <tnc/tncifimc.h> +#include <tnc/tncifimv.h> #include <library.h> +#define IETF_VENDOR_ID 0x000000 /* 0 */ +#define MICROSOFT_VENDOR_ID 0x000137 /* 311 */ +#define OSC_VENDOR_ID 0x002358 /* 9048 */ +#define FHH_VENDOR_ID 0x0080ab /* 32939 */ +#define ITA_VENDOR_ID 0x00902a /* 36906 */ +#define RESERVED_VENDOR_ID 0xffffff /* 16777215 */ + +typedef enum tnccs_type_t tnccs_type_t; + /** * Type of TNC Client/Server protocol */ enum tnccs_type_t { + TNCCS_UNKNOWN, TNCCS_1_1, TNCCS_SOH, - TNCCS_2_0 + TNCCS_2_0, + TNCCS_DYNAMIC }; /** @@ -49,4 +64,19 @@ typedef struct tnccs_t tnccs_t; */ typedef tnccs_t* (*tnccs_constructor_t)(bool is_server); -#endif /** TNC_H_ @}*/ +/** + * Callback function adding a message to a TNCCS batch + * + * @param imc_id ID of IMC or TNC_IMCID_ANY + * @param imc_id ID of IMV or TNC_IMVID_ANY + * @param msg message to be added + * @param msg_len message length + * @param msg_type message type + */ +typedef void (*tnccs_send_message_t)(tnccs_t* tncss, TNC_IMCID imc_id, + TNC_IMVID imv_id, + TNC_BufferReference msg, + TNC_UInt32 msg_len, + TNC_MessageType msg_type); + +#endif /** TNCCS_H_ @}*/ diff --git a/src/libcharon/tnc/tnccs/tnccs_manager.c b/src/libcharon/tnc/tnccs/tnccs_manager.c new file mode 100644 index 000000000..7e522b870 --- /dev/null +++ b/src/libcharon/tnc/tnccs/tnccs_manager.c @@ -0,0 +1,477 @@ +/* + * Copyright (C) 2010 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 "tnccs_manager.h" + +#include <tnc/imv/imv_recommendations.h> + +#include <debug.h> +#include <daemon.h> +#include <utils/linked_list.h> +#include <threading/rwlock.h> + +typedef struct private_tnccs_manager_t private_tnccs_manager_t; +typedef struct tnccs_entry_t tnccs_entry_t; +typedef struct tnccs_connection_entry_t tnccs_connection_entry_t; + +/** + * TNCCS constructor entry + */ +struct tnccs_entry_t { + + /** + * TNCCS protocol type + */ + tnccs_type_t type; + + /** + * constructor function to create instance + */ + tnccs_constructor_t constructor; +}; + +/** + * TNCCS connection entry + */ +struct tnccs_connection_entry_t { + + /** + * TNCCS connection ID + */ + TNC_ConnectionID id; + + /** + * TNCCS instance + */ + tnccs_t *tnccs; + + /** + * TNCCS send message function + */ + tnccs_send_message_t send_message; + + /** + * TNCCS request handshake retry flag + */ + bool *request_handshake_retry; + + /** + * collection of IMV recommendations + */ + recommendations_t *recs; +}; + +/** + * private data of tnccs_manager + */ +struct private_tnccs_manager_t { + + /** + * public functions + */ + tnccs_manager_t public; + + /** + * list of TNCCS protocol entries + */ + linked_list_t *protocols; + + /** + * rwlock to lock the TNCCS protocol entries + */ + rwlock_t *protocol_lock; + + /** + * connection ID counter + */ + TNC_ConnectionID connection_id; + + /** + * list of TNCCS connection entries + */ + linked_list_t *connections; + + /** + * rwlock to lock TNCCS connection entries + */ + rwlock_t *connection_lock; + +}; + +METHOD(tnccs_manager_t, add_method, void, + private_tnccs_manager_t *this, tnccs_type_t type, + tnccs_constructor_t constructor) +{ + tnccs_entry_t *entry; + + entry = malloc_thing(tnccs_entry_t); + entry->type = type; + entry->constructor = constructor; + + this->protocol_lock->write_lock(this->protocol_lock); + this->protocols->insert_last(this->protocols, entry); + this->protocol_lock->unlock(this->protocol_lock); +} + +METHOD(tnccs_manager_t, remove_method, void, + private_tnccs_manager_t *this, tnccs_constructor_t constructor) +{ + enumerator_t *enumerator; + tnccs_entry_t *entry; + + this->protocol_lock->write_lock(this->protocol_lock); + enumerator = this->protocols->create_enumerator(this->protocols); + while (enumerator->enumerate(enumerator, &entry)) + { + if (constructor == entry->constructor) + { + this->protocols->remove_at(this->protocols, enumerator); + free(entry); + } + } + enumerator->destroy(enumerator); + this->protocol_lock->unlock(this->protocol_lock); +} + +METHOD(tnccs_manager_t, create_instance, tnccs_t*, + private_tnccs_manager_t *this, tnccs_type_t type, bool is_server) +{ + enumerator_t *enumerator; + tnccs_entry_t *entry; + tnccs_t *protocol = NULL; + + this->protocol_lock->read_lock(this->protocol_lock); + enumerator = this->protocols->create_enumerator(this->protocols); + while (enumerator->enumerate(enumerator, &entry)) + { + if (type == entry->type) + { + protocol = entry->constructor(is_server); + if (protocol) + { + break; + } + } + } + enumerator->destroy(enumerator); + this->protocol_lock->unlock(this->protocol_lock); + + return protocol; +} + +METHOD(tnccs_manager_t, create_connection, TNC_ConnectionID, + private_tnccs_manager_t *this, tnccs_t *tnccs, + tnccs_send_message_t send_message, bool* request_handshake_retry, + recommendations_t **recs) +{ + tnccs_connection_entry_t *entry; + + entry = malloc_thing(tnccs_connection_entry_t); + entry->tnccs = tnccs; + entry->send_message = send_message; + entry->request_handshake_retry = request_handshake_retry; + if (recs) + { + /* we assume a TNC Server needing recommendations from IMVs */ + if (!charon->imvs) + { + DBG1(DBG_TNC, "no IMV manager available!"); + free(entry); + return 0; + } + entry->recs = charon->imvs->create_recommendations(charon->imvs); + *recs = entry->recs; + } + else + { + /* we assume a TNC Client */ + if (!charon->imcs) + { + DBG1(DBG_TNC, "no IMC manager available!"); + free(entry); + return 0; + } + entry->recs = NULL; + } + this->connection_lock->write_lock(this->connection_lock); + entry->id = ++this->connection_id; + this->connections->insert_last(this->connections, entry); + this->connection_lock->unlock(this->connection_lock); + + DBG1(DBG_TNC, "assigned TNCCS Connection ID %u", entry->id); + return entry->id; +} + +METHOD(tnccs_manager_t, remove_connection, void, + private_tnccs_manager_t *this, TNC_ConnectionID id) +{ + enumerator_t *enumerator; + tnccs_connection_entry_t *entry; + + this->connection_lock->write_lock(this->connection_lock); + enumerator = this->connections->create_enumerator(this->connections); + while (enumerator->enumerate(enumerator, &entry)) + { + if (id == entry->id) + { + this->connections->remove_at(this->connections, enumerator); + if (entry->recs) + { + entry->recs->destroy(entry->recs); + } + free(entry); + DBG1(DBG_TNC, "removed TNCCS Connection ID %u", id); + } + } + enumerator->destroy(enumerator); + this->connection_lock->unlock(this->connection_lock); +} + +METHOD(tnccs_manager_t, request_handshake_retry, TNC_Result, + private_tnccs_manager_t *this, bool is_imc, TNC_UInt32 imcv_id, + TNC_ConnectionID id, + TNC_RetryReason reason) +{ + enumerator_t *enumerator; + tnccs_connection_entry_t *entry; + + if (id == TNC_CONNECTIONID_ANY) + { + DBG2(DBG_TNC, "%s %u requests handshake retry for all connections " + "(reason: %u)", is_imc ? "IMC":"IMV", reason); + } + else + { + DBG2(DBG_TNC, "%s %u requests handshake retry for connection ID %u " + "(reason: %u)", is_imc ? "IMC":"IMV", id, reason); + } + this->connection_lock->read_lock(this->connection_lock); + enumerator = this->connections->create_enumerator(this->connections); + while (enumerator->enumerate(enumerator, &entry)) + { + if (id == TNC_CONNECTIONID_ANY || id == entry->id) + { + *entry->request_handshake_retry = TRUE; + break; + } + } + enumerator->destroy(enumerator); + this->connection_lock->unlock(this->connection_lock); + + return TNC_RESULT_SUCCESS; +} + +METHOD(tnccs_manager_t, send_message, TNC_Result, + private_tnccs_manager_t *this, TNC_IMCID imc_id, TNC_IMVID imv_id, + TNC_ConnectionID id, + TNC_BufferReference msg, + TNC_UInt32 msg_len, + TNC_MessageType msg_type) +{ + enumerator_t *enumerator; + tnccs_connection_entry_t *entry; + tnccs_send_message_t send_message = NULL; + tnccs_t *tnccs = NULL; + + this->connection_lock->read_lock(this->connection_lock); + enumerator = this->connections->create_enumerator(this->connections); + while (enumerator->enumerate(enumerator, &entry)) + { + if (id == entry->id) + { + tnccs = entry->tnccs; + send_message = entry->send_message; + break; + } + } + enumerator->destroy(enumerator); + this->connection_lock->unlock(this->connection_lock); + + if (tnccs && send_message) + { + send_message(tnccs, imc_id, imv_id, msg, msg_len, msg_type); + return TNC_RESULT_SUCCESS; + } + return TNC_RESULT_FATAL; +} + +METHOD(tnccs_manager_t, provide_recommendation, TNC_Result, + private_tnccs_manager_t *this, TNC_IMVID imv_id, + TNC_ConnectionID id, + TNC_IMV_Action_Recommendation rec, + TNC_IMV_Evaluation_Result eval) +{ + enumerator_t *enumerator; + tnccs_connection_entry_t *entry; + recommendations_t *recs = NULL; + + this->connection_lock->read_lock(this->connection_lock); + enumerator = this->connections->create_enumerator(this->connections); + while (enumerator->enumerate(enumerator, &entry)) + { + if (id == entry->id) + { + recs = entry->recs; + break; + } + } + enumerator->destroy(enumerator); + this->connection_lock->unlock(this->connection_lock); + + if (recs) + { + recs->provide_recommendation(recs, imv_id, rec, eval); + return TNC_RESULT_SUCCESS; + } + return TNC_RESULT_FATAL; +} + +METHOD(tnccs_manager_t, get_attribute, TNC_Result, + private_tnccs_manager_t *this, TNC_IMVID imv_id, + TNC_ConnectionID id, + TNC_AttributeID attribute_id, + TNC_UInt32 buffer_len, + TNC_BufferReference buffer, + TNC_UInt32 *out_value_len) +{ + enumerator_t *enumerator; + tnccs_connection_entry_t *entry; + recommendations_t *recs = NULL; + + if (id == TNC_CONNECTIONID_ANY || + attribute_id != TNC_ATTRIBUTEID_PREFERRED_LANGUAGE) + { + return TNC_RESULT_INVALID_PARAMETER; + } + + this->connection_lock->read_lock(this->connection_lock); + enumerator = this->connections->create_enumerator(this->connections); + while (enumerator->enumerate(enumerator, &entry)) + { + if (id == entry->id) + { + recs = entry->recs; + break; + } + } + enumerator->destroy(enumerator); + this->connection_lock->unlock(this->connection_lock); + + if (recs) + { + chunk_t pref_lang; + + pref_lang = recs->get_preferred_language(recs); + if (pref_lang.len == 0) + { + return TNC_RESULT_INVALID_PARAMETER; + } + *out_value_len = pref_lang.len; + if (buffer && buffer_len <= pref_lang.len) + { + memcpy(buffer, pref_lang.ptr, pref_lang.len); + } + return TNC_RESULT_SUCCESS; + } + return TNC_RESULT_INVALID_PARAMETER; +} + +METHOD(tnccs_manager_t, set_attribute, TNC_Result, + private_tnccs_manager_t *this, TNC_IMVID imv_id, + TNC_ConnectionID id, + TNC_AttributeID attribute_id, + TNC_UInt32 buffer_len, + TNC_BufferReference buffer) +{ + enumerator_t *enumerator; + tnccs_connection_entry_t *entry; + recommendations_t *recs = NULL; + + if (id == TNC_CONNECTIONID_ANY || + (attribute_id != TNC_ATTRIBUTEID_REASON_STRING && + attribute_id != TNC_ATTRIBUTEID_REASON_LANGUAGE)) + { + return TNC_RESULT_INVALID_PARAMETER; + } + + this->connection_lock->read_lock(this->connection_lock); + enumerator = this->connections->create_enumerator(this->connections); + while (enumerator->enumerate(enumerator, &entry)) + { + if (id == entry->id) + { + recs = entry->recs; + break; + } + } + enumerator->destroy(enumerator); + this->connection_lock->unlock(this->connection_lock); + + if (recs) + { + chunk_t attribute = { buffer, buffer_len }; + + if (attribute_id == TNC_ATTRIBUTEID_REASON_STRING) + { + return recs->set_reason_string(recs, imv_id, attribute); + } + else + { + return recs->set_reason_language(recs, imv_id, attribute); + } + } + return TNC_RESULT_INVALID_PARAMETER; +} + +METHOD(tnccs_manager_t, destroy, void, + private_tnccs_manager_t *this) +{ + this->protocols->destroy_function(this->protocols, free); + this->protocol_lock->destroy(this->protocol_lock); + this->connections->destroy_function(this->connections, free); + this->connection_lock->destroy(this->connection_lock); + free(this); +} + +/* + * See header + */ +tnccs_manager_t *tnccs_manager_create() +{ + private_tnccs_manager_t *this; + + INIT(this, + .public = { + .add_method = _add_method, + .remove_method = _remove_method, + .create_instance = _create_instance, + .create_connection = _create_connection, + .remove_connection = _remove_connection, + .request_handshake_retry = _request_handshake_retry, + .send_message = _send_message, + .provide_recommendation = _provide_recommendation, + .get_attribute = _get_attribute, + .set_attribute = _set_attribute, + .destroy = _destroy, + }, + .protocols = linked_list_create(), + .connections = linked_list_create(), + .protocol_lock = rwlock_create(RWLOCK_TYPE_DEFAULT), + .connection_lock = rwlock_create(RWLOCK_TYPE_DEFAULT), + ); + + return &this->public; +} + diff --git a/src/libcharon/tnc/tnccs/tnccs_manager.h b/src/libcharon/tnc/tnccs/tnccs_manager.h new file mode 100644 index 000000000..c02eac03c --- /dev/null +++ b/src/libcharon/tnc/tnccs/tnccs_manager.h @@ -0,0 +1,184 @@ +/* + * Copyright (C) 2010 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. + */ + +/** + * @defgroup tnccs_manager tnccs_manager + * @{ @ingroup tnccs + */ + +#ifndef TNCCS_MANAGER_H_ +#define TNCCS_MANAGER_H_ + +#include "tnccs.h" + +#include <tnc/imv/imv_recommendations.h> + +typedef struct tnccs_manager_t tnccs_manager_t; + +/** + * The TNCCS manager manages all TNCCS implementations and creates instances. + * + * A plugin registers its implemented TNCCS protocol with the manager by + * providing type and a constructor function. The manager then creates + * TNCCS protocol instances via the provided constructor. + */ +struct tnccs_manager_t { + + /** + * Register a TNCCS protocol implementation. + * + * @param type TNCCS protocol type + * @param constructor constructor, returns a TNCCS protocol implementation + */ + void (*add_method)(tnccs_manager_t *this, tnccs_type_t type, + tnccs_constructor_t constructor); + + /** + * Unregister a TNCCS protocol implementation using it's constructor. + * + * @param constructor constructor function to remove, as added in add_method + */ + void (*remove_method)(tnccs_manager_t *this, tnccs_constructor_t constructor); + + /** + * Create a new TNCCS protocol instance. + * + * @param type type of the TNCCS protocol + * @param is_server TRUE if TNC Server, FALSE if TNC Client + * @return TNCCS protocol instance, NULL if no constructor found + */ + tnccs_t* (*create_instance)(tnccs_manager_t *this, tnccs_type_t type, + bool is_server); + + /** + * Create a TNCCS connection and assign a unique connection ID as well a + * callback function for adding a message to a TNCCS batch and create + * an empty set for collecting IMV recommendations + * + * @param tnccs TNCCS connection instance + * @param send_message TNCCS callback function + * @param request_handshake_retry pointer to boolean variable + * @param recs pointer to IMV recommendation set + * @return assigned connection ID + */ + TNC_ConnectionID (*create_connection)(tnccs_manager_t *this, tnccs_t *tnccs, + tnccs_send_message_t send_message, + bool *request_handshake_retry, + recommendations_t **recs); + + /** + * Remove a TNCCS connection using its connection ID. + * + * @param id ID of the connection to be removed + */ + void (*remove_connection)(tnccs_manager_t *this, TNC_ConnectionID id); + + /** + * Request a handshake retry + * + * @param is_imc TRUE if IMC, FALSE if IMV + * @param imcv_id ID of IMC or IMV requesting the retry + * @param id ID of a specific connection or any connection + * @param reason reason for the handshake retry + * @return return code + */ + TNC_Result (*request_handshake_retry)(tnccs_manager_t *this, bool is_imc, + TNC_UInt32 imcv_id, + TNC_ConnectionID id, + TNC_RetryReason reason); + + /** + * Add an IMC/IMV message to the batch of a given connection ID. + * + * @param imc_id ID of IMC or TNC_IMCID_ANY + * @param imv_id ID of IMV or TNC_IMVID_ANY + * @param id ID of target connection + * @param msg message to be added + * @param msg_len message length + * @param msg_type message type + * @return return code + */ + TNC_Result (*send_message)(tnccs_manager_t *this, TNC_IMCID imc_id, + TNC_IMVID imv_id, + TNC_ConnectionID id, + TNC_BufferReference msg, + TNC_UInt32 msg_len, + TNC_MessageType msg_type); + + /** + * Deliver an IMV Action Recommendation and IMV Evaluation Result to the TNCS + * + * @param imv_id ID of the IMV providing the recommendation + * @param id ID of target connection + * @param rec action recommendation + * @param eval evaluation result + * @return return code + */ + TNC_Result (*provide_recommendation)(tnccs_manager_t *this, + TNC_IMVID imv_id, + TNC_ConnectionID id, + TNC_IMV_Action_Recommendation rec, + TNC_IMV_Evaluation_Result eval); + + /** + * Get the value of an attribute associated with a connection or with the + * TNCS as a whole. + * + * @param imv_id ID of the IMV requesting the attribute + * @param id ID of target connection + * @param attribute_id ID of the requested attribute + * @param buffer_len length of the buffer in bytes + * @param buffer pointer to the buffer + * @param out_value_len actual length of the returned attribute + * @return return code + */ + TNC_Result (*get_attribute)(tnccs_manager_t *this, + TNC_IMVID imv_id, + TNC_ConnectionID id, + TNC_AttributeID attribute_id, + TNC_UInt32 buffer_len, + TNC_BufferReference buffer, + TNC_UInt32 *out_value_len); + + /** + * Set the value of an attribute associated with a connection or with the + * TNCS as a whole. + * + * @param imv_id ID of the IMV setting the attribute + * @param id ID of target connection + * @param attribute_id ID of the attribute to be set + * @param buffer_len length of the buffer in bytes + * @param buffer pointer to the buffer + * @return return code + */ + TNC_Result (*set_attribute)(tnccs_manager_t *this, + TNC_IMVID imv_id, + TNC_ConnectionID id, + TNC_AttributeID attribute_id, + TNC_UInt32 buffer_len, + TNC_BufferReference buffer); + + /** + * Destroy a tnccs_manager instance. + */ + void (*destroy)(tnccs_manager_t *this); +}; + +/** + * Create a tnccs_manager instance. + */ +tnccs_manager_t *tnccs_manager_create(); + +#endif /** TNCCS_MANAGER_H_ @}*/ diff --git a/src/libcharon/tnc/tncif.h b/src/libcharon/tnc/tncif.h new file mode 100644 index 000000000..99441a9a9 --- /dev/null +++ b/src/libcharon/tnc/tncif.h @@ -0,0 +1,106 @@ +/* tncif.h + * + * Trusted Network Connect IF-IMV API version 1.20 + * Microsoft Windows DLL Platform Binding C Header + * February 5, 2007 + * + * Copyright(c) 2005-2007, Trusted Computing Group, Inc. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of the Trusted Computing Group nor the names of + * its contributors may be used to endorse or promote products + * derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * Contact the Trusted Computing Group at + * admin@trustedcomputinggroup.org for information on specification + * licensing through membership agreements. + * + * Any marks and brands contained herein are the property of their + * respective owners. + * + * Trusted Network Connect IF-IMC/IF-IMV API version 1.00 Revision 3 + * Microsoft Windows DLL Platform Binding C Header + * Common definitions for IF-IMC and IF-IMV + * extracted from tncifimc.h and tncifimv.h + * Feb 12, 2007 + */ + +/** + * @defgroup tnc tnc + * @ingroup libcharon + * + * @defgroup tncif tncif + * @{ @ingroup tnc + */ + +#ifndef TNCIF_H_ +#define TNCIF_H_ + +/* Basic Types */ +typedef unsigned long TNC_UInt32; +typedef unsigned char *TNC_BufferReference; + +/* Derived Types */ +typedef TNC_UInt32 TNC_ConnectionID; +typedef TNC_UInt32 TNC_ConnectionState; +typedef TNC_UInt32 TNC_RetryReason; +typedef TNC_UInt32 TNC_MessageType; +typedef TNC_MessageType *TNC_MessageTypeList; +typedef TNC_UInt32 TNC_VendorID; +typedef TNC_UInt32 TNC_MessageSubtype; +typedef TNC_UInt32 TNC_Version; +typedef TNC_UInt32 TNC_Result; + +/* Result Codes */ +#define TNC_RESULT_SUCCESS 0 +#define TNC_RESULT_NOT_INITIALIZED 1 +#define TNC_RESULT_ALREADY_INITIALIZED 2 +#define TNC_RESULT_NO_COMMON_VERSION 3 +#define TNC_RESULT_CANT_RETRY 4 +#define TNC_RESULT_WONT_RETRY 5 +#define TNC_RESULT_INVALID_PARAMETER 6 +#define TNC_RESULT_CANT_RESPOND 7 +#define TNC_RESULT_ILLEGAL_OPERATION 8 +#define TNC_RESULT_OTHER 9 +#define TNC_RESULT_FATAL 10 + +/* Network Connection ID Values */ +#define TNC_CONNECTIONID_ANY 0xFFFFFFFF +/* Network Connection State Values */ +#define TNC_CONNECTION_STATE_CREATE 0 +#define TNC_CONNECTION_STATE_HANDSHAKE 1 +#define TNC_CONNECTION_STATE_ACCESS_ALLOWED 2 +#define TNC_CONNECTION_STATE_ACCESS_ISOLATED 3 +#define TNC_CONNECTION_STATE_ACCESS_NONE 4 +#define TNC_CONNECTION_STATE_DELETE 5 + +/* Vendor ID Values */ +#define TNC_VENDORID_TCG 0 +#define TNC_VENDORID_ANY ((TNC_VendorID) 0xffffff) +/* Message Subtype Values */ +#define TNC_SUBTYPE_ANY ((TNC_MessageSubtype) 0xff) + +#endif /** TNCIF_H_ @}*/ diff --git a/src/libcharon/tnc/tncifimc.h b/src/libcharon/tnc/tncifimc.h new file mode 100644 index 000000000..c6ddabd45 --- /dev/null +++ b/src/libcharon/tnc/tncifimc.h @@ -0,0 +1,180 @@ +/* tncifimc.h + * + * Trusted Network Connect IF-IMC API version 1.20 Revision 8 + * Microsoft Windows DLL Platform Binding C Header + * February 5, 2007 + * + * Copyright(c) 2005-2007, Trusted Computing Group, Inc. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of the Trusted Computing Group nor the names of + * its contributors may be used to endorse or promote products + * derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * Contact the Trusted Computing Group at + * admin@trustedcomputinggroup.org for information on specification + * licensing through membership agreements. + * + * Any marks and brands contained herein are the property of their + * respective owners. + * + */ + +/** + * @defgroup tncifimc tncifimc + * @{ @ingroup tnc + */ + +#ifndef TNCIFIMC_H_ +#define TNCIFIMC_H_ + +#include "tncif.h" + +/* Derived Types */ + +typedef TNC_UInt32 TNC_IMCID; + +/* Function pointers */ + +typedef TNC_Result (*TNC_IMC_InitializePointer)( + TNC_IMCID imcID, + TNC_Version minVersion, + TNC_Version maxVersion, + TNC_Version *pOutActualVersion); +typedef TNC_Result (*TNC_IMC_NotifyConnectionChangePointer)( + TNC_IMCID imcID, + TNC_ConnectionID connectionID, + TNC_ConnectionState newState); +typedef TNC_Result (*TNC_IMC_BeginHandshakePointer)( + TNC_IMCID imcID, + TNC_ConnectionID connectionID); +typedef TNC_Result (*TNC_IMC_ReceiveMessagePointer)( + TNC_IMCID imcID, + TNC_ConnectionID connectionID, + TNC_BufferReference message, + TNC_UInt32 messageLength, + TNC_MessageType messageType); +typedef TNC_Result (*TNC_IMC_BatchEndingPointer)( + TNC_IMCID imcID, + TNC_ConnectionID connectionID); +typedef TNC_Result (*TNC_IMC_TerminatePointer)( + TNC_IMCID imcID); +typedef TNC_Result (*TNC_TNCC_ReportMessageTypesPointer)( + TNC_IMCID imcID, + TNC_MessageTypeList supportedTypes, + TNC_UInt32 typeCount); +typedef TNC_Result (*TNC_TNCC_SendMessagePointer)( + TNC_IMCID imcID, + TNC_ConnectionID connectionID, + TNC_BufferReference message, + TNC_UInt32 messageLength, + TNC_MessageType messageType); +typedef TNC_Result (*TNC_TNCC_RequestHandshakeRetryPointer)( + TNC_IMCID imcID, + TNC_ConnectionID connectionID, + TNC_RetryReason reason); +typedef TNC_Result (*TNC_TNCC_BindFunctionPointer)( + TNC_IMCID imcID, + char *functionName, + void **pOutfunctionPointer); +typedef TNC_Result (*TNC_IMC_ProvideBindFunctionPointer)( + TNC_IMCID imcID, + TNC_TNCC_BindFunctionPointer bindFunction); + +#define TNC_IFIMC_VERSION_1 1 + +/* Handshake Retry Reason Values */ + +#define TNC_RETRY_REASON_IMC_REMEDIATION_COMPLETE 0 +#define TNC_RETRY_REASON_IMC_SERIOUS_EVENT 1 +#define TNC_RETRY_REASON_IMC_INFORMATIONAL_EVENT 2 +#define TNC_RETRY_REASON_IMC_PERIODIC 3 +/* reserved for TNC_RETRY_REASON_IMV_IMPORTANT_POLICY_CHANGE: 4 */ +/* reserved for TNC_RETRY_REASON_IMV_MINOR_POLICY_CHANGE: 5 */ +/* reserved for TNC_RETRY_REASON_IMV_SERIOUS_EVENT: 6 */ +/* reserved for TNC_RETRY_REASON_IMV_MINOR_EVENT: 7 */ +/* reserved for TNC_RETRY_REASON_IMV_PERIODIC: 8 */ + +/* IMC Functions */ + +TNC_Result TNC_IMC_Initialize( +/*in*/ TNC_IMCID imcID, +/*in*/ TNC_Version minVersion, +/*in*/ TNC_Version maxVersion, +/*out*/ TNC_Version *pOutActualVersion); + +TNC_Result TNC_IMC_NotifyConnectionChange( +/*in*/ TNC_IMCID imcID, +/*in*/ TNC_ConnectionID connectionID, +/*in*/ TNC_ConnectionState newState); + +TNC_Result TNC_IMC_BeginHandshake( +/*in*/ TNC_IMCID imcID, +/*in*/ TNC_ConnectionID connectionID); + +TNC_Result TNC_IMC_ReceiveMessage( +/*in*/ TNC_IMCID imcID, +/*in*/ TNC_ConnectionID connectionID, +/*in*/ TNC_BufferReference messageBuffer, +/*in*/ TNC_UInt32 messageLength, +/*in*/ TNC_MessageType messageType); + +TNC_Result TNC_IMC_BatchEnding( +/*in*/ TNC_IMCID imcID, +/*in*/ TNC_ConnectionID connectionID); + +TNC_Result TNC_IMC_Terminate( +/*in*/ TNC_IMCID imcID); + +TNC_Result TNC_IMC_ProvideBindFunction( +/*in*/ TNC_IMCID imcID, +/*in*/ TNC_TNCC_BindFunctionPointer bindFunction); + +/* TNC Client Functions */ + +TNC_Result TNC_TNCC_ReportMessageTypes( +/*in*/ TNC_IMCID imcID, +/*in*/ TNC_MessageTypeList supportedTypes, +/*in*/ TNC_UInt32 typeCount); + +TNC_Result TNC_TNCC_SendMessage( +/*in*/ TNC_IMCID imcID, +/*in*/ TNC_ConnectionID connectionID, +/*in*/ TNC_BufferReference message, +/*in*/ TNC_UInt32 messageLength, +/*in*/ TNC_MessageType messageType); + +TNC_Result TNC_TNCC_RequestHandshakeRetry( +/*in*/ TNC_IMCID imcID, +/*in*/ TNC_ConnectionID connectionID, +/*in*/ TNC_RetryReason reason); + +TNC_Result TNC_TNCC_BindFunction( +/*in*/ TNC_IMCID imcID, +/*in*/ char *functionName, +/*out*/ void **pOutfunctionPointer); + +#endif /** TNCIFIMC_H_ @}*/ diff --git a/src/libcharon/tnc/tncifimv.c b/src/libcharon/tnc/tncifimv.c new file mode 100644 index 000000000..fbfd56566 --- /dev/null +++ b/src/libcharon/tnc/tncifimv.c @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2010 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 "tncifimv.h" + +ENUM(TNC_IMV_Action_Recommendation_names, + TNC_IMV_ACTION_RECOMMENDATION_ALLOW, + TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION, + "allow", + "no access", + "isolate", + "no recommendation" +); + +ENUM(TNC_IMV_Evaluation_Result_names, + TNC_IMV_EVALUATION_RESULT_COMPLIANT, + TNC_IMV_EVALUATION_RESULT_DONT_KNOW, + "compliant", + "non-compliant minor", + "non-compliant major", + "error", + "don't know" +); + diff --git a/src/libcharon/tnc/tncifimv.h b/src/libcharon/tnc/tncifimv.h new file mode 100644 index 000000000..4ec101337 --- /dev/null +++ b/src/libcharon/tnc/tncifimv.h @@ -0,0 +1,248 @@ +/* tncifimv.h + * + * Trusted Network Connect IF-IMV API version 1.20 + * Microsoft Windows DLL Platform Binding C Header + * February 5, 2007 + * + * Copyright(c) 2005-2007, Trusted Computing Group, Inc. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of the Trusted Computing Group nor the names of + * its contributors may be used to endorse or promote products + * derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * Contact the Trusted Computing Group at + * admin@trustedcomputinggroup.org for information on specification + * licensing through membership agreements. + * + * Any marks and brands contained herein are the property of their + * respective owners. + */ + +/** + * @defgroup tncifimv tncifimv + * @{ @ingroup tnc + */ + +#ifndef TNCIFIMV_H_ +#define TNCIFIMV_H_ + +#include "tncif.h" + +#include <library.h> + +typedef TNC_UInt32 TNC_IMVID; +typedef TNC_UInt32 TNC_IMV_Action_Recommendation; +typedef TNC_UInt32 TNC_IMV_Evaluation_Result; +typedef TNC_UInt32 TNC_AttributeID; + +/* Function pointers */ + +typedef TNC_Result (*TNC_IMV_InitializePointer)( + TNC_IMVID imvID, + TNC_Version minVersion, + TNC_Version maxVersion, + TNC_Version *pOutActualVersion); +typedef TNC_Result (*TNC_IMV_NotifyConnectionChangePointer)( + TNC_IMVID imvID, + TNC_ConnectionID connectionID, + TNC_ConnectionState newState); +typedef TNC_Result (*TNC_IMV_ReceiveMessagePointer)( + TNC_IMVID imvID, + TNC_ConnectionID connectionID, + TNC_BufferReference message, + TNC_UInt32 messageLength, + TNC_MessageType messageType); +typedef TNC_Result (*TNC_IMV_SolicitRecommendationPointer)( + TNC_IMVID imvID, + TNC_ConnectionID connectionID); +typedef TNC_Result (*TNC_IMV_BatchEndingPointer)( + TNC_IMVID imvID, + TNC_ConnectionID connectionID); +typedef TNC_Result (*TNC_IMV_TerminatePointer)( + TNC_IMVID imvID); +typedef TNC_Result (*TNC_TNCS_ReportMessageTypesPointer)( + TNC_IMVID imvID, + TNC_MessageTypeList supportedTypes, + TNC_UInt32 typeCount); +typedef TNC_Result (*TNC_TNCS_SendMessagePointer)( + TNC_IMVID imvID, + TNC_ConnectionID connectionID, + TNC_BufferReference message, + TNC_UInt32 messageLength, + TNC_MessageType messageType); +typedef TNC_Result (*TNC_TNCS_RequestHandshakeRetryPointer)( + TNC_IMVID imvID, + TNC_ConnectionID connectionID, + TNC_RetryReason reason); +typedef TNC_Result (*TNC_TNCS_ProvideRecommendationPointer)( + TNC_IMVID imvID, + TNC_ConnectionID connectionID, + TNC_IMV_Action_Recommendation recommendation, + TNC_IMV_Evaluation_Result evaluation); +typedef TNC_Result (*TNC_TNCS_GetAttributePointer)( + TNC_IMVID imvID, +TNC_ConnectionID connectionID, +TNC_AttributeID attributeID, + TNC_UInt32 bufferLength, + TNC_BufferReference buffer, + TNC_UInt32 *pOutValueLength); +typedef TNC_Result (*TNC_TNCS_SetAttributePointer)( + TNC_IMVID imvID, + TNC_ConnectionID connectionID, +TNC_AttributeID attributeID, + TNC_UInt32 bufferLength, + TNC_BufferReference buffer); +typedef TNC_Result (*TNC_TNCS_BindFunctionPointer)( + TNC_IMVID imvID, + char *functionName, + void **pOutfunctionPointer); +typedef TNC_Result (*TNC_IMV_ProvideBindFunctionPointer)( + TNC_IMVID imvID, + TNC_TNCS_BindFunctionPointer bindFunction); + +/* Version Numbers */ + +#define TNC_IFIMV_VERSION_1 1 + +/* Handshake Retry Reason Values */ + +/* reserved for TNC_RETRY_REASON_IMC_REMEDIATION_COMPLETE: 0 */ +/* reserved for TNC_RETRY_REASON_IMC_SERIOUS_EVENT: 1 */ +/* reserved for TNC_RETRY_REASON_IMC_INFORMATIONAL_EVENT: 2 */ +/* reserved for TNC_RETRY_REASON_IMC_PERIODIC: 3 */ +#define TNC_RETRY_REASON_IMV_IMPORTANT_POLICY_CHANGE 4 +#define TNC_RETRY_REASON_IMV_MINOR_POLICY_CHANGE 5 +#define TNC_RETRY_REASON_IMV_SERIOUS_EVENT 6 +#define TNC_RETRY_REASON_IMV_MINOR_EVENT 7 +#define TNC_RETRY_REASON_IMV_PERIODIC 8 + +/* IMV Action Recommendation Values */ + +#define TNC_IMV_ACTION_RECOMMENDATION_ALLOW 0 +#define TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS 1 +#define TNC_IMV_ACTION_RECOMMENDATION_ISOLATE 2 +#define TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION 3 + +extern enum_name_t *TNC_IMV_Action_Recommendation_names; + +/* IMV Evaluation Result Values */ + +#define TNC_IMV_EVALUATION_RESULT_COMPLIANT 0 +#define TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MINOR 1 +#define TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MAJOR 2 +#define TNC_IMV_EVALUATION_RESULT_ERROR 3 +#define TNC_IMV_EVALUATION_RESULT_DONT_KNOW 4 + +extern enum_name_t *TNC_IMV_Evaluation_Result_names; + +/* Message Attribute ID Values */ + +#define TNC_ATTRIBUTEID_PREFERRED_LANGUAGE ((TNC_AttributeID) 0x00000001) +#define TNC_ATTRIBUTEID_REASON_STRING ((TNC_AttributeID) 0x00000002) +#define TNC_ATTRIBUTEID_REASON_LANGUAGE ((TNC_AttributeID) 0x00000003) + +/* IMV Functions */ + +TNC_Result TNC_IMV_Initialize( +/*in*/ TNC_IMVID imvID, +/*in*/ TNC_Version minVersion, +/*in*/ TNC_Version maxVersion, +/*in*/ TNC_Version *pOutActualVersion); + +TNC_Result TNC_IMV_NotifyConnectionChange( +/*in*/ TNC_IMVID imvID, +/*in*/ TNC_ConnectionID connectionID, +/*in*/ TNC_ConnectionState newState); + +TNC_Result TNC_IMV_ReceiveMessage( +/*in*/ TNC_IMVID imvID, +/*in*/ TNC_ConnectionID connectionID, +/*in*/ TNC_BufferReference messageBuffer, +/*in*/ TNC_UInt32 messageLength, +/*in*/ TNC_MessageType messageType); + +TNC_Result TNC_IMV_SolicitRecommendation( +/*in*/ TNC_IMVID imvID, +/*in*/ TNC_ConnectionID connectionID); + +TNC_Result TNC_IMV_BatchEnding( +/*in*/ TNC_IMVID imvID, +/*in*/ TNC_ConnectionID connectionID); + +TNC_Result TNC_IMV_Terminate( +/*in*/ TNC_IMVID imvID); + +TNC_Result TNC_IMV_ProvideBindFunction( +/*in*/ TNC_IMVID imvID, +/*in*/ TNC_TNCS_BindFunctionPointer bindFunction); + +/* TNC Server Functions */ + +TNC_Result TNC_TNCS_ReportMessageTypes( +/*in*/ TNC_IMVID imvID, +/*in*/ TNC_MessageTypeList supportedTypes, +/*in*/ TNC_UInt32 typeCount); + +TNC_Result TNC_TNCS_SendMessage( +/*in*/ TNC_IMVID imvID, +/*in*/ TNC_ConnectionID connectionID, +/*in*/ TNC_BufferReference message, +/*in*/ TNC_UInt32 messageLength, +/*in*/ TNC_MessageType messageType); + +TNC_Result TNC_TNCS_RequestHandshakeRetry( +/*in*/ TNC_IMVID imvID, +/*in*/ TNC_ConnectionID connectionID, +/*in*/ TNC_RetryReason reason); + +TNC_Result TNC_TNCS_ProvideRecommendation( +/*in*/ TNC_IMVID imvID, +/*in*/ TNC_ConnectionID connectionID, +/*in*/ TNC_IMV_Action_Recommendation recommendation, +/*in*/ TNC_IMV_Evaluation_Result evaluation); + +TNC_Result TNC_TNCS_GetAttribute( +/*in*/ TNC_IMVID imvID, +/*in*/ TNC_ConnectionID connectionID, +/*in*/ TNC_AttributeID attributeID, +/*in*/ TNC_UInt32 bufferLength, +/*out*/ TNC_BufferReference buffer, +/*out*/ TNC_UInt32 *pOutValueLength); + +TNC_Result TNC_TNCS_SetAttribute( +/*in*/ TNC_IMVID imvID, +/*in*/ TNC_ConnectionID connectionID, +/*in*/ TNC_AttributeID attributeID, +/*in*/ TNC_UInt32 bufferLength, +/*in*/ TNC_BufferReference buffer); + +TNC_Result TNC_TNCS_BindFunction( +/*in*/ TNC_IMVID imvID, +/*in*/ char *functionName, +/*in*/ void **pOutfunctionPointer); + +#endif /** TNCIFIMV_H_ @}*/ diff --git a/src/libcharon/tnccs/tnccs_manager.c b/src/libcharon/tnccs/tnccs_manager.c deleted file mode 100644 index 0fd6737c0..000000000 --- a/src/libcharon/tnccs/tnccs_manager.c +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (C) 2010 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 "tnccs_manager.h" - -#include <utils/linked_list.h> -#include <threading/rwlock.h> - -typedef struct private_tnccs_manager_t private_tnccs_manager_t; -typedef struct tnccs_entry_t tnccs_entry_t; - -/** - * TNCCS constructor entry - */ -struct tnccs_entry_t { - - /** - * TNCCS protocol type - */ - tnccs_type_t type; - - /** - * constructor function to create instance - */ - tnccs_constructor_t constructor; -}; - -/** - * private data of tnccs_manager - */ -struct private_tnccs_manager_t { - - /** - * public functions - */ - tnccs_manager_t public; - - /** - * list of tnccs_entry_t's - */ - linked_list_t *protocols; - - /** - * rwlock to lock methods - */ - rwlock_t *lock; -}; - -METHOD(tnccs_manager_t, add_method, void, - private_tnccs_manager_t *this, tnccs_type_t type, - tnccs_constructor_t constructor) -{ - tnccs_entry_t *entry = malloc_thing(tnccs_entry_t); - - entry->type = type; - entry->constructor = constructor; - - this->lock->write_lock(this->lock); - this->protocols->insert_last(this->protocols, entry); - this->lock->unlock(this->lock); -} - -METHOD(tnccs_manager_t, remove_method, void, - private_tnccs_manager_t *this, tnccs_constructor_t constructor) -{ - enumerator_t *enumerator; - tnccs_entry_t *entry; - - this->lock->write_lock(this->lock); - enumerator = this->protocols->create_enumerator(this->protocols); - while (enumerator->enumerate(enumerator, &entry)) - { - if (constructor == entry->constructor) - { - this->protocols->remove_at(this->protocols, enumerator); - free(entry); - } - } - enumerator->destroy(enumerator); - this->lock->unlock(this->lock); -} - -METHOD(tnccs_manager_t, create_instance, tnccs_t*, - private_tnccs_manager_t *this, tnccs_type_t type, bool is_server) -{ - enumerator_t *enumerator; - tnccs_entry_t *entry; - tnccs_t *protocol = NULL; - - this->lock->read_lock(this->lock); - enumerator = this->protocols->create_enumerator(this->protocols); - while (enumerator->enumerate(enumerator, &entry)) - { - if (type == entry->type) - { - protocol = entry->constructor(is_server); - if (protocol) - { - break; - } - } - } - enumerator->destroy(enumerator); - this->lock->unlock(this->lock); - return protocol; -} - -METHOD(tnccs_manager_t, destroy, void, - private_tnccs_manager_t *this) -{ - this->protocols->destroy_function(this->protocols, free); - this->lock->destroy(this->lock); - free(this); -} - -/* - * See header - */ -tnccs_manager_t *tnccs_manager_create() -{ - private_tnccs_manager_t *this; - - INIT(this, - .public = { - .add_method = _add_method, - .remove_method = _remove_method, - .create_instance = _create_instance, - .destroy = _destroy, - }, - .protocols = linked_list_create(), - .lock = rwlock_create(RWLOCK_TYPE_DEFAULT), - ); - - return &this->public; -} - diff --git a/src/libcharon/tnccs/tnccs_manager.h b/src/libcharon/tnccs/tnccs_manager.h deleted file mode 100644 index 2f4a961a7..000000000 --- a/src/libcharon/tnccs/tnccs_manager.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2010 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. - */ - -/** - * @defgroup tnccs_manager tnccs_manager - * @{ @ingroup tnccs - */ - -#ifndef TNCCS_MANAGER_H_ -#define TNCCS_MANAGER_H_ - -#include "tnccs.h" - -typedef struct tnccs_manager_t tnccs_manager_t; - -/** - * The TNCCS manager manages all TNCCS implementations and creates instances. - * - * A plugin registers its implemented TNCCS protocol with the manager by - * providing type and a constructor function. The manager then creates - * TNCCS protocol instances via the provided constructor. - */ -struct tnccs_manager_t { - - /** - * Register a TNCCS protocol implementation. - * - * @param type TNCCS protocol type - * @param constructor constructor, returns a TNCCS protocol implementation - */ - void (*add_method)(tnccs_manager_t *this, tnccs_type_t type, - tnccs_constructor_t constructor); - - /** - * Unregister a TNCCS protocol implementation using it's constructor. - * - * @param constructor constructor function to remove, as added in add_method - */ - void (*remove_method)(tnccs_manager_t *this, tnccs_constructor_t constructor); - - /** - * Create a new TNCCS protocol instance. - * - * @param type type of the TNCCS protocol - * @param is_server TRUE if TNC Server, FALSE if TNC Client - * @return TNCCS protocol instance, NULL if no constructor found - */ - tnccs_t* (*create_instance)(tnccs_manager_t *this, tnccs_type_t type, - bool is_server); - - /** - * Destroy a tnccs_manager instance. - */ - void (*destroy)(tnccs_manager_t *this); -}; - -/** - * Create a tnccs_manager instance. - */ -tnccs_manager_t *tnccs_manager_create(); - -#endif /** TNCCS_MANAGER_H_ @}*/ diff --git a/src/libfast/Makefile.in b/src/libfast/Makefile.in index 777f1fd10..46f23f4d6 100644 --- a/src/libfast/Makefile.in +++ b/src/libfast/Makefile.in @@ -217,9 +217,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -258,6 +256,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libfast/request.c b/src/libfast/request.c index 16c1ae583..a3db70e82 100644 --- a/src/libfast/request.c +++ b/src/libfast/request.c @@ -120,7 +120,7 @@ static char *getenv_cb(void *null, const char *key) private_request_t *this = (private_request_t*)thread_this->get(thread_this); value = FCGX_GetParam(key, this->req.envp); - return value ? strdup(value) : NULL; + return strdupnull(value); } /** @@ -204,6 +204,14 @@ static char* get_query_data(private_request_t *this, char *name) } /** + * Implementation of request_t.get_env_var. + */ +static char* get_env_var(private_request_t *this, char *name) +{ + return FCGX_GetParam(name, this->req.envp); +} + +/** * Implementation of request_t.read_data. */ static int read_data(private_request_t *this, char *buf, int len) @@ -415,6 +423,7 @@ request_t *request_create(int fd, bool debug) this->public.add_cookie = (void(*)(request_t*, char *name, char *value))add_cookie; this->public.get_cookie = (char*(*)(request_t*,char*))get_cookie; this->public.get_query_data = (char*(*)(request_t*, char *name))get_query_data; + this->public.get_env_var = (char*(*)(request_t*, char *name))get_env_var; this->public.read_data = (int(*)(request_t*, char*, int))read_data; this->public.session_closed = (bool(*)(request_t*))session_closed; this->public.close_session = (void(*)(request_t*))close_session; diff --git a/src/libfast/request.h b/src/libfast/request.h index 9ca74a91e..c9c1f13e2 100644 --- a/src/libfast/request.h +++ b/src/libfast/request.h @@ -86,6 +86,14 @@ struct request_t { char* (*get_query_data)(request_t *this, char *name); /** + * Get an arbitrary environment variable. + * + * @param name name of the environment variable + * @return value, NULL if not found + */ + char* (*get_env_var)(request_t *this, char *name); + + /** * Read raw POST/PUT data from HTTP request. * * @param buf buffer to read data into diff --git a/src/libfreeswan/Makefile.am b/src/libfreeswan/Makefile.am index 5fee39da9..09f5fe2cd 100644 --- a/src/libfreeswan/Makefile.am +++ b/src/libfreeswan/Makefile.am @@ -1,10 +1,10 @@ noinst_LIBRARIES = libfreeswan.a libfreeswan_a_SOURCES = addrtoa.c addrtot.c addrtypeof.c anyaddr.c atoaddr.c atoasr.c \ - atosa.c atosubnet.c atoul.c copyright.c datatot.c freeswan.h \ + atosubnet.c atoul.c copyright.c datatot.c freeswan.h \ goodmask.c initaddr.c initsaid.c initsubnet.c internal.h ipsec_param.h \ - keyblobtoid.c pfkey_v2_build.c pfkey_v2_debug.c \ - pfkey_v2_ext_bits.c pfkey_v2_parse.c portof.c prng.c rangetoa.c \ - pfkey.h pfkeyv2.h rangetosubnet.c sameaddr.c satoa.c \ + pfkey_v2_build.c pfkey_v2_debug.c \ + pfkey_v2_ext_bits.c pfkey_v2_parse.c portof.c rangetoa.c \ + pfkey.h pfkeyv2.h rangetosubnet.c sameaddr.c \ satot.c subnetof.c subnettoa.c subnettot.c \ subnettypeof.c ttoaddr.c ttodata.c ttoprotoport.c ttosa.c ttosubnet.c ttoul.c \ ultoa.c ultot.c @@ -14,7 +14,7 @@ INCLUDES = \ -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/pluto -dist_man3_MANS = anyaddr.3 atoaddr.3 atoasr.3 atosa.3 atoul.3 goodmask.3 initaddr.3 initsubnet.3 \ - keyblobtoid.3 portof.3 prng.3 rangetosubnet.3 sameaddr.3 subnetof.3 \ +dist_man3_MANS = anyaddr.3 atoaddr.3 atoasr.3 atoul.3 goodmask.3 initaddr.3 initsubnet.3 \ + portof.3 rangetosubnet.3 sameaddr.3 subnetof.3 \ ttoaddr.3 ttodata.3 ttosa.3 ttoul.3 diff --git a/src/libfreeswan/Makefile.in b/src/libfreeswan/Makefile.in index 28ba035c6..88ceab557 100644 --- a/src/libfreeswan/Makefile.in +++ b/src/libfreeswan/Makefile.in @@ -58,19 +58,17 @@ libfreeswan_a_AR = $(AR) $(ARFLAGS) libfreeswan_a_LIBADD = am_libfreeswan_a_OBJECTS = addrtoa.$(OBJEXT) addrtot.$(OBJEXT) \ addrtypeof.$(OBJEXT) anyaddr.$(OBJEXT) atoaddr.$(OBJEXT) \ - atoasr.$(OBJEXT) atosa.$(OBJEXT) atosubnet.$(OBJEXT) \ - atoul.$(OBJEXT) copyright.$(OBJEXT) datatot.$(OBJEXT) \ - goodmask.$(OBJEXT) initaddr.$(OBJEXT) initsaid.$(OBJEXT) \ - initsubnet.$(OBJEXT) keyblobtoid.$(OBJEXT) \ + atoasr.$(OBJEXT) atosubnet.$(OBJEXT) atoul.$(OBJEXT) \ + copyright.$(OBJEXT) datatot.$(OBJEXT) goodmask.$(OBJEXT) \ + initaddr.$(OBJEXT) initsaid.$(OBJEXT) initsubnet.$(OBJEXT) \ pfkey_v2_build.$(OBJEXT) pfkey_v2_debug.$(OBJEXT) \ pfkey_v2_ext_bits.$(OBJEXT) pfkey_v2_parse.$(OBJEXT) \ - portof.$(OBJEXT) prng.$(OBJEXT) rangetoa.$(OBJEXT) \ - rangetosubnet.$(OBJEXT) sameaddr.$(OBJEXT) satoa.$(OBJEXT) \ - satot.$(OBJEXT) subnetof.$(OBJEXT) subnettoa.$(OBJEXT) \ - subnettot.$(OBJEXT) subnettypeof.$(OBJEXT) ttoaddr.$(OBJEXT) \ - ttodata.$(OBJEXT) ttoprotoport.$(OBJEXT) ttosa.$(OBJEXT) \ - ttosubnet.$(OBJEXT) ttoul.$(OBJEXT) ultoa.$(OBJEXT) \ - ultot.$(OBJEXT) + portof.$(OBJEXT) rangetoa.$(OBJEXT) rangetosubnet.$(OBJEXT) \ + sameaddr.$(OBJEXT) satot.$(OBJEXT) subnetof.$(OBJEXT) \ + subnettoa.$(OBJEXT) subnettot.$(OBJEXT) subnettypeof.$(OBJEXT) \ + ttoaddr.$(OBJEXT) ttodata.$(OBJEXT) ttoprotoport.$(OBJEXT) \ + ttosa.$(OBJEXT) ttosubnet.$(OBJEXT) ttoul.$(OBJEXT) \ + ultoa.$(OBJEXT) ultot.$(OBJEXT) libfreeswan_a_OBJECTS = $(am_libfreeswan_a_OBJECTS) DEFAULT_INCLUDES = -I.@am__isrc@ depcomp = $(SHELL) $(top_srcdir)/depcomp @@ -234,9 +232,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -275,6 +271,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ @@ -287,11 +285,11 @@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ noinst_LIBRARIES = libfreeswan.a libfreeswan_a_SOURCES = addrtoa.c addrtot.c addrtypeof.c anyaddr.c atoaddr.c atoasr.c \ - atosa.c atosubnet.c atoul.c copyright.c datatot.c freeswan.h \ + atosubnet.c atoul.c copyright.c datatot.c freeswan.h \ goodmask.c initaddr.c initsaid.c initsubnet.c internal.h ipsec_param.h \ - keyblobtoid.c pfkey_v2_build.c pfkey_v2_debug.c \ - pfkey_v2_ext_bits.c pfkey_v2_parse.c portof.c prng.c rangetoa.c \ - pfkey.h pfkeyv2.h rangetosubnet.c sameaddr.c satoa.c \ + pfkey_v2_build.c pfkey_v2_debug.c \ + pfkey_v2_ext_bits.c pfkey_v2_parse.c portof.c rangetoa.c \ + pfkey.h pfkeyv2.h rangetosubnet.c sameaddr.c \ satot.c subnetof.c subnettoa.c subnettot.c \ subnettypeof.c ttoaddr.c ttodata.c ttoprotoport.c ttosa.c ttosubnet.c ttoul.c \ ultoa.c ultot.c @@ -301,8 +299,8 @@ INCLUDES = \ -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/pluto -dist_man3_MANS = anyaddr.3 atoaddr.3 atoasr.3 atosa.3 atoul.3 goodmask.3 initaddr.3 initsubnet.3 \ - keyblobtoid.3 portof.3 prng.3 rangetosubnet.3 sameaddr.3 subnetof.3 \ +dist_man3_MANS = anyaddr.3 atoaddr.3 atoasr.3 atoul.3 goodmask.3 initaddr.3 initsubnet.3 \ + portof.3 rangetosubnet.3 sameaddr.3 subnetof.3 \ ttoaddr.3 ttodata.3 ttosa.3 ttoul.3 all: all-am @@ -359,7 +357,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/anyaddr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atoaddr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atoasr.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atosa.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atosubnet.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atoul.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/copyright.Po@am__quote@ @@ -368,17 +365,14 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/initaddr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/initsaid.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/initsubnet.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/keyblobtoid.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pfkey_v2_build.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pfkey_v2_debug.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pfkey_v2_ext_bits.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pfkey_v2_parse.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/portof.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/prng.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rangetoa.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rangetosubnet.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sameaddr.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/satoa.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/satot.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/subnetof.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/subnettoa.Po@am__quote@ diff --git a/src/libfreeswan/atosa.3 b/src/libfreeswan/atosa.3 deleted file mode 100644 index f57fcf1e9..000000000 --- a/src/libfreeswan/atosa.3 +++ /dev/null @@ -1,217 +0,0 @@ -.TH IPSEC_ATOSA 3 "11 June 2001" -.SH NAME -ipsec atosa, satoa \- convert IPsec Security Association IDs to and from ASCII -.SH SYNOPSIS -.B "#include <freeswan.h> -.sp -.B "const char *atosa(const char *src, size_t srclen," -.ti +1c -.B "struct sa_id *sa); -.br -.B "size_t satoa(struct sa_id sa, int format," -.ti +1c -.B "char *dst, size_t dstlen);" -.sp -.B "struct sa_id {" -.ti +1c -.B "struct in_addr dst;" -.ti +1c -.B "ipsec_spi_t spi;" -.ti +1c -.B "int proto;" -.br -.B "};" -.SH DESCRIPTION -These functions are obsolete; see -.IR ipsec_ttosa (3) -for their replacements. -.PP -.I Atosa -converts an ASCII Security Association (SA) specifier into an -.B sa_id -structure (containing -a destination-host address -in network byte order, -an SPI number in network byte order, and -a protocol code). -.I Satoa -does the reverse conversion, back to an ASCII SA specifier. -.PP -An SA is specified in ASCII with a mail-like syntax, e.g. -.BR esp507@1.2.3.4 . -An SA specifier contains -a protocol prefix (currently -.BR ah , -.BR esp , -or -.BR tun ), -an unsigned integer SPI number, -and an IP address. -The SPI number can be decimal or hexadecimal -(with -.B 0x -prefix), as accepted by -.IR ipsec_atoul (3). -The IP address can be any form accepted by -.IR ipsec_atoaddr (3), -e.g. dotted-decimal address or DNS name. -.PP -As a special case, the SA specifier -.B %passthrough -signifies the special SA used to indicate that packets should be -passed through unaltered. -(At present, this is a synonym for -.BR tun0x0@0.0.0.0 , -but that is subject to change without notice.) -This form is known to both -.I atosa -and -.IR satoa , -so the internal form of -.B %passthrough -is never visible. -.PP -The -.B <freeswan.h> -header file supplies the -.B sa_id -structure, as well as a data type -.B ipsec_spi_t -which is an unsigned 32-bit integer. -(There is no consistency between kernel and user on what such a type -is called, hence the header hides the differences.) -.PP -The protocol code uses the same numbers that IP does. -For user convenience, given the difficulty in acquiring the exact set of -protocol names used by the kernel, -.B <freeswan.h> -defines the names -.BR SA_ESP , -.BR SA_AH , -and -.B SA_IPIP -to have the same values as the kernel names -.BR IPPROTO_ESP , -.BR IPPROTO_AH , -and -.BR IPPROTO_IPIP . -.PP -The -.I srclen -parameter of -.I atosa -specifies the length of the ASCII string pointed to by -.IR src ; -it is an error for there to be anything else -(e.g., a terminating NUL) within that length. -As a convenience for cases where an entire NUL-terminated string is -to be converted, -a -.I srclen -value of -.B 0 -is taken to mean -.BR strlen(src) . -.PP -The -.I dstlen -parameter of -.I satoa -specifies the size of the -.I dst -parameter; -under no circumstances are more than -.I dstlen -bytes written to -.IR dst . -A result which will not fit is truncated. -.I Dstlen -can be zero, in which case -.I dst -need not be valid and no result is written, -but the return value is unaffected; -in all other cases, the (possibly truncated) result is NUL-terminated. -The -.I freeswan.h -header file defines a constant, -.BR SATOA_BUF , -which is the size of a buffer just large enough for worst-case results. -.PP -The -.I format -parameter of -.I satoa -specifies what format is to be used for the conversion. -The value -.B 0 -(not the ASCII character -.BR '0' , -but a zero value) -specifies a reasonable default -(currently -lowercase protocol prefix, lowercase hexadecimal SPI, dotted-decimal address). -The value -.B d -causes the SPI to be generated in decimal instead. -.PP -.I Atosa -returns -.B NULL -for success and -a pointer to a string-literal error message for failure; -see DIAGNOSTICS. -.I Satoa -returns -.B 0 -for a failure, and otherwise -always returns the size of buffer which would -be needed to -accommodate the full conversion result, including terminating NUL; -it is the caller's responsibility to check this against the size of -the provided buffer to determine whether truncation has occurred. -.SH SEE ALSO -ipsec_atoul(3), ipsec_atoaddr(3), inet(3) -.SH DIAGNOSTICS -Fatal errors in -.I atosa -are: -empty input; -input too small to be a legal SA specifier; -no -.B @ -in input; -unknown protocol prefix; -conversion error in -.I atoul -or -.IR atoaddr . -.PP -Fatal errors in -.I satoa -are: -unknown format; unknown protocol code. -.SH HISTORY -Written for the FreeS/WAN project by Henry Spencer. -.SH BUGS -The -.B tun -protocol code is a FreeS/WANism which may eventually disappear. -.PP -The restriction of ASCII-to-binary error reports to literal strings -(so that callers don't need to worry about freeing them or copying them) -does limit the precision of error reporting. -.PP -The ASCII-to-binary error-reporting convention lends itself -to slightly obscure code, -because many readers will not think of NULL as signifying success. -A good way to make it clearer is to write something like: -.PP -.RS -.nf -.B "const char *error;" -.sp -.B "error = atoaddr( /* ... */ );" -.B "if (error != NULL) {" -.B " /* something went wrong */" -.fi -.RE diff --git a/src/libfreeswan/atosa.c b/src/libfreeswan/atosa.c deleted file mode 100644 index 7339b4c3e..000000000 --- a/src/libfreeswan/atosa.c +++ /dev/null @@ -1,198 +0,0 @@ -/* - * convert from ASCII form of SA ID to binary - * Copyright (C) 1998, 1999 Henry Spencer. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Library 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/lgpl.txt>. - * - * This library 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 Library General Public - * License for more details. - */ -#include "internal.h" -#include "freeswan.h" - -static struct satype { - char *prefix; - size_t prelen; /* strlen(prefix) */ - int proto; -} satypes[] = { - { "ah", 2, SA_AH }, - { "esp", 3, SA_ESP }, - { "tun", 3, SA_IPIP }, - { "comp", 4, SA_COMP }, - { NULL, 0, 0, } -}; - -/* - - atosa - convert ASCII "ah507@10.0.0.1" to SA identifier - */ -const char * /* NULL for success, else string literal */ -atosa(src, srclen, sa) -const char *src; -size_t srclen; /* 0 means "apply strlen" */ -struct sa_id *sa; -{ - const char *at; - const char *addr; - const char *spi = NULL; - struct satype *sat; - unsigned long ul; - const char *oops; -# define MINLEN 5 /* ah0@0 is as short as it can get */ - static char ptname[] = PASSTHROUGHNAME; -# define PTNLEN (sizeof(ptname)-1) /* -1 for NUL */ - - if (srclen == 0) - srclen = strlen(src); - if (srclen == 0) - return "empty string"; - if (srclen < MINLEN) - return "string too short to be SA specifier"; - if (srclen == PTNLEN && memcmp(src, ptname, PTNLEN) == 0) { - src = PASSTHROUGHIS; - srclen = strlen(src); - } - - at = memchr(src, '@', srclen); - if (at == NULL) - return "no @ in SA specifier"; - - for (sat = satypes; sat->prefix != NULL; sat++) - if (sat->prelen < srclen && - strncmp(src, sat->prefix, sat->prelen) == 0) { - sa->proto = sat->proto; - spi = src + sat->prelen; - break; /* NOTE BREAK OUT */ - } - if (sat->prefix == NULL) - return "SA specifier lacks valid protocol prefix"; - - if (spi >= at) - return "no SPI in SA specifier"; - oops = atoul(spi, at - spi, 13, &ul); - if (oops != NULL) - return oops; - sa->spi = htonl(ul); - - addr = at + 1; - oops = atoaddr(addr, srclen - (addr - src), &sa->dst); - if (oops != NULL) - return oops; - - return NULL; -} - - - -#ifdef ATOSA_MAIN - -#include <stdio.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> - -void regress(void); - -int -main(int argc, char *argv[]) -{ - struct sa_id sa; - char buf[100]; - const char *oops; - size_t n; - - if (argc < 2) { - fprintf(stderr, "Usage: %s {ahnnn@aaa|-r}\n", argv[0]); - exit(2); - } - - if (strcmp(argv[1], "-r") == 0) { - regress(); - fprintf(stderr, "regress() returned?!?\n"); - exit(1); - } - - oops = atosa(argv[1], 0, &sa); - if (oops != NULL) { - fprintf(stderr, "%s: conversion failed: %s\n", argv[0], oops); - exit(1); - } - n = satoa(sa, 0, buf, sizeof(buf)); - if (n > sizeof(buf)) { - fprintf(stderr, "%s: reverse conv of `%d'", argv[0], sa.proto); - fprintf(stderr, "%lu@", (long unsigned int)sa.spi); - fprintf(stderr, "%s", inet_ntoa(sa.dst)); - fprintf(stderr, " failed: need %ld bytes, have only %ld\n", - (long)n, (long)sizeof(buf)); - exit(1); - } - printf("%s\n", buf); - - exit(0); -} - -struct rtab { - char *input; - char *output; /* NULL means error expected */ -} rtab[] = { - {"esp257@1.2.3.0", "esp257@1.2.3.0"}, - {"ah0x20@1.2.3.4", "ah32@1.2.3.4"}, - {"tun011@111.2.3.99", "tun11@111.2.3.99"}, - {"", NULL}, - {"_", NULL}, - {"ah2.2", NULL}, - {"goo2@1.2.3.4", NULL}, - {"esp9@1.2.3.4", "esp9@1.2.3.4"}, - {"espp9@1.2.3.4", NULL}, - {"es9@1.2.3.4", NULL}, - {"ah@1.2.3.4", NULL}, - {"esp7x7@1.2.3.4", NULL}, - {"esp77@1.0x2.3.4", NULL}, - {PASSTHROUGHNAME, PASSTHROUGHNAME}, - {NULL, NULL} -}; - -void -regress(void) -{ - struct rtab *r; - int status = 0; - struct sa_id sa; - char in[100]; - char buf[100]; - const char *oops; - size_t n; - - for (r = rtab; r->input != NULL; r++) { - strcpy(in, r->input); - oops = atosa(in, 0, &sa); - if (oops != NULL && r->output == NULL) - {} /* okay, error expected */ - else if (oops != NULL) { - printf("`%s' atosa failed: %s\n", r->input, oops); - status = 1; - } else if (r->output == NULL) { - printf("`%s' atosa succeeded unexpectedly\n", - r->input); - status = 1; - } else { - n = satoa(sa, 'd', buf, sizeof(buf)); - if (n > sizeof(buf)) { - printf("`%s' satoa failed: need %ld\n", - r->input, (long)n); - status = 1; - } else if (strcmp(r->output, buf) != 0) { - printf("`%s' gave `%s', expected `%s'\n", - r->input, buf, r->output); - status = 1; - } - } - } - exit(status); -} - -#endif /* ATOSA_MAIN */ diff --git a/src/libfreeswan/copyright.c b/src/libfreeswan/copyright.c index 65585b62e..e55e849f7 100644 --- a/src/libfreeswan/copyright.c +++ b/src/libfreeswan/copyright.c @@ -27,13 +27,13 @@ static const char *co[] = { " Christoph Gysin, Andreas Hess, Patric Lichtsteiner, Michael Meier,", " Andreas Schleiss, Ariane Seiler, Mario Strasser, Lukas Suter,", " Roger Wegmann, Simon Zwahlen,", - " Zuercher Hochschule Winterthur (Switzerland).", + " ZHW Zuercher Hochschule Winterthur (Switzerland).", "", - " Philip Boetschi, Tobias Brunner, Adrian Doerig, Andreas Eigenmann,", - " Fabian Hartmann, Noah Heusser, Jan Hutter, Thomas Kallenberg,", - " Daniel Roethlisberger, Joel Stillhart, Martin Willi, Daniel Wydler,", - " Andreas Steffen,", - " Hochschule fuer Technik Rapperswil (Switzerland).", + " Philip Boetschi, Tobias Brunner, Sansar Choinyambuu, Adrian Doerig,", + " Andreas Eigenmann, Fabian Hartmann, Noah Heusser, Jan Hutter,", + " Thomas Kallenberg, Daniel Roethlisberger, Joel Stillhart, Martin Willi,", + " Daniel Wydler, Andreas Steffen,", + " HSR Hochschule fuer Technik Rapperswil (Switzerland).", "", "This program is free software; you can redistribute it and/or modify it", "under the terms of the GNU General Public License as published by the", diff --git a/src/libfreeswan/freeswan.h b/src/libfreeswan/freeswan.h index 342f59987..724165bde 100644 --- a/src/libfreeswan/freeswan.h +++ b/src/libfreeswan/freeswan.h @@ -158,11 +158,6 @@ err_t ttodatav(const char *src, size_t srclen, int base, size_t datatot(const char *src, size_t srclen, int format, char *buf, size_t buflen); -size_t keyblobtoid(const unsigned char *src, size_t srclen, char *dst, - size_t dstlen); -size_t splitkeytoid(const unsigned char *e, size_t elen, const unsigned char *m, - size_t mlen, char *dst, size_t dstlen); -#define KEYID_BUF 10 /* up to 9 text digits plus NUL */ err_t ttoprotoport(char *src, size_t src_len, u_int8_t *proto, u_int16_t *port, bool *has_port_wildcard); @@ -206,12 +201,6 @@ void setportof(int port, ip_address *dst); struct sockaddr *sockaddrof(ip_address *src); size_t sockaddrlenof(const ip_address *src); -/* PRNG */ -void prng_init(struct prng *prng, const unsigned char *key, size_t keylen); -void prng_bytes(struct prng *prng, unsigned char *dst, size_t dstlen); -unsigned long prng_count(struct prng *prng); -void prng_final(struct prng *prng); - /* odds and ends */ const char **ipsec_copyright_notice(void); @@ -294,24 +283,6 @@ rangetoa( ); #define RANGETOA_BUF 34 /* large enough for worst case result */ -/* data types for SA conversion functions */ - -/* SAs */ -const char * /* NULL for success, else string literal */ -atosa( - const char *src, - size_t srclen, /* 0 means strlen(src) */ - struct sa_id *sa -); -size_t /* space needed for full conversion */ -satoa( - struct sa_id sa, - int format, /* character; 0 means default */ - char *dst, - size_t dstlen -); -#define SATOA_BUF (3+ULTOA_BUF+ADDRTOA_BUF) - /* generic data, e.g. keys */ const char * /* NULL for success, else string literal */ atobytes( diff --git a/src/libfreeswan/keyblobtoid.3 b/src/libfreeswan/keyblobtoid.3 deleted file mode 100644 index 8b5bfb0a2..000000000 --- a/src/libfreeswan/keyblobtoid.3 +++ /dev/null @@ -1,102 +0,0 @@ -.TH IPSEC_KEYBLOBTOID 3 "25 March 2002" -.SH NAME -ipsec keyblobtoid, splitkeytoid \- generate key IDs from RSA keys -.SH SYNOPSIS -.B "#include <freeswan.h> -.sp -.B "size_t keyblobtoid(const unsigned char *blob," -.ti +1c -.B "size_t bloblen, char *dst, size_t dstlen);" -.br -.B "size_t splitkeytoid(const unsigned char *e, size_t elen," -.ti +1c -.B "const unsigned char *m, size_t mlen, char *dst, -.ti +1c -.B "size_t dstlen);" -.SH DESCRIPTION -.I Keyblobtoid -and -.I splitkeytoid -generate -key IDs -from RSA keys, -for use in messages and reporting, -writing the result to -.IR dst . -A -.I key ID -is a short ASCII string identifying a key; -currently it is just the first nine characters of the base64 -encoding of the RFC 2537/3110 ``byte blob'' representation of the key. -(Beware that no finite key ID can be collision-proof: -there is always some small chance of two random keys having the -same ID.) -.PP -.I Keyblobtoid -generates a key ID from a key which is already in the form of an -RFC 2537/3110 binary key -.I blob -(encoded exponent length, exponent, modulus). -.PP -.I Splitkeytoid -generates a key ID from a key given in the form of a separate -(binary) exponent -.I e -and modulus -.IR m . -.PP -The -.I dstlen -parameter of either -specifies the size of the -.I dst -parameter; -under no circumstances are more than -.I dstlen -bytes written to -.IR dst . -A result which will not fit is truncated. -.I Dstlen -can be zero, in which case -.I dst -need not be valid and no result is written, -but the return value is unaffected; -in all other cases, the (possibly truncated) result is NUL-terminated. -The -.I freeswan.h -header file defines a constant -.B KEYID_BUF -which is the size of a buffer large enough for worst-case results. -.PP -Both functions return -.B 0 -for a failure, and otherwise -always return the size of buffer which would -be needed to -accommodate the full conversion result, including terminating NUL; -it is the caller's responsibility to check this against the size of -the provided buffer to determine whether truncation has occurred. -.P -With keys generated by -.IR ipsec_rsasigkey (3), -the first two base64 digits are always the same, -and the third carries only about one bit of information. -It's worse with keys using longer fixed exponents, -e.g. the 24-bit exponent that's common in X.509 certificates. -However, being able to relate key IDs to the full -base64 text form of keys by eye is sufficiently useful that this -waste of space seems justifiable. -The choice of nine digits is a compromise between bulk and -probability of collision. -.SH SEE ALSO -RFC 3110, -\fIRSA/SHA-1 SIGs and RSA KEYs in the Domain Name System (DNS)\fR, -Eastlake, 2001 -(superseding the older but better-known RFC 2537). -.SH DIAGNOSTICS -Fatal errors are: -key too short to supply enough bits to construct a complete key ID -(almost certainly indicating a garbage key); -exponent too long for its length to be representable. -.SH HISTORY -Written for the FreeS/WAN project by Henry Spencer. diff --git a/src/libfreeswan/keyblobtoid.c b/src/libfreeswan/keyblobtoid.c deleted file mode 100644 index 89ab5fced..000000000 --- a/src/libfreeswan/keyblobtoid.c +++ /dev/null @@ -1,146 +0,0 @@ -/* - * generate printable key IDs - * Copyright (C) 2002 Henry Spencer. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Library 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/lgpl.txt>. - * - * This library 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 Library General Public - * License for more details. - */ -#include "internal.h" -#include "freeswan.h" - -/* - - keyblobtoid - generate a printable key ID from an RFC 2537/3110 key blob - * Current algorithm is just to use first nine base64 digits. - */ -size_t -keyblobtoid(src, srclen, dst, dstlen) -const unsigned char *src; -size_t srclen; -char *dst; /* need not be valid if dstlen is 0 */ -size_t dstlen; -{ - char buf[KEYID_BUF]; - size_t ret; -# define NDIG 9 - - if (srclen < (NDIG*6 + 7)/8) { - strcpy(buf, "?len= ?"); - buf[5] = '0' + srclen; - ret = 0; - } else { - (void) datatot(src, srclen, 64, buf, NDIG+1); - ret = NDIG+1; - } - - if (dstlen > 0) { - if (strlen(buf)+1 > dstlen) - *(buf + dstlen - 1) = '\0'; - strcpy(dst, buf); - } - return ret; -} - -/* - - splitkeytoid - generate a printable key ID from exponent/modulus pair - * Just constructs the beginnings of a key blob and calls keyblobtoid(). - */ -size_t -splitkeytoid(e, elen, m, mlen, dst, dstlen) -const unsigned char *e; -size_t elen; -const unsigned char *m; -size_t mlen; -char *dst; /* need not be valid if dstlen is 0 */ -size_t dstlen; -{ - unsigned char buf[KEYID_BUF]; /* ample room */ - unsigned char *bufend = buf + sizeof(buf); - unsigned char *p; - size_t n; - - p = buf; - if (elen <= 255) - *p++ = elen; - else if ((elen &~ 0xffff) == 0) { - *p++ = 0; - *p++ = (elen>>8) & 0xff; - *p++ = elen & 0xff; - } else - return 0; /* unrepresentable exponent length */ - - n = bufend - p; - if (elen < n) - n = elen; - memcpy(p, e, n); - p += n; - - n = bufend - p; - if (n > 0) { - if (mlen < n) - n = mlen; - memcpy(p, m, n); - p += n; - } - - return keyblobtoid(buf, p - buf, dst, dstlen); -} - - - -#ifdef KEYBLOBTOID_MAIN - -#include <stdio.h> - -void regress(); - -int -main(argc, argv) -int argc; -char *argv[]; -{ - typedef unsigned char uc; - uc hexblob[] = "\x01\x03\x85\xf2\xd6\x76\x9b\x03\x59\xb6\x21\x52"; - uc hexe[] = "\x03"; - uc hexm[] = "\x85\xf2\xd6\x76\x9b\x03\x59\xb6\x21\x52\xef\x85"; - char b64nine[] = "AQOF8tZ2m"; - char b64six[] = "AQOF8t"; - char buf[100]; - size_t n; - char *b = b64nine; - size_t bl = strlen(b) + 1; - int st = 0; - - n = keyblobtoid(hexblob, strlen(hexblob), buf, sizeof(buf)); - if (n != bl) { - fprintf(stderr, "%s: keyblobtoid returned %d not %d\n", - argv[0], n, bl); - st = 1; - } - if (strcmp(buf, b) != 0) { - fprintf(stderr, "%s: keyblobtoid generated `%s' not `%s'\n", - argv[0], buf, b); - st = 1; - } - n = splitkeytoid(hexe, strlen(hexe), hexm, strlen(hexm), buf, - sizeof(buf)); - if (n != bl) { - fprintf(stderr, "%s: splitkeytoid returned %d not %d\n", - argv[0], n, bl); - st = 1; - } - if (strcmp(buf, b) != 0) { - fprintf(stderr, "%s: splitkeytoid generated `%s' not `%s'\n", - argv[0], buf, b); - st = 1; - } - exit(st); -} - -#endif /* KEYBLOBTOID_MAIN */ diff --git a/src/libfreeswan/prng.3 b/src/libfreeswan/prng.3 deleted file mode 100644 index 48c6ceed0..000000000 --- a/src/libfreeswan/prng.3 +++ /dev/null @@ -1,120 +0,0 @@ -.TH IPSEC_PRNG 3 "1 April 2002" -.SH NAME -ipsec prng_init \- initialize IPsec pseudorandom-number generator -.br -ipsec prng_bytes \- get bytes from IPsec pseudorandom-number generator -.br -ipsec prng_final \- close down IPsec pseudorandom-number generator -.SH SYNOPSIS -.B "#include <freeswan.h> -.sp -.B "void prng_init(struct prng *prng," -.ti +1c -.B "const unsigned char *key, size_t keylen);" -.br -.B "void prng_bytes(struct prng *prng, char *dst," -.ti +1c -.B "size_t dstlen);" -.br -.B "unsigned long prng_count(struct prng *prng);" -.br -.B "void prng_final(struct prng *prng);" -.SH DESCRIPTION -.I Prng_init -initializes a crypto-quality pseudo-random-number generator from a key; -.I prng_bytes -obtains pseudo-random bytes from it; -.I prng_count -reports the number of bytes extracted from it to date; -.I prng_final -closes it down. -It is the user's responsibility to initialize a PRNG before using it, -and not to use it again after it is closed down. -.PP -.I Prng_init -initializes, -or re-initializes, -the specified -.I prng -from the -.IR key , -whose length is given by -.IR keylen . -The user must allocate the -.B "struct prng" -pointed to by -.IR prng . -There is no particular constraint on the length of the key, -although a key longer than 256 bytes is unnecessary because -only the first 256 would be used. -Initialization requires on the order of 3000 integer operations, -independent of key length. -.PP -.I Prng_bytes -obtains -.I dstlen -pseudo-random bytes from the PRNG and puts them in -.IR buf . -This is quite fast, -on the order of 10 integer operations per byte. -.PP -.I Prng_count -reports the number of bytes obtained from the PRNG -since it was (last) initialized. -.PP -.I Prng_final -closes down a PRNG by -zeroing its internal memory, -obliterating all trace of the state used to generate its previous output. -This requires on the order of 250 integer operations. -.PP -The -.B <freeswan.h> -header file supplies the definition of the -.B prng -structure. -Examination of its innards is discouraged, as they may change. -.PP -The PRNG algorithm -used by these functions is currently identical to that of RC4(TM). -This algorithm is cryptographically strong, -sufficiently unpredictable that even a hostile observer will -have difficulty determining the next byte of output from past history, -provided it is initialized from a reasonably large key composed of -highly random bytes (see -.IR random (4)). -The usual run of software pseudo-random-number generators -(e.g. -.IR random (3)) -are -.I not -cryptographically strong. -.PP -The well-known attacks against RC4(TM), -e.g. as found in 802.11b's WEP encryption system, -apply only if multiple PRNGs are initialized with closely-related keys -(e.g., using a counter appended to a base key). -If such keys are used, the first few hundred pseudo-random bytes -from each PRNG should be discarded, -to give the PRNGs a chance to randomize their innards properly. -No useful attacks are known if the key is well randomized to begin with. -.SH SEE ALSO -random(3), random(4) -.br -Bruce Schneier, -\fIApplied Cryptography\fR, 2nd ed., 1996, ISBN 0-471-11709-9, -pp. 397-8. -.SH HISTORY -Written for the FreeS/WAN project by Henry Spencer. -.SH BUGS -If an attempt is made to obtain more than 4e9 bytes -between initializations, -the PRNG will continue to work but -.IR prng_count 's -output will stick at -.BR 4000000000 . -Fixing this would require a longer integer type and does -not seem worth the trouble, -since you should probably re-initialize before then anyway... -.PP -``RC4'' is a trademark of RSA Data Security, Inc. diff --git a/src/libfreeswan/prng.c b/src/libfreeswan/prng.c deleted file mode 100644 index 347f13f89..000000000 --- a/src/libfreeswan/prng.c +++ /dev/null @@ -1,200 +0,0 @@ -/* - * crypto-class pseudorandom number generator - * currently uses same algorithm as RC4(TM), from Schneier 2nd ed p397 - * Copyright (C) 2002 Henry Spencer. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Library 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/lgpl.txt>. - * - * This library 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 Library General Public - * License for more details. - */ -#include "internal.h" -#include "freeswan.h" - -/* - - prng_init - initialize PRNG from a key - */ -void -prng_init(prng, key, keylen) -struct prng *prng; -const unsigned char *key; -size_t keylen; -{ - unsigned char k[256]; - int i, j; - unsigned const char *p; - unsigned const char *keyend = key + keylen; - unsigned char t; - - for (i = 0; i <= 255; i++) - prng->sbox[i] = i; - p = key; - for (i = 0; i <= 255; i++) { - k[i] = *p++; - if (p >= keyend) - p = key; - } - j = 0; - for (i = 0; i <= 255; i++) { - j = (j + prng->sbox[i] + k[i]) & 0xff; - t = prng->sbox[i]; - prng->sbox[i] = prng->sbox[j]; - prng->sbox[j] = t; - k[i] = 0; /* clear out key memory */ - } - prng->i = 0; - prng->j = 0; - prng->count = 0; -} - -/* - - prng_bytes - get some pseudorandom bytes from PRNG - */ -void -prng_bytes(prng, dst, dstlen) -struct prng *prng; -unsigned char *dst; -size_t dstlen; -{ - int i, j, t; - unsigned char *p = dst; - size_t remain = dstlen; -# define MAX 4000000000ul - - while (remain > 0) { - i = (prng->i + 1) & 0xff; - prng->i = i; - j = (prng->j + prng->sbox[i]) & 0xff; - prng->j = j; - t = prng->sbox[i]; - prng->sbox[i] = prng->sbox[j]; - prng->sbox[j] = t; - t = (t + prng->sbox[i]) & 0xff; - *p++ = prng->sbox[t]; - remain--; - } - if (prng->count < MAX - dstlen) - prng->count += dstlen; - else - prng->count = MAX; -} - -/* - - prnt_count - how many bytes have been extracted from PRNG so far? - */ -unsigned long -prng_count(prng) -struct prng *prng; -{ - return prng->count; -} - -/* - - prng_final - clear out PRNG to ensure nothing left in memory - */ -void -prng_final(prng) -struct prng *prng; -{ - int i; - - for (i = 0; i <= 255; i++) - prng->sbox[i] = 0; - prng->i = 0; - prng->j = 0; - prng->count = 0; /* just for good measure */ -} - - - -#ifdef PRNG_MAIN - -#include <stdio.h> - -void regress(); - -int -main(argc, argv) -int argc; -char *argv[]; -{ - struct prng pr; - unsigned char buf[100]; - unsigned char *p; - size_t n; - - if (argc < 2) { - fprintf(stderr, "Usage: %s {key|-r}\n", argv[0]); - exit(2); - } - - if (strcmp(argv[1], "-r") == 0) { - regress(); - fprintf(stderr, "regress() returned?!?\n"); - exit(1); - } - - prng_init(&pr, argv[1], strlen(argv[1])); - prng_bytes(&pr, buf, 32); - printf("0x"); - for (p = buf, n = 32; n > 0; p++, n--) - printf("%02x", *p); - printf("\n%lu bytes\n", prng_count(&pr)); - prng_final(&pr); - exit(0); -} - -void -regress() -{ - struct prng pr; - unsigned char buf[100]; - unsigned char *p; - size_t n; - /* somewhat non-random sample key */ - unsigned char key[] = "here we go gathering nuts in May"; - /* first thirty bytes of output from that key */ - unsigned char good[] = "\x3f\x02\x8e\x4a\x2a\xea\x23\x18\x92\x7c" - "\x09\x52\x83\x61\xaa\x26\xce\xbb\x9d\x71" - "\x71\xe5\x10\x22\xaf\x60\x54\x8d\x5b\x28"; - int nzero, none; - int show = 0; - - prng_init(&pr, key, strlen(key)); - prng_bytes(&pr, buf, sizeof(buf)); - for (p = buf, n = sizeof(buf); n > 0; p++, n--) { - if (*p == 0) - nzero++; - if (*p == 255) - none++; - } - if (nzero > 3 || none > 3) { - fprintf(stderr, "suspiciously non-random output!\n"); - show = 1; - } - if (memcmp(buf, good, strlen(good)) != 0) { - fprintf(stderr, "incorrect output!\n"); - show = 1; - } - if (show) { - fprintf(stderr, "0x"); - for (p = buf, n = sizeof(buf); n > 0; p++, n--) - fprintf(stderr, "%02x", *p); - fprintf(stderr, "\n"); - exit(1); - } - if (prng_count(&pr) != sizeof(buf)) { - fprintf(stderr, "got %u bytes, but count is %lu\n", - sizeof(buf), prng_count(&pr)); - exit(1); - } - prng_final(&pr); - exit(0); -} - -#endif /* PRNG_MAIN */ diff --git a/src/libfreeswan/satoa.c b/src/libfreeswan/satoa.c deleted file mode 100644 index 09a152727..000000000 --- a/src/libfreeswan/satoa.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - * convert from binary form of SA ID to ASCII - * Copyright (C) 1998, 1999, 2001 Henry Spencer. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Library 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/lgpl.txt>. - * - * This library 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 Library General Public - * License for more details. - */ -#include "internal.h" -#include "freeswan.h" - -static struct typename { - char type; - char *name; -} typenames[] = { - { SA_AH, "ah" }, - { SA_ESP, "esp" }, - { SA_IPIP, "tun" }, - { SA_COMP, "comp" }, - { SA_INT, "int" }, - { 0, NULL } -}; - -/* - - satoa - convert SA to ASCII "ah507@1.2.3.4" - */ -size_t /* space needed for full conversion */ -satoa(sa, format, dst, dstlen) -struct sa_id sa; -int format; /* character */ -char *dst; /* need not be valid if dstlen is 0 */ -size_t dstlen; -{ - size_t len = 0; /* 0 means not handled yet */ - int base; - struct typename *tn; - char buf[30+ADDRTOA_BUF]; - - switch (format) { - case 0: - base = 16; /* temporarily at least */ - break; - case 'd': - base = 10; - break; - default: - return 0; - break; - } - - for (tn = typenames; tn->name != NULL; tn++) - if (sa.proto == tn->type) - break; - if (tn->name == NULL) - return 0; - - if (strcmp(tn->name, PASSTHROUGHTYPE) == 0 && - sa.spi == PASSTHROUGHSPI && - sa.dst.s_addr == PASSTHROUGHDST) { - strcpy(buf, PASSTHROUGHNAME); - len = strlen(buf); - } else if (sa.proto == SA_INT && sa.dst.s_addr == 0) { - char *p; - - switch (ntohl(sa.spi)) { - case SPI_PASS: p = "%pass"; break; - case SPI_DROP: p = "%drop"; break; - case SPI_REJECT: p = "%reject"; break; - case SPI_HOLD: p = "%hold"; break; - case SPI_TRAP: p = "%trap"; break; - case SPI_TRAPSUBNET: p = "%trapsubnet"; break; - default: p = NULL; break; - } - if (p != NULL) { - strcpy(buf, p); - len = strlen(buf); - } - } - - if (len == 0) { - strcpy(buf, tn->name); - len = strlen(buf); - len += ultoa(ntohl(sa.spi), base, buf+len, sizeof(buf)-len); - *(buf+len-1) = '@'; - len += addrtoa(sa.dst, 0, buf+len, sizeof(buf)-len); - } - - if (dst != NULL) { - if (len > dstlen) - *(buf+dstlen-1) = '\0'; - strcpy(dst, buf); - } - return len; -} diff --git a/src/libhydra/Makefile.in b/src/libhydra/Makefile.in index 8e5697b79..8b1e7384f 100644 --- a/src/libhydra/Makefile.in +++ b/src/libhydra/Makefile.in @@ -271,9 +271,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -312,6 +310,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libhydra/kernel/kernel_interface.c b/src/libhydra/kernel/kernel_interface.c index 3e6d46205..4fd5a7535 100644 --- a/src/libhydra/kernel/kernel_interface.c +++ b/src/libhydra/kernel/kernel_interface.c @@ -78,8 +78,8 @@ METHOD(kernel_interface_t, get_cpi, status_t, METHOD(kernel_interface_t, add_sa, status_t, private_kernel_interface_t *this, host_t *src, host_t *dst, - u_int32_t spi, u_int8_t protocol, u_int32_t reqid, - mark_t mark, lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key, + u_int32_t spi, u_int8_t protocol, u_int32_t reqid, mark_t mark, + u_int32_t tfc, lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key, u_int16_t int_alg, chunk_t int_key, ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi, bool encap, bool inbound, traffic_selector_t *src_ts, traffic_selector_t *dst_ts) @@ -89,8 +89,8 @@ METHOD(kernel_interface_t, add_sa, status_t, return NOT_SUPPORTED; } return this->ipsec->add_sa(this->ipsec, src, dst, spi, protocol, reqid, - mark, lifetime, enc_alg, enc_key, int_alg, int_key, mode, ipcomp, - cpi, encap, inbound, src_ts, dst_ts); + mark, tfc, lifetime, enc_alg, enc_key, int_alg, int_key, mode, + ipcomp, cpi, encap, inbound, src_ts, dst_ts); } METHOD(kernel_interface_t, update_sa, status_t, diff --git a/src/libhydra/kernel/kernel_interface.h b/src/libhydra/kernel/kernel_interface.h index 8b0c7a296..ec73fa1f7 100644 --- a/src/libhydra/kernel/kernel_interface.h +++ b/src/libhydra/kernel/kernel_interface.h @@ -91,6 +91,7 @@ struct kernel_interface_t { * @param protocol protocol for this SA (ESP/AH) * @param reqid unique ID for this SA * @param mark optional mark for this SA + * @param tfc Traffic Flow Confidentiality padding for this SA * @param lifetime lifetime_cfg_t for this SA * @param enc_alg Algorithm to use for encryption (ESP only) * @param enc_key key to use for encryption @@ -108,7 +109,7 @@ struct kernel_interface_t { status_t (*add_sa) (kernel_interface_t *this, host_t *src, host_t *dst, u_int32_t spi, u_int8_t protocol, u_int32_t reqid, mark_t mark, - lifetime_cfg_t *lifetime, + u_int32_t tfc, lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key, u_int16_t int_alg, chunk_t int_key, ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi, diff --git a/src/libhydra/kernel/kernel_ipsec.h b/src/libhydra/kernel/kernel_ipsec.h index 49d9cc07a..3e2d8b9ce 100644 --- a/src/libhydra/kernel/kernel_ipsec.h +++ b/src/libhydra/kernel/kernel_ipsec.h @@ -204,6 +204,7 @@ struct kernel_ipsec_t { * @param protocol protocol for this SA (ESP/AH) * @param reqid unique ID for this SA * @param mark mark for this SA + * @param tfc Traffic Flow Confidentiality padding for this SA * @param lifetime lifetime_cfg_t for this SA * @param enc_alg Algorithm to use for encryption (ESP only) * @param enc_key key to use for encryption @@ -221,7 +222,7 @@ struct kernel_ipsec_t { status_t (*add_sa) (kernel_ipsec_t *this, host_t *src, host_t *dst, u_int32_t spi, u_int8_t protocol, u_int32_t reqid, - mark_t mark, lifetime_cfg_t *lifetime, + mark_t mark, u_int32_t tfc, lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key, u_int16_t int_alg, chunk_t int_key, ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi, diff --git a/src/libhydra/plugins/attr/Makefile.in b/src/libhydra/plugins/attr/Makefile.in index 72182e57f..2da06a89c 100644 --- a/src/libhydra/plugins/attr/Makefile.in +++ b/src/libhydra/plugins/attr/Makefile.in @@ -219,9 +219,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -260,6 +258,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libhydra/plugins/attr/attr_plugin.c b/src/libhydra/plugins/attr/attr_plugin.c index 24c00bb44..0f66b680a 100644 --- a/src/libhydra/plugins/attr/attr_plugin.c +++ b/src/libhydra/plugins/attr/attr_plugin.c @@ -36,10 +36,8 @@ struct private_attr_plugin_t { attr_provider_t *provider; }; -/** - * Implementation of plugin_t.destroy - */ -static void destroy(private_attr_plugin_t *this) +METHOD(plugin_t, destroy, void, + private_attr_plugin_t *this) { hydra->attributes->remove_provider(hydra->attributes, &this->provider->provider); this->provider->destroy(this->provider); @@ -51,11 +49,16 @@ static void destroy(private_attr_plugin_t *this) */ plugin_t *attr_plugin_create() { - private_attr_plugin_t *this = malloc_thing(private_attr_plugin_t); - - this->public.plugin.destroy = (void(*)(plugin_t*))destroy; + private_attr_plugin_t *this; - this->provider = attr_provider_create(); + INIT(this, + .public = { + .plugin = { + .destroy = _destroy, + }, + }, + .provider = attr_provider_create(), + ); hydra->attributes->add_provider(hydra->attributes, &this->provider->provider); return &this->public.plugin; diff --git a/src/libhydra/plugins/attr_sql/Makefile.in b/src/libhydra/plugins/attr_sql/Makefile.in index dfb41cc02..26e7a3038 100644 --- a/src/libhydra/plugins/attr_sql/Makefile.in +++ b/src/libhydra/plugins/attr_sql/Makefile.in @@ -232,9 +232,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -273,6 +271,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libhydra/plugins/attr_sql/attr_sql_plugin.c b/src/libhydra/plugins/attr_sql/attr_sql_plugin.c index 70e7a2247..ca9de023e 100644 --- a/src/libhydra/plugins/attr_sql/attr_sql_plugin.c +++ b/src/libhydra/plugins/attr_sql/attr_sql_plugin.c @@ -43,10 +43,8 @@ struct private_attr_sql_plugin_t { }; -/** - * Implementation of plugin_t.destroy - */ -static void destroy(private_attr_sql_plugin_t *this) +METHOD(plugin_t, destroy, void, + private_attr_sql_plugin_t *this) { hydra->attributes->remove_provider(hydra->attributes, &this->attribute->provider); this->attribute->destroy(this->attribute); @@ -59,21 +57,26 @@ static void destroy(private_attr_sql_plugin_t *this) */ plugin_t *attr_sql_plugin_create() { - char *uri; private_attr_sql_plugin_t *this; + char *uri; - uri = lib->settings->get_str(lib->settings, "libhydra.plugins.attr-sql.database", NULL); + uri = lib->settings->get_str(lib->settings, "libhydra.plugins.attr-sql.database", + NULL); if (!uri) { DBG1(DBG_CFG, "attr-sql plugin: database URI not set"); return NULL; } - this = malloc_thing(private_attr_sql_plugin_t); - - this->public.plugin.destroy = (void(*)(plugin_t*))destroy; + INIT(this, + .public = { + .plugin = { + .destroy = _destroy, + }, + }, + .db = lib->db->create(lib->db, uri), + ); - this->db = lib->db->create(lib->db, uri); if (!this->db) { DBG1(DBG_CFG, "attr-sql plugin failed to connect to database"); diff --git a/src/libhydra/plugins/kernel_klips/Makefile.in b/src/libhydra/plugins/kernel_klips/Makefile.in index a451bd6f5..7d2464456 100644 --- a/src/libhydra/plugins/kernel_klips/Makefile.in +++ b/src/libhydra/plugins/kernel_klips/Makefile.in @@ -223,9 +223,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -264,6 +262,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libhydra/plugins/kernel_klips/kernel_klips_ipsec.c b/src/libhydra/plugins/kernel_klips/kernel_klips_ipsec.c index 0ccb2ac5f..cf9a3e1fd 100644 --- a/src/libhydra/plugins/kernel_klips/kernel_klips_ipsec.c +++ b/src/libhydra/plugins/kernel_klips/kernel_klips_ipsec.c @@ -1668,7 +1668,7 @@ static status_t group_ipip_sa(private_kernel_klips_ipsec_t *this, METHOD(kernel_ipsec_t, add_sa, status_t, private_kernel_klips_ipsec_t *this, host_t *src, host_t *dst, u_int32_t spi, - u_int8_t protocol, u_int32_t reqid, mark_t mark, + u_int8_t protocol, u_int32_t reqid, mark_t mark, u_int32_t tfc, lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key, u_int16_t int_alg, chunk_t int_key, ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi, bool encap, bool inbound, diff --git a/src/libhydra/plugins/kernel_klips/kernel_klips_plugin.c b/src/libhydra/plugins/kernel_klips/kernel_klips_plugin.c index 1a22835c0..3c312ca2b 100644 --- a/src/libhydra/plugins/kernel_klips/kernel_klips_plugin.c +++ b/src/libhydra/plugins/kernel_klips/kernel_klips_plugin.c @@ -32,10 +32,8 @@ struct private_kernel_klips_plugin_t { kernel_klips_plugin_t public; }; -/** - * Implementation of plugin_t.destroy - */ -static void destroy(private_kernel_klips_plugin_t *this) +METHOD(plugin_t, destroy, void, + private_kernel_klips_plugin_t *this) { hydra->kernel_interface->remove_ipsec_interface(hydra->kernel_interface, (kernel_ipsec_constructor_t)kernel_klips_ipsec_create); @@ -47,10 +45,15 @@ static void destroy(private_kernel_klips_plugin_t *this) */ plugin_t *kernel_klips_plugin_create() { - private_kernel_klips_plugin_t *this = malloc_thing(private_kernel_klips_plugin_t); - - this->public.plugin.destroy = (void(*)(plugin_t*))destroy; - + private_kernel_klips_plugin_t *this; + + INIT(this, + .public = { + .plugin = { + .destroy = _destroy, + }, + }, + ); hydra->kernel_interface->add_ipsec_interface(hydra->kernel_interface, (kernel_ipsec_constructor_t)kernel_klips_ipsec_create); diff --git a/src/libhydra/plugins/kernel_netlink/Makefile.in b/src/libhydra/plugins/kernel_netlink/Makefile.in index d41ee1456..c7404fe06 100644 --- a/src/libhydra/plugins/kernel_netlink/Makefile.in +++ b/src/libhydra/plugins/kernel_netlink/Makefile.in @@ -224,9 +224,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -265,6 +263,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c b/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c index 8cc9a6283..4dc80785c 100644 --- a/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c +++ b/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c @@ -58,8 +58,8 @@ #endif /*IPV6_XFRM_POLICY*/ /** default priority of installed policies */ -#define PRIO_LOW 3000 -#define PRIO_HIGH 2000 +#define PRIO_LOW 1024 +#define PRIO_HIGH 512 /** * map the limit for bytes and packets to XFRM_INF per default @@ -866,7 +866,7 @@ METHOD(kernel_ipsec_t, get_cpi, status_t, METHOD(kernel_ipsec_t, add_sa, status_t, private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst, u_int32_t spi, u_int8_t protocol, u_int32_t reqid, mark_t mark, - lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key, + u_int32_t tfc, lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key, u_int16_t int_alg, chunk_t int_key, ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi, bool encap, bool inbound, traffic_selector_t* src_ts, traffic_selector_t* dst_ts) @@ -882,7 +882,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t, if (ipcomp != IPCOMP_NONE && cpi != 0) { lifetime_cfg_t lft = {{0,0,0},{0,0,0},{0,0,0}}; - add_sa(this, src, dst, htonl(ntohs(cpi)), IPPROTO_COMP, reqid, mark, + add_sa(this, src, dst, htonl(ntohs(cpi)), IPPROTO_COMP, reqid, mark, tfc, &lft, ENCR_UNDEFINED, chunk_empty, AUTH_UNDEFINED, chunk_empty, mode, ipcomp, 0, FALSE, inbound, NULL, NULL); ipcomp = IPCOMP_NONE; @@ -920,6 +920,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t, sa->flags |= XFRM_STATE_AF_UNSPEC; break; case MODE_BEET: + case MODE_TRANSPORT: if(src_ts && dst_ts) { sa->sel = ts2selector(src_ts, dst_ts); @@ -1153,6 +1154,24 @@ METHOD(kernel_ipsec_t, add_sa, status_t, rthdr = XFRM_RTA_NEXT(rthdr); } + if (tfc) + { + u_int32_t *tfcpad; + + rthdr->rta_type = XFRMA_TFCPAD; + rthdr->rta_len = RTA_LENGTH(sizeof(u_int32_t)); + + hdr->nlmsg_len += rthdr->rta_len; + if (hdr->nlmsg_len > sizeof(request)) + { + return FAILED; + } + + tfcpad = (u_int32_t*)RTA_DATA(rthdr); + *tfcpad = tfc; + rthdr = XFRM_RTA_NEXT(rthdr); + } + if (this->socket_xfrm->send_ack(this->socket_xfrm, hdr) != SUCCESS) { if (mark.value) @@ -1687,11 +1706,16 @@ METHOD(kernel_ipsec_t, add_policy, status_t, policy_info = (struct xfrm_userpolicy_info*)NLMSG_DATA(hdr); policy_info->sel = policy->sel; policy_info->dir = policy->direction; - /* calculate priority based on source selector size, small size = high prio */ + + /* calculate priority based on selector size, small size = high prio */ policy_info->priority = routed ? PRIO_LOW : PRIO_HIGH; - policy_info->priority -= policy->sel.prefixlen_s * 10; - policy_info->priority -= policy->sel.proto ? 2 : 0; - policy_info->priority -= policy->sel.sport_mask ? 1 : 0; + policy_info->priority -= policy->sel.prefixlen_s; + policy_info->priority -= policy->sel.prefixlen_d; + policy_info->priority <<= 2; /* make some room for the two flags */ + policy_info->priority += policy->sel.sport_mask || + policy->sel.dport_mask ? 0 : 2; + policy_info->priority += policy->sel.proto ? 0 : 1; + policy_info->action = type != POLICY_DROP ? XFRM_POLICY_ALLOW : XFRM_POLICY_BLOCK; policy_info->share = XFRM_SHARE_ANY; @@ -1813,6 +1837,8 @@ METHOD(kernel_ipsec_t, add_policy, status_t, if (route->if_name) { + DBG2(DBG_KNL, "installing route: %R via %H src %H dev %s", + src_ts, route->gateway, route->src_ip, route->if_name); switch (hydra->kernel_interface->add_route( hydra->kernel_interface, route->dst_net, route->prefixlen, route->gateway, diff --git a/src/libhydra/plugins/kernel_netlink/kernel_netlink_plugin.c b/src/libhydra/plugins/kernel_netlink/kernel_netlink_plugin.c index 212675d1a..9fc1a03f5 100644 --- a/src/libhydra/plugins/kernel_netlink/kernel_netlink_plugin.c +++ b/src/libhydra/plugins/kernel_netlink/kernel_netlink_plugin.c @@ -33,10 +33,8 @@ struct private_kernel_netlink_plugin_t { kernel_netlink_plugin_t public; }; -/** - * Implementation of plugin_t.destroy - */ -static void destroy(private_kernel_netlink_plugin_t *this) +METHOD(plugin_t, destroy, void, + private_kernel_netlink_plugin_t *this) { hydra->kernel_interface->remove_ipsec_interface(hydra->kernel_interface, (kernel_ipsec_constructor_t)kernel_netlink_ipsec_create); @@ -50,10 +48,15 @@ static void destroy(private_kernel_netlink_plugin_t *this) */ plugin_t *kernel_netlink_plugin_create() { - private_kernel_netlink_plugin_t *this = malloc_thing(private_kernel_netlink_plugin_t); - - this->public.plugin.destroy = (void(*)(plugin_t*))destroy; + private_kernel_netlink_plugin_t *this; + INIT(this, + .public = { + .plugin = { + .destroy = _destroy, + }, + }, + ); hydra->kernel_interface->add_ipsec_interface(hydra->kernel_interface, (kernel_ipsec_constructor_t)kernel_netlink_ipsec_create); hydra->kernel_interface->add_net_interface(hydra->kernel_interface, diff --git a/src/libhydra/plugins/kernel_pfkey/Makefile.in b/src/libhydra/plugins/kernel_pfkey/Makefile.in index a98ae42d1..40363f319 100644 --- a/src/libhydra/plugins/kernel_pfkey/Makefile.in +++ b/src/libhydra/plugins/kernel_pfkey/Makefile.in @@ -223,9 +223,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -264,6 +262,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c b/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c index f5786447b..681811528 100644 --- a/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c +++ b/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c @@ -99,8 +99,8 @@ #endif /** default priority of installed policies */ -#define PRIO_LOW 3000 -#define PRIO_HIGH 2000 +#define PRIO_LOW 1024 +#define PRIO_HIGH 512 #ifdef __APPLE__ /** from xnu/bsd/net/pfkeyv2.h */ @@ -1206,7 +1206,7 @@ METHOD(kernel_ipsec_t, get_cpi, status_t, METHOD(kernel_ipsec_t, add_sa, status_t, private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst, u_int32_t spi, - u_int8_t protocol, u_int32_t reqid, mark_t mark, + u_int8_t protocol, u_int32_t reqid, mark_t mark, u_int32_t tfc, lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key, u_int16_t int_alg, chunk_t int_key, ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi, bool encap, bool inbound, @@ -1651,11 +1651,14 @@ METHOD(kernel_ipsec_t, add_policy, status_t, pol->sadb_x_policy_dir = dir2kernel(direction); pol->sadb_x_policy_type = IPSEC_POLICY_IPSEC; #ifdef HAVE_STRUCT_SADB_X_POLICY_SADB_X_POLICY_PRIORITY - /* calculate priority based on source selector size, small size = high prio */ + /* calculate priority based on selector size, small size = high prio */ pol->sadb_x_policy_priority = routed ? PRIO_LOW : PRIO_HIGH; - pol->sadb_x_policy_priority -= policy->src.mask * 10; - pol->sadb_x_policy_priority -= policy->src.proto != IPSEC_PROTO_ANY ? 2 : 0; - pol->sadb_x_policy_priority -= policy->src.net->get_port(policy->src.net) ? 1 : 0; + pol->sadb_x_policy_priority -= policy->src.mask; + pol->sadb_x_policy_priority -= policy->dst.mask; + pol->sadb_x_policy_priority <<= 2; /* make some room for the flags */ + pol->sadb_x_policy_priority += policy->src.net->get_port(policy->src.net) || + policy->dst.net->get_port(policy->dst.net) ? 0 : 2; + pol->sadb_x_policy_priority += policy->src.proto != IPSEC_PROTO_ANY ? 0 : 1; #endif /* one or more sadb_x_ipsecrequest extensions are added to the sadb_x_policy extension */ diff --git a/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_plugin.c b/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_plugin.c index 781ba5008..9e7a7904d 100644 --- a/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_plugin.c +++ b/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_plugin.c @@ -32,10 +32,8 @@ struct private_kernel_pfkey_plugin_t { kernel_pfkey_plugin_t public; }; -/** - * Implementation of plugin_t.destroy - */ -static void destroy(private_kernel_pfkey_plugin_t *this) +METHOD(plugin_t, destroy, void, + private_kernel_pfkey_plugin_t *this) { hydra->kernel_interface->remove_ipsec_interface(hydra->kernel_interface, (kernel_ipsec_constructor_t)kernel_pfkey_ipsec_create); @@ -47,10 +45,15 @@ static void destroy(private_kernel_pfkey_plugin_t *this) */ plugin_t *kernel_pfkey_plugin_create() { - private_kernel_pfkey_plugin_t *this = malloc_thing(private_kernel_pfkey_plugin_t); - - this->public.plugin.destroy = (void(*)(plugin_t*))destroy; - + private_kernel_pfkey_plugin_t *this; + + INIT(this, + .public = { + .plugin = { + .destroy = _destroy, + }, + }, + ); hydra->kernel_interface->add_ipsec_interface(hydra->kernel_interface, (kernel_ipsec_constructor_t)kernel_pfkey_ipsec_create); diff --git a/src/libhydra/plugins/kernel_pfroute/Makefile.in b/src/libhydra/plugins/kernel_pfroute/Makefile.in index b0bc00c70..4db374b75 100644 --- a/src/libhydra/plugins/kernel_pfroute/Makefile.in +++ b/src/libhydra/plugins/kernel_pfroute/Makefile.in @@ -223,9 +223,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -264,6 +262,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libhydra/plugins/kernel_pfroute/kernel_pfroute_plugin.c b/src/libhydra/plugins/kernel_pfroute/kernel_pfroute_plugin.c index 5f351bd72..a4cb53edd 100644 --- a/src/libhydra/plugins/kernel_pfroute/kernel_pfroute_plugin.c +++ b/src/libhydra/plugins/kernel_pfroute/kernel_pfroute_plugin.c @@ -32,10 +32,8 @@ struct private_kernel_pfroute_plugin_t { kernel_pfroute_plugin_t public; }; -/** - * Implementation of plugin_t.destroy - */ -static void destroy(private_kernel_pfroute_plugin_t *this) +METHOD(plugin_t, destroy, void, + private_kernel_pfroute_plugin_t *this) { hydra->kernel_interface->remove_net_interface(hydra->kernel_interface, (kernel_net_constructor_t)kernel_pfroute_net_create); @@ -47,10 +45,15 @@ static void destroy(private_kernel_pfroute_plugin_t *this) */ plugin_t *kernel_pfroute_plugin_create() { - private_kernel_pfroute_plugin_t *this = malloc_thing(private_kernel_pfroute_plugin_t); - - this->public.plugin.destroy = (void(*)(plugin_t*))destroy; - + private_kernel_pfroute_plugin_t *this; + + INIT(this, + .public = { + .plugin = { + .destroy = _destroy, + }, + }, + ); hydra->kernel_interface->add_net_interface(hydra->kernel_interface, (kernel_net_constructor_t)kernel_pfroute_net_create); diff --git a/src/libhydra/plugins/resolve/Makefile.in b/src/libhydra/plugins/resolve/Makefile.in index aedc8fdb7..e6c5fb712 100644 --- a/src/libhydra/plugins/resolve/Makefile.in +++ b/src/libhydra/plugins/resolve/Makefile.in @@ -222,9 +222,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -263,6 +261,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libhydra/plugins/resolve/resolve_plugin.c b/src/libhydra/plugins/resolve/resolve_plugin.c index 502129593..ad18c7060 100644 --- a/src/libhydra/plugins/resolve/resolve_plugin.c +++ b/src/libhydra/plugins/resolve/resolve_plugin.c @@ -36,10 +36,8 @@ struct private_resolve_plugin_t { resolve_handler_t *handler; }; -/** - * Implementation of plugin_t.destroy - */ -static void destroy(private_resolve_plugin_t *this) +METHOD(plugin_t, destroy, void, + private_resolve_plugin_t *this) { hydra->attributes->remove_handler(hydra->attributes, &this->handler->handler); this->handler->destroy(this->handler); @@ -51,10 +49,16 @@ static void destroy(private_resolve_plugin_t *this) */ plugin_t *resolve_plugin_create() { - private_resolve_plugin_t *this = malloc_thing(private_resolve_plugin_t); + private_resolve_plugin_t *this; - this->public.plugin.destroy = (void(*)(plugin_t*))destroy; - this->handler = resolve_handler_create(); + INIT(this, + .public = { + .plugin = { + .destroy = _destroy, + }, + }, + .handler = resolve_handler_create(), + ); hydra->attributes->add_handler(hydra->attributes, &this->handler->handler); return &this->public.plugin; diff --git a/src/libsimaka/Makefile.in b/src/libsimaka/Makefile.in index 0aa509acc..ef7a6ee38 100644 --- a/src/libsimaka/Makefile.in +++ b/src/libsimaka/Makefile.in @@ -192,9 +192,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -233,6 +231,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libstrongswan/Makefile.am b/src/libstrongswan/Makefile.am index 2ab8aa636..6a29d8eea 100644 --- a/src/libstrongswan/Makefile.am +++ b/src/libstrongswan/Makefile.am @@ -30,8 +30,7 @@ credentials/keys/private_key.c credentials/keys/private_key.h \ credentials/keys/public_key.c credentials/keys/public_key.h \ credentials/keys/shared_key.c credentials/keys/shared_key.h \ credentials/certificates/certificate.c credentials/certificates/certificate.h \ -credentials/certificates/x509.h credentials/certificates/x509.c \ -credentials/certificates/ac.h \ +credentials/certificates/x509.h credentials/certificates/ac.h \ credentials/certificates/crl.h credentials/certificates/crl.c \ credentials/certificates/pkcs10.h \ credentials/certificates/ocsp_request.h \ @@ -136,6 +135,13 @@ else SUBDIRS = . endif +if USE_AF_ALG + SUBDIRS += plugins/af_alg +if MONOLITHIC + libstrongswan_la_LIBADD += plugins/af_alg/libstrongswan-af-alg.la +endif +endif + if USE_AES SUBDIRS += plugins/aes if MONOLITHIC @@ -227,6 +233,13 @@ if MONOLITHIC endif endif +if USE_CONSTRAINTS + SUBDIRS += plugins/constraints +if MONOLITHIC + libstrongswan_la_LIBADD += plugins/constraints/libstrongswan-constraints.la +endif +endif + if USE_PUBKEY SUBDIRS += plugins/pubkey if MONOLITHIC @@ -269,6 +282,13 @@ if MONOLITHIC endif endif +if USE_SOUP + SUBDIRS += plugins/soup +if MONOLITHIC + libstrongswan_la_LIBADD += plugins/soup/libstrongswan-soup.la +endif +endif + if USE_LDAP SUBDIRS += plugins/ldap if MONOLITHIC diff --git a/src/libstrongswan/Makefile.in b/src/libstrongswan/Makefile.in index 8be6dd9b8..76b4f70c6 100644 --- a/src/libstrongswan/Makefile.in +++ b/src/libstrongswan/Makefile.in @@ -44,70 +44,76 @@ host_triplet = @host@ @USE_INTEGRITY_TEST_TRUE@ integrity_checker.c integrity_checker.h @USE_VSTR_TRUE@am__append_6 = -lvstr -@USE_AES_TRUE@am__append_7 = plugins/aes -@MONOLITHIC_TRUE@@USE_AES_TRUE@am__append_8 = plugins/aes/libstrongswan-aes.la -@USE_DES_TRUE@am__append_9 = plugins/des -@MONOLITHIC_TRUE@@USE_DES_TRUE@am__append_10 = plugins/des/libstrongswan-des.la -@USE_BLOWFISH_TRUE@am__append_11 = plugins/blowfish -@MONOLITHIC_TRUE@@USE_BLOWFISH_TRUE@am__append_12 = plugins/blowfish/libstrongswan-blowfish.la -@USE_MD4_TRUE@am__append_13 = plugins/md4 -@MONOLITHIC_TRUE@@USE_MD4_TRUE@am__append_14 = plugins/md4/libstrongswan-md4.la -@USE_MD5_TRUE@am__append_15 = plugins/md5 -@MONOLITHIC_TRUE@@USE_MD5_TRUE@am__append_16 = plugins/md5/libstrongswan-md5.la -@USE_SHA1_TRUE@am__append_17 = plugins/sha1 -@MONOLITHIC_TRUE@@USE_SHA1_TRUE@am__append_18 = plugins/sha1/libstrongswan-sha1.la -@USE_SHA2_TRUE@am__append_19 = plugins/sha2 -@MONOLITHIC_TRUE@@USE_SHA2_TRUE@am__append_20 = plugins/sha2/libstrongswan-sha2.la -@USE_GMP_TRUE@am__append_21 = plugins/gmp -@MONOLITHIC_TRUE@@USE_GMP_TRUE@am__append_22 = plugins/gmp/libstrongswan-gmp.la -@USE_RANDOM_TRUE@am__append_23 = plugins/random -@MONOLITHIC_TRUE@@USE_RANDOM_TRUE@am__append_24 = plugins/random/libstrongswan-random.la -@USE_HMAC_TRUE@am__append_25 = plugins/hmac -@MONOLITHIC_TRUE@@USE_HMAC_TRUE@am__append_26 = plugins/hmac/libstrongswan-hmac.la -@USE_XCBC_TRUE@am__append_27 = plugins/xcbc -@MONOLITHIC_TRUE@@USE_XCBC_TRUE@am__append_28 = plugins/xcbc/libstrongswan-xcbc.la -@USE_X509_TRUE@am__append_29 = plugins/x509 -@MONOLITHIC_TRUE@@USE_X509_TRUE@am__append_30 = plugins/x509/libstrongswan-x509.la -@USE_REVOCATION_TRUE@am__append_31 = plugins/revocation -@MONOLITHIC_TRUE@@USE_REVOCATION_TRUE@am__append_32 = plugins/revocation/libstrongswan-revocation.la -@USE_PUBKEY_TRUE@am__append_33 = plugins/pubkey -@MONOLITHIC_TRUE@@USE_PUBKEY_TRUE@am__append_34 = plugins/pubkey/libstrongswan-pubkey.la -@USE_PKCS1_TRUE@am__append_35 = plugins/pkcs1 -@MONOLITHIC_TRUE@@USE_PKCS1_TRUE@am__append_36 = plugins/pkcs1/libstrongswan-pkcs1.la -@USE_PGP_TRUE@am__append_37 = plugins/pgp -@MONOLITHIC_TRUE@@USE_PGP_TRUE@am__append_38 = plugins/pgp/libstrongswan-pgp.la -@USE_DNSKEY_TRUE@am__append_39 = plugins/dnskey -@MONOLITHIC_TRUE@@USE_DNSKEY_TRUE@am__append_40 = plugins/dnskey/libstrongswan-dnskey.la -@USE_PEM_TRUE@am__append_41 = plugins/pem -@MONOLITHIC_TRUE@@USE_PEM_TRUE@am__append_42 = plugins/pem/libstrongswan-pem.la -@USE_CURL_TRUE@am__append_43 = plugins/curl -@MONOLITHIC_TRUE@@USE_CURL_TRUE@am__append_44 = plugins/curl/libstrongswan-curl.la -@USE_LDAP_TRUE@am__append_45 = plugins/ldap -@MONOLITHIC_TRUE@@USE_LDAP_TRUE@am__append_46 = plugins/ldap/libstrongswan-ldap.la -@USE_MYSQL_TRUE@am__append_47 = plugins/mysql -@MONOLITHIC_TRUE@@USE_MYSQL_TRUE@am__append_48 = plugins/mysql/libstrongswan-mysql.la -@USE_SQLITE_TRUE@am__append_49 = plugins/sqlite -@MONOLITHIC_TRUE@@USE_SQLITE_TRUE@am__append_50 = plugins/sqlite/libstrongswan-sqlite.la -@USE_PADLOCK_TRUE@am__append_51 = plugins/padlock -@MONOLITHIC_TRUE@@USE_PADLOCK_TRUE@am__append_52 = plugins/padlock/libstrongswan-padlock.la -@USE_OPENSSL_TRUE@am__append_53 = plugins/openssl -@MONOLITHIC_TRUE@@USE_OPENSSL_TRUE@am__append_54 = plugins/openssl/libstrongswan-openssl.la -@USE_GCRYPT_TRUE@am__append_55 = plugins/gcrypt -@MONOLITHIC_TRUE@@USE_GCRYPT_TRUE@am__append_56 = plugins/gcrypt/libstrongswan-gcrypt.la -@USE_FIPS_PRF_TRUE@am__append_57 = plugins/fips_prf -@MONOLITHIC_TRUE@@USE_FIPS_PRF_TRUE@am__append_58 = plugins/fips_prf/libstrongswan-fips-prf.la -@USE_AGENT_TRUE@am__append_59 = plugins/agent -@MONOLITHIC_TRUE@@USE_AGENT_TRUE@am__append_60 = plugins/agent/libstrongswan-agent.la -@USE_PKCS11_TRUE@am__append_61 = plugins/pkcs11 -@MONOLITHIC_TRUE@@USE_PKCS11_TRUE@am__append_62 = plugins/pkcs11/libstrongswan-pkcs11.la -@USE_CTR_TRUE@am__append_63 = plugins/ctr -@MONOLITHIC_TRUE@@USE_CTR_TRUE@am__append_64 = plugins/ctr/libstrongswan-ctr.la -@USE_CCM_TRUE@am__append_65 = plugins/ccm -@MONOLITHIC_TRUE@@USE_CCM_TRUE@am__append_66 = plugins/ccm/libstrongswan-ccm.la -@USE_GCM_TRUE@am__append_67 = plugins/gcm -@MONOLITHIC_TRUE@@USE_GCM_TRUE@am__append_68 = plugins/gcm/libstrongswan-gcm.la -@USE_TEST_VECTORS_TRUE@am__append_69 = plugins/test_vectors -@MONOLITHIC_TRUE@@USE_TEST_VECTORS_TRUE@am__append_70 = plugins/test_vectors/libstrongswan-test-vectors.la +@USE_AF_ALG_TRUE@am__append_7 = plugins/af_alg +@MONOLITHIC_TRUE@@USE_AF_ALG_TRUE@am__append_8 = plugins/af_alg/libstrongswan-af-alg.la +@USE_AES_TRUE@am__append_9 = plugins/aes +@MONOLITHIC_TRUE@@USE_AES_TRUE@am__append_10 = plugins/aes/libstrongswan-aes.la +@USE_DES_TRUE@am__append_11 = plugins/des +@MONOLITHIC_TRUE@@USE_DES_TRUE@am__append_12 = plugins/des/libstrongswan-des.la +@USE_BLOWFISH_TRUE@am__append_13 = plugins/blowfish +@MONOLITHIC_TRUE@@USE_BLOWFISH_TRUE@am__append_14 = plugins/blowfish/libstrongswan-blowfish.la +@USE_MD4_TRUE@am__append_15 = plugins/md4 +@MONOLITHIC_TRUE@@USE_MD4_TRUE@am__append_16 = plugins/md4/libstrongswan-md4.la +@USE_MD5_TRUE@am__append_17 = plugins/md5 +@MONOLITHIC_TRUE@@USE_MD5_TRUE@am__append_18 = plugins/md5/libstrongswan-md5.la +@USE_SHA1_TRUE@am__append_19 = plugins/sha1 +@MONOLITHIC_TRUE@@USE_SHA1_TRUE@am__append_20 = plugins/sha1/libstrongswan-sha1.la +@USE_SHA2_TRUE@am__append_21 = plugins/sha2 +@MONOLITHIC_TRUE@@USE_SHA2_TRUE@am__append_22 = plugins/sha2/libstrongswan-sha2.la +@USE_GMP_TRUE@am__append_23 = plugins/gmp +@MONOLITHIC_TRUE@@USE_GMP_TRUE@am__append_24 = plugins/gmp/libstrongswan-gmp.la +@USE_RANDOM_TRUE@am__append_25 = plugins/random +@MONOLITHIC_TRUE@@USE_RANDOM_TRUE@am__append_26 = plugins/random/libstrongswan-random.la +@USE_HMAC_TRUE@am__append_27 = plugins/hmac +@MONOLITHIC_TRUE@@USE_HMAC_TRUE@am__append_28 = plugins/hmac/libstrongswan-hmac.la +@USE_XCBC_TRUE@am__append_29 = plugins/xcbc +@MONOLITHIC_TRUE@@USE_XCBC_TRUE@am__append_30 = plugins/xcbc/libstrongswan-xcbc.la +@USE_X509_TRUE@am__append_31 = plugins/x509 +@MONOLITHIC_TRUE@@USE_X509_TRUE@am__append_32 = plugins/x509/libstrongswan-x509.la +@USE_REVOCATION_TRUE@am__append_33 = plugins/revocation +@MONOLITHIC_TRUE@@USE_REVOCATION_TRUE@am__append_34 = plugins/revocation/libstrongswan-revocation.la +@USE_CONSTRAINTS_TRUE@am__append_35 = plugins/constraints +@MONOLITHIC_TRUE@@USE_CONSTRAINTS_TRUE@am__append_36 = plugins/constraints/libstrongswan-constraints.la +@USE_PUBKEY_TRUE@am__append_37 = plugins/pubkey +@MONOLITHIC_TRUE@@USE_PUBKEY_TRUE@am__append_38 = plugins/pubkey/libstrongswan-pubkey.la +@USE_PKCS1_TRUE@am__append_39 = plugins/pkcs1 +@MONOLITHIC_TRUE@@USE_PKCS1_TRUE@am__append_40 = plugins/pkcs1/libstrongswan-pkcs1.la +@USE_PGP_TRUE@am__append_41 = plugins/pgp +@MONOLITHIC_TRUE@@USE_PGP_TRUE@am__append_42 = plugins/pgp/libstrongswan-pgp.la +@USE_DNSKEY_TRUE@am__append_43 = plugins/dnskey +@MONOLITHIC_TRUE@@USE_DNSKEY_TRUE@am__append_44 = plugins/dnskey/libstrongswan-dnskey.la +@USE_PEM_TRUE@am__append_45 = plugins/pem +@MONOLITHIC_TRUE@@USE_PEM_TRUE@am__append_46 = plugins/pem/libstrongswan-pem.la +@USE_CURL_TRUE@am__append_47 = plugins/curl +@MONOLITHIC_TRUE@@USE_CURL_TRUE@am__append_48 = plugins/curl/libstrongswan-curl.la +@USE_SOUP_TRUE@am__append_49 = plugins/soup +@MONOLITHIC_TRUE@@USE_SOUP_TRUE@am__append_50 = plugins/soup/libstrongswan-soup.la +@USE_LDAP_TRUE@am__append_51 = plugins/ldap +@MONOLITHIC_TRUE@@USE_LDAP_TRUE@am__append_52 = plugins/ldap/libstrongswan-ldap.la +@USE_MYSQL_TRUE@am__append_53 = plugins/mysql +@MONOLITHIC_TRUE@@USE_MYSQL_TRUE@am__append_54 = plugins/mysql/libstrongswan-mysql.la +@USE_SQLITE_TRUE@am__append_55 = plugins/sqlite +@MONOLITHIC_TRUE@@USE_SQLITE_TRUE@am__append_56 = plugins/sqlite/libstrongswan-sqlite.la +@USE_PADLOCK_TRUE@am__append_57 = plugins/padlock +@MONOLITHIC_TRUE@@USE_PADLOCK_TRUE@am__append_58 = plugins/padlock/libstrongswan-padlock.la +@USE_OPENSSL_TRUE@am__append_59 = plugins/openssl +@MONOLITHIC_TRUE@@USE_OPENSSL_TRUE@am__append_60 = plugins/openssl/libstrongswan-openssl.la +@USE_GCRYPT_TRUE@am__append_61 = plugins/gcrypt +@MONOLITHIC_TRUE@@USE_GCRYPT_TRUE@am__append_62 = plugins/gcrypt/libstrongswan-gcrypt.la +@USE_FIPS_PRF_TRUE@am__append_63 = plugins/fips_prf +@MONOLITHIC_TRUE@@USE_FIPS_PRF_TRUE@am__append_64 = plugins/fips_prf/libstrongswan-fips-prf.la +@USE_AGENT_TRUE@am__append_65 = plugins/agent +@MONOLITHIC_TRUE@@USE_AGENT_TRUE@am__append_66 = plugins/agent/libstrongswan-agent.la +@USE_PKCS11_TRUE@am__append_67 = plugins/pkcs11 +@MONOLITHIC_TRUE@@USE_PKCS11_TRUE@am__append_68 = plugins/pkcs11/libstrongswan-pkcs11.la +@USE_CTR_TRUE@am__append_69 = plugins/ctr +@MONOLITHIC_TRUE@@USE_CTR_TRUE@am__append_70 = plugins/ctr/libstrongswan-ctr.la +@USE_CCM_TRUE@am__append_71 = plugins/ccm +@MONOLITHIC_TRUE@@USE_CCM_TRUE@am__append_72 = plugins/ccm/libstrongswan-ccm.la +@USE_GCM_TRUE@am__append_73 = plugins/gcm +@MONOLITHIC_TRUE@@USE_GCM_TRUE@am__append_74 = plugins/gcm/libstrongswan-gcm.la +@USE_TEST_VECTORS_TRUE@am__append_75 = plugins/test_vectors +@MONOLITHIC_TRUE@@USE_TEST_VECTORS_TRUE@am__append_76 = plugins/test_vectors/libstrongswan-test-vectors.la subdir = src/libstrongswan DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -162,7 +168,8 @@ libstrongswan_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \ $(am__append_48) $(am__append_50) $(am__append_52) \ $(am__append_54) $(am__append_56) $(am__append_58) \ $(am__append_60) $(am__append_62) $(am__append_64) \ - $(am__append_66) $(am__append_68) $(am__append_70) + $(am__append_66) $(am__append_68) $(am__append_70) \ + $(am__append_72) $(am__append_74) $(am__append_76) am__libstrongswan_la_SOURCES_DIST = library.c library.h chunk.c \ chunk.h debug.c debug.h enum.c enum.h settings.h settings.c \ printf_hook.c printf_hook.h asn1/asn1.c asn1/asn1.h \ @@ -187,8 +194,7 @@ am__libstrongswan_la_SOURCES_DIST = library.c library.h chunk.c \ credentials/keys/shared_key.h \ credentials/certificates/certificate.c \ credentials/certificates/certificate.h \ - credentials/certificates/x509.h \ - credentials/certificates/x509.c credentials/certificates/ac.h \ + credentials/certificates/x509.h credentials/certificates/ac.h \ credentials/certificates/crl.h credentials/certificates/crl.c \ credentials/certificates/pkcs10.h \ credentials/certificates/ocsp_request.h \ @@ -238,7 +244,7 @@ am_libstrongswan_la_OBJECTS = library.lo chunk.lo debug.lo enum.lo \ crypto_tester.lo diffie_hellman.lo aead.lo transform.lo \ credential_factory.lo builder.lo cred_encoding.lo \ private_key.lo public_key.lo shared_key.lo certificate.lo \ - x509.lo crl.lo ocsp_response.lo ietf_attributes.lo \ + crl.lo ocsp_response.lo ietf_attributes.lo \ credential_manager.lo auth_cfg_wrapper.lo \ ocsp_response_wrapper.lo cert_cache.lo mem_cred.lo \ callback_cred.lo auth_cfg.lo database_factory.lo \ @@ -278,14 +284,16 @@ AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ distdir ETAGS = etags CTAGS = ctags -DIST_SUBDIRS = . plugins/aes plugins/des plugins/blowfish plugins/md4 \ - plugins/md5 plugins/sha1 plugins/sha2 plugins/gmp \ - plugins/random plugins/hmac plugins/xcbc plugins/x509 \ - plugins/revocation plugins/pubkey plugins/pkcs1 plugins/pgp \ - plugins/dnskey plugins/pem plugins/curl plugins/ldap \ - plugins/mysql plugins/sqlite plugins/padlock plugins/openssl \ - plugins/gcrypt plugins/fips_prf plugins/agent plugins/pkcs11 \ - plugins/ctr plugins/ccm plugins/gcm plugins/test_vectors +DIST_SUBDIRS = . plugins/af_alg plugins/aes plugins/des \ + plugins/blowfish plugins/md4 plugins/md5 plugins/sha1 \ + plugins/sha2 plugins/gmp plugins/random plugins/hmac \ + plugins/xcbc plugins/x509 plugins/revocation \ + plugins/constraints plugins/pubkey plugins/pkcs1 plugins/pgp \ + plugins/dnskey plugins/pem plugins/curl plugins/soup \ + plugins/ldap plugins/mysql plugins/sqlite plugins/padlock \ + plugins/openssl plugins/gcrypt plugins/fips_prf plugins/agent \ + plugins/pkcs11 plugins/ctr plugins/ccm plugins/gcm \ + plugins/test_vectors DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ @@ -431,9 +439,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -472,6 +478,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ @@ -507,8 +515,7 @@ libstrongswan_la_SOURCES = library.c library.h chunk.c chunk.h debug.c \ credentials/keys/shared_key.h \ credentials/certificates/certificate.c \ credentials/certificates/certificate.h \ - credentials/certificates/x509.h \ - credentials/certificates/x509.c credentials/certificates/ac.h \ + credentials/certificates/x509.h credentials/certificates/ac.h \ credentials/certificates/crl.h credentials/certificates/crl.c \ credentials/certificates/pkcs10.h \ credentials/certificates/ocsp_request.h \ @@ -559,7 +566,8 @@ libstrongswan_la_LIBADD = $(PTHREADLIB) $(DLLIB) $(BTLIB) $(SOCKLIB) \ $(am__append_48) $(am__append_50) $(am__append_52) \ $(am__append_54) $(am__append_56) $(am__append_58) \ $(am__append_60) $(am__append_62) $(am__append_64) \ - $(am__append_66) $(am__append_68) $(am__append_70) + $(am__append_66) $(am__append_68) $(am__append_70) \ + $(am__append_72) $(am__append_74) $(am__append_76) INCLUDES = -I$(top_srcdir)/src/libstrongswan AM_CFLAGS = -DIPSEC_DIR=\"${ipsecdir}\" -DPLUGINDIR=\"${plugindir}\" \ -DSTRONGSWAN_CONF=\"${strongswan_conf}\" $(am__append_1) \ @@ -592,7 +600,9 @@ $(srcdir)/crypto/proposal/proposal_keywords.c @MONOLITHIC_FALSE@ $(am__append_55) $(am__append_57) \ @MONOLITHIC_FALSE@ $(am__append_59) $(am__append_61) \ @MONOLITHIC_FALSE@ $(am__append_63) $(am__append_65) \ -@MONOLITHIC_FALSE@ $(am__append_67) $(am__append_69) +@MONOLITHIC_FALSE@ $(am__append_67) $(am__append_69) \ +@MONOLITHIC_FALSE@ $(am__append_71) $(am__append_73) \ +@MONOLITHIC_FALSE@ $(am__append_75) # build plugins with their own Makefile ####################################### @@ -611,7 +621,9 @@ $(srcdir)/crypto/proposal/proposal_keywords.c @MONOLITHIC_TRUE@ $(am__append_55) $(am__append_57) \ @MONOLITHIC_TRUE@ $(am__append_59) $(am__append_61) \ @MONOLITHIC_TRUE@ $(am__append_63) $(am__append_65) \ -@MONOLITHIC_TRUE@ $(am__append_67) $(am__append_69) +@MONOLITHIC_TRUE@ $(am__append_67) $(am__append_69) \ +@MONOLITHIC_TRUE@ $(am__append_71) $(am__append_73) \ +@MONOLITHIC_TRUE@ $(am__append_75) all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-recursive @@ -749,7 +761,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/traffic_selector.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/transform.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/x509.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @@ -933,13 +944,6 @@ certificate.lo: credentials/certificates/certificate.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o certificate.lo `test -f 'credentials/certificates/certificate.c' || echo '$(srcdir)/'`credentials/certificates/certificate.c -x509.lo: credentials/certificates/x509.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT x509.lo -MD -MP -MF $(DEPDIR)/x509.Tpo -c -o x509.lo `test -f 'credentials/certificates/x509.c' || echo '$(srcdir)/'`credentials/certificates/x509.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/x509.Tpo $(DEPDIR)/x509.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='credentials/certificates/x509.c' object='x509.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o x509.lo `test -f 'credentials/certificates/x509.c' || echo '$(srcdir)/'`credentials/certificates/x509.c - crl.lo: credentials/certificates/crl.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT crl.lo -MD -MP -MF $(DEPDIR)/crl.Tpo -c -o crl.lo `test -f 'credentials/certificates/crl.c' || echo '$(srcdir)/'`credentials/certificates/crl.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/crl.Tpo $(DEPDIR)/crl.Plo diff --git a/src/libstrongswan/asn1/asn1.c b/src/libstrongswan/asn1/asn1.c index 6f549d42d..f80c2b93b 100644 --- a/src/libstrongswan/asn1/asn1.c +++ b/src/libstrongswan/asn1/asn1.c @@ -126,6 +126,100 @@ chunk_t asn1_build_known_oid(int n) /* * Defined in header. */ +chunk_t asn1_oid_from_string(char *str) +{ + enumerator_t *enumerator; + u_char buf[32]; + char *end; + int i = 0, pos = 0; + u_int val, first = 0; + + enumerator = enumerator_create_token(str, ".", ""); + while (enumerator->enumerate(enumerator, &str)) + { + val = strtoul(str, &end, 10); + if (end == str || pos > countof(buf)) + { + pos = 0; + break; + } + switch (i++) + { + case 0: + first = val; + break; + case 1: + buf[pos++] = first * 40 + val; + break; + default: + if (val < 128) + { + buf[pos++] = val; + } + else + { + buf[pos++] = 128 | (val >> 7); + buf[pos++] = (val % 256) & 0x7F; + } + break; + } + } + enumerator->destroy(enumerator); + + return chunk_clone(chunk_create(buf, pos)); +} + +/* + * Defined in header. + */ +char *asn1_oid_to_string(chunk_t oid) +{ + char buf[64], *pos = buf; + int len; + u_int val; + + if (!oid.len) + { + return NULL; + } + val = oid.ptr[0] / 40; + len = snprintf(buf, sizeof(buf), "%d.%d", val, oid.ptr[0] - val * 40); + oid = chunk_skip(oid, 1); + if (len < 0 || len >= sizeof(buf)) + { + return NULL; + } + pos += len; + + while (oid.len) + { + if (oid.ptr[0] < 128) + { + len = snprintf(pos, sizeof(buf) + buf - pos, ".%d", oid.ptr[0]); + oid = chunk_skip(oid, 1); + } + else + { + if (oid.len == 1) + { + return NULL; + } + val = ((u_int)(oid.ptr[0] & 0x7F) << 7) + oid.ptr[1]; + len = snprintf(pos, sizeof(buf) + buf - pos, ".%d", val); + oid = chunk_skip(oid, 2); + } + if (len < 0 || len >= sizeof(buf) + buf - pos) + { + return NULL; + } + pos += len; + } + return strdup(buf); +} + +/* + * Defined in header. + */ size_t asn1_length(chunk_t *blob) { u_char n; diff --git a/src/libstrongswan/asn1/asn1.h b/src/libstrongswan/asn1/asn1.h index 866c28095..05a060827 100644 --- a/src/libstrongswan/asn1/asn1.h +++ b/src/libstrongswan/asn1/asn1.h @@ -115,6 +115,22 @@ int asn1_known_oid(chunk_t object); chunk_t asn1_build_known_oid(int n); /** + * Convert human readable OID to ASN.1 DER encoding, without OID header. + * + * @param str OID string (e.g. 1.2.345.67.8) + * @return allocated ASN.1 encoded OID, chunk_empty on error + */ +chunk_t asn1_oid_from_string(char *str); + +/** + * Convert a DER encoded ASN.1 OID to a human readable string. + * + * @param oid DER encoded OID, without header + * @return human readable OID string, allocated, NULL on error + */ +char* asn1_oid_to_string(chunk_t oid); + +/** * Returns the length of an ASN.1 object * The blob pointer is advanced past the tag length fields * diff --git a/src/libstrongswan/asn1/asn1_parser.c b/src/libstrongswan/asn1/asn1_parser.c index 3e5bbbabd..2a7a38a52 100644 --- a/src/libstrongswan/asn1/asn1_parser.c +++ b/src/libstrongswan/asn1/asn1_parser.c @@ -78,10 +78,8 @@ struct private_asn1_parser_t { chunk_t blobs[ASN1_MAX_LEVEL + 2]; }; -/** - * Implementation of asn1_parser_t.iterate - */ -static bool iterate(private_asn1_parser_t *this, int *objectID, chunk_t *object) +METHOD(asn1_parser_t, iterate, bool, + private_asn1_parser_t *this, int *objectID, chunk_t *object) { chunk_t *blob, *blob1; u_char *start_ptr; @@ -234,43 +232,33 @@ end: return this->success; } -/** - * Implementation of asn1_parser_t.get_level - */ -static u_int get_level(private_asn1_parser_t *this) +METHOD(asn1_parser_t, get_level, u_int, +private_asn1_parser_t *this) { return this->level0 + this->objects[this->line].level; } -/** - * Implementation of asn1_parser_t.set_top_level - */ -static void set_top_level(private_asn1_parser_t *this, u_int level0) +METHOD(asn1_parser_t, set_top_level, void, + private_asn1_parser_t *this, u_int level0) { this->level0 = level0; } -/** - * Implementation of asn1_parser_t.set_flags - */ -static void set_flags(private_asn1_parser_t *this, bool implicit, bool private) +METHOD(asn1_parser_t, set_flags, void, + private_asn1_parser_t *this, bool implicit, bool private) { this->implicit = implicit; this->private = private; } -/** - * Implementation of asn1_parser_t.success - */ -static bool success(private_asn1_parser_t *this) +METHOD(asn1_parser_t, success, bool, + private_asn1_parser_t *this) { return this->success; } -/** - * Implementation of asn1_parser_t.destroy - */ -static void destroy(private_asn1_parser_t *this) +METHOD(asn1_parser_t, destroy, void, + private_asn1_parser_t *this) { free(this); } @@ -280,20 +268,22 @@ static void destroy(private_asn1_parser_t *this) */ asn1_parser_t* asn1_parser_create(asn1Object_t const *objects, chunk_t blob) { - private_asn1_parser_t *this = malloc_thing(private_asn1_parser_t); - - memset(this, '\0', sizeof(private_asn1_parser_t)); - this->objects = objects; - this->blobs[0] = blob; - this->line = -1; - this->success = TRUE; - - this->public.iterate = (bool (*)(asn1_parser_t*, int*, chunk_t*))iterate; - this->public.get_level = (u_int (*)(asn1_parser_t*))get_level; - this->public.set_top_level = (void (*)(asn1_parser_t*, u_int))set_top_level; - this->public.set_flags = (void (*)(asn1_parser_t*, bool, bool))set_flags; - this->public.success = (bool (*)(asn1_parser_t*))success; - this->public.destroy = (void (*)(asn1_parser_t*))destroy; + private_asn1_parser_t *this; + + INIT(this, + .public = { + .iterate = _iterate, + .get_level = _get_level, + .set_top_level = _set_top_level, + .set_flags = _set_flags, + .success = _success, + .destroy = _destroy, + }, + .objects = objects, + .blobs[0] = blob, + .line = -1, + .success = TRUE, + ); return &this->public; } diff --git a/src/libstrongswan/asn1/oid.c b/src/libstrongswan/asn1/oid.c index 1e5dec8a5..57a00a39e 100644 --- a/src/libstrongswan/asn1/oid.c +++ b/src/libstrongswan/asn1/oid.c @@ -10,360 +10,363 @@ #include "oid.h" const oid_t oid_names[] = { - {0x02, 7, 1, 0, "ITU-T Administration" }, /* 0 */ - { 0x82, 0, 1, 1, "" }, /* 1 */ - { 0x06, 0, 1, 2, "Germany ITU-T member" }, /* 2 */ - { 0x01, 0, 1, 3, "Deutsche Telekom AG" }, /* 3 */ - { 0x0A, 0, 1, 4, "" }, /* 4 */ - { 0x07, 0, 1, 5, "" }, /* 5 */ - { 0x14, 0, 0, 6, "ND" }, /* 6 */ - {0x09, 18, 1, 0, "data" }, /* 7 */ - { 0x92, 0, 1, 1, "" }, /* 8 */ - { 0x26, 0, 1, 2, "" }, /* 9 */ - { 0x89, 0, 1, 3, "" }, /* 10 */ - { 0x93, 0, 1, 4, "" }, /* 11 */ - { 0xF2, 0, 1, 5, "" }, /* 12 */ - { 0x2C, 0, 1, 6, "" }, /* 13 */ - { 0x64, 0, 1, 7, "pilot" }, /* 14 */ - { 0x01, 0, 1, 8, "pilotAttributeType" }, /* 15 */ - { 0x01, 17, 0, 9, "UID" }, /* 16 */ - { 0x19, 0, 0, 9, "DC" }, /* 17 */ - {0x55, 64, 1, 0, "X.500" }, /* 18 */ - { 0x04, 36, 1, 1, "X.509" }, /* 19 */ - { 0x03, 21, 0, 2, "CN" }, /* 20 */ - { 0x04, 22, 0, 2, "S" }, /* 21 */ - { 0x05, 23, 0, 2, "SN" }, /* 22 */ - { 0x06, 24, 0, 2, "C" }, /* 23 */ - { 0x07, 25, 0, 2, "L" }, /* 24 */ - { 0x08, 26, 0, 2, "ST" }, /* 25 */ - { 0x0A, 27, 0, 2, "O" }, /* 26 */ - { 0x0B, 28, 0, 2, "OU" }, /* 27 */ - { 0x0C, 29, 0, 2, "T" }, /* 28 */ - { 0x0D, 30, 0, 2, "D" }, /* 29 */ - { 0x24, 31, 0, 2, "userCertificate" }, /* 30 */ - { 0x29, 32, 0, 2, "N" }, /* 31 */ - { 0x2A, 33, 0, 2, "G" }, /* 32 */ - { 0x2B, 34, 0, 2, "I" }, /* 33 */ - { 0x2D, 35, 0, 2, "ID" }, /* 34 */ - { 0x48, 0, 0, 2, "role" }, /* 35 */ - { 0x1D, 0, 1, 1, "id-ce" }, /* 36 */ - { 0x09, 38, 0, 2, "subjectDirectoryAttrs" }, /* 37 */ - { 0x0E, 39, 0, 2, "subjectKeyIdentifier" }, /* 38 */ - { 0x0F, 40, 0, 2, "keyUsage" }, /* 39 */ - { 0x10, 41, 0, 2, "privateKeyUsagePeriod" }, /* 40 */ - { 0x11, 42, 0, 2, "subjectAltName" }, /* 41 */ - { 0x12, 43, 0, 2, "issuerAltName" }, /* 42 */ - { 0x13, 44, 0, 2, "basicConstraints" }, /* 43 */ - { 0x14, 45, 0, 2, "crlNumber" }, /* 44 */ - { 0x15, 46, 0, 2, "reasonCode" }, /* 45 */ - { 0x17, 47, 0, 2, "holdInstructionCode" }, /* 46 */ - { 0x18, 48, 0, 2, "invalidityDate" }, /* 47 */ - { 0x1B, 49, 0, 2, "deltaCrlIndicator" }, /* 48 */ - { 0x1C, 50, 0, 2, "issuingDistributionPoint" }, /* 49 */ - { 0x1D, 51, 0, 2, "certificateIssuer" }, /* 50 */ - { 0x1E, 52, 0, 2, "nameConstraints" }, /* 51 */ - { 0x1F, 53, 0, 2, "crlDistributionPoints" }, /* 52 */ - { 0x20, 55, 1, 2, "certificatePolicies" }, /* 53 */ - { 0x00, 0, 0, 3, "anyPolicy" }, /* 54 */ - { 0x21, 56, 0, 2, "policyMappings" }, /* 55 */ - { 0x23, 57, 0, 2, "authorityKeyIdentifier" }, /* 56 */ - { 0x24, 58, 0, 2, "policyConstraints" }, /* 57 */ - { 0x25, 60, 1, 2, "extendedKeyUsage" }, /* 58 */ - { 0x00, 0, 0, 3, "anyExtendedKeyUsage" }, /* 59 */ - { 0x2E, 61, 0, 2, "freshestCRL" }, /* 60 */ - { 0x36, 62, 0, 2, "inhibitAnyPolicy" }, /* 61 */ - { 0x37, 63, 0, 2, "targetInformation" }, /* 62 */ - { 0x38, 0, 0, 2, "noRevAvail" }, /* 63 */ - {0x2A, 161, 1, 0, "" }, /* 64 */ - { 0x83, 77, 1, 1, "" }, /* 65 */ - { 0x08, 0, 1, 2, "jp" }, /* 66 */ - { 0x8C, 0, 1, 3, "" }, /* 67 */ - { 0x9A, 0, 1, 4, "" }, /* 68 */ - { 0x4B, 0, 1, 5, "" }, /* 69 */ - { 0x3D, 0, 1, 6, "" }, /* 70 */ - { 0x01, 0, 1, 7, "security" }, /* 71 */ - { 0x01, 0, 1, 8, "algorithm" }, /* 72 */ - { 0x01, 0, 1, 9, "symm-encryption-alg" }, /* 73 */ - { 0x02, 75, 0, 10, "camellia128-cbc" }, /* 74 */ - { 0x03, 76, 0, 10, "camellia192-cbc" }, /* 75 */ - { 0x04, 0, 0, 10, "camellia256-cbc" }, /* 76 */ - { 0x86, 0, 1, 1, "" }, /* 77 */ - { 0x48, 0, 1, 2, "us" }, /* 78 */ - { 0x86, 120, 1, 3, "" }, /* 79 */ - { 0xF6, 85, 1, 4, "" }, /* 80 */ - { 0x7D, 0, 1, 5, "NortelNetworks" }, /* 81 */ - { 0x07, 0, 1, 6, "Entrust" }, /* 82 */ - { 0x41, 0, 1, 7, "nsn-ce" }, /* 83 */ - { 0x00, 0, 0, 8, "entrustVersInfo" }, /* 84 */ - { 0xF7, 0, 1, 4, "" }, /* 85 */ - { 0x0D, 0, 1, 5, "RSADSI" }, /* 86 */ - { 0x01, 115, 1, 6, "PKCS" }, /* 87 */ - { 0x01, 97, 1, 7, "PKCS-1" }, /* 88 */ - { 0x01, 90, 0, 8, "rsaEncryption" }, /* 89 */ - { 0x02, 91, 0, 8, "md2WithRSAEncryption" }, /* 90 */ - { 0x04, 92, 0, 8, "md5WithRSAEncryption" }, /* 91 */ - { 0x05, 93, 0, 8, "sha-1WithRSAEncryption" }, /* 92 */ - { 0x0B, 94, 0, 8, "sha256WithRSAEncryption" }, /* 93 */ - { 0x0C, 95, 0, 8, "sha384WithRSAEncryption" }, /* 94 */ - { 0x0D, 96, 0, 8, "sha512WithRSAEncryption" }, /* 95 */ - { 0x0E, 0, 0, 8, "sha224WithRSAEncryption" }, /* 96 */ - { 0x07, 104, 1, 7, "PKCS-7" }, /* 97 */ - { 0x01, 99, 0, 8, "data" }, /* 98 */ - { 0x02, 100, 0, 8, "signedData" }, /* 99 */ - { 0x03, 101, 0, 8, "envelopedData" }, /* 100 */ - { 0x04, 102, 0, 8, "signedAndEnvelopedData" }, /* 101 */ - { 0x05, 103, 0, 8, "digestedData" }, /* 102 */ - { 0x06, 0, 0, 8, "encryptedData" }, /* 103 */ - { 0x09, 0, 1, 7, "PKCS-9" }, /* 104 */ - { 0x01, 106, 0, 8, "E" }, /* 105 */ - { 0x02, 107, 0, 8, "unstructuredName" }, /* 106 */ - { 0x03, 108, 0, 8, "contentType" }, /* 107 */ - { 0x04, 109, 0, 8, "messageDigest" }, /* 108 */ - { 0x05, 110, 0, 8, "signingTime" }, /* 109 */ - { 0x06, 111, 0, 8, "counterSignature" }, /* 110 */ - { 0x07, 112, 0, 8, "challengePassword" }, /* 111 */ - { 0x08, 113, 0, 8, "unstructuredAddress" }, /* 112 */ - { 0x0E, 114, 0, 8, "extensionRequest" }, /* 113 */ - { 0x0F, 0, 0, 8, "S/MIME Capabilities" }, /* 114 */ - { 0x02, 118, 1, 6, "digestAlgorithm" }, /* 115 */ - { 0x02, 117, 0, 7, "md2" }, /* 116 */ - { 0x05, 0, 0, 7, "md5" }, /* 117 */ - { 0x03, 0, 1, 6, "encryptionAlgorithm" }, /* 118 */ - { 0x07, 0, 0, 7, "3des-ede-cbc" }, /* 119 */ - { 0xCE, 0, 1, 3, "" }, /* 120 */ - { 0x3D, 0, 1, 4, "ansi-X9-62" }, /* 121 */ - { 0x02, 124, 1, 5, "id-publicKeyType" }, /* 122 */ - { 0x01, 0, 0, 6, "id-ecPublicKey" }, /* 123 */ - { 0x03, 154, 1, 5, "ellipticCurve" }, /* 124 */ - { 0x00, 146, 1, 6, "c-TwoCurve" }, /* 125 */ - { 0x01, 127, 0, 7, "c2pnb163v1" }, /* 126 */ - { 0x02, 128, 0, 7, "c2pnb163v2" }, /* 127 */ - { 0x03, 129, 0, 7, "c2pnb163v3" }, /* 128 */ - { 0x04, 130, 0, 7, "c2pnb176w1" }, /* 129 */ - { 0x05, 131, 0, 7, "c2tnb191v1" }, /* 130 */ - { 0x06, 132, 0, 7, "c2tnb191v2" }, /* 131 */ - { 0x07, 133, 0, 7, "c2tnb191v3" }, /* 132 */ - { 0x08, 134, 0, 7, "c2onb191v4" }, /* 133 */ - { 0x09, 135, 0, 7, "c2onb191v5" }, /* 134 */ - { 0x0A, 136, 0, 7, "c2pnb208w1" }, /* 135 */ - { 0x0B, 137, 0, 7, "c2tnb239v1" }, /* 136 */ - { 0x0C, 138, 0, 7, "c2tnb239v2" }, /* 137 */ - { 0x0D, 139, 0, 7, "c2tnb239v3" }, /* 138 */ - { 0x0E, 140, 0, 7, "c2onb239v4" }, /* 139 */ - { 0x0F, 141, 0, 7, "c2onb239v5" }, /* 140 */ - { 0x10, 142, 0, 7, "c2pnb272w1" }, /* 141 */ - { 0x11, 143, 0, 7, "c2pnb304w1" }, /* 142 */ - { 0x12, 144, 0, 7, "c2tnb359v1" }, /* 143 */ - { 0x13, 145, 0, 7, "c2pnb368w1" }, /* 144 */ - { 0x14, 0, 0, 7, "c2tnb431r1" }, /* 145 */ - { 0x01, 0, 1, 6, "primeCurve" }, /* 146 */ - { 0x01, 148, 0, 7, "prime192v1" }, /* 147 */ - { 0x02, 149, 0, 7, "prime192v2" }, /* 148 */ - { 0x03, 150, 0, 7, "prime192v3" }, /* 149 */ - { 0x04, 151, 0, 7, "prime239v1" }, /* 150 */ - { 0x05, 152, 0, 7, "prime239v2" }, /* 151 */ - { 0x06, 153, 0, 7, "prime239v3" }, /* 152 */ - { 0x07, 0, 0, 7, "prime256v1" }, /* 153 */ - { 0x04, 0, 1, 5, "id-ecSigType" }, /* 154 */ - { 0x01, 156, 0, 6, "ecdsa-with-SHA1" }, /* 155 */ - { 0x03, 0, 1, 6, "ecdsa-with-Specified" }, /* 156 */ - { 0x01, 158, 0, 7, "ecdsa-with-SHA224" }, /* 157 */ - { 0x02, 159, 0, 7, "ecdsa-with-SHA256" }, /* 158 */ - { 0x03, 160, 0, 7, "ecdsa-with-SHA384" }, /* 159 */ - { 0x04, 0, 0, 7, "ecdsa-with-SHA512" }, /* 160 */ - {0x2B, 309, 1, 0, "" }, /* 161 */ - { 0x06, 223, 1, 1, "dod" }, /* 162 */ - { 0x01, 0, 1, 2, "internet" }, /* 163 */ - { 0x04, 183, 1, 3, "private" }, /* 164 */ - { 0x01, 0, 1, 4, "enterprise" }, /* 165 */ - { 0x82, 176, 1, 5, "" }, /* 166 */ - { 0x37, 0, 1, 6, "Microsoft" }, /* 167 */ - { 0x0A, 172, 1, 7, "" }, /* 168 */ - { 0x03, 0, 1, 8, "" }, /* 169 */ - { 0x03, 171, 0, 9, "msSGC" }, /* 170 */ - { 0x04, 0, 0, 9, "msEncryptingFileSystem" }, /* 171 */ - { 0x14, 0, 1, 7, "msEnrollmentInfrastructure"}, /* 172 */ - { 0x02, 0, 1, 8, "msCertificateTypeExtension"}, /* 173 */ - { 0x02, 175, 0, 9, "msSmartcardLogon" }, /* 174 */ - { 0x03, 0, 0, 9, "msUPN" }, /* 175 */ - { 0x89, 0, 1, 5, "" }, /* 176 */ - { 0x31, 0, 1, 6, "" }, /* 177 */ - { 0x01, 0, 1, 7, "" }, /* 178 */ - { 0x01, 0, 1, 8, "" }, /* 179 */ - { 0x02, 0, 1, 9, "" }, /* 180 */ - { 0x02, 182, 0, 10, "" }, /* 181 */ - { 0x4B, 0, 0, 10, "TCGID" }, /* 182 */ - { 0x05, 0, 1, 3, "security" }, /* 183 */ - { 0x05, 0, 1, 4, "mechanisms" }, /* 184 */ - { 0x07, 0, 1, 5, "id-pkix" }, /* 185 */ - { 0x01, 190, 1, 6, "id-pe" }, /* 186 */ - { 0x01, 188, 0, 7, "authorityInfoAccess" }, /* 187 */ - { 0x03, 189, 0, 7, "qcStatements" }, /* 188 */ - { 0x07, 0, 0, 7, "ipAddrBlocks" }, /* 189 */ - { 0x02, 193, 1, 6, "id-qt" }, /* 190 */ - { 0x01, 192, 0, 7, "cps" }, /* 191 */ - { 0x02, 0, 0, 7, "unotice" }, /* 192 */ - { 0x03, 203, 1, 6, "id-kp" }, /* 193 */ - { 0x01, 195, 0, 7, "serverAuth" }, /* 194 */ - { 0x02, 196, 0, 7, "clientAuth" }, /* 195 */ - { 0x03, 197, 0, 7, "codeSigning" }, /* 196 */ - { 0x04, 198, 0, 7, "emailProtection" }, /* 197 */ - { 0x05, 199, 0, 7, "ipsecEndSystem" }, /* 198 */ - { 0x06, 200, 0, 7, "ipsecTunnel" }, /* 199 */ - { 0x07, 201, 0, 7, "ipsecUser" }, /* 200 */ - { 0x08, 202, 0, 7, "timeStamping" }, /* 201 */ - { 0x09, 0, 0, 7, "ocspSigning" }, /* 202 */ - { 0x08, 205, 1, 6, "id-otherNames" }, /* 203 */ - { 0x05, 0, 0, 7, "xmppAddr" }, /* 204 */ - { 0x0A, 210, 1, 6, "id-aca" }, /* 205 */ - { 0x01, 207, 0, 7, "authenticationInfo" }, /* 206 */ - { 0x02, 208, 0, 7, "accessIdentity" }, /* 207 */ - { 0x03, 209, 0, 7, "chargingIdentity" }, /* 208 */ - { 0x04, 0, 0, 7, "group" }, /* 209 */ - { 0x0B, 211, 0, 6, "subjectInfoAccess" }, /* 210 */ - { 0x30, 0, 1, 6, "id-ad" }, /* 211 */ - { 0x01, 220, 1, 7, "ocsp" }, /* 212 */ - { 0x01, 214, 0, 8, "basic" }, /* 213 */ - { 0x02, 215, 0, 8, "nonce" }, /* 214 */ - { 0x03, 216, 0, 8, "crl" }, /* 215 */ - { 0x04, 217, 0, 8, "response" }, /* 216 */ - { 0x05, 218, 0, 8, "noCheck" }, /* 217 */ - { 0x06, 219, 0, 8, "archiveCutoff" }, /* 218 */ - { 0x07, 0, 0, 8, "serviceLocator" }, /* 219 */ - { 0x02, 221, 0, 7, "caIssuers" }, /* 220 */ - { 0x03, 222, 0, 7, "timeStamping" }, /* 221 */ - { 0x05, 0, 0, 7, "caRepository" }, /* 222 */ - { 0x0E, 229, 1, 1, "oiw" }, /* 223 */ - { 0x03, 0, 1, 2, "secsig" }, /* 224 */ - { 0x02, 0, 1, 3, "algorithms" }, /* 225 */ - { 0x07, 227, 0, 4, "des-cbc" }, /* 226 */ - { 0x1A, 228, 0, 4, "sha-1" }, /* 227 */ - { 0x1D, 0, 0, 4, "sha-1WithRSASignature" }, /* 228 */ - { 0x24, 275, 1, 1, "TeleTrusT" }, /* 229 */ - { 0x03, 0, 1, 2, "algorithm" }, /* 230 */ - { 0x03, 0, 1, 3, "signatureAlgorithm" }, /* 231 */ - { 0x01, 236, 1, 4, "rsaSignature" }, /* 232 */ - { 0x02, 234, 0, 5, "rsaSigWithripemd160" }, /* 233 */ - { 0x03, 235, 0, 5, "rsaSigWithripemd128" }, /* 234 */ - { 0x04, 0, 0, 5, "rsaSigWithripemd256" }, /* 235 */ - { 0x02, 0, 1, 4, "ecSign" }, /* 236 */ - { 0x01, 238, 0, 5, "ecSignWithsha1" }, /* 237 */ - { 0x02, 239, 0, 5, "ecSignWithripemd160" }, /* 238 */ - { 0x03, 240, 0, 5, "ecSignWithmd2" }, /* 239 */ - { 0x04, 241, 0, 5, "ecSignWithmd5" }, /* 240 */ - { 0x05, 258, 1, 5, "ttt-ecg" }, /* 241 */ - { 0x01, 246, 1, 6, "fieldType" }, /* 242 */ - { 0x01, 0, 1, 7, "characteristictwoField" }, /* 243 */ - { 0x01, 0, 1, 8, "basisType" }, /* 244 */ - { 0x01, 0, 0, 9, "ipBasis" }, /* 245 */ - { 0x02, 248, 1, 6, "keyType" }, /* 246 */ - { 0x01, 0, 0, 7, "ecgPublicKey" }, /* 247 */ - { 0x03, 249, 0, 6, "curve" }, /* 248 */ - { 0x04, 256, 1, 6, "signatures" }, /* 249 */ - { 0x01, 251, 0, 7, "ecgdsa-with-RIPEMD160" }, /* 250 */ - { 0x02, 252, 0, 7, "ecgdsa-with-SHA1" }, /* 251 */ - { 0x03, 253, 0, 7, "ecgdsa-with-SHA224" }, /* 252 */ - { 0x04, 254, 0, 7, "ecgdsa-with-SHA256" }, /* 253 */ - { 0x05, 255, 0, 7, "ecgdsa-with-SHA384" }, /* 254 */ - { 0x06, 0, 0, 7, "ecgdsa-with-SHA512" }, /* 255 */ - { 0x05, 0, 1, 6, "module" }, /* 256 */ - { 0x01, 0, 0, 7, "1" }, /* 257 */ - { 0x08, 0, 1, 5, "ecStdCurvesAndGeneration" }, /* 258 */ - { 0x01, 0, 1, 6, "ellipticCurve" }, /* 259 */ - { 0x01, 0, 1, 7, "versionOne" }, /* 260 */ - { 0x01, 262, 0, 8, "brainpoolP160r1" }, /* 261 */ - { 0x02, 263, 0, 8, "brainpoolP160t1" }, /* 262 */ - { 0x03, 264, 0, 8, "brainpoolP192r1" }, /* 263 */ - { 0x04, 265, 0, 8, "brainpoolP192t1" }, /* 264 */ - { 0x05, 266, 0, 8, "brainpoolP224r1" }, /* 265 */ - { 0x06, 267, 0, 8, "brainpoolP224t1" }, /* 266 */ - { 0x07, 268, 0, 8, "brainpoolP256r1" }, /* 267 */ - { 0x08, 269, 0, 8, "brainpoolP256t1" }, /* 268 */ - { 0x09, 270, 0, 8, "brainpoolP320r1" }, /* 269 */ - { 0x0A, 271, 0, 8, "brainpoolP320t1" }, /* 270 */ - { 0x0B, 272, 0, 8, "brainpoolP384r1" }, /* 271 */ - { 0x0C, 273, 0, 8, "brainpoolP384t1" }, /* 272 */ - { 0x0D, 274, 0, 8, "brainpoolP512r1" }, /* 273 */ - { 0x0E, 0, 0, 8, "brainpoolP512t1" }, /* 274 */ - { 0x81, 0, 1, 1, "" }, /* 275 */ - { 0x04, 0, 1, 2, "Certicom" }, /* 276 */ - { 0x00, 0, 1, 3, "curve" }, /* 277 */ - { 0x01, 279, 0, 4, "sect163k1" }, /* 278 */ - { 0x02, 280, 0, 4, "sect163r1" }, /* 279 */ - { 0x03, 281, 0, 4, "sect239k1" }, /* 280 */ - { 0x04, 282, 0, 4, "sect113r1" }, /* 281 */ - { 0x05, 283, 0, 4, "sect113r2" }, /* 282 */ - { 0x06, 284, 0, 4, "secp112r1" }, /* 283 */ - { 0x07, 285, 0, 4, "secp112r2" }, /* 284 */ - { 0x08, 286, 0, 4, "secp160r1" }, /* 285 */ - { 0x09, 287, 0, 4, "secp160k1" }, /* 286 */ - { 0x0A, 288, 0, 4, "secp256k1" }, /* 287 */ - { 0x0F, 289, 0, 4, "sect163r2" }, /* 288 */ - { 0x10, 290, 0, 4, "sect283k1" }, /* 289 */ - { 0x11, 291, 0, 4, "sect283r1" }, /* 290 */ - { 0x16, 292, 0, 4, "sect131r1" }, /* 291 */ - { 0x17, 293, 0, 4, "sect131r2" }, /* 292 */ - { 0x18, 294, 0, 4, "sect193r1" }, /* 293 */ - { 0x19, 295, 0, 4, "sect193r2" }, /* 294 */ - { 0x1A, 296, 0, 4, "sect233k1" }, /* 295 */ - { 0x1B, 297, 0, 4, "sect233r1" }, /* 296 */ - { 0x1C, 298, 0, 4, "secp128r1" }, /* 297 */ - { 0x1D, 299, 0, 4, "secp128r2" }, /* 298 */ - { 0x1E, 300, 0, 4, "secp160r2" }, /* 299 */ - { 0x1F, 301, 0, 4, "secp192k1" }, /* 300 */ - { 0x20, 302, 0, 4, "secp224k1" }, /* 301 */ - { 0x21, 303, 0, 4, "secp224r1" }, /* 302 */ - { 0x22, 304, 0, 4, "secp384r1" }, /* 303 */ - { 0x23, 305, 0, 4, "secp521r1" }, /* 304 */ - { 0x24, 306, 0, 4, "sect409k1" }, /* 305 */ - { 0x25, 307, 0, 4, "sect409r1" }, /* 306 */ - { 0x26, 308, 0, 4, "sect571k1" }, /* 307 */ - { 0x27, 0, 0, 4, "sect571r1" }, /* 308 */ - {0x60, 0, 1, 0, "" }, /* 309 */ - { 0x86, 0, 1, 1, "" }, /* 310 */ - { 0x48, 0, 1, 2, "" }, /* 311 */ - { 0x01, 0, 1, 3, "organization" }, /* 312 */ - { 0x65, 331, 1, 4, "gov" }, /* 313 */ - { 0x03, 0, 1, 5, "csor" }, /* 314 */ - { 0x04, 0, 1, 6, "nistalgorithm" }, /* 315 */ - { 0x01, 326, 1, 7, "aes" }, /* 316 */ - { 0x02, 318, 0, 8, "id-aes128-CBC" }, /* 317 */ - { 0x06, 319, 0, 8, "id-aes128-GCM" }, /* 318 */ - { 0x07, 320, 0, 8, "id-aes128-CCM" }, /* 319 */ - { 0x16, 321, 0, 8, "id-aes192-CBC" }, /* 320 */ - { 0x1A, 322, 0, 8, "id-aes192-GCM" }, /* 321 */ - { 0x1B, 323, 0, 8, "id-aes192-CCM" }, /* 322 */ - { 0x2A, 324, 0, 8, "id-aes256-CBC" }, /* 323 */ - { 0x2E, 325, 0, 8, "id-aes256-GCM" }, /* 324 */ - { 0x2F, 0, 0, 8, "id-aes256-CCM" }, /* 325 */ - { 0x02, 0, 1, 7, "hashalgs" }, /* 326 */ - { 0x01, 328, 0, 8, "id-SHA-256" }, /* 327 */ - { 0x02, 329, 0, 8, "id-SHA-384" }, /* 328 */ - { 0x03, 330, 0, 8, "id-SHA-512" }, /* 329 */ - { 0x04, 0, 0, 8, "id-SHA-224" }, /* 330 */ - { 0x86, 0, 1, 4, "" }, /* 331 */ - { 0xf8, 0, 1, 5, "" }, /* 332 */ - { 0x42, 345, 1, 6, "netscape" }, /* 333 */ - { 0x01, 340, 1, 7, "" }, /* 334 */ - { 0x01, 336, 0, 8, "nsCertType" }, /* 335 */ - { 0x03, 337, 0, 8, "nsRevocationUrl" }, /* 336 */ - { 0x04, 338, 0, 8, "nsCaRevocationUrl" }, /* 337 */ - { 0x08, 339, 0, 8, "nsCaPolicyUrl" }, /* 338 */ - { 0x0d, 0, 0, 8, "nsComment" }, /* 339 */ - { 0x03, 343, 1, 7, "directory" }, /* 340 */ - { 0x01, 0, 1, 8, "" }, /* 341 */ - { 0x03, 0, 0, 9, "employeeNumber" }, /* 342 */ - { 0x04, 0, 1, 7, "policy" }, /* 343 */ - { 0x01, 0, 0, 8, "nsSGC" }, /* 344 */ - { 0x45, 0, 1, 6, "verisign" }, /* 345 */ - { 0x01, 0, 1, 7, "pki" }, /* 346 */ - { 0x09, 0, 1, 8, "attributes" }, /* 347 */ - { 0x02, 349, 0, 9, "messageType" }, /* 348 */ - { 0x03, 350, 0, 9, "pkiStatus" }, /* 349 */ - { 0x04, 351, 0, 9, "failInfo" }, /* 350 */ - { 0x05, 352, 0, 9, "senderNonce" }, /* 351 */ - { 0x06, 353, 0, 9, "recipientNonce" }, /* 352 */ - { 0x07, 354, 0, 9, "transID" }, /* 353 */ - { 0x08, 355, 0, 9, "extensionReq" }, /* 354 */ - { 0x08, 0, 0, 9, "extensionReq" } /* 355 */ + {0x02, 7, 1, 0, "ITU-T Administration" }, /* 0 */ + { 0x82, 0, 1, 1, "" }, /* 1 */ + { 0x06, 0, 1, 2, "Germany ITU-T member" }, /* 2 */ + { 0x01, 0, 1, 3, "Deutsche Telekom AG" }, /* 3 */ + { 0x0A, 0, 1, 4, "" }, /* 4 */ + { 0x07, 0, 1, 5, "" }, /* 5 */ + { 0x14, 0, 0, 6, "ND" }, /* 6 */ + {0x09, 18, 1, 0, "data" }, /* 7 */ + { 0x92, 0, 1, 1, "" }, /* 8 */ + { 0x26, 0, 1, 2, "" }, /* 9 */ + { 0x89, 0, 1, 3, "" }, /* 10 */ + { 0x93, 0, 1, 4, "" }, /* 11 */ + { 0xF2, 0, 1, 5, "" }, /* 12 */ + { 0x2C, 0, 1, 6, "" }, /* 13 */ + { 0x64, 0, 1, 7, "pilot" }, /* 14 */ + { 0x01, 0, 1, 8, "pilotAttributeType" }, /* 15 */ + { 0x01, 17, 0, 9, "UID" }, /* 16 */ + { 0x19, 0, 0, 9, "DC" }, /* 17 */ + {0x55, 64, 1, 0, "X.500" }, /* 18 */ + { 0x04, 36, 1, 1, "X.509" }, /* 19 */ + { 0x03, 21, 0, 2, "CN" }, /* 20 */ + { 0x04, 22, 0, 2, "S" }, /* 21 */ + { 0x05, 23, 0, 2, "SN" }, /* 22 */ + { 0x06, 24, 0, 2, "C" }, /* 23 */ + { 0x07, 25, 0, 2, "L" }, /* 24 */ + { 0x08, 26, 0, 2, "ST" }, /* 25 */ + { 0x0A, 27, 0, 2, "O" }, /* 26 */ + { 0x0B, 28, 0, 2, "OU" }, /* 27 */ + { 0x0C, 29, 0, 2, "T" }, /* 28 */ + { 0x0D, 30, 0, 2, "D" }, /* 29 */ + { 0x24, 31, 0, 2, "userCertificate" }, /* 30 */ + { 0x29, 32, 0, 2, "N" }, /* 31 */ + { 0x2A, 33, 0, 2, "G" }, /* 32 */ + { 0x2B, 34, 0, 2, "I" }, /* 33 */ + { 0x2D, 35, 0, 2, "ID" }, /* 34 */ + { 0x48, 0, 0, 2, "role" }, /* 35 */ + { 0x1D, 0, 1, 1, "id-ce" }, /* 36 */ + { 0x09, 38, 0, 2, "subjectDirectoryAttrs" }, /* 37 */ + { 0x0E, 39, 0, 2, "subjectKeyIdentifier" }, /* 38 */ + { 0x0F, 40, 0, 2, "keyUsage" }, /* 39 */ + { 0x10, 41, 0, 2, "privateKeyUsagePeriod" }, /* 40 */ + { 0x11, 42, 0, 2, "subjectAltName" }, /* 41 */ + { 0x12, 43, 0, 2, "issuerAltName" }, /* 42 */ + { 0x13, 44, 0, 2, "basicConstraints" }, /* 43 */ + { 0x14, 45, 0, 2, "crlNumber" }, /* 44 */ + { 0x15, 46, 0, 2, "reasonCode" }, /* 45 */ + { 0x17, 47, 0, 2, "holdInstructionCode" }, /* 46 */ + { 0x18, 48, 0, 2, "invalidityDate" }, /* 47 */ + { 0x1B, 49, 0, 2, "deltaCrlIndicator" }, /* 48 */ + { 0x1C, 50, 0, 2, "issuingDistributionPoint" }, /* 49 */ + { 0x1D, 51, 0, 2, "certificateIssuer" }, /* 50 */ + { 0x1E, 52, 0, 2, "nameConstraints" }, /* 51 */ + { 0x1F, 53, 0, 2, "crlDistributionPoints" }, /* 52 */ + { 0x20, 55, 1, 2, "certificatePolicies" }, /* 53 */ + { 0x00, 0, 0, 3, "anyPolicy" }, /* 54 */ + { 0x21, 56, 0, 2, "policyMappings" }, /* 55 */ + { 0x23, 57, 0, 2, "authorityKeyIdentifier" }, /* 56 */ + { 0x24, 58, 0, 2, "policyConstraints" }, /* 57 */ + { 0x25, 60, 1, 2, "extendedKeyUsage" }, /* 58 */ + { 0x00, 0, 0, 3, "anyExtendedKeyUsage" }, /* 59 */ + { 0x2E, 61, 0, 2, "freshestCRL" }, /* 60 */ + { 0x36, 62, 0, 2, "inhibitAnyPolicy" }, /* 61 */ + { 0x37, 63, 0, 2, "targetInformation" }, /* 62 */ + { 0x38, 0, 0, 2, "noRevAvail" }, /* 63 */ + {0x2A, 161, 1, 0, "" }, /* 64 */ + { 0x83, 77, 1, 1, "" }, /* 65 */ + { 0x08, 0, 1, 2, "jp" }, /* 66 */ + { 0x8C, 0, 1, 3, "" }, /* 67 */ + { 0x9A, 0, 1, 4, "" }, /* 68 */ + { 0x4B, 0, 1, 5, "" }, /* 69 */ + { 0x3D, 0, 1, 6, "" }, /* 70 */ + { 0x01, 0, 1, 7, "security" }, /* 71 */ + { 0x01, 0, 1, 8, "algorithm" }, /* 72 */ + { 0x01, 0, 1, 9, "symm-encryption-alg" }, /* 73 */ + { 0x02, 75, 0, 10, "camellia128-cbc" }, /* 74 */ + { 0x03, 76, 0, 10, "camellia192-cbc" }, /* 75 */ + { 0x04, 0, 0, 10, "camellia256-cbc" }, /* 76 */ + { 0x86, 0, 1, 1, "" }, /* 77 */ + { 0x48, 0, 1, 2, "us" }, /* 78 */ + { 0x86, 120, 1, 3, "" }, /* 79 */ + { 0xF6, 85, 1, 4, "" }, /* 80 */ + { 0x7D, 0, 1, 5, "NortelNetworks" }, /* 81 */ + { 0x07, 0, 1, 6, "Entrust" }, /* 82 */ + { 0x41, 0, 1, 7, "nsn-ce" }, /* 83 */ + { 0x00, 0, 0, 8, "entrustVersInfo" }, /* 84 */ + { 0xF7, 0, 1, 4, "" }, /* 85 */ + { 0x0D, 0, 1, 5, "RSADSI" }, /* 86 */ + { 0x01, 115, 1, 6, "PKCS" }, /* 87 */ + { 0x01, 97, 1, 7, "PKCS-1" }, /* 88 */ + { 0x01, 90, 0, 8, "rsaEncryption" }, /* 89 */ + { 0x02, 91, 0, 8, "md2WithRSAEncryption" }, /* 90 */ + { 0x04, 92, 0, 8, "md5WithRSAEncryption" }, /* 91 */ + { 0x05, 93, 0, 8, "sha-1WithRSAEncryption" }, /* 92 */ + { 0x0B, 94, 0, 8, "sha256WithRSAEncryption" }, /* 93 */ + { 0x0C, 95, 0, 8, "sha384WithRSAEncryption" }, /* 94 */ + { 0x0D, 96, 0, 8, "sha512WithRSAEncryption" }, /* 95 */ + { 0x0E, 0, 0, 8, "sha224WithRSAEncryption" }, /* 96 */ + { 0x07, 104, 1, 7, "PKCS-7" }, /* 97 */ + { 0x01, 99, 0, 8, "data" }, /* 98 */ + { 0x02, 100, 0, 8, "signedData" }, /* 99 */ + { 0x03, 101, 0, 8, "envelopedData" }, /* 100 */ + { 0x04, 102, 0, 8, "signedAndEnvelopedData" }, /* 101 */ + { 0x05, 103, 0, 8, "digestedData" }, /* 102 */ + { 0x06, 0, 0, 8, "encryptedData" }, /* 103 */ + { 0x09, 0, 1, 7, "PKCS-9" }, /* 104 */ + { 0x01, 106, 0, 8, "E" }, /* 105 */ + { 0x02, 107, 0, 8, "unstructuredName" }, /* 106 */ + { 0x03, 108, 0, 8, "contentType" }, /* 107 */ + { 0x04, 109, 0, 8, "messageDigest" }, /* 108 */ + { 0x05, 110, 0, 8, "signingTime" }, /* 109 */ + { 0x06, 111, 0, 8, "counterSignature" }, /* 110 */ + { 0x07, 112, 0, 8, "challengePassword" }, /* 111 */ + { 0x08, 113, 0, 8, "unstructuredAddress" }, /* 112 */ + { 0x0E, 114, 0, 8, "extensionRequest" }, /* 113 */ + { 0x0F, 0, 0, 8, "S/MIME Capabilities" }, /* 114 */ + { 0x02, 118, 1, 6, "digestAlgorithm" }, /* 115 */ + { 0x02, 117, 0, 7, "md2" }, /* 116 */ + { 0x05, 0, 0, 7, "md5" }, /* 117 */ + { 0x03, 0, 1, 6, "encryptionAlgorithm" }, /* 118 */ + { 0x07, 0, 0, 7, "3des-ede-cbc" }, /* 119 */ + { 0xCE, 0, 1, 3, "" }, /* 120 */ + { 0x3D, 0, 1, 4, "ansi-X9-62" }, /* 121 */ + { 0x02, 124, 1, 5, "id-publicKeyType" }, /* 122 */ + { 0x01, 0, 0, 6, "id-ecPublicKey" }, /* 123 */ + { 0x03, 154, 1, 5, "ellipticCurve" }, /* 124 */ + { 0x00, 146, 1, 6, "c-TwoCurve" }, /* 125 */ + { 0x01, 127, 0, 7, "c2pnb163v1" }, /* 126 */ + { 0x02, 128, 0, 7, "c2pnb163v2" }, /* 127 */ + { 0x03, 129, 0, 7, "c2pnb163v3" }, /* 128 */ + { 0x04, 130, 0, 7, "c2pnb176w1" }, /* 129 */ + { 0x05, 131, 0, 7, "c2tnb191v1" }, /* 130 */ + { 0x06, 132, 0, 7, "c2tnb191v2" }, /* 131 */ + { 0x07, 133, 0, 7, "c2tnb191v3" }, /* 132 */ + { 0x08, 134, 0, 7, "c2onb191v4" }, /* 133 */ + { 0x09, 135, 0, 7, "c2onb191v5" }, /* 134 */ + { 0x0A, 136, 0, 7, "c2pnb208w1" }, /* 135 */ + { 0x0B, 137, 0, 7, "c2tnb239v1" }, /* 136 */ + { 0x0C, 138, 0, 7, "c2tnb239v2" }, /* 137 */ + { 0x0D, 139, 0, 7, "c2tnb239v3" }, /* 138 */ + { 0x0E, 140, 0, 7, "c2onb239v4" }, /* 139 */ + { 0x0F, 141, 0, 7, "c2onb239v5" }, /* 140 */ + { 0x10, 142, 0, 7, "c2pnb272w1" }, /* 141 */ + { 0x11, 143, 0, 7, "c2pnb304w1" }, /* 142 */ + { 0x12, 144, 0, 7, "c2tnb359v1" }, /* 143 */ + { 0x13, 145, 0, 7, "c2pnb368w1" }, /* 144 */ + { 0x14, 0, 0, 7, "c2tnb431r1" }, /* 145 */ + { 0x01, 0, 1, 6, "primeCurve" }, /* 146 */ + { 0x01, 148, 0, 7, "prime192v1" }, /* 147 */ + { 0x02, 149, 0, 7, "prime192v2" }, /* 148 */ + { 0x03, 150, 0, 7, "prime192v3" }, /* 149 */ + { 0x04, 151, 0, 7, "prime239v1" }, /* 150 */ + { 0x05, 152, 0, 7, "prime239v2" }, /* 151 */ + { 0x06, 153, 0, 7, "prime239v3" }, /* 152 */ + { 0x07, 0, 0, 7, "prime256v1" }, /* 153 */ + { 0x04, 0, 1, 5, "id-ecSigType" }, /* 154 */ + { 0x01, 156, 0, 6, "ecdsa-with-SHA1" }, /* 155 */ + { 0x03, 0, 1, 6, "ecdsa-with-Specified" }, /* 156 */ + { 0x01, 158, 0, 7, "ecdsa-with-SHA224" }, /* 157 */ + { 0x02, 159, 0, 7, "ecdsa-with-SHA256" }, /* 158 */ + { 0x03, 160, 0, 7, "ecdsa-with-SHA384" }, /* 159 */ + { 0x04, 0, 0, 7, "ecdsa-with-SHA512" }, /* 160 */ + {0x2B, 312, 1, 0, "" }, /* 161 */ + { 0x06, 226, 1, 1, "dod" }, /* 162 */ + { 0x01, 0, 1, 2, "internet" }, /* 163 */ + { 0x04, 186, 1, 3, "private" }, /* 164 */ + { 0x01, 0, 1, 4, "enterprise" }, /* 165 */ + { 0x82, 179, 1, 5, "" }, /* 166 */ + { 0x37, 176, 1, 6, "Microsoft" }, /* 167 */ + { 0x0A, 172, 1, 7, "" }, /* 168 */ + { 0x03, 0, 1, 8, "" }, /* 169 */ + { 0x03, 171, 0, 9, "msSGC" }, /* 170 */ + { 0x04, 0, 0, 9, "msEncryptingFileSystem" }, /* 171 */ + { 0x14, 0, 1, 7, "msEnrollmentInfrastructure"}, /* 172 */ + { 0x02, 0, 1, 8, "msCertificateTypeExtension"}, /* 173 */ + { 0x02, 175, 0, 9, "msSmartcardLogon" }, /* 174 */ + { 0x03, 0, 0, 9, "msUPN" }, /* 175 */ + { 0xA0, 0, 1, 6, "" }, /* 176 */ + { 0x2A, 0, 1, 7, "ITA" }, /* 177 */ + { 0x01, 0, 0, 8, "strongSwan" }, /* 178 */ + { 0x89, 0, 1, 5, "" }, /* 179 */ + { 0x31, 0, 1, 6, "" }, /* 180 */ + { 0x01, 0, 1, 7, "" }, /* 181 */ + { 0x01, 0, 1, 8, "" }, /* 182 */ + { 0x02, 0, 1, 9, "" }, /* 183 */ + { 0x02, 0, 1, 10, "" }, /* 184 */ + { 0x4B, 0, 0, 11, "TCGID" }, /* 185 */ + { 0x05, 0, 1, 3, "security" }, /* 186 */ + { 0x05, 0, 1, 4, "mechanisms" }, /* 187 */ + { 0x07, 0, 1, 5, "id-pkix" }, /* 188 */ + { 0x01, 193, 1, 6, "id-pe" }, /* 189 */ + { 0x01, 191, 0, 7, "authorityInfoAccess" }, /* 190 */ + { 0x03, 192, 0, 7, "qcStatements" }, /* 191 */ + { 0x07, 0, 0, 7, "ipAddrBlocks" }, /* 192 */ + { 0x02, 196, 1, 6, "id-qt" }, /* 193 */ + { 0x01, 195, 0, 7, "cps" }, /* 194 */ + { 0x02, 0, 0, 7, "unotice" }, /* 195 */ + { 0x03, 206, 1, 6, "id-kp" }, /* 196 */ + { 0x01, 198, 0, 7, "serverAuth" }, /* 197 */ + { 0x02, 199, 0, 7, "clientAuth" }, /* 198 */ + { 0x03, 200, 0, 7, "codeSigning" }, /* 199 */ + { 0x04, 201, 0, 7, "emailProtection" }, /* 200 */ + { 0x05, 202, 0, 7, "ipsecEndSystem" }, /* 201 */ + { 0x06, 203, 0, 7, "ipsecTunnel" }, /* 202 */ + { 0x07, 204, 0, 7, "ipsecUser" }, /* 203 */ + { 0x08, 205, 0, 7, "timeStamping" }, /* 204 */ + { 0x09, 0, 0, 7, "ocspSigning" }, /* 205 */ + { 0x08, 208, 1, 6, "id-otherNames" }, /* 206 */ + { 0x05, 0, 0, 7, "xmppAddr" }, /* 207 */ + { 0x0A, 213, 1, 6, "id-aca" }, /* 208 */ + { 0x01, 210, 0, 7, "authenticationInfo" }, /* 209 */ + { 0x02, 211, 0, 7, "accessIdentity" }, /* 210 */ + { 0x03, 212, 0, 7, "chargingIdentity" }, /* 211 */ + { 0x04, 0, 0, 7, "group" }, /* 212 */ + { 0x0B, 214, 0, 6, "subjectInfoAccess" }, /* 213 */ + { 0x30, 0, 1, 6, "id-ad" }, /* 214 */ + { 0x01, 223, 1, 7, "ocsp" }, /* 215 */ + { 0x01, 217, 0, 8, "basic" }, /* 216 */ + { 0x02, 218, 0, 8, "nonce" }, /* 217 */ + { 0x03, 219, 0, 8, "crl" }, /* 218 */ + { 0x04, 220, 0, 8, "response" }, /* 219 */ + { 0x05, 221, 0, 8, "noCheck" }, /* 220 */ + { 0x06, 222, 0, 8, "archiveCutoff" }, /* 221 */ + { 0x07, 0, 0, 8, "serviceLocator" }, /* 222 */ + { 0x02, 224, 0, 7, "caIssuers" }, /* 223 */ + { 0x03, 225, 0, 7, "timeStamping" }, /* 224 */ + { 0x05, 0, 0, 7, "caRepository" }, /* 225 */ + { 0x0E, 232, 1, 1, "oiw" }, /* 226 */ + { 0x03, 0, 1, 2, "secsig" }, /* 227 */ + { 0x02, 0, 1, 3, "algorithms" }, /* 228 */ + { 0x07, 230, 0, 4, "des-cbc" }, /* 229 */ + { 0x1A, 231, 0, 4, "sha-1" }, /* 230 */ + { 0x1D, 0, 0, 4, "sha-1WithRSASignature" }, /* 231 */ + { 0x24, 278, 1, 1, "TeleTrusT" }, /* 232 */ + { 0x03, 0, 1, 2, "algorithm" }, /* 233 */ + { 0x03, 0, 1, 3, "signatureAlgorithm" }, /* 234 */ + { 0x01, 239, 1, 4, "rsaSignature" }, /* 235 */ + { 0x02, 237, 0, 5, "rsaSigWithripemd160" }, /* 236 */ + { 0x03, 238, 0, 5, "rsaSigWithripemd128" }, /* 237 */ + { 0x04, 0, 0, 5, "rsaSigWithripemd256" }, /* 238 */ + { 0x02, 0, 1, 4, "ecSign" }, /* 239 */ + { 0x01, 241, 0, 5, "ecSignWithsha1" }, /* 240 */ + { 0x02, 242, 0, 5, "ecSignWithripemd160" }, /* 241 */ + { 0x03, 243, 0, 5, "ecSignWithmd2" }, /* 242 */ + { 0x04, 244, 0, 5, "ecSignWithmd5" }, /* 243 */ + { 0x05, 261, 1, 5, "ttt-ecg" }, /* 244 */ + { 0x01, 249, 1, 6, "fieldType" }, /* 245 */ + { 0x01, 0, 1, 7, "characteristictwoField" }, /* 246 */ + { 0x01, 0, 1, 8, "basisType" }, /* 247 */ + { 0x01, 0, 0, 9, "ipBasis" }, /* 248 */ + { 0x02, 251, 1, 6, "keyType" }, /* 249 */ + { 0x01, 0, 0, 7, "ecgPublicKey" }, /* 250 */ + { 0x03, 252, 0, 6, "curve" }, /* 251 */ + { 0x04, 259, 1, 6, "signatures" }, /* 252 */ + { 0x01, 254, 0, 7, "ecgdsa-with-RIPEMD160" }, /* 253 */ + { 0x02, 255, 0, 7, "ecgdsa-with-SHA1" }, /* 254 */ + { 0x03, 256, 0, 7, "ecgdsa-with-SHA224" }, /* 255 */ + { 0x04, 257, 0, 7, "ecgdsa-with-SHA256" }, /* 256 */ + { 0x05, 258, 0, 7, "ecgdsa-with-SHA384" }, /* 257 */ + { 0x06, 0, 0, 7, "ecgdsa-with-SHA512" }, /* 258 */ + { 0x05, 0, 1, 6, "module" }, /* 259 */ + { 0x01, 0, 0, 7, "1" }, /* 260 */ + { 0x08, 0, 1, 5, "ecStdCurvesAndGeneration" }, /* 261 */ + { 0x01, 0, 1, 6, "ellipticCurve" }, /* 262 */ + { 0x01, 0, 1, 7, "versionOne" }, /* 263 */ + { 0x01, 265, 0, 8, "brainpoolP160r1" }, /* 264 */ + { 0x02, 266, 0, 8, "brainpoolP160t1" }, /* 265 */ + { 0x03, 267, 0, 8, "brainpoolP192r1" }, /* 266 */ + { 0x04, 268, 0, 8, "brainpoolP192t1" }, /* 267 */ + { 0x05, 269, 0, 8, "brainpoolP224r1" }, /* 268 */ + { 0x06, 270, 0, 8, "brainpoolP224t1" }, /* 269 */ + { 0x07, 271, 0, 8, "brainpoolP256r1" }, /* 270 */ + { 0x08, 272, 0, 8, "brainpoolP256t1" }, /* 271 */ + { 0x09, 273, 0, 8, "brainpoolP320r1" }, /* 272 */ + { 0x0A, 274, 0, 8, "brainpoolP320t1" }, /* 273 */ + { 0x0B, 275, 0, 8, "brainpoolP384r1" }, /* 274 */ + { 0x0C, 276, 0, 8, "brainpoolP384t1" }, /* 275 */ + { 0x0D, 277, 0, 8, "brainpoolP512r1" }, /* 276 */ + { 0x0E, 0, 0, 8, "brainpoolP512t1" }, /* 277 */ + { 0x81, 0, 1, 1, "" }, /* 278 */ + { 0x04, 0, 1, 2, "Certicom" }, /* 279 */ + { 0x00, 0, 1, 3, "curve" }, /* 280 */ + { 0x01, 282, 0, 4, "sect163k1" }, /* 281 */ + { 0x02, 283, 0, 4, "sect163r1" }, /* 282 */ + { 0x03, 284, 0, 4, "sect239k1" }, /* 283 */ + { 0x04, 285, 0, 4, "sect113r1" }, /* 284 */ + { 0x05, 286, 0, 4, "sect113r2" }, /* 285 */ + { 0x06, 287, 0, 4, "secp112r1" }, /* 286 */ + { 0x07, 288, 0, 4, "secp112r2" }, /* 287 */ + { 0x08, 289, 0, 4, "secp160r1" }, /* 288 */ + { 0x09, 290, 0, 4, "secp160k1" }, /* 289 */ + { 0x0A, 291, 0, 4, "secp256k1" }, /* 290 */ + { 0x0F, 292, 0, 4, "sect163r2" }, /* 291 */ + { 0x10, 293, 0, 4, "sect283k1" }, /* 292 */ + { 0x11, 294, 0, 4, "sect283r1" }, /* 293 */ + { 0x16, 295, 0, 4, "sect131r1" }, /* 294 */ + { 0x17, 296, 0, 4, "sect131r2" }, /* 295 */ + { 0x18, 297, 0, 4, "sect193r1" }, /* 296 */ + { 0x19, 298, 0, 4, "sect193r2" }, /* 297 */ + { 0x1A, 299, 0, 4, "sect233k1" }, /* 298 */ + { 0x1B, 300, 0, 4, "sect233r1" }, /* 299 */ + { 0x1C, 301, 0, 4, "secp128r1" }, /* 300 */ + { 0x1D, 302, 0, 4, "secp128r2" }, /* 301 */ + { 0x1E, 303, 0, 4, "secp160r2" }, /* 302 */ + { 0x1F, 304, 0, 4, "secp192k1" }, /* 303 */ + { 0x20, 305, 0, 4, "secp224k1" }, /* 304 */ + { 0x21, 306, 0, 4, "secp224r1" }, /* 305 */ + { 0x22, 307, 0, 4, "secp384r1" }, /* 306 */ + { 0x23, 308, 0, 4, "secp521r1" }, /* 307 */ + { 0x24, 309, 0, 4, "sect409k1" }, /* 308 */ + { 0x25, 310, 0, 4, "sect409r1" }, /* 309 */ + { 0x26, 311, 0, 4, "sect571k1" }, /* 310 */ + { 0x27, 0, 0, 4, "sect571r1" }, /* 311 */ + {0x60, 0, 1, 0, "" }, /* 312 */ + { 0x86, 0, 1, 1, "" }, /* 313 */ + { 0x48, 0, 1, 2, "" }, /* 314 */ + { 0x01, 0, 1, 3, "organization" }, /* 315 */ + { 0x65, 334, 1, 4, "gov" }, /* 316 */ + { 0x03, 0, 1, 5, "csor" }, /* 317 */ + { 0x04, 0, 1, 6, "nistalgorithm" }, /* 318 */ + { 0x01, 329, 1, 7, "aes" }, /* 319 */ + { 0x02, 321, 0, 8, "id-aes128-CBC" }, /* 320 */ + { 0x06, 322, 0, 8, "id-aes128-GCM" }, /* 321 */ + { 0x07, 323, 0, 8, "id-aes128-CCM" }, /* 322 */ + { 0x16, 324, 0, 8, "id-aes192-CBC" }, /* 323 */ + { 0x1A, 325, 0, 8, "id-aes192-GCM" }, /* 324 */ + { 0x1B, 326, 0, 8, "id-aes192-CCM" }, /* 325 */ + { 0x2A, 327, 0, 8, "id-aes256-CBC" }, /* 326 */ + { 0x2E, 328, 0, 8, "id-aes256-GCM" }, /* 327 */ + { 0x2F, 0, 0, 8, "id-aes256-CCM" }, /* 328 */ + { 0x02, 0, 1, 7, "hashalgs" }, /* 329 */ + { 0x01, 331, 0, 8, "id-SHA-256" }, /* 330 */ + { 0x02, 332, 0, 8, "id-SHA-384" }, /* 331 */ + { 0x03, 333, 0, 8, "id-SHA-512" }, /* 332 */ + { 0x04, 0, 0, 8, "id-SHA-224" }, /* 333 */ + { 0x86, 0, 1, 4, "" }, /* 334 */ + { 0xf8, 0, 1, 5, "" }, /* 335 */ + { 0x42, 348, 1, 6, "netscape" }, /* 336 */ + { 0x01, 343, 1, 7, "" }, /* 337 */ + { 0x01, 339, 0, 8, "nsCertType" }, /* 338 */ + { 0x03, 340, 0, 8, "nsRevocationUrl" }, /* 339 */ + { 0x04, 341, 0, 8, "nsCaRevocationUrl" }, /* 340 */ + { 0x08, 342, 0, 8, "nsCaPolicyUrl" }, /* 341 */ + { 0x0d, 0, 0, 8, "nsComment" }, /* 342 */ + { 0x03, 346, 1, 7, "directory" }, /* 343 */ + { 0x01, 0, 1, 8, "" }, /* 344 */ + { 0x03, 0, 0, 9, "employeeNumber" }, /* 345 */ + { 0x04, 0, 1, 7, "policy" }, /* 346 */ + { 0x01, 0, 0, 8, "nsSGC" }, /* 347 */ + { 0x45, 0, 1, 6, "verisign" }, /* 348 */ + { 0x01, 0, 1, 7, "pki" }, /* 349 */ + { 0x09, 0, 1, 8, "attributes" }, /* 350 */ + { 0x02, 352, 0, 9, "messageType" }, /* 351 */ + { 0x03, 353, 0, 9, "pkiStatus" }, /* 352 */ + { 0x04, 354, 0, 9, "failInfo" }, /* 353 */ + { 0x05, 355, 0, 9, "senderNonce" }, /* 354 */ + { 0x06, 356, 0, 9, "recipientNonce" }, /* 355 */ + { 0x07, 357, 0, 9, "transID" }, /* 356 */ + { 0x08, 358, 0, 9, "extensionReq" }, /* 357 */ + { 0x08, 0, 0, 9, "extensionReq" } /* 358 */ }; diff --git a/src/libstrongswan/asn1/oid.h b/src/libstrongswan/asn1/oid.h index 16c9e854b..b6ee9a10d 100644 --- a/src/libstrongswan/asn1/oid.h +++ b/src/libstrongswan/asn1/oid.h @@ -49,8 +49,11 @@ extern const oid_t oid_names[]; #define OID_DELTA_CRL_INDICATOR 48 #define OID_NAME_CONSTRAINTS 51 #define OID_CRL_DISTRIBUTION_POINTS 52 +#define OID_CERTIFICATE_POLICIES 53 #define OID_ANY_POLICY 54 +#define OID_POLICY_MAPPINGS 55 #define OID_AUTHORITY_KEY_ID 56 +#define OID_POLICY_CONSTRAINTS 57 #define OID_EXTENDED_KEY_USAGE 58 #define OID_FRESHEST_CRL 60 #define OID_INHIBIT_ANY_POLICY 61 @@ -117,92 +120,95 @@ extern const oid_t oid_names[]; #define OID_ECDSA_WITH_SHA384 159 #define OID_ECDSA_WITH_SHA512 160 #define OID_USER_PRINCIPAL_NAME 175 -#define OID_TCGID 182 -#define OID_AUTHORITY_INFO_ACCESS 187 -#define OID_IP_ADDR_BLOCKS 189 -#define OID_SERVER_AUTH 194 -#define OID_CLIENT_AUTH 195 -#define OID_OCSP_SIGNING 202 -#define OID_XMPP_ADDR 204 -#define OID_AUTHENTICATION_INFO 206 -#define OID_ACCESS_IDENTITY 207 -#define OID_CHARGING_IDENTITY 208 -#define OID_GROUP 209 -#define OID_OCSP 212 -#define OID_BASIC 213 -#define OID_NONCE 214 -#define OID_CRL 215 -#define OID_RESPONSE 216 -#define OID_NO_CHECK 217 -#define OID_ARCHIVE_CUTOFF 218 -#define OID_SERVICE_LOCATOR 219 -#define OID_CA_ISSUERS 220 -#define OID_DES_CBC 226 -#define OID_SHA1 227 -#define OID_SHA1_WITH_RSA_OIW 228 -#define OID_ECGDSA_PUBKEY 247 -#define OID_ECGDSA_SIG_WITH_RIPEMD160 250 -#define OID_ECGDSA_SIG_WITH_SHA1 251 -#define OID_ECGDSA_SIG_WITH_SHA224 252 -#define OID_ECGDSA_SIG_WITH_SHA256 253 -#define OID_ECGDSA_SIG_WITH_SHA384 254 -#define OID_ECGDSA_SIG_WITH_SHA512 255 -#define OID_SECT163K1 278 -#define OID_SECT163R1 279 -#define OID_SECT239K1 280 -#define OID_SECT113R1 281 -#define OID_SECT113R2 282 -#define OID_SECT112R1 283 -#define OID_SECT112R2 284 -#define OID_SECT160R1 285 -#define OID_SECT160K1 286 -#define OID_SECT256K1 287 -#define OID_SECT163R2 288 -#define OID_SECT283K1 289 -#define OID_SECT283R1 290 -#define OID_SECT131R1 291 -#define OID_SECT131R2 292 -#define OID_SECT193R1 293 -#define OID_SECT193R2 294 -#define OID_SECT233K1 295 -#define OID_SECT233R1 296 -#define OID_SECT128R1 297 -#define OID_SECT128R2 298 -#define OID_SECT160R2 299 -#define OID_SECT192K1 300 -#define OID_SECT224K1 301 -#define OID_SECT224R1 302 -#define OID_SECT384R1 303 -#define OID_SECT521R1 304 -#define OID_SECT409K1 305 -#define OID_SECT409R1 306 -#define OID_SECT571K1 307 -#define OID_SECT571R1 308 -#define OID_AES128_CBC 317 -#define OID_AES128_GCM 318 -#define OID_AES128_CCM 319 -#define OID_AES192_CBC 320 -#define OID_AES192_GCM 321 -#define OID_AES192_CCM 322 -#define OID_AES256_CBC 323 -#define OID_AES256_GCM 324 -#define OID_AES256_CCM 325 -#define OID_SHA256 327 -#define OID_SHA384 328 -#define OID_SHA512 329 -#define OID_SHA224 330 -#define OID_NS_REVOCATION_URL 336 -#define OID_NS_CA_REVOCATION_URL 337 -#define OID_NS_CA_POLICY_URL 338 -#define OID_NS_COMMENT 339 -#define OID_EMPLOYEE_NUMBER 342 -#define OID_PKI_MESSAGE_TYPE 348 -#define OID_PKI_STATUS 349 -#define OID_PKI_FAIL_INFO 350 -#define OID_PKI_SENDER_NONCE 351 -#define OID_PKI_RECIPIENT_NONCE 352 -#define OID_PKI_TRANS_ID 353 +#define OID_STRONGSWAN 178 +#define OID_TCGID 185 +#define OID_AUTHORITY_INFO_ACCESS 190 +#define OID_IP_ADDR_BLOCKS 192 +#define OID_POLICY_QUALIFIER_CPS 194 +#define OID_POLICY_QUALIFIER_UNOTICE 195 +#define OID_SERVER_AUTH 197 +#define OID_CLIENT_AUTH 198 +#define OID_OCSP_SIGNING 205 +#define OID_XMPP_ADDR 207 +#define OID_AUTHENTICATION_INFO 209 +#define OID_ACCESS_IDENTITY 210 +#define OID_CHARGING_IDENTITY 211 +#define OID_GROUP 212 +#define OID_OCSP 215 +#define OID_BASIC 216 +#define OID_NONCE 217 +#define OID_CRL 218 +#define OID_RESPONSE 219 +#define OID_NO_CHECK 220 +#define OID_ARCHIVE_CUTOFF 221 +#define OID_SERVICE_LOCATOR 222 +#define OID_CA_ISSUERS 223 +#define OID_DES_CBC 229 +#define OID_SHA1 230 +#define OID_SHA1_WITH_RSA_OIW 231 +#define OID_ECGDSA_PUBKEY 250 +#define OID_ECGDSA_SIG_WITH_RIPEMD160 253 +#define OID_ECGDSA_SIG_WITH_SHA1 254 +#define OID_ECGDSA_SIG_WITH_SHA224 255 +#define OID_ECGDSA_SIG_WITH_SHA256 256 +#define OID_ECGDSA_SIG_WITH_SHA384 257 +#define OID_ECGDSA_SIG_WITH_SHA512 258 +#define OID_SECT163K1 281 +#define OID_SECT163R1 282 +#define OID_SECT239K1 283 +#define OID_SECT113R1 284 +#define OID_SECT113R2 285 +#define OID_SECT112R1 286 +#define OID_SECT112R2 287 +#define OID_SECT160R1 288 +#define OID_SECT160K1 289 +#define OID_SECT256K1 290 +#define OID_SECT163R2 291 +#define OID_SECT283K1 292 +#define OID_SECT283R1 293 +#define OID_SECT131R1 294 +#define OID_SECT131R2 295 +#define OID_SECT193R1 296 +#define OID_SECT193R2 297 +#define OID_SECT233K1 298 +#define OID_SECT233R1 299 +#define OID_SECT128R1 300 +#define OID_SECT128R2 301 +#define OID_SECT160R2 302 +#define OID_SECT192K1 303 +#define OID_SECT224K1 304 +#define OID_SECT224R1 305 +#define OID_SECT384R1 306 +#define OID_SECT521R1 307 +#define OID_SECT409K1 308 +#define OID_SECT409R1 309 +#define OID_SECT571K1 310 +#define OID_SECT571R1 311 +#define OID_AES128_CBC 320 +#define OID_AES128_GCM 321 +#define OID_AES128_CCM 322 +#define OID_AES192_CBC 323 +#define OID_AES192_GCM 324 +#define OID_AES192_CCM 325 +#define OID_AES256_CBC 326 +#define OID_AES256_GCM 327 +#define OID_AES256_CCM 328 +#define OID_SHA256 330 +#define OID_SHA384 331 +#define OID_SHA512 332 +#define OID_SHA224 333 +#define OID_NS_REVOCATION_URL 339 +#define OID_NS_CA_REVOCATION_URL 340 +#define OID_NS_CA_POLICY_URL 341 +#define OID_NS_COMMENT 342 +#define OID_EMPLOYEE_NUMBER 345 +#define OID_PKI_MESSAGE_TYPE 351 +#define OID_PKI_STATUS 352 +#define OID_PKI_FAIL_INFO 353 +#define OID_PKI_SENDER_NONCE 354 +#define OID_PKI_RECIPIENT_NONCE 355 +#define OID_PKI_TRANS_ID 356 -#define OID_MAX 356 +#define OID_MAX 359 #endif /* OID_H_ */ diff --git a/src/libstrongswan/asn1/oid.txt b/src/libstrongswan/asn1/oid.txt index 36db0299c..e2931c7dd 100644 --- a/src/libstrongswan/asn1/oid.txt +++ b/src/libstrongswan/asn1/oid.txt @@ -51,11 +51,11 @@ 0x1D "certificateIssuer" 0x1E "nameConstraints" OID_NAME_CONSTRAINTS 0x1F "crlDistributionPoints" OID_CRL_DISTRIBUTION_POINTS - 0x20 "certificatePolicies" + 0x20 "certificatePolicies" OID_CERTIFICATE_POLICIES 0x00 "anyPolicy" OID_ANY_POLICY - 0x21 "policyMappings" + 0x21 "policyMappings" OID_POLICY_MAPPINGS 0x23 "authorityKeyIdentifier" OID_AUTHORITY_KEY_ID - 0x24 "policyConstraints" + 0x24 "policyConstraints" OID_POLICY_CONSTRAINTS 0x25 "extendedKeyUsage" OID_EXTENDED_KEY_USAGE 0x00 "anyExtendedKeyUsage" 0x2E "freshestCRL" OID_FRESHEST_CRL @@ -124,7 +124,7 @@ 0x01 "id-ecPublicKey" OID_EC_PUBLICKEY 0x03 "ellipticCurve" 0x00 "c-TwoCurve" - 0x01 "c2pnb163v1" OID_C2PNB163V1 + 0x01 "c2pnb163v1" OID_C2PNB163V1 0x02 "c2pnb163v2" OID_C2PNB163V2 0x03 "c2pnb163v3" OID_C2PNB163V3 0x04 "c2pnb176w1" OID_C2PNB176W1 @@ -174,13 +174,16 @@ 0x02 "msCertificateTypeExtension" 0x02 "msSmartcardLogon" 0x03 "msUPN" OID_USER_PRINCIPAL_NAME + 0xA0 "" + 0x2A "ITA" + 0x01 "strongSwan" OID_STRONGSWAN 0x89 "" 0x31 "" 0x01 "" 0x01 "" 0x02 "" 0x02 "" - 0x4B "TCGID" OID_TCGID + 0x4B "TCGID" OID_TCGID 0x05 "security" 0x05 "mechanisms" 0x07 "id-pkix" @@ -189,8 +192,8 @@ 0x03 "qcStatements" 0x07 "ipAddrBlocks" OID_IP_ADDR_BLOCKS 0x02 "id-qt" - 0x01 "cps" - 0x02 "unotice" + 0x01 "cps" OID_POLICY_QUALIFIER_CPS + 0x02 "unotice" OID_POLICY_QUALIFIER_UNOTICE 0x03 "id-kp" 0x01 "serverAuth" OID_SERVER_AUTH 0x02 "clientAuth" OID_CLIENT_AUTH diff --git a/src/libstrongswan/credentials/auth_cfg.c b/src/libstrongswan/credentials/auth_cfg.c index ce718b9cb..23a3f62d9 100644 --- a/src/libstrongswan/credentials/auth_cfg.c +++ b/src/libstrongswan/credentials/auth_cfg.c @@ -131,11 +131,13 @@ static void destroy_entry_value(entry_t *entry) case AUTH_RULE_SUBJECT_CERT: case AUTH_HELPER_IM_CERT: case AUTH_HELPER_SUBJECT_CERT: + case AUTH_HELPER_REVOCATION_CERT: { certificate_t *cert = (certificate_t*)entry->value; cert->destroy(cert); break; } + case AUTH_RULE_CERT_POLICY: case AUTH_HELPER_IM_HASH_URL: case AUTH_HELPER_SUBJECT_HASH_URL: { @@ -147,6 +149,8 @@ static void destroy_entry_value(entry_t *entry) case AUTH_RULE_EAP_VENDOR: case AUTH_RULE_CRL_VALIDATION: case AUTH_RULE_OCSP_VALIDATION: + case AUTH_RULE_RSA_STRENGTH: + case AUTH_RULE_ECDSA_STRENGTH: break; } } @@ -172,6 +176,8 @@ static void replace(auth_cfg_t *this, entry_enumerator_t *enumerator, case AUTH_RULE_EAP_VENDOR: case AUTH_RULE_CRL_VALIDATION: case AUTH_RULE_OCSP_VALIDATION: + case AUTH_RULE_RSA_STRENGTH: + case AUTH_RULE_ECDSA_STRENGTH: /* integer type */ enumerator->current->value = (void*)(uintptr_t)va_arg(args, u_int); break; @@ -182,10 +188,12 @@ static void replace(auth_cfg_t *this, entry_enumerator_t *enumerator, case AUTH_RULE_CA_CERT: case AUTH_RULE_IM_CERT: case AUTH_RULE_SUBJECT_CERT: + case AUTH_RULE_CERT_POLICY: case AUTH_HELPER_IM_CERT: case AUTH_HELPER_SUBJECT_CERT: case AUTH_HELPER_IM_HASH_URL: case AUTH_HELPER_SUBJECT_HASH_URL: + case AUTH_HELPER_REVOCATION_CERT: /* pointer type */ enumerator->current->value = va_arg(args, void*); break; @@ -237,6 +245,8 @@ static void* get(private_auth_cfg_t *this, auth_rule_t type) case AUTH_RULE_EAP_TYPE: return (void*)EAP_NAK; case AUTH_RULE_EAP_VENDOR: + case AUTH_RULE_RSA_STRENGTH: + case AUTH_RULE_ECDSA_STRENGTH: return (void*)0; case AUTH_RULE_CRL_VALIDATION: case AUTH_RULE_OCSP_VALIDATION: @@ -248,10 +258,12 @@ static void* get(private_auth_cfg_t *this, auth_rule_t type) case AUTH_RULE_CA_CERT: case AUTH_RULE_IM_CERT: case AUTH_RULE_SUBJECT_CERT: + case AUTH_RULE_CERT_POLICY: case AUTH_HELPER_IM_CERT: case AUTH_HELPER_SUBJECT_CERT: case AUTH_HELPER_IM_HASH_URL: case AUTH_HELPER_SUBJECT_HASH_URL: + case AUTH_HELPER_REVOCATION_CERT: default: return NULL; } @@ -274,6 +286,8 @@ static void add(private_auth_cfg_t *this, auth_rule_t type, ...) case AUTH_RULE_EAP_VENDOR: case AUTH_RULE_CRL_VALIDATION: case AUTH_RULE_OCSP_VALIDATION: + case AUTH_RULE_RSA_STRENGTH: + case AUTH_RULE_ECDSA_STRENGTH: /* integer type */ entry->value = (void*)(uintptr_t)va_arg(args, u_int); break; @@ -284,10 +298,12 @@ static void add(private_auth_cfg_t *this, auth_rule_t type, ...) case AUTH_RULE_CA_CERT: case AUTH_RULE_IM_CERT: case AUTH_RULE_SUBJECT_CERT: + case AUTH_RULE_CERT_POLICY: case AUTH_HELPER_IM_CERT: case AUTH_HELPER_SUBJECT_CERT: case AUTH_HELPER_IM_HASH_URL: case AUTH_HELPER_SUBJECT_HASH_URL: + case AUTH_HELPER_REVOCATION_CERT: /* pointer type */ entry->value = va_arg(args, void*); break; @@ -358,38 +374,45 @@ static bool complies(private_auth_cfg_t *this, auth_cfg_t *constraints, case AUTH_RULE_CRL_VALIDATION: case AUTH_RULE_OCSP_VALIDATION: { - cert_validation_t validated, required; + uintptr_t validated; - required = (uintptr_t)value; - validated = (uintptr_t)get(this, t1); - switch (required) + e2 = create_enumerator(this); + while (e2->enumerate(e2, &t2, &validated)) { - case VALIDATION_FAILED: - /* no constraint */ - break; - case VALIDATION_SKIPPED: - if (validated == VALIDATION_SKIPPED) - { - break; - } - /* FALL */ - case VALIDATION_GOOD: - if (validated == VALIDATION_GOOD) - { - break; - } - /* FALL */ - default: - success = FALSE; - if (log_error) + if (t2 == t1) + { + switch ((uintptr_t)value) { - DBG1(DBG_CFG, "constraint check failed: %N is %N, " - "but requires at least %N", auth_rule_names, - t1, cert_validation_names, validated, - cert_validation_names, required); + case VALIDATION_FAILED: + /* no constraint */ + break; + case VALIDATION_SKIPPED: + if (validated == VALIDATION_SKIPPED) + { + break; + } + /* FALL */ + case VALIDATION_GOOD: + if (validated == VALIDATION_GOOD) + { + break; + } + /* FALL */ + default: + success = FALSE; + if (log_error) + { + DBG1(DBG_CFG, "constraint check failed: " + "%N is %N, but requires at least %N", + auth_rule_names, t1, + cert_validation_names, validated, + cert_validation_names, (uintptr_t)value); + } + break; } - break; + } } + e2->destroy(e2); break; } case AUTH_RULE_IDENTITY: @@ -473,10 +496,76 @@ static bool complies(private_auth_cfg_t *this, auth_cfg_t *constraints, e2->destroy(e2); break; } + case AUTH_RULE_RSA_STRENGTH: + case AUTH_RULE_ECDSA_STRENGTH: + { + uintptr_t strength; + + e2 = create_enumerator(this); + while (e2->enumerate(e2, &t2, &strength)) + { + if (t2 == t1) + { + if ((uintptr_t)value > strength) + { + success = FALSE; + if (log_error) + { + DBG1(DBG_CFG, "constraint requires %d bit " + "public keys, but %d bit key used", + (uintptr_t)value, strength); + } + } + } + else if (t2 == AUTH_RULE_RSA_STRENGTH) + { + success = FALSE; + if (log_error) + { + DBG1(DBG_CFG, "constraint requires %d bit ECDSA, " + "but RSA used", (uintptr_t)value); + } + } + else if (t2 == AUTH_RULE_ECDSA_STRENGTH) + { + success = FALSE; + if (log_error) + { + DBG1(DBG_CFG, "constraint requires %d bit RSA, " + "but ECDSA used", (uintptr_t)value); + } + } + } + e2->destroy(e2); + break; + } + case AUTH_RULE_CERT_POLICY: + { + char *oid1, *oid2; + + oid1 = (char*)value; + success = FALSE; + e2 = create_enumerator(this); + while (e2->enumerate(e2, &t2, &oid2)) + { + if (t2 == t1 && streq(oid1, oid2)) + { + success = TRUE; + break; + } + } + e2->destroy(e2); + if (!success && log_error) + { + DBG1(DBG_CFG, "constraint requires cert policy %s", oid1); + } + break; + } case AUTH_HELPER_IM_CERT: case AUTH_HELPER_SUBJECT_CERT: case AUTH_HELPER_IM_HASH_URL: case AUTH_HELPER_SUBJECT_HASH_URL: + case AUTH_HELPER_REVOCATION_CERT: /* skip helpers */ continue; } @@ -523,6 +612,7 @@ static void merge(private_auth_cfg_t *this, private_auth_cfg_t *other, bool copy case AUTH_RULE_SUBJECT_CERT: case AUTH_HELPER_IM_CERT: case AUTH_HELPER_SUBJECT_CERT: + case AUTH_HELPER_REVOCATION_CERT: { certificate_t *cert = (certificate_t*)value; @@ -534,6 +624,8 @@ static void merge(private_auth_cfg_t *this, private_auth_cfg_t *other, bool copy case AUTH_RULE_AUTH_CLASS: case AUTH_RULE_EAP_TYPE: case AUTH_RULE_EAP_VENDOR: + case AUTH_RULE_RSA_STRENGTH: + case AUTH_RULE_ECDSA_STRENGTH: { add(this, type, (uintptr_t)value); break; @@ -548,6 +640,7 @@ static void merge(private_auth_cfg_t *this, private_auth_cfg_t *other, bool copy add(this, type, id->clone(id)); break; } + case AUTH_RULE_CERT_POLICY: case AUTH_HELPER_IM_HASH_URL: case AUTH_HELPER_SUBJECT_HASH_URL: { @@ -600,6 +693,8 @@ static bool equals(private_auth_cfg_t *this, private_auth_cfg_t *other) case AUTH_RULE_EAP_VENDOR: case AUTH_RULE_CRL_VALIDATION: case AUTH_RULE_OCSP_VALIDATION: + case AUTH_RULE_RSA_STRENGTH: + case AUTH_RULE_ECDSA_STRENGTH: { if (i1->value == i2->value) { @@ -613,6 +708,7 @@ static bool equals(private_auth_cfg_t *this, private_auth_cfg_t *other) case AUTH_RULE_SUBJECT_CERT: case AUTH_HELPER_IM_CERT: case AUTH_HELPER_SUBJECT_CERT: + case AUTH_HELPER_REVOCATION_CERT: { certificate_t *c1, *c2; @@ -643,6 +739,7 @@ static bool equals(private_auth_cfg_t *this, private_auth_cfg_t *other) } continue; } + case AUTH_RULE_CERT_POLICY: case AUTH_HELPER_IM_HASH_URL: case AUTH_HELPER_SUBJECT_HASH_URL: { @@ -725,11 +822,13 @@ static auth_cfg_t* clone_(private_auth_cfg_t *this) case AUTH_RULE_SUBJECT_CERT: case AUTH_HELPER_IM_CERT: case AUTH_HELPER_SUBJECT_CERT: + case AUTH_HELPER_REVOCATION_CERT: { certificate_t *cert = (certificate_t*)entry->value; clone->add(clone, entry->type, cert->get_ref(cert)); break; } + case AUTH_RULE_CERT_POLICY: case AUTH_HELPER_IM_HASH_URL: case AUTH_HELPER_SUBJECT_HASH_URL: { @@ -741,6 +840,8 @@ static auth_cfg_t* clone_(private_auth_cfg_t *this) case AUTH_RULE_EAP_VENDOR: case AUTH_RULE_CRL_VALIDATION: case AUTH_RULE_OCSP_VALIDATION: + case AUTH_RULE_RSA_STRENGTH: + case AUTH_RULE_ECDSA_STRENGTH: clone->add(clone, entry->type, (uintptr_t)entry->value); break; } diff --git a/src/libstrongswan/credentials/auth_cfg.h b/src/libstrongswan/credentials/auth_cfg.h index 19624a2fe..489ce1134 100644 --- a/src/libstrongswan/credentials/auth_cfg.h +++ b/src/libstrongswan/credentials/auth_cfg.h @@ -90,6 +90,12 @@ enum auth_rule_t { * The group membership constraint is fulfilled if the subject is member of * one group defined in the constraints. */ AUTH_RULE_GROUP, + /** required RSA public key strength, u_int in bits */ + AUTH_RULE_RSA_STRENGTH, + /** required ECDSA public key strength, u_int in bits */ + AUTH_RULE_ECDSA_STRENGTH, + /** certificatePolicy constraint, numerical OID as char* */ + AUTH_RULE_CERT_POLICY, /** intermediate certificate, certificate_t* */ AUTH_HELPER_IM_CERT, @@ -99,6 +105,8 @@ enum auth_rule_t { AUTH_HELPER_IM_HASH_URL, /** Hash and URL of a end-entity certificate, char* */ AUTH_HELPER_SUBJECT_HASH_URL, + /** revocation certificate (CRL, OCSP), certificate_t* */ + AUTH_HELPER_REVOCATION_CERT, }; /** diff --git a/src/libstrongswan/credentials/builder.c b/src/libstrongswan/credentials/builder.c index c43e5fd5d..f9a277a2c 100644 --- a/src/libstrongswan/credentials/builder.c +++ b/src/libstrongswan/credentials/builder.c @@ -43,8 +43,16 @@ ENUM(builder_part_names, BUILD_FROM_FILE, BUILD_END, "BUILD_CRL_DISTRIBUTION_POINTS", "BUILD_OCSP_ACCESS_LOCATIONS", "BUILD_PATHLEN", + "BUILD_PERMITTED_NAME_CONSTRAINTS", + "BUILD_EXCLUDED_NAME_CONSTRAINTS", + "BUILD_CERTIFICATE_POLICIES", + "BUILD_POLICY_MAPPINGS", + "BUILD_POLICY_REQUIRE_EXPLICIT", + "BUILD_POLICY_INHIBIT_MAPPING", + "BUILD_POLICY_INHIBIT_ANY", "BUILD_X509_FLAG", "BUILD_REVOKED_ENUMERATOR", + "BUILD_BASE_CRL", "BUILD_CHALLENGE_PWD", "BUILD_PKCS11_MODULE", "BUILD_PKCS11_SLOT", diff --git a/src/libstrongswan/credentials/builder.h b/src/libstrongswan/credentials/builder.h index dc87da2a4..325b668cd 100644 --- a/src/libstrongswan/credentials/builder.h +++ b/src/libstrongswan/credentials/builder.h @@ -87,16 +87,32 @@ enum builder_part_t { BUILD_CA_CERT, /** a certificate, certificate_t* */ BUILD_CERT, - /** CRL distribution point URIs, linked_list_t* containing char* */ + /** CRL distribution point URIs, x509_cdp_t* */ BUILD_CRL_DISTRIBUTION_POINTS, /** OCSP AuthorityInfoAccess locations, linked_list_t* containing char* */ BUILD_OCSP_ACCESS_LOCATIONS, /** certificate path length constraint */ BUILD_PATHLEN, + /** permitted X509 name constraints, linked_list_t* of identification_t* */ + BUILD_PERMITTED_NAME_CONSTRAINTS, + /** excluded X509 name constraints, linked_list_t* of identification_t* */ + BUILD_EXCLUDED_NAME_CONSTRAINTS, + /** certificatePolicy OIDs, linked_list_t* of x509_cert_policy_t* */ + BUILD_CERTIFICATE_POLICIES, + /** policyMapping OIDs, linked_list_t* of x509_policy_mapping_t* */ + BUILD_POLICY_MAPPINGS, + /** requireExplicitPolicy constraint, int */ + BUILD_POLICY_REQUIRE_EXPLICIT, + /** inhibitPolicyMapping constraint, int */ + BUILD_POLICY_INHIBIT_MAPPING, + /** inhibitAnyPolicy constraint, int */ + BUILD_POLICY_INHIBIT_ANY, /** enforce an additional X509 flag, x509_flag_t */ BUILD_X509_FLAG, /** enumerator_t over (chunk_t serial, time_t date, crl_reason_t reason) */ BUILD_REVOKED_ENUMERATOR, + /** Base CRL serial for a delta CRL, chunk_t, */ + BUILD_BASE_CRL, /** PKCS#10 challenge password */ BUILD_CHALLENGE_PWD, /** friendly name of a PKCS#11 module, null terminated char* */ diff --git a/src/libstrongswan/credentials/cert_validator.h b/src/libstrongswan/credentials/cert_validator.h index 1e67c23ab..733d9d612 100644 --- a/src/libstrongswan/credentials/cert_validator.h +++ b/src/libstrongswan/credentials/cert_validator.h @@ -40,12 +40,13 @@ struct cert_validator_t { * @param subject subject certificate to check * @param issuer issuer of subject * @param online wheter to do online revocation checking - * @param pathlen the current length of the path up to the root CA + * @param pathlen the current length of the path bottom-up + * @param anchor is issuer trusted root anchor * @param auth container for resulting authentication info */ bool (*validate)(cert_validator_t *this, certificate_t *subject, - certificate_t *issuer, bool online, int pathlen, - auth_cfg_t *auth); + certificate_t *issuer, bool online, u_int pathlen, + bool anchor, auth_cfg_t *auth); }; #endif /** CERT_VALIDATOR_H_ @}*/ diff --git a/src/libstrongswan/credentials/certificates/crl.h b/src/libstrongswan/credentials/certificates/crl.h index 9425311fb..2f3497474 100644 --- a/src/libstrongswan/credentials/certificates/crl.h +++ b/src/libstrongswan/credentials/certificates/crl.h @@ -72,6 +72,21 @@ struct crl_t { chunk_t (*get_authKeyIdentifier)(crl_t *this); /** + * Is this CRL a delta CRL? + * + * @param base_crl gets to baseCrlNumber, if this is a delta CRL + * @return TRUE if delta CRL + */ + bool (*is_delta_crl)(crl_t *this, chunk_t *base_crl); + + /** + * Create an enumerator over Freshest CRL distribution points and issuers. + * + * @return enumerator over x509_cdp_t + */ + enumerator_t* (*create_delta_crl_uri_enumerator)(crl_t *this); + + /** * Create an enumerator over all revoked certificates. * * The enumerator takes 3 pointer arguments: diff --git a/src/libstrongswan/credentials/certificates/x509.h b/src/libstrongswan/credentials/certificates/x509.h index 6e0a5002a..fec02dbad 100644 --- a/src/libstrongswan/credentials/certificates/x509.h +++ b/src/libstrongswan/credentials/certificates/x509.h @@ -24,10 +24,15 @@ #include <utils/enumerator.h> #include <credentials/certificates/certificate.h> -#define X509_NO_PATH_LEN_CONSTRAINT -1 +/* constraints are currently restricted to the range 0..127 */ +#define X509_NO_CONSTRAINT 255 typedef struct x509_t x509_t; +typedef struct x509_cert_policy_t x509_cert_policy_t; +typedef struct x509_policy_mapping_t x509_policy_mapping_t; +typedef struct x509_cdp_t x509_cdp_t; typedef enum x509_flag_t x509_flag_t; +typedef enum x509_constraint_t x509_constraint_t; /** * X.509 certificate flags. @@ -49,12 +54,55 @@ enum x509_flag_t { X509_SELF_SIGNED = (1<<5), /** cert has an ipAddrBlocks extension */ X509_IP_ADDR_BLOCKS = (1<<6), + /** cert has CRL sign key usage */ + X509_CRL_SIGN = (1<<7), }; /** - * enum names for x509 flags + * Different numerical X.509 constraints. */ -extern enum_name_t *x509_flag_names; +enum x509_constraint_t { + /** pathLenConstraint basicConstraints */ + X509_PATH_LEN, + /** inhibitPolicyMapping policyConstraint */ + X509_INHIBIT_POLICY_MAPPING, + /** requireExplicitPolicy policyConstraint */ + X509_REQUIRE_EXPLICIT_POLICY, + /** inhibitAnyPolicy constraint */ + X509_INHIBIT_ANY_POLICY, +}; + +/** + * X.509 certPolicy extension. + */ +struct x509_cert_policy_t { + /** OID of certPolicy */ + chunk_t oid; + /** Certification Practice Statement URI qualifier */ + char *cps_uri; + /** UserNotice Text qualifier */ + char *unotice_text; +}; + +/** + * X.509 policyMapping extension + */ +struct x509_policy_mapping_t { + /** OID of issuerDomainPolicy */ + chunk_t issuer; + /** OID of subjectDomainPolicy */ + chunk_t subject; +}; + +/** + * X.509 CRL distributionPoint + */ +struct x509_cdp_t { + /** CDP URI, as string */ + char *uri; + /** CRL issuer */ + identification_t *issuer; +}; /** * X.509 certificate interface. @@ -98,11 +146,12 @@ struct x509_t { chunk_t (*get_authKeyIdentifier)(x509_t *this); /** - * Get an optional path length constraint. + * Get a numerical X.509 constraint. * - * @return pathLenConstraint, -1 if no constraint exists + * @param type type of constraint to get + * @return constraint, X509_NO_CONSTRAINT if none found */ - int (*get_pathLenConstraint)(x509_t *this); + u_int (*get_constraint)(x509_t *this, x509_constraint_t type); /** * Create an enumerator over all subjectAltNames. @@ -112,9 +161,9 @@ struct x509_t { enumerator_t* (*create_subjectAltName_enumerator)(x509_t *this); /** - * Create an enumerator over all CRL URIs. + * Create an enumerator over all CRL URIs and CRL Issuers. * - * @return enumerator over URIs as char* + * @return enumerator over x509_cdp_t */ enumerator_t* (*create_crl_uri_enumerator)(x509_t *this); @@ -131,6 +180,30 @@ struct x509_t { * @return enumerator over ipAddrBlocks as traffic_selector_t* */ enumerator_t* (*create_ipAddrBlock_enumerator)(x509_t *this); + + /** + * Create an enumerator over name constraints. + * + * @param perm TRUE for permitted, FALSE for excluded subtrees + * @return enumerator over subtrees as identification_t + */ + enumerator_t* (*create_name_constraint_enumerator)(x509_t *this, bool perm); + + /** + * Create an enumerator over certificate policies. + * + * @return enumerator over x509_cert_policy_t + */ + enumerator_t* (*create_cert_policy_enumerator)(x509_t *this); + + /** + * Create an enumerator over policy mappings. + * + * @return enumerator over x509_policy_mapping + */ + enumerator_t* (*create_policy_mapping_enumerator)(x509_t *this); + + }; #endif /** X509_H_ @}*/ diff --git a/src/libstrongswan/credentials/credential_manager.c b/src/libstrongswan/credentials/credential_manager.c index 97e8d8887..27b97eab3 100644 --- a/src/libstrongswan/credentials/credential_manager.c +++ b/src/libstrongswan/credentials/credential_manager.c @@ -452,8 +452,8 @@ static void cache_queue(private_credential_manager_t *this) * check a certificate for its lifetime */ static bool check_certificate(private_credential_manager_t *this, - certificate_t *subject, certificate_t *issuer, - bool online, int pathlen, auth_cfg_t *auth) + certificate_t *subject, certificate_t *issuer, bool online, + int pathlen, bool trusted, auth_cfg_t *auth) { time_t not_before, not_after; cert_validator_t *validator; @@ -471,29 +471,12 @@ static bool check_certificate(private_credential_manager_t *this, ¬_before, FALSE, ¬_after, FALSE); return FALSE; } - if (issuer->get_type(issuer) == CERT_X509 && - subject->get_type(subject) == CERT_X509) - { - int pathlen_constraint; - x509_t *x509; - - /* check path length constraint */ - x509 = (x509_t*)issuer; - pathlen_constraint = x509->get_pathLenConstraint(x509); - if (pathlen_constraint != X509_NO_PATH_LEN_CONSTRAINT && - pathlen > pathlen_constraint) - { - DBG1(DBG_CFG, "path length of %d violates constraint of %d", - pathlen, pathlen_constraint); - return FALSE; - } - } enumerator = this->validators->create_enumerator(this->validators); while (enumerator->enumerate(enumerator, &validator)) { if (!validator->validate(validator, subject, issuer, - online, pathlen, auth)) + online, pathlen, trusted, auth)) { enumerator->destroy(enumerator); return FALSE; @@ -551,6 +534,37 @@ static certificate_t *get_issuer_cert(private_credential_manager_t *this, } /** + * Get the strength of certificate, add it to auth + */ +static void get_key_strength(certificate_t *cert, auth_cfg_t *auth) +{ + uintptr_t strength; + public_key_t *key; + key_type_t type; + + key = cert->get_public_key(cert); + if (key) + { + type = key->get_type(key); + strength = key->get_keysize(key); + DBG2(DBG_CFG, " certificate \"%Y\" key: %d bit %N", + cert->get_subject(cert), strength, key_type_names, type); + switch (type) + { + case KEY_RSA: + auth->add(auth, AUTH_RULE_RSA_STRENGTH, strength); + break; + case KEY_ECDSA: + auth->add(auth, AUTH_RULE_ECDSA_STRENGTH, strength); + break; + default: + break; + } + key->destroy(key); + } +} + +/** * try to verify the trust chain of subject, return TRUE if trusted */ static bool verify_trust_chain(private_credential_manager_t *this, @@ -562,7 +576,9 @@ static bool verify_trust_chain(private_credential_manager_t *this, int pathlen; auth = auth_cfg_create(); + get_key_strength(subject, auth); current = subject->get_ref(subject); + auth->add(auth, AUTH_RULE_SUBJECT_CERT, current->get_ref(current)); for (pathlen = 0; pathlen <= MAX_TRUST_PATH_LEN; pathlen++) { @@ -607,13 +623,17 @@ static bool verify_trust_chain(private_credential_manager_t *this, break; } } - if (!check_certificate(this, current, issuer, online, pathlen, - current == subject ? auth : NULL)) + if (!check_certificate(this, current, issuer, online, + pathlen, trusted, auth)) { trusted = FALSE; issuer->destroy(issuer); break; } + if (issuer) + { + get_key_strength(issuer, auth); + } current->destroy(current); current = issuer; if (trusted) @@ -637,6 +657,14 @@ static bool verify_trust_chain(private_credential_manager_t *this, } /** + * List find match function for certificates + */ +static bool cert_equals(certificate_t *a, certificate_t *b) +{ + return a->equals(a, b); +} + +/** * enumerator for trusted certificates */ typedef struct { @@ -656,6 +684,8 @@ typedef struct { certificate_t *pretrusted; /** currently enumerating auth config */ auth_cfg_t *auth; + /** list of failed candidates */ + linked_list_t *failed; } trusted_enumerator_t; METHOD(enumerator_t, trusted_enumerate, bool, @@ -683,11 +713,14 @@ METHOD(enumerator_t, trusted_enumerate, bool, verify_trust_chain(this->this, this->pretrusted, this->auth, TRUE, this->online)) { - this->auth->add(this->auth, AUTH_RULE_SUBJECT_CERT, - this->pretrusted->get_ref(this->pretrusted)); DBG1(DBG_CFG, " using trusted certificate \"%Y\"", this->pretrusted->get_subject(this->pretrusted)); *cert = this->pretrusted; + if (!this->auth->get(this->auth, AUTH_RULE_SUBJECT_CERT)) + { /* add cert to auth info, if not returned by trustchain */ + this->auth->add(this->auth, AUTH_RULE_SUBJECT_CERT, + this->pretrusted->get_ref(this->pretrusted)); + } if (auth) { *auth = this->auth; @@ -705,6 +738,12 @@ METHOD(enumerator_t, trusted_enumerate, bool, continue; } + if (this->failed->find_first(this->failed, (void*)cert_equals, + NULL, current) == SUCCESS) + { /* check each candidate only once */ + continue; + } + DBG1(DBG_CFG, " using certificate \"%Y\"", current->get_subject(current)); if (verify_trust_chain(this->this, current, this->auth, FALSE, @@ -717,6 +756,7 @@ METHOD(enumerator_t, trusted_enumerate, bool, } return TRUE; } + this->failed->insert_last(this->failed, current->get_ref(current)); } return FALSE; } @@ -727,6 +767,7 @@ METHOD(enumerator_t, trusted_destroy, void, DESTROY_IF(this->pretrusted); DESTROY_IF(this->auth); DESTROY_IF(this->candidates); + this->failed->destroy_offset(this->failed, offsetof(certificate_t, destroy)); free(this); } @@ -745,6 +786,7 @@ METHOD(credential_manager_t, create_trusted_enumerator, enumerator_t*, .type = type, .id = id, .online = online, + .failed = linked_list_create(), ); return &enumerator->public; } diff --git a/src/libstrongswan/credentials/sets/auth_cfg_wrapper.c b/src/libstrongswan/credentials/sets/auth_cfg_wrapper.c index 5e8458616..225fabe31 100644 --- a/src/libstrongswan/credentials/sets/auth_cfg_wrapper.c +++ b/src/libstrongswan/credentials/sets/auth_cfg_wrapper.c @@ -132,7 +132,8 @@ static bool enumerate(wrapper_enumerator_t *this, certificate_t **cert) } } else if (rule != AUTH_HELPER_SUBJECT_CERT && - rule != AUTH_HELPER_IM_CERT) + rule != AUTH_HELPER_IM_CERT && + rule != AUTH_HELPER_REVOCATION_CERT) { /* handle only HELPER certificates */ continue; } diff --git a/src/libstrongswan/credentials/sets/mem_cred.c b/src/libstrongswan/credentials/sets/mem_cred.c index c29a99f1f..e023e8443 100644 --- a/src/libstrongswan/credentials/sets/mem_cred.c +++ b/src/libstrongswan/credentials/sets/mem_cred.c @@ -1,4 +1,6 @@ /* + * Copyright (C) 2010 Tobias Brunner + * Hochschule fuer Technik Rapperwsil * Copyright (C) 2010 Martin Willi * Copyright (C) 2010 revosec AG * @@ -54,6 +56,11 @@ struct private_mem_cred_t { * List of shared keys, as shared_entry_t */ linked_list_t *shared; + + /** + * List of CDPs, as cdp_t + */ + linked_list_t *cdps; }; /** @@ -144,21 +151,104 @@ static bool certificate_equals(certificate_t *item, certificate_t *cert) return item->equals(item, cert); } +/** + * Add a certificate the the cache. Returns a reference to "cert" or a + * previously cached certificate that equals "cert". + */ +static certificate_t *add_cert_internal(private_mem_cred_t *this, bool trusted, + certificate_t *cert) +{ + certificate_t *cached; + this->lock->write_lock(this->lock); + if (this->untrusted->find_first(this->untrusted, + (linked_list_match_t)certificate_equals, + (void**)&cached, cert) == SUCCESS) + { + cert->destroy(cert); + cert = cached->get_ref(cached); + } + else + { + if (trusted) + { + this->trusted->insert_first(this->trusted, cert->get_ref(cert)); + } + this->untrusted->insert_first(this->untrusted, cert->get_ref(cert)); + } + this->lock->unlock(this->lock); + return cert; +} + METHOD(mem_cred_t, add_cert, void, private_mem_cred_t *this, bool trusted, certificate_t *cert) { + certificate_t *cached = add_cert_internal(this, trusted, cert); + cached->destroy(cached); +} + +METHOD(mem_cred_t, add_cert_ref, certificate_t*, + private_mem_cred_t *this, bool trusted, certificate_t *cert) +{ + return add_cert_internal(this, trusted, cert); +} + +METHOD(mem_cred_t, add_crl, bool, + private_mem_cred_t *this, crl_t *crl) +{ + certificate_t *current, *cert = &crl->certificate; + enumerator_t *enumerator; + bool new = TRUE; + this->lock->write_lock(this->lock); - if (this->untrusted->find_last(this->untrusted, - (linked_list_match_t)certificate_equals, NULL, cert) != SUCCESS) + enumerator = this->untrusted->create_enumerator(this->untrusted); + while (enumerator->enumerate(enumerator, (void**)¤t)) { - if (trusted) + if (current->get_type(current) == CERT_X509_CRL) { - this->trusted->insert_last(this->trusted, cert->get_ref(cert)); + bool found = FALSE; + crl_t *crl_c = (crl_t*)current; + chunk_t authkey = crl->get_authKeyIdentifier(crl); + chunk_t authkey_c = crl_c->get_authKeyIdentifier(crl_c); + + /* compare authorityKeyIdentifiers if available */ + if (chunk_equals(authkey, authkey_c)) + { + found = TRUE; + } + else + { + identification_t *issuer = cert->get_issuer(cert); + identification_t *issuer_c = current->get_issuer(current); + + /* otherwise compare issuer distinguished names */ + if (issuer->equals(issuer, issuer_c)) + { + found = TRUE; + } + } + if (found) + { + new = crl_is_newer(crl, crl_c); + if (new) + { + this->untrusted->remove_at(this->untrusted, enumerator); + } + else + { + cert->destroy(cert); + } + break; + } } - this->untrusted->insert_last(this->untrusted, cert->get_ref(cert)); } - cert->destroy(cert); + enumerator->destroy(enumerator); + + if (new) + { + this->untrusted->insert_first(this->untrusted, cert); + } this->lock->unlock(this->lock); + return new; } /** @@ -218,7 +308,7 @@ METHOD(mem_cred_t, add_key, void, private_mem_cred_t *this, private_key_t *key) { this->lock->write_lock(this->lock); - this->keys->insert_last(this->keys, key); + this->keys->insert_first(this->keys, key); this->lock->unlock(this->lock); } @@ -342,32 +432,137 @@ METHOD(credential_set_t, create_shared_enumerator, enumerator_t*, (void*)shared_filter, data, (void*)shared_data_destroy); } -METHOD(mem_cred_t, add_shared, void, - private_mem_cred_t *this, shared_key_t *shared, ...) +METHOD(mem_cred_t, add_shared_list, void, + private_mem_cred_t *this, shared_key_t *shared, linked_list_t* owners) { shared_entry_t *entry; - identification_t *id; - va_list args; INIT(entry, .shared = shared, - .owners = linked_list_create(), + .owners = owners, ); + this->lock->write_lock(this->lock); + this->shared->insert_first(this->shared, entry); + this->lock->unlock(this->lock); +} + +METHOD(mem_cred_t, add_shared, void, + private_mem_cred_t *this, shared_key_t *shared, ...) +{ + identification_t *id; + linked_list_t *owners = linked_list_create(); + va_list args; + va_start(args, shared); do { id = va_arg(args, identification_t*); if (id) { - entry->owners->insert_last(entry->owners, id); + owners->insert_first(owners, id); } } while (id); va_end(args); + add_shared_list(this, shared, owners); +} + +/** + * Certificate distribution point + */ +typedef struct { + certificate_type_t type; + identification_t *id; + char *uri; +} cdp_t; + +/** + * Destroy a CDP entry + */ +static void cdp_destroy(cdp_t *this) +{ + this->id->destroy(this->id); + free(this->uri); + free(this); +} + +METHOD(mem_cred_t, add_cdp, void, + private_mem_cred_t *this, certificate_type_t type, + identification_t *id, char *uri) +{ + cdp_t *cdp; + + INIT(cdp, + .type = type, + .id = id->clone(id), + .uri = strdup(uri), + ); + this->lock->write_lock(this->lock); + this->cdps->insert_last(this->cdps, cdp); + this->lock->unlock(this->lock); +} + +/** + * CDP enumerator data + */ +typedef struct { + certificate_type_t type; + identification_t *id; + rwlock_t *lock; +} cdp_data_t; + +/** + * Clean up CDP enumerator data + */ +static void cdp_data_destroy(cdp_data_t *data) +{ + data->lock->unlock(data->lock); + free(data); +} + +/** + * CDP enumerator filter + */ +static bool cdp_filter(cdp_data_t *data, cdp_t **cdp, char **uri) +{ + if (data->type != CERT_ANY && data->type != (*cdp)->type) + { + return FALSE; + } + if (data->id && !(*cdp)->id->matches((*cdp)->id, data->id)) + { + return FALSE; + } + *uri = (*cdp)->uri; + return TRUE; +} + +METHOD(credential_set_t, create_cdp_enumerator, enumerator_t*, + private_mem_cred_t *this, certificate_type_t type, identification_t *id) +{ + cdp_data_t *data; + + INIT(data, + .type = type, + .id = id, + .lock = this->lock, + ); + this->lock->read_lock(this->lock); + return enumerator_create_filter(this->cdps->create_enumerator(this->cdps), + (void*)cdp_filter, data, (void*)cdp_data_destroy); + +} + +METHOD(mem_cred_t, clear_secrets, void, + private_mem_cred_t *this) +{ this->lock->write_lock(this->lock); - this->shared->insert_last(this->shared, entry); + this->keys->destroy_offset(this->keys, offsetof(private_key_t, destroy)); + this->shared->destroy_function(this->shared, (void*)shared_entry_destroy); + this->keys = linked_list_create(); + this->shared = linked_list_create(); this->lock->unlock(this->lock); } @@ -379,13 +574,13 @@ METHOD(mem_cred_t, clear_, void, offsetof(certificate_t, destroy)); this->untrusted->destroy_offset(this->untrusted, offsetof(certificate_t, destroy)); - this->keys->destroy_offset(this->keys, offsetof(private_key_t, destroy)); - this->shared->destroy_function(this->shared, (void*)shared_entry_destroy); + this->cdps->destroy_function(this->cdps, (void*)cdp_destroy); this->trusted = linked_list_create(); this->untrusted = linked_list_create(); - this->keys = linked_list_create(); - this->shared = linked_list_create(); + this->cdps = linked_list_create(); this->lock->unlock(this->lock); + + clear_secrets(this); } METHOD(mem_cred_t, destroy, void, @@ -396,6 +591,7 @@ METHOD(mem_cred_t, destroy, void, this->untrusted->destroy(this->untrusted); this->keys->destroy(this->keys); this->shared->destroy(this->shared); + this->cdps->destroy(this->cdps); this->lock->destroy(this->lock); free(this); } @@ -413,19 +609,25 @@ mem_cred_t *mem_cred_create() .create_shared_enumerator = _create_shared_enumerator, .create_private_enumerator = _create_private_enumerator, .create_cert_enumerator = _create_cert_enumerator, - .create_cdp_enumerator = (void*)return_null, + .create_cdp_enumerator = _create_cdp_enumerator, .cache_cert = (void*)nop, }, .add_cert = _add_cert, + .add_cert_ref = _add_cert_ref, + .add_crl = _add_crl, .add_key = _add_key, .add_shared = _add_shared, + .add_shared_list = _add_shared_list, + .add_cdp = _add_cdp, .clear = _clear_, + .clear_secrets = _clear_secrets, .destroy = _destroy, }, .trusted = linked_list_create(), .untrusted = linked_list_create(), .keys = linked_list_create(), .shared = linked_list_create(), + .cdps = linked_list_create(), .lock = rwlock_create(RWLOCK_TYPE_DEFAULT), ); diff --git a/src/libstrongswan/credentials/sets/mem_cred.h b/src/libstrongswan/credentials/sets/mem_cred.h index b26e43d6c..eb46b065b 100644 --- a/src/libstrongswan/credentials/sets/mem_cred.h +++ b/src/libstrongswan/credentials/sets/mem_cred.h @@ -1,4 +1,6 @@ /* + * Copyright (C) 2010 Tobias Brunner + * Hochschule fuer Technik Rapperswil * Copyright (C) 2010 Martin Willi * Copyright (C) 2010 revosec AG * @@ -24,6 +26,8 @@ typedef struct mem_cred_t mem_cred_t; #include <credentials/credential_set.h> +#include <credentials/certificates/crl.h> +#include <utils/linked_list.h> /** * Generic in-memory credential set. @@ -44,6 +48,26 @@ struct mem_cred_t { void (*add_cert)(mem_cred_t *this, bool trusted, certificate_t *cert); /** + * Add a certificate to the credential set, returning a reference to it or + * to a cached duplicate. + * + * @param trusted TRUE to serve certificate as trusted + * @param cert certificate, reference gets owned by set + * @return reference to cert or a previously cached duplicate + */ + certificate_t *(*add_cert_ref)(mem_cred_t *this, bool trusted, + certificate_t *cert); + + /** + * Add an X.509 CRL to the credential set. + * + * @param crl CRL, gets owned by set + * @return TRUE, if the CRL is newer than an existing one (or + * new at all) + */ + bool (*add_crl)(mem_cred_t *this, crl_t *crl); + + /** * Add a private key to the credential set. * * @param key key, reference gets owned by set @@ -54,16 +78,40 @@ struct mem_cred_t { * Add a shared key to the credential set. * * @param shared shared key to add, gets owned by set - * @param ... NULL terminated list of owners identification_t* + * @param ... NULL terminated list of owners (identification_t*) */ void (*add_shared)(mem_cred_t *this, shared_key_t *shared, ...); /** + * Add a shared key to the credential set. + * + * @param shared shared key to add, gets owned by set + * @param owners list of owners (identification_t*), gets owned + */ + void (*add_shared_list)(mem_cred_t *this, shared_key_t *shared, + linked_list_t *owners); + /** + * Add a certificate distribution point to the set. + * + * @param type type of the certificate + * @param id certificate ID CDP has a cert for, gets cloned + * @param uri CDP URI, gets strduped + */ + void (*add_cdp)(mem_cred_t *this, certificate_type_t type, + identification_t *id, char *uri); + + /** * Clear all credentials from the credential set. */ void (*clear)(mem_cred_t *this); /** + * Clear the secrets (private and shared keys, not the certificates) from + * the credential set. + */ + void (*clear_secrets)(mem_cred_t *this); + + /** * Destroy a mem_cred_t. */ void (*destroy)(mem_cred_t *this); diff --git a/src/libstrongswan/crypto/crypto_factory.c b/src/libstrongswan/crypto/crypto_factory.c index f2f01987d..2d13896d6 100644 --- a/src/libstrongswan/crypto/crypto_factory.c +++ b/src/libstrongswan/crypto/crypto_factory.c @@ -20,13 +20,29 @@ #include <utils/linked_list.h> #include <crypto/crypto_tester.h> +const char *default_plugin_name = "default"; + typedef struct entry_t entry_t; + struct entry_t { - /* algorithm */ + /** + * algorithm + */ u_int algo; - /* benchmarked speed */ + + /** + * plugin that registered this algorithm + */ + const char *plugin_name; + + /** + * benchmarked speed + */ u_int speed; - /* constructor */ + + /** + * constructor + */ union { crypter_constructor_t create_crypter; aead_constructor_t create_aead; @@ -128,7 +144,8 @@ METHOD(crypto_factory_t, create_crypter, crypter_t*, { if (this->test_on_create && !this->tester->test_crypter(this->tester, algo, key_size, - entry->create_crypter, NULL)) + entry->create_crypter, NULL, + default_plugin_name)) { continue; } @@ -160,7 +177,8 @@ METHOD(crypto_factory_t, create_aead, aead_t*, { if (this->test_on_create && !this->tester->test_aead(this->tester, algo, key_size, - entry->create_aead, NULL)) + entry->create_aead, NULL, + default_plugin_name)) { continue; } @@ -191,7 +209,8 @@ METHOD(crypto_factory_t, create_signer, signer_t*, { if (this->test_on_create && !this->tester->test_signer(this->tester, algo, - entry->create_signer, NULL)) + entry->create_signer, NULL, + default_plugin_name)) { continue; } @@ -223,7 +242,8 @@ METHOD(crypto_factory_t, create_hasher, hasher_t*, { if (this->test_on_create && algo != HASH_PREFERRED && !this->tester->test_hasher(this->tester, algo, - entry->create_hasher, NULL)) + entry->create_hasher, NULL, + default_plugin_name)) { continue; } @@ -254,7 +274,8 @@ METHOD(crypto_factory_t, create_prf, prf_t*, { if (this->test_on_create && !this->tester->test_prf(this->tester, algo, - entry->create_prf, NULL)) + entry->create_prf, NULL, + default_plugin_name)) { continue; } @@ -286,7 +307,8 @@ METHOD(crypto_factory_t, create_rng, rng_t*, { if (this->test_on_create && !this->tester->test_rng(this->tester, quality, - entry->create_rng, NULL)) + entry->create_rng, NULL, + default_plugin_name)) { continue; } @@ -350,7 +372,8 @@ METHOD(crypto_factory_t, create_dh, diffie_hellman_t*, * Insert an algorithm entry to a list */ static void add_entry(private_crypto_factory_t *this, linked_list_t *list, - int algo, u_int speed, void *create) + int algo, const char *plugin_name, + u_int speed, void *create) { entry_t *entry, *current; linked_list_t *tmp; @@ -358,6 +381,7 @@ static void add_entry(private_crypto_factory_t *this, linked_list_t *list, INIT(entry, .algo = algo, + .plugin_name = plugin_name, .speed = speed, ); entry->create = create; @@ -391,16 +415,16 @@ static void add_entry(private_crypto_factory_t *this, linked_list_t *list, } METHOD(crypto_factory_t, add_crypter, void, - private_crypto_factory_t *this, encryption_algorithm_t algo, - crypter_constructor_t create) + private_crypto_factory_t *this, encryption_algorithm_t algo, + const char *plugin_name, crypter_constructor_t create) { u_int speed = 0; if (!this->test_on_add || this->tester->test_crypter(this->tester, algo, 0, create, - this->bench ? &speed : NULL)) + this->bench ? &speed : NULL, plugin_name)) { - add_entry(this, this->crypters, algo, speed, create); + add_entry(this, this->crypters, algo, plugin_name, speed, create); } } @@ -425,16 +449,16 @@ METHOD(crypto_factory_t, remove_crypter, void, } METHOD(crypto_factory_t, add_aead, void, - private_crypto_factory_t *this, encryption_algorithm_t algo, - aead_constructor_t create) + private_crypto_factory_t *this, encryption_algorithm_t algo, + const char *plugin_name, aead_constructor_t create) { u_int speed = 0; if (!this->test_on_add || this->tester->test_aead(this->tester, algo, 0, create, - this->bench ? &speed : NULL)) + this->bench ? &speed : NULL, plugin_name)) { - add_entry(this, this->aeads, algo, speed, create); + add_entry(this, this->aeads, algo, plugin_name, speed, create); } } @@ -459,16 +483,16 @@ METHOD(crypto_factory_t, remove_aead, void, } METHOD(crypto_factory_t, add_signer, void, - private_crypto_factory_t *this, integrity_algorithm_t algo, - signer_constructor_t create) + private_crypto_factory_t *this, integrity_algorithm_t algo, + const char *plugin_name, signer_constructor_t create) { u_int speed = 0; if (!this->test_on_add || this->tester->test_signer(this->tester, algo, create, - this->bench ? &speed : NULL)) + this->bench ? &speed : NULL, plugin_name)) { - add_entry(this, this->signers, algo, speed, create); + add_entry(this, this->signers, algo, plugin_name, speed, create); } } @@ -493,16 +517,16 @@ METHOD(crypto_factory_t, remove_signer, void, } METHOD(crypto_factory_t, add_hasher, void, - private_crypto_factory_t *this, hash_algorithm_t algo, - hasher_constructor_t create) + private_crypto_factory_t *this, hash_algorithm_t algo, + const char *plugin_name, hasher_constructor_t create) { u_int speed = 0; if (!this->test_on_add || this->tester->test_hasher(this->tester, algo, create, - this->bench ? &speed : NULL)) + this->bench ? &speed : NULL, plugin_name)) { - add_entry(this, this->hashers, algo, speed, create); + add_entry(this, this->hashers, algo, plugin_name, speed, create); } } @@ -527,16 +551,16 @@ METHOD(crypto_factory_t, remove_hasher, void, } METHOD(crypto_factory_t, add_prf, void, - private_crypto_factory_t *this, pseudo_random_function_t algo, - prf_constructor_t create) + private_crypto_factory_t *this, pseudo_random_function_t algo, + const char *plugin_name, prf_constructor_t create) { u_int speed = 0; if (!this->test_on_add || this->tester->test_prf(this->tester, algo, create, - this->bench ? &speed : NULL)) + this->bench ? &speed : NULL, plugin_name)) { - add_entry(this, this->prfs, algo, speed, create); + add_entry(this, this->prfs, algo, plugin_name, speed, create); } } @@ -562,15 +586,15 @@ METHOD(crypto_factory_t, remove_prf, void, METHOD(crypto_factory_t, add_rng, void, private_crypto_factory_t *this, rng_quality_t quality, - rng_constructor_t create) + const char *plugin_name, rng_constructor_t create) { u_int speed = 0; if (!this->test_on_add || this->tester->test_rng(this->tester, quality, create, - this->bench ? &speed : NULL)) + this->bench ? &speed : NULL, plugin_name)) { - add_entry(this, this->rngs, quality, speed, create); + add_entry(this, this->rngs, quality, plugin_name, speed, create); } } @@ -595,10 +619,10 @@ METHOD(crypto_factory_t, remove_rng, void, } METHOD(crypto_factory_t, add_dh, void, - private_crypto_factory_t *this, diffie_hellman_group_t group, - dh_constructor_t create) + private_crypto_factory_t *this, diffie_hellman_group_t group, + const char *plugin_name, dh_constructor_t create) { - add_entry(this, this->dhs, group, 0, create); + add_entry(this, this->dhs, group, plugin_name, 0, create); } METHOD(crypto_factory_t, remove_dh, void, @@ -660,9 +684,11 @@ static enumerator_t *create_enumerator(private_crypto_factory_t *this, /** * Filter function to enumerate algorithm, not entry */ -static bool crypter_filter(void *n, entry_t **entry, encryption_algorithm_t *algo) +static bool crypter_filter(void *n, entry_t **entry, encryption_algorithm_t *algo, + void *i2, const char **plugin_name) { *algo = (*entry)->algo; + *plugin_name = (*entry)->plugin_name; return TRUE; } @@ -681,9 +707,11 @@ METHOD(crypto_factory_t, create_aead_enumerator, enumerator_t*, /** * Filter function to enumerate algorithm, not entry */ -static bool signer_filter(void *n, entry_t **entry, integrity_algorithm_t *algo) +static bool signer_filter(void *n, entry_t **entry, integrity_algorithm_t *algo, + void *i2, const char **plugin_name) { *algo = (*entry)->algo; + *plugin_name = (*entry)->plugin_name; return TRUE; } @@ -696,9 +724,11 @@ METHOD(crypto_factory_t, create_signer_enumerator, enumerator_t*, /** * Filter function to enumerate algorithm, not entry */ -static bool hasher_filter(void *n, entry_t **entry, hash_algorithm_t *algo) +static bool hasher_filter(void *n, entry_t **entry, hash_algorithm_t *algo, + void *i2, const char **plugin_name) { *algo = (*entry)->algo; + *plugin_name = (*entry)->plugin_name; return TRUE; } @@ -711,9 +741,11 @@ METHOD(crypto_factory_t, create_hasher_enumerator, enumerator_t*, /** * Filter function to enumerate algorithm, not entry */ -static bool prf_filter(void *n, entry_t **entry, pseudo_random_function_t *algo) +static bool prf_filter(void *n, entry_t **entry, pseudo_random_function_t *algo, + void *i2, const char **plugin_name) { *algo = (*entry)->algo; + *plugin_name = (*entry)->plugin_name; return TRUE; } @@ -726,9 +758,11 @@ METHOD(crypto_factory_t, create_prf_enumerator, enumerator_t*, /** * Filter function to enumerate algorithm, not entry */ -static bool dh_filter(void *n, entry_t **entry, diffie_hellman_group_t *group) +static bool dh_filter(void *n, entry_t **entry, diffie_hellman_group_t *group, + void *i2, const char **plugin_name) { *group = (*entry)->algo; + *plugin_name = (*entry)->plugin_name; return TRUE; } @@ -738,6 +772,22 @@ METHOD(crypto_factory_t, create_dh_enumerator, enumerator_t*, return create_enumerator(this, this->dhs, dh_filter); } +/** + * Filter function to enumerate algorithm, not entry + */ +static bool rng_filter(void *n, entry_t **entry, rng_quality_t *quality, + void *i2, const char **plugin_name) +{ + *quality = (*entry)->algo; + *plugin_name = (*entry)->plugin_name; + return TRUE; +} + +METHOD(crypto_factory_t, create_rng_enumerator, enumerator_t*, + private_crypto_factory_t *this) +{ + return create_enumerator(this, this->rngs, rng_filter); +} METHOD(crypto_factory_t, add_test_vector, void, private_crypto_factory_t *this, transform_type_t type, void *vector) { @@ -812,6 +862,7 @@ crypto_factory_t *crypto_factory_create() .create_hasher_enumerator = _create_hasher_enumerator, .create_prf_enumerator = _create_prf_enumerator, .create_dh_enumerator = _create_dh_enumerator, + .create_rng_enumerator = _create_rng_enumerator, .add_test_vector = _add_test_vector, .destroy = _destroy, }, diff --git a/src/libstrongswan/crypto/crypto_factory.h b/src/libstrongswan/crypto/crypto_factory.h index ff06eda7b..8e5db6355 100644 --- a/src/libstrongswan/crypto/crypto_factory.h +++ b/src/libstrongswan/crypto/crypto_factory.h @@ -33,6 +33,8 @@ typedef struct crypto_factory_t crypto_factory_t; #include <crypto/diffie_hellman.h> #include <crypto/transform.h> +#define CRYPTO_MAX_ALG_LINE 120 /* characters */ + /** * Constructor function for crypters */ @@ -144,11 +146,12 @@ struct crypto_factory_t { * Register a crypter constructor. * * @param algo algorithm to constructor + * @param plugin_name plugin that registered this algorithm * @param create constructor function for that algorithm * @return */ void (*add_crypter)(crypto_factory_t *this, encryption_algorithm_t algo, - crypter_constructor_t create); + const char *plugin_name, crypter_constructor_t create); /** * Unregister a crypter constructor. @@ -168,21 +171,23 @@ struct crypto_factory_t { * Register a aead constructor. * * @param algo algorithm to constructor + * @param plugin_name plugin that registered this algorithm * @param create constructor function for that algorithm * @return */ void (*add_aead)(crypto_factory_t *this, encryption_algorithm_t algo, - aead_constructor_t create); + const char *plugin_name, aead_constructor_t create); /** * Register a signer constructor. * * @param algo algorithm to constructor + * @param plugin_name plugin that registered this algorithm * @param create constructor function for that algorithm * @return */ void (*add_signer)(crypto_factory_t *this, integrity_algorithm_t algo, - signer_constructor_t create); + const char *plugin_name, signer_constructor_t create); /** * Unregister a signer constructor. @@ -198,11 +203,12 @@ struct crypto_factory_t { * create_hasher(HASH_PREFERRED). * * @param algo algorithm to constructor + * @param plugin_name plugin that registered this algorithm * @param create constructor function for that algorithm * @return */ void (*add_hasher)(crypto_factory_t *this, hash_algorithm_t algo, - hasher_constructor_t create); + const char *plugin_name, hasher_constructor_t create); /** * Unregister a hasher constructor. @@ -215,11 +221,12 @@ struct crypto_factory_t { * Register a prf constructor. * * @param algo algorithm to constructor + * @param plugin_name plugin that registered this algorithm * @param create constructor function for that algorithm * @return */ void (*add_prf)(crypto_factory_t *this, pseudo_random_function_t algo, - prf_constructor_t create); + const char *plugin_name, prf_constructor_t create); /** * Unregister a prf constructor. @@ -232,9 +239,11 @@ struct crypto_factory_t { * Register a source of randomness. * * @param quality quality of randomness this RNG serves + * @param plugin_name plugin that registered this algorithm * @param create constructor function for such a quality */ - void (*add_rng)(crypto_factory_t *this, rng_quality_t quality, rng_constructor_t create); + void (*add_rng)(crypto_factory_t *this, rng_quality_t quality, + const char *plugin_name, rng_constructor_t create); /** * Unregister a source of randomness. @@ -247,11 +256,12 @@ struct crypto_factory_t { * Register a diffie hellman constructor. * * @param group dh group to constructor + * @param plugin_name plugin that registered this algorithm * @param create constructor function for that algorithm * @return */ void (*add_dh)(crypto_factory_t *this, diffie_hellman_group_t group, - dh_constructor_t create); + const char *plugin_name, dh_constructor_t create); /** * Unregister a diffie hellman constructor. @@ -303,6 +313,13 @@ struct crypto_factory_t { enumerator_t* (*create_dh_enumerator)(crypto_factory_t *this); /** + * Create an enumerator over all registered random generators. + * + * @return enumerator over rng_quality_t + */ + enumerator_t* (*create_rng_enumerator)(crypto_factory_t *this); + + /** * Add a test vector to the crypto factory. * * @param type type of the test vector diff --git a/src/libstrongswan/crypto/crypto_tester.c b/src/libstrongswan/crypto/crypto_tester.c index d17485ff2..276f4329a 100644 --- a/src/libstrongswan/crypto/crypto_tester.c +++ b/src/libstrongswan/crypto/crypto_tester.c @@ -165,7 +165,7 @@ static u_int bench_crypter(private_crypto_tester_t *this, METHOD(crypto_tester_t, test_crypter, bool, private_crypto_tester_t *this, encryption_algorithm_t alg, size_t key_size, - crypter_constructor_t create, u_int *speed) + crypter_constructor_t create, u_int *speed, const char *plugin_name) { enumerator_t *enumerator; crypter_test_vector_t *vector; @@ -188,7 +188,11 @@ METHOD(crypto_tester_t, test_crypter, bool, } crypter = create(alg, vector->key_size); if (!crypter) - { /* key size not supported... */ + { + DBG1(DBG_LIB, "%N[%s]: %u bit key size not supported", + encryption_algorithm_names, alg, plugin_name, + BITS_PER_BYTE * vector->key_size); + failed = TRUE; continue; } @@ -231,31 +235,40 @@ METHOD(crypto_tester_t, test_crypter, bool, crypter->destroy(crypter); if (failed) { - DBG1(DBG_LIB, "disabled %N: %s test vector failed", - encryption_algorithm_names, alg, get_name(vector)); + DBG1(DBG_LIB, "disabled %N[%s]: %s test vector failed", + encryption_algorithm_names, alg, plugin_name, get_name(vector)); break; } } enumerator->destroy(enumerator); if (!tested) { - DBG1(DBG_LIB, "%s %N: no test vectors found", - this->required ? "disabled" : "enabled ", - encryption_algorithm_names, alg); - return !this->required; + if (failed) + { + DBG1(DBG_LIB,"disable %N[%s]: no key size supported", + encryption_algorithm_names, alg, plugin_name); + return FALSE; + } + else + { + DBG1(DBG_LIB, "%s %N[%s]: no test vectors found", + this->required ? "disabled" : "enabled ", + encryption_algorithm_names, alg, plugin_name); + return !this->required; + } } if (!failed) { if (speed) { *speed = bench_crypter(this, alg, create); - DBG1(DBG_LIB, "enabled %N: passed %u test vectors, %d points", - encryption_algorithm_names, alg, tested, *speed); + DBG1(DBG_LIB, "enabled %N[%s]: passed %u test vectors, %d points", + encryption_algorithm_names, alg, tested, plugin_name, *speed); } else { - DBG1(DBG_LIB, "enabled %N: passed %u test vectors", - encryption_algorithm_names, alg, tested); + DBG1(DBG_LIB, "enabled %N[%s]: passed %u test vectors", + encryption_algorithm_names, alg, plugin_name, tested); } } return !failed; @@ -311,7 +324,7 @@ static u_int bench_aead(private_crypto_tester_t *this, METHOD(crypto_tester_t, test_aead, bool, private_crypto_tester_t *this, encryption_algorithm_t alg, size_t key_size, - aead_constructor_t create, u_int *speed) + aead_constructor_t create, u_int *speed, const char *plugin_name) { enumerator_t *enumerator; aead_test_vector_t *vector; @@ -335,7 +348,11 @@ METHOD(crypto_tester_t, test_aead, bool, } aead = create(alg, vector->key_size); if (!aead) - { /* key size not supported... */ + { + DBG1(DBG_LIB, "%N[%s]: %u bit key size not supported", + encryption_algorithm_names, alg, plugin_name, + BITS_PER_BYTE * vector->key_size); + failed = TRUE; continue; } @@ -388,31 +405,40 @@ METHOD(crypto_tester_t, test_aead, bool, aead->destroy(aead); if (failed) { - DBG1(DBG_LIB, "disabled %N: %s test vector failed", - encryption_algorithm_names, alg, get_name(vector)); + DBG1(DBG_LIB, "disabled %N[%s]: %s test vector failed", + encryption_algorithm_names, alg, plugin_name, get_name(vector)); break; } } enumerator->destroy(enumerator); if (!tested) { - DBG1(DBG_LIB, "%s %N: no test vectors found", - this->required ? "disabled" : "enabled ", - encryption_algorithm_names, alg); - return !this->required; + if (failed) + { + DBG1(DBG_LIB,"disable %N[%s]: no key size supported", + encryption_algorithm_names, alg, plugin_name); + return FALSE; + } + else + { + DBG1(DBG_LIB, "%s %N[%s]: no test vectors found", + this->required ? "disabled" : "enabled ", + encryption_algorithm_names, alg, plugin_name); + return !this->required; + } } if (!failed) { if (speed) { *speed = bench_aead(this, alg, create); - DBG1(DBG_LIB, "enabled %N: passed %u test vectors, %d points", - encryption_algorithm_names, alg, tested, *speed); + DBG1(DBG_LIB, "enabled %N[%s]: passed %u test vectors, %d points", + encryption_algorithm_names, alg, plugin_name, tested, *speed); } else { - DBG1(DBG_LIB, "enabled %N: passed %u test vectors", - encryption_algorithm_names, alg, tested); + DBG1(DBG_LIB, "enabled %N[%s]: passed %u test vectors", + encryption_algorithm_names, alg, plugin_name, tested); } } return !failed; @@ -460,7 +486,7 @@ static u_int bench_signer(private_crypto_tester_t *this, METHOD(crypto_tester_t, test_signer, bool, private_crypto_tester_t *this, integrity_algorithm_t alg, - signer_constructor_t create, u_int *speed) + signer_constructor_t create, u_int *speed, const char *plugin_name) { enumerator_t *enumerator; signer_test_vector_t *vector; @@ -482,8 +508,8 @@ METHOD(crypto_tester_t, test_signer, bool, signer = create(alg); if (!signer) { - DBG1(DBG_LIB, "disabled %N: creating instance failed", - integrity_algorithm_names, alg); + DBG1(DBG_LIB, "disabled %N[%s]: creating instance failed", + integrity_algorithm_names, alg, plugin_name); failed = TRUE; break; } @@ -538,17 +564,17 @@ METHOD(crypto_tester_t, test_signer, bool, signer->destroy(signer); if (failed) { - DBG1(DBG_LIB, "disabled %N: %s test vector failed", - integrity_algorithm_names, alg, get_name(vector)); + DBG1(DBG_LIB, "disabled %N[%s]: %s test vector failed", + integrity_algorithm_names, alg, plugin_name, get_name(vector)); break; } } enumerator->destroy(enumerator); if (!tested) { - DBG1(DBG_LIB, "%s %N: no test vectors found", + DBG1(DBG_LIB, "%s %N[%s]: no test vectors found", this->required ? "disabled" : "enabled ", - integrity_algorithm_names, alg); + integrity_algorithm_names, alg, plugin_name); return !this->required; } if (!failed) @@ -556,13 +582,13 @@ METHOD(crypto_tester_t, test_signer, bool, if (speed) { *speed = bench_signer(this, alg, create); - DBG1(DBG_LIB, "enabled %N: passed %u test vectors, %d points", - integrity_algorithm_names, alg, tested, *speed); + DBG1(DBG_LIB, "enabled %N[%s]: passed %u test vectors, %d points", + integrity_algorithm_names, alg, plugin_name, tested, *speed); } else { - DBG1(DBG_LIB, "enabled %N: passed %u test vectors", - integrity_algorithm_names, alg, tested); + DBG1(DBG_LIB, "enabled %N[%s]: passed %u test vectors", + integrity_algorithm_names, alg, plugin_name, tested); } } return !failed; @@ -604,7 +630,7 @@ static u_int bench_hasher(private_crypto_tester_t *this, METHOD(crypto_tester_t, test_hasher, bool, private_crypto_tester_t *this, hash_algorithm_t alg, - hasher_constructor_t create, u_int *speed) + hasher_constructor_t create, u_int *speed, const char *plugin_name) { enumerator_t *enumerator; hasher_test_vector_t *vector; @@ -626,8 +652,8 @@ METHOD(crypto_tester_t, test_hasher, bool, hasher = create(alg); if (!hasher) { - DBG1(DBG_LIB, "disabled %N: creating instance failed", - hash_algorithm_names, alg); + DBG1(DBG_LIB, "disabled %N[%s]: creating instance failed", + hash_algorithm_names, alg, plugin_name); failed = TRUE; break; } @@ -669,17 +695,17 @@ METHOD(crypto_tester_t, test_hasher, bool, hasher->destroy(hasher); if (failed) { - DBG1(DBG_LIB, "disabled %N: %s test vector failed", - hash_algorithm_names, alg, get_name(vector)); + DBG1(DBG_LIB, "disabled %N[%s]: %s test vector failed", + hash_algorithm_names, alg, plugin_name, get_name(vector)); break; } } enumerator->destroy(enumerator); if (!tested) { - DBG1(DBG_LIB, "%s %N: no test vectors found", + DBG1(DBG_LIB, "%s %N[%s]: no test vectors found", this->required ? "disabled" : "enabled ", - hash_algorithm_names, alg); + hash_algorithm_names, alg, plugin_name); return !this->required; } if (!failed) @@ -687,13 +713,13 @@ METHOD(crypto_tester_t, test_hasher, bool, if (speed) { *speed = bench_hasher(this, alg, create); - DBG1(DBG_LIB, "enabled %N: passed %u test vectors, %d points", - hash_algorithm_names, alg, tested, *speed); + DBG1(DBG_LIB, "enabled %N[%s]: passed %u test vectors, %d points", + hash_algorithm_names, alg, plugin_name, tested, *speed); } else { - DBG1(DBG_LIB, "enabled %N: passed %u test vectors", - hash_algorithm_names, alg, tested); + DBG1(DBG_LIB, "enabled %N[%s]: passed %u test vectors", + hash_algorithm_names, alg, plugin_name, tested); } } return !failed; @@ -735,7 +761,7 @@ static u_int bench_prf(private_crypto_tester_t *this, METHOD(crypto_tester_t, test_prf, bool, private_crypto_tester_t *this, pseudo_random_function_t alg, - prf_constructor_t create, u_int *speed) + prf_constructor_t create, u_int *speed, const char *plugin_name) { enumerator_t *enumerator; prf_test_vector_t *vector; @@ -757,8 +783,8 @@ METHOD(crypto_tester_t, test_prf, bool, prf = create(alg); if (!prf) { - DBG1(DBG_LIB, "disabled %N: creating instance failed", - pseudo_random_function_names, alg); + DBG1(DBG_LIB, "disabled %N[%s]: creating instance failed", + pseudo_random_function_names, alg, plugin_name); failed = TRUE; break; } @@ -811,17 +837,17 @@ METHOD(crypto_tester_t, test_prf, bool, prf->destroy(prf); if (failed) { - DBG1(DBG_LIB, "disabled %N: %s test vector failed", - pseudo_random_function_names, alg, get_name(vector)); + DBG1(DBG_LIB, "disabled %N[%s]: %s test vector failed", + pseudo_random_function_names, alg, plugin_name, get_name(vector)); break; } } enumerator->destroy(enumerator); if (!tested) { - DBG1(DBG_LIB, "%s %N: no test vectors found", + DBG1(DBG_LIB, "%s %N[%s]: no test vectors found", this->required ? "disabled" : "enabled ", - pseudo_random_function_names, alg); + pseudo_random_function_names, alg, plugin_name); return !this->required; } if (!failed) @@ -829,13 +855,13 @@ METHOD(crypto_tester_t, test_prf, bool, if (speed) { *speed = bench_prf(this, alg, create); - DBG1(DBG_LIB, "enabled %N: passed %u test vectors, %d points", - pseudo_random_function_names, alg, tested, *speed); + DBG1(DBG_LIB, "enabled %N[%s]: passed %u test vectors, %d points", + pseudo_random_function_names, alg, plugin_name, tested, *speed); } else { - DBG1(DBG_LIB, "enabled %N: passed %u test vectors", - pseudo_random_function_names, alg, tested); + DBG1(DBG_LIB, "enabled %N[%s]: passed %u test vectors", + pseudo_random_function_names, alg, plugin_name, tested); } } return !failed; @@ -874,7 +900,7 @@ static u_int bench_rng(private_crypto_tester_t *this, METHOD(crypto_tester_t, test_rng, bool, private_crypto_tester_t *this, rng_quality_t quality, - rng_constructor_t create, u_int *speed) + rng_constructor_t create, u_int *speed, const char *plugin_name) { enumerator_t *enumerator; rng_test_vector_t *vector; @@ -883,8 +909,8 @@ METHOD(crypto_tester_t, test_rng, bool, if (!this->rng_true && quality == RNG_TRUE) { - DBG1(DBG_LIB, "enabled %N: skipping test (disabled by config)", - rng_quality_names, quality); + DBG1(DBG_LIB, "enabled %N[%s]: skipping test (disabled by config)", + rng_quality_names, quality, plugin_name); return TRUE; } @@ -903,8 +929,8 @@ METHOD(crypto_tester_t, test_rng, bool, rng = create(quality); if (!rng) { - DBG1(DBG_LIB, "disabled %N: creating instance failed", - rng_quality_names, quality); + DBG1(DBG_LIB, "disabled %N[%s]: creating instance failed", + rng_quality_names, quality, plugin_name); failed = TRUE; break; } @@ -933,17 +959,17 @@ METHOD(crypto_tester_t, test_rng, bool, rng->destroy(rng); if (failed) { - DBG1(DBG_LIB, "disabled %N: %s test vector failed", - rng_quality_names, quality, get_name(vector)); + DBG1(DBG_LIB, "disabled %N[%s]: %s test vector failed", + rng_quality_names, quality, plugin_name, get_name(vector)); break; } } enumerator->destroy(enumerator); if (!tested) { - DBG1(DBG_LIB, "%s %N: no test vectors found", + DBG1(DBG_LIB, "%s %N[%s]: no test vectors found", this->required ? ", disabled" : "enabled ", - rng_quality_names, quality); + rng_quality_names, quality, plugin_name); return !this->required; } if (!failed) @@ -951,13 +977,13 @@ METHOD(crypto_tester_t, test_rng, bool, if (speed) { *speed = bench_rng(this, quality, create); - DBG1(DBG_LIB, "enabled %N: passed %u test vectors, %d points", - rng_quality_names, quality, tested, *speed); + DBG1(DBG_LIB, "enabled %N[%s]: passed %u test vectors, %d points", + rng_quality_names, quality, plugin_name, tested, *speed); } else { - DBG1(DBG_LIB, "enabled %N: passed %u test vectors", - rng_quality_names, quality, tested); + DBG1(DBG_LIB, "enabled %N[%s]: passed %u test vectors", + rng_quality_names, quality, plugin_name, tested); } } return !failed; diff --git a/src/libstrongswan/crypto/crypto_tester.h b/src/libstrongswan/crypto/crypto_tester.h index cef0b3c18..019c87c39 100644 --- a/src/libstrongswan/crypto/crypto_tester.h +++ b/src/libstrongswan/crypto/crypto_tester.h @@ -143,7 +143,7 @@ struct crypto_tester_t { */ bool (*test_crypter)(crypto_tester_t *this, encryption_algorithm_t alg, size_t key_size, crypter_constructor_t create, - u_int *speed); + u_int *speed, const char *plugin_name); /** * Test an aead algorithm, optionally using a specified key size. @@ -156,7 +156,7 @@ struct crypto_tester_t { */ bool (*test_aead)(crypto_tester_t *this, encryption_algorithm_t alg, size_t key_size, aead_constructor_t create, - u_int *speed); + u_int *speed, const char *plugin_name); /** * Test a signer algorithm. * @@ -166,7 +166,8 @@ struct crypto_tester_t { * @return TRUE if test passed */ bool (*test_signer)(crypto_tester_t *this, integrity_algorithm_t alg, - signer_constructor_t create, u_int *speed); + signer_constructor_t create, + u_int *speed, const char *plugin_name); /** * Test a hasher algorithm. * @@ -176,7 +177,8 @@ struct crypto_tester_t { * @return TRUE if test passed */ bool (*test_hasher)(crypto_tester_t *this, hash_algorithm_t alg, - hasher_constructor_t create, u_int *speed); + hasher_constructor_t create, + u_int *speed, const char *plugin_name); /** * Test a PRF algorithm. * @@ -186,7 +188,8 @@ struct crypto_tester_t { * @return TRUE if test passed */ bool (*test_prf)(crypto_tester_t *this, pseudo_random_function_t alg, - prf_constructor_t create, u_int *speed); + prf_constructor_t create, + u_int *speed, const char *plugin_name); /** * Test a RNG implementation. * @@ -196,7 +199,8 @@ struct crypto_tester_t { * @return TRUE if test passed */ bool (*test_rng)(crypto_tester_t *this, rng_quality_t quality, - rng_constructor_t create, u_int *speed); + rng_constructor_t create, + u_int *speed, const char *plugin_name); /** * Add a test vector to test a crypter. * diff --git a/src/libstrongswan/eap/eap.h b/src/libstrongswan/eap/eap.h index 1d55747a4..e98a3a211 100644 --- a/src/libstrongswan/eap/eap.h +++ b/src/libstrongswan/eap/eap.h @@ -82,7 +82,7 @@ extern enum_name_t *eap_type_short_names; * Lookup the EAP method type from a string. * * @param name EAP method name (such as "md5", "aka") - * @return method type, 0 if unkown + * @return method type, 0 if unknown */ eap_type_t eap_type_from_string(char *name); diff --git a/src/libstrongswan/enum.c b/src/libstrongswan/enum.c index 258a5b410..5c811bd17 100644 --- a/src/libstrongswan/enum.c +++ b/src/libstrongswan/enum.c @@ -43,7 +43,7 @@ int enum_from_name(enum_name_t *e, char *name) { do { - int i, count = e->last - e->first; + int i, count = e->last - e->first + 1; for (i = 0; i < count; i++) { diff --git a/src/libstrongswan/fetcher/fetcher_manager.c b/src/libstrongswan/fetcher/fetcher_manager.c index c81de032c..b007c8b08 100644 --- a/src/libstrongswan/fetcher/fetcher_manager.c +++ b/src/libstrongswan/fetcher/fetcher_manager.c @@ -92,7 +92,7 @@ static status_t fetch(private_fetcher_manager_t *this, va_start(args, response); while (good) { - opt = va_arg(args, fetcher_option_t); + opt = va_arg(args, int); switch (opt) { case FETCH_REQUEST_DATA: @@ -109,7 +109,7 @@ static status_t fetch(private_fetcher_manager_t *this, good = fetcher->set_option(fetcher, opt, va_arg(args, u_int)); continue; case FETCH_END: - break;; + break; } break; } diff --git a/src/libstrongswan/integrity_checker.c b/src/libstrongswan/integrity_checker.c index c9cad44ae..e962aba70 100644 --- a/src/libstrongswan/integrity_checker.c +++ b/src/libstrongswan/integrity_checker.c @@ -57,11 +57,8 @@ struct private_integrity_checker_t { int checksum_count; }; -/** - * Implementation of integrity_checker_t.build_file - */ -static u_int32_t build_file(private_integrity_checker_t *this, char *file, - size_t *len) +METHOD(integrity_checker_t, build_file, u_int32_t, + private_integrity_checker_t *this, char *file, size_t *len) { u_int32_t checksum; chunk_t contents; @@ -136,11 +133,8 @@ static int callback(struct dl_phdr_info *dlpi, size_t size, Dl_info *dli) return 0; } -/** - * Implementation of integrity_checker_t.build_segment - */ -static u_int32_t build_segment(private_integrity_checker_t *this, void *sym, - size_t *len) +METHOD(integrity_checker_t, build_segment, u_int32_t, + private_integrity_checker_t *this, void *sym, size_t *len) { chunk_t segment; Dl_info dli; @@ -180,11 +174,8 @@ static integrity_checksum_t *find_checksum(private_integrity_checker_t *this, return NULL; } -/** - * Implementation of integrity_checker_t.check_file - */ -static bool check_file(private_integrity_checker_t *this, - char *name, char *file) +METHOD(integrity_checker_t, check_file, bool, + private_integrity_checker_t *this, char *name, char *file) { integrity_checksum_t *cs; u_int32_t sum; @@ -217,11 +208,8 @@ static bool check_file(private_integrity_checker_t *this, return TRUE; } -/** - * Implementation of integrity_checker_t.check_segment - */ -static bool check_segment(private_integrity_checker_t *this, - char *name, void *sym) +METHOD(integrity_checker_t, check_segment, bool, + private_integrity_checker_t *this, char *name, void *sym) { integrity_checksum_t *cs; u_int32_t sum; @@ -254,10 +242,8 @@ static bool check_segment(private_integrity_checker_t *this, return TRUE; } -/** - * Implementation of integrity_checker_t.check - */ -static bool check(private_integrity_checker_t *this, char *name, void *sym) +METHOD(integrity_checker_t, check, bool, + private_integrity_checker_t *this, char *name, void *sym) { Dl_info dli; @@ -277,10 +263,8 @@ static bool check(private_integrity_checker_t *this, char *name, void *sym) return TRUE; } -/** - * Implementation of integrity_checker_t.destroy. - */ -static void destroy(private_integrity_checker_t *this) +METHOD(integrity_checker_t, destroy, void, + private_integrity_checker_t *this) { if (this->handle) { @@ -294,17 +278,19 @@ static void destroy(private_integrity_checker_t *this) */ integrity_checker_t *integrity_checker_create(char *checksum_library) { - private_integrity_checker_t *this = malloc_thing(private_integrity_checker_t); - - this->public.check_file = (bool(*)(integrity_checker_t*, char *name, char *file))check_file; - this->public.build_file = (u_int32_t(*)(integrity_checker_t*, char *file, size_t *len))build_file; - this->public.check_segment = (bool(*)(integrity_checker_t*, char *name, void *sym))check_segment; - this->public.build_segment = (u_int32_t(*)(integrity_checker_t*, void *sym, size_t *len))build_segment; - this->public.check = (bool(*)(integrity_checker_t*, char *name, void *sym))check; - this->public.destroy = (void(*)(integrity_checker_t*))destroy; + private_integrity_checker_t *this; + + INIT(this, + .public = { + .check_file = _check_file, + .build_file = _build_file, + .check_segment = _check_segment, + .build_segment = _build_segment, + .check = _check, + .destroy = _destroy, + }, + ); - this->checksum_count = 0; - this->handle = NULL; if (checksum_library) { this->handle = dlopen(checksum_library, RTLD_LAZY); diff --git a/src/libstrongswan/plugins/aes/Makefile.in b/src/libstrongswan/plugins/aes/Makefile.in index 99a520852..9835cd5b9 100644 --- a/src/libstrongswan/plugins/aes/Makefile.in +++ b/src/libstrongswan/plugins/aes/Makefile.in @@ -219,9 +219,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -260,6 +258,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libstrongswan/plugins/aes/aes_plugin.c b/src/libstrongswan/plugins/aes/aes_plugin.c index 22b47e334..1c060b6c8 100644 --- a/src/libstrongswan/plugins/aes/aes_plugin.c +++ b/src/libstrongswan/plugins/aes/aes_plugin.c @@ -18,6 +18,8 @@ #include <library.h> #include "aes_crypter.h" +static const char *plugin_name = "aes"; + typedef struct private_aes_plugin_t private_aes_plugin_t; /** @@ -54,7 +56,7 @@ plugin_t *aes_plugin_create() }, ); - lib->crypto->add_crypter(lib->crypto, ENCR_AES_CBC, + lib->crypto->add_crypter(lib->crypto, ENCR_AES_CBC, plugin_name, (crypter_constructor_t)aes_crypter_create); return &this->public.plugin; diff --git a/src/libstrongswan/plugins/af_alg/Makefile.am b/src/libstrongswan/plugins/af_alg/Makefile.am new file mode 100644 index 000000000..a33fd30b6 --- /dev/null +++ b/src/libstrongswan/plugins/af_alg/Makefile.am @@ -0,0 +1,20 @@ + +INCLUDES = -I${linux_headers} -I$(top_srcdir)/src/libstrongswan + +AM_CFLAGS = -rdynamic + +if MONOLITHIC +noinst_LTLIBRARIES = libstrongswan-af-alg.la +else +plugin_LTLIBRARIES = libstrongswan-af-alg.la +endif + +libstrongswan_af_alg_la_SOURCES = \ + af_alg_plugin.h af_alg_plugin.c \ + af_alg_ops.h af_alg_ops.c \ + af_alg_hasher.h af_alg_hasher.c \ + af_alg_signer.h af_alg_signer.c \ + af_alg_prf.h af_alg_prf.c \ + af_alg_crypter.h af_alg_crypter.c + +libstrongswan_af_alg_la_LDFLAGS = -module -avoid-version diff --git a/src/libstrongswan/plugins/af_alg/Makefile.in b/src/libstrongswan/plugins/af_alg/Makefile.in new file mode 100644 index 000000000..aa8df979e --- /dev/null +++ b/src/libstrongswan/plugins/af_alg/Makefile.in @@ -0,0 +1,612 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 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. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@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 +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/libstrongswan/plugins/af_alg +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +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)/m4/macros/add-plugin.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__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' +am__installdirs = "$(DESTDIR)$(plugindir)" +LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES) +libstrongswan_af_alg_la_LIBADD = +am_libstrongswan_af_alg_la_OBJECTS = af_alg_plugin.lo af_alg_ops.lo \ + af_alg_hasher.lo af_alg_signer.lo af_alg_prf.lo \ + af_alg_crypter.lo +libstrongswan_af_alg_la_OBJECTS = \ + $(am_libstrongswan_af_alg_la_OBJECTS) +libstrongswan_af_alg_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(libstrongswan_af_alg_la_LDFLAGS) $(LDFLAGS) -o $@ +@MONOLITHIC_FALSE@am_libstrongswan_af_alg_la_rpath = -rpath \ +@MONOLITHIC_FALSE@ $(plugindir) +@MONOLITHIC_TRUE@am_libstrongswan_af_alg_la_rpath = +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) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libstrongswan_af_alg_la_SOURCES) +DIST_SOURCES = $(libstrongswan_af_alg_la_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BTLIB = @BTLIB@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLIB = @DLLIB@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GPERF = @GPERF@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +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@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +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@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PTHREADLIB = @PTHREADLIB@ +RANLIB = @RANLIB@ +RTLIB = @RTLIB@ +RUBY = @RUBY@ +RUBYINCLUDE = @RUBYINCLUDE@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKLIB = @SOCKLIB@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +c_plugins = @c_plugins@ +datadir = @datadir@ +datarootdir = @datarootdir@ +dbusservicedir = @dbusservicedir@ +default_pkcs11 = @default_pkcs11@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +gtk_CFLAGS = @gtk_CFLAGS@ +gtk_LIBS = @gtk_LIBS@ +h_plugins = @h_plugins@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +ipsecdir = @ipsecdir@ +ipsecgroup = @ipsecgroup@ +ipsecuser = @ipsecuser@ +libcharon_plugins = @libcharon_plugins@ +libdir = @libdir@ +libexecdir = @libexecdir@ +linux_headers = @linux_headers@ +localedir = @localedir@ +localstatedir = @localstatedir@ +lt_ECHO = @lt_ECHO@ +maemo_CFLAGS = @maemo_CFLAGS@ +maemo_LIBS = @maemo_LIBS@ +manager_plugins = @manager_plugins@ +mandir = @mandir@ +medsrv_plugins = @medsrv_plugins@ +mkdir_p = @mkdir_p@ +nm_CFLAGS = @nm_CFLAGS@ +nm_LIBS = @nm_LIBS@ +nm_ca_dir = @nm_ca_dir@ +oldincludedir = @oldincludedir@ +openac_plugins = @openac_plugins@ +p_plugins = @p_plugins@ +pdfdir = @pdfdir@ +piddir = @piddir@ +pki_plugins = @pki_plugins@ +plugindir = @plugindir@ +pluto_plugins = @pluto_plugins@ +pool_plugins = @pool_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@ +s_plugins = @s_plugins@ +sbindir = @sbindir@ +scepclient_plugins = @scepclient_plugins@ +scripts_plugins = @scripts_plugins@ +sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ +srcdir = @srcdir@ +strongswan_conf = @strongswan_conf@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +urandom_device = @urandom_device@ +xml_CFLAGS = @xml_CFLAGS@ +xml_LIBS = @xml_LIBS@ +INCLUDES = -I${linux_headers} -I$(top_srcdir)/src/libstrongswan +AM_CFLAGS = -rdynamic +@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-af-alg.la +@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-af-alg.la +libstrongswan_af_alg_la_SOURCES = \ + af_alg_plugin.h af_alg_plugin.c \ + af_alg_ops.h af_alg_ops.c \ + af_alg_hasher.h af_alg_hasher.c \ + af_alg_signer.h af_alg_signer.c \ + af_alg_prf.h af_alg_prf.c \ + af_alg_crypter.h af_alg_crypter.c + +libstrongswan_af_alg_la_LDFLAGS = -module -avoid-version +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libstrongswan/plugins/af_alg/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/libstrongswan/plugins/af_alg/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(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): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)" + @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \ + } + +uninstall-pluginLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \ + done + +clean-pluginLTLIBRARIES: + -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES) + @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libstrongswan-af-alg.la: $(libstrongswan_af_alg_la_OBJECTS) $(libstrongswan_af_alg_la_DEPENDENCIES) + $(libstrongswan_af_alg_la_LINK) $(am_libstrongswan_af_alg_la_rpath) $(libstrongswan_af_alg_la_OBJECTS) $(libstrongswan_af_alg_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/af_alg_crypter.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/af_alg_hasher.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/af_alg_ops.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/af_alg_plugin.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/af_alg_prf.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/af_alg_signer.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@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@ $(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@ $(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 $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + 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; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + 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; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + 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) + 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)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + 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 -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(plugindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +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" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + clean-pluginLTLIBRARIES mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-pluginLTLIBRARIES + +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-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pluginLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \ + ctags distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-pluginLTLIBRARIES install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags uninstall uninstall-am \ + uninstall-pluginLTLIBRARIES + + +# 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/libstrongswan/plugins/af_alg/af_alg_crypter.c b/src/libstrongswan/plugins/af_alg/af_alg_crypter.c new file mode 100644 index 000000000..3416ad8d2 --- /dev/null +++ b/src/libstrongswan/plugins/af_alg/af_alg_crypter.c @@ -0,0 +1,237 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * 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 "af_alg_crypter.h" +#include "af_alg_ops.h" + +typedef struct private_af_alg_crypter_t private_af_alg_crypter_t; + +/** + * Private data of af_alg_crypter_t + */ +struct private_af_alg_crypter_t { + + /** + * Public part of this class. + */ + af_alg_crypter_t public; + + /** + * AF_ALG operations + */ + af_alg_ops_t *ops; + + /** + * Size of the truncated signature + */ + size_t block_size; + + /** + * Size of the keymat + */ + size_t keymat_size; + + /** + * Size of initialization vector + */ + size_t iv_size; +}; + +/** + * Algorithm database + */ +static struct { + encryption_algorithm_t id; + char *name; + size_t block_size; + /* key size of the algorithm */ + size_t key_size; + /* size of the keying material (key + nonce for ctr mode) */ + size_t keymat_size; + size_t iv_size; +} algs[] = { + {ENCR_DES, "cbc(des)", 8, 8, 8, 8, }, + {ENCR_3DES, "cbc(des3_ede)", 8, 24, 24, 8, }, + {ENCR_AES_CBC, "cbc(aes)", 16, 16, 16, 16, }, + {ENCR_AES_CBC, "cbc(aes)", 16, 24, 24, 16, }, + {ENCR_AES_CBC, "cbc(aes)", 16, 32, 32, 16, }, + {ENCR_AES_CTR, "rfc3686(ctr(aes))", 1, 16, 20, 8, }, + {ENCR_AES_CTR, "rfc3686(ctr(aes))", 1, 24, 28, 8, }, + {ENCR_AES_CTR, "rfc3686(ctr(aes))", 1, 32, 36, 8, }, + {ENCR_CAMELLIA_CBC, "cbc(camellia)", 16, 16, 16, 16, }, + {ENCR_CAMELLIA_CBC, "cbc(camellia)", 16, 24, 24, 16, }, + {ENCR_CAMELLIA_CBC, "cbc(camellia)", 16, 32, 32, 16, }, + {ENCR_CAMELLIA_CTR, "rfc3686(ctr(camellia))", 1, 16, 20, 8, }, + {ENCR_CAMELLIA_CTR, "rfc3686(ctr(camellia))", 1, 24, 28, 8, }, + {ENCR_CAMELLIA_CTR, "rfc3686(ctr(camellia))", 1, 32, 36, 8, }, + {ENCR_CAST, "cbc(cast5)", 8, 16, 16, 8, }, + {ENCR_BLOWFISH, "cbc(blowfish)", 8, 16, 16, 8, }, + {ENCR_BLOWFISH, "cbc(blowfish)", 8, 24, 24, 8, }, + {ENCR_BLOWFISH, "cbc(blowfish)", 8, 32, 32, 8, }, + {ENCR_SERPENT_CBC, "cbc(serpent)", 16, 16, 16, 16, }, + {ENCR_SERPENT_CBC, "cbc(serpent)", 16, 24, 24, 16, }, + {ENCR_SERPENT_CBC, "cbc(serpent)", 16, 32, 32, 16, }, + {ENCR_TWOFISH_CBC, "cbc(twofish)", 16, 16, 16, 16, }, + {ENCR_TWOFISH_CBC, "cbc(twofish)", 16, 24, 24, 16, }, + {ENCR_TWOFISH_CBC, "cbc(twofish)", 16, 32, 32, 16, }, +}; + +/** + * See header. + */ +void af_alg_crypter_probe() +{ + encryption_algorithm_t prev = -1; + af_alg_ops_t *ops; + int i; + + for (i = 0; i < countof(algs); i++) + { + if (prev != algs[i].id) + { + ops = af_alg_ops_create("skcipher", algs[i].name); + if (ops) + { + ops->destroy(ops); + lib->crypto->add_crypter(lib->crypto, algs[i].id, af_alg_plugin_name, + (crypter_constructor_t)af_alg_crypter_create); + } + } + prev = algs[i].id; + } +} + +/** + * Get the kernel algorithm string and block/key size for our identifier + */ +static size_t lookup_alg(encryption_algorithm_t algo, char **name, + size_t key_size, size_t *keymat_size, size_t *iv_size) +{ + int i; + + for (i = 0; i < countof(algs); i++) + { + if (algs[i].id == algo && + (key_size == 0 || algs[i].key_size == key_size)) + { + *name = algs[i].name; + *keymat_size = algs[i].keymat_size; + *iv_size = algs[i].iv_size; + return algs[i].block_size; + } + } + return 0; +} + +METHOD(crypter_t, decrypt, void, + private_af_alg_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *dst) +{ + if (dst) + { + *dst = chunk_alloc(data.len); + this->ops->crypt(this->ops, ALG_OP_DECRYPT, iv, data, dst->ptr); + } + else + { + this->ops->crypt(this->ops, ALG_OP_DECRYPT, iv, data, data.ptr); + } +} + +METHOD(crypter_t, encrypt, void, + private_af_alg_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *dst) +{ + if (dst) + { + *dst = chunk_alloc(data.len); + this->ops->crypt(this->ops, ALG_OP_ENCRYPT, iv, data, dst->ptr); + } + else + { + this->ops->crypt(this->ops, ALG_OP_ENCRYPT, iv, data, data.ptr); + } +} + +METHOD(crypter_t, get_block_size, size_t, + private_af_alg_crypter_t *this) +{ + return this->block_size; +} + +METHOD(crypter_t, get_iv_size, size_t, + private_af_alg_crypter_t *this) +{ + return this->iv_size; +} + +METHOD(crypter_t, get_key_size, size_t, + private_af_alg_crypter_t *this) +{ + return this->keymat_size; +} + +METHOD(crypter_t, set_key, void, + private_af_alg_crypter_t *this, chunk_t key) +{ + this->ops->set_key(this->ops, key); +} + +METHOD(crypter_t, destroy, void, + private_af_alg_crypter_t *this) +{ + this->ops->destroy(this->ops); + free(this); +} + +/* + * Described in header + */ +af_alg_crypter_t *af_alg_crypter_create(encryption_algorithm_t algo, + size_t key_size) +{ + private_af_alg_crypter_t *this; + size_t block_size, keymat_size, iv_size; + char *name; + + block_size = lookup_alg(algo, &name, key_size, &keymat_size, &iv_size); + if (!block_size) + { /* not supported by kernel */ + return NULL; + } + + INIT(this, + .public = { + .crypter = { + .encrypt = _encrypt, + .decrypt = _decrypt, + .get_block_size = _get_block_size, + .get_iv_size = _get_iv_size, + .get_key_size = _get_key_size, + .set_key = _set_key, + .destroy = _destroy, + }, + }, + .block_size = block_size, + .keymat_size = keymat_size, + .iv_size = iv_size, + .ops = af_alg_ops_create("skcipher", name), + ); + + if (!this->ops) + { + free(this); + return NULL; + } + return &this->public; +} diff --git a/src/libstrongswan/plugins/af_alg/af_alg_crypter.h b/src/libstrongswan/plugins/af_alg/af_alg_crypter.h new file mode 100644 index 000000000..711d2fc35 --- /dev/null +++ b/src/libstrongswan/plugins/af_alg/af_alg_crypter.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * 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. + */ + +/** + * @defgroup af_alg_crypter af_alg_crypter + * @{ @ingroup af_alg + */ + +#ifndef AF_ALG_CRYPTER_H_ +#define AF_ALG_CRYPTER_H_ + +typedef struct af_alg_crypter_t af_alg_crypter_t; + +#include <crypto/crypters/crypter.h> + +/** + * Implementation of signers using AF_ALG. + */ +struct af_alg_crypter_t { + + /** + * The crypter_t interface. + */ + crypter_t crypter; +}; + +/** + * Constructor to create af_alg_crypter_t. + * + * @param algo algorithm to implement + * @param key_size key size in bytes + * @return af_alg_crypter_t, NULL if not supported + */ +af_alg_crypter_t *af_alg_crypter_create(encryption_algorithm_t algo, + size_t key_size); + +/** + * Probe algorithms and register af_alg_crypter_create(). + */ +void af_alg_crypter_probe(); + +#endif /** AF_ALG_CRYPTER_H_ @}*/ diff --git a/src/libstrongswan/plugins/af_alg/af_alg_hasher.c b/src/libstrongswan/plugins/af_alg/af_alg_hasher.c new file mode 100644 index 000000000..7c6297d44 --- /dev/null +++ b/src/libstrongswan/plugins/af_alg/af_alg_hasher.c @@ -0,0 +1,170 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * 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 "af_alg_hasher.h" +#include "af_alg_ops.h" + +typedef struct private_af_alg_hasher_t private_af_alg_hasher_t; + +/** + * Private data of af_alg_hasher_t + */ +struct private_af_alg_hasher_t { + + /** + * Public part of this class. + */ + af_alg_hasher_t public; + + /** + * AF_ALG operations + */ + af_alg_ops_t *ops; + + /** + * Size of the hash + */ + size_t size; +}; + +/** + * Algorithm database + */ +static struct { + hash_algorithm_t id; + char *name; + size_t size; +} algs[] = { + {HASH_SHA1, "sha1", HASH_SIZE_SHA1 }, + {HASH_MD5, "md5", HASH_SIZE_MD5 }, + {HASH_SHA224, "sha224", HASH_SIZE_SHA224 }, + {HASH_SHA256, "sha256", HASH_SIZE_SHA256 }, + {HASH_SHA384, "sha384", HASH_SIZE_SHA384 }, + {HASH_SHA512, "sha512", HASH_SIZE_SHA512 }, + {HASH_MD4, "md4", HASH_SIZE_MD4 }, +}; + +/** + * See header. + */ +void af_alg_hasher_probe() +{ + af_alg_ops_t *ops; + int i; + + for (i = 0; i < countof(algs); i++) + { + ops = af_alg_ops_create("hash", algs[i].name); + if (ops) + { + ops->destroy(ops); + lib->crypto->add_hasher(lib->crypto, algs[i].id, af_alg_plugin_name, + (hasher_constructor_t)af_alg_hasher_create); + } + } +} + +/** + * Get the kernel algorithm string and hash size for our identifier + */ +static size_t lookup_alg(hash_algorithm_t algo, char **name) +{ + int i; + + for (i = 0; i < countof(algs); i++) + { + if (algs[i].id == algo) + { + *name = algs[i].name; + return algs[i].size; + } + } + return 0; +} + +METHOD(hasher_t, get_hash_size, size_t, + private_af_alg_hasher_t *this) +{ + return this->size; +} + +METHOD(hasher_t, reset, void, + private_af_alg_hasher_t *this) +{ + this->ops->reset(this->ops); +} + +METHOD(hasher_t, get_hash, void, + private_af_alg_hasher_t *this, chunk_t chunk, u_int8_t *hash) +{ + this->ops->hash(this->ops, chunk, hash, this->size); +} + +METHOD(hasher_t, allocate_hash, void, + private_af_alg_hasher_t *this, chunk_t chunk, chunk_t *hash) +{ + if (hash) + { + *hash = chunk_alloc(get_hash_size(this)); + get_hash(this, chunk, hash->ptr); + } + else + { + get_hash(this, chunk, NULL); + } +} + +METHOD(hasher_t, destroy, void, + private_af_alg_hasher_t *this) +{ + this->ops->destroy(this->ops); + free(this); +} + +/* + * Described in header + */ +af_alg_hasher_t *af_alg_hasher_create(hash_algorithm_t algo) +{ + private_af_alg_hasher_t *this; + char *name; + size_t size; + + size = lookup_alg(algo, &name); + if (!size) + { /* not supported by kernel */ + return NULL; + } + + INIT(this, + .public = { + .hasher = { + .get_hash = _get_hash, + .allocate_hash = _allocate_hash, + .get_hash_size = _get_hash_size, + .reset = _reset, + .destroy = _destroy, + }, + }, + .ops = af_alg_ops_create("hash", name), + .size = size, + ); + if (!this->ops) + { + free(this); + return NULL; + } + return &this->public; +} diff --git a/src/libstrongswan/plugins/af_alg/af_alg_hasher.h b/src/libstrongswan/plugins/af_alg/af_alg_hasher.h new file mode 100644 index 000000000..e0833e23a --- /dev/null +++ b/src/libstrongswan/plugins/af_alg/af_alg_hasher.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * 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. + */ + +/** + * @defgroup af_alg_hasher af_alg_hasher + * @{ @ingroup af_alg + */ + +#ifndef af_alg_HASHER_H_ +#define af_alg_HASHER_H_ + +typedef struct af_alg_hasher_t af_alg_hasher_t; + +#include <crypto/hashers/hasher.h> + +/** + * Implementation of hashers using AF_ALG. + */ +struct af_alg_hasher_t { + + /** + * Implements hasher_t interface. + */ + hasher_t hasher; +}; + +/** + * Constructor to create af_alg_hasher_t. + * + * @param algo algorithm + * @return af_alg_hasher_t, NULL if not supported + */ +af_alg_hasher_t *af_alg_hasher_create(hash_algorithm_t algo); + +/** + * Probe algorithms and register af_alg_hasher_create(). + */ +void af_alg_hasher_probe(); + +#endif /** af_alg_HASHER_H_ @}*/ diff --git a/src/libstrongswan/plugins/af_alg/af_alg_ops.c b/src/libstrongswan/plugins/af_alg/af_alg_ops.c new file mode 100644 index 000000000..7bf1d90db --- /dev/null +++ b/src/libstrongswan/plugins/af_alg/af_alg_ops.c @@ -0,0 +1,226 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * 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 "af_alg_ops.h" + +#include <unistd.h> +#include <errno.h> +#include <linux/socket.h> + +#include <debug.h> + +const char *af_alg_plugin_name = "af-alg"; + +typedef struct private_af_alg_ops_t private_af_alg_ops_t; + +/** + * Private data of an af_alg_ops_t object. + */ +struct private_af_alg_ops_t { + + /** + * Public af_alg_ops_t interface. + */ + af_alg_ops_t public; + + /** + * Transform FD + */ + int tfm; + + /** + * Operation FD + */ + int op; +}; + +METHOD(af_alg_ops_t, reset, void, + private_af_alg_ops_t *this) +{ + if (this->op != -1) + { + close(this->op); + this->op = -1; + } +} + +METHOD(af_alg_ops_t, hash, void, + private_af_alg_ops_t *this, chunk_t data, char *out, size_t outlen) +{ + ssize_t len; + + while (this->op == -1) + { + this->op = accept(this->tfm, NULL, 0); + if (this->op == -1) + { + DBG1(DBG_LIB, "opening AF_ALG hasher failed: %s", strerror(errno)); + sleep(1); + } + } + do + { + len = send(this->op, data.ptr, data.len, out ? 0 : MSG_MORE); + if (len == -1) + { + DBG1(DBG_LIB, "writing to AF_ALG hasher failed: %s", strerror(errno)); + sleep(1); + } + else + { + data = chunk_skip(data, len); + } + } + while (data.len); + + if (out) + { + while (read(this->op, out, outlen) != outlen) + { + DBG1(DBG_LIB, "reading AF_ALG hasher failed: %s", strerror(errno)); + sleep(1); + } + reset(this); + } +} + +METHOD(af_alg_ops_t, crypt, void, + private_af_alg_ops_t *this, u_int32_t type, chunk_t iv, chunk_t data, + char *out) +{ + struct msghdr msg = {}; + struct cmsghdr *cmsg; + struct af_alg_iv *ivm; + struct iovec iov; + char buf[CMSG_SPACE(sizeof(type)) + + CMSG_SPACE(offsetof(struct af_alg_iv, iv) + iv.len)]; + ssize_t len; + int op; + + while ((op = accept(this->tfm, NULL, 0)) == -1) + { + DBG1(DBG_LIB, "accepting AF_ALG crypter failed: %s", strerror(errno)); + sleep(1); + } + + memset(buf, 0, sizeof(buf)); + + msg.msg_control = buf; + msg.msg_controllen = sizeof(buf); + + cmsg = CMSG_FIRSTHDR(&msg); + cmsg->cmsg_level = SOL_ALG; + cmsg->cmsg_type = ALG_SET_OP; + cmsg->cmsg_len = CMSG_LEN(sizeof(type)); + *(u_int32_t*)CMSG_DATA(cmsg) = type; + + cmsg = CMSG_NXTHDR(&msg, cmsg); + cmsg->cmsg_level = SOL_ALG; + cmsg->cmsg_type = ALG_SET_IV; + cmsg->cmsg_len = CMSG_LEN(offsetof(struct af_alg_iv, iv) + iv.len); + ivm = (void*)CMSG_DATA(cmsg); + ivm->ivlen = iv.len; + memcpy(ivm->iv, iv.ptr, iv.len); + + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + + while (data.len) + { + iov.iov_base = data.ptr; + iov.iov_len = data.len; + + len = sendmsg(op, &msg, 0); + if (len == -1) + { + DBG1(DBG_LIB, "writing to AF_ALG crypter failed: %s", + strerror(errno)); + sleep(1); + continue; + } + if (read(op, out, len) != len) + { + DBG1(DBG_LIB, "reading from AF_ALG crypter failed: %s", + strerror(errno)); + } + data = chunk_skip(data, len); + /* no IV for subsequent data chunks */ + msg.msg_controllen = 0; + } + close(op); +} + +METHOD(af_alg_ops_t, set_key, void, + private_af_alg_ops_t *this, chunk_t key) +{ + if (setsockopt(this->tfm, SOL_ALG, ALG_SET_KEY, key.ptr, key.len) == -1) + { + DBG1(DBG_LIB, "setting AF_ALG key failed: %s", strerror(errno)); + } +} + +METHOD(af_alg_ops_t, destroy, void, + private_af_alg_ops_t *this) +{ + close(this->tfm); + if (this->op != -1) + { + close(this->op); + } + free(this); +} + +/** + * See header + */ +af_alg_ops_t *af_alg_ops_create(char *type, char *alg) +{ + private_af_alg_ops_t *this; + struct sockaddr_alg sa = { + .salg_family = AF_ALG, + }; + + strncpy(sa.salg_type, type, sizeof(sa.salg_type)); + strncpy(sa.salg_name, alg, sizeof(sa.salg_name)); + + INIT(this, + .public = { + .hash = _hash, + .reset = _reset, + .crypt = _crypt, + .set_key = _set_key, + .destroy = _destroy, + }, + .tfm = socket(AF_ALG, SOCK_SEQPACKET, 0), + .op = -1, + ); + if (this->tfm == -1) + { + DBG1(DBG_LIB, "opening AF_ALG socket failed: %s", strerror(errno)); + free(this); + return NULL; + } + if (bind(this->tfm, (struct sockaddr*)&sa, sizeof(sa)) == -1) + { + if (errno != ENOENT) + { /* fail silently if algorithm not supported */ + DBG1(DBG_LIB, "binding AF_ALG socket for '%s' failed: %s", + sa.salg_name, strerror(errno)); + } + destroy(this); + return NULL; + } + return &this->public; +} diff --git a/src/libstrongswan/plugins/af_alg/af_alg_ops.h b/src/libstrongswan/plugins/af_alg/af_alg_ops.h new file mode 100644 index 000000000..b7d642c00 --- /dev/null +++ b/src/libstrongswan/plugins/af_alg/af_alg_ops.h @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * 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. + */ + +/** +* @defgroup af_alg_ops af_alg_ops + * @{ @ingroup af_alg + */ + +#ifndef AF_ALG_OPS_H_ +#define AF_ALG_OPS_H_ + +#include <library.h> + +#include <linux/if_alg.h> + +#ifndef AF_ALG +#define AF_ALG 38 +#endif /* AF_ALG */ + +#ifndef SOL_ALG +#define SOL_ALG 279 +#endif /* SOL_ALG */ + +extern const char *af_alg_plugin_name; + +typedef struct af_alg_ops_t af_alg_ops_t; + +/** + * Helper to run AF_ALG operations. + */ +struct af_alg_ops_t { + + /** + * Hash a chunk of data. + * + * @param data data to hash + * @param out buffer to write hash to, NULL for append mode + * @param outlen number of bytes to read into out + */ + void (*hash)(af_alg_ops_t *this, chunk_t data, char *out, size_t outlen); + + /** + * Reset hasher state. + */ + void (*reset)(af_alg_ops_t *this); + + /** + * En-/Decrypt a chunk of data. + * + * @param type crypto operation (ALG_OP_DECRYPT/ALG_OP_ENCRYPT) + * @param iv iv to use + * @param data data to encrypt/decrypt + * @param out buffer write processed data to + */ + void (*crypt)(af_alg_ops_t *this, u_int32_t type, chunk_t iv, chunk_t data, + char *out); + + /** + * Set the key for en-/decryption or HMAC/XCBC operations. + * + * @param key key to set for transform + */ + void (*set_key)(af_alg_ops_t *this, chunk_t key); + + /** + * Destroy a af_alg_ops_t. + */ + void (*destroy)(af_alg_ops_t *this); +}; + +/** + * Create a af_alg_ops instance. + * + * @param type algorithm type (hash, skcipher) + * @param alg algorithm name + * @return TRUE if AF_ALG socket bound successfully + */ +af_alg_ops_t *af_alg_ops_create(char *type, char *alg); + +#endif /** AF_ALG_OPS_H_ @}*/ diff --git a/src/libstrongswan/plugins/af_alg/af_alg_plugin.c b/src/libstrongswan/plugins/af_alg/af_alg_plugin.c new file mode 100644 index 000000000..54e39f1a0 --- /dev/null +++ b/src/libstrongswan/plugins/af_alg/af_alg_plugin.c @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * 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 "af_alg_plugin.h" + +#include <library.h> + +#include "af_alg_hasher.h" +#include "af_alg_signer.h" +#include "af_alg_prf.h" +#include "af_alg_crypter.h" + +typedef struct private_af_alg_plugin_t private_af_alg_plugin_t; + +/** + * private data of af_alg_plugin + */ +struct private_af_alg_plugin_t { + + /** + * public functions + */ + af_alg_plugin_t public; +}; + +METHOD(plugin_t, destroy, void, + private_af_alg_plugin_t *this) +{ + lib->crypto->remove_hasher(lib->crypto, + (hasher_constructor_t)af_alg_hasher_create); + lib->crypto->remove_signer(lib->crypto, + (signer_constructor_t)af_alg_signer_create); + lib->crypto->remove_prf(lib->crypto, + (prf_constructor_t)af_alg_prf_create); + lib->crypto->remove_crypter(lib->crypto, + (crypter_constructor_t)af_alg_crypter_create); + + free(this); +} + +/* + * see header file + */ +plugin_t *af_alg_plugin_create() +{ + private_af_alg_plugin_t *this; + + INIT(this, + .public = { + .plugin = { + .destroy = _destroy, + }, + }, + ); + + af_alg_hasher_probe(); + af_alg_signer_probe(); + af_alg_prf_probe(); + af_alg_crypter_probe(); + + return &this->public.plugin; +} diff --git a/src/libstrongswan/plugins/af_alg/af_alg_plugin.h b/src/libstrongswan/plugins/af_alg/af_alg_plugin.h new file mode 100644 index 000000000..18c069831 --- /dev/null +++ b/src/libstrongswan/plugins/af_alg/af_alg_plugin.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * 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. + */ + +/** + * @defgroup af_alg af_alg + * @ingroup plugins + * + * @defgroup af_alg_plugin af_alg_plugin + * @{ @ingroup af_alg + */ + +#ifndef AF_ALG_PLUGIN_H_ +#define AF_ALG_PLUGIN_H_ + +#include <plugins/plugin.h> + +typedef struct af_alg_plugin_t af_alg_plugin_t; + +/** + * Plugin providing the AF_ALG interface to the Linux Crypto API. + */ +struct af_alg_plugin_t { + + /** + * Implements plugin interface. + */ + plugin_t plugin; +}; + +#endif /** AF_ALG_PLUGIN_H_ @}*/ diff --git a/src/libstrongswan/plugins/af_alg/af_alg_prf.c b/src/libstrongswan/plugins/af_alg/af_alg_prf.c new file mode 100644 index 000000000..575906bae --- /dev/null +++ b/src/libstrongswan/plugins/af_alg/af_alg_prf.c @@ -0,0 +1,211 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * 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 "af_alg_prf.h" +#include "af_alg_ops.h" + +typedef struct private_af_alg_prf_t private_af_alg_prf_t; + +/** + * Private data of a af_alg_prf_t object. + */ +struct private_af_alg_prf_t { + + /** + * Public af_alg_prf_t interface. + */ + af_alg_prf_t public; + + /** + * AF_ALG operations + */ + af_alg_ops_t *ops; + + /** + * Size of the PRF output + */ + size_t block_size; + + /** + * Default key size + */ + size_t key_size; + + /** + * Using an XCBC algorithm? + */ + bool xcbc; +}; + +/** + * Algorithm database + */ +static struct { + pseudo_random_function_t id; + char *name; + size_t block_size; + bool xcbc; +} algs[] = { + {PRF_HMAC_SHA1, "hmac(sha1)", 20, FALSE, }, + {PRF_HMAC_SHA2_256, "hmac(sha256)", 32, FALSE, }, + {PRF_HMAC_MD5, "hmac(md5)", 16, FALSE, }, + {PRF_HMAC_SHA2_384, "hmac(sha384)", 48, FALSE, }, + {PRF_HMAC_SHA2_512, "hmac(sha512)", 64, FALSE, }, + {PRF_AES128_XCBC, "xcbc(aes)", 16, TRUE, }, + {PRF_CAMELLIA128_XCBC, "xcbc(camellia)", 16, TRUE, }, +}; + +/** + * See header. + */ +void af_alg_prf_probe() +{ + af_alg_ops_t *ops; + int i; + + for (i = 0; i < countof(algs); i++) + { + ops = af_alg_ops_create("hash", algs[i].name); + if (ops) + { + ops->destroy(ops); + lib->crypto->add_prf(lib->crypto, algs[i].id, af_alg_plugin_name, + (prf_constructor_t)af_alg_prf_create); + } + } +} + +/** + * Get the kernel algorithm string and block size for our identifier + */ +static size_t lookup_alg(integrity_algorithm_t algo, char **name, bool *xcbc) +{ + int i; + + for (i = 0; i < countof(algs); i++) + { + if (algs[i].id == algo) + { + *name = algs[i].name; + *xcbc = algs[i].xcbc; + return algs[i].block_size; + } + } + return 0; +} + +METHOD(prf_t, get_bytes, void, + private_af_alg_prf_t *this, chunk_t seed, u_int8_t *buffer) +{ + this->ops->hash(this->ops, seed, buffer, this->block_size); +} + +METHOD(prf_t, allocate_bytes, void, + private_af_alg_prf_t *this, chunk_t seed, chunk_t *chunk) +{ + if (chunk) + { + *chunk = chunk_alloc(this->block_size); + get_bytes(this, seed, chunk->ptr); + } + else + { + get_bytes(this, seed, NULL); + } +} + +METHOD(prf_t, get_block_size, size_t, + private_af_alg_prf_t *this) +{ + return this->block_size; +} + +METHOD(prf_t, get_key_size, size_t, + private_af_alg_prf_t *this) +{ + return this->block_size; +} + +METHOD(prf_t, set_key, void, + private_af_alg_prf_t *this, chunk_t key) +{ + char buf[this->block_size]; + + if (this->xcbc) + { + /* The kernel currently does not support variable length XCBC keys, + * do RFC4434 key padding/reduction manually. */ + if (key.len < this->block_size) + { + memset(buf, 0, this->block_size); + memcpy(buf, key.ptr, key.len); + key = chunk_from_thing(buf); + } + else if (key.len > this->block_size) + { + memset(buf, 0, this->block_size); + this->ops->set_key(this->ops, chunk_from_thing(buf)); + this->ops->hash(this->ops, key, buf, this->block_size); + key = chunk_from_thing(buf); + } + } + this->ops->set_key(this->ops, key); +} + +METHOD(prf_t, destroy, void, + private_af_alg_prf_t *this) +{ + this->ops->destroy(this->ops); + free(this); +} + +/* + * Described in header. + */ +af_alg_prf_t *af_alg_prf_create(pseudo_random_function_t algo) +{ + private_af_alg_prf_t *this; + size_t block_size; + bool xcbc; + char *name; + + block_size = lookup_alg(algo, &name, &xcbc); + if (!block_size) + { /* not supported by kernel */ + return NULL; + } + + INIT(this, + .public = { + .prf = { + .get_bytes = _get_bytes, + .allocate_bytes = _allocate_bytes, + .get_block_size = _get_block_size, + .get_key_size = _get_key_size, + .set_key = _set_key, + .destroy = _destroy, + }, + }, + .ops = af_alg_ops_create("hash", name), + .block_size = block_size, + .xcbc = xcbc, + ); + if (!this->ops) + { + free(this); + return NULL; + } + return &this->public; +} diff --git a/src/libstrongswan/plugins/af_alg/af_alg_prf.h b/src/libstrongswan/plugins/af_alg/af_alg_prf.h new file mode 100644 index 000000000..a3dea5649 --- /dev/null +++ b/src/libstrongswan/plugins/af_alg/af_alg_prf.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * 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. + */ + +/** + * @defgroup af_alg_prf af_alg_prf + * @{ @ingroup af_alg + */ + +#ifndef AF_ALG_PRF_H_ +#define AF_ALG_PRF_H_ + +typedef struct af_alg_prf_t af_alg_prf_t; + +#include <crypto/prfs/prf.h> + +/** + * Implementation of PRFs using AF_ALG. + */ +struct af_alg_prf_t { + + /** + * Implements prf_t interface. + */ + prf_t prf; +}; + +/** + * Creates a new af_alg_prf_t object. + * + * @param algo algorithm to implement + * @return af_alg_prf_t object, NULL if hash not supported + */ +af_alg_prf_t *af_alg_prf_create(pseudo_random_function_t algo); + +/** + * Probe algorithms and register af_alg_prf_create(). + */ +void af_alg_prf_probe(); + +#endif /** AF_ALG_PRF_H_ @}*/ diff --git a/src/libstrongswan/plugins/af_alg/af_alg_signer.c b/src/libstrongswan/plugins/af_alg/af_alg_signer.c new file mode 100644 index 000000000..3d6f907bf --- /dev/null +++ b/src/libstrongswan/plugins/af_alg/af_alg_signer.c @@ -0,0 +1,206 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * 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 "af_alg_signer.h" +#include "af_alg_ops.h" + +typedef struct private_af_alg_signer_t private_af_alg_signer_t; + +/** + * Private data structure with signing context. + */ +struct private_af_alg_signer_t { + + /** + * Public interface of af_alg_signer_t. + */ + af_alg_signer_t public; + + /** + * AF_ALG operations + */ + af_alg_ops_t *ops; + + /** + * Size of the truncated signature + */ + size_t block_size; + + /** + * Default key size + */ + size_t key_size; +}; + +/** + * Algorithm database + */ +static struct { + integrity_algorithm_t id; + char *name; + size_t block_size; + size_t key_size; +} algs[] = { + {AUTH_HMAC_SHA1_96, "hmac(sha1)", 12, 20, }, + {AUTH_HMAC_SHA1_128, "hmac(sha1)", 16, 20, }, + {AUTH_HMAC_SHA1_160, "hmac(sha1)", 20, 20, }, + {AUTH_HMAC_SHA2_256_96, "hmac(sha256)", 12, 32, }, + {AUTH_HMAC_SHA2_256_128, "hmac(sha256)", 16, 32, }, + {AUTH_HMAC_MD5_96, "hmac(md5)", 12, 16, }, + {AUTH_HMAC_MD5_128, "hmac(md5)", 16, 16, }, + {AUTH_HMAC_SHA2_256_256, "hmac(sha384)", 32, 32, }, + {AUTH_HMAC_SHA2_384_192, "hmac(sha384)", 24, 48, }, + {AUTH_HMAC_SHA2_384_384, "hmac(sha384)", 48, 48, }, + {AUTH_HMAC_SHA2_512_256, "hmac(sha512)", 32, 64, }, + {AUTH_AES_XCBC_96, "xcbc(aes)", 12, 16, }, + {AUTH_CAMELLIA_XCBC_96, "xcbc(camellia)", 12, 16, }, +}; + +/** + * See header. + */ +void af_alg_signer_probe() +{ + af_alg_ops_t *ops; + int i; + + for (i = 0; i < countof(algs); i++) + { + ops = af_alg_ops_create("hash", algs[i].name); + if (ops) + { + ops->destroy(ops); + lib->crypto->add_signer(lib->crypto, algs[i].id, af_alg_plugin_name, + (signer_constructor_t)af_alg_signer_create); + } + } +} + +/** + * Get the kernel algorithm string and block/key size for our identifier + */ +static size_t lookup_alg(integrity_algorithm_t algo, char **name, + size_t *key_size) +{ + int i; + + for (i = 0; i < countof(algs); i++) + { + if (algs[i].id == algo) + { + *name = algs[i].name; + *key_size = algs[i].key_size; + return algs[i].block_size; + } + } + return 0; +} + +METHOD(signer_t, get_signature, void, + private_af_alg_signer_t *this, chunk_t data, u_int8_t *buffer) +{ + this->ops->hash(this->ops, data, buffer, this->block_size); +} + +METHOD(signer_t, allocate_signature, void, + private_af_alg_signer_t *this, chunk_t data, chunk_t *chunk) +{ + if (chunk) + { + *chunk = chunk_alloc(this->block_size); + get_signature(this, data, chunk->ptr); + } + else + { + get_signature(this, data, NULL); + } +} + +METHOD(signer_t, verify_signature, bool, + private_af_alg_signer_t *this, chunk_t data, chunk_t signature) +{ + char sig[this->block_size]; + + if (signature.len != this->block_size) + { + return FALSE; + } + get_signature(this, data, sig); + return memeq(signature.ptr, sig, signature.len); +} + +METHOD(signer_t, get_key_size, size_t, + private_af_alg_signer_t *this) +{ + return this->key_size; +} + +METHOD(signer_t, get_block_size, size_t, + private_af_alg_signer_t *this) +{ + return this->block_size; +} + +METHOD(signer_t, set_key, void, + private_af_alg_signer_t *this, chunk_t key) +{ + this->ops->set_key(this->ops, key); +} + +METHOD(signer_t, destroy, void, + private_af_alg_signer_t *this) +{ + this->ops->destroy(this->ops); + free(this); +} + +/* + * Described in header + */ +af_alg_signer_t *af_alg_signer_create(integrity_algorithm_t algo) +{ + private_af_alg_signer_t *this; + size_t block_size, key_size; + char *name; + + block_size = lookup_alg(algo, &name, &key_size); + if (!block_size) + { /* not supported by kernel */ + return NULL; + } + + INIT(this, + .public = { + .signer = { + .get_signature = _get_signature, + .allocate_signature = _allocate_signature, + .verify_signature = _verify_signature, + .get_key_size = _get_key_size, + .get_block_size = _get_block_size, + .set_key = _set_key, + .destroy = _destroy, + }, + }, + .ops = af_alg_ops_create("hash", name), + .block_size = block_size, + .key_size = key_size, + ); + if (!this->ops) + { + free(this); + return NULL; + } + return &this->public; +} diff --git a/src/libstrongswan/plugins/af_alg/af_alg_signer.h b/src/libstrongswan/plugins/af_alg/af_alg_signer.h new file mode 100644 index 000000000..b1d90707f --- /dev/null +++ b/src/libstrongswan/plugins/af_alg/af_alg_signer.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * 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. + */ + +/** + * @defgroup af_alg_signer af_alg_signer + * @{ @ingroup af_alg + */ + +#ifndef AF_ALG_SIGNER_H_ +#define AF_ALG_SIGNER_H_ + +typedef struct af_alg_signer_t af_alg_signer_t; + +#include <crypto/signers/signer.h> + +/** + * Implementation of signers using AF_ALG. + */ +struct af_alg_signer_t { + + /** + * Implements signer_t interface. + */ + signer_t signer; +}; + +/** + * Creates a new af_alg_signer_t. + * + * @param algo algorithm to implement + * @return af_alg_signer_t, NULL if not supported + */ +af_alg_signer_t *af_alg_signer_create(integrity_algorithm_t algo); + +/** + * Probe algorithms and register af_alg_signer_create(). + */ +void af_alg_signer_probe(); + +#endif /** AF_ALG_SIGNER_H_ @}*/ diff --git a/src/libstrongswan/plugins/agent/Makefile.in b/src/libstrongswan/plugins/agent/Makefile.in index 9f65f4ffb..1a3533f03 100644 --- a/src/libstrongswan/plugins/agent/Makefile.in +++ b/src/libstrongswan/plugins/agent/Makefile.in @@ -221,9 +221,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -262,6 +260,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libstrongswan/plugins/blowfish/Makefile.in b/src/libstrongswan/plugins/blowfish/Makefile.in index d310843ac..251722f60 100644 --- a/src/libstrongswan/plugins/blowfish/Makefile.in +++ b/src/libstrongswan/plugins/blowfish/Makefile.in @@ -223,9 +223,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -264,6 +262,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libstrongswan/plugins/blowfish/blowfish_plugin.c b/src/libstrongswan/plugins/blowfish/blowfish_plugin.c index 6ab093d7b..5232eca28 100644 --- a/src/libstrongswan/plugins/blowfish/blowfish_plugin.c +++ b/src/libstrongswan/plugins/blowfish/blowfish_plugin.c @@ -19,6 +19,8 @@ #include <library.h> #include "blowfish_crypter.h" +static const char *plugin_name = "blowfish"; + typedef struct private_blowfish_plugin_t private_blowfish_plugin_t; /** @@ -55,7 +57,7 @@ plugin_t *blowfish_plugin_create() }, ); - lib->crypto->add_crypter(lib->crypto, ENCR_BLOWFISH, + lib->crypto->add_crypter(lib->crypto, ENCR_BLOWFISH, plugin_name, (crypter_constructor_t)blowfish_crypter_create); return &this->public.plugin; diff --git a/src/libstrongswan/plugins/ccm/Makefile.in b/src/libstrongswan/plugins/ccm/Makefile.in index 017d75c48..371e5b2f4 100644 --- a/src/libstrongswan/plugins/ccm/Makefile.in +++ b/src/libstrongswan/plugins/ccm/Makefile.in @@ -219,9 +219,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -260,6 +258,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libstrongswan/plugins/ccm/ccm_plugin.c b/src/libstrongswan/plugins/ccm/ccm_plugin.c index 5fc3b14d7..a4c89b548 100644 --- a/src/libstrongswan/plugins/ccm/ccm_plugin.c +++ b/src/libstrongswan/plugins/ccm/ccm_plugin.c @@ -19,6 +19,8 @@ #include "ccm_aead.h" +static const char *plugin_name = "ccm"; + typedef struct private_ccm_plugin_t private_ccm_plugin_t; /** @@ -47,23 +49,34 @@ METHOD(plugin_t, destroy, void, plugin_t *ccm_plugin_create() { private_ccm_plugin_t *this; + crypter_t *crypter; INIT(this, .public.plugin.destroy = _destroy, ); - lib->crypto->add_aead(lib->crypto, ENCR_AES_CCM_ICV8, - (aead_constructor_t)ccm_aead_create); - lib->crypto->add_aead(lib->crypto, ENCR_AES_CCM_ICV12, - (aead_constructor_t)ccm_aead_create); - lib->crypto->add_aead(lib->crypto, ENCR_AES_CCM_ICV16, - (aead_constructor_t)ccm_aead_create); - lib->crypto->add_aead(lib->crypto, ENCR_CAMELLIA_CCM_ICV8, - (aead_constructor_t)ccm_aead_create); - lib->crypto->add_aead(lib->crypto, ENCR_CAMELLIA_CCM_ICV12, - (aead_constructor_t)ccm_aead_create); - lib->crypto->add_aead(lib->crypto, ENCR_CAMELLIA_CCM_ICV16, - (aead_constructor_t)ccm_aead_create); + crypter = lib->crypto->create_crypter(lib->crypto, ENCR_AES_CBC, 0); + if (crypter) + { + crypter->destroy(crypter); + lib->crypto->add_aead(lib->crypto, ENCR_AES_CCM_ICV8, plugin_name, + (aead_constructor_t)ccm_aead_create); + lib->crypto->add_aead(lib->crypto, ENCR_AES_CCM_ICV12, plugin_name, + (aead_constructor_t)ccm_aead_create); + lib->crypto->add_aead(lib->crypto, ENCR_AES_CCM_ICV16, plugin_name, + (aead_constructor_t)ccm_aead_create); + } + crypter = lib->crypto->create_crypter(lib->crypto, ENCR_CAMELLIA_CBC, 0); + if (crypter) + { + crypter->destroy(crypter); + lib->crypto->add_aead(lib->crypto, ENCR_CAMELLIA_CCM_ICV8, plugin_name, + (aead_constructor_t)ccm_aead_create); + lib->crypto->add_aead(lib->crypto, ENCR_CAMELLIA_CCM_ICV12, plugin_name, + (aead_constructor_t)ccm_aead_create); + lib->crypto->add_aead(lib->crypto, ENCR_CAMELLIA_CCM_ICV16, plugin_name, + (aead_constructor_t)ccm_aead_create); + } return &this->public.plugin; } diff --git a/src/libstrongswan/plugins/constraints/Makefile.am b/src/libstrongswan/plugins/constraints/Makefile.am new file mode 100644 index 000000000..d80d39a2d --- /dev/null +++ b/src/libstrongswan/plugins/constraints/Makefile.am @@ -0,0 +1,16 @@ + +INCLUDES = -I$(top_srcdir)/src/libstrongswan + +AM_CFLAGS = -rdynamic + +if MONOLITHIC +noinst_LTLIBRARIES = libstrongswan-constraints.la +else +plugin_LTLIBRARIES = libstrongswan-constraints.la +endif + +libstrongswan_constraints_la_SOURCES = \ + constraints_plugin.h constraints_plugin.c \ + constraints_validator.h constraints_validator.c + +libstrongswan_constraints_la_LDFLAGS = -module -avoid-version diff --git a/src/libstrongswan/plugins/constraints/Makefile.in b/src/libstrongswan/plugins/constraints/Makefile.in new file mode 100644 index 000000000..382bfef98 --- /dev/null +++ b/src/libstrongswan/plugins/constraints/Makefile.in @@ -0,0 +1,604 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 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. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@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 +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/libstrongswan/plugins/constraints +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +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)/m4/macros/add-plugin.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__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' +am__installdirs = "$(DESTDIR)$(plugindir)" +LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES) +libstrongswan_constraints_la_LIBADD = +am_libstrongswan_constraints_la_OBJECTS = constraints_plugin.lo \ + constraints_validator.lo +libstrongswan_constraints_la_OBJECTS = \ + $(am_libstrongswan_constraints_la_OBJECTS) +libstrongswan_constraints_la_LINK = $(LIBTOOL) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(libstrongswan_constraints_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +@MONOLITHIC_FALSE@am_libstrongswan_constraints_la_rpath = -rpath \ +@MONOLITHIC_FALSE@ $(plugindir) +@MONOLITHIC_TRUE@am_libstrongswan_constraints_la_rpath = +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) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libstrongswan_constraints_la_SOURCES) +DIST_SOURCES = $(libstrongswan_constraints_la_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BTLIB = @BTLIB@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLIB = @DLLIB@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GPERF = @GPERF@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +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@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +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@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PTHREADLIB = @PTHREADLIB@ +RANLIB = @RANLIB@ +RTLIB = @RTLIB@ +RUBY = @RUBY@ +RUBYINCLUDE = @RUBYINCLUDE@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKLIB = @SOCKLIB@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +c_plugins = @c_plugins@ +datadir = @datadir@ +datarootdir = @datarootdir@ +dbusservicedir = @dbusservicedir@ +default_pkcs11 = @default_pkcs11@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +gtk_CFLAGS = @gtk_CFLAGS@ +gtk_LIBS = @gtk_LIBS@ +h_plugins = @h_plugins@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +ipsecdir = @ipsecdir@ +ipsecgroup = @ipsecgroup@ +ipsecuser = @ipsecuser@ +libcharon_plugins = @libcharon_plugins@ +libdir = @libdir@ +libexecdir = @libexecdir@ +linux_headers = @linux_headers@ +localedir = @localedir@ +localstatedir = @localstatedir@ +lt_ECHO = @lt_ECHO@ +maemo_CFLAGS = @maemo_CFLAGS@ +maemo_LIBS = @maemo_LIBS@ +manager_plugins = @manager_plugins@ +mandir = @mandir@ +medsrv_plugins = @medsrv_plugins@ +mkdir_p = @mkdir_p@ +nm_CFLAGS = @nm_CFLAGS@ +nm_LIBS = @nm_LIBS@ +nm_ca_dir = @nm_ca_dir@ +oldincludedir = @oldincludedir@ +openac_plugins = @openac_plugins@ +p_plugins = @p_plugins@ +pdfdir = @pdfdir@ +piddir = @piddir@ +pki_plugins = @pki_plugins@ +plugindir = @plugindir@ +pluto_plugins = @pluto_plugins@ +pool_plugins = @pool_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@ +s_plugins = @s_plugins@ +sbindir = @sbindir@ +scepclient_plugins = @scepclient_plugins@ +scripts_plugins = @scripts_plugins@ +sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ +srcdir = @srcdir@ +strongswan_conf = @strongswan_conf@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +urandom_device = @urandom_device@ +xml_CFLAGS = @xml_CFLAGS@ +xml_LIBS = @xml_LIBS@ +INCLUDES = -I$(top_srcdir)/src/libstrongswan +AM_CFLAGS = -rdynamic +@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-constraints.la +@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-constraints.la +libstrongswan_constraints_la_SOURCES = \ + constraints_plugin.h constraints_plugin.c \ + constraints_validator.h constraints_validator.c + +libstrongswan_constraints_la_LDFLAGS = -module -avoid-version +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libstrongswan/plugins/constraints/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/libstrongswan/plugins/constraints/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(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): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)" + @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \ + } + +uninstall-pluginLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \ + done + +clean-pluginLTLIBRARIES: + -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES) + @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libstrongswan-constraints.la: $(libstrongswan_constraints_la_OBJECTS) $(libstrongswan_constraints_la_DEPENDENCIES) + $(libstrongswan_constraints_la_LINK) $(am_libstrongswan_constraints_la_rpath) $(libstrongswan_constraints_la_OBJECTS) $(libstrongswan_constraints_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/constraints_plugin.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/constraints_validator.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@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@ $(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@ $(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 $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + 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; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + 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; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + 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) + 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)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + 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 -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(plugindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +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" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + clean-pluginLTLIBRARIES mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-pluginLTLIBRARIES + +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-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pluginLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \ + ctags distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-pluginLTLIBRARIES install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags uninstall uninstall-am \ + uninstall-pluginLTLIBRARIES + + +# 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/libstrongswan/plugins/constraints/constraints_plugin.c b/src/libstrongswan/plugins/constraints/constraints_plugin.c new file mode 100644 index 000000000..1c3f0c835 --- /dev/null +++ b/src/libstrongswan/plugins/constraints/constraints_plugin.c @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * 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 "constraints_plugin.h" + +#include <library.h> +#include "constraints_validator.h" + +typedef struct private_constraints_plugin_t private_constraints_plugin_t; + +/** + * private data of constraints_plugin + */ +struct private_constraints_plugin_t { + + /** + * public functions + */ + constraints_plugin_t public; + + /** + * Validator implementation instance. + */ + constraints_validator_t *validator; +}; + +METHOD(plugin_t, destroy, void, + private_constraints_plugin_t *this) +{ + lib->credmgr->remove_validator(lib->credmgr, &this->validator->validator); + this->validator->destroy(this->validator); + free(this); +} + +/* + * see header file + */ +plugin_t *constraints_plugin_create() +{ + private_constraints_plugin_t *this; + + INIT(this, + .public = { + .plugin = { + .destroy = _destroy, + }, + }, + .validator = constraints_validator_create(), + ); + lib->credmgr->add_validator(lib->credmgr, &this->validator->validator); + + return &this->public.plugin; +} diff --git a/src/libstrongswan/plugins/constraints/constraints_plugin.h b/src/libstrongswan/plugins/constraints/constraints_plugin.h new file mode 100644 index 000000000..7042a4d92 --- /dev/null +++ b/src/libstrongswan/plugins/constraints/constraints_plugin.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * 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. + */ + +/** + * @defgroup constraints constraints + * @ingroup plugins + * + * @defgroup constraints_plugin constraints_plugin + * @{ @ingroup constraints + */ + +#ifndef CONSTRAINTS_PLUGIN_H_ +#define CONSTRAINTS_PLUGIN_H_ + +#include <plugins/plugin.h> + +typedef struct constraints_plugin_t constraints_plugin_t; + +/** + * Advanced X509 constraint checking. + */ +struct constraints_plugin_t { + + /** + * Implements plugin_t. interface. + */ + plugin_t plugin; +}; + +#endif /** CONSTRAINTS_PLUGIN_H_ @}*/ diff --git a/src/libstrongswan/plugins/constraints/constraints_validator.c b/src/libstrongswan/plugins/constraints/constraints_validator.c new file mode 100644 index 000000000..b54d813df --- /dev/null +++ b/src/libstrongswan/plugins/constraints/constraints_validator.c @@ -0,0 +1,578 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * 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 "constraints_validator.h" + +#include <debug.h> +#include <asn1/asn1.h> +#include <utils/linked_list.h> +#include <credentials/certificates/x509.h> + +typedef struct private_constraints_validator_t private_constraints_validator_t; + +/** + * Private data of an constraints_validator_t object. + */ +struct private_constraints_validator_t { + + /** + * Public constraints_validator_t interface. + */ + constraints_validator_t public; +}; + +/** + * Check pathlen constraint of issuer certificate + */ +static bool check_pathlen(x509_t *issuer, int pathlen) +{ + u_int pathlen_constraint; + + pathlen_constraint = issuer->get_constraint(issuer, X509_PATH_LEN); + if (pathlen_constraint != X509_NO_CONSTRAINT && + pathlen > pathlen_constraint) + { + DBG1(DBG_CFG, "path length of %d violates constraint of %d", + pathlen, pathlen_constraint); + return FALSE; + } + return TRUE; +} + +/** + * Check if a FQDN/RFC822 constraint matches (suffix match) + */ +static bool suffix_matches(identification_t *constraint, identification_t *id) +{ + chunk_t c, i; + + c = constraint->get_encoding(constraint); + i = id->get_encoding(id); + + return i.len >= c.len && chunk_equals(c, chunk_skip(i, i.len - c.len)); +} + +/** + * Check if a DN constraint matches (RDN prefix match) + */ +static bool dn_matches(identification_t *constraint, identification_t *id) +{ + enumerator_t *ec, *ei; + id_part_t pc, pi; + chunk_t cc, ci; + bool match = TRUE; + + ec = constraint->create_part_enumerator(constraint); + ei = id->create_part_enumerator(id); + while (ec->enumerate(ec, &pc, &cc)) + { + if (!ei->enumerate(ei, &pi, &ci) || + pi != pc || !chunk_equals(cc, ci)) + { + match = FALSE; + break; + } + } + ec->destroy(ec); + ei->destroy(ei); + + return match; +} + +/** + * Check if a certificate matches to a NameConstraint + */ +static bool name_constraint_matches(identification_t *constraint, + certificate_t *cert, bool permitted) +{ + x509_t *x509 = (x509_t*)cert; + enumerator_t *enumerator; + identification_t *id; + id_type_t type; + bool matches = permitted; + + type = constraint->get_type(constraint); + if (type == ID_DER_ASN1_DN) + { + matches = dn_matches(constraint, cert->get_subject(cert)); + if (matches != permitted) + { + return matches; + } + } + + enumerator = x509->create_subjectAltName_enumerator(x509); + while (enumerator->enumerate(enumerator, &id)) + { + if (id->get_type(id) == type) + { + switch (type) + { + case ID_FQDN: + case ID_RFC822_ADDR: + matches = suffix_matches(constraint, id); + break; + case ID_DER_ASN1_DN: + matches = dn_matches(constraint, id); + break; + default: + DBG1(DBG_CFG, "%N NameConstraint matching not implemented", + id_type_names, type); + matches = FALSE; + break; + } + } + if (matches != permitted) + { + break; + } + } + enumerator->destroy(enumerator); + + return matches; +} + +/** + * Check if a permitted or excluded NameConstraint has been inherited to sub-CA + */ +static bool name_constraint_inherited(identification_t *constraint, + x509_t *x509, bool permitted) +{ + enumerator_t *enumerator; + identification_t *id; + bool inherited = FALSE; + id_type_t type; + + if (!(x509->get_flags(x509) & X509_CA)) + { /* not a sub-CA, not required */ + return TRUE; + } + + type = constraint->get_type(constraint); + enumerator = x509->create_name_constraint_enumerator(x509, permitted); + while (enumerator->enumerate(enumerator, &id)) + { + if (id->get_type(id) == type) + { + switch (type) + { + case ID_FQDN: + case ID_RFC822_ADDR: + if (permitted) + { /* permitted constraint can be narrowed */ + inherited = suffix_matches(constraint, id); + } + else + { /* excluded constraint can be widened */ + inherited = suffix_matches(id, constraint); + } + break; + case ID_DER_ASN1_DN: + if (permitted) + { + inherited = dn_matches(constraint, id); + } + else + { + inherited = dn_matches(id, constraint); + } + break; + default: + DBG1(DBG_CFG, "%N NameConstraint matching not implemented", + id_type_names, type); + inherited = FALSE; + break; + } + } + if (inherited) + { + break; + } + } + enumerator->destroy(enumerator); + return inherited; +} + +/** + * Check name constraints + */ +static bool check_name_constraints(certificate_t *subject, x509_t *issuer) +{ + enumerator_t *enumerator; + identification_t *constraint; + + enumerator = issuer->create_name_constraint_enumerator(issuer, TRUE); + while (enumerator->enumerate(enumerator, &constraint)) + { + if (!name_constraint_matches(constraint, subject, TRUE)) + { + DBG1(DBG_CFG, "certificate '%Y' does not match permitted name " + "constraint '%Y'", subject->get_subject(subject), constraint); + enumerator->destroy(enumerator); + return FALSE; + } + if (!name_constraint_inherited(constraint, (x509_t*)subject, TRUE)) + { + DBG1(DBG_CFG, "intermediate CA '%Y' does not inherit permitted name " + "constraint '%Y'", subject->get_subject(subject), constraint); + enumerator->destroy(enumerator); + return FALSE; + } + } + enumerator->destroy(enumerator); + + enumerator = issuer->create_name_constraint_enumerator(issuer, FALSE); + while (enumerator->enumerate(enumerator, &constraint)) + { + if (name_constraint_matches(constraint, subject, FALSE)) + { + DBG1(DBG_CFG, "certificate '%Y' matches excluded name " + "constraint '%Y'", subject->get_subject(subject), constraint); + enumerator->destroy(enumerator); + return FALSE; + } + if (!name_constraint_inherited(constraint, (x509_t*)subject, FALSE)) + { + DBG1(DBG_CFG, "intermediate CA '%Y' does not inherit excluded name " + "constraint '%Y'", subject->get_subject(subject), constraint); + enumerator->destroy(enumerator); + return FALSE; + } + } + enumerator->destroy(enumerator); + return TRUE; +} + +/** + * Special OID for anyPolicy + */ +static chunk_t any_policy = chunk_from_chars(0x55,0x1d,0x20,0x00); + +/** + * Check if an issuer certificate has a given policy OID + */ +static bool has_policy(x509_t *issuer, chunk_t oid) +{ + x509_policy_mapping_t *mapping; + x509_cert_policy_t *policy; + enumerator_t *enumerator; + + enumerator = issuer->create_cert_policy_enumerator(issuer); + while (enumerator->enumerate(enumerator, &policy)) + { + if (chunk_equals(oid, policy->oid) || + chunk_equals(any_policy, policy->oid)) + { + enumerator->destroy(enumerator); + return TRUE; + } + } + enumerator->destroy(enumerator); + + /* fall back to a mapped policy */ + enumerator = issuer->create_policy_mapping_enumerator(issuer); + while (enumerator->enumerate(enumerator, &mapping)) + { + if (chunk_equals(mapping->subject, oid)) + { + enumerator->destroy(enumerator); + return TRUE; + } + } + enumerator->destroy(enumerator); + return FALSE; +} + +/** + * Check certificatePolicies. + */ +static bool check_policy(x509_t *subject, x509_t *issuer, bool check, + auth_cfg_t *auth) +{ + certificate_t *cert = (certificate_t*)subject; + x509_policy_mapping_t *mapping; + x509_cert_policy_t *policy; + enumerator_t *enumerator; + char *oid; + + /* verify if policyMappings in subject are valid */ + enumerator = subject->create_policy_mapping_enumerator(subject); + while (enumerator->enumerate(enumerator, &mapping)) + { + if (!has_policy(issuer, mapping->issuer)) + { + oid = asn1_oid_to_string(mapping->issuer); + DBG1(DBG_CFG, "certificate '%Y' maps policy from %s, but issuer " + "misses it", cert->get_subject(cert), oid); + free(oid); + enumerator->destroy(enumerator); + return FALSE; + } + } + enumerator->destroy(enumerator); + + if (check) + { + enumerator = subject->create_cert_policy_enumerator(subject); + while (enumerator->enumerate(enumerator, &policy)) + { + if (!has_policy(issuer, policy->oid)) + { + oid = asn1_oid_to_string(policy->oid); + DBG1(DBG_CFG, "policy %s missing in issuing certificate '%Y'", + oid, cert->get_issuer(cert)); + free(oid); + enumerator->destroy(enumerator); + return FALSE; + } + if (auth) + { + oid = asn1_oid_to_string(policy->oid); + if (oid) + { + auth->add(auth, AUTH_RULE_CERT_POLICY, oid); + } + } + } + enumerator->destroy(enumerator); + } + + return TRUE; +} + +/** + * Check len certificates in trustchain for inherited policies + */ +static bool has_policy_chain(linked_list_t *chain, x509_t *subject, int len) +{ + enumerator_t *enumerator; + x509_t *issuer; + bool valid = TRUE; + + enumerator = chain->create_enumerator(chain); + while (len-- > 0 && enumerator->enumerate(enumerator, &issuer)) + { + if (!check_policy(subject, issuer, TRUE, NULL)) + { + valid = FALSE; + break; + } + subject = issuer; + } + enumerator->destroy(enumerator); + return valid; +} + +/** + * Check len certificates in trustchain to have no policyMappings + */ +static bool has_no_policy_mapping(linked_list_t *chain, int len) +{ + enumerator_t *enumerator, *mappings; + x509_policy_mapping_t *mapping; + certificate_t *cert; + x509_t *x509; + bool valid = TRUE; + + enumerator = chain->create_enumerator(chain); + while (len-- > 0 && enumerator->enumerate(enumerator, &x509)) + { + mappings = x509->create_policy_mapping_enumerator(x509); + valid = !mappings->enumerate(mappings, &mapping); + mappings->destroy(mappings); + if (!valid) + { + cert = (certificate_t*)x509; + DBG1(DBG_CFG, "found policyMapping in certificate '%Y', but " + "inhibitPolicyMapping in effect", cert->get_subject(cert)); + break; + } + } + enumerator->destroy(enumerator); + return valid; +} + +/** + * Check len certificates in trustchain to have no anyPolicies + */ +static bool has_no_any_policy(linked_list_t *chain, int len) +{ + enumerator_t *enumerator, *policies; + x509_cert_policy_t *policy; + certificate_t *cert; + x509_t *x509; + bool valid = TRUE; + + enumerator = chain->create_enumerator(chain); + while (len-- > 0 && enumerator->enumerate(enumerator, &x509)) + { + policies = x509->create_cert_policy_enumerator(x509); + while (policies->enumerate(policies, &policy)) + { + if (chunk_equals(policy->oid, any_policy)) + { + cert = (certificate_t*)x509; + DBG1(DBG_CFG, "found anyPolicy in certificate '%Y', but " + "inhibitAnyPolicy in effect", cert->get_subject(cert)); + valid = FALSE; + break; + } + } + policies->destroy(policies); + } + enumerator->destroy(enumerator); + return valid; +} + +/** + * Check requireExplicitPolicy and inhibitPolicyMapping constraints + */ +static bool check_policy_constraints(x509_t *issuer, u_int pathlen, + auth_cfg_t *auth) +{ + certificate_t *subject; + bool valid = TRUE; + + subject = auth->get(auth, AUTH_RULE_SUBJECT_CERT); + if (subject) + { + if (subject->get_type(subject) == CERT_X509) + { + enumerator_t *enumerator; + linked_list_t *chain; + certificate_t *cert; + auth_rule_t rule; + x509_t *x509; + int len = 0; + u_int expl, inh; + + /* prepare trustchain to validate */ + chain = linked_list_create(); + enumerator = auth->create_enumerator(auth); + while (enumerator->enumerate(enumerator, &rule, &cert)) + { + if (rule == AUTH_RULE_IM_CERT && + cert->get_type(cert) == CERT_X509) + { + chain->insert_last(chain, cert); + } + } + enumerator->destroy(enumerator); + chain->insert_last(chain, issuer); + + /* search for requireExplicitPolicy constraints */ + enumerator = chain->create_enumerator(chain); + while (enumerator->enumerate(enumerator, &x509)) + { + expl = x509->get_constraint(x509, X509_REQUIRE_EXPLICIT_POLICY); + if (expl != X509_NO_CONSTRAINT) + { + if (!has_policy_chain(chain, (x509_t*)subject, len - expl)) + { + valid = FALSE; + break; + } + } + len++; + } + enumerator->destroy(enumerator); + + /* search for inhibitPolicyMapping/inhibitAnyPolicy constraints */ + len = 0; + chain->insert_first(chain, subject); + enumerator = chain->create_enumerator(chain); + while (enumerator->enumerate(enumerator, &x509)) + { + inh = x509->get_constraint(x509, X509_INHIBIT_POLICY_MAPPING); + if (inh != X509_NO_CONSTRAINT) + { + if (!has_no_policy_mapping(chain, len - inh)) + { + valid = FALSE; + break; + } + } + inh = x509->get_constraint(x509, X509_INHIBIT_ANY_POLICY); + if (inh != X509_NO_CONSTRAINT) + { + if (!has_no_any_policy(chain, len - inh)) + { + valid = FALSE; + break; + } + } + len++; + } + enumerator->destroy(enumerator); + + chain->destroy(chain); + } + } + return valid; +} + +METHOD(cert_validator_t, validate, bool, + private_constraints_validator_t *this, certificate_t *subject, + certificate_t *issuer, bool online, u_int pathlen, bool anchor, + auth_cfg_t *auth) +{ + if (issuer->get_type(issuer) == CERT_X509 && + subject->get_type(subject) == CERT_X509) + { + if (!check_pathlen((x509_t*)issuer, pathlen)) + { + return FALSE; + } + if (!check_name_constraints(subject, (x509_t*)issuer)) + { + return FALSE; + } + if (!check_policy((x509_t*)subject, (x509_t*)issuer, !pathlen, auth)) + { + return FALSE; + } + if (anchor) + { + if (!check_policy_constraints((x509_t*)issuer, pathlen, auth)) + { + return FALSE; + } + } + } + return TRUE; +} + +METHOD(constraints_validator_t, destroy, void, + private_constraints_validator_t *this) +{ + free(this); +} + +/** + * See header + */ +constraints_validator_t *constraints_validator_create() +{ + private_constraints_validator_t *this; + + INIT(this, + .public = { + .validator.validate = _validate, + .destroy = _destroy, + }, + ); + + return &this->public; +} diff --git a/src/libstrongswan/plugins/constraints/constraints_validator.h b/src/libstrongswan/plugins/constraints/constraints_validator.h new file mode 100644 index 000000000..44582d6c8 --- /dev/null +++ b/src/libstrongswan/plugins/constraints/constraints_validator.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * 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. + */ + +/** + * @defgroup constraints_validator constraints_validator + * @{ @ingroup constraints + */ + +#ifndef CONSTRAINTS_VALIDATOR_H_ +#define CONSTRAINTS_VALIDATOR_H_ + +#include <credentials/cert_validator.h> + +typedef struct constraints_validator_t constraints_validator_t; + +/** + * Certificate validator doing advanced X509 constraint checking. + */ +struct constraints_validator_t { + + /** + * Implements cert_validator_t interface. + */ + cert_validator_t validator; + + /** + * Destroy a constraints_validator_t. + */ + void (*destroy)(constraints_validator_t *this); +}; + +/** + * Create a constraints_validator instance. + */ +constraints_validator_t *constraints_validator_create(); + +#endif /** CONSTRAINTS_VALIDATOR_H_ @}*/ diff --git a/src/libstrongswan/plugins/ctr/Makefile.in b/src/libstrongswan/plugins/ctr/Makefile.in index b51f57113..2f6be07e2 100644 --- a/src/libstrongswan/plugins/ctr/Makefile.in +++ b/src/libstrongswan/plugins/ctr/Makefile.in @@ -219,9 +219,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -260,6 +258,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libstrongswan/plugins/ctr/ctr_plugin.c b/src/libstrongswan/plugins/ctr/ctr_plugin.c index 5e47f23ec..9f1bf957f 100644 --- a/src/libstrongswan/plugins/ctr/ctr_plugin.c +++ b/src/libstrongswan/plugins/ctr/ctr_plugin.c @@ -19,6 +19,8 @@ #include "ctr_ipsec_crypter.h" +static const char *plugin_name = "ctr"; + typedef struct private_ctr_plugin_t private_ctr_plugin_t; /** @@ -47,6 +49,7 @@ METHOD(plugin_t, destroy, void, plugin_t *ctr_plugin_create() { private_ctr_plugin_t *this; + crypter_t *crypter; INIT(this, .public = { @@ -56,10 +59,19 @@ plugin_t *ctr_plugin_create() }, ); - lib->crypto->add_crypter(lib->crypto, ENCR_AES_CTR, - (crypter_constructor_t)ctr_ipsec_crypter_create); - lib->crypto->add_crypter(lib->crypto, ENCR_CAMELLIA_CTR, - (crypter_constructor_t)ctr_ipsec_crypter_create); - + crypter = lib->crypto->create_crypter(lib->crypto, ENCR_AES_CBC, 16); + if (crypter) + { + crypter->destroy(crypter); + lib->crypto->add_crypter(lib->crypto, ENCR_AES_CTR, plugin_name, + (crypter_constructor_t)ctr_ipsec_crypter_create); + } + crypter = lib->crypto->create_crypter(lib->crypto, ENCR_CAMELLIA_CBC, 16); + if (crypter) + { + crypter->destroy(crypter); + lib->crypto->add_crypter(lib->crypto, ENCR_CAMELLIA_CTR, plugin_name, + (crypter_constructor_t)ctr_ipsec_crypter_create); + } return &this->public.plugin; } diff --git a/src/libstrongswan/plugins/curl/Makefile.in b/src/libstrongswan/plugins/curl/Makefile.in index 9cc99063c..e61c73041 100644 --- a/src/libstrongswan/plugins/curl/Makefile.in +++ b/src/libstrongswan/plugins/curl/Makefile.in @@ -219,9 +219,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -260,6 +258,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libstrongswan/plugins/curl/curl_fetcher.c b/src/libstrongswan/plugins/curl/curl_fetcher.c index 4835f6461..82e24e810 100644 --- a/src/libstrongswan/plugins/curl/curl_fetcher.c +++ b/src/libstrongswan/plugins/curl/curl_fetcher.c @@ -104,6 +104,7 @@ METHOD(fetcher_t, fetch, status_t, METHOD(fetcher_t, set_option, bool, private_curl_fetcher_t *this, fetcher_option_t option, ...) { + bool supported = TRUE; va_list args; va_start(args, option); @@ -115,7 +116,7 @@ METHOD(fetcher_t, set_option, bool, curl_easy_setopt(this->curl, CURLOPT_POSTFIELDS, (char*)data.ptr); curl_easy_setopt(this->curl, CURLOPT_POSTFIELDSIZE, data.len); - return TRUE; + break; } case FETCH_REQUEST_TYPE: { @@ -124,30 +125,33 @@ METHOD(fetcher_t, set_option, bool, snprintf(header, BUF_LEN, "Content-Type: %s", request_type); this->headers = curl_slist_append(this->headers, header); - return TRUE; + break; } case FETCH_REQUEST_HEADER: { char *header = va_arg(args, char*); this->headers = curl_slist_append(this->headers, header); - return TRUE; + break; } case FETCH_HTTP_VERSION_1_0: { curl_easy_setopt(this->curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); - return TRUE; + break; } case FETCH_TIMEOUT: { curl_easy_setopt(this->curl, CURLOPT_CONNECTTIMEOUT, va_arg(args, u_int)); - return TRUE; + break; } default: - return FALSE; + supported = FALSE; + break; } + va_end(args); + return supported; } METHOD(fetcher_t, destroy, void, diff --git a/src/libstrongswan/plugins/curl/curl_plugin.c b/src/libstrongswan/plugins/curl/curl_plugin.c index e00fcfc03..387da03aa 100644 --- a/src/libstrongswan/plugins/curl/curl_plugin.c +++ b/src/libstrongswan/plugins/curl/curl_plugin.c @@ -34,10 +34,8 @@ struct private_curl_plugin_t { curl_plugin_t public; }; -/** - * Implementation of curl_plugin_t.curltroy - */ -static void destroy(private_curl_plugin_t *this) +METHOD(plugin_t, destroy, void, + private_curl_plugin_t *this) { lib->fetcher->remove_fetcher(lib->fetcher, (fetcher_constructor_t)curl_fetcher_create); @@ -51,9 +49,15 @@ static void destroy(private_curl_plugin_t *this) plugin_t *curl_plugin_create() { CURLcode res; - private_curl_plugin_t *this = malloc_thing(private_curl_plugin_t); + private_curl_plugin_t *this; - this->public.plugin.destroy = (void(*)(plugin_t*))destroy; + INIT(this, + .public = { + .plugin = { + .destroy = _destroy, + }, + }, + ); res = curl_global_init(CURL_GLOBAL_NOTHING); if (res == CURLE_OK) diff --git a/src/libstrongswan/plugins/des/Makefile.in b/src/libstrongswan/plugins/des/Makefile.in index 0e8fa7315..e45988ca9 100644 --- a/src/libstrongswan/plugins/des/Makefile.in +++ b/src/libstrongswan/plugins/des/Makefile.in @@ -219,9 +219,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -260,6 +258,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libstrongswan/plugins/des/des_plugin.c b/src/libstrongswan/plugins/des/des_plugin.c index 43b457ce2..d420d789e 100644 --- a/src/libstrongswan/plugins/des/des_plugin.c +++ b/src/libstrongswan/plugins/des/des_plugin.c @@ -18,6 +18,8 @@ #include <library.h> #include "des_crypter.h" +static const char *plugin_name = "des"; + typedef struct private_des_plugin_t private_des_plugin_t; /** @@ -54,11 +56,11 @@ plugin_t *des_plugin_create() }, ); - lib->crypto->add_crypter(lib->crypto, ENCR_3DES, + lib->crypto->add_crypter(lib->crypto, ENCR_3DES, plugin_name, (crypter_constructor_t)des_crypter_create); - lib->crypto->add_crypter(lib->crypto, ENCR_DES, + lib->crypto->add_crypter(lib->crypto, ENCR_DES, plugin_name, (crypter_constructor_t)des_crypter_create); - lib->crypto->add_crypter(lib->crypto, ENCR_DES_ECB, + lib->crypto->add_crypter(lib->crypto, ENCR_DES_ECB, plugin_name, (crypter_constructor_t)des_crypter_create); return &this->public.plugin; diff --git a/src/libstrongswan/plugins/dnskey/Makefile.in b/src/libstrongswan/plugins/dnskey/Makefile.in index 7f4529211..d1dce4679 100644 --- a/src/libstrongswan/plugins/dnskey/Makefile.in +++ b/src/libstrongswan/plugins/dnskey/Makefile.in @@ -222,9 +222,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -263,6 +261,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libstrongswan/plugins/dnskey/dnskey_plugin.c b/src/libstrongswan/plugins/dnskey/dnskey_plugin.c index bc0ee30ae..d11b149df 100644 --- a/src/libstrongswan/plugins/dnskey/dnskey_plugin.c +++ b/src/libstrongswan/plugins/dnskey/dnskey_plugin.c @@ -31,10 +31,8 @@ struct private_dnskey_plugin_t { dnskey_plugin_t public; }; -/** - * Implementation of dnskey_plugin_t.dnskeytroy - */ -static void destroy(private_dnskey_plugin_t *this) +METHOD(plugin_t, destroy, void, + private_dnskey_plugin_t *this) { lib->creds->remove_builder(lib->creds, (builder_function_t)dnskey_public_key_load); @@ -46,10 +44,15 @@ static void destroy(private_dnskey_plugin_t *this) */ plugin_t *dnskey_plugin_create() { - private_dnskey_plugin_t *this = malloc_thing(private_dnskey_plugin_t); - - this->public.plugin.destroy = (void(*)(plugin_t*))destroy; - + private_dnskey_plugin_t *this; + + INIT(this, + .public = { + .plugin = { + .destroy = _destroy, + }, + }, + ); lib->creds->add_builder(lib->creds, CRED_PUBLIC_KEY, KEY_ANY, FALSE, (builder_function_t)dnskey_public_key_load); lib->creds->add_builder(lib->creds, CRED_PUBLIC_KEY, KEY_RSA, FALSE, diff --git a/src/libstrongswan/plugins/fips_prf/Makefile.in b/src/libstrongswan/plugins/fips_prf/Makefile.in index 7e2a1ccdf..ab1ed6d00 100644 --- a/src/libstrongswan/plugins/fips_prf/Makefile.in +++ b/src/libstrongswan/plugins/fips_prf/Makefile.in @@ -222,9 +222,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -263,6 +261,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libstrongswan/plugins/fips_prf/fips_prf.c b/src/libstrongswan/plugins/fips_prf/fips_prf.c index ad03fa585..ee71f6efd 100644 --- a/src/libstrongswan/plugins/fips_prf/fips_prf.c +++ b/src/libstrongswan/plugins/fips_prf/fips_prf.c @@ -106,7 +106,8 @@ static void chunk_mod(size_t length, chunk_t chunk, u_int8_t buffer[]) * 0xcb, 0x0f, 0x6c, 0x55, 0xba, 0xbb, 0x13, 0x78, * 0x8e, 0x20, 0xd7, 0x37, 0xa3, 0x27, 0x51, 0x16 */ -static void get_bytes(private_fips_prf_t *this, chunk_t seed, u_int8_t w[]) +METHOD(prf_t, get_bytes, void, + private_fips_prf_t *this, chunk_t seed, u_int8_t w[]) { int i; u_int8_t xval[this->b]; @@ -139,34 +140,26 @@ static void get_bytes(private_fips_prf_t *this, chunk_t seed, u_int8_t w[]) /* 3.3 done already, mod q not used */ } -/** - * Implementation of prf_t.get_block_size. - */ -static size_t get_block_size(private_fips_prf_t *this) +METHOD(prf_t, get_block_size, size_t, + private_fips_prf_t *this) { return 2 * this->b; } -/** - * Implementation of prf_t.allocate_bytes. - */ -static void allocate_bytes(private_fips_prf_t *this, chunk_t seed, chunk_t *chunk) +METHOD(prf_t, allocate_bytes, void, + private_fips_prf_t *this, chunk_t seed, chunk_t *chunk) { *chunk = chunk_alloc(get_block_size(this)); get_bytes(this, seed, chunk->ptr); } -/** - * Implementation of prf_t.get_key_size. - */ -static size_t get_key_size(private_fips_prf_t *this) +METHOD(prf_t, get_key_size, size_t, + private_fips_prf_t *this) { return this->b; } -/** - * Implementation of prf_t.set_key. - */ -static void set_key(private_fips_prf_t *this, chunk_t key) +METHOD(prf_t, set_key, void, + private_fips_prf_t *this, chunk_t key) { /* save key as "key mod 2^b" */ chunk_mod(this->b, key, this->key); @@ -198,10 +191,8 @@ void g_sha1(private_fips_prf_t *this, chunk_t c, u_int8_t res[]) this->keyed_prf->get_bytes(this->keyed_prf, c, res); } -/** - * Implementation of prf_t.destroy. - */ -static void destroy(private_fips_prf_t *this) +METHOD(prf_t, destroy, void, + private_fips_prf_t *this) { this->keyed_prf->destroy(this->keyed_prf); free(this->key); @@ -213,14 +204,20 @@ static void destroy(private_fips_prf_t *this) */ fips_prf_t *fips_prf_create(pseudo_random_function_t algo) { - private_fips_prf_t *this = malloc_thing(private_fips_prf_t); - - this->public.prf_interface.get_bytes = (void (*) (prf_t *,chunk_t,u_int8_t*))get_bytes; - this->public.prf_interface.allocate_bytes = (void (*) (prf_t*,chunk_t,chunk_t*))allocate_bytes; - this->public.prf_interface.get_block_size = (size_t (*) (prf_t*))get_block_size; - this->public.prf_interface.get_key_size = (size_t (*) (prf_t*))get_key_size; - this->public.prf_interface.set_key = (void (*) (prf_t *,chunk_t))set_key; - this->public.prf_interface.destroy = (void (*) (prf_t *))destroy; + private_fips_prf_t *this; + + INIT(this, + .public = { + .prf_interface = { + .get_bytes = _get_bytes, + .allocate_bytes = _allocate_bytes, + .get_block_size = _get_block_size, + .get_key_size = _get_key_size, + .set_key = _set_key, + .destroy = _destroy, + }, + }, + ); switch (algo) { diff --git a/src/libstrongswan/plugins/fips_prf/fips_prf_plugin.c b/src/libstrongswan/plugins/fips_prf/fips_prf_plugin.c index f41265637..3cce6ad91 100644 --- a/src/libstrongswan/plugins/fips_prf/fips_prf_plugin.c +++ b/src/libstrongswan/plugins/fips_prf/fips_prf_plugin.c @@ -18,6 +18,8 @@ #include <library.h> #include "fips_prf.h" +static const char *plugin_name = "fips-prf"; + typedef struct private_fips_prf_plugin_t private_fips_prf_plugin_t; /** @@ -31,10 +33,8 @@ struct private_fips_prf_plugin_t { fips_prf_plugin_t public; }; -/** - * Implementation of fips_prf_plugin_t.destroy - */ -static void destroy(private_fips_prf_plugin_t *this) +METHOD(plugin_t, destroy, void, + private_fips_prf_plugin_t *this) { lib->crypto->remove_prf(lib->crypto, (prf_constructor_t)fips_prf_create); @@ -46,12 +46,24 @@ static void destroy(private_fips_prf_plugin_t *this) */ plugin_t *fips_prf_plugin_create() { - private_fips_prf_plugin_t *this = malloc_thing(private_fips_prf_plugin_t); + private_fips_prf_plugin_t *this; + prf_t *prf; - this->public.plugin.destroy = (void(*)(plugin_t*))destroy; + INIT(this, + .public = { + .plugin = { + .destroy = _destroy, + }, + }, + ); - lib->crypto->add_prf(lib->crypto, PRF_FIPS_SHA1_160, - (prf_constructor_t)fips_prf_create); + prf = lib->crypto->create_prf(lib->crypto, PRF_KEYED_SHA1); + if (prf) + { + prf->destroy(prf); + lib->crypto->add_prf(lib->crypto, PRF_FIPS_SHA1_160, plugin_name, + (prf_constructor_t)fips_prf_create); + } return &this->public.plugin; } diff --git a/src/libstrongswan/plugins/gcm/Makefile.in b/src/libstrongswan/plugins/gcm/Makefile.in index a4de9ea77..9e0b49776 100644 --- a/src/libstrongswan/plugins/gcm/Makefile.in +++ b/src/libstrongswan/plugins/gcm/Makefile.in @@ -219,9 +219,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -260,6 +258,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libstrongswan/plugins/gcm/gcm_plugin.c b/src/libstrongswan/plugins/gcm/gcm_plugin.c index 061001b30..a438fb073 100644 --- a/src/libstrongswan/plugins/gcm/gcm_plugin.c +++ b/src/libstrongswan/plugins/gcm/gcm_plugin.c @@ -19,6 +19,8 @@ #include "gcm_aead.h" +static const char *plugin_name = "gcm"; + typedef struct private_gcm_plugin_t private_gcm_plugin_t; /** @@ -47,17 +49,23 @@ METHOD(plugin_t, destroy, void, plugin_t *gcm_plugin_create() { private_gcm_plugin_t *this; + crypter_t *crypter; INIT(this, .public.plugin.destroy = _destroy, ); - lib->crypto->add_aead(lib->crypto, ENCR_AES_GCM_ICV8, - (aead_constructor_t)gcm_aead_create); - lib->crypto->add_aead(lib->crypto, ENCR_AES_GCM_ICV12, - (aead_constructor_t)gcm_aead_create); - lib->crypto->add_aead(lib->crypto, ENCR_AES_GCM_ICV16, - (aead_constructor_t)gcm_aead_create); + crypter = lib->crypto->create_crypter(lib->crypto, ENCR_AES_CBC, 0); + if (crypter) + { + crypter->destroy(crypter); + lib->crypto->add_aead(lib->crypto, ENCR_AES_GCM_ICV8, plugin_name, + (aead_constructor_t)gcm_aead_create); + lib->crypto->add_aead(lib->crypto, ENCR_AES_GCM_ICV12, plugin_name, + (aead_constructor_t)gcm_aead_create); + lib->crypto->add_aead(lib->crypto, ENCR_AES_GCM_ICV16, plugin_name, + (aead_constructor_t)gcm_aead_create); + } return &this->public.plugin; } diff --git a/src/libstrongswan/plugins/gcrypt/Makefile.in b/src/libstrongswan/plugins/gcrypt/Makefile.in index 00c49c487..1bcada7dc 100644 --- a/src/libstrongswan/plugins/gcrypt/Makefile.in +++ b/src/libstrongswan/plugins/gcrypt/Makefile.in @@ -223,9 +223,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -264,6 +262,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libstrongswan/plugins/gcrypt/gcrypt_plugin.c b/src/libstrongswan/plugins/gcrypt/gcrypt_plugin.c index 590add5c8..a53fed448 100644 --- a/src/libstrongswan/plugins/gcrypt/gcrypt_plugin.c +++ b/src/libstrongswan/plugins/gcrypt/gcrypt_plugin.c @@ -29,6 +29,8 @@ #include <errno.h> #include <gcrypt.h> +static const char *plugin_name = "gcrypt"; + typedef struct private_gcrypt_plugin_t private_gcrypt_plugin_t; /** @@ -148,79 +150,79 @@ plugin_t *gcrypt_plugin_create() ); /* hashers */ - lib->crypto->add_hasher(lib->crypto, HASH_SHA1, + lib->crypto->add_hasher(lib->crypto, HASH_SHA1, plugin_name, (hasher_constructor_t)gcrypt_hasher_create); - lib->crypto->add_hasher(lib->crypto, HASH_MD4, + lib->crypto->add_hasher(lib->crypto, HASH_MD4, plugin_name, (hasher_constructor_t)gcrypt_hasher_create); - lib->crypto->add_hasher(lib->crypto, HASH_MD5, + lib->crypto->add_hasher(lib->crypto, HASH_MD5, plugin_name, (hasher_constructor_t)gcrypt_hasher_create); - lib->crypto->add_hasher(lib->crypto, HASH_SHA224, + lib->crypto->add_hasher(lib->crypto, HASH_SHA224, plugin_name, (hasher_constructor_t)gcrypt_hasher_create); - lib->crypto->add_hasher(lib->crypto, HASH_SHA256, + lib->crypto->add_hasher(lib->crypto, HASH_SHA256, plugin_name, (hasher_constructor_t)gcrypt_hasher_create); - lib->crypto->add_hasher(lib->crypto, HASH_SHA384, + lib->crypto->add_hasher(lib->crypto, HASH_SHA384, plugin_name, (hasher_constructor_t)gcrypt_hasher_create); - lib->crypto->add_hasher(lib->crypto, HASH_SHA512, + lib->crypto->add_hasher(lib->crypto, HASH_SHA512, plugin_name, (hasher_constructor_t)gcrypt_hasher_create); /* crypters */ - lib->crypto->add_crypter(lib->crypto, ENCR_3DES, + lib->crypto->add_crypter(lib->crypto, ENCR_3DES, plugin_name, (crypter_constructor_t)gcrypt_crypter_create); - lib->crypto->add_crypter(lib->crypto, ENCR_CAST, + lib->crypto->add_crypter(lib->crypto, ENCR_CAST, plugin_name, (crypter_constructor_t)gcrypt_crypter_create); - lib->crypto->add_crypter(lib->crypto, ENCR_BLOWFISH, + lib->crypto->add_crypter(lib->crypto, ENCR_BLOWFISH, plugin_name, (crypter_constructor_t)gcrypt_crypter_create); - lib->crypto->add_crypter(lib->crypto, ENCR_DES, + lib->crypto->add_crypter(lib->crypto, ENCR_DES, plugin_name, (crypter_constructor_t)gcrypt_crypter_create); - lib->crypto->add_crypter(lib->crypto, ENCR_DES_ECB, + lib->crypto->add_crypter(lib->crypto, ENCR_DES_ECB, plugin_name, (crypter_constructor_t)gcrypt_crypter_create); - lib->crypto->add_crypter(lib->crypto, ENCR_AES_CBC, + lib->crypto->add_crypter(lib->crypto, ENCR_AES_CBC, plugin_name, (crypter_constructor_t)gcrypt_crypter_create); - lib->crypto->add_crypter(lib->crypto, ENCR_AES_CTR, + lib->crypto->add_crypter(lib->crypto, ENCR_AES_CTR, plugin_name, (crypter_constructor_t)gcrypt_crypter_create); #ifdef HAVE_GCRY_CIPHER_CAMELLIA - lib->crypto->add_crypter(lib->crypto, ENCR_CAMELLIA_CBC, + lib->crypto->add_crypter(lib->crypto, ENCR_CAMELLIA_CBC, plugin_name, (crypter_constructor_t)gcrypt_crypter_create); - lib->crypto->add_crypter(lib->crypto, ENCR_CAMELLIA_CTR, + lib->crypto->add_crypter(lib->crypto, ENCR_CAMELLIA_CTR, plugin_name, (crypter_constructor_t)gcrypt_crypter_create); #endif /* HAVE_GCRY_CIPHER_CAMELLIA */ - lib->crypto->add_crypter(lib->crypto, ENCR_SERPENT_CBC, + lib->crypto->add_crypter(lib->crypto, ENCR_SERPENT_CBC, plugin_name, (crypter_constructor_t)gcrypt_crypter_create); - lib->crypto->add_crypter(lib->crypto, ENCR_TWOFISH_CBC, + lib->crypto->add_crypter(lib->crypto, ENCR_TWOFISH_CBC, plugin_name, (crypter_constructor_t)gcrypt_crypter_create); /* random numbers */ - lib->crypto->add_rng(lib->crypto, RNG_WEAK, + lib->crypto->add_rng(lib->crypto, RNG_WEAK, plugin_name, (rng_constructor_t)gcrypt_rng_create); - lib->crypto->add_rng(lib->crypto, RNG_STRONG, + lib->crypto->add_rng(lib->crypto, RNG_STRONG, plugin_name, (rng_constructor_t)gcrypt_rng_create); - lib->crypto->add_rng(lib->crypto, RNG_TRUE, + lib->crypto->add_rng(lib->crypto, RNG_TRUE, plugin_name, (rng_constructor_t)gcrypt_rng_create); /* diffie hellman groups, using modp */ - lib->crypto->add_dh(lib->crypto, MODP_2048_BIT, + lib->crypto->add_dh(lib->crypto, MODP_2048_BIT, plugin_name, (dh_constructor_t)gcrypt_dh_create); - lib->crypto->add_dh(lib->crypto, MODP_2048_224, + lib->crypto->add_dh(lib->crypto, MODP_2048_224, plugin_name, (dh_constructor_t)gcrypt_dh_create); - lib->crypto->add_dh(lib->crypto, MODP_2048_256, + lib->crypto->add_dh(lib->crypto, MODP_2048_256, plugin_name, (dh_constructor_t)gcrypt_dh_create); - lib->crypto->add_dh(lib->crypto, MODP_1536_BIT, + lib->crypto->add_dh(lib->crypto, MODP_1536_BIT, plugin_name, (dh_constructor_t)gcrypt_dh_create); - lib->crypto->add_dh(lib->crypto, MODP_3072_BIT, + lib->crypto->add_dh(lib->crypto, MODP_3072_BIT, plugin_name, (dh_constructor_t)gcrypt_dh_create); - lib->crypto->add_dh(lib->crypto, MODP_4096_BIT, + lib->crypto->add_dh(lib->crypto, MODP_4096_BIT, plugin_name, (dh_constructor_t)gcrypt_dh_create); - lib->crypto->add_dh(lib->crypto, MODP_6144_BIT, + lib->crypto->add_dh(lib->crypto, MODP_6144_BIT, plugin_name, (dh_constructor_t)gcrypt_dh_create); - lib->crypto->add_dh(lib->crypto, MODP_8192_BIT, + lib->crypto->add_dh(lib->crypto, MODP_8192_BIT, plugin_name, (dh_constructor_t)gcrypt_dh_create); - lib->crypto->add_dh(lib->crypto, MODP_1024_BIT, + lib->crypto->add_dh(lib->crypto, MODP_1024_BIT, plugin_name, (dh_constructor_t)gcrypt_dh_create); - lib->crypto->add_dh(lib->crypto, MODP_1024_160, + lib->crypto->add_dh(lib->crypto, MODP_1024_160, plugin_name, (dh_constructor_t)gcrypt_dh_create); - lib->crypto->add_dh(lib->crypto, MODP_768_BIT, + lib->crypto->add_dh(lib->crypto, MODP_768_BIT, plugin_name, (dh_constructor_t)gcrypt_dh_create); - lib->crypto->add_dh(lib->crypto, MODP_CUSTOM, + lib->crypto->add_dh(lib->crypto, MODP_CUSTOM, plugin_name, (dh_constructor_t)gcrypt_dh_create_custom); /* RSA */ diff --git a/src/libstrongswan/plugins/gmp/Makefile.in b/src/libstrongswan/plugins/gmp/Makefile.in index b4ec1ed8d..f73bfb406 100644 --- a/src/libstrongswan/plugins/gmp/Makefile.in +++ b/src/libstrongswan/plugins/gmp/Makefile.in @@ -220,9 +220,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -261,6 +259,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libstrongswan/plugins/gmp/gmp_plugin.c b/src/libstrongswan/plugins/gmp/gmp_plugin.c index 9b4fad3da..e9bfbcc28 100644 --- a/src/libstrongswan/plugins/gmp/gmp_plugin.c +++ b/src/libstrongswan/plugins/gmp/gmp_plugin.c @@ -20,6 +20,8 @@ #include "gmp_rsa_private_key.h" #include "gmp_rsa_public_key.h" +static const char *plugin_name = "gmp"; + typedef struct private_gmp_plugin_t private_gmp_plugin_t; /** @@ -64,30 +66,30 @@ plugin_t *gmp_plugin_create() }, ); - lib->crypto->add_dh(lib->crypto, MODP_2048_BIT, + lib->crypto->add_dh(lib->crypto, MODP_2048_BIT, plugin_name, (dh_constructor_t)gmp_diffie_hellman_create); - lib->crypto->add_dh(lib->crypto, MODP_2048_224, + lib->crypto->add_dh(lib->crypto, MODP_2048_224, plugin_name, (dh_constructor_t)gmp_diffie_hellman_create); - lib->crypto->add_dh(lib->crypto, MODP_2048_256, + lib->crypto->add_dh(lib->crypto, MODP_2048_256, plugin_name, (dh_constructor_t)gmp_diffie_hellman_create); - lib->crypto->add_dh(lib->crypto, MODP_1536_BIT, + lib->crypto->add_dh(lib->crypto, MODP_1536_BIT, plugin_name, (dh_constructor_t)gmp_diffie_hellman_create); - lib->crypto->add_dh(lib->crypto, MODP_3072_BIT, + lib->crypto->add_dh(lib->crypto, MODP_3072_BIT, plugin_name, (dh_constructor_t)gmp_diffie_hellman_create); - lib->crypto->add_dh(lib->crypto, MODP_4096_BIT, + lib->crypto->add_dh(lib->crypto, MODP_4096_BIT, plugin_name, (dh_constructor_t)gmp_diffie_hellman_create); - lib->crypto->add_dh(lib->crypto, MODP_6144_BIT, + lib->crypto->add_dh(lib->crypto, MODP_6144_BIT, plugin_name, (dh_constructor_t)gmp_diffie_hellman_create); - lib->crypto->add_dh(lib->crypto, MODP_8192_BIT, + lib->crypto->add_dh(lib->crypto, MODP_8192_BIT, plugin_name, (dh_constructor_t)gmp_diffie_hellman_create); - lib->crypto->add_dh(lib->crypto, MODP_1024_BIT, + lib->crypto->add_dh(lib->crypto, MODP_1024_BIT, plugin_name, (dh_constructor_t)gmp_diffie_hellman_create); - lib->crypto->add_dh(lib->crypto, MODP_1024_160, + lib->crypto->add_dh(lib->crypto, MODP_1024_160, plugin_name, (dh_constructor_t)gmp_diffie_hellman_create); - lib->crypto->add_dh(lib->crypto, MODP_768_BIT, + lib->crypto->add_dh(lib->crypto, MODP_768_BIT, plugin_name, (dh_constructor_t)gmp_diffie_hellman_create); - lib->crypto->add_dh(lib->crypto, MODP_CUSTOM, + lib->crypto->add_dh(lib->crypto, MODP_CUSTOM, plugin_name, (dh_constructor_t)gmp_diffie_hellman_create_custom); lib->creds->add_builder(lib->creds, CRED_PRIVATE_KEY, KEY_RSA, FALSE, diff --git a/src/libstrongswan/plugins/hmac/Makefile.in b/src/libstrongswan/plugins/hmac/Makefile.in index 42a7d3747..72cc23b72 100644 --- a/src/libstrongswan/plugins/hmac/Makefile.in +++ b/src/libstrongswan/plugins/hmac/Makefile.in @@ -220,9 +220,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -261,6 +259,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libstrongswan/plugins/hmac/hmac_plugin.c b/src/libstrongswan/plugins/hmac/hmac_plugin.c index 73df4dc6c..76d6157ae 100644 --- a/src/libstrongswan/plugins/hmac/hmac_plugin.c +++ b/src/libstrongswan/plugins/hmac/hmac_plugin.c @@ -19,6 +19,8 @@ #include "hmac_signer.h" #include "hmac_prf.h" +static const char *plugin_name = "hmac"; + typedef struct private_hmac_plugin_t private_hmac_plugin_t; /** @@ -48,6 +50,7 @@ METHOD(plugin_t, destroy, void, plugin_t *hmac_plugin_create() { private_hmac_plugin_t *this; + hasher_t *hasher; INIT(this, .public = { @@ -57,37 +60,62 @@ plugin_t *hmac_plugin_create() }, ); - lib->crypto->add_prf(lib->crypto, PRF_HMAC_SHA2_256, - (prf_constructor_t)hmac_prf_create); - lib->crypto->add_prf(lib->crypto, PRF_HMAC_SHA1, - (prf_constructor_t)hmac_prf_create); - lib->crypto->add_prf(lib->crypto, PRF_HMAC_MD5, - (prf_constructor_t)hmac_prf_create); - lib->crypto->add_prf(lib->crypto, PRF_HMAC_SHA2_384, - (prf_constructor_t)hmac_prf_create); - lib->crypto->add_prf(lib->crypto, PRF_HMAC_SHA2_512, - (prf_constructor_t)hmac_prf_create); + hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1); + if (hasher) + { + hasher->destroy(hasher); + lib->crypto->add_prf(lib->crypto, PRF_HMAC_SHA1, plugin_name, + (prf_constructor_t)hmac_prf_create); + lib->crypto->add_signer(lib->crypto, AUTH_HMAC_SHA1_96, plugin_name, + (signer_constructor_t)hmac_signer_create); + lib->crypto->add_signer(lib->crypto, AUTH_HMAC_SHA1_128, plugin_name, + (signer_constructor_t)hmac_signer_create); + lib->crypto->add_signer(lib->crypto, AUTH_HMAC_SHA1_160, plugin_name, + (signer_constructor_t)hmac_signer_create); + } + hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA256); + if (hasher) + { + hasher->destroy(hasher); + lib->crypto->add_prf(lib->crypto, PRF_HMAC_SHA2_256, plugin_name, + (prf_constructor_t)hmac_prf_create); + lib->crypto->add_signer(lib->crypto, AUTH_HMAC_SHA2_256_128, plugin_name, + (signer_constructor_t)hmac_signer_create); + lib->crypto->add_signer(lib->crypto, AUTH_HMAC_SHA2_256_256, plugin_name, + (signer_constructor_t)hmac_signer_create); - lib->crypto->add_signer(lib->crypto, AUTH_HMAC_SHA1_96, - (signer_constructor_t)hmac_signer_create); - lib->crypto->add_signer(lib->crypto, AUTH_HMAC_SHA1_128, - (signer_constructor_t)hmac_signer_create); - lib->crypto->add_signer(lib->crypto, AUTH_HMAC_SHA1_160, - (signer_constructor_t)hmac_signer_create); - lib->crypto->add_signer(lib->crypto, AUTH_HMAC_SHA2_256_128, - (signer_constructor_t)hmac_signer_create); - lib->crypto->add_signer(lib->crypto, AUTH_HMAC_SHA2_256_256, - (signer_constructor_t)hmac_signer_create); - lib->crypto->add_signer(lib->crypto, AUTH_HMAC_MD5_96, - (signer_constructor_t)hmac_signer_create); - lib->crypto->add_signer(lib->crypto, AUTH_HMAC_MD5_128, - (signer_constructor_t)hmac_signer_create); - lib->crypto->add_signer(lib->crypto, AUTH_HMAC_SHA2_384_192, - (signer_constructor_t)hmac_signer_create); - lib->crypto->add_signer(lib->crypto, AUTH_HMAC_SHA2_384_384, - (signer_constructor_t)hmac_signer_create); - lib->crypto->add_signer(lib->crypto, AUTH_HMAC_SHA2_512_256, - (signer_constructor_t)hmac_signer_create); + } + hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD5); + if (hasher) + { + hasher->destroy(hasher); + lib->crypto->add_prf(lib->crypto, PRF_HMAC_MD5, plugin_name, + (prf_constructor_t)hmac_prf_create); + lib->crypto->add_signer(lib->crypto, AUTH_HMAC_MD5_96, plugin_name, + (signer_constructor_t)hmac_signer_create); + lib->crypto->add_signer(lib->crypto, AUTH_HMAC_MD5_128, plugin_name, + (signer_constructor_t)hmac_signer_create); + } + hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA384); + if (hasher) + { + hasher->destroy(hasher); + lib->crypto->add_prf(lib->crypto, PRF_HMAC_SHA2_384, plugin_name, + (prf_constructor_t)hmac_prf_create); + lib->crypto->add_signer(lib->crypto, AUTH_HMAC_SHA2_384_192, plugin_name, + (signer_constructor_t)hmac_signer_create); + lib->crypto->add_signer(lib->crypto, AUTH_HMAC_SHA2_384_384, plugin_name, + (signer_constructor_t)hmac_signer_create); + } + hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA512); + if (hasher) + { + hasher->destroy(hasher); + lib->crypto->add_prf(lib->crypto, PRF_HMAC_SHA2_512, plugin_name, + (prf_constructor_t)hmac_prf_create); + lib->crypto->add_signer(lib->crypto, AUTH_HMAC_SHA2_512_256, plugin_name, + (signer_constructor_t)hmac_signer_create); + } return &this->public.plugin; } diff --git a/src/libstrongswan/plugins/ldap/Makefile.in b/src/libstrongswan/plugins/ldap/Makefile.in index 65a135e76..7235784e2 100644 --- a/src/libstrongswan/plugins/ldap/Makefile.in +++ b/src/libstrongswan/plugins/ldap/Makefile.in @@ -219,9 +219,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -260,6 +258,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libstrongswan/plugins/ldap/ldap_fetcher.c b/src/libstrongswan/plugins/ldap/ldap_fetcher.c index 59e655cd5..e6c592217 100644 --- a/src/libstrongswan/plugins/ldap/ldap_fetcher.c +++ b/src/libstrongswan/plugins/ldap/ldap_fetcher.c @@ -100,8 +100,8 @@ static bool parse(LDAP *ldap, LDAPMessage *result, chunk_t *response) } -static status_t fetch(private_ldap_fetcher_t *this, char *url, - chunk_t *result, va_list args) +METHOD(fetcher_t, fetch, status_t, + private_ldap_fetcher_t *this, char *url, chunk_t *result) { LDAP *ldap; LDAPURLDesc *lurl; @@ -166,10 +166,8 @@ static status_t fetch(private_ldap_fetcher_t *this, char *url, } -/** - * Implementation of fetcher_t.set_option. - */ -static bool set_option(private_ldap_fetcher_t *this, fetcher_option_t option, ...) +METHOD(fetcher_t, set_option, bool, + private_ldap_fetcher_t *this, fetcher_option_t option, ...) { va_list args; @@ -186,10 +184,8 @@ static bool set_option(private_ldap_fetcher_t *this, fetcher_option_t option, .. } } -/** - * Implements ldap_fetcher_t.destroy - */ -static void destroy(private_ldap_fetcher_t *this) +METHOD(fetcher_t, destroy, void, + private_ldap_fetcher_t *this) { free(this); } @@ -199,13 +195,18 @@ static void destroy(private_ldap_fetcher_t *this) */ ldap_fetcher_t *ldap_fetcher_create() { - private_ldap_fetcher_t *this = malloc_thing(private_ldap_fetcher_t); - - this->public.interface.fetch = (status_t(*)(fetcher_t*,char*,chunk_t*))fetch; - this->public.interface.set_option = (bool(*)(fetcher_t*, fetcher_option_t option, ...))set_option; - this->public.interface.destroy = (void (*)(fetcher_t*))destroy; - - this->timeout = DEFAULT_TIMEOUT; + private_ldap_fetcher_t *this; + + INIT(this, + .public = { + .interface = { + .fetch = _fetch, + .set_option = _set_option, + .destroy = _destroy, + }, + }, + .timeout = DEFAULT_TIMEOUT, + ); return &this->public; } diff --git a/src/libstrongswan/plugins/ldap/ldap_plugin.c b/src/libstrongswan/plugins/ldap/ldap_plugin.c index 372ac9f93..3682ddd1f 100644 --- a/src/libstrongswan/plugins/ldap/ldap_plugin.c +++ b/src/libstrongswan/plugins/ldap/ldap_plugin.c @@ -31,10 +31,8 @@ struct private_ldap_plugin_t { ldap_plugin_t public; }; -/** - * Implementation of ldap_plugin_t.destroy - */ -static void destroy(private_ldap_plugin_t *this) +METHOD(plugin_t, destroy, void, + private_ldap_plugin_t *this) { lib->fetcher->remove_fetcher(lib->fetcher, (fetcher_constructor_t)ldap_fetcher_create); @@ -46,9 +44,15 @@ static void destroy(private_ldap_plugin_t *this) */ plugin_t *ldap_plugin_create() { - private_ldap_plugin_t *this = malloc_thing(private_ldap_plugin_t); + private_ldap_plugin_t *this; - this->public.plugin.destroy = (void(*)(plugin_t*))destroy; + INIT(this, + .public = { + .plugin = { + .destroy = _destroy, + }, + }, + ); lib->fetcher->add_fetcher(lib->fetcher, (fetcher_constructor_t)ldap_fetcher_create, "ldap://"); diff --git a/src/libstrongswan/plugins/md4/Makefile.in b/src/libstrongswan/plugins/md4/Makefile.in index a78dad97c..ea1a7a69a 100644 --- a/src/libstrongswan/plugins/md4/Makefile.in +++ b/src/libstrongswan/plugins/md4/Makefile.in @@ -219,9 +219,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -260,6 +258,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libstrongswan/plugins/md4/md4_plugin.c b/src/libstrongswan/plugins/md4/md4_plugin.c index 38ae0d4bc..cea1a61f3 100644 --- a/src/libstrongswan/plugins/md4/md4_plugin.c +++ b/src/libstrongswan/plugins/md4/md4_plugin.c @@ -18,6 +18,8 @@ #include <library.h> #include "md4_hasher.h" +static const char *plugin_name = "md4"; + typedef struct private_md4_plugin_t private_md4_plugin_t; /** @@ -31,10 +33,8 @@ struct private_md4_plugin_t { md4_plugin_t public; }; -/** - * Implementation of md4_plugin_t.destroy - */ -static void destroy(private_md4_plugin_t *this) +METHOD(plugin_t, destroy, void, + private_md4_plugin_t *this) { lib->crypto->remove_hasher(lib->crypto, (hasher_constructor_t)md4_hasher_create); @@ -46,11 +46,17 @@ static void destroy(private_md4_plugin_t *this) */ plugin_t *md4_plugin_create() { - private_md4_plugin_t *this = malloc_thing(private_md4_plugin_t); + private_md4_plugin_t *this; - this->public.plugin.destroy = (void(*)(plugin_t*))destroy; + INIT(this, + .public = { + .plugin = { + .destroy = _destroy, + }, + }, + ); - lib->crypto->add_hasher(lib->crypto, HASH_MD4, + lib->crypto->add_hasher(lib->crypto, HASH_MD4, plugin_name, (hasher_constructor_t)md4_hasher_create); return &this->public.plugin; diff --git a/src/libstrongswan/plugins/md5/Makefile.in b/src/libstrongswan/plugins/md5/Makefile.in index 6de400e8e..05f101564 100644 --- a/src/libstrongswan/plugins/md5/Makefile.in +++ b/src/libstrongswan/plugins/md5/Makefile.in @@ -219,9 +219,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -260,6 +258,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libstrongswan/plugins/md5/md5_plugin.c b/src/libstrongswan/plugins/md5/md5_plugin.c index cfbf6acea..d11173817 100644 --- a/src/libstrongswan/plugins/md5/md5_plugin.c +++ b/src/libstrongswan/plugins/md5/md5_plugin.c @@ -18,6 +18,8 @@ #include <library.h> #include "md5_hasher.h" +static const char *plugin_name = "md5"; + typedef struct private_md5_plugin_t private_md5_plugin_t; /** @@ -31,10 +33,8 @@ struct private_md5_plugin_t { md5_plugin_t public; }; -/** - * Implementation of md5_plugin_t.destroy - */ -static void destroy(private_md5_plugin_t *this) +METHOD(plugin_t, destroy, void, + private_md5_plugin_t *this) { lib->crypto->remove_hasher(lib->crypto, (hasher_constructor_t)md5_hasher_create); @@ -46,11 +46,17 @@ static void destroy(private_md5_plugin_t *this) */ plugin_t *md5_plugin_create() { - private_md5_plugin_t *this = malloc_thing(private_md5_plugin_t); + private_md5_plugin_t *this; - this->public.plugin.destroy = (void(*)(plugin_t*))destroy; + INIT(this, + .public = { + .plugin = { + .destroy = _destroy, + }, + }, + ); - lib->crypto->add_hasher(lib->crypto, HASH_MD5, + lib->crypto->add_hasher(lib->crypto, HASH_MD5, plugin_name, (hasher_constructor_t)md5_hasher_create); return &this->public.plugin; diff --git a/src/libstrongswan/plugins/mysql/Makefile.in b/src/libstrongswan/plugins/mysql/Makefile.in index 7d4d42c14..4880415b3 100644 --- a/src/libstrongswan/plugins/mysql/Makefile.in +++ b/src/libstrongswan/plugins/mysql/Makefile.in @@ -221,9 +221,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -262,6 +260,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libstrongswan/plugins/mysql/mysql_database.c b/src/libstrongswan/plugins/mysql/mysql_database.c index 8005b9149..5fbfa0f28 100644 --- a/src/libstrongswan/plugins/mysql/mysql_database.c +++ b/src/libstrongswan/plugins/mysql/mysql_database.c @@ -474,10 +474,8 @@ static bool mysql_enumerator_enumerate(mysql_enumerator_t *this, ...) return TRUE; } -/** - * Implementation of database_t.query. - */ -static enumerator_t* query(private_mysql_database_t *this, char *sql, ...) +METHOD(database_t, query, enumerator_t*, + private_mysql_database_t *this, char *sql, ...) { MYSQL_STMT *stmt; va_list args; @@ -563,10 +561,8 @@ static enumerator_t* query(private_mysql_database_t *this, char *sql, ...) return (enumerator_t*)enumerator; } -/** - * Implementation of database_t.execute. - */ -static int execute(private_mysql_database_t *this, int *rowid, char *sql, ...) +METHOD(database_t, execute, int, + private_mysql_database_t *this, int *rowid, char *sql, ...) { MYSQL_STMT *stmt; va_list args; @@ -594,18 +590,14 @@ static int execute(private_mysql_database_t *this, int *rowid, char *sql, ...) return affected; } -/** - * Implementation of database_t.get_driver - */ -static db_driver_t get_driver(private_mysql_database_t *this) +METHOD(database_t, get_driver,db_driver_t, + private_mysql_database_t *this) { return DB_MYSQL; } -/** - * Implementation of database_t.destroy - */ -static void destroy(private_mysql_database_t *this) +METHOD(database_t, destroy, void, + private_mysql_database_t *this) { this->pool->destroy_function(this->pool, (void*)conn_destroy); this->mutex->destroy(this->mutex); @@ -677,12 +669,16 @@ mysql_database_t *mysql_database_create(char *uri) return NULL; } - this = malloc_thing(private_mysql_database_t); - - this->public.db.query = (enumerator_t* (*)(database_t *this, char *sql, ...))query; - this->public.db.execute = (int (*)(database_t *this, int *rowid, char *sql, ...))execute; - this->public.db.get_driver = (db_driver_t(*)(database_t*))get_driver; - this->public.db.destroy = (void(*)(database_t*))destroy; + INIT(this, + .public = { + .db = { + .query = _query, + .execute = _execute, + .get_driver = _get_driver, + .destroy = _destroy, + }, + }, + ); if (!parse_uri(this, uri)) { diff --git a/src/libstrongswan/plugins/mysql/mysql_plugin.c b/src/libstrongswan/plugins/mysql/mysql_plugin.c index a13aa8091..65d8681cb 100644 --- a/src/libstrongswan/plugins/mysql/mysql_plugin.c +++ b/src/libstrongswan/plugins/mysql/mysql_plugin.c @@ -32,10 +32,8 @@ struct private_mysql_plugin_t { mysql_plugin_t public; }; -/** - * Implementation of plugin_t.destroy - */ -static void destroy(private_mysql_plugin_t *this) +METHOD(plugin_t, destroy, void, + private_mysql_plugin_t *this) { lib->db->remove_database(lib->db, (database_constructor_t)mysql_database_create); @@ -56,8 +54,13 @@ plugin_t *mysql_plugin_create() return NULL; } - this = malloc_thing(private_mysql_plugin_t); - this->public.plugin.destroy = (void(*)(plugin_t*))destroy; + INIT(this, + .public = { + .plugin = { + .destroy = _destroy, + }, + }, + ); lib->db->add_database(lib->db, (database_constructor_t)mysql_database_create); diff --git a/src/libstrongswan/plugins/openssl/Makefile.in b/src/libstrongswan/plugins/openssl/Makefile.in index a32418b16..b43be29f1 100644 --- a/src/libstrongswan/plugins/openssl/Makefile.in +++ b/src/libstrongswan/plugins/openssl/Makefile.in @@ -226,9 +226,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -267,6 +265,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libstrongswan/plugins/openssl/openssl_crl.c b/src/libstrongswan/plugins/openssl/openssl_crl.c index b9d97a901..58401faa5 100644 --- a/src/libstrongswan/plugins/openssl/openssl_crl.c +++ b/src/libstrongswan/plugins/openssl/openssl_crl.c @@ -382,6 +382,8 @@ static private_openssl_crl_t *create_empty() }, .get_serial = _get_serial, .get_authKeyIdentifier = _get_authKeyIdentifier, + .is_delta_crl = (void*)return_false, + .create_delta_crl_uri_enumerator = (void*)enumerator_create_empty, .create_enumerator = _create_enumerator, }, }, @@ -458,7 +460,14 @@ static bool parse_extensions(private_openssl_crl_t *this) ok = parse_crlNumber_ext(this, ext); break; default: - ok = TRUE; + ok = X509_EXTENSION_get_critical(ext) == 0 || + !lib->settings->get_bool(lib->settings, + "libstrongswan.x509.enforce_critical", TRUE); + if (!ok) + { + DBG1(DBG_LIB, "found unsupported critical X.509 " + "CRL extension"); + } break; } if (!ok) diff --git a/src/libstrongswan/plugins/openssl/openssl_plugin.c b/src/libstrongswan/plugins/openssl/openssl_plugin.c index 0ab4eda9c..0050572ee 100644 --- a/src/libstrongswan/plugins/openssl/openssl_plugin.c +++ b/src/libstrongswan/plugins/openssl/openssl_plugin.c @@ -41,6 +41,8 @@ #include "openssl_x509.h" #include "openssl_crl.h" +static const char *plugin_name = "openssl"; + typedef struct private_openssl_plugin_t private_openssl_plugin_t; /** @@ -272,85 +274,85 @@ plugin_t *openssl_plugin_create() } /* crypter */ - lib->crypto->add_crypter(lib->crypto, ENCR_AES_CBC, + lib->crypto->add_crypter(lib->crypto, ENCR_AES_CBC, plugin_name, (crypter_constructor_t)openssl_crypter_create); - lib->crypto->add_crypter(lib->crypto, ENCR_CAMELLIA_CBC, + lib->crypto->add_crypter(lib->crypto, ENCR_CAMELLIA_CBC, plugin_name, (crypter_constructor_t)openssl_crypter_create); - lib->crypto->add_crypter(lib->crypto, ENCR_3DES, + lib->crypto->add_crypter(lib->crypto, ENCR_3DES, plugin_name, (crypter_constructor_t)openssl_crypter_create); - lib->crypto->add_crypter(lib->crypto, ENCR_RC5, + lib->crypto->add_crypter(lib->crypto, ENCR_RC5, plugin_name, (crypter_constructor_t)openssl_crypter_create); - lib->crypto->add_crypter(lib->crypto, ENCR_IDEA, + lib->crypto->add_crypter(lib->crypto, ENCR_IDEA, plugin_name, (crypter_constructor_t)openssl_crypter_create); - lib->crypto->add_crypter(lib->crypto, ENCR_CAST, + lib->crypto->add_crypter(lib->crypto, ENCR_CAST, plugin_name, (crypter_constructor_t)openssl_crypter_create); - lib->crypto->add_crypter(lib->crypto, ENCR_BLOWFISH, + lib->crypto->add_crypter(lib->crypto, ENCR_BLOWFISH, plugin_name, (crypter_constructor_t)openssl_crypter_create); - lib->crypto->add_crypter(lib->crypto, ENCR_DES, + lib->crypto->add_crypter(lib->crypto, ENCR_DES, plugin_name, (crypter_constructor_t)openssl_crypter_create); - lib->crypto->add_crypter(lib->crypto, ENCR_DES_ECB, + lib->crypto->add_crypter(lib->crypto, ENCR_DES_ECB, plugin_name, (crypter_constructor_t)openssl_crypter_create); - lib->crypto->add_crypter(lib->crypto, ENCR_NULL, + lib->crypto->add_crypter(lib->crypto, ENCR_NULL, plugin_name, (crypter_constructor_t)openssl_crypter_create); /* hasher */ - lib->crypto->add_hasher(lib->crypto, HASH_SHA1, + lib->crypto->add_hasher(lib->crypto, HASH_SHA1, plugin_name, (hasher_constructor_t)openssl_hasher_create); - lib->crypto->add_hasher(lib->crypto, HASH_MD2, + lib->crypto->add_hasher(lib->crypto, HASH_MD2, plugin_name, (hasher_constructor_t)openssl_hasher_create); - lib->crypto->add_hasher(lib->crypto, HASH_MD4, + lib->crypto->add_hasher(lib->crypto, HASH_MD4, plugin_name, (hasher_constructor_t)openssl_hasher_create); - lib->crypto->add_hasher(lib->crypto, HASH_MD5, + lib->crypto->add_hasher(lib->crypto, HASH_MD5, plugin_name, (hasher_constructor_t)openssl_hasher_create); - lib->crypto->add_hasher(lib->crypto, HASH_SHA224, + lib->crypto->add_hasher(lib->crypto, HASH_SHA224, plugin_name, (hasher_constructor_t)openssl_hasher_create); - lib->crypto->add_hasher(lib->crypto, HASH_SHA256, + lib->crypto->add_hasher(lib->crypto, HASH_SHA256, plugin_name, (hasher_constructor_t)openssl_hasher_create); - lib->crypto->add_hasher(lib->crypto, HASH_SHA384, + lib->crypto->add_hasher(lib->crypto, HASH_SHA384, plugin_name, (hasher_constructor_t)openssl_hasher_create); - lib->crypto->add_hasher(lib->crypto, HASH_SHA512, + lib->crypto->add_hasher(lib->crypto, HASH_SHA512, plugin_name, (hasher_constructor_t)openssl_hasher_create); /* prf */ - lib->crypto->add_prf(lib->crypto, PRF_KEYED_SHA1, + lib->crypto->add_prf(lib->crypto, PRF_KEYED_SHA1, plugin_name, (prf_constructor_t)openssl_sha1_prf_create); /* (ec) diffie hellman */ - lib->crypto->add_dh(lib->crypto, MODP_2048_BIT, + lib->crypto->add_dh(lib->crypto, MODP_2048_BIT, plugin_name, (dh_constructor_t)openssl_diffie_hellman_create); - lib->crypto->add_dh(lib->crypto, MODP_2048_224, + lib->crypto->add_dh(lib->crypto, MODP_2048_224, plugin_name, (dh_constructor_t)openssl_diffie_hellman_create); - lib->crypto->add_dh(lib->crypto, MODP_2048_256, + lib->crypto->add_dh(lib->crypto, MODP_2048_256, plugin_name, (dh_constructor_t)openssl_diffie_hellman_create); - lib->crypto->add_dh(lib->crypto, MODP_1536_BIT, + lib->crypto->add_dh(lib->crypto, MODP_1536_BIT, plugin_name, (dh_constructor_t)openssl_diffie_hellman_create); #ifndef OPENSSL_NO_EC - lib->crypto->add_dh(lib->crypto, ECP_256_BIT, + lib->crypto->add_dh(lib->crypto, ECP_256_BIT, plugin_name, (dh_constructor_t)openssl_ec_diffie_hellman_create); - lib->crypto->add_dh(lib->crypto, ECP_384_BIT, + lib->crypto->add_dh(lib->crypto, ECP_384_BIT, plugin_name, (dh_constructor_t)openssl_ec_diffie_hellman_create); - lib->crypto->add_dh(lib->crypto, ECP_521_BIT, + lib->crypto->add_dh(lib->crypto, ECP_521_BIT, plugin_name, (dh_constructor_t)openssl_ec_diffie_hellman_create); - lib->crypto->add_dh(lib->crypto, ECP_224_BIT, + lib->crypto->add_dh(lib->crypto, ECP_224_BIT, plugin_name, (dh_constructor_t)openssl_ec_diffie_hellman_create); - lib->crypto->add_dh(lib->crypto, ECP_192_BIT, + lib->crypto->add_dh(lib->crypto, ECP_192_BIT, plugin_name, (dh_constructor_t)openssl_ec_diffie_hellman_create); #endif /* OPENSSL_NO_EC */ - lib->crypto->add_dh(lib->crypto, MODP_3072_BIT, + lib->crypto->add_dh(lib->crypto, MODP_3072_BIT, plugin_name, (dh_constructor_t)openssl_diffie_hellman_create); - lib->crypto->add_dh(lib->crypto, MODP_4096_BIT, + lib->crypto->add_dh(lib->crypto, MODP_4096_BIT, plugin_name, (dh_constructor_t)openssl_diffie_hellman_create); - lib->crypto->add_dh(lib->crypto, MODP_6144_BIT, + lib->crypto->add_dh(lib->crypto, MODP_6144_BIT, plugin_name, (dh_constructor_t)openssl_diffie_hellman_create); - lib->crypto->add_dh(lib->crypto, MODP_8192_BIT, + lib->crypto->add_dh(lib->crypto, MODP_8192_BIT, plugin_name, (dh_constructor_t)openssl_diffie_hellman_create); - lib->crypto->add_dh(lib->crypto, MODP_1024_BIT, + lib->crypto->add_dh(lib->crypto, MODP_1024_BIT, plugin_name, (dh_constructor_t)openssl_diffie_hellman_create); - lib->crypto->add_dh(lib->crypto, MODP_1024_160, + lib->crypto->add_dh(lib->crypto, MODP_1024_160, plugin_name, (dh_constructor_t)openssl_diffie_hellman_create); - lib->crypto->add_dh(lib->crypto, MODP_768_BIT, + lib->crypto->add_dh(lib->crypto, MODP_768_BIT, plugin_name, (dh_constructor_t)openssl_diffie_hellman_create); - lib->crypto->add_dh(lib->crypto, MODP_CUSTOM, + lib->crypto->add_dh(lib->crypto, MODP_CUSTOM, plugin_name, (dh_constructor_t)openssl_diffie_hellman_create); /* rsa */ diff --git a/src/libstrongswan/plugins/openssl/openssl_x509.c b/src/libstrongswan/plugins/openssl/openssl_x509.c index aa39bc93d..f7495b2ae 100644 --- a/src/libstrongswan/plugins/openssl/openssl_x509.c +++ b/src/libstrongswan/plugins/openssl/openssl_x509.c @@ -84,7 +84,7 @@ struct private_openssl_x509_t { /** * Pathlen constraint */ - int pathlen; + u_char pathlen; /** * certificate subject @@ -137,7 +137,7 @@ struct private_openssl_x509_t { linked_list_t *issuerAltNames; /** - * List of CRL URIs + * List of CRL URIs, as x509_cdp_t */ linked_list_t *crl_uris; @@ -153,6 +153,16 @@ struct private_openssl_x509_t { }; /** + * Destroy a CRL URI struct + */ +static void crl_uri_destroy(x509_cdp_t *this) +{ + free(this->uri); + DESTROY_IF(this->issuer); + free(this); +} + +/** * Convert a GeneralName to an identification_t. */ static identification_t *general_name2id(GENERAL_NAME *name) @@ -240,10 +250,16 @@ METHOD(x509_t, get_authKeyIdentifier, chunk_t, return chunk_empty; } -METHOD(x509_t, get_pathLenConstraint, int, - private_openssl_x509_t *this) +METHOD(x509_t, get_constraint, u_int, + private_openssl_x509_t *this, x509_constraint_t type) { - return this->pathlen; + switch (type) + { + case X509_PATH_LEN: + return this->pathlen; + default: + return X509_NO_CONSTRAINT; + } } METHOD(x509_t, create_subjectAltName_enumerator, enumerator_t*, @@ -264,13 +280,6 @@ METHOD(x509_t, create_ocsp_uri_enumerator, enumerator_t*, return this->ocsp_uris->create_enumerator(this->ocsp_uris); } -METHOD(x509_t, create_ipAddrBlock_enumerator, enumerator_t*, - private_openssl_x509_t *this) -{ - /* TODO */ - return enumerator_create_empty(); -} - METHOD(certificate_t, get_type, certificate_type_t, private_openssl_x509_t *this) { @@ -483,7 +492,7 @@ METHOD(certificate_t, destroy, void, offsetof(identification_t, destroy)); this->issuerAltNames->destroy_offset(this->issuerAltNames, offsetof(identification_t, destroy)); - this->crl_uris->destroy_function(this->crl_uris, free); + this->crl_uris->destroy_function(this->crl_uris, (void*)crl_uri_destroy); this->ocsp_uris->destroy_function(this->ocsp_uris, free); free(this); } @@ -517,18 +526,21 @@ static private_openssl_x509_t *create_empty() .get_serial = _get_serial, .get_subjectKeyIdentifier = _get_subjectKeyIdentifier, .get_authKeyIdentifier = _get_authKeyIdentifier, - .get_pathLenConstraint = _get_pathLenConstraint, + .get_constraint = _get_constraint, .create_subjectAltName_enumerator = _create_subjectAltName_enumerator, .create_crl_uri_enumerator = _create_crl_uri_enumerator, .create_ocsp_uri_enumerator = _create_ocsp_uri_enumerator, - .create_ipAddrBlock_enumerator = _create_ipAddrBlock_enumerator, + .create_ipAddrBlock_enumerator = (void*)enumerator_create_empty, + .create_name_constraint_enumerator = (void*)enumerator_create_empty, + .create_cert_policy_enumerator = (void*)enumerator_create_empty, + .create_policy_mapping_enumerator = (void*)enumerator_create_empty, }, }, .subjectAltNames = linked_list_create(), .issuerAltNames = linked_list_create(), .crl_uris = linked_list_create(), .ocsp_uris = linked_list_create(), - .pathlen = X509_NO_PATH_LEN_CONSTRAINT, + .pathlen = X509_NO_CONSTRAINT, .ref = 1, ); @@ -574,6 +586,7 @@ static bool parse_basicConstraints_ext(private_openssl_x509_t *this, X509_EXTENSION *ext) { BASIC_CONSTRAINTS *constraints; + long pathlen; constraints = (BASIC_CONSTRAINTS*)X509V3_EXT_d2i(ext); if (constraints) @@ -584,7 +597,10 @@ static bool parse_basicConstraints_ext(private_openssl_x509_t *this, } if (constraints->pathlen) { - this->pathlen = ASN1_INTEGER_get(constraints->pathlen); + + pathlen = ASN1_INTEGER_get(constraints->pathlen); + this->pathlen = (pathlen >= 0 && pathlen < 128) ? + pathlen : X509_NO_CONSTRAINT; } BASIC_CONSTRAINTS_free(constraints); return TRUE; @@ -600,9 +616,10 @@ static bool parse_crlDistributionPoints_ext(private_openssl_x509_t *this, { CRL_DIST_POINTS *cdps; DIST_POINT *cdp; - identification_t *id; + identification_t *id, *issuer; + x509_cdp_t *entry; char *uri; - int i, j, point_num, name_num; + int i, j, k, point_num, name_num, issuer_num; cdps = X509V3_EXT_d2i(ext); if (!cdps) @@ -627,12 +644,38 @@ static bool parse_crlDistributionPoints_ext(private_openssl_x509_t *this, { if (asprintf(&uri, "%Y", id) > 0) { - this->crl_uris->insert_first(this->crl_uris, uri); + if (cdp->CRLissuer) + { + issuer_num = sk_GENERAL_NAME_num(cdp->CRLissuer); + for (k = 0; k < issuer_num; k++) + { + issuer = general_name2id( + sk_GENERAL_NAME_value(cdp->CRLissuer, k)); + if (issuer) + { + INIT(entry, + .uri = strdup(uri), + .issuer = issuer, + ); + this->crl_uris->insert_last( + this->crl_uris, entry); + } + } + free(uri); + } + else + { + INIT(entry, + .uri = uri, + ); + this->crl_uris->insert_last(this->crl_uris, entry); + } } id->destroy(id); } } } + DIST_POINT_free(cdp); } } @@ -765,7 +808,13 @@ static bool parse_extensions(private_openssl_x509_t *this) ok = parse_crlDistributionPoints_ext(this, ext); break; default: - ok = TRUE; + ok = X509_EXTENSION_get_critical(ext) == 0 || + !lib->settings->get_bool(lib->settings, + "libstrongswan.x509.enforce_critical", TRUE); + if (!ok) + { + DBG1(DBG_LIB, "found unsupported critical X.509 extension"); + } break; } if (!ok) @@ -823,6 +872,13 @@ static bool parse_certificate(private_openssl_x509_t *this) { return FALSE; } + if (X509_get_version(this->x509) < 0 || X509_get_version(this->x509) > 2) + { + DBG1(DBG_LIB, "unsupported x509 version: %d", + X509_get_version(this->x509) + 1); + return FALSE; + } + this->subject = openssl_x509_name2id(X509_get_subject_name(this->x509)); this->issuer = openssl_x509_name2id(X509_get_issuer_name(this->x509)); @@ -866,7 +922,7 @@ static bool parse_certificate(private_openssl_x509_t *this) if (!parse_extensions(this)) { - return TRUE; + return FALSE; } parse_extKeyUsage(this); diff --git a/src/libstrongswan/plugins/padlock/Makefile.in b/src/libstrongswan/plugins/padlock/Makefile.in index 46953f681..7c89d0abd 100644 --- a/src/libstrongswan/plugins/padlock/Makefile.in +++ b/src/libstrongswan/plugins/padlock/Makefile.in @@ -222,9 +222,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -263,6 +261,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libstrongswan/plugins/padlock/padlock_plugin.c b/src/libstrongswan/plugins/padlock/padlock_plugin.c index 027c53c7b..695823acf 100644 --- a/src/libstrongswan/plugins/padlock/padlock_plugin.c +++ b/src/libstrongswan/plugins/padlock/padlock_plugin.c @@ -23,6 +23,8 @@ #include <library.h> #include <debug.h> +static const char *plugin_name = "padlock"; + typedef struct private_padlock_plugin_t private_padlock_plugin_t; typedef enum padlock_feature_t padlock_feature_t; @@ -161,21 +163,21 @@ plugin_t *padlock_plugin_create() if (this->features & PADLOCK_RNG_ENABLED) { - lib->crypto->add_rng(lib->crypto, RNG_TRUE, + lib->crypto->add_rng(lib->crypto, RNG_TRUE, plugin_name, (rng_constructor_t)padlock_rng_create); - lib->crypto->add_rng(lib->crypto, RNG_STRONG, + lib->crypto->add_rng(lib->crypto, RNG_STRONG, plugin_name, (rng_constructor_t)padlock_rng_create); - lib->crypto->add_rng(lib->crypto, RNG_WEAK, + lib->crypto->add_rng(lib->crypto, RNG_WEAK, plugin_name, (rng_constructor_t)padlock_rng_create); } if (this->features & PADLOCK_ACE2_ENABLED) { - lib->crypto->add_crypter(lib->crypto, ENCR_AES_CBC, + lib->crypto->add_crypter(lib->crypto, ENCR_AES_CBC, plugin_name, (crypter_constructor_t)padlock_aes_crypter_create); } if (this->features & PADLOCK_PHE_ENABLED) { - lib->crypto->add_hasher(lib->crypto, HASH_SHA1, + lib->crypto->add_hasher(lib->crypto, HASH_SHA1, plugin_name, (hasher_constructor_t)padlock_sha1_hasher_create); } return &this->public.plugin; diff --git a/src/libstrongswan/plugins/pem/Makefile.in b/src/libstrongswan/plugins/pem/Makefile.in index cf5acdd1c..60740eb35 100644 --- a/src/libstrongswan/plugins/pem/Makefile.in +++ b/src/libstrongswan/plugins/pem/Makefile.in @@ -220,9 +220,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -261,6 +259,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libstrongswan/plugins/pem/pem_encoder.c b/src/libstrongswan/plugins/pem/pem_encoder.c index e255d6fd0..9c8237e4d 100644 --- a/src/libstrongswan/plugins/pem/pem_encoder.c +++ b/src/libstrongswan/plugins/pem/pem_encoder.c @@ -111,7 +111,7 @@ bool pem_encoder_encode(cred_encoding_type_t type, chunk_t *encoding, } /* compute and allocate maximum size of PEM object */ - pem_chars = 4*(asn1.len + 2)/3; + pem_chars = 4 * ((asn1.len + 2) / 3); pem_lines = (asn1.len + BYTES_PER_LINE - 1) / BYTES_PER_LINE; *encoding = chunk_alloc(5 + 2*(6 + strlen(label) + 6) + 3 + pem_chars + pem_lines); pos = encoding->ptr; diff --git a/src/libstrongswan/plugins/pem/pem_plugin.c b/src/libstrongswan/plugins/pem/pem_plugin.c index 83efb155b..f2415a318 100644 --- a/src/libstrongswan/plugins/pem/pem_plugin.c +++ b/src/libstrongswan/plugins/pem/pem_plugin.c @@ -33,10 +33,8 @@ struct private_pem_plugin_t { pem_plugin_t public; }; -/** - * Implementation of pem_plugin_t.pemtroy - */ -static void destroy(private_pem_plugin_t *this) +METHOD(plugin_t, destroy, void, + private_pem_plugin_t *this) { lib->creds->remove_builder(lib->creds, (builder_function_t)pem_private_key_load); @@ -52,9 +50,15 @@ static void destroy(private_pem_plugin_t *this) */ plugin_t *pem_plugin_create() { - private_pem_plugin_t *this = malloc_thing(private_pem_plugin_t); - - this->public.plugin.destroy = (void(*)(plugin_t*))destroy; + private_pem_plugin_t *this; + + INIT(this, + .public = { + .plugin = { + .destroy = _destroy, + }, + }, + ); /* register private key PEM decoding builders */ lib->creds->add_builder(lib->creds, CRED_PRIVATE_KEY, KEY_ANY, FALSE, diff --git a/src/libstrongswan/plugins/pgp/Makefile.in b/src/libstrongswan/plugins/pgp/Makefile.in index 0098147a9..ab14f8ced 100644 --- a/src/libstrongswan/plugins/pgp/Makefile.in +++ b/src/libstrongswan/plugins/pgp/Makefile.in @@ -220,9 +220,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -261,6 +259,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libstrongswan/plugins/pgp/pgp_plugin.c b/src/libstrongswan/plugins/pgp/pgp_plugin.c index 41e0a5df6..eaf0a1088 100644 --- a/src/libstrongswan/plugins/pgp/pgp_plugin.c +++ b/src/libstrongswan/plugins/pgp/pgp_plugin.c @@ -33,10 +33,8 @@ struct private_pgp_plugin_t { pgp_plugin_t public; }; -/** - * Implementation of pgp_plugin_t.pgptroy - */ -static void destroy(private_pgp_plugin_t *this) +METHOD(plugin_t, destroy, void, + private_pgp_plugin_t *this) { lib->creds->remove_builder(lib->creds, (builder_function_t)pgp_public_key_load); @@ -56,10 +54,15 @@ static void destroy(private_pgp_plugin_t *this) */ plugin_t *pgp_plugin_create() { - private_pgp_plugin_t *this = malloc_thing(private_pgp_plugin_t); - - this->public.plugin.destroy = (void(*)(plugin_t*))destroy; - + private_pgp_plugin_t *this; + + INIT(this, + .public = { + .plugin = { + .destroy = _destroy, + }, + }, + ); lib->creds->add_builder(lib->creds, CRED_PUBLIC_KEY, KEY_ANY, FALSE, (builder_function_t)pgp_public_key_load); lib->creds->add_builder(lib->creds, CRED_PUBLIC_KEY, KEY_RSA, FALSE, @@ -68,10 +71,8 @@ plugin_t *pgp_plugin_create() (builder_function_t)pgp_private_key_load); lib->creds->add_builder(lib->creds, CRED_PRIVATE_KEY, KEY_RSA, FALSE, (builder_function_t)pgp_private_key_load); - lib->creds->add_builder(lib->creds, CRED_CERTIFICATE, CERT_GPG, FALSE, (builder_function_t)pgp_cert_load); - lib->encoding->add_encoder(lib->encoding, pgp_encoder_encode); return &this->public.plugin; diff --git a/src/libstrongswan/plugins/pkcs1/Makefile.in b/src/libstrongswan/plugins/pkcs1/Makefile.in index 8b41499a7..8ed4a08e9 100644 --- a/src/libstrongswan/plugins/pkcs1/Makefile.in +++ b/src/libstrongswan/plugins/pkcs1/Makefile.in @@ -221,9 +221,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -262,6 +260,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libstrongswan/plugins/pkcs1/pkcs1_plugin.c b/src/libstrongswan/plugins/pkcs1/pkcs1_plugin.c index d3afb5c67..33732f8a4 100644 --- a/src/libstrongswan/plugins/pkcs1/pkcs1_plugin.c +++ b/src/libstrongswan/plugins/pkcs1/pkcs1_plugin.c @@ -32,10 +32,8 @@ struct private_pkcs1_plugin_t { pkcs1_plugin_t public; }; -/** - * Implementation of pkcs1_plugin_t.pkcs1troy - */ -static void destroy(private_pkcs1_plugin_t *this) +METHOD(plugin_t, destroy, void, + private_pkcs1_plugin_t *this) { lib->creds->remove_builder(lib->creds, (builder_function_t)pkcs1_public_key_load); @@ -52,9 +50,15 @@ static void destroy(private_pkcs1_plugin_t *this) */ plugin_t *pkcs1_plugin_create() { - private_pkcs1_plugin_t *this = malloc_thing(private_pkcs1_plugin_t); + private_pkcs1_plugin_t *this; - this->public.plugin.destroy = (void(*)(plugin_t*))destroy; + INIT(this, + .public = { + .plugin = { + .destroy = _destroy, + }, + }, + ); lib->creds->add_builder(lib->creds, CRED_PUBLIC_KEY, KEY_ANY, FALSE, (builder_function_t)pkcs1_public_key_load); diff --git a/src/libstrongswan/plugins/pkcs11/Makefile.in b/src/libstrongswan/plugins/pkcs11/Makefile.in index c27310910..6c03b0497 100644 --- a/src/libstrongswan/plugins/pkcs11/Makefile.in +++ b/src/libstrongswan/plugins/pkcs11/Makefile.in @@ -223,9 +223,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -264,6 +262,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libstrongswan/plugins/pkcs11/pkcs11_creds.c b/src/libstrongswan/plugins/pkcs11/pkcs11_creds.c index 1b1448c6a..a81ec1147 100644 --- a/src/libstrongswan/plugins/pkcs11/pkcs11_creds.c +++ b/src/libstrongswan/plugins/pkcs11/pkcs11_creds.c @@ -55,19 +55,20 @@ struct private_pkcs11_creds_t { * Find certificates, optionally trusted */ static void find_certificates(private_pkcs11_creds_t *this, - CK_SESSION_HANDLE session, CK_BBOOL trusted) + CK_SESSION_HANDLE session) { CK_OBJECT_CLASS class = CKO_CERTIFICATE; CK_CERTIFICATE_TYPE type = CKC_X_509; + CK_BBOOL trusted = TRUE; CK_ATTRIBUTE tmpl[] = { {CKA_CLASS, &class, sizeof(class)}, {CKA_CERTIFICATE_TYPE, &type, sizeof(type)}, - {CKA_TRUSTED, &trusted, sizeof(trusted)}, }; CK_OBJECT_HANDLE object; CK_ATTRIBUTE attr[] = { {CKA_VALUE, NULL, 0}, {CKA_LABEL, NULL, 0}, + {CKA_TRUSTED, &trusted, sizeof(trusted)} }; enumerator_t *enumerator; linked_list_t *raw; @@ -75,11 +76,19 @@ static void find_certificates(private_pkcs11_creds_t *this, struct { chunk_t value; chunk_t label; + bool trusted; } *entry; + int count = countof(attr); + /* store result in a temporary list, avoid recursive operation */ raw = linked_list_create(); + /* do not use trusted argument if not supported */ + if (!(this->lib->get_features(this->lib) & PKCS11_TRUSTED_CERTS)) + { + count--; + } enumerator = this->lib->create_object_enumerator(this->lib, - session, tmpl, countof(tmpl), attr, countof(attr)); + session, tmpl, countof(tmpl), attr, count); while (enumerator->enumerate(enumerator, &object)) { entry = malloc(sizeof(*entry)); @@ -87,6 +96,7 @@ static void find_certificates(private_pkcs11_creds_t *this, chunk_create(attr[0].pValue, attr[0].ulValueLen)); entry->label = chunk_clone( chunk_create(attr[1].pValue, attr[1].ulValueLen)); + entry->trusted = trusted; raw->insert_last(raw, entry); } enumerator->destroy(enumerator); @@ -99,10 +109,10 @@ static void find_certificates(private_pkcs11_creds_t *this, if (cert) { DBG1(DBG_CFG, " loaded %strusted cert '%.*s'", - trusted ? "" : "un", entry->label.len, entry->label.ptr); + entry->trusted ? "" : "un", entry->label.len, entry->label.ptr); /* trusted certificates are also returned as untrusted */ this->untrusted->insert_last(this->untrusted, cert); - if (trusted) + if (entry->trusted) { this->trusted->insert_last(this->trusted, cert->get_ref(cert)); } @@ -135,8 +145,7 @@ static bool load_certificates(private_pkcs11_creds_t *this) return FALSE; } - find_certificates(this, session, CK_TRUE); - find_certificates(this, session, CK_FALSE); + find_certificates(this, session); this->lib->f->C_CloseSession(session); return TRUE; diff --git a/src/libstrongswan/plugins/pkcs11/pkcs11_library.c b/src/libstrongswan/plugins/pkcs11/pkcs11_library.c index 9fb1b7769..6f7926808 100644 --- a/src/libstrongswan/plugins/pkcs11/pkcs11_library.c +++ b/src/libstrongswan/plugins/pkcs11/pkcs11_library.c @@ -466,6 +466,11 @@ struct private_pkcs11_library_t { * Name as passed to the constructor */ char *name; + + /** + * Supported feature set + */ + pkcs11_feature_t features; }; METHOD(pkcs11_library_t, get_name, char*, @@ -474,6 +479,12 @@ METHOD(pkcs11_library_t, get_name, char*, return this->name; } +METHOD(pkcs11_library_t, get_features, pkcs11_feature_t, + private_pkcs11_library_t *this) +{ + return this->features; +} + /** * Object enumerator */ @@ -766,19 +777,45 @@ static CK_RV UnlockMutex(CK_VOID_PTR data) } /** + * Check if the library has at least a given cryptoki version + */ +static bool has_version(CK_INFO *info, int major, int minor) +{ + return info->cryptokiVersion.major > major || + (info->cryptokiVersion.major == major && + info->cryptokiVersion.minor >= minor); +} + +/** + * Check for optional PKCS#11 library functionality + */ +static void check_features(private_pkcs11_library_t *this, CK_INFO *info) +{ + if (has_version(info, 2, 20)) + { + this->features |= PKCS11_TRUSTED_CERTS; + this->features |= PKCS11_ALWAYS_AUTH_KEYS; + } +} + +/** * Initialize a PKCS#11 library */ -static bool initialize(private_pkcs11_library_t *this, char *name, char *file) +static bool initialize(private_pkcs11_library_t *this, char *name, char *file, + bool os_locking) { CK_C_GetFunctionList pC_GetFunctionList; CK_INFO info; CK_RV rv; - CK_C_INITIALIZE_ARGS args = { + static CK_C_INITIALIZE_ARGS args = { .CreateMutex = CreateMutex, .DestroyMutex = DestroyMutex, .LockMutex = LockMutex, .UnlockMutex = UnlockMutex, }; + static CK_C_INITIALIZE_ARGS args_os = { + .flags = CKF_OS_LOCKING_OK, + }; pC_GetFunctionList = dlsym(this->handle, "C_GetFunctionList"); if (!pC_GetFunctionList) @@ -793,14 +830,19 @@ static bool initialize(private_pkcs11_library_t *this, char *name, char *file) name, ck_rv_names, rv); return FALSE; } - - rv = this->public.f->C_Initialize(&args); - if (rv == CKR_CANT_LOCK) - { /* try OS locking */ - memset(&args, 0, sizeof(args)); - args.flags = CKF_OS_LOCKING_OK; + if (os_locking) + { + rv = CKR_CANT_LOCK; + } + else + { rv = this->public.f->C_Initialize(&args); } + if (rv == CKR_CANT_LOCK) + { /* fallback to OS locking */ + os_locking = TRUE; + rv = this->public.f->C_Initialize(&args_os); + } if (rv != CKR_OK) { DBG1(DBG_CFG, "C_Initialize() error for '%s': %N", @@ -826,23 +868,26 @@ static bool initialize(private_pkcs11_library_t *this, char *name, char *file) DBG1(DBG_CFG, " %s: %s v%d.%d", info.manufacturerID, info.libraryDescription, info.libraryVersion.major, info.libraryVersion.minor); - if (args.flags & CKF_OS_LOCKING_OK) + if (os_locking) { DBG1(DBG_CFG, " uses OS locking functions"); } + + check_features(this, &info); return TRUE; } /** * See header */ -pkcs11_library_t *pkcs11_library_create(char *name, char *file) +pkcs11_library_t *pkcs11_library_create(char *name, char *file, bool os_locking) { private_pkcs11_library_t *this; INIT(this, .public = { .get_name = _get_name, + .get_features = _get_features, .create_object_enumerator = _create_object_enumerator, .create_mechanism_enumerator = _create_mechanism_enumerator, .destroy = _destroy, @@ -858,7 +903,7 @@ pkcs11_library_t *pkcs11_library_create(char *name, char *file) return NULL; } - if (!initialize(this, name, file)) + if (!initialize(this, name, file, os_locking)) { dlclose(this->handle); free(this); diff --git a/src/libstrongswan/plugins/pkcs11/pkcs11_library.h b/src/libstrongswan/plugins/pkcs11/pkcs11_library.h index 1457d24d4..abe023448 100644 --- a/src/libstrongswan/plugins/pkcs11/pkcs11_library.h +++ b/src/libstrongswan/plugins/pkcs11/pkcs11_library.h @@ -21,6 +21,7 @@ #ifndef PKCS11_LIBRARY_H_ #define PKCS11_LIBRARY_H_ +typedef enum pkcs11_feature_t pkcs11_feature_t; typedef struct pkcs11_library_t pkcs11_library_t; #include "pkcs11.h" @@ -29,6 +30,16 @@ typedef struct pkcs11_library_t pkcs11_library_t; #include <utils/enumerator.h> /** + * Optional PKCS#11 features some libraries support, some not + */ +enum pkcs11_feature_t { + /** CKA_TRUSTED attribute supported for certificate objects */ + PKCS11_TRUSTED_CERTS = (1<<0), + /** CKA_ALWAYS_AUTHENTICATE attribute supported for private keys */ + PKCS11_ALWAYS_AUTH_KEYS = (1<<1), +}; + +/** * A loaded and initialized PKCS#11 library. */ struct pkcs11_library_t { @@ -46,6 +57,13 @@ struct pkcs11_library_t { char* (*get_name)(pkcs11_library_t *this); /** + * Get the feature set supported by this library. + * + * @return ORed set of features supported + */ + pkcs11_feature_t (*get_features)(pkcs11_library_t *this); + + /** * Create an enumerator over CK_OBJECT_HANDLE using a search template. * * An optional attribute array is automatically filled in with the @@ -103,8 +121,9 @@ void pkcs11_library_trim(char *str, int len); * * @param name an arbitrary name, for debugging * @param file pkcs11 library file to dlopen() + * @param os_lock enforce OS Locking for this library * @return library abstraction */ -pkcs11_library_t *pkcs11_library_create(char *name, char *file); +pkcs11_library_t *pkcs11_library_create(char *name, char *file, bool os_lock); #endif /** PKCS11_LIBRARY_H_ @}*/ diff --git a/src/libstrongswan/plugins/pkcs11/pkcs11_manager.c b/src/libstrongswan/plugins/pkcs11/pkcs11_manager.c index 0c27600a6..9308e9c25 100644 --- a/src/libstrongswan/plugins/pkcs11/pkcs11_manager.c +++ b/src/libstrongswan/plugins/pkcs11/pkcs11_manager.c @@ -373,7 +373,10 @@ pkcs11_manager_t *pkcs11_manager_create(pkcs11_manager_token_event_t cb, free(entry); continue; } - entry->lib = pkcs11_library_create(module, entry->path); + entry->lib = pkcs11_library_create(module, entry->path, + lib->settings->get_bool(lib->settings, + "libstrongswan.plugins.pkcs11.modules.%s.os_locking", + FALSE, module)); if (!entry->lib) { free(entry); diff --git a/src/libstrongswan/plugins/pkcs11/pkcs11_plugin.c b/src/libstrongswan/plugins/pkcs11/pkcs11_plugin.c index ace405c23..071d2f782 100644 --- a/src/libstrongswan/plugins/pkcs11/pkcs11_plugin.c +++ b/src/libstrongswan/plugins/pkcs11/pkcs11_plugin.c @@ -26,6 +26,8 @@ #include "pkcs11_public_key.h" #include "pkcs11_hasher.h" +static const char *plugin_name = "pkcs11"; + typedef struct private_pkcs11_plugin_t private_pkcs11_plugin_t; /** @@ -146,17 +148,17 @@ plugin_t *pkcs11_plugin_create() if (lib->settings->get_bool(lib->settings, "libstrongswan.plugins.pkcs11.use_hasher", FALSE)) { - lib->crypto->add_hasher(lib->crypto, HASH_MD2, + lib->crypto->add_hasher(lib->crypto, HASH_MD2, plugin_name, (hasher_constructor_t)pkcs11_hasher_create); - lib->crypto->add_hasher(lib->crypto, HASH_MD5, + lib->crypto->add_hasher(lib->crypto, HASH_MD5, plugin_name, (hasher_constructor_t)pkcs11_hasher_create); - lib->crypto->add_hasher(lib->crypto, HASH_SHA1, + lib->crypto->add_hasher(lib->crypto, HASH_SHA1, plugin_name, (hasher_constructor_t)pkcs11_hasher_create); - lib->crypto->add_hasher(lib->crypto, HASH_SHA256, + lib->crypto->add_hasher(lib->crypto, HASH_SHA256, plugin_name, (hasher_constructor_t)pkcs11_hasher_create); - lib->crypto->add_hasher(lib->crypto, HASH_SHA384, + lib->crypto->add_hasher(lib->crypto, HASH_SHA384, plugin_name, (hasher_constructor_t)pkcs11_hasher_create); - lib->crypto->add_hasher(lib->crypto, HASH_SHA512, + lib->crypto->add_hasher(lib->crypto, HASH_SHA512, plugin_name, (hasher_constructor_t)pkcs11_hasher_create); } diff --git a/src/libstrongswan/plugins/pkcs11/pkcs11_private_key.c b/src/libstrongswan/plugins/pkcs11/pkcs11_private_key.c index cabca3f54..b4cc7a805 100644 --- a/src/libstrongswan/plugins/pkcs11/pkcs11_private_key.c +++ b/src/libstrongswan/plugins/pkcs11/pkcs11_private_key.c @@ -401,30 +401,36 @@ static bool find_key(private_pkcs11_private_key_t *this, chunk_t keyid) }; CK_OBJECT_HANDLE object; CK_KEY_TYPE type; - CK_BBOOL reauth; + CK_BBOOL reauth = FALSE; CK_ATTRIBUTE attr[] = { {CKA_KEY_TYPE, &type, sizeof(type)}, - {CKA_ALWAYS_AUTHENTICATE, &reauth, sizeof(reauth)}, {CKA_MODULUS, NULL, 0}, {CKA_PUBLIC_EXPONENT, NULL, 0}, + {CKA_ALWAYS_AUTHENTICATE, &reauth, sizeof(reauth)}, }; enumerator_t *enumerator; chunk_t modulus, pubexp; + int count = countof(attr); + /* do not use CKA_ALWAYS_AUTHENTICATE if not supported */ + if (!(this->lib->get_features(this->lib) & PKCS11_ALWAYS_AUTH_KEYS)) + { + count--; + } enumerator = this->lib->create_object_enumerator(this->lib, - this->session, tmpl, countof(tmpl), attr, countof(attr)); + this->session, tmpl, countof(tmpl), attr, count); if (enumerator->enumerate(enumerator, &object)) { switch (type) { case CKK_RSA: - if (attr[2].ulValueLen == -1 || attr[3].ulValueLen == -1) + if (attr[1].ulValueLen == -1 || attr[2].ulValueLen == -1) { DBG1(DBG_CFG, "reading modulus/exponent from PKCS#1 failed"); break; } - modulus = chunk_create(attr[2].pValue, attr[2].ulValueLen); - pubexp = chunk_create(attr[3].pValue, attr[3].ulValueLen); + modulus = chunk_create(attr[1].pValue, attr[1].ulValueLen); + pubexp = chunk_create(attr[2].pValue, attr[2].ulValueLen); this->pubkey = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA, BUILD_RSA_MODULUS, modulus, BUILD_RSA_PUB_EXP, pubexp, BUILD_END); diff --git a/src/libstrongswan/plugins/plugin_loader.c b/src/libstrongswan/plugins/plugin_loader.c index e1427bf15..473db5ccf 100644 --- a/src/libstrongswan/plugins/plugin_loader.c +++ b/src/libstrongswan/plugins/plugin_loader.c @@ -50,62 +50,77 @@ struct private_plugin_loader_t { linked_list_t *names; }; -#ifdef MONOLITHIC /** - * load a single plugin in monolithic mode + * create a plugin + * returns: NOT_FOUND, if the constructor was not found + * FAILED, if the plugin could not be constructed */ -static plugin_t* load_plugin(private_plugin_loader_t *this, - char *path, char *name) +static status_t create_plugin(private_plugin_loader_t *this, void *handle, + char *name, bool integrity, plugin_t **plugin) { char create[128]; - plugin_t *plugin; plugin_constructor_t constructor; if (snprintf(create, sizeof(create), "%s_plugin_create", name) >= sizeof(create)) { - return NULL; + return FAILED; } translate(create, "-", "_"); - constructor = dlsym(RTLD_DEFAULT, create); + constructor = dlsym(handle, create); if (constructor == NULL) { - DBG1(DBG_LIB, "plugin '%s': failed to load - %s not found", name, + DBG2(DBG_LIB, "plugin '%s': failed to load - %s not found", name, create); - return NULL; + return NOT_FOUND; } - plugin = constructor(); - if (plugin == NULL) + if (integrity && lib->integrity) + { + if (!lib->integrity->check_segment(lib->integrity, name, constructor)) + { + DBG1(DBG_LIB, "plugin '%s': failed segment integrity test", name); + return FAILED; + } + DBG1(DBG_LIB, "plugin '%s': passed file and segment integrity tests", + name); + } + *plugin = constructor(); + if (*plugin == NULL) { DBG1(DBG_LIB, "plugin '%s': failed to load - %s returned NULL", name, create); - return NULL; + return FAILED; } DBG2(DBG_LIB, "plugin '%s': loaded successfully", name); - - return plugin; + return SUCCESS; } -#else + /** * load a single plugin */ static plugin_t* load_plugin(private_plugin_loader_t *this, char *path, char *name) { - char create[128]; char file[PATH_MAX]; void *handle; plugin_t *plugin; - plugin_constructor_t constructor; + + switch (create_plugin(this, RTLD_DEFAULT, name, FALSE, &plugin)) + { + case SUCCESS: + return plugin; + case NOT_FOUND: + /* try to load the plugin from a file */ + break; + default: + return NULL; + } if (snprintf(file, sizeof(file), "%s/libstrongswan-%s.so", path, - name) >= sizeof(file) || - snprintf(create, sizeof(create), "%s_plugin_create", - name) >= sizeof(create)) + name) >= sizeof(file)) { return NULL; } - translate(create, "-", "_"); if (lib->integrity) { if (!lib->integrity->check_file(lib->integrity, name, file)) @@ -121,40 +136,37 @@ static plugin_t* load_plugin(private_plugin_loader_t *this, DBG1(DBG_LIB, "plugin '%s' failed to load: %s", name, dlerror()); return NULL; } - constructor = dlsym(handle, create); - if (constructor == NULL) + if (create_plugin(this, handle, name, TRUE, &plugin) != SUCCESS) { - DBG1(DBG_LIB, "plugin '%s': failed to load - %s not found", name, - create); dlclose(handle); return NULL; } - if (lib->integrity) + /* we do not store or free dlopen() handles, leak_detective requires + * the modules to keep loaded until leak report */ + return plugin; +} + +/** + * Check if a plugin is already loaded + */ +static bool plugin_loaded(private_plugin_loader_t *this, char *name) +{ + enumerator_t *enumerator; + bool found = FALSE; + char *current; + + enumerator = this->names->create_enumerator(this->names); + while (enumerator->enumerate(enumerator, ¤t)) { - if (!lib->integrity->check_segment(lib->integrity, name, constructor)) + if (streq(name, current)) { - DBG1(DBG_LIB, "plugin '%s': failed segment integrity test", name); - dlclose(handle); - return NULL; + found = TRUE; + break; } - DBG1(DBG_LIB, "plugin '%s': passed file and segment integrity tests", - name); } - plugin = constructor(); - if (plugin == NULL) - { - DBG1(DBG_LIB, "plugin '%s': failed to load - %s returned NULL", name, - create); - dlclose(handle); - return NULL; - } - DBG2(DBG_LIB, "plugin '%s': loaded successfully", name); - - /* we do not store or free dlopen() handles, leak_detective requires - * the modules to keep loaded until leak report */ - return plugin; + enumerator->destroy(enumerator); + return found; } -#endif /** * Implementation of plugin_loader_t.load_plugins. @@ -165,12 +177,10 @@ static bool load(private_plugin_loader_t *this, char *path, char *list) char *token; bool critical_failed = FALSE; -#ifndef MONOLITHIC if (path == NULL) { path = PLUGINDIR; } -#endif enumerator = enumerator_create_token(list, " ", " "); while (!critical_failed && enumerator->enumerate(enumerator, &token)) @@ -186,6 +196,11 @@ static bool load(private_plugin_loader_t *this, char *path, char *list) critical = TRUE; token[len-1] = '\0'; } + if (plugin_loaded(this, token)) + { + free(token); + continue; + } plugin = load_plugin(this, path, token); if (plugin) { diff --git a/src/libstrongswan/plugins/pubkey/Makefile.in b/src/libstrongswan/plugins/pubkey/Makefile.in index 495223855..46349f9ba 100644 --- a/src/libstrongswan/plugins/pubkey/Makefile.in +++ b/src/libstrongswan/plugins/pubkey/Makefile.in @@ -221,9 +221,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -262,6 +260,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libstrongswan/plugins/pubkey/pubkey_plugin.c b/src/libstrongswan/plugins/pubkey/pubkey_plugin.c index 6f41ada2a..cc12217a4 100644 --- a/src/libstrongswan/plugins/pubkey/pubkey_plugin.c +++ b/src/libstrongswan/plugins/pubkey/pubkey_plugin.c @@ -31,10 +31,8 @@ struct private_pubkey_plugin_t { pubkey_plugin_t public; }; -/** - * Implementation of pubkey_plugin_t.pubkeytroy - */ -static void destroy(private_pubkey_plugin_t *this) +METHOD(plugin_t, destroy, void, + private_pubkey_plugin_t *this) { lib->creds->remove_builder(lib->creds, (builder_function_t)pubkey_cert_wrap); @@ -46,9 +44,15 @@ static void destroy(private_pubkey_plugin_t *this) */ plugin_t *pubkey_plugin_create() { - private_pubkey_plugin_t *this = malloc_thing(private_pubkey_plugin_t); - - this->public.plugin.destroy = (void(*)(plugin_t*))destroy; + private_pubkey_plugin_t *this; + + INIT(this, + .public = { + .plugin = { + .destroy = _destroy, + }, + }, + ); lib->creds->add_builder(lib->creds, CRED_CERTIFICATE, CERT_TRUSTED_PUBKEY, FALSE, (builder_function_t)pubkey_cert_wrap); diff --git a/src/libstrongswan/plugins/random/Makefile.in b/src/libstrongswan/plugins/random/Makefile.in index efd24c761..21f8aff11 100644 --- a/src/libstrongswan/plugins/random/Makefile.in +++ b/src/libstrongswan/plugins/random/Makefile.in @@ -221,9 +221,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -262,6 +260,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libstrongswan/plugins/random/random_plugin.c b/src/libstrongswan/plugins/random/random_plugin.c index 39678ba71..cc5cb0a3c 100644 --- a/src/libstrongswan/plugins/random/random_plugin.c +++ b/src/libstrongswan/plugins/random/random_plugin.c @@ -18,6 +18,8 @@ #include <library.h> #include "random_rng.h" +static const char *plugin_name = "random"; + typedef struct private_random_plugin_t private_random_plugin_t; /** @@ -31,10 +33,8 @@ struct private_random_plugin_t { random_plugin_t public; }; -/** - * Implementation of random_plugin_t.gmptroy - */ -static void destroy(private_random_plugin_t *this) +METHOD(plugin_t, destroy, void, + private_random_plugin_t *this) { lib->crypto->remove_rng(lib->crypto, (rng_constructor_t)random_rng_create); @@ -46,13 +46,19 @@ static void destroy(private_random_plugin_t *this) */ plugin_t *random_plugin_create() { - private_random_plugin_t *this = malloc_thing(private_random_plugin_t); + private_random_plugin_t *this; - this->public.plugin.destroy = (void(*)(plugin_t*))destroy; + INIT(this, + .public = { + .plugin = { + .destroy = _destroy, + }, + }, + ); - lib->crypto->add_rng(lib->crypto, RNG_STRONG, + lib->crypto->add_rng(lib->crypto, RNG_STRONG, plugin_name, (rng_constructor_t)random_rng_create); - lib->crypto->add_rng(lib->crypto, RNG_TRUE, + lib->crypto->add_rng(lib->crypto, RNG_TRUE, plugin_name, (rng_constructor_t)random_rng_create); return &this->public.plugin; diff --git a/src/libstrongswan/plugins/random/random_rng.c b/src/libstrongswan/plugins/random/random_rng.c index b09f3f57a..1d99a63d5 100644 --- a/src/libstrongswan/plugins/random/random_rng.c +++ b/src/libstrongswan/plugins/random/random_rng.c @@ -55,11 +55,8 @@ struct private_random_rng_t { char *file; }; -/** - * Implementation of random_rng_t.get_bytes. - */ -static void get_bytes(private_random_rng_t *this, size_t bytes, - u_int8_t *buffer) +METHOD(rng_t, get_bytes, void, + private_random_rng_t *this, size_t bytes, u_int8_t *buffer) { size_t done; ssize_t got; @@ -81,20 +78,15 @@ static void get_bytes(private_random_rng_t *this, size_t bytes, } } -/** - * Implementation of random_rng_t.allocate_bytes. - */ -static void allocate_bytes(private_random_rng_t *this, size_t bytes, - chunk_t *chunk) +METHOD(rng_t, allocate_bytes, void, + private_random_rng_t *this, size_t bytes, chunk_t *chunk) { *chunk = chunk_alloc(bytes); get_bytes(this, chunk->len, chunk->ptr); } -/** - * Implementation of random_rng_t.destroy. - */ -static void destroy(private_random_rng_t *this) +METHOD(rng_t, destroy, void, + private_random_rng_t *this) { close(this->dev); free(this); @@ -105,12 +97,17 @@ static void destroy(private_random_rng_t *this) */ random_rng_t *random_rng_create(rng_quality_t quality) { - private_random_rng_t *this = malloc_thing(private_random_rng_t); - - /* public functions */ - this->public.rng.get_bytes = (void (*) (rng_t *, size_t, u_int8_t*)) get_bytes; - this->public.rng.allocate_bytes = (void (*) (rng_t *, size_t, chunk_t*)) allocate_bytes; - this->public.rng.destroy = (void (*) (rng_t *))destroy; + private_random_rng_t *this; + + INIT(this, + .public = { + .rng = { + .get_bytes = _get_bytes, + .allocate_bytes = _allocate_bytes, + .destroy = _destroy, + }, + }, + ); if (quality == RNG_TRUE) { diff --git a/src/libstrongswan/plugins/revocation/Makefile.in b/src/libstrongswan/plugins/revocation/Makefile.in index 16a9d21c5..4ed4b9694 100644 --- a/src/libstrongswan/plugins/revocation/Makefile.in +++ b/src/libstrongswan/plugins/revocation/Makefile.in @@ -223,9 +223,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -264,6 +262,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libstrongswan/plugins/revocation/revocation_validator.c b/src/libstrongswan/plugins/revocation/revocation_validator.c index 29d2bc128..def169275 100644 --- a/src/libstrongswan/plugins/revocation/revocation_validator.c +++ b/src/libstrongswan/plugins/revocation/revocation_validator.c @@ -93,12 +93,13 @@ static certificate_t *fetch_ocsp(char *url, certificate_t *subject, /** * check the signature of an OCSP response */ -static bool verify_ocsp(ocsp_response_t *response) +static bool verify_ocsp(ocsp_response_t *response, auth_cfg_t *auth) { certificate_t *issuer, *subject; identification_t *responder; ocsp_response_wrapper_t *wrapper; enumerator_t *enumerator; + auth_cfg_t *current; bool verified = FALSE; wrapper = ocsp_response_wrapper_create((ocsp_response_t*)response); @@ -108,12 +109,16 @@ static bool verify_ocsp(ocsp_response_t *response) responder = subject->get_issuer(subject); enumerator = lib->credmgr->create_trusted_enumerator(lib->credmgr, KEY_ANY, responder, FALSE); - while (enumerator->enumerate(enumerator, &issuer, NULL)) + while (enumerator->enumerate(enumerator, &issuer, ¤t)) { if (lib->credmgr->issued_by(lib->credmgr, subject, issuer)) { DBG1(DBG_CFG, " ocsp response correctly signed by \"%Y\"", issuer->get_subject(issuer)); + if (auth) + { + auth->merge(auth, current, FALSE); + } verified = TRUE; break; } @@ -129,7 +134,8 @@ static bool verify_ocsp(ocsp_response_t *response) * Get the better of two OCSP responses, and check for usable OCSP info */ static certificate_t *get_better_ocsp(certificate_t *cand, certificate_t *best, - x509_t *subject, x509_t *issuer, cert_validation_t *valid, bool cache) + x509_t *subject, x509_t *issuer, cert_validation_t *valid, + auth_cfg_t *auth, bool cache) { ocsp_response_t *response; time_t revocation, this_update, next_update, valid_until; @@ -139,7 +145,7 @@ static certificate_t *get_better_ocsp(certificate_t *cand, certificate_t *best, response = (ocsp_response_t*)cand; /* check ocsp signature */ - if (!verify_ocsp(response)) + if (!verify_ocsp(response, auth)) { DBG1(DBG_CFG, "ocsp response verification failed"); cand->destroy(cand); @@ -220,7 +226,8 @@ static cert_validation_t check_ocsp(x509_t *subject, x509_t *issuer, while (enumerator->enumerate(enumerator, ¤t)) { current->get_ref(current); - best = get_better_ocsp(current, best, subject, issuer, &valid, FALSE); + best = get_better_ocsp(current, best, subject, issuer, + &valid, auth, FALSE); if (best && valid != VALIDATION_STALE) { DBG1(DBG_CFG, " using cached ocsp response"); @@ -247,7 +254,7 @@ static cert_validation_t check_ocsp(x509_t *subject, x509_t *issuer, if (current) { best = get_better_ocsp(current, best, subject, issuer, - &valid, TRUE); + &valid, auth, TRUE); if (best && valid != VALIDATION_STALE) { break; @@ -269,7 +276,7 @@ static cert_validation_t check_ocsp(x509_t *subject, x509_t *issuer, if (current) { best = get_better_ocsp(current, best, subject, issuer, - &valid, TRUE); + &valid, auth, TRUE); if (best && valid != VALIDATION_STALE) { break; @@ -323,20 +330,25 @@ static certificate_t* fetch_crl(char *url) /** * check the signature of an CRL */ -static bool verify_crl(certificate_t *crl) +static bool verify_crl(certificate_t *crl, auth_cfg_t *auth) { certificate_t *issuer; enumerator_t *enumerator; bool verified = FALSE; + auth_cfg_t *current; enumerator = lib->credmgr->create_trusted_enumerator(lib->credmgr, KEY_ANY, crl->get_issuer(crl), FALSE); - while (enumerator->enumerate(enumerator, &issuer, NULL)) + while (enumerator->enumerate(enumerator, &issuer, ¤t)) { if (lib->credmgr->issued_by(lib->credmgr, crl, issuer)) { DBG1(DBG_CFG, " crl correctly signed by \"%Y\"", issuer->get_subject(issuer)); + if (auth) + { + auth->merge(auth, current, FALSE); + } verified = TRUE; break; } @@ -350,23 +362,41 @@ static bool verify_crl(certificate_t *crl) * Get the better of two CRLs, and check for usable CRL info */ static certificate_t *get_better_crl(certificate_t *cand, certificate_t *best, - x509_t *subject, x509_t *issuer, cert_validation_t *valid, bool cache) + x509_t *subject, cert_validation_t *valid, auth_cfg_t *auth, + bool cache, crl_t *base) { enumerator_t *enumerator; time_t revocation, valid_until; crl_reason_t reason; chunk_t serial; - crl_t *crl; + crl_t *crl = (crl_t*)cand; + + if (base) + { + if (!crl->is_delta_crl(crl, &serial) || + !chunk_equals(serial, base->get_serial(base))) + { + cand->destroy(cand); + return best; + } + } + else + { + if (crl->is_delta_crl(crl, NULL)) + { + cand->destroy(cand); + return best; + } + } /* check CRL signature */ - if (!verify_crl(cand)) + if (!verify_crl(cand, auth)) { DBG1(DBG_CFG, "crl response verification failed"); cand->destroy(cand); return best; } - crl = (crl_t*)cand; enumerator = crl->create_enumerator(crl); while (enumerator->enumerate(enumerator, &serial, &revocation, &reason)) { @@ -411,79 +441,191 @@ static certificate_t *get_better_crl(certificate_t *cand, certificate_t *best, } /** - * validate a x509 certificate using CRL + * Find or fetch a certificate for a given crlIssuer */ -static cert_validation_t check_crl(x509_t *subject, x509_t *issuer, - auth_cfg_t *auth) +static cert_validation_t find_crl(x509_t *subject, identification_t *issuer, + auth_cfg_t *auth, crl_t *base, + certificate_t **best, bool *uri_found) { cert_validation_t valid = VALIDATION_SKIPPED; - identification_t *keyid = NULL; - certificate_t *best = NULL; + enumerator_t *enumerator; certificate_t *current; - public_key_t *public; + char *uri; + + /* find a cached (delta) crl */ + enumerator = lib->credmgr->create_cert_enumerator(lib->credmgr, + CERT_X509_CRL, KEY_ANY, issuer, FALSE); + while (enumerator->enumerate(enumerator, ¤t)) + { + current->get_ref(current); + *best = get_better_crl(current, *best, subject, &valid, + auth, FALSE, base); + if (*best && valid != VALIDATION_STALE) + { + DBG1(DBG_CFG, " using cached crl"); + break; + } + } + enumerator->destroy(enumerator); + + /* fallback to fetching crls from credential sets cdps */ + if (!base && valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED) + { + enumerator = lib->credmgr->create_cdp_enumerator(lib->credmgr, + CERT_X509_CRL, issuer); + while (enumerator->enumerate(enumerator, &uri)) + { + *uri_found = TRUE; + current = fetch_crl(uri); + if (current) + { + if (!current->has_issuer(current, issuer)) + { + DBG1(DBG_CFG, "issuer of fetched CRL '%Y' does not match CRL " + "issuer '%Y'", current->get_issuer(current), issuer); + current->destroy(current); + continue; + } + *best = get_better_crl(current, *best, subject, + &valid, auth, TRUE, base); + if (*best && valid != VALIDATION_STALE) + { + break; + } + } + } + enumerator->destroy(enumerator); + } + return valid; +} + +/** + * Look for a delta CRL for a given base CRL + */ +static cert_validation_t check_delta_crl(x509_t *subject, x509_t *issuer, + crl_t *base, cert_validation_t base_valid, auth_cfg_t *auth) +{ + cert_validation_t valid = VALIDATION_SKIPPED; + certificate_t *best = NULL, *current; enumerator_t *enumerator; + identification_t *id; + x509_cdp_t *cdp; chunk_t chunk; - char *uri = NULL; + bool uri; - /* derive the authorityKeyIdentifier from the issuer's public key */ - current = &issuer->interface; - public = current->get_public_key(current); - if (public && public->get_fingerprint(public, KEYID_PUBKEY_SHA1, &chunk)) + /* find cached delta CRL via subjectKeyIdentifier */ + chunk = issuer->get_subjectKeyIdentifier(issuer); + if (chunk.len) { - keyid = identification_create_from_encoding(ID_KEY_ID, chunk); + id = identification_create_from_encoding(ID_KEY_ID, chunk); + valid = find_crl(subject, id, auth, base, &best, &uri); + id->destroy(id); + } - /* find a cached crl by authorityKeyIdentifier */ - enumerator = lib->credmgr->create_cert_enumerator(lib->credmgr, - CERT_X509_CRL, KEY_ANY, keyid, FALSE); - while (enumerator->enumerate(enumerator, ¤t)) + /* find delta CRL by CRLIssuer */ + enumerator = subject->create_crl_uri_enumerator(subject); + while (valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED && + enumerator->enumerate(enumerator, &cdp)) + { + if (cdp->issuer) { - current->get_ref(current); - best = get_better_crl(current, best, subject, issuer, - &valid, FALSE); + valid = find_crl(subject, cdp->issuer, auth, base, &best, &uri); + } + } + enumerator->destroy(enumerator); + + /* fetch from URIs found in Freshest CRL extension */ + enumerator = base->create_delta_crl_uri_enumerator(base); + while (valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED && + enumerator->enumerate(enumerator, &cdp)) + { + current = fetch_crl(cdp->uri); + if (current) + { + if (cdp->issuer && !current->has_issuer(current, cdp->issuer)) + { + DBG1(DBG_CFG, "issuer of fetched delta CRL '%Y' does not match " + "certificates CRL issuer '%Y'", + current->get_issuer(current), cdp->issuer); + current->destroy(current); + continue; + } + best = get_better_crl(current, best, subject, &valid, + auth, TRUE, base); if (best && valid != VALIDATION_STALE) { - DBG1(DBG_CFG, " using cached crl"); break; } } - enumerator->destroy(enumerator); + } + enumerator->destroy(enumerator); + + if (best) + { + best->destroy(best); + return valid; + } + return base_valid; +} + + +/** + * validate a x509 certificate using CRL + */ +static cert_validation_t check_crl(x509_t *subject, x509_t *issuer, + auth_cfg_t *auth) +{ + cert_validation_t valid = VALIDATION_SKIPPED; + certificate_t *best = NULL; + identification_t *id; + x509_cdp_t *cdp; + bool uri_found = FALSE; + certificate_t *current; + enumerator_t *enumerator; + chunk_t chunk; + + /* use issuers subjectKeyIdentifier to find a cached CRL / fetch from CDP */ + chunk = issuer->get_subjectKeyIdentifier(issuer); + if (chunk.len) + { + id = identification_create_from_encoding(ID_KEY_ID, chunk); + valid = find_crl(subject, id, auth, NULL, &best, &uri_found); + id->destroy(id); + } - /* fallback to fetching crls from credential sets cdps */ - if (valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED) + /* find a cached CRL or fetch via configured CDP via CRLIssuer */ + enumerator = subject->create_crl_uri_enumerator(subject); + while (valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED && + enumerator->enumerate(enumerator, &cdp)) + { + if (cdp->issuer) { - enumerator = lib->credmgr->create_cdp_enumerator(lib->credmgr, - CERT_X509_CRL, keyid); - while (enumerator->enumerate(enumerator, &uri)) - { - current = fetch_crl(uri); - if (current) - { - best = get_better_crl(current, best, subject, issuer, - &valid, TRUE); - if (best && valid != VALIDATION_STALE) - { - break; - } - } - } - enumerator->destroy(enumerator); + valid = find_crl(subject, cdp->issuer, auth, NULL, + &best, &uri_found); } - keyid->destroy(keyid); } - DESTROY_IF(public); + enumerator->destroy(enumerator); - /* fallback to fetching crls from cdps from subject's certificate */ + /* fallback to fetching CRLs from CDPs found in subjects certificate */ if (valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED) { enumerator = subject->create_crl_uri_enumerator(subject); - - while (enumerator->enumerate(enumerator, &uri)) + while (enumerator->enumerate(enumerator, &cdp)) { - current = fetch_crl(uri); + uri_found = TRUE; + current = fetch_crl(cdp->uri); if (current) { - best = get_better_crl(current, best, subject, issuer, - &valid, TRUE); + if (cdp->issuer && !current->has_issuer(current, cdp->issuer)) + { + DBG1(DBG_CFG, "issuer of fetched CRL '%Y' does not match " + "certificates CRL issuer '%Y'", + current->get_issuer(current), cdp->issuer); + current->destroy(current); + continue; + } + best = get_better_crl(current, best, subject, &valid, + auth, TRUE, NULL); if (best && valid != VALIDATION_STALE) { break; @@ -493,8 +635,14 @@ static cert_validation_t check_crl(x509_t *subject, x509_t *issuer, enumerator->destroy(enumerator); } + /* look for delta CRLs */ + if (best && (valid == VALIDATION_GOOD || valid == VALIDATION_STALE)) + { + valid = check_delta_crl(subject, issuer, (crl_t*)best, valid, auth); + } + /* an uri was found, but no result. switch validation state to failed */ - if (valid == VALIDATION_SKIPPED && uri) + if (valid == VALIDATION_SKIPPED && uri_found) { valid = VALIDATION_FAILED; } @@ -517,7 +665,8 @@ static cert_validation_t check_crl(x509_t *subject, x509_t *issuer, METHOD(cert_validator_t, validate, bool, private_revocation_validator_t *this, certificate_t *subject, - certificate_t *issuer, bool online, int pathlen, auth_cfg_t *auth) + certificate_t *issuer, bool online, u_int pathlen, bool anchor, + auth_cfg_t *auth) { if (subject->get_type(subject) == CERT_X509 && issuer->get_type(issuer) == CERT_X509 && @@ -525,7 +674,8 @@ METHOD(cert_validator_t, validate, bool, { DBG1(DBG_CFG, "checking certificate status of \"%Y\"", subject->get_subject(subject)); - switch (check_ocsp((x509_t*)subject, (x509_t*)issuer, auth)) + switch (check_ocsp((x509_t*)subject, (x509_t*)issuer, + pathlen ? NULL : auth)) { case VALIDATION_GOOD: DBG1(DBG_CFG, "certificate status is good"); @@ -543,7 +693,8 @@ METHOD(cert_validator_t, validate, bool, DBG1(DBG_CFG, "ocsp check failed, fallback to crl"); break; } - switch (check_crl((x509_t*)subject, (x509_t*)issuer, auth)) + switch (check_crl((x509_t*)subject, (x509_t*)issuer, + pathlen ? NULL : auth)) { case VALIDATION_GOOD: DBG1(DBG_CFG, "certificate status is good"); diff --git a/src/libstrongswan/plugins/sha1/Makefile.in b/src/libstrongswan/plugins/sha1/Makefile.in index 1036bedfc..3d96f4339 100644 --- a/src/libstrongswan/plugins/sha1/Makefile.in +++ b/src/libstrongswan/plugins/sha1/Makefile.in @@ -220,9 +220,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -261,6 +259,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libstrongswan/plugins/sha1/sha1_plugin.c b/src/libstrongswan/plugins/sha1/sha1_plugin.c index 7b9cf878f..dda2cbc1a 100644 --- a/src/libstrongswan/plugins/sha1/sha1_plugin.c +++ b/src/libstrongswan/plugins/sha1/sha1_plugin.c @@ -19,6 +19,8 @@ #include "sha1_hasher.h" #include "sha1_prf.h" +static const char *plugin_name = "sha1"; + typedef struct private_sha1_plugin_t private_sha1_plugin_t; /** @@ -32,10 +34,8 @@ struct private_sha1_plugin_t { sha1_plugin_t public; }; -/** - * Implementation of sha1_plugin_t.destroy - */ -static void destroy(private_sha1_plugin_t *this) +METHOD(plugin_t, destroy, void, + private_sha1_plugin_t *this) { lib->crypto->remove_hasher(lib->crypto, (hasher_constructor_t)sha1_hasher_create); @@ -49,13 +49,19 @@ static void destroy(private_sha1_plugin_t *this) */ plugin_t *sha1_plugin_create() { - private_sha1_plugin_t *this = malloc_thing(private_sha1_plugin_t); + private_sha1_plugin_t *this; - this->public.plugin.destroy = (void(*)(plugin_t*))destroy; + INIT(this, + .public = { + .plugin = { + .destroy = _destroy, + }, + }, + ); - lib->crypto->add_hasher(lib->crypto, HASH_SHA1, + lib->crypto->add_hasher(lib->crypto, HASH_SHA1, plugin_name, (hasher_constructor_t)sha1_hasher_create); - lib->crypto->add_prf(lib->crypto, PRF_KEYED_SHA1, + lib->crypto->add_prf(lib->crypto, PRF_KEYED_SHA1, plugin_name, (prf_constructor_t)sha1_prf_create); return &this->public.plugin; diff --git a/src/libstrongswan/plugins/sha2/Makefile.in b/src/libstrongswan/plugins/sha2/Makefile.in index 579e6f9b0..fcbfa0c44 100644 --- a/src/libstrongswan/plugins/sha2/Makefile.in +++ b/src/libstrongswan/plugins/sha2/Makefile.in @@ -219,9 +219,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -260,6 +258,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libstrongswan/plugins/sha2/sha2_plugin.c b/src/libstrongswan/plugins/sha2/sha2_plugin.c index 810d9922a..a5937dbb2 100644 --- a/src/libstrongswan/plugins/sha2/sha2_plugin.c +++ b/src/libstrongswan/plugins/sha2/sha2_plugin.c @@ -18,6 +18,8 @@ #include <library.h> #include "sha2_hasher.h" +static const char *plugin_name = "sha2"; + typedef struct private_sha2_plugin_t private_sha2_plugin_t; /** @@ -31,10 +33,8 @@ struct private_sha2_plugin_t { sha2_plugin_t public; }; -/** - * Implementation of sha2_plugin_t.destroy - */ -static void destroy(private_sha2_plugin_t *this) +METHOD(plugin_t, destroy, void, + private_sha2_plugin_t *this) { lib->crypto->remove_hasher(lib->crypto, (hasher_constructor_t)sha2_hasher_create); @@ -46,17 +46,23 @@ static void destroy(private_sha2_plugin_t *this) */ plugin_t *sha2_plugin_create() { - private_sha2_plugin_t *this = malloc_thing(private_sha2_plugin_t); + private_sha2_plugin_t *this; - this->public.plugin.destroy = (void(*)(plugin_t*))destroy; + INIT(this, + .public = { + .plugin = { + .destroy = _destroy, + }, + }, + ); - lib->crypto->add_hasher(lib->crypto, HASH_SHA224, + lib->crypto->add_hasher(lib->crypto, HASH_SHA224, plugin_name, (hasher_constructor_t)sha2_hasher_create); - lib->crypto->add_hasher(lib->crypto, HASH_SHA256, + lib->crypto->add_hasher(lib->crypto, HASH_SHA256, plugin_name, (hasher_constructor_t)sha2_hasher_create); - lib->crypto->add_hasher(lib->crypto, HASH_SHA384, + lib->crypto->add_hasher(lib->crypto, HASH_SHA384, plugin_name, (hasher_constructor_t)sha2_hasher_create); - lib->crypto->add_hasher(lib->crypto, HASH_SHA512, + lib->crypto->add_hasher(lib->crypto, HASH_SHA512, plugin_name, (hasher_constructor_t)sha2_hasher_create); return &this->public.plugin; diff --git a/src/libstrongswan/plugins/soup/Makefile.am b/src/libstrongswan/plugins/soup/Makefile.am new file mode 100644 index 000000000..9006f1b7c --- /dev/null +++ b/src/libstrongswan/plugins/soup/Makefile.am @@ -0,0 +1,16 @@ + +INCLUDES = -I$(top_srcdir)/src/libstrongswan ${soup_CFLAGS} + +AM_CFLAGS = -rdynamic + +if MONOLITHIC +noinst_LTLIBRARIES = libstrongswan-soup.la +else +plugin_LTLIBRARIES = libstrongswan-soup.la +endif + +libstrongswan_soup_la_SOURCES = \ + soup_plugin.h soup_plugin.c soup_fetcher.c soup_fetcher.h + +libstrongswan_soup_la_LDFLAGS = -module -avoid-version +libstrongswan_soup_la_LIBADD = ${soup_LIBS} diff --git a/src/libstrongswan/plugins/soup/Makefile.in b/src/libstrongswan/plugins/soup/Makefile.in new file mode 100644 index 000000000..35d175f95 --- /dev/null +++ b/src/libstrongswan/plugins/soup/Makefile.in @@ -0,0 +1,601 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 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. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@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 +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/libstrongswan/plugins/soup +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +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)/m4/macros/add-plugin.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__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' +am__installdirs = "$(DESTDIR)$(plugindir)" +LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES) +am__DEPENDENCIES_1 = +libstrongswan_soup_la_DEPENDENCIES = $(am__DEPENDENCIES_1) +am_libstrongswan_soup_la_OBJECTS = soup_plugin.lo soup_fetcher.lo +libstrongswan_soup_la_OBJECTS = $(am_libstrongswan_soup_la_OBJECTS) +libstrongswan_soup_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(libstrongswan_soup_la_LDFLAGS) $(LDFLAGS) -o $@ +@MONOLITHIC_FALSE@am_libstrongswan_soup_la_rpath = -rpath $(plugindir) +@MONOLITHIC_TRUE@am_libstrongswan_soup_la_rpath = +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) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libstrongswan_soup_la_SOURCES) +DIST_SOURCES = $(libstrongswan_soup_la_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BTLIB = @BTLIB@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLIB = @DLLIB@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GPERF = @GPERF@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +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@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +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@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PTHREADLIB = @PTHREADLIB@ +RANLIB = @RANLIB@ +RTLIB = @RTLIB@ +RUBY = @RUBY@ +RUBYINCLUDE = @RUBYINCLUDE@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKLIB = @SOCKLIB@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +c_plugins = @c_plugins@ +datadir = @datadir@ +datarootdir = @datarootdir@ +dbusservicedir = @dbusservicedir@ +default_pkcs11 = @default_pkcs11@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +gtk_CFLAGS = @gtk_CFLAGS@ +gtk_LIBS = @gtk_LIBS@ +h_plugins = @h_plugins@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +ipsecdir = @ipsecdir@ +ipsecgroup = @ipsecgroup@ +ipsecuser = @ipsecuser@ +libcharon_plugins = @libcharon_plugins@ +libdir = @libdir@ +libexecdir = @libexecdir@ +linux_headers = @linux_headers@ +localedir = @localedir@ +localstatedir = @localstatedir@ +lt_ECHO = @lt_ECHO@ +maemo_CFLAGS = @maemo_CFLAGS@ +maemo_LIBS = @maemo_LIBS@ +manager_plugins = @manager_plugins@ +mandir = @mandir@ +medsrv_plugins = @medsrv_plugins@ +mkdir_p = @mkdir_p@ +nm_CFLAGS = @nm_CFLAGS@ +nm_LIBS = @nm_LIBS@ +nm_ca_dir = @nm_ca_dir@ +oldincludedir = @oldincludedir@ +openac_plugins = @openac_plugins@ +p_plugins = @p_plugins@ +pdfdir = @pdfdir@ +piddir = @piddir@ +pki_plugins = @pki_plugins@ +plugindir = @plugindir@ +pluto_plugins = @pluto_plugins@ +pool_plugins = @pool_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@ +s_plugins = @s_plugins@ +sbindir = @sbindir@ +scepclient_plugins = @scepclient_plugins@ +scripts_plugins = @scripts_plugins@ +sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ +srcdir = @srcdir@ +strongswan_conf = @strongswan_conf@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +urandom_device = @urandom_device@ +xml_CFLAGS = @xml_CFLAGS@ +xml_LIBS = @xml_LIBS@ +INCLUDES = -I$(top_srcdir)/src/libstrongswan ${soup_CFLAGS} +AM_CFLAGS = -rdynamic +@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-soup.la +@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-soup.la +libstrongswan_soup_la_SOURCES = \ + soup_plugin.h soup_plugin.c soup_fetcher.c soup_fetcher.h + +libstrongswan_soup_la_LDFLAGS = -module -avoid-version +libstrongswan_soup_la_LIBADD = ${soup_LIBS} +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libstrongswan/plugins/soup/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/libstrongswan/plugins/soup/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(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): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)" + @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \ + } + +uninstall-pluginLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \ + done + +clean-pluginLTLIBRARIES: + -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES) + @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libstrongswan-soup.la: $(libstrongswan_soup_la_OBJECTS) $(libstrongswan_soup_la_DEPENDENCIES) + $(libstrongswan_soup_la_LINK) $(am_libstrongswan_soup_la_rpath) $(libstrongswan_soup_la_OBJECTS) $(libstrongswan_soup_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/soup_fetcher.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/soup_plugin.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@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@ $(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@ $(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 $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + 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; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + 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; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + 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) + 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)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + 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 -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(plugindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +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" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + clean-pluginLTLIBRARIES mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-pluginLTLIBRARIES + +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-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pluginLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \ + ctags distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-pluginLTLIBRARIES install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags uninstall uninstall-am \ + uninstall-pluginLTLIBRARIES + + +# 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/libstrongswan/plugins/soup/soup_fetcher.c b/src/libstrongswan/plugins/soup/soup_fetcher.c new file mode 100644 index 000000000..fd97631bd --- /dev/null +++ b/src/libstrongswan/plugins/soup/soup_fetcher.c @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * 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 "soup_fetcher.h" + +#include <libsoup/soup.h> + +#include <library.h> +#include <debug.h> + +#define DEFAULT_TIMEOUT 10 + +typedef struct private_soup_fetcher_t private_soup_fetcher_t; + +/** + * private data of a soup_fetcher_t object. + */ +struct private_soup_fetcher_t { + + /** + * Public data + */ + soup_fetcher_t public; + + /** + * HTTP request method + */ + const char *method; + + /** + * Request content type + */ + char *type; + + /** + * Request data + */ + chunk_t data; + + /** + * Request timeout + */ + u_int timeout; + + /** + * HTTP request version + */ + SoupHTTPVersion version; +}; + +METHOD(fetcher_t, fetch, status_t, + private_soup_fetcher_t *this, char *uri, chunk_t *result) +{ + SoupSession *session; + SoupMessage *message; + status_t status = FAILED; + + message = soup_message_new(this->method, uri); + if (!message) + { + return NOT_SUPPORTED; + } + if (this->type) + { + soup_message_set_request(message, this->type, SOUP_MEMORY_STATIC, + this->data.ptr, this->data.len); + } + soup_message_set_http_version(message, this->version); + session = soup_session_sync_new(); + g_object_set(G_OBJECT(session), + SOUP_SESSION_TIMEOUT, (guint)this->timeout, NULL); + + DBG2(DBG_LIB, "sending http request to '%s'...", uri); + soup_session_send_message(session, message); + if (SOUP_STATUS_IS_SUCCESSFUL(message->status_code)) + { + *result = chunk_clone(chunk_create((u_char*)message->response_body->data, + message->response_body->length)); + status = SUCCESS; + } + else + { + DBG1(DBG_LIB, "HTTP request failed, code %d", message->status_code); + } + g_object_unref(G_OBJECT(message)); + g_object_unref(G_OBJECT(session)); + return status; +} + +METHOD(fetcher_t, set_option, bool, + private_soup_fetcher_t *this, fetcher_option_t option, ...) +{ + bool supported = TRUE; + va_list args; + + va_start(args, option); + switch (option) + { + case FETCH_REQUEST_DATA: + this->method = SOUP_METHOD_POST; + this->data = va_arg(args, chunk_t); + break; + case FETCH_REQUEST_TYPE: + this->type = va_arg(args, char*); + break; + case FETCH_HTTP_VERSION_1_0: + this->version = SOUP_HTTP_1_0; + break; + case FETCH_TIMEOUT: + this->timeout = va_arg(args, u_int); + break; + default: + supported = FALSE; + break; + } + va_end(args); + return supported; +} + +METHOD(fetcher_t, destroy, void, + private_soup_fetcher_t *this) +{ + free(this); +} + +/* + * Described in header. + */ +soup_fetcher_t *soup_fetcher_create() +{ + private_soup_fetcher_t *this; + + INIT(this, + .public = { + .interface = { + .fetch = _fetch, + .set_option = _set_option, + .destroy = _destroy, + }, + }, + .method = SOUP_METHOD_GET, + .version = SOUP_HTTP_1_1, + .timeout = DEFAULT_TIMEOUT, + ); + + return &this->public; +} diff --git a/src/libstrongswan/plugins/soup/soup_fetcher.h b/src/libstrongswan/plugins/soup/soup_fetcher.h new file mode 100644 index 000000000..9b2579515 --- /dev/null +++ b/src/libstrongswan/plugins/soup/soup_fetcher.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * 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. + */ + +/** + * @defgroup soup_fetcher soup_fetcher + * @{ @ingroup soup_p + */ + +#ifndef SOUP_FETCHER_H_ +#define SOUP_FETCHER_H_ + +#include <library.h> + +typedef struct soup_fetcher_t soup_fetcher_t; + +/** + * Fetcher implementation for HTTP using libsoup. + */ +struct soup_fetcher_t { + + /** + * Implements fetcher interface. + */ + fetcher_t interface; +}; + +/** + * Create a soup_fetcher instance. + */ +soup_fetcher_t *soup_fetcher_create(); + +#endif /** SOUP_FETCHER_H_ @}*/ diff --git a/src/libstrongswan/plugins/soup/soup_plugin.c b/src/libstrongswan/plugins/soup/soup_plugin.c new file mode 100644 index 000000000..970e32472 --- /dev/null +++ b/src/libstrongswan/plugins/soup/soup_plugin.c @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * 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 "soup_plugin.h" +#include "soup_fetcher.h" + +#include <glib.h> +#include <glib-object.h> + +#include <library.h> + +typedef struct private_soup_plugin_t private_soup_plugin_t; + +/** + * private data of soup_plugin + */ +struct private_soup_plugin_t { + + /** + * public functions + */ + soup_plugin_t public; +}; + +METHOD(plugin_t, destroy, void, + private_soup_plugin_t *this) +{ + lib->fetcher->remove_fetcher(lib->fetcher, + (fetcher_constructor_t)soup_fetcher_create); + free(this); +} + +/* + * see header file + */ +plugin_t *soup_plugin_create() +{ + private_soup_plugin_t *this; + + g_type_init(); + if (!g_thread_get_initialized()) + { + g_thread_init(NULL); + } + + INIT(this, + .public = { + .plugin = { + .destroy = _destroy, + }, + }, + ); + + lib->fetcher->add_fetcher(lib->fetcher, + (fetcher_constructor_t)soup_fetcher_create, "http://"); + lib->fetcher->add_fetcher(lib->fetcher, + (fetcher_constructor_t)soup_fetcher_create, "https://"); + + return &this->public.plugin; +} diff --git a/src/libstrongswan/plugins/soup/soup_plugin.h b/src/libstrongswan/plugins/soup/soup_plugin.h new file mode 100644 index 000000000..2dfa1d243 --- /dev/null +++ b/src/libstrongswan/plugins/soup/soup_plugin.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * 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. + */ + +/** + * @defgroup soup_p soup + * @ingroup plugins + * + * @defgroup soup_plugin soup_plugin + * @{ @ingroup soup_p + */ + +#ifndef SOUP_PLUGIN_H_ +#define SOUP_PLUGIN_H_ + +#include <plugins/plugin.h> + +typedef struct soup_plugin_t soup_plugin_t; + +/** + * Plugin implementing fetcher interface for HTTP using libsoup. + */ +struct soup_plugin_t { + + /** + * Implements plugin interface + */ + plugin_t plugin; +}; + +#endif /** SOUP_PLUGIN_H_ @}*/ diff --git a/src/libstrongswan/plugins/sqlite/Makefile.in b/src/libstrongswan/plugins/sqlite/Makefile.in index 9c9b57f98..ae015d1a8 100644 --- a/src/libstrongswan/plugins/sqlite/Makefile.in +++ b/src/libstrongswan/plugins/sqlite/Makefile.in @@ -222,9 +222,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -263,6 +261,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libstrongswan/plugins/sqlite/sqlite_database.c b/src/libstrongswan/plugins/sqlite/sqlite_database.c index 3e20dbb51..f9e06199e 100644 --- a/src/libstrongswan/plugins/sqlite/sqlite_database.c +++ b/src/libstrongswan/plugins/sqlite/sqlite_database.c @@ -213,10 +213,8 @@ static bool sqlite_enumerator_enumerate(sqlite_enumerator_t *this, ...) return TRUE; } -/** - * Implementation of database_t.query. - */ -static enumerator_t* query(private_sqlite_database_t *this, char *sql, ...) +METHOD(database_t, query, enumerator_t*, + private_sqlite_database_t *this, char *sql, ...) { sqlite3_stmt *stmt; va_list args; @@ -248,10 +246,8 @@ static enumerator_t* query(private_sqlite_database_t *this, char *sql, ...) return (enumerator_t*)enumerator; } -/** - * Implementation of database_t.execute. - */ -static int execute(private_sqlite_database_t *this, int *rowid, char *sql, ...) +METHOD(database_t, execute, int, + private_sqlite_database_t *this, int *rowid, char *sql, ...) { sqlite3_stmt *stmt; int affected = -1; @@ -283,10 +279,8 @@ static int execute(private_sqlite_database_t *this, int *rowid, char *sql, ...) return affected; } -/** - * Implementation of database_t.get_driver - */ -static db_driver_t get_driver(private_sqlite_database_t *this) +METHOD(database_t, get_driver, db_driver_t, + private_sqlite_database_t *this) { return DB_SQLITE; } @@ -302,10 +296,8 @@ static int busy_handler(private_sqlite_database_t *this, int count) return 1; } -/** - * Implementation of database_t.destroy - */ -static void destroy(private_sqlite_database_t *this) +METHOD(database_t, destroy, void, + private_sqlite_database_t *this) { sqlite3_close(this->db); this->mutex->destroy(this->mutex); @@ -329,20 +321,23 @@ sqlite_database_t *sqlite_database_create(char *uri) } file = uri + 9; - this = malloc_thing(private_sqlite_database_t); - - this->public.db.query = (enumerator_t* (*)(database_t *this, char *sql, ...))query; - this->public.db.execute = (int (*)(database_t *this, int *rowid, char *sql, ...))execute; - this->public.db.get_driver = (db_driver_t(*)(database_t*))get_driver; - this->public.db.destroy = (void(*)(database_t*))destroy; - - this->mutex = mutex_create(MUTEX_TYPE_RECURSIVE); + INIT(this, + .public = { + .db = { + .query = _query, + .execute = _execute, + .get_driver = _get_driver, + .destroy = _destroy, + }, + }, + .mutex = mutex_create(MUTEX_TYPE_RECURSIVE), + ); if (sqlite3_open(file, &this->db) != SQLITE_OK) { DBG1(DBG_LIB, "opening SQLite database '%s' failed: %s", file, sqlite3_errmsg(this->db)); - destroy(this); + _destroy(this); return NULL; } diff --git a/src/libstrongswan/plugins/sqlite/sqlite_plugin.c b/src/libstrongswan/plugins/sqlite/sqlite_plugin.c index 332d82318..e0b8e6ce1 100644 --- a/src/libstrongswan/plugins/sqlite/sqlite_plugin.c +++ b/src/libstrongswan/plugins/sqlite/sqlite_plugin.c @@ -31,10 +31,8 @@ struct private_sqlite_plugin_t { sqlite_plugin_t public; }; -/** - * Implementation of plugin_t.destroy - */ -static void destroy(private_sqlite_plugin_t *this) +METHOD(plugin_t, destroy, void, + private_sqlite_plugin_t *this) { lib->db->remove_database(lib->db, (database_constructor_t)sqlite_database_create); @@ -46,9 +44,15 @@ static void destroy(private_sqlite_plugin_t *this) */ plugin_t *sqlite_plugin_create() { - private_sqlite_plugin_t *this = malloc_thing(private_sqlite_plugin_t); - - this->public.plugin.destroy = (void(*)(plugin_t*))destroy; + private_sqlite_plugin_t *this; + + INIT(this, + .public = { + .plugin = { + .destroy = _destroy, + }, + }, + ); lib->db->add_database(lib->db, (database_constructor_t)sqlite_database_create); diff --git a/src/libstrongswan/plugins/test_vectors/Makefile.in b/src/libstrongswan/plugins/test_vectors/Makefile.in index 9be3f825a..9dccb05e3 100644 --- a/src/libstrongswan/plugins/test_vectors/Makefile.in +++ b/src/libstrongswan/plugins/test_vectors/Makefile.in @@ -227,9 +227,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -268,6 +266,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libstrongswan/plugins/test_vectors/test_vectors_plugin.c b/src/libstrongswan/plugins/test_vectors/test_vectors_plugin.c index f3a254d8d..176bc438d 100644 --- a/src/libstrongswan/plugins/test_vectors/test_vectors_plugin.c +++ b/src/libstrongswan/plugins/test_vectors/test_vectors_plugin.c @@ -104,10 +104,8 @@ struct private_test_vectors_plugin_t { test_vectors_plugin_t public; }; -/** - * Implementation of test_vectors_plugin_t.test_vectorstroy - */ -static void destroy(private_test_vectors_plugin_t *this) +METHOD(plugin_t, destroy, void, + private_test_vectors_plugin_t *this) { free(this); } @@ -117,10 +115,16 @@ static void destroy(private_test_vectors_plugin_t *this) */ plugin_t *test_vectors_plugin_create() { - private_test_vectors_plugin_t *this = malloc_thing(private_test_vectors_plugin_t); + private_test_vectors_plugin_t *this; int i; - this->public.plugin.destroy = (void(*)(plugin_t*))destroy; + INIT(this, + .public = { + .plugin = { + .destroy = _destroy, + }, + }, + ); for (i = 0; i < countof(crypter); i++) { diff --git a/src/libstrongswan/plugins/x509/Makefile.in b/src/libstrongswan/plugins/x509/Makefile.in index b1cc2f168..57deab98e 100644 --- a/src/libstrongswan/plugins/x509/Makefile.in +++ b/src/libstrongswan/plugins/x509/Makefile.in @@ -221,9 +221,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -262,6 +260,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libstrongswan/plugins/x509/x509_cert.c b/src/libstrongswan/plugins/x509/x509_cert.c index 559090aa0..526dbe8c6 100644 --- a/src/libstrongswan/plugins/x509/x509_cert.c +++ b/src/libstrongswan/plugins/x509/x509_cert.c @@ -117,7 +117,7 @@ struct private_x509_cert_t { linked_list_t *subjectAltNames; /** - * List of crlDistributionPoints as allocated char* + * List of crlDistributionPoints as x509_cdp_t* */ linked_list_t *crl_uris; @@ -132,6 +132,26 @@ struct private_x509_cert_t { linked_list_t *ipAddrBlocks; /** + * List of permitted name constraints + */ + linked_list_t *permitted_names; + + /** + * List of exluced name constraints + */ + linked_list_t *excluded_names; + + /** + * List of certificatePolicies, as x509_cert_policy_t + */ + linked_list_t *cert_policies; + + /** + * List of policyMappings, as x509_policy_mapping_t + */ + linked_list_t *policy_mappings; + + /** * certificate's embedded public key */ public_key_t *public_key; @@ -154,7 +174,22 @@ struct private_x509_cert_t { /** * Path Length Constraint */ - int pathLenConstraint; + u_char pathLenConstraint; + + /** + * requireExplicitPolicy Constraint + */ + u_char require_explicit; + + /** + * inhibitPolicyMapping Constraint + */ + u_char inhibit_mapping; + + /** + * inhibitAnyPolicy Constraint + */ + u_char inhibit_any; /** * x509 constraints and other flags @@ -187,6 +222,53 @@ static const chunk_t ASN1_subjectAltName_oid = chunk_from_chars( ); /** + * Destroy a CertificateDistributionPoint + */ +static void crl_uri_destroy(x509_cdp_t *this) +{ + free(this->uri); + DESTROY_IF(this->issuer); + free(this); +} + +/** + * Destroy a CertificatePolicy + */ +static void cert_policy_destroy(x509_cert_policy_t *this) +{ + free(this->oid.ptr); + free(this->cps_uri); + free(this->unotice_text); + free(this); +} + +/** + * Free policy mapping + */ +static void policy_mapping_destroy(x509_policy_mapping_t *mapping) +{ + free(mapping->issuer.ptr); + free(mapping->subject.ptr); + free(mapping); +} + +/** + * Parse a length constraint from an unwrapped integer + */ +static u_int parse_constraint(chunk_t object) +{ + switch (object.len) + { + case 0: + return 0; + case 1: + return (object.ptr[0] & 0x80) ? X509_NO_CONSTRAINT : object.ptr[0]; + default: + return X509_NO_CONSTRAINT; + } +} + +/** * ASN.1 definition of a basicConstraints extension */ static const asn1Object_t basicConstraintsObjects[] = { @@ -228,15 +310,7 @@ static void parse_basicConstraints(chunk_t blob, int level0, case BASIC_CONSTRAINTS_PATH_LEN: if (isCA) { - if (object.len == 0) - { - this->pathLenConstraint = 0; - } - else if (object.len == 1) - { - this->pathLenConstraint = *object.ptr; - } - /* we ignore path length constraints > 127 */ + this->pathLenConstraint = parse_constraint(object); } break; default: @@ -574,7 +648,7 @@ static void parse_authorityInfoAccess(chunk_t blob, int level0, } break; default: - /* unkown accessMethod, ignoring */ + /* unknown accessMethod, ignoring */ break; } break; @@ -589,6 +663,60 @@ end: } /** + * Extract KeyUsage flags + */ +static void parse_keyUsage(chunk_t blob, private_x509_cert_t *this) +{ + enum { + KU_DIGITAL_SIGNATURE = 0, + KU_NON_REPUDIATION = 1, + KU_KEY_ENCIPHERMENT = 2, + KU_DATA_ENCIPHERMENT = 3, + KU_KEY_AGREEMENT = 4, + KU_KEY_CERT_SIGN = 5, + KU_CRL_SIGN = 6, + KU_ENCIPHER_ONLY = 7, + KU_DECIPHER_ONLY = 8, + }; + + if (asn1_unwrap(&blob, &blob) == ASN1_BIT_STRING && blob.len) + { + int bit, byte, unused = blob.ptr[0]; + + blob = chunk_skip(blob, 1); + for (byte = 0; byte < blob.len; byte++) + { + for (bit = 0; bit < 8; bit++) + { + if (byte == blob.len - 1 && bit > (7 - unused)) + { + break; + } + if (blob.ptr[byte] & 1 << (7 - bit)) + { + switch (byte * 8 + bit) + { + case KU_CRL_SIGN: + this->flags |= X509_CRL_SIGN; + break; + case KU_KEY_CERT_SIGN: + /* we use the caBasicConstraint, MUST be set */ + case KU_DIGITAL_SIGNATURE: + case KU_NON_REPUDIATION: + case KU_KEY_ENCIPHERMENT: + case KU_DATA_ENCIPHERMENT: + case KU_KEY_AGREEMENT: + case KU_ENCIPHER_ONLY: + case KU_DECIPHER_ONLY: + break; + } + } + } + } + } +} + +/** * ASN.1 definition of a extendedKeyUsage extension */ static const asn1Object_t extendedKeyUsageObjects[] = { @@ -600,7 +728,7 @@ static const asn1Object_t extendedKeyUsageObjects[] = { #define EXT_KEY_USAGE_PURPOSE_ID 1 /** - * Extracts extendedKeyUsage OIDs - currently only OCSP_SIGING is returned + * Extracts extendedKeyUsage OIDs */ static void parse_extendedKeyUsage(chunk_t blob, int level0, private_x509_cert_t *this) @@ -649,51 +777,328 @@ static const asn1Object_t crlDistributionPointsObjects[] = { { 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, "crlIssuer", ASN1_CONTEXT_C_2, ASN1_OPT|ASN1_OBJ }, /* 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 1 #define CRL_DIST_POINTS_FULLNAME 3 +#define CRL_DIST_POINTS_ISSUER 10 + +/** + * Add entry to the list of each pairing of URI and Issuer + */ +static void add_cdps(linked_list_t *list, linked_list_t *uris, + linked_list_t *issuers) +{ + identification_t *issuer, *id; + enumerator_t *enumerator; + x509_cdp_t *cdp; + char *uri; + + while (uris->remove_last(uris, (void**)&id) == SUCCESS) + { + if (asprintf(&uri, "%Y", id) > 0) + { + if (issuers->get_count(issuers)) + { + enumerator = issuers->create_enumerator(issuers); + while (enumerator->enumerate(enumerator, &issuer)) + { + INIT(cdp, + .uri = strdup(uri), + .issuer = issuer->clone(issuer), + ); + list->insert_last(list, cdp); + } + enumerator->destroy(enumerator); + free(uri); + } + else + { + INIT(cdp, + .uri = uri, + ); + list->insert_last(list, cdp); + } + } + id->destroy(id); + } + while (issuers->remove_last(issuers, (void**)&id) == SUCCESS) + { + id->destroy(id); + } +} /** * Extracts one or several crlDistributionPoints into a list */ -static void parse_crlDistributionPoints(chunk_t blob, int level0, - private_x509_cert_t *this) +void x509_parse_crlDistributionPoints(chunk_t blob, int level0, + linked_list_t *list) { + linked_list_t *uris, *issuers; asn1_parser_t *parser; chunk_t object; int objectID; - linked_list_t *list = linked_list_create(); + uris = linked_list_create(); + issuers = linked_list_create(); parser = asn1_parser_create(crlDistributionPointsObjects, blob); parser->set_top_level(parser, level0); while (parser->iterate(parser, &objectID, &object)) { - if (objectID == CRL_DIST_POINTS_FULLNAME) + switch (objectID) { - identification_t *id; + case CRL_DIST_POINTS: + add_cdps(list, uris, issuers); + break; + case CRL_DIST_POINTS_FULLNAME: + x509_parse_generalNames(object, parser->get_level(parser) + 1, + TRUE, uris); + break; + case CRL_DIST_POINTS_ISSUER: + x509_parse_generalNames(object, parser->get_level(parser) + 1, + TRUE, issuers); + break; + default: + break; + } + } + parser->destroy(parser); - /* append extracted generalNames to existing chained list */ - x509_parse_generalNames(object, parser->get_level(parser)+1, - TRUE, list); + add_cdps(list, uris, issuers); - while (list->remove_last(list, (void**)&id) == SUCCESS) - { - char *uri; + uris->destroy(uris); + issuers->destroy(issuers); +} + +/** + * ASN.1 definition of nameConstraints + */ +static const asn1Object_t nameConstraintsObjects[] = { + { 0, "nameConstraints", ASN1_SEQUENCE, ASN1_LOOP }, /* 0 */ + { 1, "permittedSubtrees", ASN1_CONTEXT_C_0, ASN1_OPT|ASN1_LOOP }, /* 1 */ + { 2, "generalSubtree", ASN1_SEQUENCE, ASN1_BODY }, /* 2 */ + { 1, "end loop", ASN1_EOC, ASN1_END }, /* 3 */ + { 1, "excludedSubtrees", ASN1_CONTEXT_C_1, ASN1_OPT|ASN1_LOOP }, /* 4 */ + { 2, "generalSubtree", ASN1_SEQUENCE, ASN1_BODY }, /* 5 */ + { 1, "end loop", ASN1_EOC, ASN1_END }, /* 6 */ + { 0, "end loop", ASN1_EOC, ASN1_END }, /* 7 */ + { 0, "exit", ASN1_EOC, ASN1_EXIT } +}; +#define NAME_CONSTRAINT_PERMITTED 2 +#define NAME_CONSTRAINT_EXCLUDED 5 + +/** + * Parse permitted/excluded nameConstraints + */ +static void parse_nameConstraints(chunk_t blob, int level0, + private_x509_cert_t *this) +{ + asn1_parser_t *parser; + identification_t *id; + chunk_t object; + int objectID; + + parser = asn1_parser_create(nameConstraintsObjects, blob); + parser->set_top_level(parser, level0); - if (asprintf(&uri, "%Y", id) > 0) + while (parser->iterate(parser, &objectID, &object)) + { + switch (objectID) + { + case NAME_CONSTRAINT_PERMITTED: + id = parse_generalName(object, parser->get_level(parser) + 1); + if (id) { - this->crl_uris->insert_last(this->crl_uris, uri); + this->permitted_names->insert_last(this->permitted_names, id); } - id->destroy(id); - } + break; + case NAME_CONSTRAINT_EXCLUDED: + id = parse_generalName(object, parser->get_level(parser) + 1); + if (id) + { + this->excluded_names->insert_last(this->excluded_names, id); + } + break; + default: + break; + } + } + parser->destroy(parser); +} + +/** + * ASN.1 definition of a certificatePolicies extension + */ +static const asn1Object_t certificatePoliciesObject[] = { + { 0, "certificatePolicies", ASN1_SEQUENCE, ASN1_LOOP }, /* 0 */ + { 1, "policyInformation", ASN1_SEQUENCE, ASN1_NONE }, /* 1 */ + { 2, "policyId", ASN1_OID, ASN1_BODY }, /* 2 */ + { 2, "qualifier", ASN1_SEQUENCE, ASN1_OPT|ASN1_BODY }, /* 3 */ + { 3, "qualifierInfo", ASN1_SEQUENCE, ASN1_NONE }, /* 4 */ + { 4, "qualifierId", ASN1_OID, ASN1_BODY }, /* 5 */ + { 4, "cPSuri", ASN1_IA5STRING, ASN1_OPT|ASN1_BODY }, /* 6 */ + { 4, "end choice", ASN1_EOC, ASN1_END }, /* 7 */ + { 4, "userNotice", ASN1_SEQUENCE, ASN1_OPT|ASN1_NONE }, /* 8 */ + { 5, "explicitText", ASN1_EOC, ASN1_RAW }, /* 9 */ + { 4, "end choice", ASN1_EOC, ASN1_END }, /* 10 */ + { 2, "end opt", ASN1_EOC, ASN1_END }, /* 12 */ + { 0, "end loop", ASN1_EOC, ASN1_END }, /* 13 */ + { 0, "exit", ASN1_EOC, ASN1_EXIT } +}; +#define CERT_POLICY_ID 2 +#define CERT_POLICY_QUALIFIER_ID 5 +#define CERT_POLICY_CPS_URI 6 +#define CERT_POLICY_EXPLICIT_TEXT 9 + +/** + * Parse certificatePolicies + */ +static void parse_certificatePolicies(chunk_t blob, int level0, + private_x509_cert_t *this) +{ + x509_cert_policy_t *policy = NULL; + asn1_parser_t *parser; + chunk_t object; + int objectID, qualifier = OID_UNKNOWN; + + parser = asn1_parser_create(certificatePoliciesObject, blob); + parser->set_top_level(parser, level0); + + while (parser->iterate(parser, &objectID, &object)) + { + switch (objectID) + { + case CERT_POLICY_ID: + INIT(policy, + .oid = chunk_clone(object), + ); + this->cert_policies->insert_last(this->cert_policies, policy); + break; + case CERT_POLICY_QUALIFIER_ID: + qualifier = asn1_known_oid(object); + break; + case CERT_POLICY_CPS_URI: + if (policy && !policy->cps_uri && object.len && + qualifier == OID_POLICY_QUALIFIER_CPS && + chunk_printable(object, NULL, 0)) + { + policy->cps_uri = strndup(object.ptr, object.len); + } + break; + case CERT_POLICY_EXPLICIT_TEXT: + /* TODO */ + break; + default: + break; + } + } + parser->destroy(parser); +} + +/** + * ASN.1 definition of a policyMappings extension + */ +static const asn1Object_t policyMappingsObjects[] = { + { 0, "policyMappings", ASN1_SEQUENCE, ASN1_LOOP }, /* 0 */ + { 1, "policyMapping", ASN1_SEQUENCE, ASN1_NONE }, /* 1 */ + { 2, "issuerPolicy", ASN1_OID, ASN1_BODY }, /* 2 */ + { 2, "subjectPolicy", ASN1_OID, ASN1_BODY }, /* 3 */ + { 0, "end loop", ASN1_EOC, ASN1_END }, /* 4 */ + { 0, "exit", ASN1_EOC, ASN1_EXIT } +}; +#define POLICY_MAPPING 1 +#define POLICY_MAPPING_ISSUER 2 +#define POLICY_MAPPING_SUBJECT 3 + +/** + * Parse policyMappings + */ +static void parse_policyMappings(chunk_t blob, int level0, + private_x509_cert_t *this) +{ + x509_policy_mapping_t *map = NULL; + asn1_parser_t *parser; + chunk_t object; + int objectID; + + parser = asn1_parser_create(policyMappingsObjects, blob); + parser->set_top_level(parser, level0); + + while (parser->iterate(parser, &objectID, &object)) + { + switch (objectID) + { + case POLICY_MAPPING: + INIT(map); + this->policy_mappings->insert_last(this->policy_mappings, map); + break; + case POLICY_MAPPING_ISSUER: + if (map && !map->issuer.len) + { + map->issuer = chunk_clone(object); + } + break; + case POLICY_MAPPING_SUBJECT: + if (map && !map->subject.len) + { + map->subject = chunk_clone(object); + } + break; + default: + break; + } + } + parser->destroy(parser); +} + +/** + * ASN.1 definition of a policyConstraints extension + */ +static const asn1Object_t policyConstraintsObjects[] = { + { 0, "policyConstraints", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ + { 1, "requireExplicitPolicy", ASN1_CONTEXT_C_0, ASN1_OPT|ASN1_NONE }, /* 1 */ + { 2, "SkipCerts", ASN1_INTEGER, ASN1_BODY }, /* 2 */ + { 1, "end opt", ASN1_EOC, ASN1_END }, /* 3 */ + { 1, "inhibitPolicyMapping", ASN1_CONTEXT_C_1, ASN1_OPT|ASN1_NONE }, /* 4 */ + { 2, "SkipCerts", ASN1_INTEGER, ASN1_BODY }, /* 5 */ + { 1, "end opt", ASN1_EOC, ASN1_END }, /* 6 */ + { 0, "exit", ASN1_EOC, ASN1_EXIT } +}; +#define POLICY_CONSTRAINT_EXPLICIT 2 +#define POLICY_CONSTRAINT_INHIBIT 5 + +/** + * Parse policyConstraints + */ +static void parse_policyConstraints(chunk_t blob, int level0, + private_x509_cert_t *this) +{ + asn1_parser_t *parser; + chunk_t object; + int objectID; + + parser = asn1_parser_create(policyConstraintsObjects, blob); + parser->set_top_level(parser, level0); + + while (parser->iterate(parser, &objectID, &object)) + { + switch (objectID) + { + case POLICY_CONSTRAINT_EXPLICIT: + this->require_explicit = parse_constraint(object); + break; + case POLICY_CONSTRAINT_INHIBIT: + this->inhibit_mapping = parse_constraint(object); + break; + default: + break; } } parser->destroy(parser); - list->destroy(list); } /** @@ -888,11 +1293,6 @@ static const asn1Object_t certObjects[] = { #define X509_OBJ_SIGNATURE 25 /** - * forward declaration - */ -static bool issued_by(private_x509_cert_t *this, certificate_t *issuer); - -/** * Parses an X.509v3 certificate */ static bool parse_certificate(private_x509_cert_t *this) @@ -992,7 +1392,8 @@ static bool parse_certificate(private_x509_cert_t *this) parse_basicConstraints(object, level, this); break; case OID_CRL_DISTRIBUTION_POINTS: - parse_crlDistributionPoints(object, level, this); + x509_parse_crlDistributionPoints(object, level, + this->crl_uris); break; case OID_AUTHORITY_KEY_ID: this->authKeyIdentifier = x509_parse_authorityKeyIdentifier(object, @@ -1002,7 +1403,7 @@ static bool parse_certificate(private_x509_cert_t *this) parse_authorityInfoAccess(object, level, this); break; case OID_KEY_USAGE: - /* TODO parse the flags */ + parse_keyUsage(object, this); break; case OID_EXTENDED_KEY_USAGE: parse_extendedKeyUsage(object, level, this); @@ -1010,6 +1411,26 @@ static bool parse_certificate(private_x509_cert_t *this) case OID_IP_ADDR_BLOCKS: parse_ipAddrBlocks(object, level, this); break; + case OID_NAME_CONSTRAINTS: + parse_nameConstraints(object, level, this); + break; + case OID_CERTIFICATE_POLICIES: + parse_certificatePolicies(object, level, this); + break; + case OID_POLICY_MAPPINGS: + parse_policyMappings(object, level, this); + break; + case OID_POLICY_CONSTRAINTS: + parse_policyConstraints(object, level, this); + break; + case OID_INHIBIT_ANY_POLICY: + if (!asn1_parse_simple_object(&object, ASN1_INTEGER, + level, "inhibitAnyPolicy")) + { + goto end; + } + this->inhibit_any = parse_constraint(object); + break; case OID_NS_REVOCATION_URL: case OID_NS_CA_REVOCATION_URL: case OID_NS_CA_POLICY_URL: @@ -1022,9 +1443,9 @@ static bool parse_certificate(private_x509_cert_t *this) break; default: if (critical && lib->settings->get_bool(lib->settings, - "libstrongswan.plugins.x509.enforce_critical", FALSE)) + "libstrongswan.x509.enforce_critical", TRUE)) { - DBG1(DBG_LIB, "critical %s extension not supported", + DBG1(DBG_LIB, "critical '%s' extension not supported", (extn_oid == OID_UNKNOWN) ? "unknown" : (char*)oid_names[extn_oid].name); goto end; @@ -1057,7 +1478,9 @@ end: hasher_t *hasher; /* check if the certificate is self-signed */ - if (issued_by(this, &this->public.interface.interface)) + if (this->public.interface.interface.issued_by( + &this->public.interface.interface, + &this->public.interface.interface)) { this->flags |= X509_SELF_SIGNED; } @@ -1074,34 +1497,26 @@ end: return success; } -/** - * Implementation of certificate_t.get_type - */ -static certificate_type_t get_type(private_x509_cert_t *this) +METHOD(certificate_t, get_type, certificate_type_t, + private_x509_cert_t *this) { return CERT_X509; } -/** - * Implementation of certificate_t.get_subject - */ -static identification_t* get_subject(private_x509_cert_t *this) +METHOD(certificate_t, get_subject, identification_t*, + private_x509_cert_t *this) { return this->subject; } -/** - * Implementation of certificate_t.get_issuer - */ -static identification_t* get_issuer(private_x509_cert_t *this) +METHOD(certificate_t, get_issuer, identification_t*, + private_x509_cert_t *this) { return this->issuer; } -/** - * Implementation of certificate_t.has_subject. - */ -static id_match_t has_subject(private_x509_cert_t *this, identification_t *subject) +METHOD(certificate_t, has_subject, id_match_t, + private_x509_cert_t *this, identification_t *subject) { identification_t *current; enumerator_t *enumerator; @@ -1142,19 +1557,15 @@ static id_match_t has_subject(private_x509_cert_t *this, identification_t *subje return best; } -/** - * Implementation of certificate_t.has_issuer. - */ -static id_match_t has_issuer(private_x509_cert_t *this, identification_t *issuer) +METHOD(certificate_t, has_issuer, id_match_t, + private_x509_cert_t *this, identification_t *issuer) { /* issuerAltNames currently not supported */ return this->issuer->matches(this->issuer, issuer); } -/** - * Implementation of certificate_t.issued_by. - */ -static bool issued_by(private_x509_cert_t *this, certificate_t *issuer) +METHOD(certificate_t, issued_by, bool, + private_x509_cert_t *this, certificate_t *issuer) { public_key_t *key; signature_scheme_t scheme; @@ -1201,37 +1612,23 @@ static bool issued_by(private_x509_cert_t *this, certificate_t *issuer) return valid; } -/** - * Implementation of certificate_t.get_public_key - */ -static public_key_t* get_public_key(private_x509_cert_t *this) +METHOD(certificate_t, get_public_key, public_key_t*, + private_x509_cert_t *this) { this->public_key->get_ref(this->public_key); return this->public_key; } -/** - * Implementation of certificate_t.get_ref - */ -static private_x509_cert_t* get_ref(private_x509_cert_t *this) +METHOD(certificate_t, get_ref, certificate_t*, + private_x509_cert_t *this) { ref_get(&this->ref); - return this; + return &this->public.interface.interface; } -/** - * Implementation of x509_cert_t.get_flags. - */ -static x509_flag_t get_flags(private_x509_cert_t *this) -{ - return this->flags; -} - -/** - * Implementation of x509_cert_t.get_validity. - */ -static bool get_validity(private_x509_cert_t *this, time_t *when, - time_t *not_before, time_t *not_after) +METHOD(certificate_t, get_validity, bool, + private_x509_cert_t *this, time_t *when, time_t *not_before, + time_t *not_after) { time_t t = when ? *when : time(NULL); @@ -1246,11 +1643,8 @@ static bool get_validity(private_x509_cert_t *this, time_t *when, return (t >= this->notBefore && t <= this->notAfter); } -/** - * Implementation of certificate_t.get_encoding. - */ -static bool get_encoding(private_x509_cert_t *this, cred_encoding_type_t type, - chunk_t *encoding) +METHOD(certificate_t, get_encoding, bool, + private_x509_cert_t *this, cred_encoding_type_t type, chunk_t *encoding) { if (type == CERT_ASN1_DER) { @@ -1261,10 +1655,8 @@ static bool get_encoding(private_x509_cert_t *this, cred_encoding_type_t type, CRED_PART_X509_ASN1_DER, this->encoding, CRED_PART_END); } -/** - * Implementation of certificate_t.equals. - */ -static bool equals(private_x509_cert_t *this, certificate_t *other) +METHOD(certificate_t, equals, bool, + private_x509_cert_t *this, certificate_t *other) { chunk_t encoding; bool equal; @@ -1290,18 +1682,20 @@ static bool equals(private_x509_cert_t *this, certificate_t *other) return equal; } -/** - * Implementation of x509_t.get_serial. - */ -static chunk_t get_serial(private_x509_cert_t *this) +METHOD(x509_t, get_flags, x509_flag_t, + private_x509_cert_t *this) +{ + return this->flags; +} + +METHOD(x509_t, get_serial, chunk_t, + private_x509_cert_t *this) { return this->serialNumber; } -/** - * Implementation of x509_t.get_subjectKeyIdentifier. - */ -static chunk_t get_subjectKeyIdentifier(private_x509_cert_t *this) +METHOD(x509_t, get_subjectKeyIdentifier, chunk_t, + private_x509_cert_t *this) { if (this->subjectKeyIdentifier.ptr) { @@ -1323,66 +1717,95 @@ static chunk_t get_subjectKeyIdentifier(private_x509_cert_t *this) } } -/** - * Implementation of x509_t.get_authKeyIdentifier. - */ -static chunk_t get_authKeyIdentifier(private_x509_cert_t *this) +METHOD(x509_t, get_authKeyIdentifier, chunk_t, + private_x509_cert_t *this) { return this->authKeyIdentifier; } -/** - * Implementation of x509_t.get_pathLenConstraint. - */ -static int get_pathLenConstraint(private_x509_cert_t *this) +METHOD(x509_t, get_constraint, u_int, + private_x509_cert_t *this, x509_constraint_t type) { - return this->pathLenConstraint; + switch (type) + { + case X509_PATH_LEN: + return this->pathLenConstraint; + case X509_REQUIRE_EXPLICIT_POLICY: + return this->require_explicit; + case X509_INHIBIT_POLICY_MAPPING: + return this->inhibit_mapping; + case X509_INHIBIT_ANY_POLICY: + return this->inhibit_any; + default: + return X509_NO_CONSTRAINT; + } } -/** - * Implementation of x509_cert_t.create_subjectAltName_enumerator. - */ -static enumerator_t* create_subjectAltName_enumerator(private_x509_cert_t *this) +METHOD(x509_t, create_subjectAltName_enumerator, enumerator_t*, + private_x509_cert_t *this) { return this->subjectAltNames->create_enumerator(this->subjectAltNames); } -/** - * Implementation of x509_cert_t.create_ocsp_uri_enumerator. - */ -static enumerator_t* create_ocsp_uri_enumerator(private_x509_cert_t *this) +METHOD(x509_t, create_ocsp_uri_enumerator, enumerator_t*, + private_x509_cert_t *this) { return this->ocsp_uris->create_enumerator(this->ocsp_uris); } -/** - * Implementation of x509_cert_t.create_crl_uri_enumerator. - */ -static enumerator_t* create_crl_uri_enumerator(private_x509_cert_t *this) +METHOD(x509_t, create_crl_uri_enumerator, enumerator_t*, + private_x509_cert_t *this) { return this->crl_uris->create_enumerator(this->crl_uris); } -/** - * Implementation of x509_cert_t.create_ipAddrBlock_enumerator. - */ -static enumerator_t* create_ipAddrBlock_enumerator(private_x509_cert_t *this) +METHOD(x509_t, create_ipAddrBlock_enumerator, enumerator_t*, + private_x509_cert_t *this) { return this->ipAddrBlocks->create_enumerator(this->ipAddrBlocks); } -/** - * Implementation of certificate_t.destroy. - */ -static void destroy(private_x509_cert_t *this) +METHOD(x509_t, create_name_constraint_enumerator, enumerator_t*, + private_x509_cert_t *this, bool perm) +{ + if (perm) + { + return this->permitted_names->create_enumerator(this->permitted_names); + } + return this->excluded_names->create_enumerator(this->excluded_names); +} + +METHOD(x509_t, create_cert_policy_enumerator, enumerator_t*, + private_x509_cert_t *this) +{ + return this->cert_policies->create_enumerator(this->cert_policies); +} + +METHOD(x509_t, create_policy_mapping_enumerator, enumerator_t*, + private_x509_cert_t *this) +{ + return this->policy_mappings->create_enumerator(this->policy_mappings); +} + +METHOD(certificate_t, destroy, void, + private_x509_cert_t *this) { if (ref_put(&this->ref)) { this->subjectAltNames->destroy_offset(this->subjectAltNames, offsetof(identification_t, destroy)); - this->crl_uris->destroy_function(this->crl_uris, free); + this->crl_uris->destroy_function(this->crl_uris, (void*)crl_uri_destroy); this->ocsp_uris->destroy_function(this->ocsp_uris, free); - this->ipAddrBlocks->destroy_offset(this->ipAddrBlocks, offsetof(traffic_selector_t, destroy)); + this->ipAddrBlocks->destroy_offset(this->ipAddrBlocks, + offsetof(traffic_selector_t, destroy)); + this->permitted_names->destroy_offset(this->permitted_names, + offsetof(identification_t, destroy)); + this->excluded_names->destroy_offset(this->excluded_names, + offsetof(identification_t, destroy)); + this->cert_policies->destroy_function(this->cert_policies, + (void*)cert_policy_destroy); + this->policy_mappings->destroy_function(this->policy_mappings, + (void*)policy_mapping_destroy); DESTROY_IF(this->issuer); DESTROY_IF(this->subject); DESTROY_IF(this->public_key); @@ -1404,63 +1827,93 @@ static void destroy(private_x509_cert_t *this) */ static private_x509_cert_t* create_empty(void) { - private_x509_cert_t *this = malloc_thing(private_x509_cert_t); - - this->public.interface.interface.get_type = (certificate_type_t (*) (certificate_t*))get_type; - this->public.interface.interface.get_subject = (identification_t* (*) (certificate_t*))get_subject; - this->public.interface.interface.get_issuer = (identification_t* (*) (certificate_t*))get_issuer; - this->public.interface.interface.has_subject = (id_match_t (*) (certificate_t*, identification_t*))has_subject; - this->public.interface.interface.has_issuer = (id_match_t (*) (certificate_t*, identification_t*))has_issuer; - this->public.interface.interface.issued_by = (bool (*) (certificate_t*, certificate_t*))issued_by; - this->public.interface.interface.get_public_key = (public_key_t* (*) (certificate_t*))get_public_key; - this->public.interface.interface.get_validity = (bool (*) (certificate_t*, time_t*, time_t*, time_t*))get_validity; - this->public.interface.interface.get_encoding = (bool (*) (certificate_t*,cred_encoding_type_t,chunk_t*))get_encoding; - this->public.interface.interface.equals = (bool (*)(certificate_t*, certificate_t*))equals; - this->public.interface.interface.get_ref = (certificate_t* (*)(certificate_t*))get_ref; - this->public.interface.interface.destroy = (void (*)(certificate_t*))destroy; - this->public.interface.get_flags = (x509_flag_t (*)(x509_t*))get_flags; - this->public.interface.get_serial = (chunk_t (*)(x509_t*))get_serial; - this->public.interface.get_subjectKeyIdentifier = (chunk_t (*)(x509_t*))get_subjectKeyIdentifier; - this->public.interface.get_authKeyIdentifier = (chunk_t (*)(x509_t*))get_authKeyIdentifier; - this->public.interface.get_pathLenConstraint = (int (*)(x509_t*))get_pathLenConstraint; - this->public.interface.create_subjectAltName_enumerator = (enumerator_t* (*)(x509_t*))create_subjectAltName_enumerator; - this->public.interface.create_crl_uri_enumerator = (enumerator_t* (*)(x509_t*))create_crl_uri_enumerator; - this->public.interface.create_ocsp_uri_enumerator = (enumerator_t* (*)(x509_t*))create_ocsp_uri_enumerator; - this->public.interface.create_ipAddrBlock_enumerator = (enumerator_t* (*)(x509_t*))create_ipAddrBlock_enumerator; - - this->encoding = chunk_empty; - this->encoding_hash = chunk_empty; - this->tbsCertificate = chunk_empty; - this->version = 1; - this->serialNumber = chunk_empty; - this->notBefore = 0; - this->notAfter = 0; - this->public_key = NULL; - this->subject = NULL; - this->issuer = NULL; - this->subjectAltNames = linked_list_create(); - this->crl_uris = linked_list_create(); - this->ocsp_uris = linked_list_create(); - this->ipAddrBlocks = linked_list_create(); - this->subjectKeyIdentifier = chunk_empty; - this->authKeyIdentifier = chunk_empty; - this->authKeySerialNumber = chunk_empty; - this->pathLenConstraint = X509_NO_PATH_LEN_CONSTRAINT; - this->algorithm = 0; - this->signature = chunk_empty; - this->flags = 0; - this->ref = 1; - this->parsed = FALSE; - + private_x509_cert_t *this; + + INIT(this, + .public = { + .interface = { + .interface = { + .get_type = _get_type, + .get_subject = _get_subject, + .get_issuer = _get_issuer, + .has_subject = _has_subject, + .has_issuer = _has_issuer, + .issued_by = _issued_by, + .get_public_key = _get_public_key, + .get_validity = _get_validity, + .get_encoding = _get_encoding, + .equals = _equals, + .get_ref = _get_ref, + .destroy = _destroy, + }, + .get_flags = _get_flags, + .get_serial = _get_serial, + .get_subjectKeyIdentifier = _get_subjectKeyIdentifier, + .get_authKeyIdentifier = _get_authKeyIdentifier, + .get_constraint = _get_constraint, + .create_subjectAltName_enumerator = _create_subjectAltName_enumerator, + .create_crl_uri_enumerator = _create_crl_uri_enumerator, + .create_ocsp_uri_enumerator = _create_ocsp_uri_enumerator, + .create_ipAddrBlock_enumerator = _create_ipAddrBlock_enumerator, + .create_name_constraint_enumerator = _create_name_constraint_enumerator, + .create_cert_policy_enumerator = _create_cert_policy_enumerator, + .create_policy_mapping_enumerator = _create_policy_mapping_enumerator, + }, + }, + .version = 1, + .subjectAltNames = linked_list_create(), + .crl_uris = linked_list_create(), + .ocsp_uris = linked_list_create(), + .ipAddrBlocks = linked_list_create(), + .permitted_names = linked_list_create(), + .excluded_names = linked_list_create(), + .cert_policies = linked_list_create(), + .policy_mappings = linked_list_create(), + .pathLenConstraint = X509_NO_CONSTRAINT, + .require_explicit = X509_NO_CONSTRAINT, + .inhibit_mapping = X509_NO_CONSTRAINT, + .inhibit_any = X509_NO_CONSTRAINT, + .ref = 1, + ); return this; } /** + * Build a generalName from an id + */ +chunk_t build_generalName(identification_t *id) +{ + int context; + + switch (id->get_type(id)) + { + case ID_RFC822_ADDR: + context = ASN1_CONTEXT_S_1; + break; + case ID_FQDN: + context = ASN1_CONTEXT_S_2; + break; + case ID_DER_ASN1_DN: + context = ASN1_CONTEXT_C_4; + break; + case ID_IPV4_ADDR: + case ID_IPV6_ADDR: + context = ASN1_CONTEXT_S_7; + break; + default: + DBG1(DBG_LIB, "encoding %N as generalName not supported", + id_type_names, id->get_type(id)); + return chunk_empty; + } + return asn1_wrap(context, "c", id->get_encoding(id)); +} + +/** * Encode a linked list of subjectAltNames */ chunk_t x509_build_subjectAltNames(linked_list_t *list) { - chunk_t subjectAltNames = chunk_empty; + chunk_t subjectAltNames = chunk_empty, name; enumerator_t *enumerator; identification_t *id; @@ -1472,29 +1925,7 @@ chunk_t x509_build_subjectAltNames(linked_list_t *list) enumerator = list->create_enumerator(list); while (enumerator->enumerate(enumerator, &id)) { - int context; - chunk_t name; - - switch (id->get_type(id)) - { - case ID_RFC822_ADDR: - context = ASN1_CONTEXT_S_1; - break; - case ID_FQDN: - context = ASN1_CONTEXT_S_2; - break; - case ID_IPV4_ADDR: - case ID_IPV6_ADDR: - context = ASN1_CONTEXT_S_7; - break; - default: - DBG1(DBG_LIB, "encoding %N as subjectAltName not supported", - id_type_names, id->get_type(id)); - enumerator->destroy(enumerator); - free(subjectAltNames.ptr); - return chunk_empty; - } - name = asn1_wrap(context, "c", id->get_encoding(id)); + name = build_generalName(id); subjectAltNames = chunk_cat("mm", subjectAltNames, name); } enumerator->destroy(enumerator); @@ -1508,6 +1939,47 @@ chunk_t x509_build_subjectAltNames(linked_list_t *list) } /** + * Encode CRL distribution points extension from a x509_cdp_t list + */ +chunk_t x509_build_crlDistributionPoints(linked_list_t *list, int extn) +{ + chunk_t crlDistributionPoints = chunk_empty; + enumerator_t *enumerator; + x509_cdp_t *cdp; + + if (list->get_count(list) == 0) + { + return chunk_empty; + } + + enumerator = list->create_enumerator(list); + while (enumerator->enumerate(enumerator, &cdp)) + { + chunk_t distributionPoint, crlIssuer = chunk_empty; + + if (cdp->issuer) + { + crlIssuer = asn1_wrap(ASN1_CONTEXT_C_2, "m", + build_generalName(cdp->issuer)); + } + distributionPoint = asn1_wrap(ASN1_SEQUENCE, "mm", + asn1_wrap(ASN1_CONTEXT_C_0, "m", + asn1_wrap(ASN1_CONTEXT_C_0, "m", + asn1_wrap(ASN1_CONTEXT_S_6, "c", + chunk_create(cdp->uri, strlen(cdp->uri))))), + crlIssuer); + crlDistributionPoints = chunk_cat("mm", crlDistributionPoints, + distributionPoint); + } + enumerator->destroy(enumerator); + + return asn1_wrap(ASN1_SEQUENCE, "mm", + asn1_build_known_oid(extn), + asn1_wrap(ASN1_OCTET_STRING, "m", + asn1_wrap(ASN1_SEQUENCE, "m", crlDistributionPoints))); +} + +/** * Generate and sign a new certificate */ static bool generate(private_x509_cert_t *cert, certificate_t *sign_cert, @@ -1515,12 +1987,13 @@ static bool generate(private_x509_cert_t *cert, certificate_t *sign_cert, { chunk_t extensions = chunk_empty, extendedKeyUsage = chunk_empty; chunk_t serverAuth = chunk_empty, clientAuth = chunk_empty; - chunk_t ocspSigning = chunk_empty; - chunk_t basicConstraints = chunk_empty; - chunk_t keyUsage = chunk_empty; - chunk_t subjectAltNames = chunk_empty; + chunk_t ocspSigning = chunk_empty, certPolicies = chunk_empty; + chunk_t basicConstraints = chunk_empty, nameConstraints = chunk_empty; + chunk_t keyUsage = chunk_empty, keyUsageBits = chunk_empty; + chunk_t subjectAltNames = chunk_empty, policyMappings = chunk_empty; chunk_t subjectKeyIdentifier = chunk_empty, authKeyIdentifier = chunk_empty; chunk_t crlDistributionPoints = chunk_empty, authorityInfoAccess = chunk_empty; + chunk_t policyConstraints = chunk_empty, inhibitAnyPolicy = chunk_empty; identification_t *issuer, *subject; chunk_t key_info; signature_scheme_t scheme; @@ -1574,29 +2047,8 @@ static bool generate(private_x509_cert_t *cert, certificate_t *sign_cert, /* encode subjectAltNames */ subjectAltNames = x509_build_subjectAltNames(cert->subjectAltNames); - /* encode CRL distribution points extension */ - enumerator = cert->crl_uris->create_enumerator(cert->crl_uris); - while (enumerator->enumerate(enumerator, &uri)) - { - chunk_t distributionPoint; - - distributionPoint = asn1_wrap(ASN1_SEQUENCE, "m", - asn1_wrap(ASN1_CONTEXT_C_0, "m", - asn1_wrap(ASN1_CONTEXT_C_0, "m", - asn1_wrap(ASN1_CONTEXT_S_6, "c", - chunk_create(uri, strlen(uri)))))); - - crlDistributionPoints = chunk_cat("mm", crlDistributionPoints, - distributionPoint); - } - enumerator->destroy(enumerator); - if (crlDistributionPoints.ptr) - { - crlDistributionPoints = asn1_wrap(ASN1_SEQUENCE, "mm", - asn1_build_known_oid(OID_CRL_DISTRIBUTION_POINTS), - asn1_wrap(ASN1_OCTET_STRING, "m", - asn1_wrap(ASN1_SEQUENCE, "m", crlDistributionPoints))); - } + crlDistributionPoints = x509_build_crlDistributionPoints(cert->crl_uris, + OID_CRL_DISTRIBUTION_POINTS); /* encode OCSP URIs in authorityInfoAccess extension */ enumerator = cert->ocsp_uris->create_enumerator(cert->ocsp_uris); @@ -1625,11 +2077,10 @@ static bool generate(private_x509_cert_t *cert, certificate_t *sign_cert, { chunk_t pathLenConstraint = chunk_empty; - if (cert->pathLenConstraint != X509_NO_PATH_LEN_CONSTRAINT) + if (cert->pathLenConstraint != X509_NO_CONSTRAINT) { - char pathlen = (char)cert->pathLenConstraint; - - pathLenConstraint = asn1_integer("c", chunk_from_thing(pathlen)); + pathLenConstraint = asn1_integer("c", + chunk_from_thing(cert->pathLenConstraint)); } basicConstraints = asn1_wrap(ASN1_SEQUENCE, "mmm", asn1_build_known_oid(OID_BASIC_CONSTRAINTS), @@ -1640,13 +2091,20 @@ static bool generate(private_x509_cert_t *cert, certificate_t *sign_cert, asn1_wrap(ASN1_BOOLEAN, "c", chunk_from_chars(0xFF)), pathLenConstraint))); + /* set CertificateSign and implicitly CRLsign */ + keyUsageBits = chunk_from_chars(0x01, 0x06); + } + else if (cert->flags & X509_CRL_SIGN) + { + keyUsageBits = chunk_from_chars(0x01, 0x02); + } + if (keyUsageBits.len) + { keyUsage = asn1_wrap(ASN1_SEQUENCE, "mmm", - asn1_build_known_oid(OID_KEY_USAGE), - asn1_wrap(ASN1_BOOLEAN, "c", - chunk_from_chars(0xFF)), - asn1_wrap(ASN1_OCTET_STRING, "m", - asn1_wrap(ASN1_BIT_STRING, "c", - chunk_from_chars(0x01, 0x06)))); + asn1_build_known_oid(OID_KEY_USAGE), + asn1_wrap(ASN1_BOOLEAN, "c", chunk_from_chars(0xFF)), + asn1_wrap(ASN1_OCTET_STRING, "m", + asn1_wrap(ASN1_BIT_STRING, "c", keyUsageBits))); } /* add serverAuth extendedKeyUsage flag */ @@ -1675,7 +2133,7 @@ static bool generate(private_x509_cert_t *cert, certificate_t *sign_cert, } /* add subjectKeyIdentifier to CA and OCSP signer certificates */ - if (cert->flags & (X509_CA | X509_OCSP_SIGNER)) + if (cert->flags & (X509_CA | X509_OCSP_SIGNER | X509_CRL_SIGN)) { chunk_t keyid; @@ -1703,15 +2161,153 @@ static bool generate(private_x509_cert_t *cert, certificate_t *sign_cert, asn1_wrap(ASN1_CONTEXT_S_0, "c", keyid)))); } } + + if (cert->permitted_names->get_count(cert->permitted_names) || + cert->excluded_names->get_count(cert->excluded_names)) + { + chunk_t permitted = chunk_empty, excluded = chunk_empty, subtree; + identification_t *id; + + enumerator = create_name_constraint_enumerator(cert, TRUE); + while (enumerator->enumerate(enumerator, &id)) + { + subtree = asn1_wrap(ASN1_SEQUENCE, "m", build_generalName(id)); + permitted = chunk_cat("mm", permitted, subtree); + } + enumerator->destroy(enumerator); + if (permitted.ptr) + { + permitted = asn1_wrap(ASN1_CONTEXT_C_0, "m", permitted); + } + + enumerator = create_name_constraint_enumerator(cert, FALSE); + while (enumerator->enumerate(enumerator, &id)) + { + subtree = asn1_wrap(ASN1_SEQUENCE, "m", build_generalName(id)); + excluded = chunk_cat("mm", excluded, subtree); + } + enumerator->destroy(enumerator); + if (excluded.ptr) + { + excluded = asn1_wrap(ASN1_CONTEXT_C_1, "m", excluded); + } + + nameConstraints = asn1_wrap(ASN1_SEQUENCE, "mm", + asn1_build_known_oid(OID_NAME_CONSTRAINTS), + asn1_wrap(ASN1_OCTET_STRING, "m", + asn1_wrap(ASN1_SEQUENCE, "mm", + permitted, excluded))); + } + + if (cert->cert_policies->get_count(cert->cert_policies)) + { + x509_cert_policy_t *policy; + + enumerator = create_cert_policy_enumerator(cert); + while (enumerator->enumerate(enumerator, &policy)) + { + chunk_t chunk = chunk_empty, cps = chunk_empty, notice = chunk_empty; + + if (policy->cps_uri) + { + cps = asn1_wrap(ASN1_SEQUENCE, "mm", + asn1_build_known_oid(OID_POLICY_QUALIFIER_CPS), + asn1_wrap(ASN1_IA5STRING, "c", + chunk_create(policy->cps_uri, + strlen(policy->cps_uri)))); + } + if (policy->unotice_text) + { + notice = asn1_wrap(ASN1_SEQUENCE, "mm", + asn1_build_known_oid(OID_POLICY_QUALIFIER_UNOTICE), + asn1_wrap(ASN1_SEQUENCE, "m", + asn1_wrap(ASN1_VISIBLESTRING, "c", + chunk_create(policy->unotice_text, + strlen(policy->unotice_text))))); + } + if (cps.len || notice.len) + { + chunk = asn1_wrap(ASN1_SEQUENCE, "mm", cps, notice); + } + chunk = asn1_wrap(ASN1_SEQUENCE, "mm", + asn1_wrap(ASN1_OID, "c", policy->oid), chunk); + certPolicies = chunk_cat("mm", certPolicies, chunk); + } + enumerator->destroy(enumerator); + + certPolicies = asn1_wrap(ASN1_SEQUENCE, "mm", + asn1_build_known_oid(OID_CERTIFICATE_POLICIES), + asn1_wrap(ASN1_OCTET_STRING, "m", + asn1_wrap(ASN1_SEQUENCE, "m", certPolicies))); + } + + if (cert->policy_mappings->get_count(cert->policy_mappings)) + { + x509_policy_mapping_t *mapping; + + enumerator = create_policy_mapping_enumerator(cert); + while (enumerator->enumerate(enumerator, &mapping)) + { + chunk_t chunk; + + chunk = asn1_wrap(ASN1_SEQUENCE, "mm", + asn1_wrap(ASN1_OID, "c", mapping->issuer), + asn1_wrap(ASN1_OID, "c", mapping->subject)); + policyMappings = chunk_cat("mm", policyMappings, chunk); + } + enumerator->destroy(enumerator); + + policyMappings = asn1_wrap(ASN1_SEQUENCE, "mm", + asn1_build_known_oid(OID_POLICY_MAPPINGS), + asn1_wrap(ASN1_OCTET_STRING, "m", + asn1_wrap(ASN1_SEQUENCE, "m", policyMappings))); + } + + if (cert->inhibit_mapping != X509_NO_CONSTRAINT || + cert->require_explicit != X509_NO_CONSTRAINT) + { + chunk_t inhibit = chunk_empty, explicit = chunk_empty; + + if (cert->require_explicit != X509_NO_CONSTRAINT) + { + explicit = asn1_wrap(ASN1_CONTEXT_C_0, "m", + asn1_integer("c", + chunk_from_thing(cert->require_explicit))); + } + if (cert->inhibit_mapping != X509_NO_CONSTRAINT) + { + inhibit = asn1_wrap(ASN1_CONTEXT_C_1, "m", + asn1_integer("c", + chunk_from_thing(cert->inhibit_mapping))); + } + policyConstraints = asn1_wrap(ASN1_SEQUENCE, "mmm", + asn1_build_known_oid(OID_POLICY_CONSTRAINTS), + asn1_wrap(ASN1_BOOLEAN, "c", chunk_from_chars(0xFF)), + asn1_wrap(ASN1_OCTET_STRING, "m", + asn1_wrap(ASN1_SEQUENCE, "mm", + explicit, inhibit))); + } + + if (cert->inhibit_any != X509_NO_CONSTRAINT) + { + inhibitAnyPolicy = asn1_wrap(ASN1_SEQUENCE, "mmm", + asn1_build_known_oid(OID_INHIBIT_ANY_POLICY), + asn1_wrap(ASN1_BOOLEAN, "c", chunk_from_chars(0xFF)), + asn1_wrap(ASN1_OCTET_STRING, "m", + asn1_integer("c", + chunk_from_thing(cert->inhibit_any)))); + } + if (basicConstraints.ptr || subjectAltNames.ptr || authKeyIdentifier.ptr || - crlDistributionPoints.ptr) + crlDistributionPoints.ptr || nameConstraints.ptr) { extensions = asn1_wrap(ASN1_CONTEXT_C_3, "m", - asn1_wrap(ASN1_SEQUENCE, "mmmmmmmm", + asn1_wrap(ASN1_SEQUENCE, "mmmmmmmmmmmmm", basicConstraints, keyUsage, subjectKeyIdentifier, authKeyIdentifier, subjectAltNames, extendedKeyUsage, crlDistributionPoints, - authorityInfoAccess)); + authorityInfoAccess, nameConstraints, certPolicies, + policyMappings, policyConstraints, inhibitAnyPolicy)); } cert->tbsCertificate = asn1_wrap(ASN1_SEQUENCE, "mmmcmcmm", @@ -1794,6 +2390,7 @@ x509_cert_t *x509_cert_gen(certificate_type_t type, va_list args) certificate_t *sign_cert = NULL; private_key_t *sign_key = NULL; hash_algorithm_t digest_alg = HASH_SHA1; + u_int constraint; cert = create_empty(); while (TRUE) @@ -1837,13 +2434,17 @@ x509_cert_t *x509_cert_gen(certificate_type_t type, va_list args) { enumerator_t *enumerator; linked_list_t *list; - char *uri; + x509_cdp_t *in, *cdp; list = va_arg(args, linked_list_t*); enumerator = list->create_enumerator(list); - while (enumerator->enumerate(enumerator, &uri)) + while (enumerator->enumerate(enumerator, &in)) { - cert->crl_uris->insert_last(cert->crl_uris, strdup(uri)); + INIT(cdp, + .uri = strdup(in->uri), + .issuer = in->issuer ? in->issuer->clone(in->issuer) : NULL, + ); + cert->crl_uris->insert_last(cert->crl_uris, cdp); } enumerator->destroy(enumerator); continue; @@ -1864,11 +2465,96 @@ x509_cert_t *x509_cert_gen(certificate_type_t type, va_list args) continue; } case BUILD_PATHLEN: - cert->pathLenConstraint = va_arg(args, int); - if (cert->pathLenConstraint < 0 || cert->pathLenConstraint > 127) + constraint = va_arg(args, u_int); + cert->pathLenConstraint = (constraint < 128) ? + constraint : X509_NO_CONSTRAINT; + continue; + case BUILD_PERMITTED_NAME_CONSTRAINTS: + { + enumerator_t *enumerator; + linked_list_t *list; + identification_t *constraint; + + list = va_arg(args, linked_list_t*); + enumerator = list->create_enumerator(list); + while (enumerator->enumerate(enumerator, &constraint)) + { + cert->permitted_names->insert_last(cert->permitted_names, + constraint->clone(constraint)); + } + enumerator->destroy(enumerator); + continue; + } + case BUILD_EXCLUDED_NAME_CONSTRAINTS: + { + enumerator_t *enumerator; + linked_list_t *list; + identification_t *constraint; + + list = va_arg(args, linked_list_t*); + enumerator = list->create_enumerator(list); + while (enumerator->enumerate(enumerator, &constraint)) + { + cert->excluded_names->insert_last(cert->excluded_names, + constraint->clone(constraint)); + } + enumerator->destroy(enumerator); + continue; + } + case BUILD_CERTIFICATE_POLICIES: + { + enumerator_t *enumerator; + linked_list_t *list; + x509_cert_policy_t *policy, *in; + + list = va_arg(args, linked_list_t*); + enumerator = list->create_enumerator(list); + while (enumerator->enumerate(enumerator, &in)) + { + INIT(policy, + .oid = chunk_clone(in->oid), + .cps_uri = strdupnull(in->cps_uri), + .unotice_text = strdupnull(in->unotice_text), + ); + cert->cert_policies->insert_last(cert->cert_policies, policy); + } + enumerator->destroy(enumerator); + continue; + } + case BUILD_POLICY_MAPPINGS: + { + enumerator_t *enumerator; + linked_list_t *list; + x509_policy_mapping_t* mapping, *in; + + list = va_arg(args, linked_list_t*); + enumerator = list->create_enumerator(list); + while (enumerator->enumerate(enumerator, &in)) { - cert->pathLenConstraint = X509_NO_PATH_LEN_CONSTRAINT; + INIT(mapping, + .issuer = chunk_clone(in->issuer), + .subject = chunk_clone(in->subject), + ); + cert->policy_mappings->insert_last(cert->policy_mappings, + mapping); } + enumerator->destroy(enumerator); + continue; + } + case BUILD_POLICY_REQUIRE_EXPLICIT: + constraint = va_arg(args, u_int); + cert->require_explicit = (constraint < 128) ? + constraint : X509_NO_CONSTRAINT; + continue; + case BUILD_POLICY_INHIBIT_MAPPING: + constraint = va_arg(args, u_int); + cert->inhibit_mapping = (constraint < 128) ? + constraint : X509_NO_CONSTRAINT; + continue; + case BUILD_POLICY_INHIBIT_ANY: + constraint = va_arg(args, u_int); + cert->inhibit_any = (constraint < 128) ? + constraint : X509_NO_CONSTRAINT; continue; case BUILD_NOT_BEFORE_TIME: cert->notBefore = va_arg(args, time_t); diff --git a/src/libstrongswan/plugins/x509/x509_crl.c b/src/libstrongswan/plugins/x509/x509_crl.c index 4bd0470d3..758505ab5 100644 --- a/src/libstrongswan/plugins/x509/x509_crl.c +++ b/src/libstrongswan/plugins/x509/x509_crl.c @@ -100,6 +100,11 @@ struct private_x509_crl_t { linked_list_t *revoked; /** + * List of Freshest CRL distribution points + */ + linked_list_t *crl_uris; + + /** * Authority Key Identifier */ chunk_t authKeyIdentifier; @@ -110,6 +115,11 @@ struct private_x509_crl_t { chunk_t authKeySerialNumber; /** + * Number of BaseCRL, if a delta CRL + */ + chunk_t baseCrlNumber; + + /** * Signature algorithm */ int algorithm; @@ -133,9 +143,19 @@ struct private_x509_crl_t { /** * from x509_cert */ -extern chunk_t x509_parse_authorityKeyIdentifier( - chunk_t blob, int level0, - chunk_t *authKeySerialNumber); +extern chunk_t x509_parse_authorityKeyIdentifier(chunk_t blob, int level0, + chunk_t *authKeySerialNumber); + +/** + * from x509_cert + */ +extern void x509_parse_crlDistributionPoints(chunk_t blob, int level0, + linked_list_t *list); + +/** + * from x509_cert + */ +extern chunk_t x509_build_crlDistributionPoints(linked_list_t *list, int extn); /** * ASN.1 definition of an X.509 certificate revocation list @@ -206,7 +226,7 @@ static bool parse(private_x509_crl_t *this) int objectID; int sig_alg = OID_UNKNOWN; bool success = FALSE; - bool critical; + bool critical = FALSE; revoked_t *revoked = NULL; parser = asn1_parser_create(crlObjects, this->encoding); @@ -258,35 +278,61 @@ static bool parse(private_x509_crl_t *this) break; case CRL_OBJ_CRL_ENTRY_EXTN_VALUE: case CRL_OBJ_EXTN_VALUE: - { - int extn_oid = asn1_known_oid(extnID); + { + int extn_oid = asn1_known_oid(extnID); - if (revoked && extn_oid == OID_CRL_REASON_CODE) - { - if (*object.ptr == ASN1_ENUMERATED && - asn1_length(&object) == 1) + switch (extn_oid) + { + case OID_CRL_REASON_CODE: + if (revoked) { - revoked->reason = *object.ptr; + if (object.len && *object.ptr == ASN1_ENUMERATED && + asn1_length(&object) == 1) + { + revoked->reason = *object.ptr; + } + DBG2(DBG_LIB, " '%N'", crl_reason_names, + revoked->reason); } - DBG2(DBG_LIB, " '%N'", crl_reason_names, - revoked->reason); - } - else if (extn_oid == OID_AUTHORITY_KEY_ID) - { - this->authKeyIdentifier = x509_parse_authorityKeyIdentifier(object, - level, &this->authKeySerialNumber); - } - else if (extn_oid == OID_CRL_NUMBER) - { + break; + case OID_AUTHORITY_KEY_ID: + this->authKeyIdentifier = + x509_parse_authorityKeyIdentifier( + object, level, &this->authKeySerialNumber); + break; + case OID_CRL_NUMBER: if (!asn1_parse_simple_object(&object, ASN1_INTEGER, level, "crlNumber")) { goto end; } this->crlNumber = object; - } + break; + case OID_FRESHEST_CRL: + x509_parse_crlDistributionPoints(object, level, + this->crl_uris); + break; + case OID_DELTA_CRL_INDICATOR: + if (!asn1_parse_simple_object(&object, ASN1_INTEGER, + level, "deltaCrlIndicator")) + { + goto end; + } + this->baseCrlNumber = object; + break; + default: + if (critical && lib->settings->get_bool(lib->settings, + "libstrongswan.x509.enforce_critical", TRUE)) + { + DBG1(DBG_LIB, "critical '%s' extension not supported", + (extn_oid == OID_UNKNOWN) ? "unknown" : + (char*)oid_names[extn_oid].name); + goto end; + } + break; } break; + } case CRL_OBJ_ALGORITHM: { this->algorithm = asn1_parse_algorithmIdentifier(object, level, NULL); @@ -344,6 +390,26 @@ METHOD(crl_t, get_authKeyIdentifier, chunk_t, return this->authKeyIdentifier; } +METHOD(crl_t, is_delta_crl, bool, + private_x509_crl_t *this, chunk_t *base_crl) +{ + if (this->baseCrlNumber.len) + { + if (base_crl) + { + *base_crl = this->baseCrlNumber; + } + return TRUE; + } + return FALSE; +} + +METHOD(crl_t, create_delta_crl_uri_enumerator, enumerator_t*, + private_x509_crl_t *this) +{ + return this->crl_uris->create_enumerator(this->crl_uris); +} + METHOD(crl_t, create_enumerator, enumerator_t*, private_x509_crl_t *this) { @@ -388,7 +454,7 @@ METHOD(certificate_t, issued_by, bool, { return FALSE; } - if (!(x509->get_flags(x509) & X509_CA)) + if (!(x509->get_flags(x509) & (X509_CA | X509_CRL_SIGN))) { return FALSE; } @@ -501,18 +567,30 @@ static void revoked_destroy(revoked_t *revoked) free(revoked); } +/** + * Destroy a CDP entry + */ +static void cdp_destroy(x509_cdp_t *this) +{ + free(this->uri); + DESTROY_IF(this->issuer); + free(this); +} + METHOD(certificate_t, destroy, void, private_x509_crl_t *this) { if (ref_put(&this->ref)) { this->revoked->destroy_function(this->revoked, (void*)revoked_destroy); + this->crl_uris->destroy_function(this->crl_uris, (void*)cdp_destroy); DESTROY_IF(this->issuer); free(this->authKeyIdentifier.ptr); free(this->encoding.ptr); if (this->generated) { free(this->crlNumber.ptr); + free(this->baseCrlNumber.ptr); free(this->signature.ptr); free(this->tbsCertList.ptr); } @@ -546,10 +624,13 @@ static private_x509_crl_t* create_empty(void) }, .get_serial = _get_serial, .get_authKeyIdentifier = _get_authKeyIdentifier, + .is_delta_crl = _is_delta_crl, + .create_delta_crl_uri_enumerator = _create_delta_crl_uri_enumerator, .create_enumerator = _create_enumerator, }, }, .revoked = linked_list_create(), + .crl_uris = linked_list_create(), .ref = 1, ); return this; @@ -618,6 +699,7 @@ static bool generate(private_x509_crl_t *this, certificate_t *cert, private_key_t *key, hash_algorithm_t digest_alg) { chunk_t extensions = chunk_empty, certList = chunk_empty, serial; + chunk_t crlDistributionPoints = chunk_empty, baseCrlNumber = chunk_empty; enumerator_t *enumerator; crl_reason_t reason; time_t date; @@ -625,7 +707,7 @@ static bool generate(private_x509_crl_t *this, certificate_t *cert, x509 = (x509_t*)cert; - this->issuer = cert->get_issuer(cert); + this->issuer = cert->get_subject(cert); this->issuer = this->issuer->clone(this->issuer); this->authKeyIdentifier = chunk_clone(x509->get_subjectKeyIdentifier(x509)); @@ -660,8 +742,21 @@ static bool generate(private_x509_crl_t *this, certificate_t *cert, } enumerator->destroy(enumerator); + crlDistributionPoints = x509_build_crlDistributionPoints(this->crl_uris, + OID_FRESHEST_CRL); + + if (this->baseCrlNumber.len) + { + baseCrlNumber = asn1_wrap(ASN1_SEQUENCE, "mmm", + asn1_build_known_oid(OID_DELTA_CRL_INDICATOR), + asn1_wrap(ASN1_BOOLEAN, "c", + chunk_from_chars(0xFF)), + asn1_wrap(ASN1_OCTET_STRING, "m", + asn1_integer("c", this->baseCrlNumber))); + } + extensions = asn1_wrap(ASN1_CONTEXT_C_0, "m", - asn1_wrap(ASN1_SEQUENCE, "mm", + asn1_wrap(ASN1_SEQUENCE, "mmmm", asn1_wrap(ASN1_SEQUENCE, "mm", asn1_build_known_oid(OID_AUTHORITY_KEY_ID), asn1_wrap(ASN1_OCTET_STRING, "m", @@ -671,9 +766,8 @@ static bool generate(private_x509_crl_t *this, certificate_t *cert, asn1_wrap(ASN1_SEQUENCE, "mm", asn1_build_known_oid(OID_CRL_NUMBER), asn1_wrap(ASN1_OCTET_STRING, "m", - asn1_integer("c", this->crlNumber)) - ) - )); + asn1_integer("c", this->crlNumber))), + crlDistributionPoints, baseCrlNumber)); this->tbsCertList = asn1_wrap(ASN1_SEQUENCE, "cmcmmmm", ASN1_INTEGER_1, @@ -736,6 +830,29 @@ x509_crl_t *x509_crl_gen(certificate_type_t type, va_list args) case BUILD_REVOKED_ENUMERATOR: read_revoked(crl, va_arg(args, enumerator_t*)); continue; + case BUILD_BASE_CRL: + crl->baseCrlNumber = va_arg(args, chunk_t); + crl->baseCrlNumber = chunk_clone(crl->baseCrlNumber); + break; + case BUILD_CRL_DISTRIBUTION_POINTS: + { + enumerator_t *enumerator; + linked_list_t *list; + x509_cdp_t *in, *cdp; + + list = va_arg(args, linked_list_t*); + enumerator = list->create_enumerator(list); + while (enumerator->enumerate(enumerator, &in)) + { + INIT(cdp, + .uri = strdup(in->uri), + .issuer = in->issuer ? in->issuer->clone(in->issuer) : NULL, + ); + crl->crl_uris->insert_last(crl->crl_uris, cdp); + } + enumerator->destroy(enumerator); + continue; + } case BUILD_END: break; default: diff --git a/src/libstrongswan/plugins/x509/x509_plugin.c b/src/libstrongswan/plugins/x509/x509_plugin.c index 11a7f023c..d40cc3567 100644 --- a/src/libstrongswan/plugins/x509/x509_plugin.c +++ b/src/libstrongswan/plugins/x509/x509_plugin.c @@ -36,10 +36,8 @@ struct private_x509_plugin_t { x509_plugin_t public; }; -/** - * Implementation of x509_plugin_t.x509troy - */ -static void destroy(private_x509_plugin_t *this) +METHOD(plugin_t, destroy, void, + private_x509_plugin_t *this) { lib->creds->remove_builder(lib->creds, (builder_function_t)x509_cert_gen); @@ -69,9 +67,15 @@ static void destroy(private_x509_plugin_t *this) */ plugin_t *x509_plugin_create() { - private_x509_plugin_t *this = malloc_thing(private_x509_plugin_t); + private_x509_plugin_t *this; - this->public.plugin.destroy = (void(*)(plugin_t*))destroy; + INIT(this, + .public = { + .plugin = { + .destroy = _destroy, + }, + }, + ); lib->creds->add_builder(lib->creds, CRED_CERTIFICATE, CERT_X509, FALSE, (builder_function_t)x509_cert_gen); diff --git a/src/libstrongswan/plugins/xcbc/Makefile.in b/src/libstrongswan/plugins/xcbc/Makefile.in index e82e5246f..06d7a2121 100644 --- a/src/libstrongswan/plugins/xcbc/Makefile.in +++ b/src/libstrongswan/plugins/xcbc/Makefile.in @@ -220,9 +220,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -261,6 +259,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libstrongswan/plugins/xcbc/xcbc_plugin.c b/src/libstrongswan/plugins/xcbc/xcbc_plugin.c index 88156f383..65e88335c 100644 --- a/src/libstrongswan/plugins/xcbc/xcbc_plugin.c +++ b/src/libstrongswan/plugins/xcbc/xcbc_plugin.c @@ -19,6 +19,8 @@ #include "xcbc_signer.h" #include "xcbc_prf.h" +static const char *plugin_name = "xcbc"; + typedef struct private_xcbc_plugin_t private_xcbc_plugin_t; /** @@ -48,6 +50,7 @@ METHOD(plugin_t, destroy, void, plugin_t *xcbc_plugin_create() { private_xcbc_plugin_t *this; + crypter_t *crypter; INIT(this, .public = { @@ -57,15 +60,24 @@ plugin_t *xcbc_plugin_create() }, ); - lib->crypto->add_prf(lib->crypto, PRF_AES128_XCBC, - (prf_constructor_t)xcbc_prf_create); - lib->crypto->add_prf(lib->crypto, PRF_CAMELLIA128_XCBC, - (prf_constructor_t)xcbc_prf_create); - lib->crypto->add_signer(lib->crypto, AUTH_AES_XCBC_96, - (signer_constructor_t)xcbc_signer_create); - lib->crypto->add_signer(lib->crypto, AUTH_CAMELLIA_XCBC_96, - (signer_constructor_t)xcbc_signer_create); - + crypter = lib->crypto->create_crypter(lib->crypto, ENCR_AES_CBC, 16); + if (crypter) + { + crypter->destroy(crypter); + lib->crypto->add_prf(lib->crypto, PRF_AES128_XCBC, plugin_name, + (prf_constructor_t)xcbc_prf_create); + lib->crypto->add_signer(lib->crypto, AUTH_AES_XCBC_96, plugin_name, + (signer_constructor_t)xcbc_signer_create); + } + crypter = lib->crypto->create_crypter(lib->crypto, ENCR_CAMELLIA_CBC, 16); + if (crypter) + { + crypter->destroy(crypter); + lib->crypto->add_prf(lib->crypto, PRF_CAMELLIA128_XCBC, plugin_name, + (prf_constructor_t)xcbc_prf_create); + lib->crypto->add_signer(lib->crypto, AUTH_CAMELLIA_XCBC_96, plugin_name, + (signer_constructor_t)xcbc_signer_create); + } return &this->public.plugin; } diff --git a/src/libstrongswan/printf_hook.c b/src/libstrongswan/printf_hook.c index 4d4cef829..7e7045d69 100644 --- a/src/libstrongswan/printf_hook.c +++ b/src/libstrongswan/printf_hook.c @@ -377,10 +377,8 @@ int vstr_wrapper_vasprintf(char **str, const char *format, va_list args) } #endif -/** - * Implementation of printf_hook_t.add_handler. - */ -static void add_handler(private_printf_hook_t *this, char spec, +METHOD(printf_hook_t, add_handler, void, + private_printf_hook_t *this, char spec, printf_hook_function_t hook, ...) { int i = -1; @@ -439,10 +437,8 @@ static void add_handler(private_printf_hook_t *this, char spec, } } -/** - * Implementation of printf_hook_t.destroy - */ -static void destroy(private_printf_hook_t *this) +METHOD(printf_hook_t, destroy, void, + private_printf_hook_t *this) { int i; #ifdef USE_VSTR @@ -477,10 +473,14 @@ static void destroy(private_printf_hook_t *this) */ printf_hook_t *printf_hook_create() { - private_printf_hook_t *this = malloc_thing(private_printf_hook_t); - - this->public.add_handler = (void(*)(printf_hook_t*, char, printf_hook_function_t, ...))add_handler; - this->public.destroy = (void(*)(printf_hook_t*))destroy; + private_printf_hook_t *this; + + INIT(this, + .public = { + .add_handler = _add_handler, + .destroy = _destroy, + }, + ); memset(printf_hooks, 0, sizeof(printf_hooks)); diff --git a/src/libstrongswan/processing/processor.c b/src/libstrongswan/processing/processor.c index 2a44f61e8..723aec908 100644 --- a/src/libstrongswan/processing/processor.c +++ b/src/libstrongswan/processing/processor.c @@ -248,7 +248,7 @@ static void destroy(private_processor_t *this) /* * Described in header. */ -processor_t *processor_create(size_t pool_size) +processor_t *processor_create() { private_processor_t *this = malloc_thing(private_processor_t); diff --git a/src/libstrongswan/selectors/traffic_selector.c b/src/libstrongswan/selectors/traffic_selector.c index 68bbbe2fd..32da194ef 100644 --- a/src/libstrongswan/selectors/traffic_selector.c +++ b/src/libstrongswan/selectors/traffic_selector.c @@ -393,13 +393,15 @@ static bool equals(private_traffic_selector_t *this, private_traffic_selector_t switch (this->type) { case TS_IPV4_ADDR_RANGE: - if (memeq(this->from4, other->from4, sizeof(this->from4))) + if (memeq(this->from4, other->from4, sizeof(this->from4)) && + memeq(this->to4, other->to4, sizeof(this->to4))) { return TRUE; } break; case TS_IPV6_ADDR_RANGE: - if (memeq(this->from6, other->from6, sizeof(this->from6))) + if (memeq(this->from6, other->from6, sizeof(this->from6)) && + memeq(this->to6, other->to6, sizeof(this->to6))) { return TRUE; } diff --git a/src/libstrongswan/settings.c b/src/libstrongswan/settings.c index d85abb1df..bd279f51d 100644 --- a/src/libstrongswan/settings.c +++ b/src/libstrongswan/settings.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2010 Tobias Brunner * Copyright (C) 2008 Martin Willi * Hochschule fuer Technik Rapperswil * @@ -18,12 +19,17 @@ #include <stdarg.h> #include <stdio.h> #include <errno.h> +#include <limits.h> +#include <glob.h> +#include <libgen.h> #include "settings.h" #include "debug.h" #include "utils/linked_list.h" +#include "threading/rwlock.h" +#define MAX_INCLUSION_LEVEL 10 typedef struct private_settings_t private_settings_t; typedef struct section_t section_t; @@ -45,9 +51,14 @@ struct private_settings_t { section_t *top; /** - * allocated file text + * contents of loaded files and in-memory settings (char*) */ - char *text; + linked_list_t *contents; + + /** + * lock to safely access the settings + */ + rwlock_t *lock; }; /** @@ -88,6 +99,69 @@ struct kv_t { }; /** + * create a key/value pair + */ +static kv_t *kv_create(char *key, char *value) +{ + kv_t *this; + INIT(this, + .key = strdup(key), + .value = value, + ); + return this; +} + +/** + * destroy a key/value pair + */ +static void kv_destroy(kv_t *this) +{ + free(this->key); + free(this); +} + +/** + * create a section with the given name + */ +static section_t *section_create(char *name) +{ + section_t *this; + INIT(this, + .name = strdupnull(name), + .sections = linked_list_create(), + .kv = linked_list_create(), + ); + return this; +} + +/** + * destroy a section + */ +static void section_destroy(section_t *this) +{ + this->kv->destroy_function(this->kv, (void*)kv_destroy); + this->sections->destroy_function(this->sections, (void*)section_destroy); + free(this->name); + free(this); +} + +/** + * callback to find a section by name + */ +static bool section_find(section_t *this, char *name) +{ + return streq(this->name, name); +} + +/** + * callback to find a kv pair by key + */ +static bool kv_find(kv_t *this, char *key) +{ + return streq(this->key, key); +} + +/** * Print a format key, but consume already processed arguments */ static bool print_key(char *buf, int len, char *start, char *key, va_list args) @@ -136,14 +210,15 @@ static bool print_key(char *buf, int len, char *start, char *key, va_list args) } /** - * find a section by a given key, using buffered key, reusable buffer + * Find a section by a given key, using buffered key, reusable buffer. + * If "ensure" is TRUE, the sections are created if they don't exist. */ static section_t *find_section_buffered(section_t *section, - char *start, char *key, va_list args, char *buf, int len) + char *start, char *key, va_list args, char *buf, int len, + bool ensure) { char *pos; - enumerator_t *enumerator; - section_t *current, *found = NULL; + section_t *found = NULL; if (section == NULL) { @@ -159,47 +234,75 @@ static section_t *find_section_buffered(section_t *section, { return NULL; } - enumerator = section->sections->create_enumerator(section->sections); - while (enumerator->enumerate(enumerator, ¤t)) + if (section->sections->find_first(section->sections, + (linked_list_match_t)section_find, + (void**)&found, buf) != SUCCESS) { - if (streq(current->name, buf)) + if (ensure) { - found = current; - break; + found = section_create(buf); + section->sections->insert_last(section->sections, found); } } - enumerator->destroy(enumerator); if (found && pos) { - return find_section_buffered(found, start, pos, args, buf, len); + return find_section_buffered(found, start, pos, args, buf, len, ensure); } return found; } /** - * find a section by a given key + * Find a section by a given key (thread-safe). */ -static section_t *find_section(section_t *section, char *key, va_list args) +static section_t *find_section(private_settings_t *this, section_t *section, + char *key, va_list args) { char buf[128], keybuf[512]; + section_t *found; if (snprintf(keybuf, sizeof(keybuf), "%s", key) >= sizeof(keybuf)) { return NULL; } - return find_section_buffered(section, keybuf, keybuf, args, buf, sizeof(buf)); + this->lock->read_lock(this->lock); + found = find_section_buffered(section, keybuf, keybuf, args, buf, + sizeof(buf), FALSE); + this->lock->unlock(this->lock); + return found; } /** - * Find the string value for a key, using buffered key, reusable buffer + * Ensure that the section with the given key exists (thread-safe). */ -static char *find_value_buffered(section_t *section, - char *start, char *key, va_list args, char *buf, int len) +static section_t *ensure_section(private_settings_t *this, section_t *section, + char *key, va_list args) { - char *pos, *value = NULL; - enumerator_t *enumerator; - kv_t *kv; - section_t *current, *found = NULL; + char buf[128], keybuf[512]; + section_t *found; + + if (snprintf(keybuf, sizeof(keybuf), "%s", key) >= sizeof(keybuf)) + { + return NULL; + } + /* we might have to change the tree */ + this->lock->write_lock(this->lock); + found = find_section_buffered(section, keybuf, keybuf, args, buf, + sizeof(buf), TRUE); + this->lock->unlock(this->lock); + return found; +} + +/** + * Find the key/value pair for a key, using buffered key, reusable buffer + * If "ensure" is TRUE, the sections (and key/value pair) are created if they + * don't exist. + */ +static kv_t *find_value_buffered(section_t *section, char *start, char *key, + va_list args, char *buf, int len, bool ensure) +{ + char *pos; + kv_t *kv = NULL; + section_t *found = NULL; if (section == NULL) { @@ -216,20 +319,19 @@ static char *find_value_buffered(section_t *section, { return NULL; } - enumerator = section->sections->create_enumerator(section->sections); - while (enumerator->enumerate(enumerator, ¤t)) + if (section->sections->find_first(section->sections, + (linked_list_match_t)section_find, + (void**)&found, buf) != SUCCESS) { - if (streq(current->name, buf)) + if (!ensure) { - found = current; - break; + return NULL; } + found = section_create(buf); + section->sections->insert_last(section->sections, found); } - enumerator->destroy(enumerator); - if (found) - { - return find_value_buffered(found, start, pos, args, buf, len); - } + return find_value_buffered(found, start, pos, args, buf, len, + ensure); } else { @@ -237,44 +339,86 @@ static char *find_value_buffered(section_t *section, { return NULL; } - enumerator = section->kv->create_enumerator(section->kv); - while (enumerator->enumerate(enumerator, &kv)) + if (section->kv->find_first(section->kv, (linked_list_match_t)kv_find, + (void**)&kv, buf) != SUCCESS) { - if (streq(kv->key, buf)) + if (ensure) { - value = kv->value; - break; + kv = kv_create(buf, NULL); + section->kv->insert_last(section->kv, kv); } } - enumerator->destroy(enumerator); } - return value; + return kv; } /** - * Find the string value for a key + * Find the string value for a key (thread-safe). */ -static char *find_value(section_t *section, char *key, va_list args) +static char *find_value(private_settings_t *this, section_t *section, + char *key, va_list args) { - char buf[128], keybuf[512]; + char buf[128], keybuf[512], *value = NULL; + kv_t *kv; if (snprintf(keybuf, sizeof(keybuf), "%s", key) >= sizeof(keybuf)) { return NULL; } - return find_value_buffered(section, keybuf, keybuf, args, buf, sizeof(buf)); + this->lock->read_lock(this->lock); + kv = find_value_buffered(section, keybuf, keybuf, args, buf, sizeof(buf), + FALSE); + if (kv) + { + value = kv->value; + } + this->lock->unlock(this->lock); + return value; } /** - * Implementation of settings_t.get. + * Set a value to a copy of the given string (thread-safe). */ -static char* get_str(private_settings_t *this, char *key, char *def, ...) +static void set_value(private_settings_t *this, section_t *section, + char *key, va_list args, char *value) +{ + char buf[128], keybuf[512]; + kv_t *kv; + + if (snprintf(keybuf, sizeof(keybuf), "%s", key) >= sizeof(keybuf)) + { + return; + } + this->lock->write_lock(this->lock); + kv = find_value_buffered(section, keybuf, keybuf, args, buf, sizeof(buf), + TRUE); + if (kv) + { + if (!value) + { + kv->value = NULL; + } + else if (kv->value && (strlen(value) <= strlen(kv->value))) + { /* overwrite in-place, if possible */ + strcpy(kv->value, value); + } + else + { /* otherwise clone the string and store it in the cache */ + kv->value = strdup(value); + this->contents->insert_last(this->contents, kv->value); + } + } + this->lock->unlock(this->lock); +} + +METHOD(settings_t, get_str, char*, + private_settings_t *this, char *key, char *def, ...) { char *value; va_list args; va_start(args, def); - value = find_value(this->top, key, args); + value = find_value(this, this->top, key, args); va_end(args); if (value) { @@ -284,29 +428,23 @@ static char* get_str(private_settings_t *this, char *key, char *def, ...) } /** - * Implementation of settings_t.get_bool. + * Described in header */ -static bool get_bool(private_settings_t *this, char *key, bool def, ...) +inline bool settings_value_as_bool(char *value, bool def) { - char *value; - va_list args; - - va_start(args, def); - value = find_value(this->top, key, args); - va_end(args); if (value) { - if (strcaseeq(value, "true") || - strcaseeq(value, "enabled") || + if (strcaseeq(value, "1") || strcaseeq(value, "yes") || - strcaseeq(value, "1")) + strcaseeq(value, "true") || + strcaseeq(value, "enabled")) { return TRUE; } - else if (strcaseeq(value, "false") || - strcaseeq(value, "disabled") || + else if (strcaseeq(value, "0") || strcaseeq(value, "no") || - strcaseeq(value, "0")) + strcaseeq(value, "false") || + strcaseeq(value, "disabled")) { return FALSE; } @@ -314,18 +452,24 @@ static bool get_bool(private_settings_t *this, char *key, bool def, ...) return def; } -/** - * Implementation of settings_t.get_int. - */ -static int get_int(private_settings_t *this, char *key, int def, ...) +METHOD(settings_t, get_bool, bool, + private_settings_t *this, char *key, bool def, ...) { char *value; - int intval; va_list args; va_start(args, def); - value = find_value(this->top, key, args); + value = find_value(this, this->top, key, args); va_end(args); + return settings_value_as_bool(value, def); +} + +/** + * Described in header + */ +inline int settings_value_as_int(char *value, int def) +{ + int intval; if (value) { errno = 0; @@ -338,18 +482,24 @@ static int get_int(private_settings_t *this, char *key, int def, ...) return def; } -/** - * Implementation of settings_t.get_double. - */ -static double get_double(private_settings_t *this, char *key, double def, ...) +METHOD(settings_t, get_int, int, + private_settings_t *this, char *key, int def, ...) { char *value; - double dval; va_list args; va_start(args, def); - value = find_value(this->top, key, args); + value = find_value(this, this->top, key, args); va_end(args); + return settings_value_as_int(value, def); +} + +/** + * Described in header + */ +inline double settings_value_as_double(char *value, double def) +{ + double dval; if (value) { errno = 0; @@ -362,18 +512,25 @@ static double get_double(private_settings_t *this, char *key, double def, ...) return def; } -/** - * Implementation of settings_t.get_time. - */ -static u_int32_t get_time(private_settings_t *this, char *key, u_int32_t def, ...) +METHOD(settings_t, get_double, double, + private_settings_t *this, char *key, double def, ...) { - char *value, *endptr; - u_int32_t timeval; + char *value; va_list args; va_start(args, def); - value = find_value(this->top, key, args); + value = find_value(this, this->top, key, args); va_end(args); + return settings_value_as_double(value, def); +} + +/** + * Described in header + */ +inline u_int32_t settings_value_as_time(char *value, u_int32_t def) +{ + char *endptr; + u_int32_t timeval; if (value) { errno = 0; @@ -392,7 +549,7 @@ static u_int32_t get_time(private_settings_t *this, char *key, u_int32_t def, .. timeval *= 60; break; case 's': /* time in seconds */ - default: + default: break; } return timeval; @@ -401,6 +558,75 @@ static u_int32_t get_time(private_settings_t *this, char *key, u_int32_t def, .. return def; } +METHOD(settings_t, get_time, u_int32_t, + private_settings_t *this, char *key, u_int32_t def, ...) +{ + char *value; + va_list args; + + va_start(args, def); + value = find_value(this, this->top, key, args); + va_end(args); + return settings_value_as_time(value, def); +} + +METHOD(settings_t, set_str, void, + private_settings_t *this, char *key, char *value, ...) +{ + va_list args; + va_start(args, value); + set_value(this, this->top, key, args, value); + va_end(args); +} + +METHOD(settings_t, set_bool, void, + private_settings_t *this, char *key, bool value, ...) +{ + va_list args; + va_start(args, value); + set_value(this, this->top, key, args, value ? "1" : "0"); + va_end(args); +} + +METHOD(settings_t, set_int, void, + private_settings_t *this, char *key, int value, ...) +{ + char val[16]; + va_list args; + va_start(args, value); + if (snprintf(val, sizeof(val), "%d", value) < sizeof(val)) + { + set_value(this, this->top, key, args, val); + } + va_end(args); +} + +METHOD(settings_t, set_double, void, + private_settings_t *this, char *key, double value, ...) +{ + char val[64]; + va_list args; + va_start(args, value); + if (snprintf(val, sizeof(val), "%f", value) < sizeof(val)) + { + set_value(this, this->top, key, args, val); + } + va_end(args); +} + +METHOD(settings_t, set_time, void, + private_settings_t *this, char *key, u_int32_t value, ...) +{ + char val[16]; + va_list args; + va_start(args, value); + if (snprintf(val, sizeof(val), "%u", value) < sizeof(val)) + { + set_value(this, this->top, key, args, val); + } + va_end(args); +} + /** * Enumerate section names, not sections */ @@ -410,26 +636,24 @@ static bool section_filter(void *null, section_t **in, char **out) return TRUE; } -/** - * Implementation of settings_t.create_section_enumerator - */ -static enumerator_t* create_section_enumerator(private_settings_t *this, - char *key, ...) +METHOD(settings_t, create_section_enumerator, enumerator_t*, + private_settings_t *this, char *key, ...) { section_t *section; va_list args; va_start(args, key); - section = find_section(this->top, key, args); + section = find_section(this, this->top, key, args); va_end(args); if (!section) { return enumerator_create_empty(); } + this->lock->read_lock(this->lock); return enumerator_create_filter( - section->sections->create_enumerator(section->sections), - (void*)section_filter, NULL, NULL); + section->sections->create_enumerator(section->sections), + (void*)section_filter, this->lock, (void*)this->lock->unlock); } /** @@ -443,37 +667,24 @@ static bool kv_filter(void *null, kv_t **in, char **key, return TRUE; } -/** - * Implementation of settings_t.create_key_value_enumerator - */ -static enumerator_t* create_key_value_enumerator(private_settings_t *this, - char *key, ...) +METHOD(settings_t, create_key_value_enumerator, enumerator_t*, + private_settings_t *this, char *key, ...) { section_t *section; va_list args; va_start(args, key); - section = find_section(this->top, key, args); + section = find_section(this, this->top, key, args); va_end(args); if (!section) { return enumerator_create_empty(); } + this->lock->read_lock(this->lock); return enumerator_create_filter( section->kv->create_enumerator(section->kv), - (void*)kv_filter, NULL, NULL); -} - -/** - * destroy a section - */ -static void section_destroy(section_t *this) -{ - this->kv->destroy_function(this->kv, free); - this->sections->destroy_function(this->sections, (void*)section_destroy); - - free(this); + (void*)kv_filter, this->lock, (void*)this->lock->unlock); } /** @@ -551,45 +762,134 @@ static char parse(char **text, char *skip, char *term, char *br, char **token) } /** + * Check if "text" starts with "pattern". + * Characters in "skip" are skipped first. If found, TRUE is returned and "text" + * is modified to point to the character right after "pattern". + */ +static bool starts_with(char **text, char *skip, char *pattern) +{ + char *pos = *text; + int len = strlen(pattern); + while (strchr(skip, *pos)) + { + pos++; + if (!*pos) + { + return FALSE; + } + } + if (strlen(pos) < len || !strneq(pos, pattern, len)) + { + return FALSE; + } + *text = pos + len; + return TRUE; +} + +/** + * Check if what follows in "text" is an include statement. + * If this function returns TRUE, "text" will point to the character right after + * the include pattern, which is returned in "pattern". + */ +static bool parse_include(char **text, char **pattern) +{ + char *pos = *text; + if (!starts_with(&pos, "\n\t ", "include")) + { + return FALSE; + } + if (starts_with(&pos, "\t ", "=")) + { /* ignore "include = value" */ + return FALSE; + } + *text = pos; + return parse(text, "\t ", "\n", NULL, pattern) != 0; +} + +/** + * Forward declaration. + */ +static bool parse_files(linked_list_t *contents, char *file, int level, + char *pattern, section_t *section); + +/** * Parse a section */ -static section_t* parse_section(char **text, char *name) +static bool parse_section(linked_list_t *contents, char *file, int level, + char **text, section_t *section) { - section_t *sub, *section; bool finished = FALSE; char *key, *value, *inner; - static int lev = 0; - lev++; - - section = malloc_thing(section_t); - section->name = name; - section->sections = linked_list_create(); - section->kv = linked_list_create(); - while (!finished) { + if (parse_include(text, &value)) + { + if (!parse_files(contents, file, level, value, section)) + { + DBG1(DBG_LIB, "failed to include '%s'", value); + return FALSE; + } + continue; + } switch (parse(text, "\t\n ", "{=#", NULL, &key)) { case '{': if (parse(text, "\t ", "}", "{", &inner)) { - sub = parse_section(&inner, key); - if (sub) + section_t *sub; + if (!strlen(key)) { - section->sections->insert_last(section->sections, sub); + DBG1(DBG_LIB, "skipping section without name in '%s'", + section->name); continue; } + if (section->sections->find_first(section->sections, + (linked_list_match_t)section_find, + (void**)&sub, key) != SUCCESS) + { + sub = section_create(key); + if (parse_section(contents, file, level, &inner, sub)) + { + section->sections->insert_last(section->sections, + sub); + continue; + } + section_destroy(sub); + } + else + { /* extend the existing section */ + if (parse_section(contents, file, level, &inner, sub)) + { + continue; + } + } + DBG1(DBG_LIB, "parsing subsection '%s' failed", key); + break; } DBG1(DBG_LIB, "matching '}' not found near %s", *text); break; case '=': if (parse(text, "\t ", "\n", NULL, &value)) { - kv_t *kv = malloc_thing(kv_t); - kv->key = key; - kv->value = value; - section->kv->insert_last(section->kv, kv); + kv_t *kv; + if (!strlen(key)) + { + DBG1(DBG_LIB, "skipping value without key in '%s'", + section->name); + continue; + } + if (section->kv->find_first(section->kv, + (linked_list_match_t)kv_find, + (void**)&kv, key) != SUCCESS) + { + kv = kv_create(key, value); + section->kv->insert_last(section->kv, kv); + } + else + { /* replace with the most recently read value */ + kv->value = value; + } continue; } DBG1(DBG_LIB, "parsing value failed near %s", *text); @@ -601,78 +901,272 @@ static section_t* parse_section(char **text, char *name) finished = TRUE; continue; } - section_destroy(section); - return NULL; + return FALSE; } - return section; + return TRUE; } /** - * Implementation of settings_t.destroy + * Parse a file and add the settings to the given section. */ -static void destroy(private_settings_t *this) +static bool parse_file(linked_list_t *contents, char *file, int level, + section_t *section) { - if (this->top) + bool success; + char *text, *pos; + FILE *fd; + int len; + + DBG2(DBG_LIB, "loading config file '%s'", file); + fd = fopen(file, "r"); + if (fd == NULL) { - section_destroy(this->top); + DBG1(DBG_LIB, "'%s' does not exist or is not readable", file); + return FALSE; } - free(this->text); - free(this); + fseek(fd, 0, SEEK_END); + len = ftell(fd); + rewind(fd); + text = malloc(len + 1); + text[len] = '\0'; + if (fread(text, 1, len, fd) != len) + { + free(text); + return FALSE; + } + fclose(fd); + + pos = text; + success = parse_section(contents, file, level, &pos, section); + if (!success) + { + free(text); + } + else + { + contents->insert_last(contents, text); + } + return success; } -/* - * see header file +/** + * Load the files matching "pattern", which is resolved with glob(3). + * If the pattern is relative, the directory of "file" is used as base. */ -settings_t *settings_create(char *file) +static bool parse_files(linked_list_t *contents, char *file, int level, + char *pattern, section_t *section) { - private_settings_t *this; - char *pos; - FILE *fd; - int len; + bool success = TRUE; + int status; + glob_t buf; + char **expanded, pat[PATH_MAX]; - this = malloc_thing(private_settings_t); - this->public.get_str = (char*(*)(settings_t*, char *key, char* def, ...))get_str; - this->public.get_int = (int(*)(settings_t*, char *key, int def, ...))get_int; - this->public.get_double = (double(*)(settings_t*, char *key, double def, ...))get_double; - this->public.get_time = (u_int32_t(*)(settings_t*, char *key, u_int32_t def, ...))get_time; - this->public.get_bool = (bool(*)(settings_t*, char *key, bool def, ...))get_bool; - this->public.create_section_enumerator = (enumerator_t*(*)(settings_t*,char *section, ...))create_section_enumerator; - this->public.create_key_value_enumerator = (enumerator_t*(*)(settings_t*, char *key, ...))create_key_value_enumerator; - this->public.destroy = (void(*)(settings_t*))destroy; + if (level > MAX_INCLUSION_LEVEL) + { + DBG1(DBG_LIB, "maximum level of %d includes reached, ignored", + MAX_INCLUSION_LEVEL); + return TRUE; + } - this->top = NULL; - this->text = NULL; + if (!strlen(pattern)) + { + DBG2(DBG_LIB, "empty include pattern, ignored"); + return TRUE; + } - if (file == NULL) + if (!file || pattern[0] == '/') + { /* absolute path */ + if (snprintf(pat, sizeof(pat), "%s", pattern) >= sizeof(pat)) + { + DBG1(DBG_LIB, "include pattern too long, ignored"); + return TRUE; + } + } + else + { /* base relative paths to the directory of the current file */ + char *dir = strdup(file); + dir = dirname(dir); + if (snprintf(pat, sizeof(pat), "%s/%s", dir, pattern) >= sizeof(pat)) + { + DBG1(DBG_LIB, "include pattern too long, ignored"); + free(dir); + return TRUE; + } + free(dir); + } + status = glob(pat, GLOB_ERR, NULL, &buf); + if (status == GLOB_NOMATCH) { - file = STRONGSWAN_CONF; + DBG2(DBG_LIB, "no files found matching '%s', ignored", pat); } - fd = fopen(file, "r"); - if (fd == NULL) + else if (status != 0) { - DBG1(DBG_LIB, "'%s' does not exist or is not readable", file); - return &this->public; + DBG1(DBG_LIB, "expanding file pattern '%s' failed", pat); + success = FALSE; } - fseek(fd, 0, SEEK_END); - len = ftell(fd); - rewind(fd); - this->text = malloc(len + 1); - this->text[len] = '\0'; - if (fread(this->text, 1, len, fd) != len) + else { - free(this->text); - this->text = NULL; - return &this->public; + for (expanded = buf.gl_pathv; *expanded != NULL; expanded++) + { + success &= parse_file(contents, *expanded, level + 1, section); + if (!success) + { + break; + } + } } - fclose(fd); + globfree(&buf); + return success; +} + +/** + * Recursivly extends "base" with "extension". + */ +static void section_extend(section_t *base, section_t *extension) +{ + enumerator_t *enumerator; + section_t *sec; + kv_t *kv; + + enumerator = extension->sections->create_enumerator(extension->sections); + while (enumerator->enumerate(enumerator, (void**)&sec)) + { + section_t *found; + if (base->sections->find_first(base->sections, + (linked_list_match_t)section_find, (void**)&found, + sec->name) == SUCCESS) + { + section_extend(found, sec); + } + else + { + extension->sections->remove_at(extension->sections, enumerator); + base->sections->insert_last(base->sections, sec); + } + } + enumerator->destroy(enumerator); + + enumerator = extension->kv->create_enumerator(extension->kv); + while (enumerator->enumerate(enumerator, (void**)&kv)) + { + kv_t *found; + if (base->kv->find_first(base->kv, (linked_list_match_t)kv_find, + (void**)&found, kv->key) == SUCCESS) + { + found->value = kv->value; + } + else + { + extension->kv->remove_at(extension->kv, enumerator); + base->kv->insert_last(base->kv, kv); + } + } + enumerator->destroy(enumerator); +} + +/** + * Load settings from files matching the given file pattern. + * All sections and values are added relative to "parent". + * All files (even included ones) have to be loaded successfully. + */ +static bool load_files_internal(private_settings_t *this, section_t *parent, + char *pattern) +{ + char *text; + linked_list_t *contents = linked_list_create(); + section_t *section = section_create(NULL); + + if (!parse_files(contents, NULL, 0, pattern, section)) + { + contents->destroy_function(contents, (void*)free); + section_destroy(section); + return FALSE; + } + + this->lock->write_lock(this->lock); + /* extend parent section */ + section_extend(parent, section); + /* move contents of loaded files to main store */ + while (contents->remove_first(contents, (void**)&text) == SUCCESS) + { + this->contents->insert_last(this->contents, text); + } + this->lock->unlock(this->lock); + + section_destroy(section); + contents->destroy(contents); + return TRUE; +} + +METHOD(settings_t, load_files, bool, + private_settings_t *this, char *pattern) +{ + return load_files_internal(this, this->top, pattern); +} + +METHOD(settings_t, load_files_section, bool, + private_settings_t *this, char *pattern, char *key, ...) +{ + section_t *section; + va_list args; + + va_start(args, key); + section = ensure_section(this, this->top, key, args); + va_end(args); - pos = this->text; - this->top = parse_section(&pos, NULL); - if (this->top == NULL) + if (!section) { - free(this->text); - this->text = NULL; + return FALSE; } + return load_files_internal(this, section, pattern); +} + +METHOD(settings_t, destroy, void, + private_settings_t *this) +{ + section_destroy(this->top); + this->contents->destroy_function(this->contents, (void*)free); + this->lock->destroy(this->lock); + free(this); +} + +/* + * see header file + */ +settings_t *settings_create(char *file) +{ + private_settings_t *this; + + INIT(this, + .public = { + .get_str = _get_str, + .get_int = _get_int, + .get_double = _get_double, + .get_time = _get_time, + .get_bool = _get_bool, + .set_str = _set_str, + .set_int = _set_int, + .set_double = _set_double, + .set_time = _set_time, + .set_bool = _set_bool, + .create_section_enumerator = _create_section_enumerator, + .create_key_value_enumerator = _create_key_value_enumerator, + .load_files = _load_files, + .load_files_section = _load_files_section, + .destroy = _destroy, + }, + .top = section_create(NULL), + .contents = linked_list_create(), + .lock = rwlock_create(RWLOCK_TYPE_DEFAULT), + ); + + if (file == NULL) + { + file = STRONGSWAN_CONF; + } + + load_files(this, file); + return &this->public; } diff --git a/src/libstrongswan/settings.h b/src/libstrongswan/settings.h index 486de8def..bc3df3706 100644 --- a/src/libstrongswan/settings.h +++ b/src/libstrongswan/settings.h @@ -1,4 +1,5 @@ /* + * Copyright (C) 2010 Tobias Brunner * Copyright (C) 2008 Martin Willi * Hochschule fuer Technik Rapperswil * @@ -27,14 +28,54 @@ typedef struct settings_t settings_t; #include "utils/enumerator.h" /** + * Convert a string value returned by a key/value enumerator to a boolean. + * + * @see settings_t.create_key_value_enumerator() + * @see settings_t.get_bool() + * @param value the string value + * @param def the default value, if value is NULL or invalid + */ +bool settings_value_as_bool(char *value, bool def); + +/** + * Convert a string value returned by a key/value enumerator to an integer. + * + * @see settings_t.create_key_value_enumerator() + * @see settings_t.get_int() + * @param value the string value + * @param def the default value, if value is NULL or invalid + */ +int settings_value_as_int(char *value, int def); + +/** + * Convert a string value returned by a key/value enumerator to a double. + * + * @see settings_t.create_key_value_enumerator() + * @see settings_t.get_double() + * @param value the string value + * @param def the default value, if value is NULL or invalid + */ +double settings_value_as_double(char *value, double def); + +/** + * Convert a string value returned by a key/value enumerator to a time value. + * + * @see settings_t.create_key_value_enumerator() + * @see settings_t.get_time() + * @param value the string value + * @param def the default value, if value is NULL or invalid + */ +u_int32_t settings_value_as_time(char *value, u_int32_t def); + +/** * Generic configuration options read from a config file. * * The syntax is quite simple: - * + * @code * settings := (section|keyvalue)* * section := name { settings } * keyvalue := key = value\n - * + * @endcode * E.g.: * @code a = b @@ -54,6 +95,51 @@ typedef struct settings_t settings_t; * * Currently only a limited set of printf format specifiers are supported * (namely %s, %d and %N, see implementation for details). + * + * \section includes Including other files + * Other files can be included, using the include statement e.g. + * @code + * include /somepath/subconfig.conf + * @endcode + * Shell patterns like *.conf are possible. + * + * If the path is relative, the directory of the file containing the include + * statement is used as base. + * + * Sections loaded from included files extend previously loaded sections, + * already existing values are replaced. + * + * All settings included from files are added relative to the section the + * include statment is in. + * + * The following files result in the same final config as above: + * + * @code + a = b + section-one { + somevalue = before include + include include.conf + } + include two.conf + @endcode + * include.conf + * @code + somevalue = asdf + subsection { + othervalue = yyy + } + yetanother = zz + @endcode + * two.conf + * @code + section-one { + subsection { + othervalue = xxx + } + } + section-two { + } + @endcode */ struct settings_t { @@ -108,6 +194,51 @@ struct settings_t { u_int32_t (*get_time)(settings_t *this, char *key, u_int32_t def, ...); /** + * Set a string value. + * + * @param key key including sections, printf style format + * @param value value to set (gets cloned) + * @param ... argument list for key + */ + void (*set_str)(settings_t *this, char *key, char *value, ...); + + /** + * Set a boolean value. + * + * @param key key including sections, printf style format + * @param value value to set + * @param ... argument list for key + */ + void (*set_bool)(settings_t *this, char *key, bool value, ...); + + /** + * Set an integer value. + * + * @param key key including sections, printf style format + * @param value value to set + * @param ... argument list for key + */ + void (*set_int)(settings_t *this, char *key, int value, ...); + + /** + * Set an double value. + * + * @param key key including sections, printf style format + * @param value value to set + * @param ... argument list for key + */ + void (*set_double)(settings_t *this, char *key, double value, ...); + + /** + * Set a time value. + * + * @param key key including sections, printf style format + * @param def value to set + * @param ... argument list for key + */ + void (*set_time)(settings_t *this, char *key, u_int32_t value, ...); + + /** * Create an enumerator over subsection names of a section. * * @param section section including parents, printf style format @@ -121,13 +252,47 @@ struct settings_t { * Create an enumerator over key/value pairs in a section. * * @param section section name to list key/value pairs of, printf style - * @param ... argmuent list for section + * @param ... argument list for section * @return enumerator over (char *key, char *value) */ enumerator_t* (*create_key_value_enumerator)(settings_t *this, char *section, ...); /** + * Load settings from the files matching the given pattern. + * + * Existing sections are extended, existing values replaced, by those found + * in the loaded files. + * + * @note If any of the files matching the pattern fails to load, no settings + * are added at all. So, it's all or nothing. + * + * @param pattern file pattern + * @return TRUE, if settings were loaded successfully + */ + bool (*load_files)(settings_t *this, char *pattern); + + /** + * Load settings from the files matching the given pattern. + * + * Existing sections are extended, existing values replaced, by those found + * in the loaded files. + * + * All settings are loaded relative to the given section. The section is + * created, if it does not yet exist. + * + * @note If any of the files matching the pattern fails to load, no settings + * are added at all. So, it's all or nothing. + * + * @param pattern file pattern + * @param section section name of parent section, printf style + * @param ... argument list for section + * @return TRUE, if settings were loaded successfully + */ + bool (*load_files_section)(settings_t *this, char *pattern, + char *section, ...); + + /** * Destroy a settings instance. */ void (*destroy)(settings_t *this); diff --git a/src/libstrongswan/utils.c b/src/libstrongswan/utils.c index b868d538d..2ab061a74 100644 --- a/src/libstrongswan/utils.c +++ b/src/libstrongswan/utils.c @@ -247,6 +247,14 @@ bool return_false() } /** + * returns FAILED + */ +status_t return_failed() +{ + return FAILED; +} + +/** * nop operation */ void nop() diff --git a/src/libstrongswan/utils.h b/src/libstrongswan/utils.h index 35d3bebd1..ed61895ee 100644 --- a/src/libstrongswan/utils.h +++ b/src/libstrongswan/utils.h @@ -57,7 +57,7 @@ #define streq(x,y) (strcmp(x, y) == 0) /** - * Macro compares two strings for equality + * Macro compares two strings for equality, length limited */ #define strneq(x,y,len) (strncmp(x, y, len) == 0) @@ -67,6 +67,16 @@ #define strcaseeq(x,y) (strcasecmp(x, y) == 0) /** + * Macro compares two strings for equality ignoring case, length limited + */ +#define strncaseeq(x,y,len) (strncasecmp(x, y, len) == 0) + +/** + * NULL-safe strdup variant + */ +#define strdupnull(x) ({ char *_x = x; _x ? strdup(_x) : NULL; }) + +/** * Macro compares two binary blobs for equality */ #define memeq(x,y,len) (memcmp(x, y, len) == 0) @@ -382,6 +392,11 @@ bool return_true(); bool return_false(); /** + * returns FAILED + */ +status_t return_failed(); + +/** * Write a 16-bit host order value in network order to an unaligned address. * * @param host host order 16-bit value diff --git a/src/libstrongswan/utils/backtrace.c b/src/libstrongswan/utils/backtrace.c index a67245194..41224e8c2 100644 --- a/src/libstrongswan/utils/backtrace.c +++ b/src/libstrongswan/utils/backtrace.c @@ -132,10 +132,11 @@ static void log_(private_backtrace_t *this, FILE *file, bool detailed) /** * Implementation of backtrace_t.contains_function */ -static bool contains_function(private_backtrace_t *this, char *function) +static bool contains_function(private_backtrace_t *this, + char *function[], int count) { #ifdef HAVE_DLADDR - int i; + int i, j; for (i = 0; i< this->frame_count; i++) { @@ -143,9 +144,12 @@ static bool contains_function(private_backtrace_t *this, char *function) if (dladdr(this->frames[i], &info) && info.dli_sname) { - if (streq(info.dli_sname, function)) + for (j = 0; j < count; j++) { - return TRUE; + if (streq(info.dli_sname, function[j])) + { + return TRUE; + } } } } @@ -179,7 +183,7 @@ backtrace_t *backtrace_create(int skip) this->frame_count = frame_count; this->public.log = (void(*)(backtrace_t*,FILE*,bool))log_; - this->public.contains_function = (bool(*)(backtrace_t*, char *function))contains_function; + this->public.contains_function = (bool(*)(backtrace_t*, char *function[], int count))contains_function; this->public.destroy = (void(*)(backtrace_t*))destroy; return &this->public; diff --git a/src/libstrongswan/utils/backtrace.h b/src/libstrongswan/utils/backtrace.h index c6b0ec78f..e8ccfc1bd 100644 --- a/src/libstrongswan/utils/backtrace.h +++ b/src/libstrongswan/utils/backtrace.h @@ -41,12 +41,13 @@ struct backtrace_t { void (*log)(backtrace_t *this, FILE *file, bool detailed); /** - * Check if the backtrace contains a frame in a specific function. + * Check if the backtrace contains a frame having a function in a list. * - * @param function name - * @return TRUE if function is in the stack + * @param function name array + * @param number of elements in function array + * @return TRUE if one of the functions is in the stack */ - bool (*contains_function)(backtrace_t *this, char *function); + bool (*contains_function)(backtrace_t *this, char *function[], int count); /** * Destroy a backtrace instance. diff --git a/src/libstrongswan/utils/hashtable.c b/src/libstrongswan/utils/hashtable.c index dde57dc65..49b0bb68c 100644 --- a/src/libstrongswan/utils/hashtable.c +++ b/src/libstrongswan/utils/hashtable.c @@ -186,7 +186,7 @@ static void rehash(private_hashtable_t *this) linked_list_t **old_table; u_int row, old_capacity; - if (this->capacity < MAX_CAPACITY) + if (this->capacity >= MAX_CAPACITY) { return; } @@ -249,6 +249,7 @@ METHOD(hashtable_t, put, void*, { old_value = pair->value; pair->value = value; + pair->key = key; break; } } diff --git a/src/libstrongswan/utils/host.c b/src/libstrongswan/utils/host.c index 112d07e5c..ffeebd05c 100644 --- a/src/libstrongswan/utils/host.c +++ b/src/libstrongswan/utils/host.c @@ -476,6 +476,10 @@ host_t *host_create_from_dns(char *string, int af, u_int16_t port) { return host_create_any_port(af ? af : AF_INET6, port); } + if (af == AF_INET && strchr(string, ':')) + { /* do not try to convert v6 addresses for v4 family */ + return NULL; + } memset(&hints, 0, sizeof(hints)); hints.ai_family = af; @@ -564,6 +568,41 @@ host_t *host_create_from_chunk(int family, chunk_t address, u_int16_t port) /* * Described in header. */ +host_t *host_create_from_subnet(char *string, int *bits) +{ + char *pos, buf[64]; + host_t *net; + + pos = strchr(string, '/'); + if (pos) + { + if (pos - string >= sizeof(buf)) + { + return NULL; + } + strncpy(buf, string, pos - string); + buf[pos - string] = '\0'; + *bits = atoi(pos + 1); + return host_create_from_string(buf, 0); + } + net = host_create_from_string(buf, 0); + if (net) + { + if (net->get_family(net) == AF_INET) + { + *bits = 32; + } + else + { + *bits = 128; + } + } + return net; +} + +/* + * Described in header. + */ host_t *host_create_any(int family) { private_host_t *this = host_create_empty(); diff --git a/src/libstrongswan/utils/host.h b/src/libstrongswan/utils/host.h index f5796154c..0a1be6e47 100644 --- a/src/libstrongswan/utils/host.h +++ b/src/libstrongswan/utils/host.h @@ -190,6 +190,15 @@ host_t *host_create_from_chunk(int family, chunk_t address, u_int16_t port); host_t *host_create_from_sockaddr(sockaddr_t *sockaddr); /** + * Create a host from a CIDR subnet definition (1.2.3.0/24), return bits. + * + * @param string string to parse + * @param bits gets the number of network bits in CIDR notation + * @return network start address, NULL on error + */ +host_t *host_create_from_subnet(char *string, int *bits); + +/** * Create a host without an address, a "any" host. * * @param family family of the any host diff --git a/src/libstrongswan/utils/identification.c b/src/libstrongswan/utils/identification.c index 0696c1030..fd2716deb 100644 --- a/src/libstrongswan/utils/identification.c +++ b/src/libstrongswan/utils/identification.c @@ -281,11 +281,13 @@ static void dntoa(chunk_t dn, char *buf, size_t len) chunk_t oid_data, data, printable; u_char type; int oid, written; - bool finished = FALSE; + bool finished = FALSE, empty = TRUE; e = create_rdn_enumerator(dn); while (e->enumerate(e, &oid_data, &type, &data)) { + empty = FALSE; + oid = asn1_known_oid(oid_data); if (oid == OID_UNKNOWN) @@ -329,7 +331,11 @@ static void dntoa(chunk_t dn, char *buf, size_t len) break; } } - if (!finished) + if (empty) + { + snprintf(buf, len, ""); + } + else if (!finished) { snprintf(buf, len, "(invalid ID_DER_ASN1_DN)"); } diff --git a/src/libstrongswan/utils/leak_detective.c b/src/libstrongswan/utils/leak_detective.c index 5673fc32d..52e92951b 100644 --- a/src/libstrongswan/utils/leak_detective.c +++ b/src/libstrongswan/utils/leak_detective.c @@ -218,25 +218,23 @@ char *whitelist[] = { "gcry_create_nonce", /* NSPR */ "PR_CallOnce", + /* libapr */ + "apr_pool_create_ex", + /* glib */ + "g_type_init_with_debug_flags", + "g_type_register_static", + "g_type_class_ref", + "g_type_create_instance", + "g_type_add_interface_static", + "g_type_interface_add_prerequisite", + "g_socket_connection_factory_lookup_type", + /* libgpg */ + "gpg_err_init", + /* gnutls */ + "gnutls_global_init", }; /** - * check if a stack frame contains functions listed above - */ -static bool is_whitelisted(backtrace_t *backtrace) -{ - int i; - for (i = 0; i < sizeof(whitelist)/sizeof(char*); i++) - { - if (backtrace->contains_function(backtrace, whitelist[i])) - { - return TRUE; - } - } - return FALSE; -} - -/** * Report leaks at library destruction */ static void report(private_leak_detective_t *this, bool detailed) @@ -248,7 +246,8 @@ static void report(private_leak_detective_t *this, bool detailed) for (hdr = first_header.next; hdr != NULL; hdr = hdr->next) { - if (is_whitelisted(hdr->backtrace)) + if (hdr->backtrace->contains_function(hdr->backtrace, + whitelist, countof(whitelist))) { whitelisted++; } diff --git a/src/libstrongswan/utils/optionsfrom.c b/src/libstrongswan/utils/optionsfrom.c index d8f635c62..e51780290 100644 --- a/src/libstrongswan/utils/optionsfrom.c +++ b/src/libstrongswan/utils/optionsfrom.c @@ -61,11 +61,8 @@ struct private_options_t { char *buffers[MAX_USES]; }; -/** - * Defined in header - */ -bool from(private_options_t *this, char *filename, int *argcp, char **argvp[], - int optind) +METHOD(options_t, from, bool, + private_options_t *this, char *filename, int *argcp, char **argvp[], int optind) { int newargc; int next; /* place for next argument */ @@ -182,10 +179,8 @@ bool from(private_options_t *this, char *filename, int *argcp, char **argvp[], return good; } -/** - * Defined in header - */ -void destroy(private_options_t *this) +METHOD(options_t, destroy, void, + private_options_t *this) { while (this->nuses >= 0) { @@ -200,17 +195,16 @@ void destroy(private_options_t *this) */ options_t *options_create(void) { - private_options_t *this = malloc_thing(private_options_t); + private_options_t *this; - /* initialize */ - this->newargv = NULL; - this->room = 0; - this->nuses = -1; - memset(this->buffers, '\0', MAX_USES); + INIT(this, + .public = { + .from = _from, + .destroy = _destroy, - /* public functions */ - this->public.from = (bool (*) (options_t*,char*,int*,char***,int))from; - this->public.destroy = (void (*) (options_t*))destroy; + }, + .nuses = -1, + ); return &this->public; } diff --git a/src/libtls/Makefile.in b/src/libtls/Makefile.in index 9f0a817f5..93e8b4a9b 100644 --- a/src/libtls/Makefile.in +++ b/src/libtls/Makefile.in @@ -195,9 +195,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -236,6 +234,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/libtls/tls.h b/src/libtls/tls.h index 1908f5dd4..e2c377ad3 100644 --- a/src/libtls/tls.h +++ b/src/libtls/tls.h @@ -202,7 +202,7 @@ struct tls_t { /** * Check if TLS negotiation completed successfully. * - * @return TRUE if TLS negotation and authentication complete + * @return TRUE if TLS negotiation and authentication complete */ bool (*is_complete)(tls_t *this); diff --git a/src/libtls/tls_crypto.c b/src/libtls/tls_crypto.c index 78f2a796d..b4eaf4d79 100644 --- a/src/libtls/tls_crypto.c +++ b/src/libtls/tls_crypto.c @@ -626,15 +626,18 @@ static void filter_suite(private_tls_crypto_t *this, suite_algs_t suites[], int *count, int offset, enumerator_t*(*create_enumerator)(crypto_factory_t*)) { + const char *plugin_name; suite_algs_t current; - int i, remaining = 0; + int *current_alg, i, remaining = 0; enumerator_t *enumerator; memset(¤t, 0, sizeof(current)); + current_alg = (int*)((char*)¤t + offset); + for (i = 0; i < *count; i++) { enumerator = create_enumerator(lib->crypto); - while (enumerator->enumerate(enumerator, ((char*)¤t) + offset)) + while (enumerator->enumerate(enumerator, current_alg, &plugin_name)) { if ((suites[i].encr == ENCR_NULL || !current.encr || current.encr == suites[i].encr) && @@ -1060,10 +1063,11 @@ METHOD(tls_crypto_t, get_signature_algorithms, void, enumerator_t *enumerator; hash_algorithm_t alg; tls_hash_algorithm_t hash; + const char *plugin_name; supported = tls_writer_create(32); enumerator = lib->crypto->create_hasher_enumerator(lib->crypto); - while (enumerator->enumerate(enumerator, &alg)) + while (enumerator->enumerate(enumerator, &alg, &plugin_name)) { switch (alg) { diff --git a/src/libtls/tls_eap.c b/src/libtls/tls_eap.c index a8c3a5053..8204a3441 100644 --- a/src/libtls/tls_eap.c +++ b/src/libtls/tls_eap.c @@ -303,17 +303,21 @@ METHOD(tls_eap_t, process, status_t, DBG2(DBG_TLS, "received %N acknowledgement packet", eap_type_names, this->type); status = build_pkt(this, pkt->identifier, out); - if (status == INVALID_STATE && - this->tls->is_complete(this->tls)) + if (status == INVALID_STATE && this->tls->is_complete(this->tls)) { return SUCCESS; } return status; } status = process_pkt(this, pkt); - if (status != NEED_MORE) + switch (status) { - return status; + case NEED_MORE: + break; + case SUCCESS: + return this->tls->is_complete(this->tls) ? SUCCESS : FAILED; + default: + return status; } } status = build_pkt(this, pkt->identifier, out); diff --git a/src/libtls/tls_reader.c b/src/libtls/tls_reader.c index 17ec68fd5..2b3cd8cac 100644 --- a/src/libtls/tls_reader.c +++ b/src/libtls/tls_reader.c @@ -52,8 +52,8 @@ METHOD(tls_reader_t, read_uint8, bool, { if (this->buf.len < 1) { - DBG1(DBG_TLS, "%d bytes insufficient to parse uint%d TLS data", - this->buf.len, 8); + DBG1(DBG_TLS, "%d bytes insufficient to parse u_int8 data", + this->buf.len); return FALSE; } *res = this->buf.ptr[0]; @@ -66,8 +66,8 @@ METHOD(tls_reader_t, read_uint16, bool, { if (this->buf.len < 2) { - DBG1(DBG_TLS, "%d bytes insufficient to parse uint%d TLS data", - this->buf.len, 16); + DBG1(DBG_TLS, "%d bytes insufficient to parse u_int16 data", + this->buf.len); return FALSE; } *res = untoh16(this->buf.ptr); @@ -80,8 +80,8 @@ METHOD(tls_reader_t, read_uint24, bool, { if (this->buf.len < 3) { - DBG1(DBG_TLS, "%d bytes insufficient to parse uint%d TLS data", - this->buf.len, 24); + DBG1(DBG_TLS, "%d bytes insufficient to parse u_int24 data", + this->buf.len); return FALSE; } *res = untoh32(this->buf.ptr) >> 8; @@ -94,8 +94,8 @@ METHOD(tls_reader_t, read_uint32, bool, { if (this->buf.len < 4) { - DBG1(DBG_TLS, "%d bytes insufficient to parse uint%d TLS data", - this->buf.len, 32); + DBG1(DBG_TLS, "%d bytes insufficient to parse u_int32 data", + this->buf.len); return FALSE; } *res = untoh32(this->buf.ptr); @@ -108,7 +108,7 @@ METHOD(tls_reader_t, read_data, bool, { if (this->buf.len < len) { - DBG1(DBG_TLS, "%d bytes insufficient to parse %d bytes TLS data", + DBG1(DBG_TLS, "%d bytes insufficient to parse %d bytes of data", this->buf.len, len); return FALSE; } diff --git a/src/libtls/tls_writer.c b/src/libtls/tls_writer.c index 235dc2cdf..e87c2efea 100644 --- a/src/libtls/tls_writer.c +++ b/src/libtls/tls_writer.c @@ -226,7 +226,7 @@ tls_writer_t *tls_writer_create(u_int32_t bufsize) .get_buf = _get_buf, .destroy = _destroy, }, - .increase = bufsize ?: 32, + .increase = bufsize ? max(bufsize, 4) : 32, ); if (bufsize) { diff --git a/src/manager/Makefile.in b/src/manager/Makefile.in index 5073d9686..2e139f839 100644 --- a/src/manager/Makefile.in +++ b/src/manager/Makefile.in @@ -236,9 +236,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -277,6 +275,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/medsrv/Makefile.in b/src/medsrv/Makefile.in index 07315cfd2..9c9662f7f 100644 --- a/src/medsrv/Makefile.in +++ b/src/medsrv/Makefile.in @@ -226,9 +226,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -267,6 +265,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/openac/Makefile.in b/src/openac/Makefile.in index fcac66226..ec4657e55 100644 --- a/src/openac/Makefile.in +++ b/src/openac/Makefile.in @@ -220,9 +220,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -261,6 +259,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/pki/Makefile.in b/src/pki/Makefile.in index 0ec6f9c0b..c6651fdf5 100644 --- a/src/pki/Makefile.in +++ b/src/pki/Makefile.in @@ -197,9 +197,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -238,6 +236,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/pki/command.c b/src/pki/command.c index b9c35d99b..0142b4ab7 100644 --- a/src/pki/command.c +++ b/src/pki/command.c @@ -201,7 +201,7 @@ int command_usage(char *error) } for (i = 0; cmds[active].options[i].name; i++) { - fprintf(out, " --%-8s (-%c) %s\n", + fprintf(out, " --%-15s (-%c) %s\n", cmds[active].options[i].name, cmds[active].options[i].op, cmds[active].options[i].desc); } diff --git a/src/pki/command.h b/src/pki/command.h index fad598c0b..a6f8bc758 100644 --- a/src/pki/command.h +++ b/src/pki/command.h @@ -29,7 +29,7 @@ /** * Maximum number of options in a command (+1) */ -#define MAX_OPTIONS 20 +#define MAX_OPTIONS 32 /** * Maximum number of usage summary lines (+1) diff --git a/src/pki/commands/issue.c b/src/pki/commands/issue.c index 8ea852e31..6a5686d92 100644 --- a/src/pki/commands/issue.c +++ b/src/pki/commands/issue.c @@ -18,12 +18,41 @@ #include "pki.h" #include <debug.h> +#include <asn1/asn1.h> #include <utils/linked_list.h> #include <credentials/certificates/certificate.h> #include <credentials/certificates/x509.h> #include <credentials/certificates/pkcs10.h> /** + * Free cert policy with OID + */ +static void destroy_cert_policy(x509_cert_policy_t *policy) +{ + free(policy->oid.ptr); + free(policy); +} + +/** + * Free policy mapping + */ +static void destroy_policy_mapping(x509_policy_mapping_t *mapping) +{ + free(mapping->issuer.ptr); + free(mapping->subject.ptr); + free(mapping); +} + +/** + * Free a CRL DistributionPoint + */ +static void destroy_cdp(x509_cdp_t *this) +{ + DESTROY_IF(this->issuer); + free(this); +} + +/** * Issue a certificate using a CA certificate and key */ static int issue() @@ -37,19 +66,26 @@ static int issue() char *file = NULL, *dn = NULL, *hex = NULL, *cacert = NULL, *cakey = NULL; char *error = NULL, *keyid = NULL; identification_t *id = NULL; - linked_list_t *san, *cdps, *ocsp; + linked_list_t *san, *cdps, *ocsp, *permitted, *excluded, *policies, *mappings; int lifetime = 1095; - int pathlen = X509_NO_PATH_LEN_CONSTRAINT; + int pathlen = X509_NO_CONSTRAINT, inhibit_any = X509_NO_CONSTRAINT; + int inhibit_mapping = X509_NO_CONSTRAINT, require_explicit = X509_NO_CONSTRAINT; chunk_t serial = chunk_empty; chunk_t encoding = chunk_empty; time_t not_before, not_after; x509_flag_t flags = 0; x509_t *x509; + x509_cdp_t *cdp = NULL; + x509_cert_policy_t *policy = NULL; char *arg; san = linked_list_create(); cdps = linked_list_create(); ocsp = linked_list_create(); + permitted = linked_list_create(); + excluded = linked_list_create(); + policies = linked_list_create(); + mappings = linked_list_create(); while (TRUE) { @@ -111,6 +147,79 @@ static int issue() case 'p': pathlen = atoi(arg); continue; + case 'n': + permitted->insert_last(permitted, + identification_create_from_string(arg)); + continue; + case 'N': + excluded->insert_last(excluded, + identification_create_from_string(arg)); + continue; + case 'P': + { + chunk_t oid; + + oid = asn1_oid_from_string(arg); + if (!oid.len) + { + error = "--cert-policy OID invalid"; + goto usage; + } + INIT(policy, + .oid = oid, + ); + policies->insert_last(policies, policy); + continue; + } + case 'C': + if (!policy) + { + error = "--cps-uri must follow a --cert-policy"; + goto usage; + } + policy->cps_uri = arg; + continue; + case 'U': + if (!policy) + { + error = "--user-notice must follow a --cert-policy"; + goto usage; + } + policy->unotice_text = arg; + continue; + case 'M': + { + char *pos = strchr(arg, ':'); + x509_policy_mapping_t *mapping; + chunk_t subject_oid, issuer_oid; + + if (pos) + { + *pos++ = '\0'; + issuer_oid = asn1_oid_from_string(arg); + subject_oid = asn1_oid_from_string(pos); + } + if (!pos || !issuer_oid.len || !subject_oid.len) + { + error = "--policy-map OIDs invalid"; + goto usage; + } + INIT(mapping, + .issuer = issuer_oid, + .subject = subject_oid, + ); + mappings->insert_last(mappings, mapping); + continue; + } + case 'E': + require_explicit = atoi(arg); + continue; + case 'H': + inhibit_mapping = atoi(arg); + continue; + case 'A': + inhibit_any = atoi(arg); + continue; case 'e': if (streq(arg, "serverAuth")) { @@ -120,6 +229,10 @@ static int issue() { flags |= X509_CLIENT_AUTH; } + else if (streq(arg, "crlSign")) + { + flags |= X509_CRL_SIGN; + } else if (streq(arg, "ocspSigning")) { flags |= X509_OCSP_SIGNER; @@ -128,11 +241,23 @@ static int issue() case 'f': if (!get_form(arg, &form, CRED_CERTIFICATE)) { - return command_usage("invalid output format"); + error = "invalid output format"; + goto usage; } continue; case 'u': - cdps->insert_last(cdps, arg); + INIT(cdp, + .uri = arg, + ); + cdps->insert_last(cdps, cdp); + continue; + case 'I': + if (!cdp || cdp->issuer) + { + error = "--crlissuer must follow a --crl"; + goto usage; + } + cdp->issuer = identification_create_from_string(arg); continue; case 'o': ocsp->insert_last(ocsp, arg); @@ -145,12 +270,6 @@ static int issue() } break; } - - if (!pkcs10 && !dn) - { - error = "--dn is required"; - goto usage; - } if (!cacert) { error = "--cacert is required"; @@ -161,7 +280,7 @@ static int issue() error = "--cakey or --keyid is required"; goto usage; } - if (dn) + if (dn && *dn) { id = identification_create_from_string(dn); if (id->get_type(id) != ID_DER_ASN1_DN) @@ -306,6 +425,12 @@ static int issue() goto end; } + if (!id) + { + id = identification_create_from_encoding(ID_DER_ASN1_DN, + chunk_from_chars(ASN1_SEQUENCE, 0)); + } + not_before = time(NULL); not_after = not_before + lifetime * 24 * 60 * 60; @@ -317,7 +442,15 @@ static int issue() BUILD_SUBJECT_ALTNAMES, san, BUILD_X509_FLAG, flags, BUILD_PATHLEN, pathlen, BUILD_CRL_DISTRIBUTION_POINTS, cdps, - BUILD_OCSP_ACCESS_LOCATIONS, ocsp, BUILD_END); + BUILD_OCSP_ACCESS_LOCATIONS, ocsp, + BUILD_PERMITTED_NAME_CONSTRAINTS, permitted, + BUILD_EXCLUDED_NAME_CONSTRAINTS, excluded, + BUILD_CERTIFICATE_POLICIES, policies, + BUILD_POLICY_MAPPINGS, mappings, + BUILD_POLICY_REQUIRE_EXPLICIT, require_explicit, + BUILD_POLICY_INHIBIT_MAPPING, inhibit_mapping, + BUILD_POLICY_INHIBIT_ANY, inhibit_any, + BUILD_END); if (!cert) { error = "generating certificate failed"; @@ -342,7 +475,11 @@ end: DESTROY_IF(public); DESTROY_IF(private); san->destroy_offset(san, offsetof(identification_t, destroy)); - cdps->destroy(cdps); + permitted->destroy_offset(permitted, offsetof(identification_t, destroy)); + excluded->destroy_offset(excluded, offsetof(identification_t, destroy)); + policies->destroy_function(policies, (void*)destroy_cert_policy); + mappings->destroy_function(mappings, (void*)destroy_policy_mapping); + cdps->destroy_function(cdps, (void*)destroy_cdp); ocsp->destroy(ocsp); free(encoding.ptr); free(serial.ptr); @@ -356,7 +493,11 @@ end: usage: san->destroy_offset(san, offsetof(identification_t, destroy)); - cdps->destroy(cdps); + permitted->destroy_offset(permitted, offsetof(identification_t, destroy)); + excluded->destroy_offset(excluded, offsetof(identification_t, destroy)); + policies->destroy_function(policies, (void*)destroy_cert_policy); + mappings->destroy_function(mappings, (void*)destroy_policy_mapping); + cdps->destroy_function(cdps, (void*)destroy_cdp); ocsp->destroy(ocsp); return command_usage(error); } @@ -370,28 +511,42 @@ static void __attribute__ ((constructor))reg() issue, 'i', "issue", "issue a certificate using a CA certificate and key", {"[--in file] [--type pub|pkcs10] --cakey file | --cakeyid hex", - " --cacert file --dn subject-dn [--san subjectAltName]+", - "[--lifetime days] [--serial hex] [--crl uri]+ [--ocsp uri]+", - "[--ca] [--pathlen len] [--flag serverAuth|clientAuth|ocspSigning]+", + " --cacert file [--dn subject-dn] [--san subjectAltName]+", + "[--lifetime days] [--serial hex] [--crl uri [--crlissuer i] ]+ [--ocsp uri]+", + "[--ca] [--pathlen len] [--flag serverAuth|clientAuth|crlSign|ocspSigning]+", + "[--nc-permitted name] [--nc-excluded name]", + "[--cert-policy oid [--cps-uri uri] [--user-notice text] ]+", + "[--policy-map issuer-oid:subject-oid]", + "[--policy-explicit len] [--policy-inhibit len] [--policy-any len]", "[--digest md5|sha1|sha224|sha256|sha384|sha512] [--outform der|pem]"}, { - {"help", 'h', 0, "show usage information"}, - {"in", 'i', 1, "public key/request file to issue, default: stdin"}, - {"type", 't', 1, "type of input, default: pub"}, - {"cacert", 'c', 1, "CA certificate file"}, - {"cakey", 'k', 1, "CA private key file"}, - {"cakeyid", 'x', 1, "keyid on smartcard of CA private key"}, - {"dn", 'd', 1, "distinguished name to include as subject"}, - {"san", 'a', 1, "subjectAltName to include in certificate"}, - {"lifetime",'l', 1, "days the certificate is valid, default: 1095"}, - {"serial", 's', 1, "serial number in hex, default: random"}, - {"ca", 'b', 0, "include CA basicConstraint, default: no"}, - {"pathlen", 'p', 1, "set path length constraint"}, - {"flag", 'e', 1, "include extendedKeyUsage flag"}, - {"crl", 'u', 1, "CRL distribution point URI to include"}, - {"ocsp", 'o', 1, "OCSP AuthorityInfoAccess URI to include"}, - {"digest", 'g', 1, "digest for signature creation, default: sha1"}, - {"outform", 'f', 1, "encoding of generated cert, default: der"}, + {"help", 'h', 0, "show usage information"}, + {"in", 'i', 1, "public key/request file to issue, default: stdin"}, + {"type", 't', 1, "type of input, default: pub"}, + {"cacert", 'c', 1, "CA certificate file"}, + {"cakey", 'k', 1, "CA private key file"}, + {"cakeyid", 'x', 1, "keyid on smartcard of CA private key"}, + {"dn", 'd', 1, "distinguished name to include as subject"}, + {"san", 'a', 1, "subjectAltName to include in certificate"}, + {"lifetime", 'l', 1, "days the certificate is valid, default: 1095"}, + {"serial", 's', 1, "serial number in hex, default: random"}, + {"ca", 'b', 0, "include CA basicConstraint, default: no"}, + {"pathlen", 'p', 1, "set path length constraint"}, + {"nc-permitted", 'n', 1, "add permitted NameConstraint"}, + {"nc-excluded", 'N', 1, "add excluded NameConstraint"}, + {"cert-policy", 'P', 1, "certificatePolicy OID to include"}, + {"cps-uri", 'C', 1, "Certification Practice statement URI for certificatePolicy"}, + {"user-notice", 'U', 1, "user notice for certificatePolicy"}, + {"policy-mapping", 'M', 1, "policyMapping from issuer to subject OID"}, + {"policy-explicit", 'E', 1, "requireExplicitPolicy constraint"}, + {"policy-inhibit", 'H', 1, "inhibitPolicyMapping constraint"}, + {"policy-any", 'A', 1, "inhibitAnyPolicy constraint"}, + {"flag", 'e', 1, "include extendedKeyUsage flag"}, + {"crl", 'u', 1, "CRL distribution point URI to include"}, + {"crlissuer", 'I', 1, "CRL Issuer for CRL at distribution point"}, + {"ocsp", 'o', 1, "OCSP AuthorityInfoAccess URI to include"}, + {"digest", 'g', 1, "digest for signature creation, default: sha1"}, + {"outform", 'f', 1, "encoding of generated cert, default: der"}, } }); } diff --git a/src/pki/commands/print.c b/src/pki/commands/print.c index 870dca920..ee6f30c98 100644 --- a/src/pki/commands/print.c +++ b/src/pki/commands/print.c @@ -15,6 +15,7 @@ #include "pki.h" +#include <asn1/asn1.h> #include <credentials/certificates/certificate.h> #include <credentials/certificates/x509.h> #include <credentials/certificates/crl.h> @@ -72,8 +73,11 @@ static void print_x509(x509_t *x509) chunk_t chunk; bool first; char *uri; - int len; + int len, explicit, inhibit; x509_flag_t flags; + x509_cdp_t *cdp; + x509_cert_policy_t *policy; + x509_policy_mapping_t *mapping; chunk = x509->get_serial(x509); printf("serial: %#B\n", &chunk); @@ -105,6 +109,10 @@ static void print_x509(x509_t *x509) { printf("CA "); } + if (flags & X509_CRL_SIGN) + { + printf("CRLSign "); + } if (flags & X509_AA) { printf("AA "); @@ -133,17 +141,22 @@ static void print_x509(x509_t *x509) first = TRUE; enumerator = x509->create_crl_uri_enumerator(x509); - while (enumerator->enumerate(enumerator, &uri)) + while (enumerator->enumerate(enumerator, &cdp)) { if (first) { - printf("CRL URIs: %s\n", uri); + printf("CRL URIs: %s", cdp->uri); first = FALSE; } else { - printf(" %s\n", uri); + printf(" %s", cdp->uri); + } + if (cdp->issuer) + { + printf(" (CRL issuer: %Y)", cdp->issuer); } + printf("\n"); } enumerator->destroy(enumerator); @@ -163,12 +176,111 @@ static void print_x509(x509_t *x509) } enumerator->destroy(enumerator); - len = x509->get_pathLenConstraint(x509); - if (len != X509_NO_PATH_LEN_CONSTRAINT) + len = x509->get_constraint(x509, X509_PATH_LEN); + if (len != X509_NO_CONSTRAINT) { printf("pathlen: %d\n", len); } + first = TRUE; + enumerator = x509->create_name_constraint_enumerator(x509, TRUE); + while (enumerator->enumerate(enumerator, &id)) + { + if (first) + { + printf("Permitted NameConstraints:\n"); + first = FALSE; + } + printf(" %Y\n", id); + } + enumerator->destroy(enumerator); + first = TRUE; + enumerator = x509->create_name_constraint_enumerator(x509, FALSE); + while (enumerator->enumerate(enumerator, &id)) + { + if (first) + { + printf("Excluded NameConstraints:\n"); + first = FALSE; + } + printf(" %Y\n", id); + } + enumerator->destroy(enumerator); + + first = TRUE; + enumerator = x509->create_cert_policy_enumerator(x509); + while (enumerator->enumerate(enumerator, &policy)) + { + char *oid; + + if (first) + { + printf("CertificatePolicies:\n"); + first = FALSE; + } + oid = asn1_oid_to_string(policy->oid); + if (oid) + { + printf(" %s\n", oid); + free(oid); + } + else + { + printf(" %#B\n", &policy->oid); + } + if (policy->cps_uri) + { + printf(" CPS: %s\n", policy->cps_uri); + } + if (policy->unotice_text) + { + printf(" Notice: %s\n", policy->unotice_text); + + } + } + enumerator->destroy(enumerator); + + first = TRUE; + enumerator = x509->create_policy_mapping_enumerator(x509); + while (enumerator->enumerate(enumerator, &mapping)) + { + char *issuer_oid, *subject_oid; + + if (first) + { + printf("PolicyMappings:\n"); + first = FALSE; + } + issuer_oid = asn1_oid_to_string(mapping->issuer); + subject_oid = asn1_oid_to_string(mapping->subject); + printf(" %s => %s\n", issuer_oid, subject_oid); + free(issuer_oid); + free(subject_oid); + } + enumerator->destroy(enumerator); + + explicit = x509->get_constraint(x509, X509_REQUIRE_EXPLICIT_POLICY); + inhibit = x509->get_constraint(x509, X509_INHIBIT_POLICY_MAPPING); + len = x509->get_constraint(x509, X509_INHIBIT_ANY_POLICY); + + if (explicit != X509_NO_CONSTRAINT || inhibit != X509_NO_CONSTRAINT || + len != X509_NO_CONSTRAINT) + { + printf("PolicyConstraints:\n"); + if (explicit != X509_NO_CONSTRAINT) + { + printf(" requireExplicitPolicy: %d\n", explicit); + } + if (inhibit != X509_NO_CONSTRAINT) + { + printf(" inhibitPolicyMapping: %d\n", inhibit); + } + if (len != X509_NO_CONSTRAINT) + { + printf(" inhibitAnyPolicy: %d\n", len); + } + } + chunk = x509->get_authKeyIdentifier(x509); if (chunk.ptr) { @@ -212,14 +324,41 @@ static void print_crl(crl_t *crl) crl_reason_t reason; chunk_t chunk; int count = 0; + bool first; char buf[64]; struct tm tm; + x509_cdp_t *cdp; chunk = crl->get_serial(crl); printf("serial: %#B\n", &chunk); + if (crl->is_delta_crl(crl, &chunk)) + { + printf("delta CRL: for serial %#B\n", &chunk); + } chunk = crl->get_authKeyIdentifier(crl); printf("authKeyId: %#B\n", &chunk); + first = TRUE; + enumerator = crl->create_delta_crl_uri_enumerator(crl); + while (enumerator->enumerate(enumerator, &cdp)) + { + if (first) + { + printf("freshest: %s", cdp->uri); + first = FALSE; + } + else + { + printf(" %s", cdp->uri); + } + if (cdp->issuer) + { + printf(" (CRL issuer: %Y)", cdp->issuer); + } + printf("\n"); + } + enumerator->destroy(enumerator); + enumerator = crl->create_enumerator(crl); while (enumerator->enumerate(enumerator, &chunk, &ts, &reason)) { diff --git a/src/pki/commands/self.c b/src/pki/commands/self.c index 5e6f0bd14..c7788ff62 100644 --- a/src/pki/commands/self.c +++ b/src/pki/commands/self.c @@ -20,6 +20,26 @@ #include <utils/linked_list.h> #include <credentials/certificates/certificate.h> #include <credentials/certificates/x509.h> +#include <asn1/asn1.h> + +/** + * Free cert policy with OID + */ +static void destroy_cert_policy(x509_cert_policy_t *policy) +{ + free(policy->oid.ptr); + free(policy); +} + +/** + * Free policy mapping + */ +static void destroy_policy_mapping(x509_policy_mapping_t *mapping) +{ + free(mapping->issuer.ptr); + free(mapping->subject.ptr); + free(mapping); +} /** * Create a self signed certificate. @@ -34,17 +54,23 @@ static int self() public_key_t *public = NULL; char *file = NULL, *dn = NULL, *hex = NULL, *error = NULL, *keyid = NULL; identification_t *id = NULL; - linked_list_t *san, *ocsp; + linked_list_t *san, *ocsp, *permitted, *excluded, *policies, *mappings; int lifetime = 1095; - int pathlen = X509_NO_PATH_LEN_CONSTRAINT; + int pathlen = X509_NO_CONSTRAINT, inhibit_any = X509_NO_CONSTRAINT; + int inhibit_mapping = X509_NO_CONSTRAINT, require_explicit = X509_NO_CONSTRAINT; chunk_t serial = chunk_empty; chunk_t encoding = chunk_empty; time_t not_before, not_after; x509_flag_t flags = 0; + x509_cert_policy_t *policy = NULL; char *arg; san = linked_list_create(); ocsp = linked_list_create(); + permitted = linked_list_create(); + excluded = linked_list_create(); + policies = linked_list_create(); + mappings = linked_list_create(); while (TRUE) { @@ -104,6 +130,79 @@ static int self() case 'p': pathlen = atoi(arg); continue; + case 'n': + permitted->insert_last(permitted, + identification_create_from_string(arg)); + continue; + case 'N': + excluded->insert_last(excluded, + identification_create_from_string(arg)); + continue; + case 'P': + { + chunk_t oid; + + oid = asn1_oid_from_string(arg); + if (!oid.len) + { + error = "--cert-policy OID invalid"; + goto usage; + } + INIT(policy, + .oid = oid, + ); + policies->insert_last(policies, policy); + continue; + } + case 'C': + if (!policy) + { + error = "--cps-uri must follow a --cert-policy"; + goto usage; + } + policy->cps_uri = arg; + continue; + case 'U': + if (!policy) + { + error = "--user-notice must follow a --cert-policy"; + goto usage; + } + policy->unotice_text = arg; + continue; + case 'M': + { + char *pos = strchr(arg, ':'); + x509_policy_mapping_t *mapping; + chunk_t subject_oid, issuer_oid; + + if (pos) + { + *pos++ = '\0'; + issuer_oid = asn1_oid_from_string(arg); + subject_oid = asn1_oid_from_string(pos); + } + if (!pos || !issuer_oid.len || !subject_oid.len) + { + error = "--policy-map OIDs invalid"; + goto usage; + } + INIT(mapping, + .issuer = issuer_oid, + .subject = subject_oid, + ); + mappings->insert_last(mappings, mapping); + continue; + } + case 'E': + require_explicit = atoi(arg); + continue; + case 'H': + inhibit_mapping = atoi(arg); + continue; + case 'A': + inhibit_any = atoi(arg); + continue; case 'e': if (streq(arg, "serverAuth")) { @@ -113,6 +212,10 @@ static int self() { flags |= X509_CLIENT_AUTH; } + else if (streq(arg, "crlSign")) + { + flags |= X509_CRL_SIGN; + } else if (streq(arg, "ocspSigning")) { flags |= X509_OCSP_SIGNER; @@ -121,7 +224,8 @@ static int self() case 'f': if (!get_form(arg, &form, CRED_CERTIFICATE)) { - return command_usage("invalid output format"); + error = "invalid output format"; + goto usage; } continue; case 'o': @@ -206,7 +310,15 @@ static int self() BUILD_NOT_AFTER_TIME, not_after, BUILD_SERIAL, serial, BUILD_DIGEST_ALG, digest, BUILD_X509_FLAG, flags, BUILD_PATHLEN, pathlen, BUILD_SUBJECT_ALTNAMES, san, - BUILD_OCSP_ACCESS_LOCATIONS, ocsp, BUILD_END); + BUILD_OCSP_ACCESS_LOCATIONS, ocsp, + BUILD_PERMITTED_NAME_CONSTRAINTS, permitted, + BUILD_EXCLUDED_NAME_CONSTRAINTS, excluded, + BUILD_CERTIFICATE_POLICIES, policies, + BUILD_POLICY_MAPPINGS, mappings, + BUILD_POLICY_REQUIRE_EXPLICIT, require_explicit, + BUILD_POLICY_INHIBIT_MAPPING, inhibit_mapping, + BUILD_POLICY_INHIBIT_ANY, inhibit_any, + BUILD_END); if (!cert) { error = "generating certificate failed"; @@ -229,6 +341,10 @@ end: DESTROY_IF(public); DESTROY_IF(private); san->destroy_offset(san, offsetof(identification_t, destroy)); + permitted->destroy_offset(permitted, offsetof(identification_t, destroy)); + excluded->destroy_offset(excluded, offsetof(identification_t, destroy)); + policies->destroy_function(policies, (void*)destroy_cert_policy); + mappings->destroy_function(mappings, (void*)destroy_policy_mapping); ocsp->destroy(ocsp); free(encoding.ptr); free(serial.ptr); @@ -242,6 +358,10 @@ end: usage: san->destroy_offset(san, offsetof(identification_t, destroy)); + permitted->destroy_offset(permitted, offsetof(identification_t, destroy)); + excluded->destroy_offset(excluded, offsetof(identification_t, destroy)); + policies->destroy_function(policies, (void*)destroy_cert_policy); + mappings->destroy_function(mappings, (void*)destroy_policy_mapping); ocsp->destroy(ocsp); return command_usage(error); } @@ -257,23 +377,36 @@ static void __attribute__ ((constructor))reg() {"[--in file | --keyid hex] [--type rsa|ecdsa]", " --dn distinguished-name [--san subjectAltName]+", "[--lifetime days] [--serial hex] [--ca] [--ocsp uri]+", - "[--flag serverAuth|clientAuth|ocspSigning]+", + "[--flag serverAuth|clientAuth|crlSign|ocspSigning]+", + "[--nc-permitted name] [--nc-excluded name]", + "[--cert-policy oid [--cps-uri uri] [--user-notice text] ]+", + "[--policy-map issuer-oid:subject-oid]", + "[--policy-explicit len] [--policy-inhibit len] [--policy-any len]", "[--digest md5|sha1|sha224|sha256|sha384|sha512] [--outform der|pem]"}, { - {"help", 'h', 0, "show usage information"}, - {"in", 'i', 1, "private key input file, default: stdin"}, - {"keyid", 'x', 1, "keyid on smartcard of private key"}, - {"type", 't', 1, "type of input key, default: rsa"}, - {"dn", 'd', 1, "subject and issuer distinguished name"}, - {"san", 'a', 1, "subjectAltName to include in certificate"}, - {"lifetime",'l', 1, "days the certificate is valid, default: 1095"}, - {"serial", 's', 1, "serial number in hex, default: random"}, - {"ca", 'b', 0, "include CA basicConstraint, default: no"}, - {"pathlen", 'p', 1, "set path length constraint"}, - {"flag", 'e', 1, "include extendedKeyUsage flag"}, - {"ocsp", 'o', 1, "OCSP AuthorityInfoAccess URI to include"}, - {"digest", 'g', 1, "digest for signature creation, default: sha1"}, - {"outform", 'f', 1, "encoding of generated cert, default: der"}, + {"help", 'h', 0, "show usage information"}, + {"in", 'i', 1, "private key input file, default: stdin"}, + {"keyid", 'x', 1, "keyid on smartcard of private key"}, + {"type", 't', 1, "type of input key, default: rsa"}, + {"dn", 'd', 1, "subject and issuer distinguished name"}, + {"san", 'a', 1, "subjectAltName to include in certificate"}, + {"lifetime", 'l', 1, "days the certificate is valid, default: 1095"}, + {"serial", 's', 1, "serial number in hex, default: random"}, + {"ca", 'b', 0, "include CA basicConstraint, default: no"}, + {"pathlen", 'p', 1, "set path length constraint"}, + {"nc-permitted", 'n', 1, "add permitted NameConstraint"}, + {"nc-excluded", 'N', 1, "add excluded NameConstraint"}, + {"cert-policy", 'P', 1, "certificatePolicy OID to include"}, + {"cps-uri", 'C', 1, "Certification Practice statement URI for certificatePolicy"}, + {"user-notice", 'U', 1, "user notice for certificatePolicy"}, + {"policy-mapping", 'M', 1, "policyMapping from issuer to subject OID"}, + {"policy-explicit", 'E', 1, "requireExplicitPolicy constraint"}, + {"policy-inhibit", 'H', 1, "inhibitPolicyMapping constraint"}, + {"policy-any", 'A', 1, "inhibitAnyPolicy constraint"}, + {"flag", 'e', 1, "include extendedKeyUsage flag"}, + {"ocsp", 'o', 1, "OCSP AuthorityInfoAccess URI to include"}, + {"digest", 'g', 1, "digest for signature creation, default: sha1"}, + {"outform", 'f', 1, "encoding of generated cert, default: der"}, } }); } diff --git a/src/pki/commands/signcrl.c b/src/pki/commands/signcrl.c index 24bf9123f..4b1c12e5c 100644 --- a/src/pki/commands/signcrl.c +++ b/src/pki/commands/signcrl.c @@ -98,6 +98,15 @@ static int read_serial(char *file, char *buf, int buflen) } /** + * Destroy a CDP + */ +static void cdp_destroy(x509_cdp_t *this) +{ + free(this->uri); + free(this); +} + +/** * Sign a CRL */ static int sign_crl() @@ -110,16 +119,19 @@ static int sign_crl() x509_t *x509; hash_algorithm_t digest = HASH_SHA1; char *arg, *cacert = NULL, *cakey = NULL, *lastupdate = NULL, *error = NULL; + char *basecrl = NULL; char serial[512], crl_serial[8], *keyid = NULL; int serial_len = 0; crl_reason_t reason = CRL_REASON_UNSPECIFIED; time_t thisUpdate, nextUpdate, date = time(NULL); int lifetime = 15; - linked_list_t *list; + linked_list_t *list, *cdps; enumerator_t *enumerator, *lastenum = NULL; - chunk_t encoding = chunk_empty; + x509_cdp_t *cdp; + chunk_t encoding = chunk_empty, baseCrlNumber = chunk_empty; list = linked_list_create(); + cdps = linked_list_create(); memset(crl_serial, 0, sizeof(crl_serial)); @@ -190,6 +202,15 @@ static int sign_crl() reason = CRL_REASON_UNSPECIFIED; continue; } + case 'b': + basecrl = arg; + continue; + case 'u': + INIT(cdp, + .uri = strdup(arg), + ); + cdps->insert_last(cdps, cdp); + continue; case 'r': if (streq(arg, "key-compromise")) { @@ -262,9 +283,9 @@ static int sign_crl() goto error; } x509 = (x509_t*)ca; - if (!(x509->get_flags(x509) & X509_CA)) + if (!(x509->get_flags(x509) & (X509_CA | X509_CRL_SIGN))) { - error = "CA certificate misses CA basicConstraint"; + error = "CA certificate misses CA basicConstraint / CRLSign keyUsage"; goto error; } public = ca->get_public_key(ca); @@ -302,6 +323,22 @@ static int sign_crl() thisUpdate = time(NULL); nextUpdate = thisUpdate + lifetime * 24 * 60 * 60; + if (basecrl) + { + lastcrl = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509_CRL, + BUILD_FROM_FILE, basecrl, BUILD_END); + if (!lastcrl) + { + error = "loading base CRL failed"; + goto error; + } + memcpy(crl_serial, lastcrl->get_serial(lastcrl).ptr, + min(lastcrl->get_serial(lastcrl).len, sizeof(crl_serial))); + baseCrlNumber = chunk_clone(lastcrl->get_serial(lastcrl)); + DESTROY_IF((certificate_t*)lastcrl); + lastcrl = NULL; + } + if (lastupdate) { lastcrl = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509_CRL, @@ -315,6 +352,10 @@ static int sign_crl() min(lastcrl->get_serial(lastcrl).len, sizeof(crl_serial))); lastenum = lastcrl->create_enumerator(lastcrl); } + else + { + lastenum = enumerator_create_empty(); + } chunk_increment(chunk_create(crl_serial, sizeof(crl_serial))); @@ -324,11 +365,12 @@ static int sign_crl() BUILD_SIGNING_KEY, private, BUILD_SIGNING_CERT, ca, BUILD_SERIAL, chunk_create(crl_serial, sizeof(crl_serial)), BUILD_NOT_BEFORE_TIME, thisUpdate, BUILD_NOT_AFTER_TIME, nextUpdate, - BUILD_REVOKED_ENUMERATOR, enumerator, BUILD_DIGEST_ALG, digest, - lastenum ? BUILD_REVOKED_ENUMERATOR : BUILD_END, lastenum, + BUILD_REVOKED_ENUMERATOR, enumerator, + BUILD_REVOKED_ENUMERATOR, lastenum, BUILD_DIGEST_ALG, digest, + BUILD_CRL_DISTRIBUTION_POINTS, cdps, BUILD_BASE_CRL, baseCrlNumber, BUILD_END); enumerator->destroy(enumerator); - DESTROY_IF(lastenum); + lastenum->destroy(lastenum); DESTROY_IF((certificate_t*)lastcrl); if (!crl) @@ -353,7 +395,9 @@ error: DESTROY_IF(ca); DESTROY_IF(crl); free(encoding.ptr); + free(baseCrlNumber.ptr); list->destroy_function(list, (void*)revoked_destroy); + cdps->destroy_function(cdps, (void*)cdp_destroy); if (error) { fprintf(stderr, "%s\n", error); @@ -363,6 +407,7 @@ error: usage: list->destroy_function(list, (void*)revoked_destroy); + cdps->destroy_function(cdps, (void*)cdp_destroy); return command_usage(error); } @@ -375,24 +420,27 @@ static void __attribute__ ((constructor))reg() sign_crl, 'c', "signcrl", "issue a CRL using a CA certificate and key", {"--cacert file --cakey file | --cakeyid hex --lifetime days", + "[--lastcrl crl] [--basecrl crl] [--crluri uri ]+", "[ [--reason key-compromise|ca-compromise|affiliation-changed|", " superseded|cessation-of-operation|certificate-hold]", " [--date timestamp]", " --cert file | --serial hex ]*", "[--digest md5|sha1|sha224|sha256|sha384|sha512] [--outform der|pem]"}, { - {"help", 'h', 0, "show usage information"}, - {"cacert", 'c', 1, "CA certificate file"}, - {"cakey", 'k', 1, "CA private key file"}, - {"cakeyid", 'x', 1, "keyid on smartcard of CA private key"}, - {"lifetime",'l', 1, "days the CRL gets a nextUpdate, default: 15"}, - {"lastcrl", 'a', 1, "CRL of lastUpdate to copy revocations from"}, - {"cert", 'z', 1, "certificate file to revoke"}, - {"serial", 's', 1, "hex encoded certificate serial number to revoke"}, - {"reason", 'r', 1, "reason for certificate revocation"}, - {"date", 'd', 1, "revocation date as unix timestamp, default: now"}, - {"digest", 'g', 1, "digest for signature creation, default: sha1"}, - {"outform", 'f', 1, "encoding of generated crl, default: der"}, + {"help", 'h', 0, "show usage information"}, + {"cacert", 'c', 1, "CA certificate file"}, + {"cakey", 'k', 1, "CA private key file"}, + {"cakeyid", 'x', 1, "keyid on smartcard of CA private key"}, + {"lifetime", 'l', 1, "days the CRL gets a nextUpdate, default: 15"}, + {"lastcrl", 'a', 1, "CRL of lastUpdate to copy revocations from"}, + {"basecrl", 'b', 1, "base CRL to create a delta CRL for"}, + {"crluri", 'u', 1, "freshest delta CRL URI to include"}, + {"cert", 'z', 1, "certificate file to revoke"}, + {"serial", 's', 1, "hex encoded certificate serial number to revoke"}, + {"reason", 'r', 1, "reason for certificate revocation"}, + {"date", 'd', 1, "revocation date as unix timestamp, default: now"}, + {"digest", 'g', 1, "digest for signature creation, default: sha1"}, + {"outform", 'f', 1, "encoding of generated crl, default: der"}, } }); } diff --git a/src/pluto/Makefile.in b/src/pluto/Makefile.in index 080530f86..1428854ee 100644 --- a/src/pluto/Makefile.in +++ b/src/pluto/Makefile.in @@ -304,9 +304,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -345,6 +343,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/pluto/ca.c b/src/pluto/ca.c index 2654774fa..add85def8 100644 --- a/src/pluto/ca.c +++ b/src/pluto/ca.c @@ -629,7 +629,7 @@ void add_ca_info(const whack_message_t *msg) if (strncasecmp(msg->ocspuri, "http", 4) == 0) ca->ocspuri = clone_str(msg->ocspuri); else - plog(" ignoring ocspuri with unkown protocol"); + plog(" ignoring ocspuri with unknown protocol"); } /* add crl uris */ diff --git a/src/pluto/crl.c b/src/pluto/crl.c index c8fb107d5..1c9c9a8cc 100644 --- a/src/pluto/crl.c +++ b/src/pluto/crl.c @@ -352,7 +352,7 @@ cert_status_t verify_by_crl(cert_t *cert, time_t *until, time_t *revocationDate, x509crl_t *x509crl; ca_info_t *ca; enumerator_t *enumerator; - char *point; + x509_cdp_t *cdp; ca = get_ca_info(issuer, authKeyID); @@ -376,9 +376,9 @@ cert_status_t verify_by_crl(cert_t *cert, time_t *until, time_t *revocationDate, } enumerator = x509->create_crl_uri_enumerator(x509); - while (enumerator->enumerate(enumerator, &point)) + while (enumerator->enumerate(enumerator, &cdp)) { - add_distribution_point(crluris, point); + add_distribution_point(crluris, cdp->uri); } enumerator->destroy(enumerator); @@ -416,9 +416,9 @@ cert_status_t verify_by_crl(cert_t *cert, time_t *until, time_t *revocationDate, } enumerator = x509->create_crl_uri_enumerator(x509); - while (enumerator->enumerate(enumerator, &point)) + while (enumerator->enumerate(enumerator, &cdp)) { - add_distribution_point(x509crl->distributionPoints, point); + add_distribution_point(x509crl->distributionPoints, cdp->uri); } enumerator->destroy(enumerator); diff --git a/src/pluto/crypto.c b/src/pluto/crypto.c index 0684de618..f01966c72 100644 --- a/src/pluto/crypto.c +++ b/src/pluto/crypto.c @@ -26,14 +26,15 @@ static struct encrypt_desc encrypt_desc_3des = { - algo_type: IKE_ALG_ENCRYPT, - algo_id: OAKLEY_3DES_CBC, - algo_next: NULL, - - 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, + algo_type: IKE_ALG_ENCRYPT, + algo_id: OAKLEY_3DES_CBC, + plugin_name: NULL, + algo_next: NULL, + + 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, }; #define AES_KEY_MIN_LEN 128 @@ -42,14 +43,15 @@ static struct encrypt_desc encrypt_desc_3des = static struct encrypt_desc encrypt_desc_aes = { - algo_type: IKE_ALG_ENCRYPT, - algo_id: OAKLEY_AES_CBC, - algo_next: NULL, - - enc_blocksize: AES_BLOCK_SIZE, - keyminlen: AES_KEY_MIN_LEN, - keydeflen: AES_KEY_DEF_LEN, - keymaxlen: AES_KEY_MAX_LEN, + algo_type: IKE_ALG_ENCRYPT, + algo_id: OAKLEY_AES_CBC, + plugin_name: NULL, + algo_next: NULL, + + enc_blocksize: AES_BLOCK_SIZE, + keyminlen: AES_KEY_MIN_LEN, + keydeflen: AES_KEY_DEF_LEN, + keymaxlen: AES_KEY_MAX_LEN, }; #define CAMELLIA_KEY_MIN_LEN 128 @@ -58,14 +60,15 @@ static struct encrypt_desc encrypt_desc_aes = 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, + algo_type: IKE_ALG_ENCRYPT, + algo_id: OAKLEY_CAMELLIA_CBC, + plugin_name: NULL, + 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 @@ -73,14 +76,15 @@ static struct encrypt_desc encrypt_desc_camellia = static struct encrypt_desc encrypt_desc_blowfish = { - algo_type: IKE_ALG_ENCRYPT, - algo_id: OAKLEY_BLOWFISH_CBC, - algo_next: NULL, - - enc_blocksize: BLOWFISH_BLOCK_SIZE, - keyminlen: BLOWFISH_KEY_MIN_LEN, - keydeflen: BLOWFISH_KEY_MIN_LEN, - keymaxlen: BLOWFISH_KEY_MAX_LEN, + algo_type: IKE_ALG_ENCRYPT, + algo_id: OAKLEY_BLOWFISH_CBC, + plugin_name: NULL, + algo_next: NULL, + + enc_blocksize: BLOWFISH_BLOCK_SIZE, + keyminlen: BLOWFISH_KEY_MIN_LEN, + keydeflen: BLOWFISH_KEY_MIN_LEN, + keymaxlen: BLOWFISH_KEY_MAX_LEN, }; #define SERPENT_KEY_MIN_LEN 128 @@ -89,14 +93,15 @@ static struct encrypt_desc encrypt_desc_blowfish = static struct encrypt_desc encrypt_desc_serpent = { - algo_type: IKE_ALG_ENCRYPT, - algo_id: OAKLEY_SERPENT_CBC, - algo_next: NULL, - - enc_blocksize: SERPENT_BLOCK_SIZE, - keyminlen: SERPENT_KEY_MIN_LEN, - keydeflen: SERPENT_KEY_DEF_LEN, - keymaxlen: SERPENT_KEY_MAX_LEN, + algo_type: IKE_ALG_ENCRYPT, + algo_id: OAKLEY_SERPENT_CBC, + plugin_name: NULL, + algo_next: NULL, + + enc_blocksize: SERPENT_BLOCK_SIZE, + keyminlen: SERPENT_KEY_MIN_LEN, + keydeflen: SERPENT_KEY_DEF_LEN, + keymaxlen: SERPENT_KEY_MAX_LEN, }; #define TWOFISH_KEY_MIN_LEN 128 @@ -105,32 +110,35 @@ static struct encrypt_desc encrypt_desc_serpent = static struct encrypt_desc encrypt_desc_twofish = { - algo_type: IKE_ALG_ENCRYPT, - algo_id: OAKLEY_TWOFISH_CBC, - algo_next: NULL, - - enc_blocksize: TWOFISH_BLOCK_SIZE, - keydeflen: TWOFISH_KEY_MIN_LEN, - keyminlen: TWOFISH_KEY_DEF_LEN, - keymaxlen: TWOFISH_KEY_MAX_LEN, + algo_type: IKE_ALG_ENCRYPT, + algo_id: OAKLEY_TWOFISH_CBC, + plugin_name: NULL, + algo_next: NULL, + + enc_blocksize: TWOFISH_BLOCK_SIZE, + keydeflen: TWOFISH_KEY_MIN_LEN, + keyminlen: TWOFISH_KEY_DEF_LEN, + keymaxlen: TWOFISH_KEY_MAX_LEN, }; static struct encrypt_desc encrypt_desc_twofish_ssh = { - algo_type: IKE_ALG_ENCRYPT, - algo_id: OAKLEY_TWOFISH_CBC_SSH, - algo_next: NULL, - - enc_blocksize: TWOFISH_BLOCK_SIZE, - keydeflen: TWOFISH_KEY_MIN_LEN, - keyminlen: TWOFISH_KEY_DEF_LEN, - keymaxlen: TWOFISH_KEY_MAX_LEN, + algo_type: IKE_ALG_ENCRYPT, + algo_id: OAKLEY_TWOFISH_CBC_SSH, + plugin_name: NULL, + algo_next: NULL, + + enc_blocksize: TWOFISH_BLOCK_SIZE, + keydeflen: TWOFISH_KEY_MIN_LEN, + keyminlen: TWOFISH_KEY_DEF_LEN, + keymaxlen: TWOFISH_KEY_MAX_LEN, }; static struct hash_desc hash_desc_md5 = { algo_type: IKE_ALG_HASH, algo_id: OAKLEY_MD5, + plugin_name: NULL, algo_next: NULL, hash_digest_size: HASH_SIZE_MD5, }; @@ -139,6 +147,7 @@ static struct hash_desc hash_desc_sha1 = { algo_type: IKE_ALG_HASH, algo_id: OAKLEY_SHA, + plugin_name: NULL, algo_next: NULL, hash_digest_size: HASH_SIZE_SHA1, }; @@ -146,6 +155,7 @@ static struct hash_desc hash_desc_sha1 = static struct hash_desc hash_desc_sha2_256 = { algo_type: IKE_ALG_HASH, algo_id: OAKLEY_SHA2_256, + plugin_name: NULL, algo_next: NULL, hash_digest_size: HASH_SIZE_SHA256, }; @@ -153,6 +163,7 @@ static struct hash_desc hash_desc_sha2_256 = { static struct hash_desc hash_desc_sha2_384 = { algo_type: IKE_ALG_HASH, algo_id: OAKLEY_SHA2_384, + plugin_name: NULL, algo_next: NULL, hash_digest_size: HASH_SIZE_SHA384, }; @@ -160,120 +171,136 @@ static struct hash_desc hash_desc_sha2_384 = { static struct hash_desc hash_desc_sha2_512 = { algo_type: IKE_ALG_HASH, algo_id: OAKLEY_SHA2_512, + plugin_name: NULL, algo_next: NULL, hash_digest_size: HASH_SIZE_SHA512, }; const struct dh_desc unset_group = { - algo_type: IKE_ALG_DH_GROUP, - algo_id: MODP_NONE, - algo_next: NULL, - ke_size: 0 + algo_type: IKE_ALG_DH_GROUP, + algo_id: MODP_NONE, + plugin_name: NULL, + algo_next: NULL, + ke_size: 0 }; static struct dh_desc dh_desc_modp_1024 = { - algo_type: IKE_ALG_DH_GROUP, - algo_id: MODP_1024_BIT, - algo_next: NULL, - ke_size: 1024 / BITS_PER_BYTE + algo_type: IKE_ALG_DH_GROUP, + algo_id: MODP_1024_BIT, + plugin_name: NULL, + algo_next: NULL, + ke_size: 1024 / BITS_PER_BYTE }; static struct dh_desc dh_desc_modp_1536 = { - algo_type: IKE_ALG_DH_GROUP, - algo_id: MODP_1536_BIT, - algo_next: NULL, - ke_size: 1536 / BITS_PER_BYTE + algo_type: IKE_ALG_DH_GROUP, + algo_id: MODP_1536_BIT, + plugin_name: NULL, + algo_next: NULL, + ke_size: 1536 / BITS_PER_BYTE }; static struct dh_desc dh_desc_modp_2048 = { - algo_type: IKE_ALG_DH_GROUP, - algo_id: MODP_2048_BIT, - algo_next: NULL, - ke_size: 2048 / BITS_PER_BYTE + algo_type: IKE_ALG_DH_GROUP, + algo_id: MODP_2048_BIT, + algo_next: NULL, + ke_size: 2048 / BITS_PER_BYTE }; static struct dh_desc dh_desc_modp_3072 = { - algo_type: IKE_ALG_DH_GROUP, - algo_id: MODP_3072_BIT, - algo_next: NULL, - ke_size: 3072 / BITS_PER_BYTE + algo_type: IKE_ALG_DH_GROUP, + algo_id: MODP_3072_BIT, + plugin_name: NULL, + algo_next: NULL, + ke_size: 3072 / BITS_PER_BYTE }; static struct dh_desc dh_desc_modp_4096 = { - algo_type: IKE_ALG_DH_GROUP, - algo_id: MODP_4096_BIT, - algo_next: NULL, - ke_size: 4096 / BITS_PER_BYTE + algo_type: IKE_ALG_DH_GROUP, + algo_id: MODP_4096_BIT, + plugin_name: NULL, + algo_next: NULL, + ke_size: 4096 / BITS_PER_BYTE }; static struct dh_desc dh_desc_modp_6144 = { - algo_type: IKE_ALG_DH_GROUP, - algo_id: MODP_6144_BIT, - algo_next: NULL, - ke_size: 6144 / BITS_PER_BYTE + algo_type: IKE_ALG_DH_GROUP, + algo_id: MODP_6144_BIT, + plugin_name: NULL, + algo_next: NULL, + ke_size: 6144 / BITS_PER_BYTE }; static struct dh_desc dh_desc_modp_8192 = { - algo_type: IKE_ALG_DH_GROUP, - algo_id: MODP_8192_BIT, - algo_next: NULL, - ke_size: 8192 / BITS_PER_BYTE + algo_type: IKE_ALG_DH_GROUP, + algo_id: MODP_8192_BIT, + plugin_name: NULL, + algo_next: NULL, + ke_size: 8192 / BITS_PER_BYTE }; static struct dh_desc dh_desc_ecp_256 = { - algo_type: IKE_ALG_DH_GROUP, - algo_id: ECP_256_BIT, - algo_next: NULL, - ke_size: 2*256 / BITS_PER_BYTE + algo_type: IKE_ALG_DH_GROUP, + algo_id: ECP_256_BIT, + plugin_name: NULL, + algo_next: NULL, + ke_size: 2*256 / BITS_PER_BYTE }; static struct dh_desc dh_desc_ecp_384 = { - algo_type: IKE_ALG_DH_GROUP, - algo_id: ECP_384_BIT, - algo_next: NULL, - ke_size: 2*384 / BITS_PER_BYTE + algo_type: IKE_ALG_DH_GROUP, + algo_id: ECP_384_BIT, + plugin_name: NULL, + algo_next: NULL, + ke_size: 2*384 / BITS_PER_BYTE }; static struct dh_desc dh_desc_ecp_521 = { - algo_type: IKE_ALG_DH_GROUP, - algo_id: ECP_521_BIT, - algo_next: NULL, - ke_size: 2*528 / BITS_PER_BYTE + algo_type: IKE_ALG_DH_GROUP, + algo_id: ECP_521_BIT, + plugin_name: NULL, + algo_next: NULL, + ke_size: 2*528 / BITS_PER_BYTE }; static struct dh_desc dh_desc_modp_1024_160 = { - algo_type: IKE_ALG_DH_GROUP, - algo_id: MODP_1024_160, - algo_next: NULL, - ke_size: 1024 / BITS_PER_BYTE + algo_type: IKE_ALG_DH_GROUP, + algo_id: MODP_1024_160, + plugin_name: NULL, + algo_next: NULL, + ke_size: 1024 / BITS_PER_BYTE }; static struct dh_desc dh_desc_modp_2048_224 = { - algo_type: IKE_ALG_DH_GROUP, - algo_id: MODP_2048_224, - algo_next: NULL, - ke_size: 2048 / BITS_PER_BYTE + algo_type: IKE_ALG_DH_GROUP, + algo_id: MODP_2048_224, + plugin_name: NULL, + algo_next: NULL, + ke_size: 2048 / BITS_PER_BYTE }; static struct dh_desc dh_desc_modp_2048_256 = { - algo_type: IKE_ALG_DH_GROUP, - algo_id: MODP_2048_256, - algo_next: NULL, - ke_size: 2048 / BITS_PER_BYTE + algo_type: IKE_ALG_DH_GROUP, + algo_id: MODP_2048_256, + plugin_name: NULL, + algo_next: NULL, + ke_size: 2048 / BITS_PER_BYTE }; static struct dh_desc dh_desc_ecp_192 = { - algo_type: IKE_ALG_DH_GROUP, - algo_id: ECP_192_BIT, - algo_next: NULL, - ke_size: 2*192 / BITS_PER_BYTE + algo_type: IKE_ALG_DH_GROUP, + algo_id: ECP_192_BIT, + plugin_name: NULL, + algo_next: NULL, + ke_size: 2*192 / BITS_PER_BYTE }; static struct dh_desc dh_desc_ecp_224 = { algo_type: IKE_ALG_DH_GROUP, algo_id: ECP_224_BIT, - algo_next: NULL, - ke_size: 2*224 / BITS_PER_BYTE + plugin_name: NULL, + algo_next: NULL, + ke_size: 2*224 / BITS_PER_BYTE }; bool init_crypto(void) @@ -282,11 +309,12 @@ bool init_crypto(void) encryption_algorithm_t encryption_alg; hash_algorithm_t hash_alg; diffie_hellman_group_t dh_group; + const char *plugin_name; bool no_md5 = TRUE; bool no_sha1 = TRUE; enumerator = lib->crypto->create_hasher_enumerator(lib->crypto); - while (enumerator->enumerate(enumerator, &hash_alg)) + while (enumerator->enumerate(enumerator, &hash_alg, &plugin_name)) { const struct hash_desc *desc; @@ -312,7 +340,7 @@ bool init_crypto(void) default: continue; } - ike_alg_add((struct ike_alg *)desc); + ike_alg_add((struct ike_alg *)desc, plugin_name); } enumerator->destroy(enumerator); @@ -326,7 +354,7 @@ bool init_crypto(void) } enumerator = lib->crypto->create_crypter_enumerator(lib->crypto); - while (enumerator->enumerate(enumerator, &encryption_alg)) + while (enumerator->enumerate(enumerator, &encryption_alg, &plugin_name)) { const struct encrypt_desc *desc; @@ -346,7 +374,8 @@ bool init_crypto(void) break; case ENCR_TWOFISH_CBC: desc = &encrypt_desc_twofish; - ike_alg_add((struct ike_alg *)&encrypt_desc_twofish_ssh); + ike_alg_add((struct ike_alg *)&encrypt_desc_twofish_ssh, + plugin_name); break; case ENCR_SERPENT_CBC: desc = &encrypt_desc_serpent; @@ -354,12 +383,12 @@ bool init_crypto(void) default: continue; } - ike_alg_add((struct ike_alg *)desc); + ike_alg_add((struct ike_alg *)desc, plugin_name); } enumerator->destroy(enumerator); enumerator = lib->crypto->create_dh_enumerator(lib->crypto); - while (enumerator->enumerate(enumerator, &dh_group)) + while (enumerator->enumerate(enumerator, &dh_group, &plugin_name)) { const struct dh_desc *desc; @@ -413,7 +442,7 @@ bool init_crypto(void) default: continue; } - ike_alg_add((struct ike_alg *)desc); + ike_alg_add((struct ike_alg *)desc, plugin_name); } enumerator->destroy(enumerator); return TRUE; diff --git a/src/pluto/demux.c b/src/pluto/demux.c index 0590a3585..249e645ed 100644 --- a/src/pluto/demux.c +++ b/src/pluto/demux.c @@ -1147,7 +1147,7 @@ read_packet(struct msg_digest *md) } else if (from_ugh != NULL) { - plog("recvfrom on %s returned misformed source sockaddr: %s" + plog("recvfrom on %s returned malformed source sockaddr: %s" , ifp->rname, from_ugh); return FALSE; } diff --git a/src/pluto/ike_alg.c b/src/pluto/ike_alg.c index 08353907e..a36b5ce4e 100644 --- a/src/pluto/ike_alg.c +++ b/src/pluto/ike_alg.c @@ -72,7 +72,7 @@ static struct ike_alg *ike_alg_find(u_int algo_type, u_int algo_id, /** * "raw" ike_alg list adding function */ -int ike_alg_add(struct ike_alg* a) +int ike_alg_add(struct ike_alg* a, const char *plugin_name) { if (a->algo_type > IKE_ALG_MAX) { @@ -96,6 +96,7 @@ int ike_alg_add(struct ike_alg* a) e = *ep; } *ep = a; + a->plugin_name = plugin_name; a->algo_next = e; return 0; } @@ -304,63 +305,71 @@ fail: } /** + * Print the name of an algorithm plus the name of the plugin that registered it + */ +static void print_alg(char *buf, int *len, enum_names *alg_names, int alg_type, + const char *plugin_name) +{ + char alg_name[BUF_LEN]; + int alg_name_len; + + alg_name_len = sprintf(alg_name, " %s[%s]", enum_name(alg_names, alg_type), + plugin_name); + if (*len + alg_name_len > CRYPTO_MAX_ALG_LINE) + { + whack_log(RC_COMMENT, "%s", buf); + *len = sprintf(buf, " "); + } + sprintf(buf + *len, "%s", alg_name); + *len += alg_name_len; +} + +/** * Show registered IKE algorithms */ void ike_alg_list(void) { + rng_quality_t quality; + enumerator_t *enumerator; + const char *plugin_name; char buf[BUF_LEN]; - char *pos; - int n, len; + int len; struct ike_alg *a; whack_log(RC_COMMENT, " "); whack_log(RC_COMMENT, "List of registered IKEv1 Algorithms:"); whack_log(RC_COMMENT, " "); - pos = buf; - *pos = '\0'; - len = BUF_LEN; + len = sprintf(buf, " encryption:"); for (a = ike_alg_base[IKE_ALG_ENCRYPT]; a != NULL; a = a->algo_next) { - n = snprintf(pos, len, " %s", enum_name(&oakley_enc_names, a->algo_id)); - pos += n; - len -= n; - if (len <= 0) - { - break; - } + print_alg(buf, &len, &oakley_enc_names, a->algo_id, a->plugin_name); } - whack_log(RC_COMMENT, " encryption:%s", buf); + whack_log(RC_COMMENT, "%s", buf); - pos = buf; - *pos = '\0'; - len = BUF_LEN; + len = sprintf(buf, " integrity: "); for (a = ike_alg_base[IKE_ALG_HASH]; a != NULL; a = a->algo_next) { - n = snprintf(pos, len, " %s", enum_name(&oakley_hash_names, a->algo_id)); - pos += n; - len -= n; - if (len <= 0) - { - break; - } + print_alg(buf, &len, &oakley_hash_names, a->algo_id, a->plugin_name); } - whack_log(RC_COMMENT, " integrity: %s", buf); + whack_log(RC_COMMENT, "%s", buf); - pos = buf; - *pos = '\0'; - len = BUF_LEN; + len = sprintf(buf, " dh-group: "); for (a = ike_alg_base[IKE_ALG_DH_GROUP]; a != NULL; a = a->algo_next) { - n = snprintf(pos, len, " %s", enum_name(&oakley_group_names, a->algo_id)); - pos += n; - len -= n; - if (len <= 0) - { - break; - } + print_alg(buf, &len, &oakley_group_names, a->algo_id, a->plugin_name); + } + whack_log(RC_COMMENT, "%s", buf); + + len = sprintf(buf, " random-gen:"); + enumerator = lib->crypto->create_rng_enumerator(lib->crypto); + while (enumerator->enumerate(enumerator, &quality, &plugin_name)) + { + len += sprintf(buf + len, " %N[%s]", rng_quality_names, quality, + plugin_name); } - whack_log(RC_COMMENT, " dh-group: %s", buf); + enumerator->destroy(enumerator); + whack_log(RC_COMMENT, "%s", buf); } /** diff --git a/src/pluto/ike_alg.h b/src/pluto/ike_alg.h index 458d14c3a..c3ce8bb38 100644 --- a/src/pluto/ike_alg.h +++ b/src/pluto/ike_alg.h @@ -22,12 +22,14 @@ struct ike_alg { u_int16_t algo_type; u_int16_t algo_id; + const char *plugin_name; struct ike_alg *algo_next; }; struct encrypt_desc { u_int16_t algo_type; u_int16_t algo_id; + const char *plugin_name; struct ike_alg *algo_next; size_t enc_blocksize; @@ -39,6 +41,7 @@ struct encrypt_desc { struct hash_desc { u_int16_t algo_type; u_int16_t algo_id; + const char *plugin_name; struct ike_alg *algo_next; size_t hash_digest_size; @@ -47,6 +50,7 @@ struct hash_desc { struct dh_desc { u_int16_t algo_type; u_int16_t algo_id; + const char *plugin_name; struct ike_alg *algo_next; size_t ke_size; @@ -57,7 +61,7 @@ struct dh_desc { #define IKE_ALG_DH_GROUP 2 #define IKE_ALG_MAX IKE_ALG_DH_GROUP -extern int ike_alg_add(struct ike_alg *a); +extern int ike_alg_add(struct ike_alg *a, const char *plugin_name); extern struct hash_desc *ike_alg_get_hasher(u_int alg); extern struct encrypt_desc *ike_alg_get_crypter(u_int alg); extern struct dh_desc *ike_alg_get_dh_group(u_int alg); diff --git a/src/pluto/kernel.c b/src/pluto/kernel.c index e57822ffb..104b6c2d4 100644 --- a/src/pluto/kernel.c +++ b/src/pluto/kernel.c @@ -1183,7 +1183,7 @@ static bool setup_half_ipsec_sa(struct state *st, bool inbound) if (hydra->kernel_interface->add_sa(hydra->kernel_interface, host_src, host_dst, ipcomp_spi, said_next->proto, c->spd.reqid, - mark, <_none, ENCR_UNDEFINED, chunk_empty, + mark, 0, <_none, ENCR_UNDEFINED, chunk_empty, AUTH_UNDEFINED, chunk_empty, mode, st->st_ipcomp.attrs.transid, 0 /* cpi */, FALSE, inbound, NULL, NULL) != SUCCESS) @@ -1292,7 +1292,7 @@ static bool setup_half_ipsec_sa(struct state *st, bool inbound) if (hydra->kernel_interface->add_sa(hydra->kernel_interface, host_src, host_dst, esp_spi, said_next->proto, c->spd.reqid, - mark, <_none, enc_alg, enc_key, + mark, 0, <_none, enc_alg, enc_key, auth_alg, auth_key, mode, IPCOMP_NONE, 0 /* cpi */, encap, inbound, NULL, NULL) != SUCCESS) { @@ -1325,7 +1325,7 @@ static bool setup_half_ipsec_sa(struct state *st, bool inbound) if (hydra->kernel_interface->add_sa(hydra->kernel_interface, host_src, host_dst, ah_spi, said_next->proto, c->spd.reqid, - mark, <_none, ENCR_UNDEFINED, chunk_empty, + mark, 0, <_none, ENCR_UNDEFINED, chunk_empty, auth_alg, auth_key, mode, IPCOMP_NONE, 0 /* cpi */, FALSE, inbound, NULL, NULL) != SUCCESS) { diff --git a/src/pluto/kernel_alg.c b/src/pluto/kernel_alg.c index 2a195cffc..c82c376f8 100644 --- a/src/pluto/kernel_alg.c +++ b/src/pluto/kernel_alg.c @@ -397,55 +397,55 @@ struct sadb_alg* kernel_alg_esp_sadb_alg(u_int alg_id) return sadb_alg; } +/** + * Print the name of a kernel algorithm + */ +static void print_alg(char *buf, int *len, enum_names *alg_names, int alg_type) +{ + char alg_name[BUF_LEN]; + int alg_name_len; + + alg_name_len = sprintf(alg_name, " %s", enum_name(alg_names, alg_type)); + if (*len + alg_name_len > CRYPTO_MAX_ALG_LINE) + { + whack_log(RC_COMMENT, "%s", buf); + *len = sprintf(buf, " "); + } + sprintf(buf + *len, "%s", alg_name); + *len += alg_name_len; +} + void kernel_alg_list(void) { char buf[BUF_LEN]; - char *pos; - int n, len; + int len; u_int sadb_id; whack_log(RC_COMMENT, " "); whack_log(RC_COMMENT, "List of registered ESP Algorithms:"); whack_log(RC_COMMENT, " "); - pos = buf; - *pos = '\0'; - len = BUF_LEN; + len = sprintf(buf, " encryption:"); for (sadb_id = 1; sadb_id <= SADB_EALG_MAX; sadb_id++) { if (ESP_EALG_PRESENT(sadb_id)) { - n = snprintf(pos, len, " %s", - enum_name(&esp_transform_names, sadb_id)); - pos += n; - len -= n; - if (len <= 0) - { - break; - } + print_alg(buf, &len, &esp_transform_names, sadb_id); } } - whack_log(RC_COMMENT, " encryption:%s", buf); + whack_log(RC_COMMENT, "%s", buf); - pos = buf; - *pos = '\0'; - len = BUF_LEN; + len = sprintf(buf, " integrity: "); for (sadb_id = 1; sadb_id <= SADB_AALG_MAX; sadb_id++) { if (ESP_AALG_PRESENT(sadb_id)) { u_int aaid = alg_info_esp_sadb2aa(sadb_id); - n = snprintf(pos, len, " %s", enum_name(&auth_alg_names, aaid)); - pos += n; - len -= n; - if (len <= 0) - { - break; - } + print_alg(buf, &len, &auth_alg_names, aaid); } } - whack_log(RC_COMMENT, " integrity: %s", buf); + whack_log(RC_COMMENT, "%s", buf); } void kernel_alg_show_connection(connection_t *c, const char *instance) diff --git a/src/pluto/keys.c b/src/pluto/keys.c index a79c2c0d2..86b46c6c1 100644 --- a/src/pluto/keys.c +++ b/src/pluto/keys.c @@ -902,6 +902,7 @@ static void process_secret(secret_t *s, int whackfd) { loglog(RC_LOG_SERIOUS, "\"%s\" line %d: %s" , flp->filename, flp->lino, ugh); + s->ids->destroy_offset(s->ids, offsetof(identification_t, destroy)); free(s); } else if (flushline("expected record boundary in key")) @@ -1010,8 +1011,11 @@ static void process_secret_records(int whackfd) if (!shift()) { /* unexpected Record Boundary or EOF */ - loglog(RC_LOG_SERIOUS, "\"%s\" line %d: unexpected end of id list" - , flp->filename, flp->lino); + loglog(RC_LOG_SERIOUS, "\"%s\" line %d: unexpected end" + " of id list", flp->filename, flp->lino); + s->ids->destroy_offset(s->ids, + offsetof(identification_t, destroy)); + free(s); break; } } diff --git a/src/pluto/ocsp.c b/src/pluto/ocsp.c index 8a351be6d..a3694b7b5 100644 --- a/src/pluto/ocsp.c +++ b/src/pluto/ocsp.c @@ -1045,8 +1045,8 @@ static bool valid_ocsp_response(response_t *res) ) /* check path length constraint */ - pathlen_constraint = x509->get_pathLenConstraint(x509); - if (pathlen_constraint != X509_NO_PATH_LEN_CONSTRAINT && + pathlen_constraint = x509->get_constraint(x509, X509_PATH_LEN); + if (pathlen_constraint != X509_NO_CONSTRAINT && pathlen > pathlen_constraint) { plog("path length of %d violates constraint of %d", diff --git a/src/pluto/plugins/xauth/Makefile.in b/src/pluto/plugins/xauth/Makefile.in index b2ffb11db..358805cc4 100644 --- a/src/pluto/plugins/xauth/Makefile.in +++ b/src/pluto/plugins/xauth/Makefile.in @@ -218,9 +218,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -259,6 +257,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/pluto/pluto.8 b/src/pluto/pluto.8 index 58cb15091..9ac537bd9 100644 --- a/src/pluto/pluto.8 +++ b/src/pluto/pluto.8 @@ -1,8 +1,8 @@ .TH IPSEC_PLUTO 8 "28 March 1999" .SH NAME -ipsec pluto \- IPsec IKE keying daemon -.br -ipsec whack \- control interface for IPSEC keying daemon +pluto \- IPsec IKE keying daemon and control interface +.PP +whack \- control interface for IKE keying daemon .SH SYNOPSIS .na .nh @@ -1009,7 +1009,7 @@ specifies the name of the operation to be performed \fBup-host\fP, \fBup-client\fP, \fBdown-host\fP, or \fBdown-client\fP). If the address family for security gateway to security gateway communications is IPv6, then -a suffix of -v6 is added to the verb. +a suffix of \-v6 is added to the verb. .TP \fBPLUTO_CONNECTION\fP is the name of the connection for which we are routing. @@ -1571,7 +1571,7 @@ rejected with ECONNREFUSED (kernel supplied no details)''. John Denker suggests that this command is useful for tracking down the source of these problems: .br - tcpdump -i eth0 icmp[0] != 8 and icmp[0] != 0 + tcpdump \-i eth0 icmp[0] != 8 and icmp[0] != 0 .br Substitute your public interface for eth0 if it is different. .LP diff --git a/src/pluto/x509.c b/src/pluto/x509.c index d717beb15..7e2aca862 100644 --- a/src/pluto/x509.c +++ b/src/pluto/x509.c @@ -255,8 +255,8 @@ bool verify_x509cert(cert_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_constraint = x509->get_constraint(x509, X509_PATH_LEN); + if (pathlen_constraint != X509_NO_CONSTRAINT && pathlen > pathlen_constraint) { plog("path length of %d violates constraint of %d", @@ -450,8 +450,8 @@ void list_x509cert_chain(const char *caption, cert_t* cert, } /* list optional pathLenConstraint */ - pathlen = x509->get_pathLenConstraint(x509); - if (pathlen != X509_NO_PATH_LEN_CONSTRAINT) + pathlen = x509->get_constraint(x509, X509_PATH_LEN); + if (pathlen != X509_NO_CONSTRAINT) { whack_log(RC_COMMENT, " pathlen: %d", pathlen); } diff --git a/src/scepclient/Makefile.in b/src/scepclient/Makefile.in index a20fa2eb9..623585f65 100644 --- a/src/scepclient/Makefile.in +++ b/src/scepclient/Makefile.in @@ -228,9 +228,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -269,6 +267,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/scepclient/scepclient.8 b/src/scepclient/scepclient.8 index 4b5234da2..72750e155 100644 --- a/src/scepclient/scepclient.8 +++ b/src/scepclient/scepclient.8 @@ -239,12 +239,12 @@ Log raw hex dumps. .PP .B \-C, \-\-debug\-control .RS 4 -Log informations about control flow. +Log information about control flow. .RE .PP .B \-M, \-\-debug\-controlmore .RS 4 -Log more detailed informations about control flow. +Log more detailed information about control flow. .RE .PP .B \-X, \-\-debug\-private diff --git a/src/starter/Makefile.am b/src/starter/Makefile.am index 75297f767..f05aeca22 100644 --- a/src/starter/Makefile.am +++ b/src/starter/Makefile.am @@ -25,7 +25,6 @@ AM_CFLAGS = \ starter_LDADD = defs.o $(top_builddir)/src/libfreeswan/libfreeswan.a $(top_builddir)/src/libstrongswan/libstrongswan.la $(SOCKLIB) EXTRA_DIST = parser.l parser.y keywords.txt ipsec.conf -dist_man_MANS = starter.8 MAINTAINERCLEANFILES = lex.yy.c y.tab.c y.tab.h keywords.c PLUTODIR=$(top_srcdir)/src/pluto @@ -59,14 +58,14 @@ defs.o: $(PLUTODIR)/defs.c $(PLUTODIR)/defs.h $(COMPILE) -c -o $@ $(PLUTODIR)/defs.c install-exec-local : - test -e "$(DESTDIR)${sysconfdir}/ipsec.d" || $(INSTALL) -o ${ipsecuid} -g ${ipsecgid} -d "$(DESTDIR)$(sysconfdir)/ipsec.d" || true - test -e "$(DESTDIR)${sysconfdir}/ipsec.d/cacerts" || $(INSTALL) -o ${ipsecuid} -g ${ipsecgid} -d "$(DESTDIR)$(sysconfdir)/ipsec.d/cacerts" || true - test -e "$(DESTDIR)${sysconfdir}/ipsec.d/ocspcerts" || $(INSTALL) -o ${ipsecuid} -g ${ipsecgid} -d "$(DESTDIR)$(sysconfdir)/ipsec.d/ocspcerts" || true - test -e "$(DESTDIR)${sysconfdir}/ipsec.d/certs" || $(INSTALL) -o ${ipsecuid} -g ${ipsecgid} -d "$(DESTDIR)$(sysconfdir)/ipsec.d/certs" || true - test -e "$(DESTDIR)${sysconfdir}/ipsec.d/acerts" || $(INSTALL) -o ${ipsecuid} -g ${ipsecgid} -d "$(DESTDIR)$(sysconfdir)/ipsec.d/acerts" || true - test -e "$(DESTDIR)${sysconfdir}/ipsec.d/aacerts" || $(INSTALL) -o ${ipsecuid} -g ${ipsecgid} -d "$(DESTDIR)$(sysconfdir)/ipsec.d/aacerts" || true - test -e "$(DESTDIR)${sysconfdir}/ipsec.d/crls" || $(INSTALL) -o ${ipsecuid} -g ${ipsecgid} -d "$(DESTDIR)$(sysconfdir)/ipsec.d/crls" || true - test -e "$(DESTDIR)${sysconfdir}/ipsec.d/reqs" || $(INSTALL) -o ${ipsecuid} -g ${ipsecgid} -d "$(DESTDIR)$(sysconfdir)/ipsec.d/reqs" || true - test -e "$(DESTDIR)${sysconfdir}/ipsec.d/private" || $(INSTALL) -o ${ipsecuid} -g ${ipsecgid} -d -m 750 "$(DESTDIR)$(sysconfdir)/ipsec.d/private" || true - test -e "$(DESTDIR)$(sysconfdir)/ipsec.conf" || $(INSTALL) -o ${ipsecuid} -g ${ipsecgid} -m 644 $(srcdir)/ipsec.conf $(DESTDIR)$(sysconfdir)/ipsec.conf || true + test -e "$(DESTDIR)${sysconfdir}/ipsec.d" || $(INSTALL) -o -d "$(DESTDIR)$(sysconfdir)/ipsec.d" || true + test -e "$(DESTDIR)${sysconfdir}/ipsec.d/cacerts" || $(INSTALL) -d "$(DESTDIR)$(sysconfdir)/ipsec.d/cacerts" || true + test -e "$(DESTDIR)${sysconfdir}/ipsec.d/ocspcerts" || $(INSTALL) -d "$(DESTDIR)$(sysconfdir)/ipsec.d/ocspcerts" || true + test -e "$(DESTDIR)${sysconfdir}/ipsec.d/certs" || $(INSTALL) -d "$(DESTDIR)$(sysconfdir)/ipsec.d/certs" || true + test -e "$(DESTDIR)${sysconfdir}/ipsec.d/acerts" || $(INSTALL) -d "$(DESTDIR)$(sysconfdir)/ipsec.d/acerts" || true + test -e "$(DESTDIR)${sysconfdir}/ipsec.d/aacerts" || $(INSTALL) -d "$(DESTDIR)$(sysconfdir)/ipsec.d/aacerts" || true + test -e "$(DESTDIR)${sysconfdir}/ipsec.d/crls" || $(INSTALL) -d "$(DESTDIR)$(sysconfdir)/ipsec.d/crls" || true + test -e "$(DESTDIR)${sysconfdir}/ipsec.d/reqs" || $(INSTALL) -d "$(DESTDIR)$(sysconfdir)/ipsec.d/reqs" || true + test -e "$(DESTDIR)${sysconfdir}/ipsec.d/private" || $(INSTALL) -d -m 750 "$(DESTDIR)$(sysconfdir)/ipsec.d/private" || true + test -e "$(DESTDIR)$(sysconfdir)/ipsec.conf" || $(INSTALL) -m 644 $(srcdir)/ipsec.conf $(DESTDIR)$(sysconfdir)/ipsec.conf || true diff --git a/src/starter/Makefile.in b/src/starter/Makefile.in index 446f183f1..f1c370ad9 100644 --- a/src/starter/Makefile.in +++ b/src/starter/Makefile.in @@ -39,8 +39,7 @@ ipsec_PROGRAMS = starter$(EXEEXT) @USE_CHARON_TRUE@am__append_2 = -DSTART_CHARON @USE_LOAD_WARNING_TRUE@am__append_3 = -DLOAD_WARNING subdir = src/starter -DIST_COMMON = README $(dist_man_MANS) $(srcdir)/Makefile.am \ - $(srcdir)/Makefile.in +DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \ $(top_srcdir)/m4/config/ltoptions.m4 \ @@ -56,7 +55,7 @@ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ mkinstalldirs = $(install_sh) -d CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = -am__installdirs = "$(DESTDIR)$(ipsecdir)" "$(DESTDIR)$(man8dir)" +am__installdirs = "$(DESTDIR)$(ipsecdir)" PROGRAMS = $(ipsec_PROGRAMS) am_starter_OBJECTS = y.tab.$(OBJEXT) netkey.$(OBJEXT) \ starterwhack.$(OBJEXT) starterstroke.$(OBJEXT) \ @@ -85,30 +84,6 @@ LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ $(LDFLAGS) -o $@ SOURCES = $(starter_SOURCES) DIST_SOURCES = $(starter_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' -man8dir = $(mandir)/man8 -NROFF = nroff -MANS = $(dist_man_MANS) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) @@ -231,9 +206,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -272,6 +245,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ @@ -304,7 +279,6 @@ AM_CFLAGS = -DIPSEC_DIR=\"${ipsecdir}\" \ $(am__append_2) $(am__append_3) starter_LDADD = defs.o $(top_builddir)/src/libfreeswan/libfreeswan.a $(top_builddir)/src/libstrongswan/libstrongswan.la $(SOCKLIB) EXTRA_DIST = parser.l parser.y keywords.txt ipsec.conf -dist_man_MANS = starter.8 MAINTAINERCLEANFILES = lex.yy.c y.tab.c y.tab.h keywords.c PLUTODIR = $(top_srcdir)/src/pluto SCEPCLIENTDIR = $(top_srcdir)/src/scepclient @@ -438,44 +412,6 @@ mostlyclean-libtool: clean-libtool: -rm -rf .libs _libs -install-man8: $(dist_man_MANS) - @$(NORMAL_INSTALL) - test -z "$(man8dir)" || $(MKDIR_P) "$(DESTDIR)$(man8dir)" - @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 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=''; 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)'; \ @@ -530,19 +466,6 @@ 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)'; \ @@ -574,9 +497,9 @@ distdir: $(DISTFILES) done check-am: all-am check: check-am -all-am: Makefile $(PROGRAMS) $(MANS) +all-am: Makefile $(PROGRAMS) installdirs: - for dir in "$(DESTDIR)$(ipsecdir)" "$(DESTDIR)$(man8dir)"; do \ + for dir in "$(DESTDIR)$(ipsecdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am @@ -628,7 +551,7 @@ info: info-am info-am: -install-data-am: install-ipsecPROGRAMS install-man +install-data-am: install-ipsecPROGRAMS install-dvi: install-dvi-am @@ -644,7 +567,7 @@ install-info: install-info-am install-info-am: -install-man: install-man8 +install-man: install-pdf: install-pdf-am @@ -674,9 +597,7 @@ ps: ps-am ps-am: -uninstall-am: uninstall-ipsecPROGRAMS uninstall-man - -uninstall-man: uninstall-man8 +uninstall-am: uninstall-ipsecPROGRAMS .MAKE: install-am install-strip @@ -687,13 +608,12 @@ uninstall-man: uninstall-man8 install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-exec-local \ install-html install-html-am install-info install-info-am \ - install-ipsecPROGRAMS install-man install-man8 install-pdf \ - install-pdf-am install-ps install-ps-am install-strip \ - installcheck installcheck-am installdirs maintainer-clean \ + install-ipsecPROGRAMS install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ - tags uninstall uninstall-am uninstall-ipsecPROGRAMS \ - uninstall-man uninstall-man8 + tags uninstall uninstall-am uninstall-ipsecPROGRAMS lex.yy.c: $(srcdir)/parser.l $(srcdir)/parser.y $(srcdir)/parser.h y.tab.h @@ -712,16 +632,16 @@ defs.o: $(PLUTODIR)/defs.c $(PLUTODIR)/defs.h $(COMPILE) -c -o $@ $(PLUTODIR)/defs.c install-exec-local : - test -e "$(DESTDIR)${sysconfdir}/ipsec.d" || $(INSTALL) -o ${ipsecuid} -g ${ipsecgid} -d "$(DESTDIR)$(sysconfdir)/ipsec.d" || true - test -e "$(DESTDIR)${sysconfdir}/ipsec.d/cacerts" || $(INSTALL) -o ${ipsecuid} -g ${ipsecgid} -d "$(DESTDIR)$(sysconfdir)/ipsec.d/cacerts" || true - test -e "$(DESTDIR)${sysconfdir}/ipsec.d/ocspcerts" || $(INSTALL) -o ${ipsecuid} -g ${ipsecgid} -d "$(DESTDIR)$(sysconfdir)/ipsec.d/ocspcerts" || true - test -e "$(DESTDIR)${sysconfdir}/ipsec.d/certs" || $(INSTALL) -o ${ipsecuid} -g ${ipsecgid} -d "$(DESTDIR)$(sysconfdir)/ipsec.d/certs" || true - test -e "$(DESTDIR)${sysconfdir}/ipsec.d/acerts" || $(INSTALL) -o ${ipsecuid} -g ${ipsecgid} -d "$(DESTDIR)$(sysconfdir)/ipsec.d/acerts" || true - test -e "$(DESTDIR)${sysconfdir}/ipsec.d/aacerts" || $(INSTALL) -o ${ipsecuid} -g ${ipsecgid} -d "$(DESTDIR)$(sysconfdir)/ipsec.d/aacerts" || true - test -e "$(DESTDIR)${sysconfdir}/ipsec.d/crls" || $(INSTALL) -o ${ipsecuid} -g ${ipsecgid} -d "$(DESTDIR)$(sysconfdir)/ipsec.d/crls" || true - test -e "$(DESTDIR)${sysconfdir}/ipsec.d/reqs" || $(INSTALL) -o ${ipsecuid} -g ${ipsecgid} -d "$(DESTDIR)$(sysconfdir)/ipsec.d/reqs" || true - test -e "$(DESTDIR)${sysconfdir}/ipsec.d/private" || $(INSTALL) -o ${ipsecuid} -g ${ipsecgid} -d -m 750 "$(DESTDIR)$(sysconfdir)/ipsec.d/private" || true - test -e "$(DESTDIR)$(sysconfdir)/ipsec.conf" || $(INSTALL) -o ${ipsecuid} -g ${ipsecgid} -m 644 $(srcdir)/ipsec.conf $(DESTDIR)$(sysconfdir)/ipsec.conf || true + test -e "$(DESTDIR)${sysconfdir}/ipsec.d" || $(INSTALL) -o -d "$(DESTDIR)$(sysconfdir)/ipsec.d" || true + test -e "$(DESTDIR)${sysconfdir}/ipsec.d/cacerts" || $(INSTALL) -d "$(DESTDIR)$(sysconfdir)/ipsec.d/cacerts" || true + test -e "$(DESTDIR)${sysconfdir}/ipsec.d/ocspcerts" || $(INSTALL) -d "$(DESTDIR)$(sysconfdir)/ipsec.d/ocspcerts" || true + test -e "$(DESTDIR)${sysconfdir}/ipsec.d/certs" || $(INSTALL) -d "$(DESTDIR)$(sysconfdir)/ipsec.d/certs" || true + test -e "$(DESTDIR)${sysconfdir}/ipsec.d/acerts" || $(INSTALL) -d "$(DESTDIR)$(sysconfdir)/ipsec.d/acerts" || true + test -e "$(DESTDIR)${sysconfdir}/ipsec.d/aacerts" || $(INSTALL) -d "$(DESTDIR)$(sysconfdir)/ipsec.d/aacerts" || true + test -e "$(DESTDIR)${sysconfdir}/ipsec.d/crls" || $(INSTALL) -d "$(DESTDIR)$(sysconfdir)/ipsec.d/crls" || true + test -e "$(DESTDIR)${sysconfdir}/ipsec.d/reqs" || $(INSTALL) -d "$(DESTDIR)$(sysconfdir)/ipsec.d/reqs" || true + test -e "$(DESTDIR)${sysconfdir}/ipsec.d/private" || $(INSTALL) -d -m 750 "$(DESTDIR)$(sysconfdir)/ipsec.d/private" || true + test -e "$(DESTDIR)$(sysconfdir)/ipsec.conf" || $(INSTALL) -m 644 $(srcdir)/ipsec.conf $(DESTDIR)$(sysconfdir)/ipsec.conf || true # 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. diff --git a/src/starter/args.c b/src/starter/args.c index 37d600283..87307f1aa 100644 --- a/src/starter/args.c +++ b/src/starter/args.c @@ -239,6 +239,7 @@ static const token_info_t token_info[] = { ARG_MISC, 0, NULL /* KW_MARK */ }, { ARG_MISC, 0, NULL /* KW_MARK_IN */ }, { ARG_MISC, 0, NULL /* KW_MARK_OUT */ }, + { ARG_MISC, 0, NULL /* KW_TFC */ }, /* ca section keywords */ { ARG_STR, offsetof(starter_ca_t, name), NULL }, @@ -272,6 +273,7 @@ static const token_info_t token_info[] = { ARG_STR, offsetof(starter_end_t, rsakey), NULL }, { ARG_STR, offsetof(starter_end_t, cert), NULL }, { ARG_STR, offsetof(starter_end_t, cert2), NULL }, + { ARG_STR, offsetof(starter_end_t, cert_policy), NULL }, { ARG_ENUM, offsetof(starter_end_t, sendcert), LST_sendcert }, { ARG_STR, offsetof(starter_end_t, ca), NULL }, { ARG_STR, offsetof(starter_end_t, ca2), NULL }, diff --git a/src/starter/confread.c b/src/starter/confread.c index 3367616ca..1e7daa6a9 100644 --- a/src/starter/confread.c +++ b/src/starter/confread.c @@ -705,6 +705,23 @@ static void load_conn(starter_conn_t *conn, kw_list_t *kw, starter_config_t *cfg cfg->err++; } break; + case KW_TFC: + if (streq(kw->value, "%mtu")) + { + conn->tfc = -1; + } + else + { + char *endptr; + + conn->tfc = strtoul(kw->value, &endptr, 10); + if (*endptr != '\0') + { + plog("# bad integer value: %s=%s", kw->entry->name, kw->value); + cfg->err++; + } + } + break; case KW_KEYINGTRIES: if (streq(kw->value, "%forever")) { diff --git a/src/starter/confread.h b/src/starter/confread.h index 982d1d206..4f9c5f7d0 100644 --- a/src/starter/confread.h +++ b/src/starter/confread.h @@ -64,6 +64,7 @@ struct starter_end { char *ca; char *ca2; char *groups; + char *cert_policy; char *iface; ip_address addr; u_int ikeport; @@ -125,6 +126,7 @@ struct starter_conn { u_int32_t reqid; mark_t mark_in; mark_t mark_out; + u_int32_t tfc; sa_family_t addr_family; sa_family_t tunnel_addr_family; bool install_policy; diff --git a/src/starter/keywords.c b/src/starter/keywords.c index 0c24c7dcf..340b7131d 100644 --- a/src/starter/keywords.c +++ b/src/starter/keywords.c @@ -54,12 +54,12 @@ struct kw_entry { kw_token_t token; }; -#define TOTAL_KEYWORDS 127 +#define TOTAL_KEYWORDS 130 #define MIN_WORD_LENGTH 3 #define MAX_WORD_LENGTH 17 -#define MIN_HASH_VALUE 12 -#define MAX_HASH_VALUE 238 -/* maximum key range = 227, duplicates = 0 */ +#define MIN_HASH_VALUE 18 +#define MAX_HASH_VALUE 249 +/* maximum key range = 232, duplicates = 0 */ #ifdef __GNUC__ __inline @@ -75,32 +75,32 @@ hash (str, len) { static const unsigned char asso_values[] = { - 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, - 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, - 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, - 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, - 239, 239, 239, 239, 239, 239, 239, 239, 239, 2, - 104, 239, 239, 239, 239, 239, 239, 239, 239, 239, - 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, - 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, - 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, - 239, 239, 239, 239, 239, 15, 239, 20, 14, 58, - 51, 1, 7, 1, 81, 1, 239, 132, 47, 4, - 1, 49, 10, 9, 23, 1, 20, 48, 4, 239, - 239, 35, 1, 239, 239, 239, 239, 239, 239, 239, - 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, - 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, - 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, - 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, - 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, - 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, - 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, - 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, - 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, - 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, - 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, - 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, - 239, 239, 239, 239, 239, 239 + 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, + 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, + 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, + 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, + 250, 250, 250, 250, 250, 250, 250, 250, 250, 11, + 125, 250, 250, 250, 250, 250, 250, 250, 250, 250, + 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, + 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, + 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, + 250, 250, 250, 250, 250, 20, 250, 18, 6, 55, + 59, 3, 9, 3, 92, 3, 250, 147, 71, 12, + 29, 83, 38, 4, 13, 3, 8, 80, 3, 250, + 250, 12, 9, 250, 250, 250, 250, 250, 250, 250, + 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, + 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, + 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, + 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, + 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, + 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, + 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, + 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, + 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, + 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, + 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, + 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, + 250, 250, 250, 250, 250, 250 }; register int hval = len; @@ -124,160 +124,164 @@ hash (str, len) static const struct kw_entry wordlist[] = { {"pfs", KW_PFS}, - {"uniqueids", KW_UNIQUEIDS}, - {"rightgroups", KW_RIGHTGROUPS}, - {"lifetime", KW_KEYLIFE}, - {"rightsubnetwithin", KW_RIGHTSUBNETWITHIN}, - {"rightnatip", KW_RIGHTNATIP}, - {"esp", KW_ESP}, - {"rightnexthop", KW_RIGHTNEXTHOP}, - {"rightsourceip", KW_RIGHTSOURCEIP}, {"right", KW_RIGHT}, - {"leftupdown", KW_LEFTUPDOWN}, - {"leftnexthop", KW_LEFTNEXTHOP}, + {"rightgroups", KW_RIGHTGROUPS}, {"left", KW_LEFT}, - {"keep_alive", KW_KEEP_ALIVE}, + {"lifetime", KW_KEYLIFE}, {"rightsubnet", KW_RIGHTSUBNET}, {"rightikeport", KW_RIGHTIKEPORT}, {"rightsendcert", KW_RIGHTSENDCERT}, - {"leftcert", KW_LEFTCERT,}, - {"interfaces", KW_INTERFACES}, - {"lifepackets", KW_LIFEPACKETS}, - {"leftsendcert", KW_LEFTSENDCERT}, - {"leftgroups", KW_LEFTGROUPS}, - {"eap", KW_EAP}, - {"rightprotoport", KW_RIGHTPROTOPORT}, - {"leftnatip", KW_LEFTNATIP}, + {"leftcert", KW_LEFTCERT}, {"keyingtries", KW_KEYINGTRIES}, - {"type", KW_TYPE}, {"keylife", KW_KEYLIFE}, - {"mark_in", KW_MARK_IN}, + {"leftsendcert", KW_LEFTSENDCERT}, {"lifebytes", KW_LIFEBYTES}, - {"leftca", KW_LEFTCA}, - {"margintime", KW_REKEYMARGIN}, - {"marginbytes", KW_MARGINBYTES}, + {"keep_alive", KW_KEEP_ALIVE}, + {"leftgroups", KW_LEFTGROUPS}, {"leftrsasigkey", KW_LEFTRSASIGKEY}, - {"marginpackets", KW_MARGINPACKETS}, + {"leftcertpolicy", KW_LEFTCERTPOLICY}, {"certuribase", KW_CERTURIBASE}, - {"virtual_private", KW_VIRTUAL_PRIVATE}, - {"rightid", KW_RIGHTID}, - {"rightupdown", KW_RIGHTUPDOWN}, - {"compress", KW_COMPRESS}, + {"lifepackets", KW_LIFEPACKETS}, + {"rightrsasigkey", KW_RIGHTRSASIGKEY}, {"leftprotoport", KW_LEFTPROTOPORT}, - {"overridemtu", KW_OVERRIDEMTU}, + {"uniqueids", KW_UNIQUEIDS}, + {"rightallowany", KW_RIGHTALLOWANY}, + {"virtual_private", KW_VIRTUAL_PRIVATE}, + {"leftca", KW_LEFTCA}, + {"rightsubnetwithin", KW_RIGHTSUBNETWITHIN}, + {"strictcrlpolicy", KW_STRICTCRLPOLICY}, + {"type", KW_TYPE}, + {"interfaces", KW_INTERFACES}, + {"rightsourceip", KW_RIGHTSOURCEIP}, + {"leftnexthop", KW_LEFTNEXTHOP}, + {"rightprotoport", KW_RIGHTPROTOPORT}, + {"mark_in", KW_MARK_IN}, {"reqid", KW_REQID}, {"inactivity", KW_INACTIVITY}, + {"margintime", KW_REKEYMARGIN}, + {"marginbytes", KW_MARGINBYTES}, + {"rightid", KW_RIGHTID}, + {"marginpackets", KW_MARGINPACKETS}, + {"leftnatip", KW_LEFTNATIP}, + {"rightcert", KW_RIGHTCERT}, + {"ocspuri", KW_OCSPURI}, + {"esp", KW_ESP}, + {"rightnatip", KW_RIGHTNATIP}, + {"keyexchange", KW_KEYEXCHANGE}, + {"rightnexthop", KW_RIGHTNEXTHOP}, + {"rightca", KW_RIGHTCA}, + {"rightcertpolicy", KW_RIGHTCERTPOLICY}, + {"leftupdown", KW_LEFTUPDOWN}, + {"ocspuri1", KW_OCSPURI}, + {"mediated_by", KW_MEDIATED_BY}, + {"me_peerid", KW_ME_PEERID}, + {"cacert", KW_CACERT}, + {"crluri", KW_CRLURI}, + {"eap", KW_EAP}, {"leftfirewall", KW_LEFTFIREWALL}, {"rightfirewall", KW_RIGHTFIREWALL}, - {"rightallowany", KW_RIGHTALLOWANY}, + {"overridemtu", KW_OVERRIDEMTU}, {"mobike", KW_MOBIKE}, - {"lefthostaccess", KW_LEFTHOSTACCESS}, - {"leftsubnetwithin", KW_LEFTSUBNETWITHIN}, - {"rightrsasigkey", KW_RIGHTRSASIGKEY}, - {"pfsgroup", KW_PFSGROUP}, - {"me_peerid", KW_ME_PEERID}, - {"crluri", KW_CRLURI}, - {"leftsourceip", KW_LEFTSOURCEIP}, + {"packetdefault", KW_PACKETDEFAULT}, {"crluri1", KW_CRLURI}, + {"ldapbase", KW_LDAPBASE}, + {"leftallowany", KW_LEFTALLOWANY}, {"mediation", KW_MEDIATION}, - {"dumpdir", KW_DUMPDIR}, - {"forceencaps", KW_FORCEENCAPS}, + {"compress", KW_COMPRESS}, {"leftsubnet", KW_LEFTSUBNET}, - {"rightca", KW_RIGHTCA}, - {"rightcert", KW_RIGHTCERT}, - {"ocspuri", KW_OCSPURI}, - {"dpdaction", KW_DPDACTION}, - {"ocspuri1", KW_OCSPURI}, + {"lefthostaccess", KW_LEFTHOSTACCESS}, + {"forceencaps", KW_FORCEENCAPS}, + {"dumpdir", KW_DUMPDIR}, + {"righthostaccess", KW_RIGHTHOSTACCESS}, + {"authby", KW_AUTHBY}, + {"aaa_identity", KW_AAA_IDENTITY}, + {"tfc", KW_TFC}, + {"nat_traversal", KW_NAT_TRAVERSAL}, + {"rightauth", KW_RIGHTAUTH}, + {"rightupdown", KW_RIGHTUPDOWN}, {"dpdtimeout", KW_DPDTIMEOUT}, {"installpolicy", KW_INSTALLPOLICY}, - {"righthostaccess", KW_RIGHTHOSTACCESS}, - {"ldapbase", KW_LDAPBASE}, - {"also", KW_ALSO}, - {"leftallowany", KW_LEFTALLOWANY}, + {"mark_out", KW_MARK_OUT}, + {"fragicmp", KW_FRAGICMP}, {"force_keepalive", KW_FORCE_KEEPALIVE}, - {"keyexchange", KW_KEYEXCHANGE}, - {"hidetos", KW_HIDETOS}, - {"klipsdebug", KW_KLIPSDEBUG}, - {"plutostderrlog", KW_PLUTOSTDERRLOG}, - {"rightauth", KW_RIGHTAUTH}, - {"strictcrlpolicy", KW_STRICTCRLPOLICY}, - {"charondebug", KW_CHARONDEBUG}, - {"rightid2", KW_RIGHTID2}, {"leftid", KW_LEFTID}, - {"mediated_by", KW_MEDIATED_BY}, - {"fragicmp", KW_FRAGICMP}, - {"mark_out", KW_MARK_OUT}, - {"auto", KW_AUTO}, - {"leftcert2", KW_LEFTCERT2,}, - {"nat_traversal", KW_NAT_TRAVERSAL}, - {"cacert", KW_CACERT}, - {"plutostart", KW_PLUTOSTART}, + {"leftsubnetwithin", KW_LEFTSUBNETWITHIN}, {"eap_identity", KW_EAP_IDENTITY}, - {"prepluto", KW_PREPLUTO}, - {"packetdefault", KW_PACKETDEFAULT}, + {"cachecrls", KW_CACHECRLS}, + {"pfsgroup", KW_PFSGROUP}, + {"rightid2", KW_RIGHTID2}, + {"dpdaction", KW_DPDACTION}, {"xauth_identity", KW_XAUTH_IDENTITY}, + {"leftsourceip", KW_LEFTSOURCEIP}, + {"klipsdebug", KW_KLIPSDEBUG}, + {"leftcert2", KW_LEFTCERT2}, + {"charondebug", KW_CHARONDEBUG}, + {"hidetos", KW_HIDETOS}, + {"ike", KW_IKE}, {"charonstart", KW_CHARONSTART}, - {"crlcheckinterval", KW_CRLCHECKINTERVAL}, {"rightauth2", KW_RIGHTAUTH2}, - {"ike", KW_IKE}, - {"aaa_identity", KW_AAA_IDENTITY}, + {"also", KW_ALSO}, {"leftca2", KW_LEFTCA2}, - {"authby", KW_AUTHBY}, - {"leftauth", KW_LEFTAUTH}, - {"cachecrls", KW_CACHECRLS}, + {"rekey", KW_REKEY}, + {"plutostderrlog", KW_PLUTOSTDERRLOG}, + {"plutostart", KW_PLUTOSTART}, + {"ikelifetime", KW_IKELIFETIME}, + {"crlcheckinterval", KW_CRLCHECKINTERVAL}, + {"auto", KW_AUTO}, {"ldaphost", KW_LDAPHOST}, - {"rekeymargin", KW_REKEYMARGIN}, {"rekeyfuzz", KW_REKEYFUZZ}, - {"dpddelay", KW_DPDDELAY}, - {"ikelifetime", KW_IKELIFETIME}, - {"auth", KW_AUTH}, - {"xauth", KW_XAUTH}, - {"postpluto", KW_POSTPLUTO}, - {"plutodebug", KW_PLUTODEBUG}, - {"modeconfig", KW_MODECONFIG}, - {"nocrsend", KW_NOCRSEND}, - {"leftauth2", KW_LEFTAUTH2}, - {"leftid2", KW_LEFTID2}, {"leftikeport", KW_LEFTIKEPORT}, + {"mark", KW_MARK}, + {"auth", KW_AUTH}, + {"prepluto", KW_PREPLUTO}, + {"dpddelay", KW_DPDDELAY}, + {"leftauth", KW_LEFTAUTH}, {"rightca2", KW_RIGHTCA2}, - {"rekey", KW_REKEY}, + {"xauth", KW_XAUTH}, {"rightcert2", KW_RIGHTCERT2}, - {"mark", KW_MARK}, - {"crluri2", KW_CRLURI2}, - {"reauth", KW_REAUTH}, + {"rekeymargin", KW_REKEYMARGIN}, + {"leftid2", KW_LEFTID2}, {"ocspuri2", KW_OCSPURI2}, + {"nocrsend", KW_NOCRSEND}, + {"reauth", KW_REAUTH}, + {"crluri2", KW_CRLURI2}, + {"plutodebug", KW_PLUTODEBUG}, + {"leftauth2", KW_LEFTAUTH2}, {"pkcs11module", KW_PKCS11MODULE}, {"pkcs11initargs", KW_PKCS11INITARGS}, {"pkcs11keepstate", KW_PKCS11KEEPSTATE}, - {"pkcs11proxy", KW_PKCS11PROXY} + {"pkcs11proxy", KW_PKCS11PROXY}, + {"modeconfig", KW_MODECONFIG}, + {"postpluto", KW_POSTPLUTO} }; static const short lookup[] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 0, 1, -1, 2, -1, -1, 3, -1, - -1, 4, -1, 5, 6, 7, 8, 9, -1, 10, - 11, -1, 12, 13, 14, 15, 16, 17, -1, 18, - 19, 20, 21, 22, -1, -1, 23, 24, -1, 25, - 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, - 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, - 46, 47, 48, 49, 50, 51, -1, 52, 53, 54, - 55, -1, 56, 57, -1, 58, 59, 60, -1, 61, - 62, 63, 64, -1, -1, 65, -1, 66, -1, 67, - 68, 69, 70, 71, -1, -1, 72, -1, -1, 73, - 74, 75, 76, 77, 78, 79, 80, -1, 81, 82, - 83, 84, 85, 86, 87, -1, 88, -1, 89, 90, - -1, 91, 92, 93, 94, -1, 95, 96, 97, 98, - -1, -1, -1, -1, 99, 100, 101, -1, 102, 103, - 104, 105, 106, 107, 108, 109, -1, 110, -1, -1, - 111, -1, -1, -1, -1, -1, -1, 112, -1, 113, - 114, 115, 116, 117, 118, -1, -1, -1, -1, 119, - -1, -1, 120, -1, -1, -1, -1, -1, -1, 121, - -1, -1, -1, -1, 122, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 123, -1, 124, 125, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 126 + -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, + -1, -1, -1, 2, 3, -1, 4, -1, 5, 6, + 7, 8, 9, -1, 10, 11, 12, 13, 14, -1, + 15, 16, -1, 17, 18, 19, 20, 21, -1, 22, + -1, -1, 23, -1, 24, 25, 26, 27, -1, 28, + 29, -1, -1, -1, 30, -1, 31, -1, -1, -1, + 32, 33, 34, 35, 36, 37, 38, 39, 40, -1, + -1, 41, 42, 43, 44, 45, 46, -1, 47, 48, + 49, -1, -1, 50, 51, 52, 53, 54, 55, 56, + 57, 58, 59, -1, -1, 60, 61, 62, 63, 64, + 65, -1, 66, 67, -1, 68, 69, -1, 70, 71, + -1, -1, 72, 73, -1, 74, 75, 76, 77, -1, + 78, -1, 79, -1, 80, -1, 81, 82, -1, 83, + 84, 85, 86, 87, 88, 89, 90, -1, -1, 91, + -1, -1, -1, 92, -1, 93, 94, -1, 95, 96, + -1, 97, 98, -1, -1, -1, -1, 99, -1, -1, + -1, 100, 101, 102, 103, 104, 105, 106, 107, -1, + -1, -1, 108, -1, 109, -1, -1, 110, 111, -1, + -1, -1, 112, -1, 113, 114, 115, -1, -1, -1, + -1, -1, 116, 117, 118, -1, -1, -1, 119, -1, + -1, 120, -1, -1, -1, -1, -1, -1, -1, 121, + -1, -1, -1, 122, -1, -1, 123, -1, 124, -1, + 125, 126, -1, -1, -1, -1, 127, -1, 128, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 129 }; #ifdef __GNUC__ diff --git a/src/starter/keywords.h b/src/starter/keywords.h index 1dae65a99..9f46a8b4b 100644 --- a/src/starter/keywords.h +++ b/src/starter/keywords.h @@ -102,9 +102,10 @@ typedef enum { KW_MARK, KW_MARK_IN, KW_MARK_OUT, + KW_TFC, #define KW_CONN_FIRST KW_CONN_SETUP -#define KW_CONN_LAST KW_MARK_OUT +#define KW_CONN_LAST KW_TFC /* ca section keywords */ KW_CA_NAME, @@ -141,6 +142,7 @@ typedef enum { KW_RSASIGKEY, KW_CERT, KW_CERT2, + KW_CERTPOLICY, KW_SENDCERT, KW_CA, KW_CA2, @@ -170,6 +172,7 @@ typedef enum { KW_LEFTRSASIGKEY, KW_LEFTCERT, KW_LEFTCERT2, + KW_LEFTCERTPOLICY, KW_LEFTSENDCERT, KW_LEFTCA, KW_LEFTCA2, @@ -198,6 +201,7 @@ typedef enum { KW_RIGHTRSASIGKEY, KW_RIGHTCERT, KW_RIGHTCERT2, + KW_RIGHTCERTPOLICY, KW_RIGHTSENDCERT, KW_RIGHTCA, KW_RIGHTCA2, diff --git a/src/starter/keywords.txt b/src/starter/keywords.txt index 06705635a..2c0e5de3d 100644 --- a/src/starter/keywords.txt +++ b/src/starter/keywords.txt @@ -93,6 +93,7 @@ reqid, KW_REQID mark, KW_MARK mark_in, KW_MARK_IN mark_out, KW_MARK_OUT +tfc, KW_TFC cacert, KW_CACERT ldaphost, KW_LDAPHOST ldapbase, KW_LDAPBASE @@ -120,8 +121,9 @@ leftid2, KW_LEFTID2 leftauth, KW_LEFTAUTH leftauth2, KW_LEFTAUTH2 leftrsasigkey, KW_LEFTRSASIGKEY -leftcert, KW_LEFTCERT, -leftcert2, KW_LEFTCERT2, +leftcert, KW_LEFTCERT +leftcert2, KW_LEFTCERT2 +leftcertpolicy, KW_LEFTCERTPOLICY leftsendcert, KW_LEFTSENDCERT leftca, KW_LEFTCA leftca2, KW_LEFTCA2 @@ -145,6 +147,7 @@ rightauth2, KW_RIGHTAUTH2 rightrsasigkey, KW_RIGHTRSASIGKEY rightcert, KW_RIGHTCERT rightcert2, KW_RIGHTCERT2 +rightcertpolicy, KW_RIGHTCERTPOLICY rightsendcert, KW_RIGHTSENDCERT rightca, KW_RIGHTCA rightca2, KW_RIGHTCA2 diff --git a/src/starter/starter.8 b/src/starter/starter.8 deleted file mode 100644 index e69de29bb..000000000 --- a/src/starter/starter.8 +++ /dev/null diff --git a/src/starter/starterstroke.c b/src/starter/starterstroke.c index 9ba569d47..f251667c7 100644 --- a/src/starter/starterstroke.c +++ b/src/starter/starterstroke.c @@ -171,6 +171,7 @@ static void starter_stroke_add_end(stroke_msg_t *msg, stroke_end_t *msg_end, sta msg_end->id2 = push_string(msg, conn_end->id2); msg_end->cert = push_string(msg, conn_end->cert); msg_end->cert2 = push_string(msg, conn_end->cert2); + msg_end->cert_policy = push_string(msg, conn_end->cert_policy); msg_end->ca = push_string(msg, conn_end->ca); msg_end->ca2 = push_string(msg, conn_end->ca2); msg_end->groups = push_string(msg, conn_end->groups); @@ -266,6 +267,7 @@ int starter_stroke_add_conn(starter_config_t *cfg, starter_conn_t *conn) msg.add_conn.mark_in.mask = conn->mark_in.mask; msg.add_conn.mark_out.value = conn->mark_out.value; msg.add_conn.mark_out.mask = conn->mark_out.mask; + msg.add_conn.tfc = conn->tfc; starter_stroke_add_end(&msg, &msg.add_conn.me, &conn->left); starter_stroke_add_end(&msg, &msg.add_conn.other, &conn->right); diff --git a/src/stroke/Makefile.in b/src/stroke/Makefile.in index c490be114..d621f21ca 100644 --- a/src/stroke/Makefile.in +++ b/src/stroke/Makefile.in @@ -197,9 +197,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -238,6 +236,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ diff --git a/src/stroke/stroke.c b/src/stroke/stroke.c index 103617f08..a88fa10d7 100644 --- a/src/stroke/stroke.c +++ b/src/stroke/stroke.c @@ -197,6 +197,16 @@ static int terminate_connection_srcip(char *start, char *end) return send_stroke_msg(&msg); } +static int rekey_connection(char *name) +{ + stroke_msg_t msg; + + msg.type = STR_REKEY; + msg.length = offsetof(stroke_msg_t, buffer); + msg.rekey.name = push_string(&msg, name); + return send_stroke_msg(&msg); +} + static int route_connection(char *name) { stroke_msg_t msg; @@ -276,6 +286,8 @@ static int reread(stroke_keyword_t kw) static int purge_flags[] = { PURGE_OCSP, PURGE_IKE, + PURGE_CRLS, + PURGE_CERTS, }; static int purge(stroke_keyword_t kw) @@ -373,6 +385,10 @@ static void exit_usage(char *error) printf(" stroke rereadsecrets|rereadcrls|rereadall\n"); printf(" Purge ocsp cache entries:\n"); printf(" stroke purgeocsp\n"); + printf(" Purge CRL cache entries:\n"); + printf(" stroke purgecrls\n"); + printf(" Purge X509 cache entries:\n"); + printf(" stroke purgecerts\n"); printf(" Purge IKE_SAs without a CHILD_SA:\n"); printf(" stroke purgeike\n"); printf(" Export credentials to the console:\n"); @@ -443,6 +459,13 @@ int main(int argc, char *argv[]) } res = terminate_connection_srcip(argv[2], argc > 3 ? argv[3] : NULL); break; + case STROKE_REKEY: + if (argc < 3) + { + exit_usage("\"rekey\" needs a connection name"); + } + res = rekey_connection(argv[2]); + break; case STROKE_ROUTE: if (argc < 3) { @@ -491,6 +514,8 @@ int main(int argc, char *argv[]) res = reread(token->kw); break; case STROKE_PURGE_OCSP: + case STROKE_PURGE_CRLS: + case STROKE_PURGE_CERTS: case STROKE_PURGE_IKE: res = purge(token->kw); break; diff --git a/src/stroke/stroke_keywords.c b/src/stroke/stroke_keywords.c index c2d79176e..b43f4b475 100644 --- a/src/stroke/stroke_keywords.c +++ b/src/stroke/stroke_keywords.c @@ -54,12 +54,12 @@ struct stroke_token { stroke_keyword_t kw; }; -#define TOTAL_KEYWORDS 34 +#define TOTAL_KEYWORDS 37 #define MIN_WORD_LENGTH 2 #define MAX_WORD_LENGTH 15 -#define MIN_HASH_VALUE 3 -#define MAX_HASH_VALUE 39 -/* maximum key range = 37, duplicates = 0 */ +#define MIN_HASH_VALUE 2 +#define MAX_HASH_VALUE 42 +/* maximum key range = 41, duplicates = 0 */ #ifdef __GNUC__ __inline @@ -75,32 +75,32 @@ hash (str, len) { static const unsigned char asso_values[] = { - 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, - 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, - 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, - 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, - 40, 40, 40, 40, 40, 18, 40, 40, 40, 40, - 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, - 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, - 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, - 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, - 40, 40, 40, 40, 40, 40, 40, 0, 4, 1, - 1, 0, 40, 17, 40, 20, 40, 3, 0, 40, - 40, 12, 19, 40, 6, 3, 20, 12, 40, 40, - 10, 40, 40, 40, 40, 40, 40, 40, 40, 40, - 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, - 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, - 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, - 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, - 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, - 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, - 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, - 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, - 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, - 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, - 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, - 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, - 40, 40, 40, 40, 40, 40 + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 20, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 0, 23, 1, + 1, 15, 43, 21, 43, 23, 43, 9, 0, 43, + 43, 10, 2, 43, 6, 5, 1, 0, 43, 43, + 2, 19, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43 }; register int hval = len; @@ -125,47 +125,51 @@ hash (str, len) static const struct stroke_token wordlist[] = { + {"up", STROKE_UP}, {"add", STROKE_ADD}, {"del", STROKE_DEL}, {"down", STROKE_DOWN}, - {"leases", STROKE_LEASES}, {"listall", STROKE_LIST_ALL}, - {"loglevel", STROKE_LOGLEVEL}, + {"delete", STROKE_DELETE}, {"listcrls", STROKE_LIST_CRLS}, - {"listacerts", STROKE_LIST_ACERTS}, - {"route", STROKE_ROUTE}, + {"status", STROKE_STATUS}, {"listaacerts", STROKE_LIST_AACERTS}, {"listcacerts", STROKE_LIST_CACERTS}, - {"up", STROKE_UP}, + {"statusall", STROKE_STATUSALL}, {"rereadall", STROKE_REREAD_ALL}, {"listcerts", STROKE_LIST_CERTS}, {"rereadcrls", STROKE_REREAD_CRLS}, {"rereadacerts", STROKE_REREAD_ACERTS}, {"rereadaacerts", STROKE_REREAD_AACERTS}, {"rereadcacerts", STROKE_REREAD_CACERTS}, - {"status", STROKE_STATUS}, - {"rereadsecrets", STROKE_REREAD_SECRETS}, + {"leases", STROKE_LEASES}, + {"unroute", STROKE_UNROUTE}, {"listocsp", STROKE_LIST_OCSP}, - {"statusall", STROKE_STATUSALL}, + {"rereadsecrets", STROKE_REREAD_SECRETS}, + {"listacerts", STROKE_LIST_ACERTS}, + {"route", STROKE_ROUTE}, + {"purgeocsp", STROKE_PURGE_OCSP}, + {"listocspcerts", STROKE_LIST_OCSPCERTS}, {"listalgs", STROKE_LIST_ALGS}, + {"rekey", STROKE_REKEY}, + {"rereadocspcerts", STROKE_REREAD_OCSPCERTS}, + {"purgecrls", STROKE_PURGE_CRLS}, {"exportx509", STROKE_EXPORT_X509}, - {"delete", STROKE_DELETE}, - {"listocspcerts", STROKE_LIST_OCSPCERTS}, - {"purgeocsp", STROKE_PURGE_OCSP}, {"purgeike", STROKE_PURGE_IKE}, - {"unroute", STROKE_UNROUTE}, {"listcainfos", STROKE_LIST_CAINFOS}, - {"rereadocspcerts", STROKE_REREAD_OCSPCERTS}, {"listpubkeys", STROKE_LIST_PUBKEYS}, {"down-srcip", STROKE_DOWN_SRCIP}, - {"listgroups", STROKE_LIST_GROUPS} + {"loglevel", STROKE_LOGLEVEL}, + {"listgroups", STROKE_LIST_GROUPS}, + {"purgecerts", STROKE_PURGE_CERTS} }; static const short lookup[] = { - -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, - 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 25, 26, 27, 28, 29, 30, 31, 32, -1, -1, -1, 33 + -1, -1, 0, 1, 2, 3, -1, 4, 5, 6, -1, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, -1, -1, 35, + 36 }; #ifdef __GNUC__ diff --git a/src/stroke/stroke_keywords.h b/src/stroke/stroke_keywords.h index 4a3826536..ff2ba36ef 100644 --- a/src/stroke/stroke_keywords.h +++ b/src/stroke/stroke_keywords.h @@ -25,6 +25,7 @@ typedef enum { STROKE_UP, STROKE_DOWN, STROKE_DOWN_SRCIP, + STROKE_REKEY, STROKE_LOGLEVEL, STROKE_STATUS, STROKE_STATUSALL, @@ -48,6 +49,8 @@ typedef enum { STROKE_REREAD_CRLS, STROKE_REREAD_ALL, STROKE_PURGE_OCSP, + STROKE_PURGE_CRLS, + STROKE_PURGE_CERTS, STROKE_PURGE_IKE, STROKE_EXPORT_X509, STROKE_LEASES, diff --git a/src/stroke/stroke_keywords.txt b/src/stroke/stroke_keywords.txt index 0b8092985..dafd1ab08 100644 --- a/src/stroke/stroke_keywords.txt +++ b/src/stroke/stroke_keywords.txt @@ -32,6 +32,7 @@ unroute, STROKE_UNROUTE up, STROKE_UP down, STROKE_DOWN down-srcip, STROKE_DOWN_SRCIP +rekey, STROKE_REKEY loglevel, STROKE_LOGLEVEL status, STROKE_STATUS statusall, STROKE_STATUSALL @@ -55,6 +56,8 @@ rereadacerts, STROKE_REREAD_ACERTS rereadcrls, STROKE_REREAD_CRLS rereadall, STROKE_REREAD_ALL purgeocsp, STROKE_PURGE_OCSP +purgecrls, STROKE_PURGE_CRLS +purgecerts, STROKE_PURGE_CERTS purgeike, STROKE_PURGE_IKE exportx509, STROKE_EXPORT_X509 leases, STROKE_LEASES diff --git a/src/stroke/stroke_msg.h b/src/stroke/stroke_msg.h index 9466cf0b0..3af2b7042 100644 --- a/src/stroke/stroke_msg.h +++ b/src/stroke/stroke_msg.h @@ -107,6 +107,10 @@ enum purge_flag_t { PURGE_OCSP = 0x0001, /** purge IKE_SAs without a CHILD_SA */ PURGE_IKE = 0x0002, + /** purge CRL cache entries */ + PURGE_CRLS = 0x0004, + /** purge X509 cache entries */ + PURGE_CERTS = 0x0008, }; typedef enum export_flag_t export_flag_t; @@ -145,6 +149,7 @@ struct stroke_end_t { char *ca; char *ca2; char *groups; + char *cert_policy; char *updown; char *address; u_int16_t ikeport; @@ -183,6 +188,8 @@ struct stroke_msg_t { STR_TERMINATE, /* terminate connection by peers srcip/virtual ip */ STR_TERMINATE_SRCIP, + /* rekey a connection */ + STR_REKEY, /* show connection status */ STR_STATUS, /* show verbose connection status */ @@ -215,7 +222,7 @@ struct stroke_msg_t { /* data for STR_INITIATE, STR_ROUTE, STR_UP, STR_DOWN, ... */ struct { char *name; - } initiate, route, unroute, terminate, status, del_conn, del_ca; + } initiate, route, unroute, terminate, rekey, status, del_conn, del_ca; /* data for STR_TERMINATE_SRCIP */ struct { @@ -241,6 +248,7 @@ struct stroke_msg_t { int proxy_mode; int install_policy; u_int32_t reqid; + u_int32_t tfc; crl_policy_t crl_policy; int unique; diff --git a/src/whack/Makefile.in b/src/whack/Makefile.in index 270e8fe50..b51056a38 100644 --- a/src/whack/Makefile.in +++ b/src/whack/Makefile.in @@ -196,9 +196,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -237,6 +235,8 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ |