diff options
Diffstat (limited to 'src/pluto')
42 files changed, 3007 insertions, 1422 deletions
diff --git a/src/pluto/Makefile.am b/src/pluto/Makefile.am index a264e642e..9f631ca28 100644 --- a/src/pluto/Makefile.am +++ b/src/pluto/Makefile.am @@ -37,6 +37,7 @@ nat_traversal.c nat_traversal.h \ ocsp.c ocsp.h \ packet.c packet.h \ pkcs7.c pkcs7.h \ +pluto.c pluto.h \ plutomain.c \ rcv_whack.c rcv_whack.h \ server.c server.h \ @@ -47,7 +48,8 @@ timer.c timer.h \ vendor.c vendor.h \ virtual.c virtual.h \ whack_attribute.c whack_attribute.h \ -xauth.c xauth.h \ +xauth/xauth_manager.c xauth/xauth_manager.h \ +xauth/xauth_provider.h xauth/xauth_verifier.h \ x509.c x509.h \ builder.c builder.h \ rsaref/pkcs11t.h rsaref/pkcs11.h rsaref/unix.h rsaref/pkcs11f.h @@ -67,12 +69,12 @@ INCLUDES = \ -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/whack -AM_CFLAGS = \ +AM_CFLAGS = -rdynamic \ -DIPSEC_DIR=\"${ipsecdir}\" \ -DIPSEC_CONFDIR=\"${sysconfdir}\" \ -DIPSEC_PIDDIR=\"${piddir}\" \ -DSHARED_SECRETS_FILE=\"${sysconfdir}/ipsec.secrets\" \ --DPLUGINS=\""${pluto_plugins}\"" \ +-DPLUGINS=\""${pluto_plugins} ${libhydra_plugins}\"" \ -DPKCS11_DEFAULT_LIB=\"${default_pkcs11}\" \ -DKERNEL26_SUPPORT -DKERNEL26_HAS_KAME_DUPLICATES \ -DPLUTO -DKLIPS -DDEBUG @@ -87,7 +89,12 @@ _pluto_adns_LDADD = \ $(LIBFREESWANDIR)/libfreeswan.a \ -lresolv $(DLLIB) +CLEANFILES = ipsec.secrets.5 dist_man_MANS = pluto.8 ipsec.secrets.5 +EXTRA_DIST = ipsec.secrets.5.in + +# compile options +################# # This compile option activates the sending of a strongSwan VID if USE_VENDORID @@ -114,10 +121,25 @@ if USE_SMARTCARD AM_CFLAGS += -DSMARTCARD endif -if USE_CAPABILITIES +if USE_LIBCAP pluto_LDADD += -lcap endif if USE_THREADS AM_CFLAGS += -DTHREADS endif + +# build optional plugins +######################## + +SUBDIRS = . + +if USE_XAUTH + SUBDIRS += plugins/xauth +endif + +ipsec.secrets.5 : ipsec.secrets.5.in + sed \ + -e "s:@IPSEC_VERSION@:$(PACKAGE_VERSION):" \ + $(srcdir)/$@.in > $@ + diff --git a/src/pluto/Makefile.in b/src/pluto/Makefile.in index 47be9acf7..41fc4927e 100644 --- a/src/pluto/Makefile.in +++ b/src/pluto/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.11 from Makefile.am. +# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, @@ -40,6 +40,9 @@ build_triplet = @build@ host_triplet = @host@ ipsec_PROGRAMS = pluto$(EXEEXT) _pluto_adns$(EXEEXT) +# compile options +################# + # This compile option activates the sending of a strongSwan VID @USE_VENDORID_TRUE@am__append_1 = -DVENDORID @@ -54,8 +57,9 @@ ipsec_PROGRAMS = pluto$(EXEEXT) _pluto_adns$(EXEEXT) # This compile option activates smartcard support @USE_SMARTCARD_TRUE@am__append_5 = -DSMARTCARD -@USE_CAPABILITIES_TRUE@am__append_6 = -lcap +@USE_LIBCAP_TRUE@am__append_6 = -lcap @USE_THREADS_TRUE@am__append_7 = -DTHREADS +@USE_XAUTH_TRUE@am__append_8 = plugins/xauth subdir = src/pluto DIST_COMMON = $(dist_man_MANS) $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in @@ -91,11 +95,11 @@ am_pluto_OBJECTS = ac.$(OBJEXT) alg_info.$(OBJEXT) ca.$(OBJEXT) \ kernel_noklips.$(OBJEXT) kernel_pfkey.$(OBJEXT) keys.$(OBJEXT) \ lex.$(OBJEXT) log.$(OBJEXT) myid.$(OBJEXT) modecfg.$(OBJEXT) \ nat_traversal.$(OBJEXT) ocsp.$(OBJEXT) packet.$(OBJEXT) \ - pkcs7.$(OBJEXT) plutomain.$(OBJEXT) rcv_whack.$(OBJEXT) \ - server.$(OBJEXT) smartcard.$(OBJEXT) spdb.$(OBJEXT) \ - state.$(OBJEXT) timer.$(OBJEXT) vendor.$(OBJEXT) \ - virtual.$(OBJEXT) whack_attribute.$(OBJEXT) xauth.$(OBJEXT) \ - x509.$(OBJEXT) builder.$(OBJEXT) + pkcs7.$(OBJEXT) pluto.$(OBJEXT) plutomain.$(OBJEXT) \ + rcv_whack.$(OBJEXT) server.$(OBJEXT) smartcard.$(OBJEXT) \ + spdb.$(OBJEXT) state.$(OBJEXT) timer.$(OBJEXT) \ + vendor.$(OBJEXT) virtual.$(OBJEXT) whack_attribute.$(OBJEXT) \ + xauth_manager.$(OBJEXT) x509.$(OBJEXT) builder.$(OBJEXT) pluto_OBJECTS = $(am_pluto_OBJECTS) pluto_DEPENDENCIES = $(LIBSTRONGSWANDIR)/libstrongswan.la \ $(LIBFREESWANDIR)/libfreeswan.a $(LIBHYDRADIR)/libhydra.la \ @@ -116,6 +120,13 @@ LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ $(LDFLAGS) -o $@ SOURCES = $(_pluto_adns_SOURCES) $(pluto_SOURCES) DIST_SOURCES = $(_pluto_adns_SOURCES) $(pluto_SOURCES) +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-dvi-recursive install-exec-recursive \ + install-html-recursive install-info-recursive \ + install-pdf-recursive install-ps-recursive install-recursive \ + installcheck-recursive installdirs-recursive pdf-recursive \ + ps-recursive uninstall-recursive am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ @@ -141,9 +152,40 @@ man5dir = $(mandir)/man5 man8dir = $(mandir)/man8 NROFF = nroff MANS = $(dist_man_MANS) +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ + $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ + distdir ETAGS = etags CTAGS = ctags +DIST_SUBDIRS = . plugins/xauth DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ @@ -332,6 +374,7 @@ nat_traversal.c nat_traversal.h \ ocsp.c ocsp.h \ packet.c packet.h \ pkcs7.c pkcs7.h \ +pluto.c pluto.h \ plutomain.c \ rcv_whack.c rcv_whack.h \ server.c server.h \ @@ -342,7 +385,8 @@ timer.c timer.h \ vendor.c vendor.h \ virtual.c virtual.h \ whack_attribute.c whack_attribute.h \ -xauth.c xauth.h \ +xauth/xauth_manager.c xauth/xauth_manager.h \ +xauth/xauth_provider.h xauth/xauth_verifier.h \ x509.c x509.h \ builder.c builder.h \ rsaref/pkcs11t.h rsaref/pkcs11.h rsaref/unix.h rsaref/pkcs11f.h @@ -358,10 +402,10 @@ INCLUDES = \ -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/whack -AM_CFLAGS = -DIPSEC_DIR=\"${ipsecdir}\" \ +AM_CFLAGS = -rdynamic -DIPSEC_DIR=\"${ipsecdir}\" \ -DIPSEC_CONFDIR=\"${sysconfdir}\" -DIPSEC_PIDDIR=\"${piddir}\" \ -DSHARED_SECRETS_FILE=\"${sysconfdir}/ipsec.secrets\" \ - -DPLUGINS=\""${pluto_plugins}\"" \ + -DPLUGINS=\""${pluto_plugins} ${libhydra_plugins}\"" \ -DPKCS11_DEFAULT_LIB=\"${default_pkcs11}\" -DKERNEL26_SUPPORT \ -DKERNEL26_HAS_KAME_DUPLICATES -DPLUTO -DKLIPS -DDEBUG \ $(am__append_1) $(am__append_2) $(am__append_3) \ @@ -373,8 +417,14 @@ _pluto_adns_LDADD = \ $(LIBFREESWANDIR)/libfreeswan.a \ -lresolv $(DLLIB) +CLEANFILES = ipsec.secrets.5 dist_man_MANS = pluto.8 ipsec.secrets.5 -all: all-am +EXTRA_DIST = ipsec.secrets.5.in + +# build optional plugins +######################## +SUBDIRS = . $(am__append_8) +all: all-recursive .SUFFIXES: .SUFFIXES: .c .lo .o .obj @@ -497,6 +547,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ocsp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/packet.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pkcs7.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pluto.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plutomain.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rcv_whack.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/server.Po@am__quote@ @@ -508,7 +559,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/virtual.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/whack_attribute.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/x509.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xauth.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xauth_manager.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @@ -531,6 +582,20 @@ distclean-compile: @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< +xauth_manager.o: xauth/xauth_manager.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xauth_manager.o -MD -MP -MF $(DEPDIR)/xauth_manager.Tpo -c -o xauth_manager.o `test -f 'xauth/xauth_manager.c' || echo '$(srcdir)/'`xauth/xauth_manager.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/xauth_manager.Tpo $(DEPDIR)/xauth_manager.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='xauth/xauth_manager.c' object='xauth_manager.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xauth_manager.o `test -f 'xauth/xauth_manager.c' || echo '$(srcdir)/'`xauth/xauth_manager.c + +xauth_manager.obj: xauth/xauth_manager.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xauth_manager.obj -MD -MP -MF $(DEPDIR)/xauth_manager.Tpo -c -o xauth_manager.obj `if test -f 'xauth/xauth_manager.c'; then $(CYGPATH_W) 'xauth/xauth_manager.c'; else $(CYGPATH_W) '$(srcdir)/xauth/xauth_manager.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/xauth_manager.Tpo $(DEPDIR)/xauth_manager.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='xauth/xauth_manager.c' object='xauth_manager.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xauth_manager.obj `if test -f 'xauth/xauth_manager.c'; then $(CYGPATH_W) 'xauth/xauth_manager.c'; else $(CYGPATH_W) '$(srcdir)/xauth/xauth_manager.c'; fi` + mostlyclean-libtool: -rm -f *.lo @@ -613,6 +678,76 @@ uninstall-man8: echo " ( cd '$(DESTDIR)$(man8dir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(man8dir)" && rm -f $$files; } +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +$(RECURSIVE_CLEAN_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done + ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ @@ -623,10 +758,23 @@ ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) mkid -fID $$unique tags: TAGS -TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ @@ -645,7 +793,7 @@ TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ fi; \ fi ctags: CTAGS -CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ @@ -708,22 +856,51 @@ distdir: $(DISTFILES) || exit 1; \ fi; \ done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done check-am: all-am -check: check-am +check: check-recursive all-am: Makefile $(PROGRAMS) $(MANS) -installdirs: +installdirs: installdirs-recursive +installdirs-am: for dir in "$(DESTDIR)$(ipsecdir)" "$(DESTDIR)$(man5dir)" "$(DESTDIR)$(man8dir)"; 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: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am -installcheck: installcheck-am +installcheck: installcheck-recursive install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ @@ -732,6 +909,7 @@ install-strip: mostlyclean-generic: clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) @@ -740,72 +918,72 @@ distclean-generic: 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: clean-recursive clean-am: clean-generic clean-ipsecPROGRAMS clean-libtool \ mostlyclean-am -distclean: distclean-am +distclean: distclean-recursive -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags -dvi: dvi-am +dvi: dvi-recursive dvi-am: -html: html-am +html: html-recursive html-am: -info: info-am +info: info-recursive info-am: install-data-am: install-ipsecPROGRAMS install-man -install-dvi: install-dvi-am +install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: -install-html: install-html-am +install-html: install-html-recursive install-html-am: -install-info: install-info-am +install-info: install-info-recursive install-info-am: install-man: install-man5 install-man8 -install-pdf: install-pdf-am +install-pdf: install-pdf-recursive install-pdf-am: -install-ps: install-ps-am +install-ps: install-ps-recursive install-ps-am: installcheck-am: -maintainer-clean: maintainer-clean-am +maintainer-clean: maintainer-clean-recursive -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic -mostlyclean: mostlyclean-am +mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool -pdf: pdf-am +pdf: pdf-recursive pdf-am: -ps: ps-am +ps: ps-recursive ps-am: @@ -813,27 +991,35 @@ uninstall-am: uninstall-ipsecPROGRAMS uninstall-man uninstall-man: uninstall-man5 uninstall-man8 -.MAKE: install-am install-strip - -.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ - clean-ipsecPROGRAMS clean-libtool ctags distclean \ - distclean-compile distclean-generic distclean-libtool \ - distclean-tags distdir dvi dvi-am html html-am info info-am \ - install install-am install-data install-data-am install-dvi \ - install-dvi-am install-exec install-exec-am install-html \ - install-html-am install-info install-info-am \ - install-ipsecPROGRAMS install-man install-man5 install-man8 \ - install-pdf install-pdf-am install-ps install-ps-am \ - install-strip installcheck installcheck-am installdirs \ - maintainer-clean maintainer-clean-generic mostlyclean \ - mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ - pdf pdf-am ps ps-am tags uninstall uninstall-am \ +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \ + install-am install-strip tags-recursive + +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ + all all-am check check-am clean clean-generic \ + clean-ipsecPROGRAMS clean-libtool ctags ctags-recursive \ + distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-ipsecPROGRAMS install-man install-man5 \ + install-man8 install-pdf install-pdf-am install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-recursive uninstall uninstall-am \ uninstall-ipsecPROGRAMS uninstall-man uninstall-man5 \ uninstall-man8 plutomain.o : $(top_builddir)/config.status +ipsec.secrets.5 : ipsec.secrets.5.in + sed \ + -e "s:@IPSEC_VERSION@:$(PACKAGE_VERSION):" \ + $(srcdir)/$@.in > $@ + # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: diff --git a/src/pluto/ac.c b/src/pluto/ac.c index 3ee05d213..3339d91fb 100644 --- a/src/pluto/ac.c +++ b/src/pluto/ac.c @@ -141,7 +141,7 @@ static void ac_add_cert(certificate_t *cert) if (hIssuer->equals(hIssuer, ac_old->get_holderIssuer(ac_old)) && chunk_equals(hSerial, ac_old->get_holderSerial(ac_old))) { - if (cert->is_newer(cert, cert_old)) + if (certificate_is_newer(cert, cert_old)) { acerts->remove_at(acerts, enumerator); cert_old->destroy(cert_old); diff --git a/src/pluto/certs.c b/src/pluto/certs.c index 8bce4c5c2..24e8ffb27 100644 --- a/src/pluto/certs.c +++ b/src/pluto/certs.c @@ -318,11 +318,11 @@ void list_pgp_end_certs(bool utc) key_type_names, key->get_type(key), key->get_keysize(key) * BITS_PER_BYTE, has_private_key(cert)? ", has private key" : ""); - if (key->get_fingerprint(key, KEY_ID_PUBKEY_INFO_SHA1, &keyid)) + if (key->get_fingerprint(key, KEYID_PUBKEY_INFO_SHA1, &keyid)) { whack_log(RC_COMMENT, " keyid: %#B", &keyid); } - if (key->get_fingerprint(key, KEY_ID_PUBKEY_SHA1, &keyid)) + if (key->get_fingerprint(key, KEYID_PUBKEY_SHA1, &keyid)) { whack_log(RC_COMMENT, " subjkey: %#B", &keyid); } diff --git a/src/pluto/connections.c b/src/pluto/connections.c index dd193042a..e1f47f2d6 100644 --- a/src/pluto/connections.c +++ b/src/pluto/connections.c @@ -63,6 +63,7 @@ #include "nat_traversal.h" #include "virtual.h" #include "whack_attribute.h" +#include "modecfg.h" static void flush_pending_by_connection(connection_t *c); /* forward */ @@ -294,8 +295,10 @@ void release_connection(connection_t *c, bool relations) void delete_connection(connection_t *c, bool relations) { - connection_t *old_cur_connection - = cur_connection == c? NULL : cur_connection; + modecfg_attribute_t *ca; + connection_t *old_cur_connection; + + old_cur_connection = cur_connection == c? NULL : cur_connection; #ifdef DEBUG lset_t old_cur_debugging = cur_debugging; #endif @@ -366,14 +369,29 @@ void delete_connection(connection_t *c, bool relations) /* release virtual IP address lease if any */ if (c->spd.that.modecfg && c->spd.that.pool && - !isanyaddr(&c->spd.that.host_srcip)) + !c->spd.that.host_srcip->is_anyaddr(c->spd.that.host_srcip)) { - host_t *vip; - - vip = host_create_from_sockaddr((sockaddr_t*)&c->spd.that.host_srcip); hydra->attributes->release_address(hydra->attributes, c->spd.that.pool, - vip, c->spd.that.id); - vip->destroy(vip); + c->spd.that.host_srcip, c->spd.that.id); + } + + /* release requested attributes if any */ + if (c->requested) + { + c->requested->destroy_function(c->requested, + (void*)modecfg_attribute_destroy); + } + + /* release other attributes if any */ + if (c->attributes) + { + while (c->attributes->remove_last(c->attributes, (void **)&ca) == SUCCESS) + { + hydra->attributes->release(hydra->attributes, ca->handler, + c->spd.that.id, ca->type, ca->value); + modecfg_attribute_destroy(ca); + } + c->attributes->destroy(c->attributes); } if (c->kind != CK_GOING_AWAY) @@ -386,14 +404,17 @@ void delete_connection(connection_t *c, bool relations) cur_debugging = old_cur_debugging; #endif free(c->name); + DESTROY_IF(c->xauth_identity); DESTROY_IF(c->spd.this.id); DESTROY_IF(c->spd.this.ca); DESTROY_IF(c->spd.this.groups); + DESTROY_IF(c->spd.this.host_srcip); free(c->spd.this.updown); free(c->spd.this.pool); DESTROY_IF(c->spd.that.id); DESTROY_IF(c->spd.that.ca); DESTROY_IF(c->spd.that.groups); + DESTROY_IF(c->spd.that.host_srcip); free(c->spd.that.updown); free(c->spd.that.pool); if (c->requested_ca) @@ -656,7 +677,7 @@ size_t format_end(char *buf, size_t buf_len, const struct end *this, subnettot(&this->client, 0, client, sizeof(client)); } } - else if (this->modecfg && isanyaddr(&this->host_srcip)) + else if (this->modecfg && this->host_srcip->is_anyaddr(this->host_srcip)) { /* we are mode config client, or a server with a pool */ client_sep = "==="; @@ -738,9 +759,14 @@ static size_t format_connection(char *buf, size_t buf_len, static void unshare_connection_strings(connection_t *c) { c->name = clone_str(c->name); + if (c->xauth_identity) + { + c->xauth_identity = c->xauth_identity->clone(c->xauth_identity); + } c->spd.this.id = c->spd.this.id->clone(c->spd.this.id); c->spd.this.pool = clone_str(c->spd.this.pool); c->spd.this.updown = clone_str(c->spd.this.updown); + c->spd.this.host_srcip = c->spd.this.host_srcip->clone(c->spd.this.host_srcip); scx_share(c->spd.this.sc); cert_share(c->spd.this.cert); if (c->spd.this.ca) @@ -754,6 +780,7 @@ static void unshare_connection_strings(connection_t *c) c->spd.that.id = c->spd.that.id->clone(c->spd.that.id); c->spd.that.pool = clone_str(c->spd.that.pool); c->spd.that.updown = clone_str(c->spd.that.updown); + c->spd.that.host_srcip = c->spd.that.host_srcip->clone(c->spd.that.host_srcip); scx_share(c->spd.that.sc); cert_share(c->spd.that.cert); if (c->spd.that.ca) @@ -902,7 +929,7 @@ static bool extract_end(struct end *dst, const whack_end_t *src, /* the rest is simple copying of corresponding fields */ dst->host_addr = src->host_addr; dst->host_nexthop = src->host_nexthop; - dst->host_srcip = src->host_srcip; + dst->host_srcip = host_create_from_sockaddr((sockaddr_t*)&src->host_srcip); dst->has_natip = src->has_natip; dst->client = src->client; dst->protocol = src->protocol; @@ -927,10 +954,14 @@ static bool extract_end(struct end *dst, const whack_end_t *src, /* if host sourceip is defined but no client is present * behind the host then set client to sourceip/32 */ - if (addrbytesptr(&dst->host_srcip, NULL) && - !isanyaddr(&dst->host_srcip) && !dst->has_natip && !dst->has_client) + if (!dst->host_srcip->is_anyaddr(dst->host_srcip) && + !dst->has_natip && !dst->has_client) { - err_t ugh = addrtosubnet(&dst->host_srcip, &dst->client); + ip_address addr; + err_t ugh; + + addr = *(ip_address*)dst->host_srcip->get_sockaddr(dst->host_srcip); + ugh = addrtosubnet(&addr, &dst->client); if (ugh) { @@ -1110,6 +1141,12 @@ void add_connection(const whack_message_t *wm) } } + if (wm->xauth_identity) + { + c->xauth_identity + = identification_create_from_string(wm->xauth_identity); + } + c->sa_ike_life_seconds = wm->sa_ike_life_seconds; c->sa_ipsec_life_seconds = wm->sa_ipsec_life_seconds; c->sa_rekey_margin = wm->sa_rekey_margin; @@ -1211,7 +1248,8 @@ void add_connection(const whack_message_t *wm) c->spd.that.modecfg = TRUE; c->spd.that.has_client = FALSE; /* reset the host_srcip so that it gets assigned in modecfg */ - anyaddr(AF_INET, &c->spd.that.host_srcip); + DESTROY_IF(c->spd.that.host_srcip); + c->spd.that.host_srcip = host_create_any(AF_INET); } if (c->ikev1) @@ -3046,7 +3084,8 @@ void ISAKMP_SA_established(connection_t *c, so_serial_t serial) /* the connection is now oriented so that we are able to determine * whether we are a mode config server with a virtual IP to send. */ - if (!isanyaddr(&c->spd.that.host_srcip) && !c->spd.that.has_natip) + if (!c->spd.that.host_srcip->is_anyaddr(c->spd.that.host_srcip) && + !c->spd.that.has_natip) { c->spd.that.modecfg = TRUE; } @@ -3693,8 +3732,10 @@ static connection_t *fc_try(const connection_t *c, struct host_pair *hp, } else { + host_t *vip = c->spd.that.host_srcip; + if (!peer_net_is_host && !(sr->that.modecfg && c->spd.that.modecfg && - subnetisaddr(peer_net, &c->spd.that.host_srcip))) + subnetisaddr(peer_net, (ip_address*)vip->get_sockaddr(vip)))) { continue; } diff --git a/src/pluto/connections.h b/src/pluto/connections.h index 66aea1541..b67f0b562 100644 --- a/src/pluto/connections.h +++ b/src/pluto/connections.h @@ -1,6 +1,6 @@ /* information about connections between hosts and clients * Copyright (C) 1998-2001 D. Hugh Redelmeier - * Copyright (C) 2009 Andreas Steffen - Hochschule fuer Technik Rapperswil + * Copyright (C) 2009-2010 Andreas Steffen - Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -18,6 +18,7 @@ #include <sys/queue.h> +#include <utils/host.h> #include <utils/linked_list.h> #include <utils/identification.h> #include <credentials/ietf_attributes/ietf_attributes.h> @@ -131,10 +132,8 @@ struct virtual_t; struct end { identification_t *id; - ip_address - host_addr, - host_nexthop, - host_srcip; + ip_address host_addr, host_nexthop; + host_t *host_srcip; ip_subnet client; bool is_left; @@ -184,6 +183,8 @@ struct connection { unsigned long sa_rekey_fuzz; unsigned long sa_keying_tries; + identification_t *xauth_identity; /* XAUTH identity */ + /* RFC 3706 DPD */ time_t dpd_delay; time_t dpd_timeout; @@ -226,6 +227,8 @@ struct connection { connection_t *hp_next; /* host pair list link */ connection_t *ac_next; /* all connections list link */ linked_list_t *requested_ca; /* collected certificate requests */ + linked_list_t *requested; /* requested attributes with handlers */ + linked_list_t *attributes; /* configuration attributes with handlers */ bool got_certrequest; }; diff --git a/src/pluto/constants.h b/src/pluto/constants.h index e9567c07a..790bbefa6 100644 --- a/src/pluto/constants.h +++ b/src/pluto/constants.h @@ -543,45 +543,6 @@ extern enum_names attr_msg_type_names; extern enum_names modecfg_attr_names; -/* XAUTH attribute values */ -#define XAUTH_TYPE 16520 -#define XAUTH_USER_NAME 16521 -#define XAUTH_USER_PASSWORD 16522 -#define XAUTH_PASSCODE 16523 -#define XAUTH_MESSAGE 16524 -#define XAUTH_CHALLENGE 16525 -#define XAUTH_DOMAIN 16526 -#define XAUTH_STATUS 16527 -#define XAUTH_NEXT_PIN 16528 -#define XAUTH_ANSWER 16529 - -#define XAUTH_BASE XAUTH_TYPE - -extern enum_names xauth_attr_names; - -/* ISAKMP mode config attributes specific to Microsoft */ -#define INTERNAL_IP4_SERVER 23456 -#define INTERNAL_IP6_SERVER 23457 - -extern enum_names microsoft_attr_names; - -/* ISAKMP mode config attributes specific to the Unity vendor ID */ -#define UNITY_BANNER 28672 -#define UNITY_SAVE_PASSWD 28673 -#define UNITY_DEF_DOMAIN 28674 -#define UNITY_SPLITDNS_NAME 28675 -#define UNITY_SPLIT_INCLUDE 28676 -#define UNITY_NATT_PORT 28677 -#define UNITY_LOCAL_LAN 28678 -#define UNITY_PFS 28679 -#define UNITY_FW_TYPE 28680 -#define UNITY_BACKUP_SERVERS 28681 -#define UNITY_DDNS_HOSTNAME 28682 - -#define UNITY_BASE UNITY_BANNER - -extern enum_names unity_attr_names; - /* XAUTH authentication types */ #define XAUTH_TYPE_GENERIC 0 #define XAUTH_TYPE_CHAP 1 diff --git a/src/pluto/crl.c b/src/pluto/crl.c index 84fe77554..c8fb107d5 100644 --- a/src/pluto/crl.c +++ b/src/pluto/crl.c @@ -159,7 +159,7 @@ bool insert_crl(x509crl_t *x509crl, char *crl_uri, bool cache_crl) { certificate_t *old_cert_crl = oldcrl->crl; - if (cert_crl->is_newer(cert_crl, old_cert_crl)) + if (crl_is_newer((crl_t*)cert_crl, (crl_t*)old_cert_crl)) { /* keep any known CRL distribution points */ add_distribution_points(x509crl->distributionPoints, @@ -202,9 +202,11 @@ bool insert_crl(x509crl_t *x509crl, char *crl_uri, bool cache_crl) snprintf(buf, sizeof(buf), "%s/%s.crl", CRL_PATH, hex); free(hex.ptr); - encoding = cert_crl->get_encoding(cert_crl); - chunk_write(encoding, buf, "crl", 022, TRUE); - free(encoding.ptr); + if (cert_crl->get_encoding(cert_crl, CERT_ASN1_DER, &encoding)) + { + chunk_write(encoding, buf, "crl", 022, TRUE); + free(encoding.ptr); + } } /* is the fetched crl valid? */ @@ -313,7 +315,7 @@ void check_crls(void) certificate_t *cert_crl = x509crl->crl; crl_t *crl = (crl_t*)cert_crl; identification_t *issuer = cert_crl->get_issuer(cert_crl); - chunk_t authKeyID = crl->get_authKeyIdentifier(crl); + chunk_t authKeyID = crl->get_authKeyIdentifier(crl); cert_crl->get_validity(cert_crl, &now, NULL, &nextUpdate); time_left = nextUpdate - now; @@ -353,7 +355,7 @@ cert_status_t verify_by_crl(cert_t *cert, time_t *until, time_t *revocationDate, char *point; ca = get_ca_info(issuer, authKeyID); - + *revocationDate = UNDEFINED_TIME; *revocationReason = CRL_REASON_UNSPECIFIED; diff --git a/src/pluto/demux.c b/src/pluto/demux.c index fad1450cd..617353c6c 100644 --- a/src/pluto/demux.c +++ b/src/pluto/demux.c @@ -1215,7 +1215,7 @@ read_packet(struct msg_digest *md) /* ignore IKEv2 packets - they will be handled by charon */ if (pbs_room(&md->packet_pbs) > IKEV2_VERSION_OFFSET - && md->packet_pbs.start[IKEV2_VERSION_OFFSET] == IKEV2_VERSION) + && (md->packet_pbs.start[IKEV2_VERSION_OFFSET] & 0xF0) == IKEV2_VERSION) { DBG(DBG_CONTROLMORE, DBG_log(" ignoring IKEv2 packet") diff --git a/src/pluto/demux.h b/src/pluto/demux.h index 2161bbd02..6ce53c14f 100644 --- a/src/pluto/demux.h +++ b/src/pluto/demux.h @@ -12,9 +12,12 @@ * for more details. */ +#ifndef _DEMUX_H +#define _DEMUX_H + #include "packet.h" +#include "state.h" -struct state; /* forward declaration of tag */ extern void init_demux(void); extern bool send_packet(struct state *st, const char *where); extern void comm_handle(const struct iface *ifp); @@ -90,3 +93,5 @@ typedef stf_status state_transition_fn(struct msg_digest *md); extern void complete_state_transition(struct msg_digest **mdp, stf_status result); extern void free_md_pool(void); + +#endif /* _DEMUX_H */ diff --git a/src/pluto/dnskey.c b/src/pluto/dnskey.c index ec56b8530..4f8e4ebf4 100644 --- a/src/pluto/dnskey.c +++ b/src/pluto/dnskey.c @@ -424,7 +424,7 @@ static err_t process_txt_rr_body(u_char *str, bool doit, public_key_t *key = gi.key->public_key; if (gi.gw_key_present && - key->get_fingerprint(key, KEY_ID_PUBKEY_SHA1, &keyid)) + key->get_fingerprint(key, KEYID_PUBKEY_SHA1, &keyid)) { DBG_log("gateway for %s is %s with key %#B", client_id, gi.gw_id, &keyid); diff --git a/src/pluto/ipsec.secrets.5 b/src/pluto/ipsec.secrets.5 index 3cce4d3f8..6c39f86e1 100644 --- a/src/pluto/ipsec.secrets.5 +++ b/src/pluto/ipsec.secrets.5 @@ -1,148 +1,116 @@ -.TH IPSEC.SECRETS 5 "28 March 1999" +.TH IPSEC.SECRETS 5 "2010-05-30" "4.4.1rc3" "strongSwan" .SH NAME ipsec.secrets \- secrets for IKE/IPsec authentication .SH DESCRIPTION The file \fIipsec.secrets\fP holds a table of secrets. -These secrets are used by \fIipsec_pluto\fP(8), the FreeS/WAN Internet Key -Exchange daemon, to authenticate other hosts. -Currently there are two kinds of secrets: preshared secrets and -.\" the private part of DSS keys. -RSA private keys. +These secrets are used by the strongSwan Internet Key Exchange (IKE) daemons +pluto (IKEv1) and charon (IKEv2) to authenticate other hosts. .LP It is vital that these secrets be protected. The file should be owned by the super-user, and its permissions should be set to block all access by others. .LP The file is a sequence of entries and include directives. -Here is an example. Each entry or directive must start at the -left margin, but if it continues beyond a single line, each continuation -line must be indented. +Here is an example. .LP .RS .nf -# sample /etc/ipsec.secrets file for 10.1.0.1 -10.1.0.1 10.2.0.1: PSK "secret shared by two hosts" +# /etc/ipsec.secrets - strongSwan IPsec secrets file +192.168.0.1 %any : PSK "v+NkxY9LLZvwj4qCC2o/gGrWDF2d21jL" -# an entry may be split across lines, -# but indentation matters -www.xs4all.nl @www.kremvax.ru -\ \ \ \ 10.6.0.1 10.7.0.1 1.8.0.1: PSK "secret shared by 5" +: RSA moonKey.pem -.\" # Private part of our DSS key, in base 64, -.\" # as generated by BIND 8.2.1's dnskeygen. -.\" # Since this is the default key for this host, -.\" # there is no need to specify indices. -.\" : DSS 0siMs0N/hfRoCBMXA6plPtuv58/+c= -# an RSA private key. -# note that the lines are too wide for a -# man page, so ... has been substituted for -# the truncated part -@my.com: rsa { -\ \ \ \ Modulus:\ 0syXpo/6waam+ZhSs8Lt6jnBzu3C4grtt... -\ \ \ \ PublicExponent:\ 0sAw== -\ \ \ \ PrivateExponent:\ 0shlGbVR1m8Z+7rhzSyenCaBN... -\ \ \ \ Prime1:\ 0s8njV7WTxzVzRz7AP+0OraDxmEAt1BL5l... -\ \ \ \ Prime2:\ 0s1LgR7/oUMo9BvfU8yRFNos1s211KX5K0... -\ \ \ \ Exponent1:\ 0soaXj85ihM5M2inVf/NfHmtLutVz4r... -\ \ \ \ Exponent2:\ 0sjdAL9VFizF+BKU4ohguJFzOd55OG6... -\ \ \ \ Coefficient:\ 0sK1LWwgnNrNFGZsS/2GuMBg9nYVZ... -\ \ \ \ } +alice@strongswan.org : EAP "x3.dEhgN" -include ipsec.*.secrets # get secrets from other files +: XAUTH carol "4iChxLT3" + +: XAUTH dave "ryftzG4A" + +# get secrets from other files +include ipsec.*.secrets .fi .RE .LP -Each entry in the file is a list of indices, followed by a secret. -The two parts are separated by a colon (\fB:\fP) that is -followed by whitespace or a newline. For compatability -with the previous form of this file, if the key part is just a -double-quoted string the colon may be left out. +Each entry in the file is a list of optional ID selectors, followed by a secret. +The two parts are separated by a colon (\fB:\fP) that is surrounded +by whitespace. If no ID selectors are specified the line must start with a +colon. .LP -An index is an IP address, or a Fully Qualified Domain Name, user@FQDN, +A selector is an IP address, a Fully Qualified Domain Name, user@FQDN, \fB%any\fP or \fB%any6\fP (other kinds may come). An IP address may be written in the familiar dotted quad form or as a domain name to be looked up -when the file is loaded -(or in any of the forms supported by the FreeS/WAN \fIipsec_ttoaddr\fP(3) -routine). In many cases it is a bad idea to use domain names because +when the file is loaded. +In many cases it is a bad idea to use domain names because the name server may not be running or may be insecure. To denote a Fully Qualified Domain Name (as opposed to an IP address denoted by its domain name), precede the name with an at sign (\fB@\fP). .LP -Matching IDs with indices is fairly straightforward: they have to be +Matching IDs with selectors is fairly straightforward: they have to be equal. In the case of a ``Road Warrior'' connection, if an equal match is not found for the Peer's ID, and it is in the form of an IP -address, an index of \fB%any\fP will match the peer's IP address if IPV4 +address, a selector of \fB%any\fP will match the peer's IP address if IPV4 and \fB%any6\fP will match a the peer's IP address if IPV6. Currently, the obsolete notation \fB0.0.0.0\fP may be used in place of \fB%any\fP. .LP -An additional complexity +In IKEv1 an additional complexity arises in the case of authentication by preshared secret: the responder will need to look up the secret before the Peer's ID payload has been decoded, so the ID used will be the IP address. .LP To authenticate a connection between two hosts, the entry that most specifically matches the host and peer IDs is used. An entry with no -index will match any host and peer. More specifically, an entry with one index will -match a host and peer if the index matches the host's ID (the peer isn't -considered). Still more specifically, an entry with multiple indices will match a host and -peer if the host ID and peer ID each match one of the indices. If the key -is for an asymmetric authentication technique (i.e. a public key -system such as RSA), an entry with multiple indices will match a host -and peer even if only the host ID matches an index (it is presumed that the -multiple indices are all identities of the host). +selectors will match any host and peer. More specifically, an entry with one +selector will match a host and peer if the selector matches the host's ID (the +peer isn't considered). Still more specifically, an entry with multiple +selectors will match a host and peer if the host ID and peer ID each match one +of the selectors. If the key is for an asymmetric authentication technique +(i.e. a public key system such as RSA), an entry with multiple selectors will +match a host and peer even if only the host ID matches a selector (it is +presumed that the selectors are all identities of the host). It is acceptable for two entries to be the best match as long as they agree about the secret or private key. .LP Authentication by preshared secret requires that both systems find the identical secret (the secret is not actually transmitted by the IKE -protocol). If both the host and peer appear in the index list, the +protocol). If both the host and peer appear in the selector list, the same entry will be suitable for both systems so verbatim copying between systems can be used. This naturally extends to larger groups -sharing the same secret. Thus multiple-index entries are best for PSK +sharing the same secret. Thus multiple-selector entries are best for PSK authentication. .LP -Authentication by RSA Signatures requires that each host have its own private -key. A host could reasonably use a different private keys +Authentication by public key systems such as RSA requires that each host +have its own private key. A host could reasonably use a different private keys for different interfaces and for different peers. But it would not -be normal to share entries between systems. Thus thus no-index and -one-index forms of entry often make sense for RSA Signature authentication. -.LP -The key part of an entry may start with a token indicating the kind of -key. ``RSA'' signifies RSA private key and ``PSK'' signifies -PreShared Key (case is ignored). For compatability with previous -forms of this file, PSK is the default. -.LP -A preshared secret is most conveniently represented as a sequence of -characters, delimited by the double-quote -character (\fB"\fP). The sequence cannot contain a newline or -double-quote. Strictly speaking, the secret is actually the sequence -of bytes that is used in the file to represent the sequence of -characters (excluding the delimiters). -A preshared secret may also be represented, without quotes, in any form supported by -\fIipsec_ttodata\fP(3). -.LP -An RSA private key is a composite of eight generally large numbers. The notation -used is a brace-enclosed list of field name and value pairs (see the example above). -A suitable key, in a suitable format, may be generated by \fIipsec_rsasigkey\fP(8). -The structure is very similar to that used by BIND 8.2.2 or later, but note that -the numbers must have a ``0s'' prefix if they are in base 64. The order of -the fields is fixed. -.LP -The first token an entry must start in -the first column of its line. Subsequent tokens must be -separated by whitespace, -except for a colon token, which only needs to be followed by whitespace. -A newline is taken as whitespace, but every -line of an entry after the first must be indented. -.LP -Whitespace at the end of a line is ignored (except in the 0t -notation for a key). At the start of line or +be normal to share entries between systems. Thus thus no-selector and +one-selector forms of entry often make sense for public key authentication. +.LP +The key part of an entry must start with a token indicating the kind of +key. The following types of secrets are currently supported: +.TP +.B PSK +defines a pre-shared key +.TP +.B RSA +defines an RSA private key +.TP +.B ECDSA +defines an ECDSA private key +.TP +.B EAP +defines EAP credentials +.TP +.B XAUTH +defines XAUTH credentials +.TP +.B PIN +defines a smartcard PIN +.LP +Details on each type of secret are given below. +.LP +Whitespace at the end of a line is ignored. At the start of a line or after whitespace, \fB#\fP and the following text up to the end of the -line is treated as a comment. Within entries, all lines must be -indented (except for lines with no tokens). -Outside entries, no line may be indented (this is to make sure that -the file layout reflects its structure). +line is treated as a comment. .LP An include directive causes the contents of the named file to be processed before continuing with the current file. The filename is subject to @@ -153,23 +121,55 @@ directory containing the current file is prepended to the name. The include directive is a line that starts with the word \fBinclude\fP, followed by whitespace, followed by the filename (which must not contain whitespace). +.SS TYPES OF SECRETS +.TP +.B [ <selectors> ] : PSK <secret> +A preshared secret is most conveniently represented as a sequence of +characters, delimited by double-quote characters (\fB"\fP). +The sequence cannot contain a newline or double-quote. +Strictly speaking, the secret is actually the sequence +of bytes that is used in the file to represent the sequence of +characters (excluding the delimiters). +.TP +.B [ <selectors> ] : RSA <private key file> [ <passphrase> | %prompt ] +.TQ +.B [ <selectors> ] : ECDSA <private key file> [ <passphrase> | %prompt ] +For the private key file both absolute paths or paths relative to +\fI/etc/ipsec.d/private\fP are accepted. If the private key file is +encrypted, the \fIpassphrase\fP must be defined. Instead of a passphrase +.B %prompt +can be used which then causes the daemons to ask the user for the password +whenever it is required to decrypt the key. +.TP +.B <user id> : EAP <secret> +As with \fBPSK\fP secrets the \fIsecret\fP is a sequence of characters, +delimited by double-quote characters (\fB"\fP). +.br +\fBEAP\fP secrets are IKEv2 only. +.TP +.B : XAUTH <username> <password> +\fBXAUTH\fP secrets are IKEv1 only. +.TP +.B : PIN <smartcard selector> <pin code> | %prompt +The format +.B "%smartcard[<slot nr>[:<key id>]]" +is used to specify the smartcard selector (e.g. %smartcard1:50). For IKEv1, +instead of specifying the pin code statically, +.B %prompt +can be specified, which causes the pluto daemon to ask the user for the pin +code. +.LP + .SH FILES /etc/ipsec.secrets .SH SEE ALSO -The rest of the FreeS/WAN distribution, in particular \fIipsec.conf\fP(5), -\fIipsec\fP(8), -\fIipsec_newhostkey\fP(8), -\fIipsec_rsasigkey\fP(8), -\fIipsec_showhostkey\fP(8), -\fIipsec_auto\fP(8) \fB\-\-rereadsecrets\fP, -and \fIipsec_pluto\fP(8) \fB\-\-listen\fP,. +\fIipsec\fP(8) .br -BIND 8.2.2 or later, ftp://ftp.isc.org/isc/bind/src/ .SH HISTORY -Designed for the FreeS/WAN project -<http://www.freeswan.org> -by D. Hugh Redelmeier. +Originally written for the FreeS/WAN project by D. Hugh Redelmeier. +Updated and extended for the strongSwan project <http://www.strongswan.org> by +Tobias Brunner and Andreas Steffen. .SH BUGS If an ID is \fB0.0.0.0\fP, it will match \fB%any\fP; if it is \fB0::0\fP, it will match \fB%any6\fP. diff --git a/src/pluto/ipsec.secrets.5.in b/src/pluto/ipsec.secrets.5.in new file mode 100644 index 000000000..adb915e4d --- /dev/null +++ b/src/pluto/ipsec.secrets.5.in @@ -0,0 +1,175 @@ +.TH IPSEC.SECRETS 5 "2010-05-30" "@IPSEC_VERSION@" "strongSwan" +.SH NAME +ipsec.secrets \- secrets for IKE/IPsec authentication +.SH DESCRIPTION +The file \fIipsec.secrets\fP holds a table of secrets. +These secrets are used by the strongSwan Internet Key Exchange (IKE) daemons +pluto (IKEv1) and charon (IKEv2) to authenticate other hosts. +.LP +It is vital that these secrets be protected. The file should be owned +by the super-user, +and its permissions should be set to block all access by others. +.LP +The file is a sequence of entries and include directives. +Here is an example. +.LP +.RS +.nf +# /etc/ipsec.secrets - strongSwan IPsec secrets file +192.168.0.1 %any : PSK "v+NkxY9LLZvwj4qCC2o/gGrWDF2d21jL" + +: RSA moonKey.pem + +alice@strongswan.org : EAP "x3.dEhgN" + +: XAUTH carol "4iChxLT3" + +: XAUTH dave "ryftzG4A" + +# get secrets from other files +include ipsec.*.secrets +.fi +.RE +.LP +Each entry in the file is a list of optional ID selectors, followed by a secret. +The two parts are separated by a colon (\fB:\fP) that is surrounded +by whitespace. If no ID selectors are specified the line must start with a +colon. +.LP +A selector is an IP address, a Fully Qualified Domain Name, user@FQDN, +\fB%any\fP or \fB%any6\fP (other kinds may come). An IP address may be written +in the familiar dotted quad form or as a domain name to be looked up +when the file is loaded. +In many cases it is a bad idea to use domain names because +the name server may not be running or may be insecure. To denote a +Fully Qualified Domain Name (as opposed to an IP address denoted by +its domain name), precede the name with an at sign (\fB@\fP). +.LP +Matching IDs with selectors is fairly straightforward: they have to be +equal. In the case of a ``Road Warrior'' connection, if an equal +match is not found for the Peer's ID, and it is in the form of an IP +address, a selector of \fB%any\fP will match the peer's IP address if IPV4 +and \fB%any6\fP will match a the peer's IP address if IPV6. +Currently, the obsolete notation \fB0.0.0.0\fP may be used in place of +\fB%any\fP. +.LP +In IKEv1 an additional complexity +arises in the case of authentication by preshared secret: the +responder will need to look up the secret before the Peer's ID payload has +been decoded, so the ID used will be the IP address. +.LP +To authenticate a connection between two hosts, the entry that most +specifically matches the host and peer IDs is used. An entry with no +selectors will match any host and peer. More specifically, an entry with one +selector will match a host and peer if the selector matches the host's ID (the +peer isn't considered). Still more specifically, an entry with multiple +selectors will match a host and peer if the host ID and peer ID each match one +of the selectors. If the key is for an asymmetric authentication technique +(i.e. a public key system such as RSA), an entry with multiple selectors will +match a host and peer even if only the host ID matches a selector (it is +presumed that the selectors are all identities of the host). +It is acceptable for two entries to be the best match as +long as they agree about the secret or private key. +.LP +Authentication by preshared secret requires that both systems find the +identical secret (the secret is not actually transmitted by the IKE +protocol). If both the host and peer appear in the selector list, the +same entry will be suitable for both systems so verbatim copying +between systems can be used. This naturally extends to larger groups +sharing the same secret. Thus multiple-selector entries are best for PSK +authentication. +.LP +Authentication by public key systems such as RSA requires that each host +have its own private key. A host could reasonably use a different private keys +for different interfaces and for different peers. But it would not +be normal to share entries between systems. Thus thus no-selector and +one-selector forms of entry often make sense for public key authentication. +.LP +The key part of an entry must start with a token indicating the kind of +key. The following types of secrets are currently supported: +.TP +.B PSK +defines a pre-shared key +.TP +.B RSA +defines an RSA private key +.TP +.B ECDSA +defines an ECDSA private key +.TP +.B EAP +defines EAP credentials +.TP +.B XAUTH +defines XAUTH credentials +.TP +.B PIN +defines a smartcard PIN +.LP +Details on each type of secret are given below. +.LP +Whitespace at the end of a line is ignored. At the start of a line or +after whitespace, \fB#\fP and the following text up to the end of the +line is treated as a comment. +.LP +An include directive causes the contents of the named file to be processed +before continuing with the current file. The filename is subject to +``globbing'' as in \fIsh\fP(1), so every file with a matching name +is processed. Includes may be nested to a modest +depth (10, currently). If the filename doesn't start with a \fB/\fP, the +directory containing the current file is prepended to the name. The +include directive is a line that starts with the word \fBinclude\fP, +followed by whitespace, followed by the filename (which must not contain +whitespace). +.SS TYPES OF SECRETS +.TP +.B [ <selectors> ] : PSK <secret> +A preshared secret is most conveniently represented as a sequence of +characters, delimited by double-quote characters (\fB"\fP). +The sequence cannot contain a newline or double-quote. +Strictly speaking, the secret is actually the sequence +of bytes that is used in the file to represent the sequence of +characters (excluding the delimiters). +.TP +.B [ <selectors> ] : RSA <private key file> [ <passphrase> | %prompt ] +.TQ +.B [ <selectors> ] : ECDSA <private key file> [ <passphrase> | %prompt ] +For the private key file both absolute paths or paths relative to +\fI/etc/ipsec.d/private\fP are accepted. If the private key file is +encrypted, the \fIpassphrase\fP must be defined. Instead of a passphrase +.B %prompt +can be used which then causes the daemons to ask the user for the password +whenever it is required to decrypt the key. +.TP +.B <user id> : EAP <secret> +As with \fBPSK\fP secrets the \fIsecret\fP is a sequence of characters, +delimited by double-quote characters (\fB"\fP). +.br +\fBEAP\fP secrets are IKEv2 only. +.TP +.B : XAUTH <username> <password> +\fBXAUTH\fP secrets are IKEv1 only. +.TP +.B : PIN <smartcard selector> <pin code> | %prompt +The format +.B "%smartcard[<slot nr>[:<key id>]]" +is used to specify the smartcard selector (e.g. %smartcard1:50). For IKEv1, +instead of specifying the pin code statically, +.B %prompt +can be specified, which causes the pluto daemon to ask the user for the pin +code. +.LP + +.SH FILES +/etc/ipsec.secrets +.SH SEE ALSO +\fIipsec.conf\fP(5), +\fIipsec\fP(8) +.br +.SH HISTORY +Originally written for the FreeS/WAN project by D. Hugh Redelmeier. +Updated and extended for the strongSwan project <http://www.strongswan.org> by +Tobias Brunner and Andreas Steffen. +.SH BUGS +If an ID is \fB0.0.0.0\fP, it will match \fB%any\fP; +if it is \fB0::0\fP, it will match \fB%any6\fP. diff --git a/src/pluto/ipsec_doi.c b/src/pluto/ipsec_doi.c index 34c42e294..4a6a7c872 100644 --- a/src/pluto/ipsec_doi.c +++ b/src/pluto/ipsec_doi.c @@ -260,7 +260,7 @@ static linked_list_t* collect_rw_ca_candidates(struct msg_digest *md) { new_entry = FALSE; break; - } + } } enumerator->destroy(enumerator); @@ -702,7 +702,7 @@ void accept_delete(struct state *st, struct msg_digest *md, struct payload_digest *p) { struct isakmp_delete *d = &(p->payload.delete); - identification_t *this_id, *that_id; + identification_t *this_id = NULL, *that_id = NULL; ip_address peer_addr; size_t sizespi; int i; @@ -1568,7 +1568,7 @@ static bool take_a_crack(struct tac_state *s, pubkey_t *kr) s->tried_cnt++; scheme = oakley_to_signature_scheme(s->st->st_oakley.auth); - pub_key->get_fingerprint(pub_key, KEY_ID_PUBKEY_INFO_SHA1, &keyid); + pub_key->get_fingerprint(pub_key, KEYID_PUBKEY_INFO_SHA1, &keyid); if (pub_key->verify(pub_key, scheme, s->hash, s->sig)) { @@ -1944,27 +1944,34 @@ stf_status quick_outI1(int whack_sock, struct state *isakmp_sa, bool has_client = c->spd.this.has_client || c->spd.that.has_client || c->spd.this.protocol || c->spd.that.protocol || c->spd.this.port || c->spd.that.port; - bool send_natoa = FALSE; u_int8_t np = ISAKMP_NEXT_NONE; + connection_t *ph1_c = isakmp_sa->st_connection; if (c->spd.this.modecfg && !c->spd.this.has_client && - isanyaddr(&c->spd.this.host_srcip)) + c->spd.this.host_srcip->is_anyaddr(c->spd.this.host_srcip)) { - connection_t *ph1_c = isakmp_sa->st_connection; + host_t * ph1_srcip = ph1_c->spd.this.host_srcip; - if (ph1_c->spd.this.modecfg && !isanyaddr(&ph1_c->spd.this.host_srcip)) + if (ph1_c->spd.this.modecfg && !ph1_srcip->is_anyaddr(ph1_srcip)) { - char srcip[ADDRTOT_BUF]; - - c->spd.this.host_srcip = ph1_c->spd.this.host_srcip; + c->spd.this.host_srcip->destroy(c->spd.this.host_srcip); + c->spd.this.host_srcip = ph1_srcip->clone(ph1_srcip); c->spd.this.client = ph1_c->spd.this.client; c->spd.this.has_client = TRUE; - addrtot(&c->spd.this.host_srcip, 0, srcip, sizeof(srcip)); - plog("inheriting virtual IP source address %s from ModeCfg", srcip); + plog("inheriting virtual IP source address %H from ModeCfg", ph1_srcip); } } + if (ph1_c->policy & (POLICY_XAUTH_RSASIG | POLICY_XAUTH_PSK) && + ph1_c->xauth_identity && !c->xauth_identity) + { + DBG(DBG_CONTROL, + DBG_log("inheriting XAUTH identity %Y", ph1_c->xauth_identity) + ) + c->xauth_identity = ph1_c->xauth_identity->clone(ph1_c->xauth_identity); + } + st->st_whack_sock = whack_sock; st->st_connection = c; set_cur_state(st); /* we must reset before exit */ @@ -3535,7 +3542,7 @@ stf_status main_inR2_outI3(struct msg_digest *md) struct state *const st = md->st; pb_stream *const keyex_pbs = &md->chain[ISAKMP_NEXT_KE]->pbs; pb_stream id_pbs; /* ID Payload; also used for hash calculation */ - + connection_t *c = st->st_connection; certpolicy_t cert_policy = c->spd.this.sendcert; cert_t *mycert = c->spd.this.cert; @@ -3638,7 +3645,7 @@ stf_status main_inR2_outI3(struct msg_digest *md) } if (send_cert) { - bool success; + bool success = FALSE; chunk_t cert_encoding; pb_stream cert_pbs; @@ -3650,9 +3657,12 @@ stf_status main_inR2_outI3(struct msg_digest *md) { return STF_INTERNAL_ERROR; } - cert_encoding = mycert->cert->get_encoding(mycert->cert); - success = out_chunk(cert_encoding, &cert_pbs, "CERT"); - free(cert_encoding.ptr); + if (mycert->cert->get_encoding(mycert->cert, CERT_ASN1_DER, + &cert_encoding)) + { + success = out_chunk(cert_encoding, &cert_pbs, "CERT"); + free(cert_encoding.ptr); + } if (!success) { return STF_INTERNAL_ERROR; @@ -4079,7 +4089,7 @@ main_inI3_outR3_tail(struct msg_digest *md } if (send_cert) { - bool success; + bool success = FALSE; chunk_t cert_encoding; pb_stream cert_pbs; struct isakmp_cert cert_hd; @@ -4091,9 +4101,12 @@ main_inI3_outR3_tail(struct msg_digest *md { return STF_INTERNAL_ERROR; } - cert_encoding = mycert->cert->get_encoding(mycert->cert); - success = out_chunk(cert_encoding, &cert_pbs, "CERT"); - free(cert_encoding.ptr); + if (mycert->cert->get_encoding(mycert->cert, CERT_ASN1_DER, + &cert_encoding)) + { + success = out_chunk(cert_encoding, &cert_pbs, "CERT"); + free(cert_encoding.ptr); + } if (!success) { return STF_INTERNAL_ERROR; @@ -4888,23 +4901,32 @@ static stf_status quick_inI1_outR1_tail(struct verify_oppo_bundle *b, /* Plain Road Warrior: * instantiate, carrying over authenticated peer ID */ + host_t *vip = c->spd.that.host_srcip; + p = rw_instantiate(p, &c->spd.that.host_addr, md->sender_port , his_net, c->spd.that.id); - /* inherit any virtual IP assigned by a Mode Config exchange */ + /* inherit any virtual IP assigned by a Mode Config exchange */ if (p->spd.that.modecfg && c->spd.that.modecfg && - subnetisaddr(his_net, &c->spd.that.host_srcip)) + subnetisaddr(his_net, (ip_address*)vip->get_sockaddr(vip))) { - char srcip[ADDRTOT_BUF]; - DBG(DBG_CONTROL, - addrtot(&c->spd.that.host_srcip, 0, srcip, sizeof(srcip)); - DBG_log("inheriting virtual IP source address %s from ModeCfg", srcip) + DBG_log("inheriting virtual IP source address %H from ModeCfg", vip) ) - p->spd.that.host_srcip = c->spd.that.host_srcip; + p->spd.that.host_srcip->destroy(p->spd.that.host_srcip); + p->spd.that.host_srcip = vip->clone(vip); p->spd.that.client = c->spd.that.client; p->spd.that.has_client = TRUE; } + + if (c->policy & (POLICY_XAUTH_RSASIG | POLICY_XAUTH_PSK) && + c->xauth_identity && !p->xauth_identity) + { + DBG(DBG_CONTROL, + DBG_log("inheriting XAUTH identity %Y", c->xauth_identity) + ) + p->xauth_identity = c->xauth_identity->clone(c->xauth_identity); + } } } #ifdef DEBUG diff --git a/src/pluto/kernel.c b/src/pluto/kernel.c index ee22fb55e..dd7ed8893 100644 --- a/src/pluto/kernel.c +++ b/src/pluto/kernel.c @@ -464,9 +464,11 @@ static bool do_command(connection_t *c, struct spd_route *sr, peerclientnet_str[ADDRTOT_BUF], peerclientmask_str[ADDRTOT_BUF], peerca_str[BUF_LEN], + xauth_id_str[BUF_LEN] = "", secure_myid_str[BUF_LEN] = "", secure_peerid_str[BUF_LEN] = "", - secure_peerca_str[BUF_LEN] = ""; + secure_peerca_str[BUF_LEN] = "", + secure_xauth_id_str[BUF_LEN] = ""; ip_address ta; pubkey_list_t *p; @@ -483,16 +485,14 @@ static bool do_command(connection_t *c, struct spd_route *sr, strncat(nexthop_str, "' ", sizeof(nexthop_str)); } - if (addrbytesptr(&sr->this.host_srcip, NULL) - && !isanyaddr(&sr->this.host_srcip)) + if (!sr->this.host_srcip->is_anyaddr(sr->this.host_srcip)) { char *n; strcpy(srcip_str, "PLUTO_MY_SOURCEIP='"); n = srcip_str + strlen(srcip_str); - - addrtot(&sr->this.host_srcip, 0 - ,n , sizeof(srcip_str)-strlen(srcip_str)); + snprintf(n, sizeof(srcip_str)-strlen(srcip_str), "%H", + sr->this.host_srcip); strncat(srcip_str, "' ", sizeof(srcip_str)); } @@ -505,6 +505,16 @@ static bool do_command(connection_t *c, struct spd_route *sr, maskof(&sr->this.client, &ta); addrtot(&ta, 0, myclientmask_str, sizeof(myclientmask_str)); + if (c->xauth_identity && + c->xauth_identity->get_type(c->xauth_identity) != ID_ANY) + { + snprintf(xauth_id_str, sizeof(xauth_id_str), "%Y", c->xauth_identity); + escape_metachar(xauth_id_str, secure_xauth_id_str, + sizeof(secure_xauth_id_str)); + snprintf(xauth_id_str, sizeof(xauth_id_str), "PLUTO_XAUTH_ID='%s' ", + secure_xauth_id_str); + } + addrtot(&sr->that.host_addr, 0, peer_str, sizeof(peer_str)); snprintf(peerid_str, sizeof(peerid_str), "%Y", sr->that.id); escape_metachar(peerid_str, secure_peerid_str, sizeof(secure_peerid_str)); @@ -562,6 +572,7 @@ static bool do_command(connection_t *c, struct spd_route *sr, "PLUTO_PEER_PROTOCOL='%u' " "PLUTO_PEER_CA='%s' " "%s" /* optional PLUTO_MY_SRCIP */ + "%s" /* optional PLUTO_XAUTH_ID */ "%s" /* actual script */ , verb, verb_suffix , c->name @@ -585,6 +596,7 @@ static bool do_command(connection_t *c, struct spd_route *sr, , sr->that.protocol , secure_peerca_str , srcip_str + , xauth_id_str , sr->this.updown == NULL? DEFAULT_UPDOWN : sr->this.updown)) { loglog(RC_LOG_SERIOUS, "%s%s command too long!", verb, verb_suffix); diff --git a/src/pluto/keys.c b/src/pluto/keys.c index 8cf28ace1..6db757ba7 100644 --- a/src/pluto/keys.c +++ b/src/pluto/keys.c @@ -53,25 +53,26 @@ #include "whack.h" /* for RC_LOG_SERIOUS */ #include "timer.h" #include "fetch.h" -#include "xauth.h" const char *shared_secrets_file = SHARED_SECRETS_FILE; -typedef struct id_list id_list_t; -struct id_list { - identification_t *id; - id_list_t *next; +typedef enum secret_kind_t secret_kind_t; + +enum secret_kind_t { + SECRET_PSK, + SECRET_PUBKEY, + SECRET_XAUTH, + SECRET_PIN }; -typedef struct secret secret_t; +typedef struct secret_t secret_t; -struct secret { - id_list_t *ids; - enum PrivateKeyKind kind; +struct secret_t { + linked_list_t *ids; + secret_kind_t kind; union { chunk_t preshared_secret; - xauth_t xauth_secret; private_key_t *private_key; smartcard_t *smartcard; } u; @@ -92,12 +93,11 @@ static void free_public_key(pubkey_t *pk) secret_t *secrets = NULL; -/* find the struct secret associated with the combination of - * me and the peer. We match the Id (if none, the IP address). - * Failure is indicated by a NULL. +/** + * Find the secret associated with the combination of me and the peer. */ -static const secret_t* get_secret(const connection_t *c, - enum PrivateKeyKind kind, bool asym) +const secret_t* match_secret(identification_t *my_id, identification_t *his_id, + secret_kind_t kind) { enum { /* bits */ match_default = 0x01, @@ -106,128 +106,92 @@ static const secret_t* get_secret(const connection_t *c, }; unsigned int best_match = 0; - secret_t *best = NULL; - secret_t *s; - identification_t *my_id, *his_id; + secret_t *s, *best = NULL; - /* is there a certificate assigned to this connection? */ - if (kind == PPK_PUBKEY && c->spd.this.cert) + for (s = secrets; s != NULL; s = s->next) { - certificate_t *certificate = c->spd.this.cert->cert; + unsigned int match = 0; - public_key_t *pub_key = certificate->get_public_key(certificate); - - for (s = secrets; s != NULL; s = s->next) + if (s->kind != kind) { - if (s->kind == kind && - s->u.private_key->belongs_to(s->u.private_key, pub_key)) - { - best = s; - break; /* we have found the private key - no sense in searching further */ - } + continue; } - pub_key->destroy(pub_key); - return best; - } - - my_id = c->spd.this.id; - - if (his_id_was_instantiated(c)) - { - /* roadwarrior: replace him with 0.0.0.0 */ - his_id = identification_create_from_string("%any"); - } - else if (kind == PPK_PSK && (c->policy & (POLICY_PSK | POLICY_XAUTH_PSK)) && - ((c->kind == CK_TEMPLATE && - c->spd.that.id->get_type(c->spd.that.id) == ID_ANY) || - (c->kind == CK_INSTANCE && id_is_ipaddr(c->spd.that.id)))) - { - /* roadwarrior: replace him with 0.0.0.0 */ - his_id = identification_create_from_string("%any"); - } - else - { - his_id = c->spd.that.id->clone(c->spd.that.id); - } - for (s = secrets; s != NULL; s = s->next) - { - if (s->kind == kind) + if (s->ids->get_count(s->ids) == 0) + { + /* a default (signified by lack of ids): + * accept if no more specific match found + */ + match = match_default; + } + else { - unsigned int match = 0; + /* check if both ends match ids */ + enumerator_t *enumerator; + identification_t *id; - if (s->ids == NULL) - { - /* a default (signified by lack of ids): - * accept if no more specific match found - */ - match = match_default; - } - else + enumerator = s->ids->create_enumerator(s->ids); + while (enumerator->enumerate(enumerator, &id)) { - /* check if both ends match ids */ - id_list_t *i; - - for (i = s->ids; i != NULL; i = i->next) + if (my_id->equals(my_id, id)) { - if (my_id->equals(my_id, i->id)) - { - match |= match_me; - } - if (his_id->equals(his_id, i->id)) - { - match |= match_him; - } + match |= match_me; } - - /* If our end matched the only id in the list, - * default to matching any peer. - * A more specific match will trump this. - */ - if (match == match_me && s->ids->next == NULL) + if (his_id->equals(his_id, id)) { - match |= match_default; + match |= match_him; } } + enumerator->destroy(enumerator); - switch (match) + /* If our end matched the only id in the list, + * default to matching any peer. + * A more specific match will trump this. + */ + if (match == match_me && s->ids->get_count(s->ids) == 1) { + match |= match_default; + } + } + + switch (match) + { case match_me: /* if this is an asymmetric (eg. public key) system, * allow this-side-only match to count, even if * there are other ids in the list. */ - if (!asym) + if (kind != SECRET_PUBKEY) { break; } /* FALLTHROUGH */ - case match_default: /* default all */ - case match_me | match_default: /* default peer */ - case match_me | match_him: /* explicit */ + case match_default: /* default all */ + case match_me | match_default: /* default peer */ + case match_me | match_him: /* explicit */ if (match == best_match) { - /* two good matches are equally good: - * do they agree? - */ + /* two good matches are equally good: do they agree? */ bool same = FALSE; switch (kind) { - case PPK_PSK: - same = s->u.preshared_secret.len == best->u.preshared_secret.len - && memeq(s->u.preshared_secret.ptr, best->u.preshared_secret.ptr, s->u.preshared_secret.len); + case SECRET_PSK: + case SECRET_XAUTH: + same = chunk_equals(s->u.preshared_secret, + best->u.preshared_secret); break; - case PPK_PUBKEY: - same = s->u.private_key->equals(s->u.private_key, best->u.private_key); + case SECRET_PUBKEY: + same = s->u.private_key->equals(s->u.private_key, + best->u.private_key); break; default: bad_case(kind); } if (!same) { - loglog(RC_LOG_SERIOUS, "multiple ipsec.secrets entries with distinct secrets match endpoints:" - " first secret used"); + loglog(RC_LOG_SERIOUS, "multiple ipsec.secrets entries with " + "distinct secrets match endpoints: first secret used"); best = s; /* list is backwards: take latest in list */ } } @@ -237,9 +201,63 @@ static const secret_t* get_secret(const connection_t *c, best_match = match; best = s; } - } } } + return best; +} + +/** + * Retrieves an XAUTH secret primarily based on the user ID and + * secondarily based on the server ID + */ +bool get_xauth_secret(identification_t *user, identification_t *server, + chunk_t *secret) +{ + const secret_t *s; + + s = match_secret(user, server, SECRET_XAUTH); + if (s) + { + *secret = chunk_clone(s->u.preshared_secret); + return TRUE; + } + else + { + *secret = chunk_empty; + return FALSE; + } +} + +/** + * We match the ID (if none, the IP address). Failure is indicated by a NULL. + */ +static const secret_t* get_secret(const connection_t *c, secret_kind_t kind) +{ + identification_t *my_id, *his_id; + const secret_t *best; + + my_id = c->spd.this.id; + + if (his_id_was_instantiated(c)) + { + /* roadwarrior: replace him with 0.0.0.0 */ + his_id = identification_create_from_string("%any"); + } + else if (kind == SECRET_PSK && (c->policy & (POLICY_PSK | POLICY_XAUTH_PSK)) && + ((c->kind == CK_TEMPLATE && + c->spd.that.id->get_type(c->spd.that.id) == ID_ANY) || + (c->kind == CK_INSTANCE && id_is_ipaddr(c->spd.that.id)))) + { + /* roadwarrior: replace him with 0.0.0.0 */ + his_id = identification_create_from_string("%any"); + } + else + { + his_id = c->spd.that.id->clone(c->spd.that.id); + } + + best = match_secret(my_id, his_id, kind); + his_id->destroy(his_id); return best; } @@ -250,7 +268,7 @@ static const secret_t* get_secret(const connection_t *c, */ const chunk_t* get_preshared_secret(const connection_t *c) { - const secret_t *s = get_secret(c, PPK_PSK, FALSE); + const secret_t *s = get_secret(c, SECRET_PSK); DBG(DBG_PRIVATE, if (s == NULL) @@ -272,7 +290,7 @@ bool has_private_key(cert_t *cert) for (s = secrets; s != NULL; s = s->next) { - if (s->kind == PPK_PUBKEY && + if (s->kind == SECRET_PUBKEY && s->u.private_key->belongs_to(s->u.private_key, pub_key)) { has_key = TRUE; @@ -295,7 +313,7 @@ private_key_t* get_x509_private_key(const cert_t *cert) for (s = secrets; s != NULL; s = s->next) { - if (s->kind == PPK_PUBKEY && + if (s->kind == SECRET_PUBKEY && s->u.private_key->belongs_to(s->u.private_key, public_key)) { private_key = s->u.private_key; @@ -311,9 +329,33 @@ private_key_t* get_x509_private_key(const cert_t *cert) */ private_key_t* get_private_key(const connection_t *c) { - const secret_t *s = get_secret(c, PPK_PUBKEY, TRUE); + const secret_t *s, *best = NULL; + + /* is a certificate assigned to this connection? */ + if (c->spd.this.cert) + { + certificate_t *certificate; + public_key_t *pub_key; - return s == NULL? NULL : s->u.private_key; + certificate = c->spd.this.cert->cert; + pub_key = certificate->get_public_key(certificate); + + for (s = secrets; s != NULL; s = s->next) + { + if (s->kind == SECRET_PUBKEY && + s->u.private_key->belongs_to(s->u.private_key, pub_key)) + { + best = s; + break; /* found the private key - no sense in searching further */ + } + } + pub_key->destroy(pub_key); + } + else + { + best = get_secret(c, SECRET_PUBKEY); + } + return best ? best->u.private_key : NULL; } /* digest a secrets file @@ -556,120 +598,6 @@ static err_t process_keyfile(private_key_t **key, key_type_t type, int whackfd) } /** - * Process xauth secret read from ipsec.secrets - */ -static err_t process_xauth(secret_t *s) -{ - chunk_t user_name; - - s->kind = PPK_XAUTH; - - if (!shift()) - return "missing xauth user name"; - if (*tok == '"' || *tok == '\'') /* quoted user name */ - { - user_name.ptr = tok + 1; - user_name.len = flp->cur - tok - 2; - } - else - { - user_name.ptr = tok; - user_name.len = flp->cur - tok; - } - plog(" loaded xauth credentials of user '%.*s'" - , user_name.len - , user_name.ptr); - s->u.xauth_secret.user_name = chunk_clone(user_name); - - if (!shift()) - return "missing xauth user password"; - return process_psk_secret(&s->u.xauth_secret.user_password); -} - -/** - * Get XAUTH secret from chained secrets lists - * only one entry is currently supported - */ -static bool xauth_get_secret(xauth_t *xauth_secret) -{ - secret_t *s; - bool found = FALSE; - - for (s = secrets; s != NULL; s = s->next) - { - if (s->kind == PPK_XAUTH) - { - if (found) - { - plog("found multiple xauth secrets - first selected"); - } - else - { - found = TRUE; - *xauth_secret = s->u.xauth_secret; - } - } - } - return found; -} - -/** - * find a matching secret - */ -static bool xauth_verify_secret(const xauth_peer_t *peer, - const xauth_t *xauth_secret) -{ - bool found = FALSE; - secret_t *s; - - for (s = secrets; s != NULL; s = s->next) - { - if (s->kind == PPK_XAUTH) - { - if (!chunk_equals(xauth_secret->user_name, s->u.xauth_secret.user_name)) - { - continue; - } - found = TRUE; - if (chunk_equals(xauth_secret->user_password, s->u.xauth_secret.user_password)) - { - return TRUE; - } - } - } - plog("xauth user '%.*s' %s" - , xauth_secret->user_name.len, xauth_secret->user_name.ptr - , found? "sent wrong password":"not found"); - return FALSE; -} - -/** - * the global xauth_module struct is defined here - */ -xauth_module_t xauth_module; - -/** - * Assign the default xauth functions to any null function pointers - */ -void xauth_defaults(void) -{ - if (xauth_module.get_secret == NULL) - { - DBG(DBG_CONTROL, - DBG_log("xauth module: using default get_secret() function") - ) - xauth_module.get_secret = xauth_get_secret; - } - if (xauth_module.verify_secret == NULL) - { - DBG(DBG_CONTROL, - DBG_log("xauth module: using default verify_secret() function") - ) - xauth_module.verify_secret = xauth_verify_secret; - } -}; - -/** * Process pin read from ipsec.secrets or prompted for it using whack */ static err_t process_pin(secret_t *s, int whackfd) @@ -677,7 +605,7 @@ static err_t process_pin(secret_t *s, int whackfd) smartcard_t *sc; const char *pin_status = "no pin"; - s->kind = PPK_PIN; + s->kind = SECRET_PIN; /* looking for the smartcard keyword */ if (!shift() || strncmp(tok, SCX_TOKEN, strlen(SCX_TOKEN)) != 0) @@ -748,57 +676,69 @@ static err_t process_pin(secret_t *s, int whackfd) return NULL; } -static void log_psk(secret_t *s) +static void log_psk(char *label, secret_t *s) { int n = 0; char buf[BUF_LEN]; - id_list_t *id_list = s->ids; + enumerator_t *enumerator; + identification_t *id; - if (id_list == NULL) + if (s->ids->get_count(s->ids) == 0) { n = snprintf(buf, BUF_LEN, "%%any"); } else { - do + enumerator = s->ids->create_enumerator(s->ids); + while(enumerator->enumerate(enumerator, &id)) { - n += snprintf(buf + n, BUF_LEN - n, "%Y ", id_list->id); + n += snprintf(buf + n, BUF_LEN - n, "%Y ", id); if (n >= BUF_LEN) { n = BUF_LEN - 1; break; } - id_list = id_list->next; } - while (id_list); + enumerator->destroy(enumerator); } - plog(" loaded shared key for %.*s", n, buf); + plog(" loaded %s secret for %.*s", label, n, buf); } static void process_secret(secret_t *s, int whackfd) { err_t ugh = NULL; - s->kind = PPK_PSK; /* default */ + s->kind = SECRET_PSK; /* default */ if (*tok == '"' || *tok == '\'') { + log_psk("PSK", s); + /* old PSK format: just a string */ - log_psk(s); ugh = process_psk_secret(&s->u.preshared_secret); } else if (tokeqword("psk")) { + log_psk("PSK", s); + /* preshared key: quoted string or ttodata format */ - log_psk(s); ugh = !shift()? "unexpected end of record in PSK" : process_psk_secret(&s->u.preshared_secret); } + else if (tokeqword("xauth")) + { + s->kind = SECRET_XAUTH; + log_psk("XAUTH", s); + + /* xauth secret: quoted string or ttodata format */ + ugh = !shift()? "unexpected end of record in XAUTH" + : process_psk_secret(&s->u.preshared_secret); + } else if (tokeqword("rsa")) { /* RSA key: the fun begins. * A braced list of keyword and value pairs. */ - s->kind = PPK_PUBKEY; + s->kind = SECRET_PUBKEY; if (!shift()) { ugh = "bad RSA key syntax"; @@ -814,7 +754,7 @@ static void process_secret(secret_t *s, int whackfd) } else if (tokeqword("ecdsa")) { - s->kind = PPK_PUBKEY; + s->kind = SECRET_PUBKEY; if (!shift()) { ugh = "bad ECDSA key syntax"; @@ -824,10 +764,6 @@ static void process_secret(secret_t *s, int whackfd) ugh = process_keyfile(&s->u.private_key, KEY_ECDSA, whackfd); } } - else if (tokeqword("xauth")) - { - ugh = process_xauth(s); - } else if (tokeqword("pin")) { ugh = process_pin(s, whackfd); @@ -919,8 +855,8 @@ static void process_secret_records(int whackfd) secret_t *s = malloc_thing(secret_t); zero(s); - s->ids = NULL; - s->kind = PPK_PSK; /* default */ + s->ids = linked_list_create(); + s->kind = SECRET_PSK; /* default */ s->u.preshared_secret = chunk_empty; s->next = NULL; @@ -941,14 +877,10 @@ static void process_secret_records(int whackfd) } else { - /* an id - * See RFC2407 IPsec Domain of Interpretation 4.6.2 - */ - id_list_t *i = malloc_thing(id_list_t); + identification_t *id; - i->id = identification_create_from_string(tok); - i->next = s->ids; - s->ids = i; + id = identification_create_from_string(tok); + s->ids->insert_last(s->ids, id); if (!shift()) { @@ -1035,32 +967,23 @@ void free_preshared_secrets(void) for (s = secrets; s != NULL; s = ns) { - id_list_t *i, *ni; - ns = s->next; - for (i = s->ids; i != NULL; i = ni) - { - ni = i->next; - i->id->destroy(i->id); - free(i); - } + s->ids->destroy_offset(s->ids, offsetof(identification_t, destroy)); + switch (s->kind) { - case PPK_PSK: - free(s->u.preshared_secret.ptr); - break; - case PPK_PUBKEY: - DESTROY_IF(s->u.private_key); - break; - case PPK_XAUTH: - free(s->u.xauth_secret.user_name.ptr); - free(s->u.xauth_secret.user_password.ptr); - break; - case PPK_PIN: - scx_release(s->u.smartcard); - break; - default: - bad_case(s->kind); + case SECRET_PSK: + case SECRET_XAUTH: + free(s->u.preshared_secret.ptr); + break; + case SECRET_PUBKEY: + DESTROY_IF(s->u.private_key); + break; + case SECRET_PIN: + scx_release(s->u.smartcard); + break; + default: + bad_case(s->kind); } free(s); } @@ -1315,7 +1238,7 @@ void add_public_key_from_cert(cert_t *cert , time_t until, /* insert all subjectAltNames from X.509 certificates */ enumerator = x509->create_subjectAltName_enumerator(x509); - while (enumerator->enumerate(enumerator, &id)) + while (enumerator->enumerate(enumerator, &id)) { if (id->get_type(id) != ID_ANY) { @@ -1404,7 +1327,7 @@ void list_public_keys(bool utc) public->get_keysize(public) * BITS_PER_BYTE, &key->until_time, utc, check_expiry(key->until_time, PUBKEY_WARNING_INTERVAL, TRUE)); - if (public->get_fingerprint(public, KEY_ID_PUBKEY_INFO_SHA1, &keyid)) + if (public->get_fingerprint(public, KEYID_PUBKEY_INFO_SHA1, &keyid)) { whack_log(RC_COMMENT," keyid: %#B", &keyid); } diff --git a/src/pluto/keys.h b/src/pluto/keys.h index d856c0009..73cc21392 100644 --- a/src/pluto/keys.h +++ b/src/pluto/keys.h @@ -21,6 +21,7 @@ #include <credentials/keys/public_key.h> #include "certs.h" +#include "connections.h" #ifndef SHARED_SECRETS_FILE # define SHARED_SECRETS_FILE IPSEC_CONFDIR "/ipsec.secrets" @@ -31,20 +32,12 @@ const char *shared_secrets_file; extern void load_preshared_secrets(int whackfd); extern void free_preshared_secrets(void); -enum PrivateKeyKind { - PPK_PSK, - PPK_PUBKEY, - PPK_XAUTH, - PPK_PIN -}; - extern void xauth_defaults(void); -/* forward declaration */ -struct connection; - -extern const chunk_t *get_preshared_secret(const struct connection *c); -extern private_key_t *get_private_key(const struct connection *c); +extern bool get_xauth_secret(identification_t *user, identification_t *server, + chunk_t *secret); +extern const chunk_t *get_preshared_secret(const connection_t *c); +extern private_key_t *get_private_key(const connection_t *c); extern private_key_t *get_x509_private_key(const cert_t *cert); /* public key machinery */ diff --git a/src/pluto/modecfg.c b/src/pluto/modecfg.c index 0c4f2bd6b..0d0cd899c 100644 --- a/src/pluto/modecfg.c +++ b/src/pluto/modecfg.c @@ -2,7 +2,7 @@ * Copyright (C) 2001-2002 Colubris Networks * Copyright (C) 2003 Sean Mathews - Nu Tech Software Solutions, inc. * Copyright (C) 2003-2004 Xelerance Corporation - * Copyright (C) 2006-2009 Andreas Steffen - Hochschule fuer Technik Rapperswil + * Copyright (C) 2006-2010 Andreas Steffen - Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -27,7 +27,7 @@ #include <library.h> #include <hydra.h> -#include <attributes/attributes.h> +#include <utils/linked_list.h> #include <crypto/prfs/prf.h> #include "constants.h" @@ -40,106 +40,121 @@ #include "crypto.h" #include "modecfg.h" #include "whack.h" -#include "xauth.h" +#include "pluto.h" #define MAX_XAUTH_TRIES 3 -#define DNS_SERVER_MAX 2 -#define NBNS_SERVER_MAX 2 -#define SUPPORTED_ATTR_SET ( LELEM(INTERNAL_IP4_ADDRESS) \ - | LELEM(INTERNAL_IP4_NETMASK) \ - | LELEM(INTERNAL_IP4_DNS) \ - | LELEM(INTERNAL_IP4_NBNS) \ - | LELEM(APPLICATION_VERSION) \ - | LELEM(INTERNAL_IP6_DNS) \ - | LELEM(INTERNAL_IP6_NBNS) \ - ) +#define DEFAULT_UNITY_BANNER "Welcome to strongSwan - the Linux VPN Solution!\n" -#define SUPPORTED_UNITY_ATTR_SET ( LELEM(UNITY_BANNER - UNITY_BASE) ) +/** + * Creates a modecfg_attribute_t object + */ +static modecfg_attribute_t *modecfg_attribute_create(configuration_attribute_type_t type, + chunk_t value) +{ + modecfg_attribute_t *this; -#define UNITY_BANNER_STR "Welcome to strongSwan - the Linux VPN Solution!\n" + this = malloc_thing(modecfg_attribute_t); + this->type = ((u_int16_t)type) & 0x7FFF; + this->is_tv = FALSE; + this->value = chunk_clone(value); + this->handler = NULL; -/* - * Addresses assigned (usually via ModeCfg) to the Initiator - */ -typedef struct internal_addr internal_addr_t; + return this; +} -struct internal_addr +/** + * Creates a modecfg_attribute_t object coded in TV format + */ +static modecfg_attribute_t *modecfg_attribute_create_tv(configuration_attribute_type_t type, + size_t value) { - lset_t attr_set; - lset_t xauth_attr_set; - lset_t unity_attr_set; - - /* ModeCfg variables */ - ip_address ipaddr; - ip_address dns[DNS_SERVER_MAX]; - ip_address nbns[NBNS_SERVER_MAX]; + modecfg_attribute_t *this; - char *unity_banner; + this = modecfg_attribute_create(type, chunk_empty); + this->value.len = value; + this->is_tv = TRUE; - /* XAUTH variables */ - u_int16_t xauth_type; - xauth_t xauth_secret; - bool xauth_status; -}; + return this; +} /** - * Initialize an internal_addr struct + * Destroys a modecfg_attribute_t object */ -static void init_internal_addr(internal_addr_t *ia) +void modecfg_attribute_destroy(modecfg_attribute_t *this) { - int i; + free(this->value.ptr); + free(this); +} - ia->attr_set = LEMPTY; - ia->xauth_attr_set = LEMPTY; - ia->xauth_secret.user_name = chunk_empty; - ia->xauth_secret.user_password = chunk_empty; - ia->xauth_type = XAUTH_TYPE_GENERIC; - ia->xauth_status = XAUTH_STATUS_FAIL; - ia->unity_attr_set = LEMPTY; - ia->unity_banner = NULL; +/** + * Get attributes to be sent to client + */ +static void get_attributes(connection_t *c, linked_list_t *ca_list) +{ + configuration_attribute_type_t type; + identification_t *client_id; + modecfg_attribute_t *ca; + enumerator_t *enumerator; + chunk_t value; + host_t *vip = NULL, *requested_vip = NULL; + bool want_unity_banner = FALSE; + int family; - anyaddr(AF_INET, &ia->ipaddr); +#ifdef CISCO_QUIRKS + /* always send banner in ModeCfg push mode */ + if (ca_list->get_count(ca_list) == 0) + { + want_unity_banner = TRUE; + } +#endif - /* initialize DNS server information */ - for (i = 0; i < DNS_SERVER_MAX; i++) + /* scan list of requested attributes in ModeCfg pull mode */ + while (ca_list->remove_last(ca_list, (void **)&ca) == SUCCESS) { - anyaddr(AF_INET, &ia->dns[i]); + switch (ca->type) + { + case INTERNAL_IP4_ADDRESS: + case INTERNAL_IP6_ADDRESS: + { + int family; + + family = (ca->type == INTERNAL_IP4_ADDRESS) ? AF_INET : AF_INET6; + requested_vip = (ca->value.len) ? + host_create_from_chunk(family, ca->value, 0) : + host_create_any(family); + plog("peer requested virtual IP %H", requested_vip); + break; + } +#ifdef CISCO_QUIRKS + case UNITY_BANNER: + want_unity_banner = TRUE; + break; +#endif + default: + break; + } + modecfg_attribute_destroy(ca); } - /* initialize NBNS server information */ - for (i = 0; i < NBNS_SERVER_MAX; i++) + if (requested_vip == NULL) { - anyaddr(AF_INET, &ia->nbns[i]); + requested_vip = host_create_any(AF_INET); } -} -/** - * Get internal IP address for a connection - */ -static void get_internal_addr(connection_t *c, host_t *requested_vip, - internal_addr_t *ia) -{ - int dns_idx = 0, nbns_idx = 0; - enumerator_t *enumerator; - configuration_attribute_type_t type; - chunk_t value; - host_t *vip = NULL; + client_id = (c->xauth_identity) ? c->xauth_identity : c->spd.that.id; - if (isanyaddr(&c->spd.that.host_srcip)) + /* if no virtual IP has been assigned yet - acquire one */ + if (c->spd.that.host_srcip->is_anyaddr(c->spd.that.host_srcip)) { if (c->spd.that.pool) { vip = hydra->attributes->acquire_address(hydra->attributes, - c->spd.that.pool, c->spd.that.id, - requested_vip); + c->spd.that.pool, client_id, requested_vip); if (vip) { - chunk_t addr = vip->get_address(vip); - - plog("assigning virtual IP %H to peer", vip); - initaddr(addr.ptr, addr.len, vip->get_family(vip), &ia->ipaddr); - + c->spd.that.host_srcip->destroy(c->spd.that.host_srcip); + c->spd.that.host_srcip = vip; } } else @@ -147,132 +162,184 @@ static void get_internal_addr(connection_t *c, host_t *requested_vip, plog("no virtual IP found"); } } - else - { - ia->ipaddr = c->spd.that.host_srcip; - vip = host_create_from_sockaddr((sockaddr_t*)&ia->ipaddr); - plog("assigning virtual IP %H to peer", vip); - } - if (!isanyaddr(&ia->ipaddr)) /* We got an IP address, send it */ + requested_vip->destroy(requested_vip); + + /* if we have a virtual IP address - send it */ + if (!c->spd.that.host_srcip->is_anyaddr(c->spd.that.host_srcip)) { - c->spd.that.host_srcip = ia->ipaddr; - c->spd.that.client.addr = ia->ipaddr; - c->spd.that.client.maskbits = 32; + vip = c->spd.that.host_srcip; + plog("assigning virtual IP %H to peer", vip); + family = vip->get_family(vip); + ca = modecfg_attribute_create((family == AF_INET) ? + INTERNAL_IP4_ADDRESS : + INTERNAL_IP6_ADDRESS, + vip->get_address(vip)); + ca_list->insert_last(ca_list, ca); + + /* set the remote client subnet to virtual IP */ + c->spd.that.client.addr = *(ip_address*)vip->get_sockaddr(vip); + c->spd.that.client.maskbits = (family == AF_INET) ? 32 : 128; c->spd.that.has_client = TRUE; - - ia->attr_set = LELEM(INTERNAL_IP4_ADDRESS) - | LELEM(INTERNAL_IP4_NETMASK); } /* assign attributes from registered providers */ enumerator = hydra->attributes->create_responder_enumerator(hydra->attributes, - c->spd.that.id, vip); + c->spd.that.pool, client_id, vip); while (enumerator->enumerate(enumerator, &type, &value)) { - err_t ugh; - host_t *server; - sa_family_t family = AF_INET; + ca = modecfg_attribute_create(type, value); + ca_list->insert_last(ca_list, ca); + if (type == UNITY_BANNER) + { + want_unity_banner = FALSE; + } + } + enumerator->destroy(enumerator); + + if (want_unity_banner) + { + ca = modecfg_attribute_create(UNITY_BANNER, + chunk_create(DEFAULT_UNITY_BANNER, + strlen(DEFAULT_UNITY_BANNER))); + ca_list->insert_last(ca_list, ca); + } +} + +/** + * Set srcip and client subnet to internal IP address + */ +static bool set_attributes(connection_t *c, linked_list_t *ca_list) +{ + host_t *vip, *srcip; + modecfg_attribute_t *ca, *ca_handler; + enumerator_t *enumerator; + bool vip_set = FALSE; + + enumerator = ca_list->create_enumerator(ca_list); + while (enumerator->enumerate(enumerator, &ca)) + { + int family = AF_INET6; + attribute_handler_t *handler = NULL; + enumerator_t *e; - switch (type) + switch (ca->type) { - case INTERNAL_IP6_DNS: - family = AF_INET6; - /* fallthrough */ - case INTERNAL_IP4_DNS: - if (dns_idx >= DNS_SERVER_MAX) + case INTERNAL_IP4_ADDRESS: + family = AF_INET; + /* fall */ + case INTERNAL_IP6_ADDRESS: + if (ca->value.len == 0) { - plog("exceeded the maximum number of %d DNS servers", - DNS_SERVER_MAX); - break; + vip = host_create_any(family); } - ugh = initaddr(value.ptr, value.len, family, &ia->dns[dns_idx]); - if (ugh) + else { - plog("error in DNS server address: %s", ugh); - break; + /* skip prefix byte in IPv6 payload*/ + if (family == AF_INET6) + { + ca->value.len = 16; + } + vip = host_create_from_chunk(family, ca->value, 0); } - server = host_create_from_chunk(family, value, 0); - plog("assigning DNS server %H to peer", server); - server->destroy(server); - - /* differentiate between IP4 and IP6 in modecfg_build_msg() */ - ia->attr_set |= LELEM(INTERNAL_IP4_DNS); - dns_idx++; - break; - - case INTERNAL_IP6_NBNS: - family = AF_INET6; - /* fallthrough */ - case INTERNAL_IP4_NBNS: - if (nbns_idx >= NBNS_SERVER_MAX) + if (vip) { - plog("exceeded the maximum number of %d NBNS servers", - NBNS_SERVER_MAX); - break; - } - ugh = initaddr(value.ptr, value.len, family, &ia->nbns[nbns_idx]); - if (ugh) + srcip = c->spd.this.host_srcip; + + if (srcip->is_anyaddr(srcip) || srcip->equals(srcip, vip)) + { + plog("setting virtual IP source address to %H", vip); + } + else + { + plog("replacing virtual IP source address %H by %H", + srcip, vip); + } + srcip->destroy(srcip); + c->spd.this.host_srcip = vip; + + /* setting client subnet to vip/32 */ + addrtosubnet((ip_address*)vip->get_sockaddr(vip), + &c->spd.this.client); + setportof(0, &c->spd.this.client.addr); + c->spd.this.has_client = TRUE; + + vip_set = TRUE; + } + continue; + case APPLICATION_VERSION: +#ifdef CISCO_QUIRKS + case UNITY_BANNER: +#endif + if (ca->value.len > 0) { - plog("error in NBNS server address: %s", ugh); - break; + DBG(DBG_PARSING | DBG_CONTROLMORE, + DBG_log(" '%.*s'", ca->value.len, ca->value.ptr) + ) } - server = host_create_from_chunk(family, value, 0); - plog("assigning NBNS server %H to peer", server); - server->destroy(server); - - /* differentiate between IP4 and IP6 in modecfg_build_msg() */ - ia->attr_set |= LELEM(INTERNAL_IP4_NBNS); - nbns_idx++; break; - default: break; } - } - enumerator->destroy(enumerator); - DESTROY_IF(vip); -} - -/** - * Set srcip and client subnet to internal IP address - */ -static bool set_internal_addr(connection_t *c, internal_addr_t *ia) -{ - if (ia->attr_set & LELEM(INTERNAL_IP4_ADDRESS) - && !isanyaddr(&ia->ipaddr)) - { - if (addrbytesptr(&c->spd.this.host_srcip, NULL) == 0 - || isanyaddr(&c->spd.this.host_srcip) - || sameaddr(&c->spd.this.host_srcip, &ia->ipaddr)) + /* find the first handler which requested this attribute */ + e = c->requested->create_enumerator(c->requested); + while (e->enumerate(e, &ca_handler)) { - char srcip[ADDRTOT_BUF]; - - addrtot(&ia->ipaddr, 0, srcip, sizeof(srcip)); - plog("setting virtual IP source address to %s", srcip); + if (ca_handler->type == ca->type) + { + handler = ca_handler->handler; + break; + } } - else + e->destroy(e); + + /* and pass it to the handle function */ + handler = hydra->attributes->handle(hydra->attributes, + c->spd.that.id, handler, ca->type, ca->value); + if (handler) { - char old_srcip[ADDRTOT_BUF]; - char new_srcip[ADDRTOT_BUF]; + ca_handler = modecfg_attribute_create(ca->type, ca->value); + ca_handler->handler = handler; - addrtot(&c->spd.this.host_srcip, 0, old_srcip, sizeof(old_srcip)); - addrtot(&ia->ipaddr, 0, new_srcip, sizeof(new_srcip)); - plog("replacing virtual IP source address %s by %s" - , old_srcip, new_srcip); + if (c->attributes == NULL) + { + c->attributes = linked_list_create(); + } + c->attributes->insert_last(c->attributes, ca_handler); } + } + enumerator->destroy(enumerator); + c->requested->destroy_function(c->requested, (void*)modecfg_attribute_destroy); + c->requested = NULL; + return vip_set; +} - /* setting srcip */ - c->spd.this.host_srcip = ia->ipaddr; +/** + * Register configuration attribute handlers + */ +static void register_attribute_handlers(connection_t *c) +{ + configuration_attribute_type_t type; + modecfg_attribute_t *ca; + chunk_t value; + attribute_handler_t *handler; + enumerator_t *enumerator; - /* setting client subnet to srcip/32 */ - addrtosubnet(&ia->ipaddr, &c->spd.this.client); - setportof(0, &c->spd.this.client.addr); - c->spd.this.has_client = TRUE; - return TRUE; + /* add configuration attributes requested by handlers */ + if (c->requested == NULL) + { + c->requested = linked_list_create(); } - return FALSE; + enumerator = hydra->attributes->create_initiator_enumerator( + hydra->attributes,c->spd.that.id, c->spd.this.host_srcip); + while (enumerator->enumerate(enumerator, &handler, &type, &value)) + { + ca = modecfg_attribute_create(type, value); + ca->handler = handler; + c->requested->insert_last(c->requested, ca); + } + enumerator->destroy(enumerator); } /** @@ -307,218 +374,53 @@ static size_t modecfg_hash(u_char *dest, u_char *start, u_char *roof, * Generate an IKE message containing ModeCfg information (eg: IP, DNS, WINS) */ static stf_status modecfg_build_msg(struct state *st, pb_stream *rbody, - u_int16_t msg_type, - internal_addr_t *ia, + u_int16_t msg_type, linked_list_t *ca_list, u_int16_t ap_id) { u_char *r_hash_start, *r_hashval; + struct isakmp_mode_attr attrh; + struct isakmp_attribute attr; + pb_stream strattr,attrval; + enumerator_t *enumerator; + modecfg_attribute_t *ca; START_HASH_PAYLOAD(*rbody, ISAKMP_NEXT_ATTR); - /* ATTR out */ + attrh.isama_np = ISAKMP_NEXT_NONE; + attrh.isama_type = msg_type; + attrh.isama_identifier = ap_id; + + if (!out_struct(&attrh, &isakmp_attr_desc, rbody, &strattr)) { - struct isakmp_mode_attr attrh; - struct isakmp_attribute attr; - pb_stream strattr,attrval; - int attr_type, dns_attr_type, nbns_attr_type; - int dns_idx, nbns_idx; - bool dont_advance; - bool is_xauth_attr_set = ia->xauth_attr_set != LEMPTY; - bool is_unity_attr_set = ia->unity_attr_set != LEMPTY; - lset_t attr_set = ia->attr_set; - - attrh.isama_np = ISAKMP_NEXT_NONE; - attrh.isama_type = msg_type; - attrh.isama_identifier = ap_id; - - if (!out_struct(&attrh, &isakmp_attr_desc, rbody, &strattr)) + return STF_INTERNAL_ERROR; + } + + enumerator = ca_list->create_enumerator(ca_list); + while (enumerator->enumerate(enumerator, &ca)) + { + DBG(DBG_CONTROLMORE, + DBG_log("building %N attribute", configuration_attribute_type_names, ca->type) + ) + if (ca->is_tv) { - return STF_INTERNAL_ERROR; + attr.isaat_af_type = ca->type | ISAKMP_ATTR_AF_TV; + attr.isaat_lv = ca->value.len; + out_struct(&attr, &isakmp_modecfg_attribute_desc, &strattr, &attrval); } - attr_type = 0; - dns_idx = 0; - nbns_idx = 0; - - while (attr_set != LEMPTY || is_xauth_attr_set || is_unity_attr_set) + else { - if (attr_set == LEMPTY) - { - if (is_xauth_attr_set) - { - attr_set = ia->xauth_attr_set; - attr_type = XAUTH_BASE; - is_xauth_attr_set = FALSE; - } - else - { - attr_set = ia->unity_attr_set; - attr_type = UNITY_BASE; - is_unity_attr_set = FALSE; - } - } - - dont_advance = FALSE; - - if (attr_set & 1) - { - const u_char *byte_ptr; - u_int len; - - /* ISAKMP attr out */ - if (attr_type == XAUTH_TYPE) - { - attr.isaat_af_type = attr_type | ISAKMP_ATTR_AF_TV; - attr.isaat_lv = ia->xauth_type; - } - else if (attr_type == XAUTH_STATUS) - { - attr.isaat_af_type = attr_type | ISAKMP_ATTR_AF_TV; - attr.isaat_lv = ia->xauth_status; - } - else if (attr_type == INTERNAL_IP4_DNS && !isanyaddr(&ia->dns[dns_idx])) - { - dns_attr_type = (addrtypeof(&ia->dns[dns_idx]) == AF_INET) ? - INTERNAL_IP4_DNS : INTERNAL_IP6_DNS; - attr.isaat_af_type = dns_attr_type | ISAKMP_ATTR_AF_TLV; - - } - else if (attr_type == INTERNAL_IP4_NBNS && !isanyaddr(&ia->nbns[nbns_idx])) - { - nbns_attr_type = (addrtypeof(&ia->nbns[nbns_idx]) == AF_INET) ? - INTERNAL_IP4_NBNS : INTERNAL_IP6_NBNS; - attr.isaat_af_type = nbns_attr_type | ISAKMP_ATTR_AF_TLV; - - } - else - { - attr.isaat_af_type = attr_type | ISAKMP_ATTR_AF_TLV; - } - out_struct(&attr, &isakmp_modecfg_attribute_desc, &strattr, &attrval); + char buf[BUF_LEN]; - switch (attr_type) - { - case INTERNAL_IP4_ADDRESS: - if (!isanyaddr(&ia->ipaddr)) - { - len = addrbytesptr(&ia->ipaddr, &byte_ptr); - out_raw(byte_ptr, len, &attrval, "IP4_addr"); - } - break; - case INTERNAL_IP4_NETMASK: - { - u_int mask; -#if 0 - char mask[4],bits[8]={0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe}; - int t,m=st->st_connection->that.host_addr.maskbit; - for (t=0; t<4; t++) - { - if (m < 8) - mask[t] = bits[m]; - else - mask[t] = 0xff; - m -= 8; - } -#endif - if (st->st_connection->spd.this.client.maskbits == 0) - { - mask = 0; - } - else - { - mask = 0xffffffff * 1; - out_raw(&mask, 4, &attrval, "IP4_mask"); - } - } - break; - case INTERNAL_IP4_SUBNET: - { - char mask[4]; - char bits[8] = {0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe}; - int t; - int m = st->st_connection->spd.this.client.maskbits; - - for (t = 0; t < 4; t++) - { - mask[t] = (m < 8) ? bits[m] : 0xff; - m -= 8; - if (m < 0) - { - m = 0; - } - } - len = addrbytesptr(&st->st_connection->spd.this.client.addr, &byte_ptr); - out_raw(byte_ptr, len, &attrval, "IP4_subnet"); - out_raw(mask, sizeof(mask), &attrval, "IP4_submsk"); - } - break; - case INTERNAL_IP4_DNS: - case INTERNAL_IP6_DNS: - if (!isanyaddr(&ia->dns[dns_idx])) - { - len = addrbytesptr(&ia->dns[dns_idx++], &byte_ptr); - out_raw(byte_ptr, len, &attrval, "IP_dns"); - } - if (dns_idx < DNS_SERVER_MAX && !isanyaddr(&ia->dns[dns_idx])) - { - dont_advance = TRUE; - } - break; - case INTERNAL_IP4_NBNS: - case INTERNAL_IP6_NBNS: - if (!isanyaddr(&ia->nbns[nbns_idx])) - { - len = addrbytesptr(&ia->nbns[nbns_idx++], &byte_ptr); - out_raw(byte_ptr, len, &attrval, "IP_nbns"); - } - if (nbns_idx < NBNS_SERVER_MAX && !isanyaddr(&ia->nbns[nbns_idx])) - { - dont_advance = TRUE; - } - break; - case XAUTH_TYPE: - break; - case XAUTH_USER_NAME: - if (ia->xauth_secret.user_name.ptr != NULL) - { - out_raw(ia->xauth_secret.user_name.ptr - , ia->xauth_secret.user_name.len - , &attrval, "xauth_user_name"); - } - break; - case XAUTH_USER_PASSWORD: - if (ia->xauth_secret.user_password.ptr != NULL) - { - out_raw(ia->xauth_secret.user_password.ptr - , ia->xauth_secret.user_password.len - , &attrval, "xauth_user_password"); - } - break; - case XAUTH_STATUS: - break; - case UNITY_BANNER: - if (ia->unity_banner != NULL) - { - out_raw(ia->unity_banner - , strlen(ia->unity_banner) - , &attrval, "UNITY_BANNER"); - } - break; - default: - plog("attempt to send unsupported mode cfg attribute %s." - , enum_show(&modecfg_attr_names, attr_type)); - break; - } - close_output_pbs(&attrval); - } - if (!dont_advance) - { - attr_type++; - attr_set >>= 1; - } + attr.isaat_af_type = ca->type | ISAKMP_ATTR_AF_TLV; + out_struct(&attr, &isakmp_modecfg_attribute_desc, &strattr, &attrval); + snprintf(buf, BUF_LEN, "%N", configuration_attribute_type_names, ca->type); + out_raw(ca->value.ptr, ca->value.len, &attrval, buf); } - close_message(&strattr); + close_output_pbs(&attrval); } - + enumerator->destroy(enumerator); + close_message(&strattr); + modecfg_hash(r_hashval, r_hash_start, rbody->cur, st); close_message(rbody); encrypt_message(rbody, st); @@ -529,7 +431,7 @@ static stf_status modecfg_build_msg(struct state *st, pb_stream *rbody, * Send ModeCfg message */ static stf_status modecfg_send_msg(struct state *st, int isama_type, - internal_addr_t *ia) + linked_list_t *ca_list) { pb_stream msg; pb_stream rbody; @@ -561,12 +463,8 @@ static stf_status modecfg_send_msg(struct state *st, int isama_type, } } - /* ATTR out */ - modecfg_build_msg(st, &rbody - , isama_type - , ia - , 0 /* XXX isama_id */ - ); + /* ATTR out with isama_id of 0 */ + modecfg_build_msg(st, &rbody, isama_type, ca_list, 0); free(st->st_tpacket.ptr); st->st_tpacket = chunk_create(msg.start, pbs_offset(&msg)); @@ -586,221 +484,157 @@ static stf_status modecfg_send_msg(struct state *st, int isama_type, /** * Parse a ModeCfg attribute payload */ -static stf_status modecfg_parse_attributes(pb_stream *attrs, internal_addr_t *ia) +static stf_status modecfg_parse_attributes(pb_stream *attrs, linked_list_t *ca_list) { struct isakmp_attribute attr; pb_stream strattr; - err_t ugh; - char buf[BUF_LEN]; - int dns_idx = 0; - int nbns_idx = 0; + u_int16_t attr_type; + u_int16_t attr_len; + chunk_t attr_chunk; + modecfg_attribute_t *ca; while (pbs_left(attrs) >= sizeof(struct isakmp_attribute)) { - u_int16_t attr_type; - u_int16_t attr_len; - if (!in_struct(&attr, &isakmp_modecfg_attribute_desc, attrs, &strattr)) { return STF_FAIL; } attr_type = attr.isaat_af_type & ISAKMP_ATTR_RTYPE_MASK; attr_len = attr.isaat_lv; + DBG(DBG_CONTROLMORE, + DBG_log("processing %N attribute", + configuration_attribute_type_names, attr_type) + ) switch (attr_type) { - case INTERNAL_IP4_ADDRESS: - if (attr_len == 4) - { - ugh = initaddr((char *)(strattr.cur), 4, AF_INET, &ia->ipaddr); - if (ugh != NULL) - { - plog("received invalid virtual IPv4 address: %s", ugh); - } - } - ia->attr_set |= LELEM(attr_type); - break; - case INTERNAL_IP4_DNS: - if (attr_len == 4 && dns_idx < DNS_SERVER_MAX) - { - ugh = initaddr((char *)(strattr.cur), 4, AF_INET, &ia->dns[dns_idx]); - if (ugh != NULL) - { - plog("received invalid IPv4 DNS server address: %s", ugh); - } - else - { - addrtot(&ia->dns[dns_idx], 0, buf, BUF_LEN); - plog("received IPv4 DNS server address %s", buf); - dns_idx++; - } - } - ia->attr_set |= LELEM(attr_type); - break; - case INTERNAL_IP4_NBNS: - if (attr_len == 4 && nbns_idx < NBNS_SERVER_MAX) - { - ugh = initaddr((char *)(strattr.cur), 4, AF_INET, &ia->nbns[nbns_idx]); - if (ugh != NULL) + case INTERNAL_IP4_ADDRESS: + case INTERNAL_IP4_NETMASK: + case INTERNAL_IP4_DNS: + case INTERNAL_IP4_NBNS: + case INTERNAL_ADDRESS_EXPIRY: + case INTERNAL_IP4_DHCP: + if (attr_len != 4 && attr_len != 0) { - plog("received invalid IPv4 NBNS server address: %s", ugh); + goto error; } - else + break; + case INTERNAL_IP4_SUBNET: + if (attr_len != 8 && attr_len != 0) { - addrtot(&ia->nbns[nbns_idx], 0, buf, BUF_LEN); - plog("received IPv4 NBNS server address %s", buf); - nbns_idx++; + goto error; } - } - ia->attr_set |= LELEM(attr_type); - break; - case INTERNAL_IP6_DNS: - if (attr_len == 16 && dns_idx < DNS_SERVER_MAX) - { - ugh = initaddr((char *)(strattr.cur), 16, AF_INET6, &ia->dns[dns_idx]); - if (ugh != NULL) + break; + case INTERNAL_IP6_NETMASK: + case INTERNAL_IP6_DNS: + case INTERNAL_IP6_NBNS: + case INTERNAL_IP6_DHCP: + if (attr_len != 16 && attr_len != 0) { - plog("received invalid IPv6 DNS server address: %s", ugh); + goto error; } - else + break; + case INTERNAL_IP6_ADDRESS: + if (attr_len != 17 && attr_len != 16 && attr_len != 0) { - addrtot(&ia->dns[dns_idx], 0, buf, BUF_LEN); - plog("received IPv6 DNS server address %s", buf); - dns_idx++; + goto error; } - } - ia->attr_set |= LELEM(attr_type); - break; - case INTERNAL_IP6_NBNS: - if (attr_len == 16 && nbns_idx < NBNS_SERVER_MAX) - { - ugh = initaddr((char *)(strattr.cur), 16, AF_INET6, &ia->nbns[nbns_idx]); - if (ugh != NULL) + break; + case INTERNAL_IP6_SUBNET: + if (attr_len != 17 && attr_len != 0) { - plog("received invalid IPv6 NBNS server address: %s", ugh); + goto error; } - else + break; + case SUPPORTED_ATTRIBUTES: + if (attr_len % 2) { - addrtot(&ia->nbns[nbns_idx], 0, buf, BUF_LEN); - plog("received IPv6 NBNS server address %s", buf); - nbns_idx++; + goto error; } - } - ia->attr_set |= LELEM(attr_type); - break; - case INTERNAL_IP4_NETMASK: - case INTERNAL_IP4_SUBNET: - case INTERNAL_ADDRESS_EXPIRY: - case INTERNAL_IP4_DHCP: - case INTERNAL_IP6_ADDRESS: - case INTERNAL_IP6_NETMASK: - case INTERNAL_IP6_DHCP: - case SUPPORTED_ATTRIBUTES: - case INTERNAL_IP6_SUBNET: - ia->attr_set |= LELEM(attr_type); - break; - case APPLICATION_VERSION: - if (attr_len > 0) - { - DBG(DBG_PARSING, - DBG_log(" '%.*s'", attr_len, strattr.cur) - ) - } - ia->attr_set |= LELEM(attr_type); - break; - case XAUTH_TYPE: - ia->xauth_type = attr.isaat_lv; - ia->xauth_attr_set |= LELEM(attr_type - XAUTH_BASE); - break; - case XAUTH_USER_NAME: - ia->xauth_secret.user_name = chunk_create(strattr.cur, attr_len); - ia->xauth_attr_set |= LELEM(attr_type - XAUTH_BASE); - break; - case XAUTH_USER_PASSWORD: - ia->xauth_secret.user_password = chunk_create(strattr.cur, attr_len); - ia->xauth_attr_set |= LELEM(attr_type - XAUTH_BASE); - break; - case XAUTH_STATUS: - ia->xauth_status = attr.isaat_lv; - ia->xauth_attr_set |= LELEM(attr_type - XAUTH_BASE); - break; - case XAUTH_MESSAGE: - if (attr_len > 0) - { - DBG(DBG_PARSING, - DBG_log(" '%.*s'", attr_len, strattr.cur) - ) - } - /* fall through to set attribute flag */ - case XAUTH_PASSCODE: - case XAUTH_CHALLENGE: - case XAUTH_DOMAIN: - case XAUTH_NEXT_PIN: - case XAUTH_ANSWER: - ia->xauth_attr_set |= LELEM(attr_type - XAUTH_BASE); - break; - case UNITY_DDNS_HOSTNAME: - if (attr_len > 0) - { - DBG(DBG_PARSING, - DBG_log(" '%.*s'", attr_len, strattr.cur) - ) - } - /* fall through to set attribute flag */ - case UNITY_BANNER: - case UNITY_SAVE_PASSWD: - case UNITY_DEF_DOMAIN: - case UNITY_SPLITDNS_NAME: - case UNITY_SPLIT_INCLUDE: - case UNITY_NATT_PORT: - case UNITY_LOCAL_LAN: - case UNITY_PFS: - case UNITY_FW_TYPE: - case UNITY_BACKUP_SERVERS: - ia->unity_attr_set |= LELEM(attr_type - UNITY_BASE); - break; - default: - plog("unsupported ModeCfg attribute %s received." - , enum_show(&modecfg_attr_names, attr_type)); - break; + break; + case APPLICATION_VERSION: + break; + /* XAUTH attributes */ + case XAUTH_TYPE: + case XAUTH_STATUS: + case XAUTH_USER_NAME: + case XAUTH_USER_PASSWORD: + case XAUTH_PASSCODE: + case XAUTH_MESSAGE: + case XAUTH_CHALLENGE: + case XAUTH_DOMAIN: + case XAUTH_NEXT_PIN: + case XAUTH_ANSWER: + break; + /* Microsoft attributes */ + case INTERNAL_IP4_SERVER: + case INTERNAL_IP6_SERVER: + break; + /* Cisco Unity attributes */ + case UNITY_BANNER: + case UNITY_SAVE_PASSWD: + case UNITY_DEF_DOMAIN: + case UNITY_SPLITDNS_NAME: + case UNITY_SPLIT_INCLUDE: + case UNITY_NATT_PORT: + case UNITY_LOCAL_LAN: + case UNITY_PFS: + case UNITY_FW_TYPE: + case UNITY_BACKUP_SERVERS: + case UNITY_DDNS_HOSTNAME: + break; + default: + plog("unknown attribute type (%u)", attr_type); + continue; } + + /* add attribute */ + if (attr.isaat_af_type & ISAKMP_ATTR_AF_TV) + { + ca = modecfg_attribute_create_tv(attr_type, attr_len); + } + else + { + attr_chunk = chunk_create(strattr.cur, attr_len); + ca = modecfg_attribute_create(attr_type, attr_chunk); + } + ca_list->insert_last(ca_list, ca); } return STF_OK; + +error: + plog("%N attribute has invalid size of %u octets", + configuration_attribute_type_names, attr_type, attr_len); + return STF_FAIL; } /** * Parse a ModeCfg message */ static stf_status modecfg_parse_msg(struct msg_digest *md, int isama_type, - u_int16_t *isama_id, internal_addr_t *ia) + u_int16_t *isama_id, linked_list_t *ca_list) { + modecfg_attribute_t *ca; struct state *const st = md->st; struct payload_digest *p; stf_status stat; st->st_msgid = md->hdr.isa_msgid; - CHECK_QUICK_HASH(md, modecfg_hash(hash_val - , hash_pbs->roof - , md->message_pbs.roof, st) - , "MODECFG-HASH", "ISAKMP_CFG_MSG"); + CHECK_QUICK_HASH(md, modecfg_hash(hash_val, hash_pbs->roof, + md->message_pbs.roof, st), "MODECFG-HASH", "ISAKMP_CFG_MSG"); /* process the ModeCfg payloads received */ for (p = md->chain[ISAKMP_NEXT_ATTR]; p != NULL; p = p->next) { - internal_addr_t ia_candidate; - - init_internal_addr(&ia_candidate); - if (p->payload.attribute.isama_type == isama_type) { *isama_id = p->payload.attribute.isama_identifier; - stat = modecfg_parse_attributes(&p->pbs, &ia_candidate); + stat = modecfg_parse_attributes(&p->pbs, ca_list); if (stat == STF_OK) { /* return with a valid set of attributes */ - *ia = ia_candidate; return STF_OK; } } @@ -810,34 +644,61 @@ static stf_status modecfg_parse_msg(struct msg_digest *md, int isama_type, , enum_name(&attr_msg_type_names, isama_type) , enum_name(&attr_msg_type_names, p->payload.attribute.isama_type)); - stat = modecfg_parse_attributes(&p->pbs, &ia_candidate); + stat = modecfg_parse_attributes(&p->pbs, ca_list); } + + /* abort if a parsing error occurred */ if (stat != STF_OK) { + ca_list->destroy_function(ca_list, (void*)modecfg_attribute_destroy); return stat; } + + /* discard the parsed attributes and look for another payload */ + while (ca_list->remove_last(ca_list, (void **)&ca) == SUCCESS) {} } return STF_IGNORE; } /** - * Send ModeCfg request message from client to server in pull mode + * Used in ModeCfg pull mode on the client (initiator) + * called in demux.c + * client -> CFG_REQUEST + * STF_OK transitions to STATE_MODE_CFG_I1 */ stf_status modecfg_send_request(struct state *st) { connection_t *c = st->st_connection; stf_status stat; - internal_addr_t ia; - - init_internal_addr(&ia); - - ia.attr_set = LELEM(INTERNAL_IP4_ADDRESS) - | LELEM(INTERNAL_IP4_NETMASK); - ia.ipaddr = c->spd.this.host_srcip; + modecfg_attribute_t *ca; + enumerator_t *enumerator; + int family; + chunk_t value; + host_t *vip; + linked_list_t *ca_list = linked_list_create(); + + vip = c->spd.this.host_srcip; + value = vip->is_anyaddr(vip) ? chunk_empty : vip->get_address(vip); + family = vip->get_family(vip); + ca = modecfg_attribute_create((family == AF_INET) ? + INTERNAL_IP4_ADDRESS : INTERNAL_IP6_ADDRESS, + value); + ca_list->insert_last(ca_list, ca); + + register_attribute_handlers(c); + enumerator = c->requested->create_enumerator(c->requested); + while (enumerator->enumerate(enumerator, &ca)) + { + ca = modecfg_attribute_create(ca->type, chunk_empty); + ca_list->insert_last(ca_list, ca); + } + enumerator->destroy(enumerator); plog("sending ModeCfg request"); + st->st_state = STATE_MODE_CFG_I1; - stat = modecfg_send_msg(st, ISAKMP_CFG_REQUEST, &ia); + stat = modecfg_send_msg(st, ISAKMP_CFG_REQUEST, ca_list); + ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy); if (stat == STF_OK) { st->st_modecfg.started = TRUE; @@ -845,53 +706,37 @@ stf_status modecfg_send_request(struct state *st) return stat; } -/* STATE_MODE_CFG_R0: - * HDR*, HASH, ATTR(REQ=IP) --> HDR*, HASH, ATTR(REPLY=IP) - * - * used in ModeCfg pull mode, on the server (responder) +/** + * Used in ModeCfg pull mode on the server (responder) + * called in demux.c from STATE_MODE_CFG_R0 + * server <- CFG_REQUEST + * server -> CFG_REPLY + * STF_OK transitions to STATE_MODE_CFG_R0 */ stf_status modecfg_inR0(struct msg_digest *md) { struct state *const st = md->st; u_int16_t isama_id; - internal_addr_t ia; - bool want_unity_banner; stf_status stat, stat_build; - host_t *requested_vip; + linked_list_t *ca_list = linked_list_create(); - stat = modecfg_parse_msg(md, ISAKMP_CFG_REQUEST, &isama_id, &ia); + plog("parsing ModeCfg request"); + + stat = modecfg_parse_msg(md, ISAKMP_CFG_REQUEST, &isama_id, ca_list); if (stat != STF_OK) { return stat; } - if (ia.attr_set & LELEM(INTERNAL_IP4_ADDRESS)) - { - requested_vip = host_create_from_sockaddr((sockaddr_t*)&ia.ipaddr); - } - else - { - requested_vip = host_create_any(AF_INET); - } - plog("peer requested virtual IP %H", requested_vip); - - want_unity_banner = (ia.unity_attr_set & LELEM(UNITY_BANNER - UNITY_BASE)) != LEMPTY; - init_internal_addr(&ia); - get_internal_addr(st->st_connection, requested_vip, &ia); - requested_vip->destroy(requested_vip); - - if (want_unity_banner) - { - ia.unity_banner = UNITY_BANNER_STR; - ia.unity_attr_set |= LELEM(UNITY_BANNER - UNITY_BASE); - } + /* build the CFG_REPLY */ + get_attributes(st->st_connection, ca_list); plog("sending ModeCfg reply"); - stat_build = modecfg_build_msg(st, &md->rbody - , ISAKMP_CFG_REPLY - , &ia - , isama_id); + stat_build = modecfg_build_msg(st, &md->rbody, ISAKMP_CFG_REPLY, + ca_list, isama_id); + ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy); + if (stat_build != STF_OK) { return stat_build; @@ -900,53 +745,50 @@ stf_status modecfg_inR0(struct msg_digest *md) return STF_OK; } -/* STATE_MODE_CFG_I1: - * HDR*, HASH, ATTR(REPLY=IP) - * - * used in ModeCfg pull mode, on the client (initiator) +/** + * Used in ModeCfg pull mode on the client (initiator) + * called in demux.c from STATE_MODE_CFG_I1 + * client <- CFG_REPLY + * STF_OK transitions to STATE_MODE_CFG_I2 */ stf_status modecfg_inI1(struct msg_digest *md) { struct state *const st = md->st; u_int16_t isama_id; - internal_addr_t ia; stf_status stat; + linked_list_t *ca_list = linked_list_create(); plog("parsing ModeCfg reply"); - stat = modecfg_parse_msg(md, ISAKMP_CFG_REPLY, &isama_id, &ia); + stat = modecfg_parse_msg(md, ISAKMP_CFG_REPLY, &isama_id, ca_list); if (stat != STF_OK) { return stat; } - st->st_modecfg.vars_set = set_internal_addr(st->st_connection, &ia); + st->st_modecfg.vars_set = set_attributes(st->st_connection, ca_list); st->st_msgid = 0; + ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy); return STF_OK; } - /** - * Send ModeCfg set message from server to client in push mode + * Used in ModeCfg push mode on the server (responder) + * called in demux.c + * server -> CFG_SET + * STF_OK transitions to STATE_MODE_CFG_R3 */ stf_status modecfg_send_set(struct state *st) { stf_status stat; - internal_addr_t ia; - host_t *vip; + linked_list_t *ca_list = linked_list_create(); - init_internal_addr(&ia); - vip = host_create_any(AF_INET); - get_internal_addr(st->st_connection, vip, &ia); - vip->destroy(vip); -#ifdef CISCO_QUIRKS - ia.unity_banner = UNITY_BANNER_STR; - ia.unity_attr_set |= LELEM(UNITY_BANNER - UNITY_BASE); -#endif + plog("sending ModeCfg set"); - plog("sending ModeCfg set"); + get_attributes(st->st_connection, ca_list); st->st_state = STATE_MODE_CFG_R3; - stat = modecfg_send_msg(st, ISAKMP_CFG_SET, &ia); + stat = modecfg_send_msg(st, ISAKMP_CFG_SET, ca_list); + ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy); if (stat == STF_OK) { st->st_modecfg.started = TRUE; @@ -954,41 +796,64 @@ stf_status modecfg_send_set(struct state *st) return stat; } -/* STATE_MODE_CFG_I0: - * HDR*, HASH, ATTR(SET=IP) --> HDR*, HASH, ATTR(ACK,OK) - * - * used in ModeCfg push mode, on the client (initiator). +/** + * Used in ModeCfg push mode on the client (initiator) + * called in demux.c from STATE_MODE_CFG_I0 + * client <- CFG_SET + * client -> CFG_ACK + * STF_OK transitions to STATE_MODE_CFG_I3 */ stf_status modecfg_inI0(struct msg_digest *md) { struct state *const st = md->st; u_int16_t isama_id; - internal_addr_t ia; - lset_t attr_set, unity_attr_set; stf_status stat, stat_build; + modecfg_attribute_t *ca; + linked_list_t *ca_list, *ca_ack_list; plog("parsing ModeCfg set"); - stat = modecfg_parse_msg(md, ISAKMP_CFG_SET, &isama_id, &ia); + ca_list = linked_list_create(); + stat = modecfg_parse_msg(md, ISAKMP_CFG_SET, &isama_id, ca_list); if (stat != STF_OK) { return stat; } - st->st_modecfg.vars_set = set_internal_addr(st->st_connection, &ia); + register_attribute_handlers(st->st_connection); + st->st_modecfg.vars_set = set_attributes(st->st_connection, ca_list); /* prepare ModeCfg ack which sends zero length attributes */ - attr_set = ia.attr_set; - unity_attr_set = ia.unity_attr_set; - init_internal_addr(&ia); - ia.attr_set = attr_set & SUPPORTED_ATTR_SET; - ia.unity_attr_set = unity_attr_set & SUPPORTED_UNITY_ATTR_SET; + ca_ack_list = linked_list_create(); + while (ca_list->remove_last(ca_list, (void **)&ca) == SUCCESS) + { + switch (ca->type) + { + case INTERNAL_IP4_ADDRESS: + case INTERNAL_IP4_DNS: + case INTERNAL_IP4_NBNS: + case APPLICATION_VERSION: + case INTERNAL_IP6_ADDRESS: + case INTERNAL_IP6_DNS: + case INTERNAL_IP6_NBNS: +#ifdef CISCO_QUIRKS + case UNITY_BANNER: +#endif + /* supported attributes */ + ca->value.len = 0; + ca_ack_list->insert_last(ca_ack_list, ca); + break; + default: + /* unsupportd attributes */ + modecfg_attribute_destroy(ca); + } + } + ca_list->destroy(ca_list); plog("sending ModeCfg ack"); - stat_build = modecfg_build_msg(st, &md->rbody - , ISAKMP_CFG_ACK - , &ia - , isama_id); + stat_build = modecfg_build_msg(st, &md->rbody, ISAKMP_CFG_ACK, + ca_ack_list, isama_id); + ca_ack_list->destroy_function(ca_ack_list, (void *)modecfg_attribute_destroy); if (stat_build != STF_OK) { return stat_build; @@ -997,21 +862,23 @@ stf_status modecfg_inI0(struct msg_digest *md) return STF_OK; } -/* STATE_MODE_CFG_R3: - * HDR*, HASH, ATTR(ACK,OK) - * - * used in ModeCfg push mode, on the server (responder) +/** + * Used in ModeCfg push mode on the server (responder) + * called in demux.c from STATE_MODE_CFG_R3 + * server <- CFG_ACK + * STF_OK transitions to STATE_MODE_CFG_R4 */ stf_status modecfg_inR3(struct msg_digest *md) { struct state *const st = md->st; u_int16_t isama_id; - internal_addr_t ia; stf_status stat; + linked_list_t *ca_list = linked_list_create(); plog("parsing ModeCfg ack"); - stat = modecfg_parse_msg(md, ISAKMP_CFG_ACK, &isama_id, &ia); + stat = modecfg_parse_msg(md, ISAKMP_CFG_ACK, &isama_id, ca_list); + ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy); if (stat != STF_OK) { return stat; @@ -1021,20 +888,26 @@ stf_status modecfg_inR3(struct msg_digest *md) } /** - * Send XAUTH credentials request (username + password) + * Used on the XAUTH server (responder) + * called in demux.c + * server -> CFG_REQUEST + * STF_OK transitions to STATE_XAUTH_R1 */ stf_status xauth_send_request(struct state *st) { stf_status stat; - internal_addr_t ia; + modecfg_attribute_t *ca; + linked_list_t *ca_list = linked_list_create(); - init_internal_addr(&ia); - ia.xauth_attr_set = LELEM(XAUTH_USER_NAME - XAUTH_BASE) - | LELEM(XAUTH_USER_PASSWORD - XAUTH_BASE); + ca = modecfg_attribute_create(XAUTH_USER_NAME, chunk_empty); + ca_list->insert_last(ca_list, ca); + ca = modecfg_attribute_create(XAUTH_USER_PASSWORD, chunk_empty); + ca_list->insert_last(ca_list, ca); plog("sending XAUTH request"); st->st_state = STATE_XAUTH_R1; - stat = modecfg_send_msg(st, ISAKMP_CFG_REQUEST, &ia); + stat = modecfg_send_msg(st, ISAKMP_CFG_REQUEST, ca_list); + ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy); if (stat == STF_OK) { st->st_xauth.started = TRUE; @@ -1042,53 +915,87 @@ stf_status xauth_send_request(struct state *st) return stat; } -/* STATE_XAUTH_I0: - * HDR*, HASH, ATTR(REQ) --> HDR*, HASH, ATTR(REPLY=USERNAME/PASSWORD) - * - * used on the XAUTH client (initiator) +/** + * Used on the XAUTH client (initiator) + * called in demux.c from STATE_XAUTH_I0 + * client <- CFG_REQUEST + * client -> CFG_REPLY + * STF_OK transitions to STATE_XAUTH_I1 */ stf_status xauth_inI0(struct msg_digest *md) { struct state *const st = md->st; + connection_t *c = st->st_connection; u_int16_t isama_id; - internal_addr_t ia; stf_status stat, stat_build; - bool xauth_type_present; + modecfg_attribute_t *ca; + bool xauth_user_name_present = FALSE; + bool xauth_user_password_present = FALSE; + bool xauth_type_present = FALSE; + chunk_t xauth_user_name, xauth_user_password; + identification_t *user_id; + linked_list_t *ca_list = linked_list_create(); plog("parsing XAUTH request"); - stat = modecfg_parse_msg(md, ISAKMP_CFG_REQUEST, &isama_id, &ia); + stat = modecfg_parse_msg(md, ISAKMP_CFG_REQUEST, &isama_id, ca_list); if (stat != STF_OK) { return stat; } - /* check XAUTH attributes */ - xauth_type_present = (ia.xauth_attr_set & LELEM(XAUTH_TYPE - XAUTH_BASE)) != LEMPTY; - - if (xauth_type_present && ia.xauth_type != XAUTH_TYPE_GENERIC) + while (ca_list->remove_last(ca_list, (void **)&ca) == SUCCESS) { - plog("xauth type %s is not supported", enum_name(&xauth_type_names, ia.xauth_type)); - stat = STF_FAIL; + switch (ca->type) + { + case XAUTH_TYPE: + if (ca->value.len != XAUTH_TYPE_GENERIC) + { + plog("xauth type %s is not supported", + enum_name(&xauth_type_names, ca->value.len)); + stat = STF_FAIL; + } + else + { + xauth_type_present = TRUE; + } + break; + case XAUTH_USER_NAME: + xauth_user_name_present = TRUE; + break; + case XAUTH_USER_PASSWORD: + xauth_user_password_present = TRUE; + break; + case XAUTH_MESSAGE: + if (ca->value.len) + { + DBG(DBG_PARSING | DBG_CONTROLMORE, + DBG_log(" '%.*s'", ca->value.len, ca->value.ptr) + ) + } + break; + default: + break; + } + modecfg_attribute_destroy(ca); } - else if ((ia.xauth_attr_set & LELEM(XAUTH_USER_NAME - XAUTH_BASE)) == LEMPTY) + + if (!xauth_user_name_present) { plog("user name attribute is missing in XAUTH request"); stat = STF_FAIL; } - else if ((ia.xauth_attr_set & LELEM(XAUTH_USER_PASSWORD - XAUTH_BASE)) == LEMPTY) + if (!xauth_user_password_present) { plog("user password attribute is missing in XAUTH request"); stat = STF_FAIL; } /* prepare XAUTH reply */ - init_internal_addr(&ia); - if (stat == STF_OK) { /* get user credentials using a plugin function */ - if (!xauth_module.get_secret(&ia.xauth_secret)) + if (!pluto->xauth->get_secret(pluto->xauth, c, &xauth_user_password)) { plog("xauth user credentials not found"); stat = STF_FAIL; @@ -1096,35 +1003,42 @@ stf_status xauth_inI0(struct msg_digest *md) } if (stat == STF_OK) { + /* insert xauth type if present */ + if (xauth_type_present) + { + ca = modecfg_attribute_create_tv(XAUTH_TYPE, XAUTH_TYPE_GENERIC); + ca_list->insert_last(ca_list, ca); + } + + /* insert xauth user name */ + user_id = (c->xauth_identity) ? c->xauth_identity : c->spd.this.id; + xauth_user_name = user_id->get_encoding(user_id); DBG(DBG_CONTROL, - DBG_log("my xauth user name is '%.*s'" - , ia.xauth_secret.user_name.len - , ia.xauth_secret.user_name.ptr) + DBG_log("my xauth user name is '%.*s'", xauth_user_name.len, + xauth_user_name.ptr) ) + ca = modecfg_attribute_create(XAUTH_USER_NAME, xauth_user_name); + ca_list->insert_last(ca_list, ca); + + /* insert xauth user password */ DBG(DBG_PRIVATE, - DBG_log("my xauth user password is '%.*s'" - , ia.xauth_secret.user_password.len - , ia.xauth_secret.user_password.ptr) + DBG_log("my xauth user password is '%.*s'", xauth_user_password.len, + xauth_user_password.ptr) ) - ia.xauth_attr_set = LELEM(XAUTH_USER_NAME - XAUTH_BASE) - | LELEM(XAUTH_USER_PASSWORD - XAUTH_BASE); - if (xauth_type_present) - { - ia.xauth_attr_set |= LELEM(XAUTH_TYPE - XAUTH_BASE); - } + ca = modecfg_attribute_create(XAUTH_USER_PASSWORD, xauth_user_password); + ca_list->insert_last(ca_list, ca); + chunk_clear(&xauth_user_password); } else { - ia.xauth_attr_set = LELEM(XAUTH_STATUS - XAUTH_BASE); - ia.xauth_status = XAUTH_STATUS_FAIL; + ca = modecfg_attribute_create_tv(XAUTH_STATUS, XAUTH_STATUS_FAIL); + ca_list->insert_last(ca_list, ca); } plog("sending XAUTH reply"); - - stat_build = modecfg_build_msg(st, &md->rbody - , ISAKMP_CFG_REPLY - , &ia - , isama_id); + stat_build = modecfg_build_msg(st, &md->rbody, ISAKMP_CFG_REPLY, + ca_list, isama_id); + ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy); if (stat_build != STF_OK) { return stat_build; @@ -1147,79 +1061,105 @@ stf_status xauth_inI0(struct msg_digest *md) } } -/* STATE_XAUTH_R1: - * HDR*, HASH, ATTR(REPLY=USERNAME/PASSWORD) --> HDR*, HASH, ATTR(STATUS) - * - * used on the XAUTH server (responder) +/** + * Used on the XAUTH server (responder) + * called in demux.c from STATE_XAUTH_R1 + server <- CFG_REPLY + server -> CFG_SET + STF_OK transitions to STATE_XAUTH_R2 */ stf_status xauth_inR1(struct msg_digest *md) { struct state *const st = md->st; + connection_t *c = st->st_connection; u_int16_t isama_id; - internal_addr_t ia; stf_status stat, stat_build; + chunk_t xauth_user_name, xauth_user_password; + int xauth_status = XAUTH_STATUS_OK; + modecfg_attribute_t *ca; + linked_list_t *ca_list = linked_list_create(); plog("parsing XAUTH reply"); - stat = modecfg_parse_msg(md, ISAKMP_CFG_REPLY, &isama_id, &ia); + stat = modecfg_parse_msg(md, ISAKMP_CFG_REPLY, &isama_id, ca_list); if (stat != STF_OK) { return stat; } + /* initialize xauth_secret */ + xauth_user_name = chunk_empty; + xauth_user_password = chunk_empty; + + while (ca_list->remove_last(ca_list, (void **)&ca) == SUCCESS) + { + switch (ca->type) + { + case XAUTH_STATUS: + xauth_status = ca->value.len; + break; + case XAUTH_USER_NAME: + xauth_user_name = chunk_clone(ca->value); + break; + case XAUTH_USER_PASSWORD: + xauth_user_password = chunk_clone(ca->value); + break; + default: + break; + } + modecfg_attribute_destroy(ca); + } /* did the client return an XAUTH FAIL status? */ - if ((ia.xauth_attr_set & LELEM(XAUTH_STATUS - XAUTH_BASE)) != LEMPTY) + if (xauth_status == XAUTH_STATUS_FAIL) { plog("received FAIL status in XAUTH reply"); /* client is not able to do XAUTH, delete ISAKMP SA */ + free(xauth_user_name.ptr); + free(xauth_user_password.ptr); delete_state(st); + ca_list->destroy(ca_list); return STF_IGNORE; } /* check XAUTH reply */ - if ((ia.xauth_attr_set & LELEM(XAUTH_USER_NAME - XAUTH_BASE)) == LEMPTY) + if (xauth_user_name.ptr == NULL) { plog("user name attribute is missing in XAUTH reply"); st->st_xauth.status = FALSE; } - else if ((ia.xauth_attr_set & LELEM(XAUTH_USER_PASSWORD - XAUTH_BASE)) == LEMPTY) + else if (xauth_user_password.ptr == NULL) { plog("user password attribute is missing in XAUTH reply"); st->st_xauth.status = FALSE; } else { - xauth_peer_t peer; - - peer.conn_name = st->st_connection->name; - addrtot(&md->sender, 0, peer.ip_address, sizeof(peer.ip_address)); - snprintf(peer.id, sizeof(peer.id), "%Y", - md->st->st_connection->spd.that.id); - DBG(DBG_CONTROL, - DBG_log("peer xauth user name is '%.*s'" - , ia.xauth_secret.user_name.len - , ia.xauth_secret.user_name.ptr) + DBG_log("peer xauth user name is '%.*s'", xauth_user_name.len, + xauth_user_name.ptr) ) + DESTROY_IF(c->xauth_identity); + c->xauth_identity = identification_create_from_data(xauth_user_name); + DBG(DBG_PRIVATE, - DBG_log("peer xauth user password is '%.*s'" - , ia.xauth_secret.user_password.len - , ia.xauth_secret.user_password.ptr) + DBG_log("peer xauth user password is '%.*s'", xauth_user_password.len, + xauth_user_password.ptr) ) /* verify the user credentials using a plugin function */ - st->st_xauth.status = xauth_module.verify_secret(&peer, &ia.xauth_secret); + st->st_xauth.status = pluto->xauth->verify_secret(pluto->xauth, c, + xauth_user_password); plog("extended authentication %s", st->st_xauth.status? "was successful":"failed"); } - - /* prepare XAUTH set which sends the authentication status */ - init_internal_addr(&ia); - ia.xauth_attr_set = LELEM(XAUTH_STATUS - XAUTH_BASE); - ia.xauth_status = (st->st_xauth.status)? XAUTH_STATUS_OK : XAUTH_STATUS_FAIL; - - plog("sending XAUTH status:"); - - stat_build = modecfg_send_msg(st, ISAKMP_CFG_SET, &ia); + chunk_clear(&xauth_user_name); + chunk_clear(&xauth_user_password); + + plog("sending XAUTH status"); + xauth_status = (st->st_xauth.status) ? XAUTH_STATUS_OK : XAUTH_STATUS_FAIL; + ca = modecfg_attribute_create_tv(XAUTH_STATUS, xauth_status); + ca_list->insert_last(ca_list, ca); + stat_build = modecfg_send_msg(st, ISAKMP_CFG_SET, ca_list); + ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy); if (stat_build != STF_OK) { return stat_build; @@ -1227,20 +1167,23 @@ stf_status xauth_inR1(struct msg_digest *md) return STF_OK; } -/* STATE_XAUTH_I1: - * HDR*, HASH, ATTR(STATUS) --> HDR*, HASH, ATTR(ACK) - * - * used on the XAUTH client (initiator) +/** + * Used on the XAUTH client (initiator) + * called in demux.c from STATE_XAUTH_I1 + * client <- CFG_SET + * client -> CFG_ACK + * STF_OK transitions to STATE_XAUTH_I2 */ stf_status xauth_inI1(struct msg_digest *md) { struct state *const st = md->st; u_int16_t isama_id; - internal_addr_t ia; stf_status stat, stat_build; + modecfg_attribute_t *ca; + linked_list_t *ca_list = linked_list_create(); plog("parsing XAUTH status"); - stat = modecfg_parse_msg(md, ISAKMP_CFG_SET, &isama_id, &ia); + stat = modecfg_parse_msg(md, ISAKMP_CFG_SET, &isama_id, ca_list); if (stat != STF_OK) { /* notification payload - not exactly the right choice, but okay */ @@ -1248,15 +1191,21 @@ stf_status xauth_inI1(struct msg_digest *md) return stat; } - st->st_xauth.status = ia.xauth_status; + st->st_xauth.status = FALSE; + while (ca_list->remove_last(ca_list, (void **)&ca) == SUCCESS) + { + if (ca->type == XAUTH_STATUS) + { + st->st_xauth.status = (ca->value.len == XAUTH_STATUS_OK); + } + modecfg_attribute_destroy(ca); + } plog("extended authentication %s", st->st_xauth.status? "was successful":"failed"); plog("sending XAUTH ack"); - init_internal_addr(&ia); - stat_build = modecfg_build_msg(st, &md->rbody - , ISAKMP_CFG_ACK - , &ia - , isama_id); + stat_build = modecfg_build_msg(st, &md->rbody, ISAKMP_CFG_ACK, ca_list, isama_id); + ca_list->destroy(ca_list); + if (stat_build != STF_OK) { return stat_build; @@ -1278,25 +1227,27 @@ stf_status xauth_inI1(struct msg_digest *md) } } -/* STATE_XAUTH_R2: - * HDR*, ATTR(STATUS), HASH --> Done - * - * used on the XAUTH server (responder) +/** + * Used on the XAUTH server (responder) + * called in demux.c from STATE_XAUTH_R2 + * server <- CFG_ACK + * STF_OK transitions to STATE_XAUTH_R3 */ stf_status xauth_inR2(struct msg_digest *md) { struct state *const st = md->st; u_int16_t isama_id; - internal_addr_t ia; stf_status stat; + linked_list_t *ca_list = linked_list_create(); plog("parsing XAUTH ack"); - stat = modecfg_parse_msg(md, ISAKMP_CFG_ACK, &isama_id, &ia); + stat = modecfg_parse_msg(md, ISAKMP_CFG_ACK, &isama_id, ca_list); if (stat != STF_OK) { return stat; } + ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy); st->st_msgid = 0; if (st->st_xauth.status) { @@ -1307,4 +1258,5 @@ stf_status xauth_inR2(struct msg_digest *md) delete_state(st); return STF_IGNORE; } + } diff --git a/src/pluto/modecfg.h b/src/pluto/modecfg.h index bc1443012..7adf18682 100644 --- a/src/pluto/modecfg.h +++ b/src/pluto/modecfg.h @@ -16,8 +16,41 @@ #ifndef _MODECFG_H #define _MODECFG_H -struct state; -struct msg_digest; +#include <chunk.h> +#include <attributes/attribute_handler.h> + +#include "state.h" +#include "demux.h" + +typedef struct modecfg_attribute_t modecfg_attribute_t; + +/** + * Defines a modecfg_attribute_t object. + */ +struct modecfg_attribute_t { + /** + * Type of the attribute. + */ + u_int16_t type; + + /** + * Attribute is coded as TV + */ + bool is_tv; + + /** + * Attribute value as chunk. + */ + chunk_t value; + + /** + * Attribute handler. + */ + attribute_handler_t *handler; +}; + +/* Destroys a modecfg_attribute_t object */ +extern void modecfg_attribute_destroy(modecfg_attribute_t *this); /* ModeConfig pull mode start function */ extern stf_status modecfg_send_request(struct state *st); diff --git a/src/pluto/ocsp.c b/src/pluto/ocsp.c index b1f558ebf..8a351be6d 100644 --- a/src/pluto/ocsp.c +++ b/src/pluto/ocsp.c @@ -621,7 +621,7 @@ void list_ocsp_locations(ocsp_location_t *location, bool requests, } else { - whack_log(RC_COMMENT, " serial: %#B, %s, until %T %s", + whack_log(RC_COMMENT, " serial: %#B, %s, until %T %s", &certinfo->serialNumber, cert_status_names[certinfo->status], &certinfo->nextUpdate, utc, @@ -767,7 +767,7 @@ static chunk_t sc_build_sha1_signature(chunk_t tbs, smartcard_t *sc) */ static chunk_t build_signature(chunk_t tbsRequest) { - chunk_t sigdata, cert, certs; + chunk_t sigdata, cert, certs = chunk_empty; if (ocsp_requestor_sc) { @@ -786,10 +786,12 @@ static chunk_t build_signature(chunk_t tbsRequest) } /* include our certificate */ - cert = ocsp_requestor_cert->cert->get_encoding(ocsp_requestor_cert->cert); - certs = asn1_wrap(ASN1_CONTEXT_C_0, "m", - asn1_wrap(ASN1_SEQUENCE, "m", cert)); - + if (ocsp_requestor_cert->cert->get_encoding(ocsp_requestor_cert->cert, + CERT_ASN1_DER, &cert)) + { + certs = asn1_wrap(ASN1_CONTEXT_C_0, "m", + asn1_wrap(ASN1_SEQUENCE, "m", cert)); + } /* build signature comprising algorithm, signature and cert */ return asn1_wrap(ASN1_CONTEXT_C_0, "m" , asn1_wrap(ASN1_SEQUENCE, "mmm" @@ -1013,7 +1015,7 @@ static bool valid_ocsp_response(response_t *res) { plog("certificate is invalid (valid from %T to %T)", ¬_before, FALSE, ¬_after, FALSE); - + unlock_authcert_list("valid_ocsp_response"); return FALSE; } @@ -1154,7 +1156,7 @@ static bool parse_basic_ocsp_response(chunk_t blob, int level0, response_t *res) break; } x509 = (x509_t*)cert->cert; - + if ((x509->get_flags(x509) & X509_OCSP_SIGNER) && trust_authcert_candidate(cert, NULL)) { diff --git a/src/pluto/pkcs7.c b/src/pluto/pkcs7.c index b24ef1a8c..c0fd041a7 100644 --- a/src/pluto/pkcs7.c +++ b/src/pluto/pkcs7.c @@ -591,7 +591,7 @@ chunk_t pkcs7_build_signedData(chunk_t data, chunk_t attributes, contentInfo_t pkcs7Data, signedData; chunk_t authenticatedAttributes = chunk_empty; chunk_t encryptedDigest = chunk_empty; - chunk_t signerInfo, cInfo, signature; + chunk_t signerInfo, cInfo, signature, encoding = chunk_empty;; signature_scheme_t scheme = signature_scheme_from_oid(digest_alg); if (attributes.ptr) @@ -622,12 +622,13 @@ chunk_t pkcs7_build_signedData(chunk_t data, chunk_t attributes, pkcs7Data.content = (data.ptr == NULL)? chunk_empty : asn1_simple_object(ASN1_OCTET_STRING, data); + cert->get_encoding(cert, CERT_ASN1_DER, &encoding); signedData.type = OID_PKCS7_SIGNED_DATA; signedData.content = asn1_wrap(ASN1_SEQUENCE, "cmmmm" , ASN1_INTEGER_1 , asn1_wrap(ASN1_SET, "m", asn1_algorithmIdentifier(digest_alg)) , pkcs7_build_contentInfo(&pkcs7Data) - , asn1_wrap(ASN1_CONTEXT_C_0, "m", cert->get_encoding(cert)) + , asn1_wrap(ASN1_CONTEXT_C_0, "m", encoding) , asn1_wrap(ASN1_SET, "m", signerInfo)); cInfo = pkcs7_build_contentInfo(&signedData); diff --git a/src/pluto/plugins/xauth/Makefile.am b/src/pluto/plugins/xauth/Makefile.am new file mode 100644 index 000000000..354325b35 --- /dev/null +++ b/src/pluto/plugins/xauth/Makefile.am @@ -0,0 +1,15 @@ + +INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libfreeswan -I$(top_srcdir)/src/whack \ + -I$(top_srcdir)/src/pluto + +AM_CFLAGS = -rdynamic + +plugin_LTLIBRARIES = libstrongswan-xauth.la + +libstrongswan_xauth_la_SOURCES = \ + xauth_plugin.h xauth_plugin.c \ + xauth_default_provider.c xauth_default_provider.h \ + xauth_default_verifier.c xauth_default_verifier.h + +libstrongswan_xauth_la_LDFLAGS = -module -avoid-version diff --git a/src/pluto/plugins/xauth/Makefile.in b/src/pluto/plugins/xauth/Makefile.in new file mode 100644 index 000000000..13749e5af --- /dev/null +++ b/src/pluto/plugins/xauth/Makefile.in @@ -0,0 +1,577 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/pluto/plugins/xauth +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 = $(plugin_LTLIBRARIES) +libstrongswan_xauth_la_LIBADD = +am_libstrongswan_xauth_la_OBJECTS = xauth_plugin.lo \ + xauth_default_provider.lo xauth_default_verifier.lo +libstrongswan_xauth_la_OBJECTS = $(am_libstrongswan_xauth_la_OBJECTS) +libstrongswan_xauth_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(libstrongswan_xauth_la_LDFLAGS) $(LDFLAGS) -o $@ +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_xauth_la_SOURCES) +DIST_SOURCES = $(libstrongswan_xauth_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/libfreeswan -I$(top_srcdir)/src/whack \ + -I$(top_srcdir)/src/pluto + +AM_CFLAGS = -rdynamic +plugin_LTLIBRARIES = libstrongswan-xauth.la +libstrongswan_xauth_la_SOURCES = \ + xauth_plugin.h xauth_plugin.c \ + xauth_default_provider.c xauth_default_provider.h \ + xauth_default_verifier.c xauth_default_verifier.h + +libstrongswan_xauth_la_LDFLAGS = -module -avoid-version +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/pluto/plugins/xauth/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/pluto/plugins/xauth/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-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-xauth.la: $(libstrongswan_xauth_la_OBJECTS) $(libstrongswan_xauth_la_DEPENDENCIES) + $(libstrongswan_xauth_la_LINK) -rpath $(plugindir) $(libstrongswan_xauth_la_OBJECTS) $(libstrongswan_xauth_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xauth_default_provider.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xauth_default_verifier.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xauth_plugin.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(plugindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-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-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/pluto/plugins/xauth/xauth_default_provider.c b/src/pluto/plugins/xauth/xauth_default_provider.c new file mode 100644 index 000000000..77c5facc4 --- /dev/null +++ b/src/pluto/plugins/xauth/xauth_default_provider.c @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2010 Andreas Steffen + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * 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 <keys.h> + +#include "xauth_default_provider.h" + +typedef struct private_xauth_default_provider_t private_xauth_default_provider_t; + +/** + * private data of xauth_default_provider + */ +struct private_xauth_default_provider_t { + + /** + * public functions + */ + xauth_provider_t public; +}; + +METHOD(xauth_provider_t, get_secret, bool, + private_xauth_default_provider_t *this, connection_t *c, chunk_t *secret) +{ + identification_t *user, *server; + + server = c->spd.that.id; + user = (c->xauth_identity) ? c->xauth_identity : c->spd.this.id; + + return get_xauth_secret(user, server, secret); +} + +METHOD(xauth_provider_t, destroy, void, + private_xauth_default_provider_t *this) +{ + free(this); +} + +/* + * Described in header. + */ +xauth_provider_t *xauth_default_provider_create() +{ + private_xauth_default_provider_t *this; + + INIT(this, + .public = { + .get_secret = _get_secret, + .destroy = _destroy, + } + ); + + return &this->public; +} + diff --git a/src/pluto/plugins/xauth/xauth_default_provider.h b/src/pluto/plugins/xauth/xauth_default_provider.h new file mode 100644 index 000000000..ff1a91d16 --- /dev/null +++ b/src/pluto/plugins/xauth/xauth_default_provider.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2010 Andreas Steffen + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * 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 xauth_default_provider xauth_default_provider + * @{ @ingroup xauth + */ + +#ifndef XAUTH_DEFAULT_PROVIDER_H_ +#define XAUTH_DEFAULT_PROVIDER_H_ + +#include <xauth/xauth_provider.h> + + +/** + * Create an xauth_default_provider instance. + */ +xauth_provider_t *xauth_default_provider_create(); + +#endif /** XAUTH_DEFAULT_PROVIDER_H_ @}*/ + diff --git a/src/pluto/plugins/xauth/xauth_default_verifier.c b/src/pluto/plugins/xauth/xauth_default_verifier.c new file mode 100644 index 000000000..776f77134 --- /dev/null +++ b/src/pluto/plugins/xauth/xauth_default_verifier.c @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2010 Andreas Steffen + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * 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 <keys.h> + +#include "xauth_default_verifier.h" + +typedef struct private_xauth_default_verifier_t private_xauth_default_verifier_t; + +/** + * private data of xauth_default_verifier + */ +struct private_xauth_default_verifier_t { + + /** + * public functions + */ + xauth_verifier_t public; +}; + +METHOD(xauth_verifier_t, verify_secret, bool, + private_xauth_default_verifier_t *this, connection_t *c, chunk_t secret) +{ + identification_t *user, *server; + chunk_t xauth_secret; + bool success = FALSE; + + server = c->spd.this.id; + user = (c->xauth_identity) ? c->xauth_identity : c->spd.that.id; + + if (get_xauth_secret(user, server, &xauth_secret)) + { + success = chunk_equals(secret, xauth_secret); + chunk_clear(&xauth_secret); + } + return success; +} + +METHOD(xauth_verifier_t, destroy, void, + private_xauth_default_verifier_t *this) +{ + free(this); +} + + +/* + * Described in header. + */ +xauth_verifier_t *xauth_default_verifier_create() +{ + private_xauth_default_verifier_t *this; + + INIT(this, + .public = { + .verify_secret = _verify_secret, + .destroy = _destroy, + } + ); + + return &this->public; +} + diff --git a/src/pluto/plugins/xauth/xauth_default_verifier.h b/src/pluto/plugins/xauth/xauth_default_verifier.h new file mode 100644 index 000000000..e5814d7b4 --- /dev/null +++ b/src/pluto/plugins/xauth/xauth_default_verifier.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2010 Andreas Steffen + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * 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 xauth_default_verifier xauth_default_verifier + * @{ @ingroup xauth + */ + +#ifndef XAUTH_DEFAULT_VERIFIER_H_ +#define XAUTH_DEFAULT_VERIFIER_H_ + +#include <xauth/xauth_verifier.h> + + +/** + * Create an xauth_default_verifier instance. + */ +xauth_verifier_t *xauth_default_verifier_create(); + +#endif /** XAUTH_DEFAULT_VERIFIER_H_ @}*/ + diff --git a/src/pluto/plugins/xauth/xauth_plugin.c b/src/pluto/plugins/xauth/xauth_plugin.c new file mode 100644 index 000000000..74e16eacd --- /dev/null +++ b/src/pluto/plugins/xauth/xauth_plugin.c @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2010 Andreas Steffen + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * 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 <pluto.h> + +#include "xauth_plugin.h" +#include "xauth_default_provider.h" +#include "xauth_default_verifier.h" +/** + * Implementation of plugin_t.destroy + */ +static void destroy(xauth_plugin_t *this) +{ + free(this); +} + +/* + * see header file + */ +plugin_t *xauth_plugin_create() +{ + xauth_plugin_t *this = malloc_thing(xauth_plugin_t); + + this->plugin.destroy = (void(*)(plugin_t*))destroy; + + pluto->xauth->add_provider(pluto->xauth, xauth_default_provider_create()); + pluto->xauth->add_verifier(pluto->xauth, xauth_default_verifier_create()); + + return &this->plugin; +} + diff --git a/src/pluto/plugins/xauth/xauth_plugin.h b/src/pluto/plugins/xauth/xauth_plugin.h new file mode 100644 index 000000000..4f14828d2 --- /dev/null +++ b/src/pluto/plugins/xauth/xauth_plugin.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2010 Andreas Steffen + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * 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 xauth xauth + * @ingroup pplugins + * + * @defgroup xauth_plugin xauth_plugin + * @{ @ingroup xauth + */ + +#ifndef XAUTH_PLUGIN_H_ +#define XAUTH_PLUGIN_H_ + +#include <plugins/plugin.h> + +typedef struct xauth_plugin_t xauth_plugin_t; + +/** + * XAUTH plugin + */ +struct xauth_plugin_t { + + /** + * implements plugin interface + */ + plugin_t plugin; +}; + +#endif /** XAUTH_PLUGIN_H_ @}*/ diff --git a/src/pluto/pluto.c b/src/pluto/pluto.c new file mode 100644 index 000000000..e9c7c316b --- /dev/null +++ b/src/pluto/pluto.c @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2010 Andreas Steffen + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * 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 "pluto.h" + +#include <debug.h> + +typedef struct private_pluto_t private_pluto_t; + +/** + * Private additions to pluto_t. + */ +struct private_pluto_t { + + /** + * Public members of pluto_t. + */ + pluto_t public; +}; + +/** + * Single instance of pluto_t. + */ +pluto_t *pluto; + +/** + * Described in header. + */ +void pluto_deinit() +{ + private_pluto_t *this = (private_pluto_t*)pluto; + this->public.xauth->destroy(this->public.xauth); + free(this); + pluto = NULL; +} + +/** + * Described in header. + */ +bool pluto_init(char *file) +{ + private_pluto_t *this; + + INIT(this, + .public = { + .xauth = xauth_manager_create(), + }, + ); + pluto = &this->public; + + if (lib->integrity && + !lib->integrity->check_file(lib->integrity, "pluto", file)) + { + DBG1(DBG_LIB, "integrity check of pluto failed"); + return FALSE; + } + return TRUE; +} + diff --git a/src/pluto/pluto.h b/src/pluto/pluto.h new file mode 100644 index 000000000..37e6e3f33 --- /dev/null +++ b/src/pluto/pluto.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2010 Andreas Steffen + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * 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 pluto pluto + * + * @defgroup xauth xauth + * @ingroup pluto + * + * @defgroup pplugins plugins + * @ingroup pluto + * + * @addtogroup pluto + * @{ + */ + +#ifndef PLUTO_H_ +#define PLUTO_H_ + +typedef struct pluto_t pluto_t; + +#include <xauth/xauth_manager.h> + +#include <library.h> + +/** + * Pluto daemon support object. + */ +struct pluto_t { + + /** + * manager for payload attributes + */ + xauth_manager_t *xauth; +}; + +/** + * The single instance of pluto_t. + * + * Set between calls to pluto_init() and pluto_deinit() calls. + */ +extern pluto_t *pluto; + +/** + * Initialize pluto. + * + * @return FALSE if integrity check failed + */ +bool pluto_init(char *file); + +/** + * Deinitialize pluto. + */ +void pluto_deinit(void); + +#endif /** PLUTO_H_ @}*/ + diff --git a/src/pluto/plutomain.c b/src/pluto/plutomain.c index aa04594bc..89123bb8a 100644 --- a/src/pluto/plutomain.c +++ b/src/pluto/plutomain.c @@ -33,7 +33,9 @@ #include <grp.h> #ifdef CAPABILITIES +#ifdef HAVE_SYS_CAPABILITY_H #include <sys/capability.h> +#endif /* HAVE_SYS_CAPABILITY_H */ #endif /* CAPABILITIES */ #include <freeswan.h> @@ -68,7 +70,6 @@ #include "ocsp.h" #include "crl.h" #include "fetch.h" -#include "xauth.h" #include "crypto.h" #include "nat_traversal.h" #include "virtual.h" @@ -76,6 +77,7 @@ #include "vendor.h" #include "builder.h" #include "whack_attribute.h" +#include "pluto.h" static void usage(const char *mess) { @@ -258,7 +260,6 @@ int main(int argc, char **argv) char *virtual_private = NULL; int lockfd; #ifdef CAPABILITIES - cap_t caps; int keep[] = { CAP_NET_ADMIN, CAP_NET_BIND_SERVICE }; #endif /* CAPABILITIES */ @@ -268,18 +269,18 @@ int main(int argc, char **argv) library_deinit(); exit(SS_RC_LIBSTRONGSWAN_INTEGRITY); } - if (lib->integrity && - !lib->integrity->check_file(lib->integrity, "pluto", argv[0])) + if (!libhydra_init("pluto")) { - fprintf(stderr, "integrity check of pluto failed\n"); + libhydra_deinit(); library_deinit(); - exit(SS_RC_DAEMON_INTEGRITY); + exit(SS_RC_INITIALIZATION_FAILED); } - if (!libhydra_init("pluto")) + if (!pluto_init(argv[0])) { + pluto_deinit(); libhydra_deinit(); library_deinit(); - exit(SS_RC_INITIALIZATION_FAILED); + exit(SS_RC_DAEMON_INTEGRITY); } options = options_create(); @@ -677,7 +678,6 @@ int main(int argc, char **argv) init_nat_traversal(nat_traversal, keep_alive, force_keepalive, nat_t_spf); init_virtual_ip(virtual_private); scx_init(pkcs11_module_path, pkcs11_init_args); - xauth_init(); init_states(); init_demux(); init_kernel(); @@ -717,18 +717,41 @@ int main(int argc, char **argv) } #endif -#ifdef CAPABILITIES - caps = cap_init(); - cap_set_flag(caps, CAP_EFFECTIVE, 2, keep, CAP_SET); - cap_set_flag(caps, CAP_INHERITABLE, 2, keep, CAP_SET); - cap_set_flag(caps, CAP_PERMITTED, 2, keep, CAP_SET); - if (cap_set_proc(caps) != 0) +#ifdef CAPABILITIES_LIBCAP + { + cap_t caps; + caps = cap_init(); + cap_set_flag(caps, CAP_EFFECTIVE, countof(keep), keep, CAP_SET); + cap_set_flag(caps, CAP_INHERITABLE, countof(keep), keep, CAP_SET); + cap_set_flag(caps, CAP_PERMITTED, countof(keep), keep, CAP_SET); + if (cap_set_proc(caps) != 0) + { + plog("unable to drop daemon capabilities"); + abort(); + } + cap_free(caps); + } +#endif /* CAPABILITIES_LIBCAP */ +#ifdef CAPABILITIES_NATIVE { - plog("unable to drop daemon capabilities"); - abort(); + struct __user_cap_data_struct caps = { .effective = 0 }; + struct __user_cap_header_struct header = { + .version = _LINUX_CAPABILITY_VERSION, + }; + int i; + for (i = 0; i < countof(keep); i++) + { + caps.effective |= 1 << keep[i]; + caps.permitted |= 1 << keep[i]; + caps.inheritable |= 1 << keep[i]; + } + if (capset(&header, &caps) != 0) + { + plog("unable to drop daemon capabilities"); + abort(); + } } - cap_free(caps); -#endif /* CAPABILITIES */ +#endif /* CAPABILITIES_NATIVE */ /* loading X.509 CA certificates */ load_authcerts("ca", CA_CERT_PATH, X509_CA); @@ -771,7 +794,6 @@ void exit_pluto(int status) free_ifaces(); ac_finalize(); /* free X.509 attribute certificates */ scx_finalize(); /* finalize and unload PKCS #11 module */ - xauth_finalize(); /* finalize and unload XAUTH module */ stop_adns(); free_md_pool(); free_crypto(); @@ -781,6 +803,7 @@ void exit_pluto(int status) free_builder(); delete_lock(); options->destroy(options); + pluto_deinit(); lib->plugins->unload(lib->plugins); libhydra_deinit(); library_deinit(); diff --git a/src/pluto/rcv_whack.c b/src/pluto/rcv_whack.c index bf5ccb10c..c140095f0 100644 --- a/src/pluto/rcv_whack.c +++ b/src/pluto/rcv_whack.c @@ -329,6 +329,7 @@ void whack_handle(int whackctlfd) || !unpack_str(&msg.sc_data) /* string 26 */ || !unpack_str(&msg.whack_lease_ip) /* string 27 */ || !unpack_str(&msg.whack_lease_id) /* string 28 */ + || !unpack_str(&msg.xauth_identity) /* string 29 */ || str_roof - next_str != (ptrdiff_t)msg.keyval.len) /* check chunk */ { ugh = "message from whack contains bad string"; diff --git a/src/pluto/state.h b/src/pluto/state.h index 35ffe5a5b..c4e8db485 100644 --- a/src/pluto/state.h +++ b/src/pluto/state.h @@ -14,6 +14,9 @@ * for more details. */ +#ifndef _STATE_H +#define _STATE_H + #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> @@ -270,3 +273,5 @@ extern void fmt_state(bool all, struct state *st, time_t n , char *state_buf, size_t state_buf_len , char *state_buf2, size_t state_buf_len2); extern void delete_states_by_peer(ip_address *peer); + +#endif /* _STATE_H */ diff --git a/src/pluto/x509.c b/src/pluto/x509.c index 0a29830ea..2b8681246 100644 --- a/src/pluto/x509.c +++ b/src/pluto/x509.c @@ -393,6 +393,10 @@ void list_x509cert_chain(const char *caption, cert_t* cert, { written = snprintf(pos, len, ", %Y", id); } + if (written < 0 || written >= len) + { + break; + } pos += written; len -= written; } @@ -427,11 +431,11 @@ void list_x509cert_chain(const char *caption, cert_t* cert, cert->smartcard ? ", on smartcard" : (has_private_key(cert)? ", has private key" : "")); - if (key->get_fingerprint(key, KEY_ID_PUBKEY_INFO_SHA1, &keyid)) + if (key->get_fingerprint(key, KEYID_PUBKEY_INFO_SHA1, &keyid)) { whack_log(RC_COMMENT, " keyid: %#B", &keyid); } - if (key->get_fingerprint(key, KEY_ID_PUBKEY_SHA1, &subjkey)) + if (key->get_fingerprint(key, KEYID_PUBKEY_SHA1, &subjkey)) { whack_log(RC_COMMENT, " subjkey: %#B", &subjkey); } diff --git a/src/pluto/x509.h b/src/pluto/x509.h index e904618b3..3101724a6 100644 --- a/src/pluto/x509.h +++ b/src/pluto/x509.h @@ -26,6 +26,8 @@ #include "constants.h" #include "certs.h" +#define X509_MAX_PATH_LEN 7 + extern bool same_keyid(chunk_t a, chunk_t b); extern bool x509_check_signature(chunk_t tbs, chunk_t sig, int algorithm, certificate_t *issuer_cert); diff --git a/src/pluto/xauth.c b/src/pluto/xauth.c deleted file mode 100644 index 2086a92cc..000000000 --- a/src/pluto/xauth.c +++ /dev/null @@ -1,77 +0,0 @@ -/* Initialization and finalization of the dynamic XAUTH module - * Copyright (C) 2006 Andreas Steffen - * Hochschule fuer Technik Rapperswil, Switzerland - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * 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 <dlfcn.h> - -#include <freeswan.h> - -#include "constants.h" -#include "defs.h" -#include "xauth.h" -#include "keys.h" -#include "log.h" - -void -xauth_init(void) -{ -#ifdef XAUTH_DEFAULT_LIB - xauth_module.handle = dlopen(XAUTH_DEFAULT_LIB, RTLD_NOW); - - if (xauth_module.handle != NULL) - { - DBG(DBG_CONTROL, - DBG_log("xauth module '%s' loading'", XAUTH_DEFAULT_LIB) - ) - xauth_module.get_secret = (bool (*) (const xauth_t*)) - dlsym(xauth_module.handle, "get_secret"); - DBG(DBG_CONTROL, - if (xauth_module.get_secret != NULL) - { - DBG_log("xauth module: found get_secret() function"); - } - ) - xauth_module.verify_secret = (bool (*) (const xauth_peer_t*, const xauth_t*)) - dlsym(xauth_module.handle, "verify_secret"); - DBG(DBG_CONTROL, - if (xauth_module.verify_secret != NULL) - { - DBG_log("xauth module: found verify_secret() function"); - } - ) - } -#endif - /* any null function pointers will be filled in by default functions */ - xauth_defaults(); -} - -void -xauth_finalize(void) -{ -#ifdef XAUTH_DEFAULT_LIB - if (xauth_module.handle != NULL) - { - if (dlclose(xauth_module.handle)) - { - plog("failed to unload xauth module"); - } - else - { - DBG(DBG_CONTROL, - DBG_log("xauth module unloaded") - ) - } - } -#endif -} diff --git a/src/pluto/xauth.h b/src/pluto/xauth.h deleted file mode 100644 index 23cae3ed8..000000000 --- a/src/pluto/xauth.h +++ /dev/null @@ -1,48 +0,0 @@ -/* Interface definition of the XAUTH server and|or client module - * Copyright (C) 2006 Andreas Steffen - * Hochschule fuer Technik Rapperswil, Switzerland - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef _XAUTH_H -#define _XAUTH_H - -#include <freeswan.h> -#include "defs.h" - -/* XAUTH credentials */ - -struct chunk_t; - -typedef struct { - char *conn_name; - char id[BUF_LEN]; - char ip_address[ADDRTOT_BUF]; -} xauth_peer_t; - -typedef struct { - chunk_t user_name; - chunk_t user_password; -} xauth_t; - -typedef struct { - void *handle; - bool (*get_secret) (xauth_t *xauth_secret); - bool (*verify_secret) (const xauth_peer_t *peer, const xauth_t *xauth_secret); -} xauth_module_t; - -extern xauth_module_t xauth_module; - -extern void xauth_init(void); -extern void xauth_finalize(void); - -#endif /* _XAUTH_H */ diff --git a/src/pluto/xauth/xauth_manager.c b/src/pluto/xauth/xauth_manager.c new file mode 100644 index 000000000..2e57ccefa --- /dev/null +++ b/src/pluto/xauth/xauth_manager.c @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2010 Andreas Steffen + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * 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 "xauth_manager.h" + +typedef struct private_xauth_manager_t private_xauth_manager_t; + +/** + * private data of xauth_manager + */ +struct private_xauth_manager_t { + + /** + * public functions + */ + xauth_manager_t public; + + /** + * list of registered secret providers + */ + linked_list_t *providers; + + /** + * list of registered secret verifiers + */ + linked_list_t *verifiers; +}; + +METHOD(xauth_manager_t, get_secret, bool, + private_xauth_manager_t *this, connection_t *c, chunk_t *secret) +{ + xauth_provider_t *provider; + enumerator_t *enumerator; + bool success = FALSE; + + *secret = chunk_empty; + + enumerator = this->providers->create_enumerator(this->providers); + while (enumerator->enumerate(enumerator, &provider)) + { + if (provider->get_secret(provider, c, secret)) + { + success = TRUE; + break; + } + } + enumerator->destroy(enumerator); + return success; +} + +METHOD(xauth_manager_t, verify_secret, bool, + private_xauth_manager_t *this, connection_t *c, chunk_t secret) +{ + xauth_verifier_t *verifier; + enumerator_t *enumerator; + bool success = FALSE; + + enumerator = this->verifiers->create_enumerator(this->verifiers); + while (enumerator->enumerate(enumerator, &verifier)) + { + if (verifier->verify_secret(verifier, c, secret)) + { + success = TRUE; + break; + } + } + enumerator->destroy(enumerator); + return success; +} + +METHOD(xauth_manager_t, add_provider, void, + private_xauth_manager_t *this, xauth_provider_t *provider) +{ + this->providers->insert_last(this->providers, provider); +} + +METHOD(xauth_manager_t, add_verifier, void, + private_xauth_manager_t *this, xauth_verifier_t *verifier) +{ + this->verifiers->insert_last(this->verifiers, verifier); +} + +METHOD(xauth_manager_t, destroy, void, + private_xauth_manager_t *this) +{ + this->providers->destroy_offset(this->providers, + offsetof(xauth_provider_t, destroy)); + this->verifiers->destroy_offset(this->verifiers, + offsetof(xauth_verifier_t, destroy)); + free(this); +} + +/* + * Described in header. + */ +xauth_manager_t *xauth_manager_create() +{ + private_xauth_manager_t *this; + + INIT(this, + .public = { + .get_secret = _get_secret, + .verify_secret = _verify_secret, + .add_provider = _add_provider, + .add_verifier = _add_verifier, + .destroy = _destroy, + } + ); + + this->providers = linked_list_create(); + this->verifiers = linked_list_create(); + + return &this->public; +} + diff --git a/src/pluto/xauth/xauth_manager.h b/src/pluto/xauth/xauth_manager.h new file mode 100644 index 000000000..843eb2ff0 --- /dev/null +++ b/src/pluto/xauth/xauth_manager.h @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2010 Andreas Steffen + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * 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 xauth_manager xauth_manager + * @{ @ingroup xauth + */ + +#ifndef XAUTH_MANAGER_H_ +#define XAUTH_MANAGER_H_ + +#include "xauth_provider.h" +#include "xauth_verifier.h" + +typedef struct xauth_manager_t xauth_manager_t; + +/** + * An xauth_manager registers xauth_providers and xauth_verifiers. + */ +struct xauth_manager_t { + + /** + * Register an xauth_provider + * + * @param provider xauth_provider to be registered + */ + void (*add_provider)(xauth_manager_t *this, xauth_provider_t *provider); + + /** + * Register an xauth_verifier + * + * @param verifier xauth_verifier to be registered + */ + void (*add_verifier)(xauth_manager_t *this, xauth_verifier_t *verifier); + + /** + * Use registered providers to retrieve an XAUTH user secret + * based on connection information. + * + * @param c connection information + * @param secret secret if found, chunk_empty otherwise + * @return TRUE if a matching secret was found + */ + bool (*get_secret)(xauth_manager_t *this, connection_t *c, chunk_t *secret); + + /** + * Use registered verifiers to verify an XAUTH user secret + * based on connection information + * + * @param c connection information + * @param secret secret to be compared + * @return TRUE if secret matches + */ + bool (*verify_secret)(xauth_manager_t *this, connection_t *c, chunk_t secret); + + /** + * Destroy an xauth_verifier instance. + */ + void (*destroy)(xauth_manager_t *this); +}; + +/** + * Create an xauth_manager instance. + */ +xauth_manager_t *xauth_manager_create(); + +#endif /** XAUTH_MANAGER_H_ @}*/ + diff --git a/src/pluto/xauth/xauth_provider.h b/src/pluto/xauth/xauth_provider.h new file mode 100644 index 000000000..90adbff50 --- /dev/null +++ b/src/pluto/xauth/xauth_provider.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2010 Andreas Steffen + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * 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 xauth_provider xauth_provider + * @{ @ingroup xauth + */ + +#ifndef XAUTH_PROVIDER_H_ +#define XAUTH_PROVIDER_H_ + +#include <library.h> + +#include <connections.h> + +typedef struct xauth_provider_t xauth_provider_t; + +/** + * An xauth provider retrieves xauth user secrets on the client side. + */ +struct xauth_provider_t { + + /** + * Retrieve an XAUTH user secret based on connection information. + * + * @param c connection information + * @param secret secret if found, chunk_empty otherwise + * @return TRUE if a matching secret was found + */ + bool (*get_secret)(xauth_provider_t *this, connection_t *c, chunk_t *secret); + + /** + * Destroy an xauth_provider instance. + */ + void (*destroy)(xauth_provider_t *this); +}; + +/** + * Create an xauth_provider instance. + */ +xauth_provider_t *xauth_provider_create(); + +#endif /** XAUTH_PROVIDER_H_ @}*/ + diff --git a/src/pluto/xauth/xauth_verifier.h b/src/pluto/xauth/xauth_verifier.h new file mode 100644 index 000000000..7c9ff3a7f --- /dev/null +++ b/src/pluto/xauth/xauth_verifier.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2010 Andreas Steffen + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * 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 xauth_verifier xauth_verifier + * @{ @ingroup xauth + */ + +#ifndef XAUTH_VERIFIER_H_ +#define XAUTH_VERIFIER_H_ + +#include <library.h> + +#include <connections.h> + +typedef struct xauth_verifier_t xauth_verifier_t; + +/** + * An xauth verifier verifies xauth user secrets on the server side. + */ +struct xauth_verifier_t { + + /** + * Verify an XAUTH user secret base on connection information + * + * @param c connection information + * @param secret secret to be compared + * @return TRUE if secret matches + */ + bool (*verify_secret)(xauth_verifier_t *this, connection_t *c, chunk_t secret); + + /** + * Destroy an xauth_verifier instance. + */ + void (*destroy)(xauth_verifier_t *this); +}; + +/** + * Create an xauth_verifier instance. + */ +xauth_verifier_t *xauth_verifier_create(); + +#endif /** XAUTH_VERIFIER_H_ @}*/ + |