diff options
Diffstat (limited to 'src/charon/plugins/nm')
-rw-r--r-- | src/charon/plugins/nm/Makefile.am | 3 | ||||
-rw-r--r-- | src/charon/plugins/nm/Makefile.in | 147 | ||||
-rw-r--r-- | src/charon/plugins/nm/nm_creds.c | 240 | ||||
-rw-r--r-- | src/charon/plugins/nm/nm_creds.h | 15 | ||||
-rw-r--r-- | src/charon/plugins/nm/nm_handler.c | 69 | ||||
-rw-r--r-- | src/charon/plugins/nm/nm_handler.h | 10 | ||||
-rw-r--r-- | src/charon/plugins/nm/nm_plugin.c | 26 | ||||
-rw-r--r-- | src/charon/plugins/nm/nm_service.c | 168 |
8 files changed, 456 insertions, 222 deletions
diff --git a/src/charon/plugins/nm/Makefile.am b/src/charon/plugins/nm/Makefile.am index b74a4e46f..56eae6e00 100644 --- a/src/charon/plugins/nm/Makefile.am +++ b/src/charon/plugins/nm/Makefile.am @@ -1,7 +1,8 @@ INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon ${nm_CFLAGS} -AM_CFLAGS = -rdynamic +AM_CFLAGS = -rdynamic \ + -DNM_CA_DIR=\"${nm_ca_dir}\" plugin_LTLIBRARIES = libstrongswan-nm.la libstrongswan_nm_la_SOURCES = \ diff --git a/src/charon/plugins/nm/Makefile.in b/src/charon/plugins/nm/Makefile.in index c7c428c2a..90a50cfae 100644 --- a/src/charon/plugins/nm/Makefile.in +++ b/src/charon/plugins/nm/Makefile.in @@ -1,8 +1,9 @@ -# Makefile.in generated by automake 1.10.2 from Makefile.am. +# Makefile.in generated by automake 1.11 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. @@ -16,8 +17,9 @@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c @@ -35,19 +37,41 @@ host_triplet = @host@ subdir = src/charon/plugins/nm DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \ + $(top_srcdir)/m4/config/ltoptions.m4 \ + $(top_srcdir)/m4/config/ltsugar.m4 \ + $(top_srcdir)/m4/config/ltversion.m4 \ + $(top_srcdir)/m4/config/lt~obsolete.m4 \ + $(top_srcdir)/m4/macros/with.m4 \ + $(top_srcdir)/m4/macros/enable-disable.m4 \ + $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = am__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 = `echo $$p | sed -e 's|^.*/||'`; +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)" -pluginLTLIBRARIES_INSTALL = $(INSTALL) LTLIBRARIES = $(plugin_LTLIBRARIES) am__DEPENDENCIES_1 = libstrongswan_nm_la_DEPENDENCIES = $(am__DEPENDENCIES_1) @@ -60,6 +84,7 @@ libstrongswan_nm_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ 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) \ @@ -107,25 +132,22 @@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -IPSEC_ROUTING_TABLE = @IPSEC_ROUTING_TABLE@ -IPSEC_ROUTING_TABLE_PRIO = @IPSEC_ROUTING_TABLE_PRIO@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ -LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ -LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ -LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ -LINUX_HEADERS = @LINUX_HEADERS@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ +MYSQLCFLAG = @MYSQLCFLAG@ +MYSQLCONFIG = @MYSQLCONFIG@ +MYSQLLIB = @MYSQLLIB@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ @@ -137,11 +159,14 @@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PKG_CONFIG = @PKG_CONFIG@ +PTHREADLIB = @PTHREADLIB@ RANLIB = @RANLIB@ +RTLIB = @RTLIB@ RUBY = @RUBY@ RUBYINCLUDE = @RUBYINCLUDE@ SED = @SED@ @@ -170,9 +195,9 @@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ -confdir = @confdir@ datadir = @datadir@ datarootdir = @datarootdir@ +default_pkcs11 = @default_pkcs11@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ @@ -195,7 +220,7 @@ ipsecuser = @ipsecuser@ libdir = @libdir@ libexecdir = @libexecdir@ libstrongswan_plugins = @libstrongswan_plugins@ -linuxdir = @linuxdir@ +linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ lt_ECHO = @lt_ECHO@ @@ -203,6 +228,7 @@ mandir = @mandir@ mkdir_p = @mkdir_p@ nm_CFLAGS = @nm_CFLAGS@ nm_LIBS = @nm_LIBS@ +nm_ca_dir = @nm_ca_dir@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ piddir = @piddir@ @@ -211,10 +237,12 @@ pluto_plugins = @pluto_plugins@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ +random_device = @random_device@ resolv_conf = @resolv_conf@ +routing_table = @routing_table@ +routing_table_prio = @routing_table_prio@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ -simreader = @simreader@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ @@ -222,10 +250,13 @@ 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/charon ${nm_CFLAGS} -AM_CFLAGS = -rdynamic +AM_CFLAGS = -rdynamic \ + -DNM_CA_DIR=\"${nm_ca_dir}\" + plugin_LTLIBRARIES = libstrongswan-nm.la libstrongswan_nm_la_SOURCES = \ nm_plugin.h nm_plugin.c \ @@ -248,9 +279,9 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) exit 1;; \ esac; \ done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/charon/plugins/nm/Makefile'; \ - cd $(top_srcdir) && \ - $(AUTOMAKE) --gnu src/charon/plugins/nm/Makefile + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/charon/plugins/nm/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/charon/plugins/nm/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ @@ -268,23 +299,28 @@ $(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-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) @$(NORMAL_INSTALL) test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)" - @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \ + @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ + list2=; for p in $$list; do \ if test -f $$p; then \ - f=$(am__strip_dir) \ - echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(pluginLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(plugindir)/$$f'"; \ - $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(pluginLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(plugindir)/$$f"; \ + list2="$$list2 $$p"; \ else :; fi; \ - done + 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)'; for p in $$list; do \ - p=$(am__strip_dir) \ - echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$p'"; \ - $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$p"; \ + @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: @@ -311,21 +347,21 @@ distclean-compile: .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< @@ -348,7 +384,7 @@ tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) - tags=; \ + set x; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ @@ -356,29 +392,34 @@ TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ - if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - $$tags $$unique; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) - tags=; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ - test -z "$(CTAGS_ARGS)$$tags$$unique" \ + test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ - $$tags $$unique + $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ - && cd $(top_srcdir) \ - && gtags -i $(GTAGS_ARGS) $$here + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags @@ -399,13 +440,17 @@ distdir: $(DISTFILES) if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ - cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ - test -f $(distdir)/$$file \ - || cp -p $$d/$$file $(distdir)/$$file \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @@ -436,6 +481,7 @@ clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @@ -457,6 +503,8 @@ dvi-am: html: html-am +html-am: + info: info-am info-am: @@ -465,18 +513,28 @@ 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 @@ -515,6 +573,7 @@ uninstall-am: uninstall-pluginLTLIBRARIES 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/charon/plugins/nm/nm_creds.c b/src/charon/plugins/nm/nm_creds.c index 4ea2c36dd..193838e6b 100644 --- a/src/charon/plugins/nm/nm_creds.c +++ b/src/charon/plugins/nm/nm_creds.c @@ -15,8 +15,13 @@ #include "nm_creds.h" +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> + #include <daemon.h> -#include <utils/mutex.h> +#include <threading/rwlock.h> +#include <credentials/certificates/x509.h> typedef struct private_nm_creds_t private_nm_creds_t; @@ -29,32 +34,32 @@ struct private_nm_creds_t { * public functions */ nm_creds_t public; - + /** - * gateway certificate + * List of trusted certificates, certificate_t* */ - certificate_t *cert; - + linked_list_t *certs; + /** - * User name - */ - identification_t *user; - + * User name + */ + identification_t *user; + /** * User password */ char *pass; - + /** * users certificate */ certificate_t *usercert; - + /** * users private key */ private_key_t *key; - + /** * read/write lock */ @@ -68,13 +73,13 @@ static enumerator_t *create_usercert_enumerator(private_nm_creds_t *this, certificate_type_t cert, key_type_t key) { public_key_t *public; - + if (cert != CERT_ANY && cert != this->usercert->get_type(this->usercert)) { return NULL; } if (key != KEY_ANY) - { + { public = this->usercert->get_public_key(this->usercert); if (!public) { @@ -94,6 +99,80 @@ static enumerator_t *create_usercert_enumerator(private_nm_creds_t *this, } /** + * CA certificate enumerator data + */ +typedef struct { + /** ref to credential credential store */ + private_nm_creds_t *this; + /** type of key we are looking for */ + key_type_t key; + /** CA certificate ID */ + identification_t *id; +} cert_data_t; + +/** + * Destroy CA certificate enumerator data + */ +static void cert_data_destroy(cert_data_t *data) +{ + data->this->lock->unlock(data->this->lock); + free(data); +} + +/** + * Filter function for certificates enumerator + */ +static bool cert_filter(cert_data_t *data, certificate_t **in, + certificate_t **out) +{ + certificate_t *cert = *in; + public_key_t *public; + + public = cert->get_public_key(cert); + if (!public) + { + return FALSE; + } + if (data->key != KEY_ANY && public->get_type(public) != data->key) + { + public->destroy(public); + return FALSE; + } + if (data->id && data->id->get_type(data->id) == ID_KEY_ID && + public->has_fingerprint(public, data->id->get_encoding(data->id))) + { + public->destroy(public); + *out = cert; + return TRUE; + } + public->destroy(public); + if (data->id && !cert->has_subject(cert, data->id)) + { + return FALSE; + } + *out = cert; + return TRUE; +} + +/** + * Create enumerator for trusted certificates + */ +static enumerator_t *create_trusted_cert_enumerator(private_nm_creds_t *this, + key_type_t key, identification_t *id) +{ + cert_data_t *data = malloc_thing(cert_data_t); + + data->this = this; + data->id = id; + data->key = key; + + this->lock->read_lock(this->lock); + return enumerator_create_filter( + this->certs->create_enumerator(this->certs), + (void*)cert_filter, data, (void*)cert_data_destroy); +} + +/** * Implements credential_set_t.create_cert_enumerator */ static enumerator_t* create_cert_enumerator(private_nm_creds_t *this, @@ -105,38 +184,11 @@ static enumerator_t* create_cert_enumerator(private_nm_creds_t *this, { return create_usercert_enumerator(this, cert, key); } - - if (!this->cert) - { - return NULL; - } - if (cert != CERT_ANY && cert != this->cert->get_type(this->cert)) + if (cert == CERT_X509 || cert == CERT_ANY) { - return NULL; + return create_trusted_cert_enumerator(this, key, id); } - if (id && !this->cert->has_subject(this->cert, id)) - { - return NULL; - } - if (key != KEY_ANY) - { - public_key_t *public; - - public = this->cert->get_public_key(this->cert); - if (!public) - { - return NULL; - } - if (public->get_type(public) != key) - { - public->destroy(public); - return NULL; - } - public->destroy(public); - } - this->lock->read_lock(this->lock); - return enumerator_create_cleaner(enumerator_create_single(this->cert, NULL), - (void*)this->lock->unlock, this->lock); + return NULL; } /** @@ -155,10 +207,8 @@ static enumerator_t* create_private_enumerator(private_nm_creds_t *this, } if (id && id->get_type(id) != ID_ANY) { - identification_t *keyid; - - keyid = this->key->get_id(this->key, id->get_type(id)); - if (!keyid || !keyid->equals(keyid, id)) + if (id->get_type(id) != ID_KEY_ID || + !this->key->has_fingerprint(this->key, id->get_encoding(id))) { return NULL; } @@ -207,7 +257,7 @@ static void shared_destroy(shared_enumerator_t *this) /** * Implements credential_set_t.create_cert_enumerator */ -static enumerator_t* create_shared_enumerator(private_nm_creds_t *this, +static enumerator_t* create_shared_enumerator(private_nm_creds_t *this, shared_key_type_t type, identification_t *me, identification_t *other) { @@ -225,7 +275,7 @@ static enumerator_t* create_shared_enumerator(private_nm_creds_t *this, { return NULL; } - + enumerator = malloc_thing(shared_enumerator_t); enumerator->public.enumerate = (void*)shared_enumerate; enumerator->public.destroy = (void*)shared_destroy; @@ -239,17 +289,73 @@ static enumerator_t* create_shared_enumerator(private_nm_creds_t *this, } /** - * Implementation of nm_creds_t.set_certificate + * Implementation of nm_creds_t.add_certificate */ -static void set_certificate(private_nm_creds_t *this, certificate_t *cert) +static void add_certificate(private_nm_creds_t *this, certificate_t *cert) { this->lock->write_lock(this->lock); - DESTROY_IF(this->cert); - this->cert = cert; + this->certs->insert_last(this->certs, cert); this->lock->unlock(this->lock); } /** + * Load a certificate file + */ +static void load_ca_file(private_nm_creds_t *this, char *file) +{ + certificate_t *cert; + + /* We add the CA constraint, as many CAs miss it */ + cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, + BUILD_FROM_FILE, file, BUILD_END); + if (!cert) + { + DBG1(DBG_CFG, "loading CA certificate '%s' failed", file); + } + else + { + DBG2(DBG_CFG, "loaded CA certificate '%Y'", cert->get_subject(cert)); + x509_t *x509 = (x509_t*)cert; + if (!(x509->get_flags(x509) & X509_SELF_SIGNED)) + { + DBG1(DBG_CFG, "%Y is not self signed", cert->get_subject(cert)); + } + this->certs->insert_last(this->certs, cert); + } +} + +/** + * Implementation of nm_creds_t.load_ca_dir + */ +static void load_ca_dir(private_nm_creds_t *this, char *dir) +{ + enumerator_t *enumerator; + char *rel, *abs; + struct stat st; + + enumerator = enumerator_create_directory(dir); + if (enumerator) + { + while (enumerator->enumerate(enumerator, &rel, &abs, &st)) + { + /* skip '.', '..' and hidden files */ + if (rel[0] != '.') + { + if (S_ISDIR(st.st_mode)) + { + load_ca_dir(this, abs); + } + else if (S_ISREG(st.st_mode)) + { + load_ca_file(this, abs); + } + } + } + enumerator->destroy(enumerator); + } +} + +/** * Implementation of nm_creds_t.set_password */ static void set_username_password(private_nm_creds_t *this, identification_t *id, @@ -266,7 +372,7 @@ static void set_username_password(private_nm_creds_t *this, identification_t *id /** * Implementation of nm_creds_t.set_cert_and_key */ -static void set_cert_and_key(private_nm_creds_t *this, certificate_t *cert, +static void set_cert_and_key(private_nm_creds_t *this, certificate_t *cert, private_key_t *key) { this->lock->write_lock(this->lock); @@ -275,14 +381,19 @@ static void set_cert_and_key(private_nm_creds_t *this, certificate_t *cert, this->key = key; this->usercert = cert; this->lock->unlock(this->lock); -} +} /** * Implementation of nm_creds_t.clear */ static void clear(private_nm_creds_t *this) { - DESTROY_IF(this->cert); + certificate_t *cert; + + while (this->certs->remove_last(this->certs, (void**)&cert) == SUCCESS) + { + cert->destroy(cert); + } DESTROY_IF(this->user); free(this->pass); DESTROY_IF(this->usercert); @@ -290,7 +401,6 @@ static void clear(private_nm_creds_t *this) this->key = NULL; this->usercert = NULL; this->pass = NULL; - this->cert = NULL; this->user = NULL; } @@ -300,6 +410,7 @@ static void clear(private_nm_creds_t *this) static void destroy(private_nm_creds_t *this) { clear(this); + this->certs->destroy(this->certs); this->lock->destroy(this->lock); free(this); } @@ -310,26 +421,27 @@ static void destroy(private_nm_creds_t *this) nm_creds_t *nm_creds_create() { private_nm_creds_t *this = malloc_thing(private_nm_creds_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*)nop; - this->public.set_certificate = (void(*)(nm_creds_t*, certificate_t *cert))set_certificate; + this->public.add_certificate = (void(*)(nm_creds_t*, certificate_t *cert))add_certificate; + this->public.load_ca_dir = (void(*)(nm_creds_t*, char *dir))load_ca_dir; this->public.set_username_password = (void(*)(nm_creds_t*, identification_t *id, char *password))set_username_password; this->public.set_cert_and_key = (void(*)(nm_creds_t*, certificate_t *cert, private_key_t *key))set_cert_and_key; this->public.clear = (void(*)(nm_creds_t*))clear; this->public.destroy = (void(*)(nm_creds_t*))destroy; - + this->lock = rwlock_create(RWLOCK_TYPE_DEFAULT); - - this->cert = NULL; + + this->certs = linked_list_create(); this->user = NULL; this->pass = NULL; this->usercert = NULL; this->key = NULL; - + return &this->public; } diff --git a/src/charon/plugins/nm/nm_creds.h b/src/charon/plugins/nm/nm_creds.h index 421442c81..b55cff31e 100644 --- a/src/charon/plugins/nm/nm_creds.h +++ b/src/charon/plugins/nm/nm_creds.h @@ -35,14 +35,21 @@ struct nm_creds_t { * Implements credential_set_t */ credential_set_t set; - + /** - * Set the trusted gateway certificate to serve by this set. + * Add a trusted gateway certificate to serve by this set. * * @param cert certificate to serve */ - void (*set_certificate)(nm_creds_t *this, certificate_t *cert); - + void (*add_certificate)(nm_creds_t *this, certificate_t *cert); + + /** + * Load CA certificates recursively from a directory. + * + * @param dir directory to PEM encoded CA certificates + */ + void (*load_ca_dir)(nm_creds_t *this, char *dir); + /** * Set the username/password for authentication. * diff --git a/src/charon/plugins/nm/nm_handler.c b/src/charon/plugins/nm/nm_handler.c index 026c47af2..eacb54dda 100644 --- a/src/charon/plugins/nm/nm_handler.c +++ b/src/charon/plugins/nm/nm_handler.c @@ -23,17 +23,17 @@ typedef struct private_nm_handler_t private_nm_handler_t; * Private data of an nm_handler_t object. */ struct private_nm_handler_t { - + /** * Public nm_handler_t interface. */ nm_handler_t public; - + /** * list of received DNS server attributes, pointer to 4 byte data */ linked_list_t *dns; - + /** * list of received NBNS server attributes, pointer to 4 byte data */ @@ -43,11 +43,11 @@ struct private_nm_handler_t { /** * Implementation of attribute_handler_t.handle */ -static bool handle(private_nm_handler_t *this, ike_sa_t *ike_sa, +static bool handle(private_nm_handler_t *this, identification_t *server, configuration_attribute_type_t type, chunk_t data) { linked_list_t *list; - + switch (type) { case INTERNAL_IP4_DNS: @@ -68,6 +68,50 @@ static bool handle(private_nm_handler_t *this, ike_sa_t *ike_sa, } /** + * Implementation of create_attribute_enumerator().enumerate() for WINS + */ +static bool enumerate_nbns(enumerator_t *this, + configuration_attribute_type_t *type, chunk_t *data) +{ + *type = INTERNAL_IP4_NBNS; + *data = chunk_empty; + /* done */ + this->enumerate = (void*)return_false; + return TRUE; +} + +/** + * Implementation of create_attribute_enumerator().enumerate() for DNS + */ +static bool enumerate_dns(enumerator_t *this, + configuration_attribute_type_t *type, chunk_t *data) +{ + *type = INTERNAL_IP4_DNS; + *data = chunk_empty; + /* enumerate WINS server as next attribute ... */ + this->enumerate = (void*)enumerate_nbns; + return TRUE; +} + +/** + * Implementation of attribute_handler_t.create_attribute_enumerator + */ +static enumerator_t* create_attribute_enumerator(private_nm_handler_t *this, + identification_t *server, host_t *vip) +{ + if (vip && vip->get_family(vip) == AF_INET) + { /* no IPv6 attributes yet */ + enumerator_t *enumerator = malloc_thing(enumerator_t); + /* enumerate DNS attribute first ... */ + enumerator->enumerate = (void*)enumerate_dns; + enumerator->destroy = (void*)free; + + return enumerator; + } + return enumerator_create_empty(); +} + +/** * convert plain byte ptrs to handy chunk during enumeration */ static bool filter_chunks(void* null, char **in, chunk_t *out) @@ -83,7 +127,7 @@ static enumerator_t* create_enumerator(private_nm_handler_t *this, configuration_attribute_type_t type) { linked_list_t *list; - + switch (type) { case INTERNAL_IP4_DNS: @@ -105,7 +149,7 @@ static enumerator_t* create_enumerator(private_nm_handler_t *this, static void reset(private_nm_handler_t *this) { void *data; - + while (this->dns->remove_last(this->dns, (void**)&data) == SUCCESS) { free(data); @@ -133,16 +177,17 @@ static void destroy(private_nm_handler_t *this) nm_handler_t *nm_handler_create() { private_nm_handler_t *this = malloc_thing(private_nm_handler_t); - - this->public.handler.handle = (bool(*)(attribute_handler_t*, ike_sa_t*, configuration_attribute_type_t, chunk_t))handle; - this->public.handler.release = (void(*)(attribute_handler_t*, ike_sa_t*, configuration_attribute_type_t, chunk_t))nop; + + this->public.handler.handle = (bool(*)(attribute_handler_t*, identification_t*, configuration_attribute_type_t, chunk_t))handle; + this->public.handler.release = (void(*)(attribute_handler_t*, identification_t*, configuration_attribute_type_t, chunk_t))nop; + this->public.handler.create_attribute_enumerator = (enumerator_t*(*)(attribute_handler_t*, identification_t *server, host_t *vip))create_attribute_enumerator; this->public.create_enumerator = (enumerator_t*(*)(nm_handler_t*, configuration_attribute_type_t type))create_enumerator; this->public.reset = (void(*)(nm_handler_t*))reset; this->public.destroy = (void(*)(nm_handler_t*))destroy; - + this->dns = linked_list_create(); this->nbns = linked_list_create(); - + return &this->public; } diff --git a/src/charon/plugins/nm/nm_handler.h b/src/charon/plugins/nm/nm_handler.h index d537bb8de..bb35ce767 100644 --- a/src/charon/plugins/nm/nm_handler.h +++ b/src/charon/plugins/nm/nm_handler.h @@ -21,7 +21,7 @@ #ifndef NM_HANDLER_H_ #define NM_HANDLER_H_ -#include <config/attributes/attribute_handler.h> +#include <attributes/attribute_handler.h> typedef struct nm_handler_t nm_handler_t; @@ -29,12 +29,12 @@ typedef struct nm_handler_t nm_handler_t; * Handles DNS/NBNS attributes to pass to NM. */ struct nm_handler_t { - + /** * Implements attribute handler interface */ attribute_handler_t handler; - + /** * Create an enumerator over received attributes of a given kind. * @@ -47,7 +47,7 @@ struct nm_handler_t { * Reset state, flush all received attributes. */ void (*reset)(nm_handler_t *this); - + /** * Destroy a nm_handler_t. */ @@ -59,4 +59,4 @@ struct nm_handler_t { */ nm_handler_t *nm_handler_create(); -#endif /* NM_HANDLER_ @}*/ +#endif /** NM_HANDLER_H_ @}*/ diff --git a/src/charon/plugins/nm/nm_plugin.c b/src/charon/plugins/nm/nm_plugin.c index 1fb46f814..daf2cc660 100644 --- a/src/charon/plugins/nm/nm_plugin.c +++ b/src/charon/plugins/nm/nm_plugin.c @@ -34,22 +34,22 @@ struct private_nm_plugin_t { * implements plugin interface */ nm_plugin_t public; - + /** * NetworkManager service (VPNPlugin) */ NMStrongswanPlugin *plugin; - + /** * Glib main loop for a thread, handles DBUS calls */ GMainLoop *loop; - + /** * credential set registered at the daemon */ nm_creds_t *creds; - + /** * attribute handler regeisterd at the daemon */ @@ -84,8 +84,8 @@ static void destroy(private_nm_plugin_t *this) g_object_unref(this->plugin); } charon->credentials->remove_set(charon->credentials, &this->creds->set); + lib->attributes->remove_handler(lib->attributes, &this->handler->handler); this->creds->destroy(this->creds); - charon->attributes->remove_handler(charon->attributes, &this->handler->handler); this->handler->destroy(this->handler); free(this); } @@ -96,20 +96,20 @@ static void destroy(private_nm_plugin_t *this) plugin_t *plugin_create() { private_nm_plugin_t *this = malloc_thing(private_nm_plugin_t); - + this->public.plugin.destroy = (void(*)(plugin_t*))destroy; - + this->loop = NULL; g_type_init (); if (!g_thread_supported()) { g_thread_init(NULL); } - + this->creds = nm_creds_create(); this->handler = nm_handler_create(); + lib->attributes->add_handler(lib->attributes, &this->handler->handler); charon->credentials->add_set(charon->credentials, &this->creds->set); - charon->attributes->add_handler(charon->attributes, &this->handler->handler); this->plugin = nm_strongswan_plugin_new(this->creds, this->handler); if (!this->plugin) { @@ -117,13 +117,13 @@ plugin_t *plugin_create() destroy(this); return NULL; } - + /* bypass file permissions to read from users ssh-agent */ charon->keep_cap(charon, CAP_DAC_OVERRIDE); - - charon->processor->queue_job(charon->processor, + + charon->processor->queue_job(charon->processor, (job_t*)callback_job_create((callback_job_cb_t)run, this, NULL, NULL)); - + return &this->public.plugin; } diff --git a/src/charon/plugins/nm/nm_service.c b/src/charon/plugins/nm/nm_service.c index 88a3cc95e..b05383c2b 100644 --- a/src/charon/plugins/nm/nm_service.c +++ b/src/charon/plugins/nm/nm_service.c @@ -18,7 +18,6 @@ #include "nm_service.h" #include <daemon.h> -#include <asn1/pem.h> #include <utils/host.h> #include <utils/identification.h> #include <config/peer_cfg.h> @@ -60,7 +59,7 @@ static GValue* handler_to_val(nm_handler_t *handler, GArray *array; enumerator_t *enumerator; chunk_t chunk; - + enumerator = handler->create_enumerator(handler, type); array = g_array_new (FALSE, TRUE, sizeof (guint32)); while (enumerator->enumerate(enumerator, &chunk)) @@ -71,7 +70,7 @@ static GValue* handler_to_val(nm_handler_t *handler, val = g_slice_new0 (GValue); g_value_init (val, DBUS_TYPE_G_UINT_ARRAY); g_value_set_boxed (val, array); - + return val; } @@ -85,37 +84,37 @@ static void signal_ipv4_config(NMVPNPlugin *plugin, GHashTable *config; host_t *me, *other; nm_handler_t *handler; - + config = g_hash_table_new(g_str_hash, g_str_equal); me = ike_sa->get_my_host(ike_sa); other = ike_sa->get_other_host(ike_sa); handler = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin)->handler; - + /* NM requires a tundev, but netkey does not use one. Passing an invalid * iface makes NM complain, but it accepts it without fiddling on eth0. */ val = g_slice_new0 (GValue); g_value_init (val, G_TYPE_STRING); g_value_set_string (val, "none"); g_hash_table_insert (config, NM_VPN_PLUGIN_IP4_CONFIG_TUNDEV, val); - + val = g_slice_new0(GValue); g_value_init(val, G_TYPE_UINT); g_value_set_uint(val, *(u_int32_t*)me->get_address(me).ptr); g_hash_table_insert(config, NM_VPN_PLUGIN_IP4_CONFIG_ADDRESS, val); - + val = g_slice_new0(GValue); g_value_init(val, G_TYPE_UINT); g_value_set_uint(val, me->get_address(me).len * 8); g_hash_table_insert(config, NM_VPN_PLUGIN_IP4_CONFIG_PREFIX, val); - + val = handler_to_val(handler, INTERNAL_IP4_DNS); g_hash_table_insert(config, NM_VPN_PLUGIN_IP4_CONFIG_DNS, val); - + val = handler_to_val(handler, INTERNAL_IP4_NBNS); g_hash_table_insert(config, NM_VPN_PLUGIN_IP4_CONFIG_NBNS, val); - + handler->reset(handler); - + nm_vpn_plugin_set_ip4_config(plugin, config); } @@ -125,11 +124,11 @@ static void signal_ipv4_config(NMVPNPlugin *plugin, static void signal_failure(NMVPNPlugin *plugin, NMVPNPluginFailure failure) { nm_handler_t *handler = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin)->handler; - + handler->reset(handler); - + /* TODO: NM does not handle this failure!? */ - nm_vpn_plugin_failure(plugin, failure); + nm_vpn_plugin_failure(plugin, failure); nm_vpn_plugin_set_state(plugin, NM_VPN_SERVICE_STATE_STOPPED); } @@ -140,7 +139,7 @@ static bool ike_state_change(listener_t *listener, ike_sa_t *ike_sa, ike_sa_state_t state) { NMStrongswanPluginPrivate *private = (NMStrongswanPluginPrivate*)listener; - + if (private->ike_sa == ike_sa && state == IKE_DESTROYING) { signal_failure(private->plugin, NM_VPN_PLUGIN_FAILURE_LOGIN_FAILED); @@ -156,7 +155,7 @@ static bool child_state_change(listener_t *listener, ike_sa_t *ike_sa, child_sa_t *child_sa, child_sa_state_t state) { NMStrongswanPluginPrivate *private = (NMStrongswanPluginPrivate*)listener; - + if (private->ike_sa == ike_sa && state == CHILD_DESTROYING) { signal_failure(private->plugin, NM_VPN_PLUGIN_FAILURE_CONNECT_FAILED); @@ -172,7 +171,7 @@ static bool child_updown(listener_t *listener, ike_sa_t *ike_sa, child_sa_t *child_sa, bool up) { NMStrongswanPluginPrivate *private = (NMStrongswanPluginPrivate*)listener; - + if (private->ike_sa == ike_sa) { if (up) @@ -196,7 +195,7 @@ static bool child_updown(listener_t *listener, ike_sa_t *ike_sa, static bool ike_rekey(listener_t *listener, ike_sa_t *old, ike_sa_t *new) { NMStrongswanPluginPrivate *private = (NMStrongswanPluginPrivate*)listener; - + if (private->ike_sa == old) { /* follow a rekeyed IKE_SA */ private->ike_sa = new; @@ -213,7 +212,7 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection, NMStrongswanPluginPrivate *priv; NMSettingConnection *conn; NMSettingVPN *vpn; - identification_t *user = NULL, *gateway; + identification_t *user = NULL, *gateway = NULL; const char *address, *str; bool virtual, encap, ipcomp; ike_cfg_t *ike_cfg; @@ -226,7 +225,14 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection, certificate_t *cert = NULL; x509_t *x509; bool agent = FALSE; - + lifetime_cfg_t lifetime = { + .time = { + .life = 10800 /* 3h */, + .rekey = 10200 /* 2h50min */, + .jitter = 300 /* 5min */ + } + }; + /** * Read parameters */ @@ -248,7 +254,7 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection, if (!address || !*address) { g_set_error(err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS, - "Gateway address missing."); + "Gateway address missing."); return FALSE; } str = nm_setting_vpn_get_data_item(vpn, "virtual"); @@ -274,42 +280,50 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection, auth_class = AUTH_CLASS_PUBKEY; } } - + /** * Register credentials */ priv->creds->clear(priv->creds); - + /* gateway/CA cert */ str = nm_setting_vpn_get_data_item(vpn, "certificate"); if (str) { cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, BUILD_FROM_FILE, str, BUILD_END); - priv->creds->set_certificate(priv->creds, cert); + if (!cert) + { + g_set_error(err, NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS, + "Loading gateway certificate failed."); + return FALSE; + } + priv->creds->add_certificate(priv->creds, cert); + + x509 = (x509_t*)cert; + if (!(x509->get_flags(x509) & X509_CA)) + { /* For a gateway certificate, we use the cert subject as identity. */ + gateway = cert->get_subject(cert); + gateway = gateway->clone(gateway); + DBG1(DBG_CFG, "using gateway certificate, identity '%Y'", gateway); + } } - if (!cert) + else { - g_set_error(err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS, - "Loading gateway certificate failed."); - return FALSE; + /* no certificate defined, fall back to system-wide CA certificates */ + priv->creds->load_ca_dir(priv->creds, NM_CA_DIR); } - x509 = (x509_t*)cert; - if (x509->get_flags(x509) & X509_CA) - { /* If the user configured a CA certificate, we use the IP/DNS + if (!gateway) + { + /* If the user configured a CA certificate, we use the IP/DNS * of the gateway as its identity. This identity will be used for * certificate lookup and requires the configured IP/DNS to be * included in the gateway certificate. */ gateway = identification_create_from_string((char*)address); DBG1(DBG_CFG, "using CA certificate, gateway identity '%Y'", gateway); } - else - { /* For a gateway certificate, we use the cert subject as identity. */ - gateway = cert->get_subject(cert); - gateway = gateway->clone(gateway); - DBG1(DBG_CFG, "using gateway certificate, identity '%Y'", gateway); - } - + if (auth_class == AUTH_CLASS_EAP) { /* username/password authentication ... */ @@ -321,7 +335,7 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection, priv->creds->set_username_password(priv->creds, user, (char*)str); } } - + if (auth_class == AUTH_CLASS_PUBKEY) { /* ... or certificate/private key authenitcation */ @@ -330,7 +344,7 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection, { public_key_t *public; private_key_t *private = NULL; - + cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, BUILD_FROM_FILE, str, BUILD_END); if (!cert) @@ -341,7 +355,7 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection, gateway->destroy(gateway); return FALSE; } - /* try agent */ + /* try agent */ str = nm_setting_vpn_get_secret(vpn, "agent"); if (agent && str) { @@ -362,24 +376,20 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection, "Connecting to SSH agent failed."); } } - /* ... or key file */ + /* ... or key file */ str = nm_setting_vpn_get_data_item(vpn, "userkey"); if (!agent && str) { - chunk_t secret, chunk; - bool pgp = FALSE; - + chunk_t secret; + secret.ptr = (char*)nm_setting_vpn_get_secret(vpn, "password"); if (secret.ptr) { secret.len = strlen(secret.ptr); } - if (pem_asn1_load_file((char*)str, &secret, &chunk, &pgp)) - { - private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, - KEY_RSA, BUILD_BLOB_ASN1_DER, chunk, BUILD_END); - free(chunk.ptr); - } + private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, + KEY_RSA, BUILD_FROM_FILE, str, + BUILD_PASSPHRASE, secret, BUILD_END); if (!private) { g_set_error(err, NM_VPN_PLUGIN_ERROR, @@ -401,7 +411,7 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection, } } } - + if (!user) { g_set_error(err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS, @@ -409,7 +419,7 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection, gateway->destroy(gateway); return FALSE; } - + /** * Set up configurations */ @@ -430,12 +440,10 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection, auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY); auth->add(auth, AUTH_RULE_IDENTITY, gateway); peer_cfg->add_auth_cfg(peer_cfg, auth, FALSE); - - child_cfg = child_cfg_create(priv->name, - 10800, 10200, /* lifetime 3h, rekey 2h50min */ - 300, /* jitter 5min */ + + child_cfg = child_cfg_create(priv->name, &lifetime, NULL, TRUE, MODE_TUNNEL, /* updown, hostaccess */ - ACTION_NONE, ACTION_NONE, ipcomp); + ACTION_NONE, ACTION_NONE, ipcomp, 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); @@ -444,7 +452,7 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection, "255.255.255.255", 65535); child_cfg->add_traffic_selector(child_cfg, FALSE, ts); peer_cfg->add_child_cfg(peer_cfg, child_cfg); - + /** * Prepare IKE_SA */ @@ -454,11 +462,8 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection, { ike_sa->set_peer_cfg(ike_sa, peer_cfg); } - else - { - peer_cfg->destroy(peer_cfg); - } - + peer_cfg->destroy(peer_cfg); + /** * Register listener, enable initiate-failure-detection hooks */ @@ -466,7 +471,7 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection, priv->listener.ike_state_change = ike_state_change; priv->listener.child_state_change = child_state_change; charon->bus->add_listener(charon->bus, &priv->listener); - + /** * Initiate */ @@ -474,9 +479,9 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection, { charon->bus->remove_listener(charon->bus, &priv->listener); charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, ike_sa); - + g_set_error(err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED, - "Initiating failed."); + "Initiating failed."); return FALSE; } charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); @@ -484,16 +489,14 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection, } /** - * NeedSecrets called from NM via DBUS + * NeedSecrets called from NM via DBUS */ static gboolean need_secrets(NMVPNPlugin *plugin, NMConnection *connection, char **setting_name, GError **error) { NMSettingVPN *settings; const char *method, *path; - chunk_t secret = chunk_empty, key; - bool pgp = FALSE; - + settings = NM_SETTING_VPN(nm_connection_get_setting(connection, NM_TYPE_SETTING_VPN)); method = nm_setting_vpn_get_data_item(settings, "method"); @@ -518,14 +521,21 @@ static gboolean need_secrets(NMVPNPlugin *plugin, NMConnection *connection, path = nm_setting_vpn_get_data_item(settings, "userkey"); if (path) { + private_key_t *key; + chunk_t secret; + secret.ptr = (char*)nm_setting_vpn_get_secret(settings, "password"); if (secret.ptr) { secret.len = strlen(secret.ptr); } - if (pem_asn1_load_file((char*)path, &secret, &key, &pgp)) + /* try to load/decrypt the private key */ + key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, + KEY_RSA, BUILD_FROM_FILE, path, + BUILD_PASSPHRASE, secret, BUILD_END); + if (key) { - free(key.ptr); + key->destroy(key); return FALSE; } } @@ -536,7 +546,7 @@ static gboolean need_secrets(NMVPNPlugin *plugin, NMConnection *connection, } /** - * Disconnect called from NM via DBUS + * Disconnect called from NM via DBUS */ static gboolean disconnect(NMVPNPlugin *plugin, GError **err) { @@ -544,7 +554,7 @@ static gboolean disconnect(NMVPNPlugin *plugin, GError **err) enumerator_t *enumerator; ike_sa_t *ike_sa; u_int id; - + /* our ike_sa pointer might be invalid, lookup sa */ enumerator = charon->controller->create_ike_sa_enumerator(charon->controller); while (enumerator->enumerate(enumerator, &ike_sa)) @@ -559,7 +569,7 @@ static gboolean disconnect(NMVPNPlugin *plugin, GError **err) } } enumerator->destroy(enumerator); - + g_set_error(err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_GENERAL, "Connection not found."); return FALSE; @@ -571,7 +581,7 @@ static gboolean disconnect(NMVPNPlugin *plugin, GError **err) static void nm_strongswan_plugin_init(NMStrongswanPlugin *plugin) { NMStrongswanPluginPrivate *priv; - + priv = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin); priv->plugin = NM_VPN_PLUGIN(plugin); memset(&priv->listener.log, 0, sizeof(listener_t)); @@ -586,7 +596,7 @@ static void nm_strongswan_plugin_class_init( NMStrongswanPluginClass *strongswan_class) { NMVPNPluginClass *parent_class = NM_VPN_PLUGIN_CLASS(strongswan_class); - + g_type_class_add_private(G_OBJECT_CLASS(strongswan_class), sizeof(NMStrongswanPluginPrivate)); parent_class->connect = connect_; @@ -607,7 +617,7 @@ NMStrongswanPlugin *nm_strongswan_plugin_new(nm_creds_t *creds, if (plugin) { NMStrongswanPluginPrivate *priv; - + priv = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin); priv->creds = creds; priv->handler = handler; |