diff options
Diffstat (limited to 'src/libcharon/plugins/nm')
-rw-r--r-- | src/libcharon/plugins/nm/Makefile.am | 21 | ||||
-rw-r--r-- | src/libcharon/plugins/nm/Makefile.in | 595 | ||||
-rw-r--r-- | src/libcharon/plugins/nm/nm_creds.c | 447 | ||||
-rw-r--r-- | src/libcharon/plugins/nm/nm_creds.h | 85 | ||||
-rw-r--r-- | src/libcharon/plugins/nm/nm_handler.c | 193 | ||||
-rw-r--r-- | src/libcharon/plugins/nm/nm_handler.h | 62 | ||||
-rw-r--r-- | src/libcharon/plugins/nm/nm_plugin.c | 130 | ||||
-rw-r--r-- | src/libcharon/plugins/nm/nm_plugin.h | 42 | ||||
-rw-r--r-- | src/libcharon/plugins/nm/nm_service.c | 629 | ||||
-rw-r--r-- | src/libcharon/plugins/nm/nm_service.h | 55 |
10 files changed, 2259 insertions, 0 deletions
diff --git a/src/libcharon/plugins/nm/Makefile.am b/src/libcharon/plugins/nm/Makefile.am new file mode 100644 index 000000000..8e12a72be --- /dev/null +++ b/src/libcharon/plugins/nm/Makefile.am @@ -0,0 +1,21 @@ + +INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libcharon ${nm_CFLAGS} + +AM_CFLAGS = -rdynamic \ + -DNM_CA_DIR=\"${nm_ca_dir}\" + +if MONOLITHIC +noinst_LTLIBRARIES = libstrongswan-nm.la +else +plugin_LTLIBRARIES = libstrongswan-nm.la +endif + +libstrongswan_nm_la_SOURCES = \ + nm_plugin.h nm_plugin.c \ + nm_service.h nm_service.c \ + nm_creds.h nm_creds.c \ + nm_handler.h nm_handler.c + +libstrongswan_nm_la_LDFLAGS = -module -avoid-version +libstrongswan_nm_la_LIBADD = ${nm_LIBS} diff --git a/src/libcharon/plugins/nm/Makefile.in b/src/libcharon/plugins/nm/Makefile.in new file mode 100644 index 000000000..c7f288f54 --- /dev/null +++ b/src/libcharon/plugins/nm/Makefile.in @@ -0,0 +1,595 @@ +# 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, 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/nm +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)/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_nm_la_DEPENDENCIES = $(am__DEPENDENCIES_1) +am_libstrongswan_nm_la_OBJECTS = nm_plugin.lo nm_service.lo \ + nm_creds.lo nm_handler.lo +libstrongswan_nm_la_OBJECTS = $(am_libstrongswan_nm_la_OBJECTS) +libstrongswan_nm_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(libstrongswan_nm_la_LDFLAGS) $(LDFLAGS) -o $@ +@MONOLITHIC_FALSE@am_libstrongswan_nm_la_rpath = -rpath $(plugindir) +@MONOLITHIC_TRUE@am_libstrongswan_nm_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_nm_la_SOURCES) +DIST_SOURCES = $(libstrongswan_nm_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@ +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@ +datadir = @datadir@ +datarootdir = @datarootdir@ +default_pkcs11 = @default_pkcs11@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +gtk_CFLAGS = @gtk_CFLAGS@ +gtk_LIBS = @gtk_LIBS@ +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@ +ipsecgid = @ipsecgid@ +ipsecgroup = @ipsecgroup@ +ipsecuid = @ipsecuid@ +ipsecuser = @ipsecuser@ +libdir = @libdir@ +libexecdir = @libexecdir@ +libhydra_plugins = @libhydra_plugins@ +libstrongswan_plugins = @libstrongswan_plugins@ +linux_headers = @linux_headers@ +localedir = @localedir@ +localstatedir = @localstatedir@ +lt_ECHO = @lt_ECHO@ +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@ +plugindir = @plugindir@ +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@ +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 ${nm_CFLAGS} + +AM_CFLAGS = -rdynamic \ + -DNM_CA_DIR=\"${nm_ca_dir}\" + +@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-nm.la +@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-nm.la +libstrongswan_nm_la_SOURCES = \ + nm_plugin.h nm_plugin.c \ + nm_service.h nm_service.c \ + nm_creds.h nm_creds.c \ + nm_handler.h nm_handler.c + +libstrongswan_nm_la_LDFLAGS = -module -avoid-version +libstrongswan_nm_la_LIBADD = ${nm_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/libcharon/plugins/nm/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/libcharon/plugins/nm/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-nm.la: $(libstrongswan_nm_la_OBJECTS) $(libstrongswan_nm_la_DEPENDENCIES) + $(libstrongswan_nm_la_LINK) $(am_libstrongswan_nm_la_rpath) $(libstrongswan_nm_la_OBJECTS) $(libstrongswan_nm_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm_creds.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm_handler.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm_plugin.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm_service.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/nm/nm_creds.c b/src/libcharon/plugins/nm/nm_creds.c new file mode 100644 index 000000000..193838e6b --- /dev/null +++ b/src/libcharon/plugins/nm/nm_creds.c @@ -0,0 +1,447 @@ +/* + * 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 "nm_creds.h" + +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> + +#include <daemon.h> +#include <threading/rwlock.h> +#include <credentials/certificates/x509.h> + +typedef struct private_nm_creds_t private_nm_creds_t; + +/** + * private data of nm_creds + */ +struct private_nm_creds_t { + + /** + * public functions + */ + nm_creds_t public; + + /** + * List of trusted certificates, certificate_t* + */ + linked_list_t *certs; + + /** + * User name + */ + identification_t *user; + + /** + * User password + */ + char *pass; + + /** + * users certificate + */ + certificate_t *usercert; + + /** + * users private key + */ + private_key_t *key; + + /** + * read/write lock + */ + rwlock_t *lock; +}; + +/** + * Enumerator for user certificate + */ +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) + { + 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->usercert, NULL), + (void*)this->lock->unlock, this->lock); +} + +/** + * 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, + certificate_type_t cert, key_type_t key, + identification_t *id, bool trusted) +{ + if (id && this->usercert && + id->equals(id, this->usercert->get_subject(this->usercert))) + { + return create_usercert_enumerator(this, cert, key); + } + if (cert == CERT_X509 || cert == CERT_ANY) + { + return create_trusted_cert_enumerator(this, key, id); + } + return NULL; +} + +/** + * Implements credential_set_t.create_cert_enumerator + */ +static enumerator_t* create_private_enumerator(private_nm_creds_t *this, + key_type_t type, identification_t *id) +{ + if (this->key == NULL) + { + return NULL; + } + if (type != KEY_ANY && type != this->key->get_type(this->key)) + { + return NULL; + } + if (id && id->get_type(id) != ID_ANY) + { + if (id->get_type(id) != ID_KEY_ID || + !this->key->has_fingerprint(this->key, id->get_encoding(id))) + { + return NULL; + } + } + this->lock->read_lock(this->lock); + return enumerator_create_cleaner(enumerator_create_single(this->key, NULL), + (void*)this->lock->unlock, this->lock); +} + +/** + * shared key enumerator implementation + */ +typedef struct { + enumerator_t public; + private_nm_creds_t *this; + shared_key_t *key; + bool done; +} shared_enumerator_t; + +/** + * enumerate function for shared enumerator + */ +static bool shared_enumerate(shared_enumerator_t *this, shared_key_t **key, + id_match_t *me, id_match_t *other) +{ + if (this->done) + { + return FALSE; + } + *key = this->key; + *me = ID_MATCH_PERFECT; + *other = ID_MATCH_ANY; + this->done = TRUE; + return TRUE; +} + +/** + * Destroy function for shared enumerator + */ +static void shared_destroy(shared_enumerator_t *this) +{ + this->key->destroy(this->key); + this->this->lock->unlock(this->this->lock); + free(this); +} +/** + * Implements credential_set_t.create_cert_enumerator + */ +static enumerator_t* create_shared_enumerator(private_nm_creds_t *this, + shared_key_type_t type, identification_t *me, + identification_t *other) +{ + shared_enumerator_t *enumerator; + + if (!this->pass || !this->user) + { + return NULL; + } + if (type != SHARED_EAP && type != SHARED_IKE) + { + return NULL; + } + if (me && !me->equals(me, this->user)) + { + return NULL; + } + + enumerator = malloc_thing(shared_enumerator_t); + enumerator->public.enumerate = (void*)shared_enumerate; + enumerator->public.destroy = (void*)shared_destroy; + enumerator->this = this; + enumerator->done = FALSE; + this->lock->read_lock(this->lock); + enumerator->key = shared_key_create(type, + chunk_clone(chunk_create(this->pass, + strlen(this->pass)))); + return &enumerator->public; +} + +/** + * Implementation of nm_creds_t.add_certificate + */ +static void add_certificate(private_nm_creds_t *this, certificate_t *cert) +{ + this->lock->write_lock(this->lock); + 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, + char *password) +{ + this->lock->write_lock(this->lock); + DESTROY_IF(this->user); + this->user = id->clone(id); + free(this->pass); + this->pass = password ? strdup(password) : NULL; + this->lock->unlock(this->lock); +} + +/** + * Implementation of nm_creds_t.set_cert_and_key + */ +static void set_cert_and_key(private_nm_creds_t *this, certificate_t *cert, + private_key_t *key) +{ + this->lock->write_lock(this->lock); + DESTROY_IF(this->key); + DESTROY_IF(this->usercert); + 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) +{ + 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); + DESTROY_IF(this->key); + this->key = NULL; + this->usercert = NULL; + this->pass = NULL; + this->user = NULL; +} + +/** + * Implementation of nm_creds_t.destroy + */ +static void destroy(private_nm_creds_t *this) +{ + clear(this); + this->certs->destroy(this->certs); + this->lock->destroy(this->lock); + free(this); +} + +/* + * see header file + */ +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.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->certs = linked_list_create(); + this->user = NULL; + this->pass = NULL; + this->usercert = NULL; + this->key = NULL; + + return &this->public; +} + diff --git a/src/libcharon/plugins/nm/nm_creds.h b/src/libcharon/plugins/nm/nm_creds.h new file mode 100644 index 000000000..b55cff31e --- /dev/null +++ b/src/libcharon/plugins/nm/nm_creds.h @@ -0,0 +1,85 @@ +/* + * 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 nm_creds nm_creds + * @{ @ingroup nm + */ + +#ifndef NM_CREDS_H_ +#define NM_CREDS_H_ + +#include <credentials/keys/private_key.h> +#include <credentials/credential_set.h> + +typedef struct nm_creds_t nm_creds_t; + +/** + * NetworkManager credentials helper. + */ +struct nm_creds_t { + + /** + * Implements credential_set_t + */ + credential_set_t set; + + /** + * Add a trusted gateway certificate to serve by this set. + * + * @param cert certificate to serve + */ + 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. + * + * @param id ID of the user + * @param password password to use for authentication + */ + void (*set_username_password)(nm_creds_t *this, identification_t *id, + char *password); + /** + * Set the certificate and private key to use for client authentication. + * + * @param cert client certificate + * @param key associated private key + */ + void (*set_cert_and_key)(nm_creds_t *this, certificate_t *cert, + private_key_t *key); + /** + * Clear the stored credentials. + */ + void (*clear)(nm_creds_t *this); + + /** + * Destroy a nm_creds instance. + */ + void (*destroy)(nm_creds_t *this); +}; + +/** + * Create a nm_creds instance. + */ +nm_creds_t *nm_creds_create(); + +#endif /** NM_CREDS_H_ @}*/ diff --git a/src/libcharon/plugins/nm/nm_handler.c b/src/libcharon/plugins/nm/nm_handler.c new file mode 100644 index 000000000..eacb54dda --- /dev/null +++ b/src/libcharon/plugins/nm/nm_handler.c @@ -0,0 +1,193 @@ +/* + * Copyright (C) 2009 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 "nm_handler.h" + +#include <daemon.h> + +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 + */ + linked_list_t *nbns; +}; + +/** + * Implementation of attribute_handler_t.handle + */ +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: + list = this->dns; + break; + case INTERNAL_IP4_NBNS: + list = this->nbns; + break; + default: + return FALSE; + } + if (data.len != 4) + { + return FALSE; + } + list->insert_last(list, chunk_clone(data).ptr); + return TRUE; +} + +/** + * 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) +{ + *out = chunk_create(*in, 4); + return TRUE; +} + +/** + * Implementation of nm_handler_t.create_enumerator + */ +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: + list = this->dns; + break; + case INTERNAL_IP4_NBNS: + list = this->nbns; + break; + default: + return enumerator_create_empty(); + } + return enumerator_create_filter(list->create_enumerator(list), + (void*)filter_chunks, NULL, NULL); +} + +/** + * Implementation of nm_handler_t.reset + */ +static void reset(private_nm_handler_t *this) +{ + void *data; + + while (this->dns->remove_last(this->dns, (void**)&data) == SUCCESS) + { + free(data); + } + while (this->nbns->remove_last(this->nbns, (void**)&data) == SUCCESS) + { + free(data); + } +} + +/** + * Implementation of nm_handler_t.destroy. + */ +static void destroy(private_nm_handler_t *this) +{ + reset(this); + this->dns->destroy(this->dns); + this->nbns->destroy(this->nbns); + free(this); +} + +/** + * See header + */ +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*, 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/libcharon/plugins/nm/nm_handler.h b/src/libcharon/plugins/nm/nm_handler.h new file mode 100644 index 000000000..bb35ce767 --- /dev/null +++ b/src/libcharon/plugins/nm/nm_handler.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2009 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 nm_handler nm_handler + * @{ @ingroup nm + */ + +#ifndef NM_HANDLER_H_ +#define NM_HANDLER_H_ + +#include <attributes/attribute_handler.h> + +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. + * + * @param type type of attributes to enumerate + * @return enumerator over attribute data (chunk_t) + */ + enumerator_t* (*create_enumerator)(nm_handler_t *this, + configuration_attribute_type_t type); + /** + * Reset state, flush all received attributes. + */ + void (*reset)(nm_handler_t *this); + + /** + * Destroy a nm_handler_t. + */ + void (*destroy)(nm_handler_t *this); +}; + +/** + * Create a nm_handler instance. + */ +nm_handler_t *nm_handler_create(); + +#endif /** NM_HANDLER_H_ @}*/ diff --git a/src/libcharon/plugins/nm/nm_plugin.c b/src/libcharon/plugins/nm/nm_plugin.c new file mode 100644 index 000000000..6087f6589 --- /dev/null +++ b/src/libcharon/plugins/nm/nm_plugin.c @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2008-2009 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 "nm_plugin.h" +#include "nm_service.h" +#include "nm_creds.h" +#include "nm_handler.h" + +#include <hydra.h> +#include <daemon.h> +#include <processing/jobs/callback_job.h> + +#define CAP_DAC_OVERRIDE 1 + +typedef struct private_nm_plugin_t private_nm_plugin_t; + +/** + * private data of nm plugin + */ +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 + */ + nm_handler_t *handler; +}; + +/** + * NM plugin processing routine, creates and handles NMVPNPlugin + */ +static job_requeue_t run(private_nm_plugin_t *this) +{ + this->loop = g_main_loop_new(NULL, FALSE); + g_main_loop_run(this->loop); + return JOB_REQUEUE_NONE; +} + +/** + * Implementation of plugin_t.destroy + */ +static void destroy(private_nm_plugin_t *this) +{ + if (this->loop) + { + if (g_main_loop_is_running(this->loop)) + { + g_main_loop_quit(this->loop); + } + g_main_loop_unref(this->loop); + } + if (this->plugin) + { + g_object_unref(this->plugin); + } + charon->credentials->remove_set(charon->credentials, &this->creds->set); + hydra->attributes->remove_handler(hydra->attributes, &this->handler->handler); + this->creds->destroy(this->creds); + this->handler->destroy(this->handler); + free(this); +} + +/* + * see header file + */ +plugin_t *nm_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(); + hydra->attributes->add_handler(hydra->attributes, &this->handler->handler); + charon->credentials->add_set(charon->credentials, &this->creds->set); + this->plugin = nm_strongswan_plugin_new(this->creds, this->handler); + if (!this->plugin) + { + DBG1(DBG_CFG, "DBUS binding failed"); + 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, + (job_t*)callback_job_create((callback_job_cb_t)run, this, NULL, NULL)); + + return &this->public.plugin; +} + diff --git a/src/libcharon/plugins/nm/nm_plugin.h b/src/libcharon/plugins/nm/nm_plugin.h new file mode 100644 index 000000000..b64b3edf6 --- /dev/null +++ b/src/libcharon/plugins/nm/nm_plugin.h @@ -0,0 +1,42 @@ +/* + * 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 nm nm + * @ingroup cplugins + * + * @defgroup nm_plugin nm_plugin + * @{ @ingroup nm + */ + +#ifndef NM_PLUGIN_H_ +#define NM_PLUGIN_H_ + +#include <plugins/plugin.h> + +typedef struct nm_plugin_t nm_plugin_t; + +/** + * NetworkManager integration plugin. + */ +struct nm_plugin_t { + + /** + * implements plugin interface + */ + plugin_t plugin; +}; + +#endif /** NM_PLUGIN_H_ @}*/ diff --git a/src/libcharon/plugins/nm/nm_service.c b/src/libcharon/plugins/nm/nm_service.c new file mode 100644 index 000000000..cdf7dc962 --- /dev/null +++ b/src/libcharon/plugins/nm/nm_service.c @@ -0,0 +1,629 @@ +/* + * Copyright (C) 2008-2009 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 <nm-setting-vpn.h> +#include <nm-setting-connection.h> +#include "nm_service.h" + +#include <daemon.h> +#include <utils/host.h> +#include <utils/identification.h> +#include <config/peer_cfg.h> +#include <credentials/certificates/x509.h> + +#include <stdio.h> + +G_DEFINE_TYPE(NMStrongswanPlugin, nm_strongswan_plugin, NM_TYPE_VPN_PLUGIN) + +/** + * Private data of NMStrongswanPlugin + */ +typedef struct { + /* implements bus listener interface */ + listener_t listener; + /* IKE_SA we are listening on */ + ike_sa_t *ike_sa; + /* backref to public plugin */ + NMVPNPlugin *plugin; + /* credentials to use for authentication */ + nm_creds_t *creds; + /* attribute handler for DNS/NBNS server information */ + nm_handler_t *handler; + /* name of the connection */ + char *name; +} NMStrongswanPluginPrivate; + +#define NM_STRONGSWAN_PLUGIN_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), \ + NM_TYPE_STRONGSWAN_PLUGIN, NMStrongswanPluginPrivate)) + +/** + * convert enumerated handler chunks to a UINT_ARRAY GValue + */ +static GValue* handler_to_val(nm_handler_t *handler, + configuration_attribute_type_t type) +{ + GValue *val; + 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)) + { + g_array_append_val (array, *(u_int32_t*)chunk.ptr); + } + enumerator->destroy(enumerator); + val = g_slice_new0 (GValue); + g_value_init (val, DBUS_TYPE_G_UINT_ARRAY); + g_value_set_boxed (val, array); + + return val; +} + +/** + * signal IPv4 config to NM, set connection as established + */ +static void signal_ipv4_config(NMVPNPlugin *plugin, + ike_sa_t *ike_sa, child_sa_t *child_sa) +{ + GValue *val; + 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); +} + +/** + * signal failure to NM, connecting failed + */ +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_set_state(plugin, NM_VPN_SERVICE_STATE_STOPPED); +} + +/** + * Implementation of listener_t.ike_state_change + */ +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); + return FALSE; + } + return TRUE; +} + +/** + * Implementation of listener_t.child_state_change + */ +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); + return FALSE; + } + return TRUE; +} + +/** + * Implementation of listener_t.child_updown + */ +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) + { /* disable initiate-failure-detection hooks */ + private->listener.ike_state_change = NULL; + private->listener.child_state_change = NULL; + signal_ipv4_config(private->plugin, ike_sa, child_sa); + } + else + { + signal_failure(private->plugin, NM_VPN_PLUGIN_FAILURE_CONNECT_FAILED); + return FALSE; + } + } + return TRUE; +} + +/** + * Implementation of listener_t.ike_rekey + */ +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; + } + return TRUE; +} + +/** + * Connect function called from NM via DBUS + */ +static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection, + GError **err) +{ + NMStrongswanPluginPrivate *priv; + NMSettingConnection *conn; + NMSettingVPN *vpn; + identification_t *user = NULL, *gateway = NULL; + const char *address, *str; + bool virtual, encap, ipcomp; + ike_cfg_t *ike_cfg; + peer_cfg_t *peer_cfg; + child_cfg_t *child_cfg; + traffic_selector_t *ts; + ike_sa_t *ike_sa; + auth_cfg_t *auth; + auth_class_t auth_class = AUTH_CLASS_EAP; + 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 + */ + priv = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin); + conn = NM_SETTING_CONNECTION(nm_connection_get_setting(connection, + NM_TYPE_SETTING_CONNECTION)); + vpn = NM_SETTING_VPN(nm_connection_get_setting(connection, + NM_TYPE_SETTING_VPN)); + if (priv->name) + { + free(priv->name); + } + priv->name = strdup(nm_setting_connection_get_id(conn)); + DBG1(DBG_CFG, "received initiate for NetworkManager connection %s", + priv->name); + DBG4(DBG_CFG, "%s", + nm_setting_to_string(NM_SETTING(vpn))); + address = nm_setting_vpn_get_data_item(vpn, "address"); + if (!address || !*address) + { + g_set_error(err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS, + "Gateway address missing."); + return FALSE; + } + str = nm_setting_vpn_get_data_item(vpn, "virtual"); + virtual = str && streq(str, "yes"); + str = nm_setting_vpn_get_data_item(vpn, "encap"); + encap = str && streq(str, "yes"); + str = nm_setting_vpn_get_data_item(vpn, "ipcomp"); + ipcomp = str && streq(str, "yes"); + str = nm_setting_vpn_get_data_item(vpn, "method"); + if (str) + { + if (streq(str, "psk")) + { + auth_class = AUTH_CLASS_PSK; + } + else if (streq(str, "agent")) + { + auth_class = AUTH_CLASS_PUBKEY; + agent = TRUE; + } + else if (streq(str, "key")) + { + 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); + 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); + } + } + else + { + /* no certificate defined, fall back to system-wide CA certificates */ + priv->creds->load_ca_dir(priv->creds, NM_CA_DIR); + } + 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); + } + + if (auth_class == AUTH_CLASS_EAP) + { + /* username/password authentication ... */ + str = nm_setting_vpn_get_data_item(vpn, "user"); + if (str) + { + user = identification_create_from_string((char*)str); + str = nm_setting_vpn_get_secret(vpn, "password"); + priv->creds->set_username_password(priv->creds, user, (char*)str); + } + } + + if (auth_class == AUTH_CLASS_PUBKEY) + { + /* ... or certificate/private key authenitcation */ + str = nm_setting_vpn_get_data_item(vpn, "usercert"); + if (str) + { + 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) + { + g_set_error(err, NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS, + "Loading peer certificate failed."); + gateway->destroy(gateway); + return FALSE; + } + /* try agent */ + str = nm_setting_vpn_get_secret(vpn, "agent"); + if (agent && str) + { + public = cert->get_public_key(cert); + if (public) + { + private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, + public->get_type(public), + BUILD_AGENT_SOCKET, str, + BUILD_PUBLIC_KEY, public, + BUILD_END); + public->destroy(public); + } + if (!private) + { + g_set_error(err, NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS, + "Connecting to SSH agent failed."); + } + } + /* ... or key file */ + str = nm_setting_vpn_get_data_item(vpn, "userkey"); + if (!agent && str) + { + chunk_t secret; + + secret.ptr = (char*)nm_setting_vpn_get_secret(vpn, "password"); + if (secret.ptr) + { + secret.len = strlen(secret.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, + NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS, + "Loading private key failed."); + } + } + if (private) + { + user = cert->get_subject(cert); + user = user->clone(user); + priv->creds->set_cert_and_key(priv->creds, cert, private); + } + else + { + DESTROY_IF(cert); + gateway->destroy(gateway); + return FALSE; + } + } + } + + if (!user) + { + g_set_error(err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS, + "Configuration parameters missing."); + gateway->destroy(gateway); + return FALSE; + } + + /** + * Set up configurations + */ + ike_cfg = ike_cfg_create(TRUE, encap, + "0.0.0.0", IKEV2_UDP_PORT, (char*)address, IKEV2_UDP_PORT); + ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE)); + peer_cfg = peer_cfg_create(priv->name, 2, ike_cfg, + CERT_SEND_IF_ASKED, UNIQUE_REPLACE, 1, /* keyingtries */ + 36000, 0, /* rekey 10h, reauth none */ + 600, 600, /* jitter, over 10min */ + TRUE, 0, /* mobike, DPD */ + virtual ? host_create_from_string("0.0.0.0", 0) : NULL, + NULL, FALSE, NULL, NULL); /* pool, mediation */ + auth = auth_cfg_create(); + auth->add(auth, AUTH_RULE_AUTH_CLASS, auth_class); + auth->add(auth, AUTH_RULE_IDENTITY, user); + peer_cfg->add_auth_cfg(peer_cfg, auth, TRUE); + auth = auth_cfg_create(); + 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, &lifetime, + NULL, TRUE, MODE_TUNNEL, /* updown, hostaccess */ + 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); + ts = traffic_selector_create_from_string(0, TS_IPV4_ADDR_RANGE, + "0.0.0.0", 0, + "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 + */ + ike_sa = charon->ike_sa_manager->checkout_by_config(charon->ike_sa_manager, + peer_cfg); + if (!ike_sa->get_peer_cfg(ike_sa)) + { + ike_sa->set_peer_cfg(ike_sa, peer_cfg); + } + peer_cfg->destroy(peer_cfg); + + /** + * Register listener, enable initiate-failure-detection hooks + */ + priv->ike_sa = ike_sa; + 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 + */ + if (ike_sa->initiate(ike_sa, child_cfg, 0, NULL, NULL) != SUCCESS) + { + 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."); + return FALSE; + } + charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); + return TRUE; +} + +/** + * 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; + + settings = NM_SETTING_VPN(nm_connection_get_setting(connection, + NM_TYPE_SETTING_VPN)); + method = nm_setting_vpn_get_data_item(settings, "method"); + if (method) + { + if (streq(method, "eap")) + { + if (nm_setting_vpn_get_secret(settings, "password")) + { + return FALSE; + } + } + else if (streq(method, "agent")) + { + if (nm_setting_vpn_get_secret(settings, "agent")) + { + return FALSE; + } + } + else if (streq(method, "key")) + { + 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); + } + /* 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) + { + key->destroy(key); + return FALSE; + } + } + } + } + *setting_name = NM_SETTING_VPN_SETTING_NAME; + return TRUE; +} + +/** + * Disconnect called from NM via DBUS + */ +static gboolean disconnect(NMVPNPlugin *plugin, GError **err) +{ + NMStrongswanPluginPrivate *priv = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin); + 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)) + { + if (priv->ike_sa == ike_sa) + { + id = ike_sa->get_unique_id(ike_sa); + enumerator->destroy(enumerator); + charon->controller->terminate_ike(charon->controller, id, + controller_cb_empty, NULL); + return TRUE; + } + } + enumerator->destroy(enumerator); + + g_set_error(err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_GENERAL, + "Connection not found."); + return FALSE; +} + +/** + * Initializer + */ +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)); + priv->listener.child_updown = child_updown; + priv->listener.ike_rekey = ike_rekey; +} + +/** + * Class constructor + */ +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_; + parent_class->need_secrets = need_secrets; + parent_class->disconnect = disconnect; +} + +/** + * Object constructor + */ +NMStrongswanPlugin *nm_strongswan_plugin_new(nm_creds_t *creds, + nm_handler_t *handler) +{ + NMStrongswanPlugin *plugin = (NMStrongswanPlugin *)g_object_new ( + NM_TYPE_STRONGSWAN_PLUGIN, + NM_VPN_PLUGIN_DBUS_SERVICE_NAME, NM_DBUS_SERVICE_STRONGSWAN, + NULL); + if (plugin) + { + NMStrongswanPluginPrivate *priv; + + priv = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin); + priv->creds = creds; + priv->handler = handler; + priv->name = NULL; + } + return plugin; +} + diff --git a/src/libcharon/plugins/nm/nm_service.h b/src/libcharon/plugins/nm/nm_service.h new file mode 100644 index 000000000..b00000b6f --- /dev/null +++ b/src/libcharon/plugins/nm/nm_service.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2008-2009 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 nm_service nm_service + * @{ @ingroup nm + */ + +#ifndef NM_SERVICE_H_ +#define NM_SERVICE_H_ + +#include <glib/gtypes.h> +#include <glib-object.h> +#include <nm-vpn-plugin.h> + +#include "nm_creds.h" +#include "nm_handler.h" + +#define NM_TYPE_STRONGSWAN_PLUGIN (nm_strongswan_plugin_get_type ()) +#define NM_STRONGSWAN_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_STRONGSWAN_PLUGIN, NMSTRONGSWANPlugin)) +#define NM_STRONGSWAN_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_STRONGSWAN_PLUGIN, NMSTRONGSWANPluginClass)) +#define NM_IS_STRONGSWAN_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_STRONGSWAN_PLUGIN)) +#define NM_IS_STRONGSWAN_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_STRONGSWAN_PLUGIN)) +#define NM_STRONGSWAN_PLUGIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_STRONGSWAN_PLUGIN, NMSTRONGSWANPluginClass)) + +#define NM_DBUS_SERVICE_STRONGSWAN "org.freedesktop.NetworkManager.strongswan" +#define NM_DBUS_INTERFACE_STRONGSWAN "org.freedesktop.NetworkManager.strongswan" +#define NM_DBUS_PATH_STRONGSWAN "/org/freedesktop/NetworkManager/strongswan" + +typedef struct { + NMVPNPlugin parent; +} NMStrongswanPlugin; + +typedef struct { + NMVPNPluginClass parent; +} NMStrongswanPluginClass; + +GType nm_strongswan_plugin_get_type(void); + +NMStrongswanPlugin *nm_strongswan_plugin_new(nm_creds_t *creds, + nm_handler_t *handler); + +#endif /** NM_SERVICE_H_ @}*/ |