diff options
Diffstat (limited to 'src/charon/plugins/eap_sim')
-rw-r--r-- | src/charon/plugins/eap_sim/Makefile.am | 15 | ||||
-rw-r--r-- | src/charon/plugins/eap_sim/Makefile.in | 184 | ||||
-rw-r--r-- | src/charon/plugins/eap_sim/eap_sim.c | 1149 | ||||
-rw-r--r-- | src/charon/plugins/eap_sim/eap_sim_peer.c | 654 | ||||
-rw-r--r-- | src/charon/plugins/eap_sim/eap_sim_peer.h | 57 | ||||
-rw-r--r-- | src/charon/plugins/eap_sim/eap_sim_plugin.c | 19 | ||||
-rw-r--r-- | src/charon/plugins/eap_sim/eap_sim_server.c | 611 | ||||
-rw-r--r-- | src/charon/plugins/eap_sim/eap_sim_server.h (renamed from src/charon/plugins/eap_sim/eap_sim.h) | 44 |
8 files changed, 1485 insertions, 1248 deletions
diff --git a/src/charon/plugins/eap_sim/Makefile.am b/src/charon/plugins/eap_sim/Makefile.am index e503bddab..74b9bb4e8 100644 --- a/src/charon/plugins/eap_sim/Makefile.am +++ b/src/charon/plugins/eap_sim/Makefile.am @@ -1,11 +1,14 @@ -INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon +INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon \ + -I$(top_srcdir)/src/libsimaka -AM_CFLAGS = -rdynamic -DIPSEC_CONFDIR=\"${confdir}\" -DSIM_READER_LIB=\"${simreader}\" +AM_CFLAGS = -rdynamic -plugin_LTLIBRARIES = libstrongswan-eapsim.la +plugin_LTLIBRARIES = libstrongswan-eap-sim.la -libstrongswan_eapsim_la_SOURCES = eap_sim.h eap_sim.c \ - eap_sim_plugin.h eap_sim_plugin.c -libstrongswan_eapsim_la_LDFLAGS = -module -avoid-version +libstrongswan_eap_sim_la_SOURCES = eap_sim_plugin.h eap_sim_plugin.c \ + eap_sim_peer.h eap_sim_peer.c \ + eap_sim_server.h eap_sim_server.c +libstrongswan_eap_sim_la_LIBADD = $(top_builddir)/src/libsimaka/libsimaka.la +libstrongswan_eap_sim_la_LDFLAGS = -module -avoid-version diff --git a/src/charon/plugins/eap_sim/Makefile.in b/src/charon/plugins/eap_sim/Makefile.in index 8f6daacad..d9b568a42 100644 --- a/src/charon/plugins/eap_sim/Makefile.in +++ b/src/charon/plugins/eap_sim/Makefile.in @@ -1,8 +1,9 @@ -# Makefile.in generated by automake 1.10.2 from Makefile.am. +# Makefile.in generated by automake 1.11 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. @@ -16,8 +17,9 @@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c @@ -35,30 +37,55 @@ host_triplet = @host@ subdir = src/charon/plugins/eap_sim DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \ + $(top_srcdir)/m4/config/ltoptions.m4 \ + $(top_srcdir)/m4/config/ltsugar.m4 \ + $(top_srcdir)/m4/config/ltversion.m4 \ + $(top_srcdir)/m4/config/lt~obsolete.m4 \ + $(top_srcdir)/m4/macros/with.m4 \ + $(top_srcdir)/m4/macros/enable-disable.m4 \ + $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; -am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__installdirs = "$(DESTDIR)$(plugindir)" -pluginLTLIBRARIES_INSTALL = $(INSTALL) LTLIBRARIES = $(plugin_LTLIBRARIES) -libstrongswan_eapsim_la_LIBADD = -am_libstrongswan_eapsim_la_OBJECTS = eap_sim.lo eap_sim_plugin.lo -libstrongswan_eapsim_la_OBJECTS = \ - $(am_libstrongswan_eapsim_la_OBJECTS) -libstrongswan_eapsim_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ +libstrongswan_eap_sim_la_DEPENDENCIES = \ + $(top_builddir)/src/libsimaka/libsimaka.la +am_libstrongswan_eap_sim_la_OBJECTS = eap_sim_plugin.lo \ + eap_sim_peer.lo eap_sim_server.lo +libstrongswan_eap_sim_la_OBJECTS = \ + $(am_libstrongswan_eap_sim_la_OBJECTS) +libstrongswan_eap_sim_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ - $(libstrongswan_eapsim_la_LDFLAGS) $(LDFLAGS) -o $@ + $(libstrongswan_eap_sim_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) \ @@ -68,8 +95,8 @@ CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ -SOURCES = $(libstrongswan_eapsim_la_SOURCES) -DIST_SOURCES = $(libstrongswan_eapsim_la_SOURCES) +SOURCES = $(libstrongswan_eap_sim_la_SOURCES) +DIST_SOURCES = $(libstrongswan_eap_sim_la_SOURCES) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) @@ -106,25 +133,22 @@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -IPSEC_ROUTING_TABLE = @IPSEC_ROUTING_TABLE@ -IPSEC_ROUTING_TABLE_PRIO = @IPSEC_ROUTING_TABLE_PRIO@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ -LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ -LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ -LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ -LINUX_HEADERS = @LINUX_HEADERS@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ +MYSQLCFLAG = @MYSQLCFLAG@ +MYSQLCONFIG = @MYSQLCONFIG@ +MYSQLLIB = @MYSQLLIB@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ @@ -136,11 +160,14 @@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PKG_CONFIG = @PKG_CONFIG@ +PTHREADLIB = @PTHREADLIB@ RANLIB = @RANLIB@ +RTLIB = @RTLIB@ RUBY = @RUBY@ RUBYINCLUDE = @RUBYINCLUDE@ SED = @SED@ @@ -169,9 +196,9 @@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ -confdir = @confdir@ datadir = @datadir@ datarootdir = @datarootdir@ +default_pkcs11 = @default_pkcs11@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ @@ -194,7 +221,7 @@ ipsecuser = @ipsecuser@ libdir = @libdir@ libexecdir = @libexecdir@ libstrongswan_plugins = @libstrongswan_plugins@ -linuxdir = @linuxdir@ +linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ lt_ECHO = @lt_ECHO@ @@ -202,6 +229,7 @@ mandir = @mandir@ mkdir_p = @mkdir_p@ nm_CFLAGS = @nm_CFLAGS@ nm_LIBS = @nm_LIBS@ +nm_ca_dir = @nm_ca_dir@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ piddir = @piddir@ @@ -210,10 +238,12 @@ pluto_plugins = @pluto_plugins@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ +random_device = @random_device@ resolv_conf = @resolv_conf@ +routing_table = @routing_table@ +routing_table_prio = @routing_table_prio@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ -simreader = @simreader@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ @@ -221,15 +251,20 @@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ +urandom_device = @urandom_device@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ -INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon -AM_CFLAGS = -rdynamic -DIPSEC_CONFDIR=\"${confdir}\" -DSIM_READER_LIB=\"${simreader}\" -plugin_LTLIBRARIES = libstrongswan-eapsim.la -libstrongswan_eapsim_la_SOURCES = eap_sim.h eap_sim.c \ - eap_sim_plugin.h eap_sim_plugin.c +INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon \ + -I$(top_srcdir)/src/libsimaka + +AM_CFLAGS = -rdynamic +plugin_LTLIBRARIES = libstrongswan-eap-sim.la +libstrongswan_eap_sim_la_SOURCES = eap_sim_plugin.h eap_sim_plugin.c \ + eap_sim_peer.h eap_sim_peer.c \ + eap_sim_server.h eap_sim_server.c -libstrongswan_eapsim_la_LDFLAGS = -module -avoid-version +libstrongswan_eap_sim_la_LIBADD = $(top_builddir)/src/libsimaka/libsimaka.la +libstrongswan_eap_sim_la_LDFLAGS = -module -avoid-version all: all-am .SUFFIXES: @@ -243,9 +278,9 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) exit 1;; \ esac; \ done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/charon/plugins/eap_sim/Makefile'; \ - cd $(top_srcdir) && \ - $(AUTOMAKE) --gnu src/charon/plugins/eap_sim/Makefile + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/charon/plugins/eap_sim/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/charon/plugins/eap_sim/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ @@ -263,23 +298,28 @@ $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) @$(NORMAL_INSTALL) test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)" - @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \ + @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ + list2=; for p in $$list; do \ if test -f $$p; then \ - f=$(am__strip_dir) \ - echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(pluginLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(plugindir)/$$f'"; \ - $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(pluginLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(plugindir)/$$f"; \ + list2="$$list2 $$p"; \ else :; fi; \ - done + done; \ + test -z "$$list2" || { \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \ + } uninstall-pluginLTLIBRARIES: @$(NORMAL_UNINSTALL) - @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \ - p=$(am__strip_dir) \ - echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$p'"; \ - $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$p"; \ + @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \ done clean-pluginLTLIBRARIES: @@ -290,8 +330,8 @@ clean-pluginLTLIBRARIES: echo "rm -f \"$${dir}/so_locations\""; \ rm -f "$${dir}/so_locations"; \ done -libstrongswan-eapsim.la: $(libstrongswan_eapsim_la_OBJECTS) $(libstrongswan_eapsim_la_DEPENDENCIES) - $(libstrongswan_eapsim_la_LINK) -rpath $(plugindir) $(libstrongswan_eapsim_la_OBJECTS) $(libstrongswan_eapsim_la_LIBADD) $(LIBS) +libstrongswan-eap-sim.la: $(libstrongswan_eap_sim_la_OBJECTS) $(libstrongswan_eap_sim_la_DEPENDENCIES) + $(libstrongswan_eap_sim_la_LINK) -rpath $(plugindir) $(libstrongswan_eap_sim_la_OBJECTS) $(libstrongswan_eap_sim_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) @@ -299,26 +339,27 @@ mostlyclean-compile: distclean-compile: -rm -f *.tab.c -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_sim.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_sim_peer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_sim_plugin.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_sim_server.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< @@ -341,7 +382,7 @@ tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) - tags=; \ + set x; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ @@ -349,29 +390,34 @@ TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ - if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - $$tags $$unique; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) - tags=; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ - test -z "$(CTAGS_ARGS)$$tags$$unique" \ + test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ - $$tags $$unique + $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ - && cd $(top_srcdir) \ - && gtags -i $(GTAGS_ARGS) $$here + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags @@ -392,13 +438,17 @@ distdir: $(DISTFILES) if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ - cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ - test -f $(distdir)/$$file \ - || cp -p $$d/$$file $(distdir)/$$file \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @@ -429,6 +479,7 @@ clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @@ -450,6 +501,8 @@ dvi-am: html: html-am +html-am: + info: info-am info-am: @@ -458,18 +511,28 @@ install-data-am: install-pluginLTLIBRARIES install-dvi: install-dvi-am +install-dvi-am: + install-exec-am: install-html: install-html-am +install-html-am: + install-info: install-info-am +install-info-am: + install-man: install-pdf: install-pdf-am +install-pdf-am: + install-ps: install-ps-am +install-ps-am: + installcheck-am: maintainer-clean: maintainer-clean-am @@ -508,6 +571,7 @@ uninstall-am: uninstall-pluginLTLIBRARIES mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags uninstall uninstall-am uninstall-pluginLTLIBRARIES + # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: diff --git a/src/charon/plugins/eap_sim/eap_sim.c b/src/charon/plugins/eap_sim/eap_sim.c deleted file mode 100644 index 2dd6e534b..000000000 --- a/src/charon/plugins/eap_sim/eap_sim.c +++ /dev/null @@ -1,1149 +0,0 @@ -/* - * Copyright (C) 2007 Martin Willi - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#include "eap_sim.h" - -#include <dlfcn.h> - -#include <daemon.h> -#include <library.h> - -#define MAX_TRIES 3 - -/* number of triplets for one authentication */ -#define TRIPLET_COUNT 3 - -typedef enum sim_subtype_t sim_subtype_t; - -/** - * Subtypes of SIM messages - */ -enum sim_subtype_t { - SIM_START = 10, - SIM_CHALLENGE = 11, - SIM_NOTIFICATION = 12, - SIM_CLIENT_ERROR = 14, -}; - -ENUM(sim_subtype_names, SIM_START, SIM_CLIENT_ERROR, - "SIM_START", - "SIM_CHALLENGE", - "SIM_NOTIFICATION", - "SIM_13", - "SIM_CLIENT_ERROR", -); - -typedef enum sim_attribute_t sim_attribute_t; - -/** - * Attributes in SIM messages - */ -enum sim_attribute_t { - /** defines the end of attribute list */ - AT_END = -1, - AT_RAND = 1, - AT_AUTN = 2, - AT_RES = 3, - AT_AUTS = 4, - AT_PADDING = 6, - AT_NONCE_MT = 7, - AT_PERMANENT_ID_REQ = 10, - AT_MAC = 11, - AT_NOTIFICATION = 12, - AT_ANY_ID_REQ = 13, - AT_IDENTITY = 14, - AT_VERSION_LIST = 15, - AT_SELECTED_VERSION = 16, - AT_FULLAUTH_ID_REQ = 17, - AT_COUNTER = 19, - AT_COUNTER_TOO_SMALL = 20, - AT_NONCE_S = 21, - AT_CLIENT_ERROR_CODE = 22, - AT_IV = 129, - AT_ENCR_DATA = 130, - AT_NEXT_PSEUDONYM = 132, - AT_NEXT_REAUTH_ID = 133, - AT_CHECKCODE = 134, - AT_RESULT_IND = 135, -}; - -ENUM_BEGIN(sim_attribute_names, AT_END, AT_CLIENT_ERROR_CODE, - "AT_END", - "AT_0", - "AT_RAND", - "AT_AUTN", - "AT_RES", - "AT_AUTS", - "AT_5", - "AT_PADDING", - "AT_NONCE_MT", - "AT_8", - "AT_9", - "AT_PERMANENT_ID_REQ", - "AT_MAC", - "AT_NOTIFICATION", - "AT_ANY_ID_REQ", - "AT_IDENTITY", - "AT_VERSION_LIST", - "AT_SELECTED_VERSION", - "AT_FULLAUTH_ID_REQ", - "AT_18", - "AT_COUNTER", - "AT_COUNTER_TOO_SMALL", - "AT_NONCE_S", - "AT_CLIENT_ERROR_CODE"); -ENUM_NEXT(sim_attribute_names, AT_IV, AT_RESULT_IND, AT_CLIENT_ERROR_CODE, - "AT_IV", - "AT_ENCR_DATA", - "AT_131", - "AT_NEXT_PSEUDONYM", - "AT_NEXT_REAUTH_ID", - "AT_CHECKCODE", - "AT_RESULT_IND"); -ENUM_END(sim_attribute_names, AT_RESULT_IND); - - -typedef struct private_eap_sim_t private_eap_sim_t; - -/** - * Private data of an eap_sim_t object. - */ -struct private_eap_sim_t { - - /** - * Public authenticator_t interface. - */ - eap_sim_t public; - - /** - * ID of ourself - */ - identification_t *peer; - - /** - * hashing function - */ - hasher_t *hasher; - - /** - * prf - */ - prf_t *prf; - - /** - * MAC function - */ - signer_t *signer; - - /** - * how many times we try to authenticate - */ - int tries; - - /** - * unique EAP identifier - */ - u_int8_t identifier; - - /** - * EAP message type this role sends - */ - u_int8_t type; - - /** - * version this implementation uses - */ - chunk_t version; - - /** - * version list received from server - */ - chunk_t version_list; - - /** - * Nonce value used in AT_NONCE_MT - */ - chunk_t nonce; - - /** - * concatenated SRES values - */ - chunk_t sreses; - - /** - * k_encr key derived from MK - */ - chunk_t k_encr; - - /** - * k_auth key derived from MK, used for AT_MAC verification - */ - chunk_t k_auth; - - /** - * MSK, used for EAP-SIM based IKEv2 authentication - */ - chunk_t msk; - - /** - * EMSK, extended MSK for further uses - */ - chunk_t emsk; -}; - -/** length of the AT_NONCE_MT nonce value */ -#define NONCE_LEN 16 -/** length of the AT_MAC value */ -#define MAC_LEN 16 -/** length of the AT_RAND value */ -#define RAND_LEN 16 -/** length of Kc */ -#define KC_LEN 8 -/** length of SRES */ -#define SRES_LEN 4 -/** length of the k_encr key */ -#define KENCR_LEN 16 -/** length of the k_auth key */ -#define KAUTH_LEN 16 -/** length of the MSK */ -#define MSK_LEN 64 -/** length of the EMSK */ -#define EMSK_LEN 64 - -static char version[] = {0x00,0x01}; -/* client error codes used in AT_CLIENT_ERROR_CODE */ -char client_error_general_buf[] = {0x00, 0x01}; -char client_error_unsupported_buf[] = {0x00, 0x02}; -char client_error_insufficient_buf[] = {0x00, 0x03}; -char client_error_notfresh_buf[] = {0x00, 0x04}; -chunk_t client_error_general = chunk_from_buf(client_error_general_buf); -chunk_t client_error_unsupported = chunk_from_buf(client_error_unsupported_buf); -chunk_t client_error_insufficient = chunk_from_buf(client_error_insufficient_buf); -chunk_t client_error_notfresh = chunk_from_buf(client_error_notfresh_buf); - -/** - * Read EAP and EAP-SIM header, return SIM type - */ -static sim_subtype_t read_header(chunk_t *message) -{ - sim_subtype_t type; - - if (message->len < 8) - { - *message = chunk_empty; - return 0; - } - type = *(message->ptr + 5); - *message = chunk_skip(*message, 8); - return type; -} - -/** - * read the next attribute from the chunk data - */ -static sim_attribute_t read_attribute(chunk_t *message, chunk_t *data) -{ - sim_attribute_t attribute; - size_t length; - - DBG3(DBG_IKE, "reading attribute from %B", message); - - if (message->len < 2) - { - return AT_END; - } - attribute = *message->ptr++; - length = *message->ptr++ * 4 - 2; - message->len -= 2; - DBG3(DBG_IKE, "found attribute %N with length %d", - sim_attribute_names, attribute, length); - - if (length > message->len) - { - return AT_END; - } - data->len = length; - data->ptr = message->ptr; - *message = chunk_skip(*message, length); - return attribute; -} - -/** - * Build an EAP-SIM payload using a variable length attribute list. - * The variable argument takes a sim_attribute_t followed by its data in a chunk. - */ -static eap_payload_t *build_payload(private_eap_sim_t *this, u_int8_t identifier, - sim_subtype_t type, ...) -{ - chunk_t message = chunk_alloca(512); - chunk_t pos = message; - eap_payload_t *payload; - va_list args; - sim_attribute_t attr; - u_int8_t *mac_pos = NULL; - chunk_t mac_data = chunk_empty; - - /* write EAP header, skip length bytes */ - *pos.ptr++ = this->type; - *pos.ptr++ = identifier; - pos.ptr += 2; - pos.len -= 4; - /* write SIM header with type and subtype, zero reserved bytes */ - *pos.ptr++ = EAP_SIM; - *pos.ptr++ = type; - *pos.ptr++ = 0; - *pos.ptr++ = 0; - pos.len -= 4; - - va_start(args, type); - while ((attr = va_arg(args, sim_attribute_t)) != AT_END) - { - chunk_t data = va_arg(args, chunk_t); - - DBG3(DBG_IKE, "building %N %B", sim_attribute_names, attr, &data); - - /* write attribute header */ - *pos.ptr++ = attr; - pos.len--; - - switch (attr) - { - case AT_CLIENT_ERROR_CODE: - case AT_SELECTED_VERSION: - { - *pos.ptr = data.len/4 + 1; - pos = chunk_skip(pos, 1); - memcpy(pos.ptr, data.ptr, data.len); - pos = chunk_skip(pos, data.len); - break; - } - case AT_IDENTITY: - case AT_VERSION_LIST: - { - u_int16_t act_len = data.len; - /* align up to four byte */ - if (data.len % 4) - { - chunk_t tmp = chunk_alloca((data.len/4)*4 + 4); - memset(tmp.ptr, 0, tmp.len); - memcpy(tmp.ptr, data.ptr, data.len); - data = tmp; - } - *pos.ptr = data.len/4 + 1; - pos = chunk_skip(pos, 1); - /* actual length in bytes */ - *(u_int16_t*)pos.ptr = htons(act_len); - pos = chunk_skip(pos, sizeof(u_int16_t)); - memcpy(pos.ptr, data.ptr, data.len); - pos = chunk_skip(pos, data.len); - break; - } - case AT_NONCE_MT: - { - *pos.ptr = data.len/4 + 1; - pos = chunk_skip(pos, 1); - memset(pos.ptr, 0, 2); - pos = chunk_skip(pos, 2); - memcpy(pos.ptr, data.ptr, data.len); - pos = chunk_skip(pos, data.len); - break; - } - case AT_MAC: - { - *pos.ptr++ = 5; pos.len--; - *pos.ptr++ = 0; pos.len--; - *pos.ptr++ = 0; pos.len--; - mac_pos = pos.ptr; - memset(mac_pos, 0, MAC_LEN); - pos = chunk_skip(pos, MAC_LEN); - mac_data = data; - break; - } - case AT_RAND: - { - *pos.ptr++ = data.len/4 + 1; pos.len--; - *pos.ptr++ = 0; pos.len--; - *pos.ptr++ = 0; pos.len--; - memcpy(pos.ptr, data.ptr, data.len); - pos = chunk_skip(pos, data.len); - break; - } - default: - DBG1(DBG_IKE, "no rule to build EAP_SIM attribute %N, skipped", - sim_attribute_names, attr); - break; - } - } - va_end(args); - - /* calculate message length, write into header */ - message.len = pos.ptr - message.ptr; - *(u_int16_t*)(message.ptr + 2) = htons(message.len); - - /* create MAC if AT_MAC attribte was included. Append supplied va_arg - * chunk mac_data to "to-sign" chunk */ - if (mac_pos) - { - this->signer->set_key(this->signer, this->k_auth); - mac_data = chunk_cata("cc", message, mac_data); - this->signer->get_signature(this->signer, mac_data, mac_pos); - DBG3(DBG_IKE, "AT_MAC signature of %B\n is %b", - &mac_data, mac_pos, MAC_LEN); - } - - payload = eap_payload_create_data(message); - - DBG3(DBG_IKE, "created EAP message %B", &message); - return payload; -} - -/** - * process an EAP-SIM/Request/Start message - */ -static status_t peer_process_start(private_eap_sim_t *this, eap_payload_t *in, - eap_payload_t **out) -{ - chunk_t message, data; - sim_attribute_t attribute, include_id = AT_END; - u_int8_t identifier; - - identifier = in->get_identifier(in); - message = in->get_data(in); - read_header(&message); - - while ((attribute = read_attribute(&message, &data)) != AT_END) - { - switch (attribute) - { - case AT_VERSION_LIST: - { - /* check if server supports our implementation */ - bool found = FALSE; - if (data.len > 2) - { - /* read actual length first */ - data.len = min(data.len, ntohs(*(u_int16_t*)data.ptr) + 2); - data = chunk_skip(data, 2); - chunk_free(&this->version_list); - this->version_list = chunk_clone(data); - while (data.len >= this->version.len) - { - if (memeq(data.ptr, this->version.ptr, this->version.len)) - { - found = TRUE; - break; - } - data = chunk_skip(data, this->version.len); - } - } - if (!found) - { - DBG1(DBG_IKE, "server does not support EAP_SIM " - "version number %#B", &this->version); - *out = build_payload(this, identifier, SIM_CLIENT_ERROR, - AT_CLIENT_ERROR_CODE, client_error_unsupported, - AT_END); - return NEED_MORE; - } - break; - } - case AT_PERMANENT_ID_REQ: - case AT_FULLAUTH_ID_REQ: - case AT_ANY_ID_REQ: - /* only include AT_IDENTITY if requested */ - include_id = AT_IDENTITY; - break; - case AT_NOTIFICATION: - { - u_int16_t code = 0; - if (data.len == 2) - { - code = ntohs(*(u_int16_t*)data.ptr); - } - if (code <= 32767) /* no success bit */ - { - DBG1(DBG_IKE, "received %N error %d", - sim_attribute_names, attribute, code); - *out = build_payload(this, - in->get_identifier(in), SIM_CLIENT_ERROR, - AT_CLIENT_ERROR_CODE, client_error_general, - AT_END); - return NEED_MORE; - } - else - { - DBG1(DBG_IKE, "received %N code %d", - sim_attribute_names, attribute, code); - } - break; - } - default: - DBG1(DBG_IKE, "ignoring EAP_SIM attribute %N", - sim_attribute_names, attribute); - break; - } - } - - /* build payload. If "include_id" is AT_END, AT_IDENTITY is ommited */ - *out = build_payload(this, identifier, SIM_START, - AT_SELECTED_VERSION, this->version, - AT_NONCE_MT, this->nonce, - include_id, this->peer->get_encoding(this->peer), - AT_END); - return NEED_MORE; -} - -/** - * derive EAP keys from kc - */ -static void derive_keys(private_eap_sim_t *this, chunk_t kcs) -{ - chunk_t tmp, mk; - int i; - - /* build MK = SHA1(Identity|n*Kc|NONCE_MT|Version List|Selected Version) */ - tmp = chunk_cata("ccccc", this->peer->get_encoding(this->peer), kcs, - this->nonce, this->version_list, this->version); - mk = chunk_alloca(this->hasher->get_hash_size(this->hasher)); - this->hasher->get_hash(this->hasher, tmp, mk.ptr); - DBG3(DBG_IKE, "MK = SHA1(%B\n) = %B", &tmp, &mk); - - /* K_encr | K_auth | MSK | EMSK = prf() | prf() | prf() | prf() - * FIPS PRF has 320 bit block size, we need 160 byte for keys - * => run prf four times */ - this->prf->set_key(this->prf, mk); - tmp = chunk_alloca(this->prf->get_block_size(this->prf) * 4); - for (i = 0; i < 4; i++) - { - this->prf->get_bytes(this->prf, chunk_empty, tmp.ptr + tmp.len / 4 * i); - } - chunk_free(&this->k_encr); - chunk_free(&this->k_auth); - chunk_free(&this->msk); - chunk_free(&this->emsk); - chunk_split(tmp, "aaaa", KENCR_LEN, &this->k_encr, KAUTH_LEN, &this->k_auth, - MSK_LEN, &this->msk, EMSK_LEN, &this->emsk); - DBG3(DBG_IKE, "K_encr %B\nK_auth %B\nMSK %B\nEMSK %B", - &this->k_encr, &this->k_auth, &this->msk, &this->emsk); -} - -/** - * Read a triplet from the SIM card - */ -static bool get_card_triplet(private_eap_sim_t *this, - char *rand, char *sres, char *kc) -{ - enumerator_t *enumerator; - sim_card_t *card = NULL, *current; - id_match_t match, best = ID_MATCH_NONE; - bool success = FALSE; - - /* find the best matching SIM */ - enumerator = charon->sim->create_card_enumerator(charon->sim); - while (enumerator->enumerate(enumerator, ¤t)) - { - match = this->peer->matches(this->peer, current->get_imsi(current)); - if (match > best) - { - card = current; - best = match; - break; - } - } - if (card) - { - success = card->get_triplet(card, rand, sres, kc); - } - enumerator->destroy(enumerator); - if (!card) - { - DBG1(DBG_IKE, "no SIM card found matching '%Y'", this->peer); - } - return success; -} - -/** - * process an EAP-SIM/Request/Challenge message - */ -static status_t peer_process_challenge(private_eap_sim_t *this, - eap_payload_t *in, eap_payload_t **out) -{ - chunk_t message, data, tmp, kcs, kc, sreses, sres; - sim_attribute_t attribute; - u_int8_t identifier; - chunk_t mac = chunk_empty, rands = chunk_empty; - - if (this->tries-- <= 0) - { - /* give up without notification. This hack is required as some buggy - * server implementations won't respect our client-error. */ - return FAILED; - } - - identifier = in->get_identifier(in); - message = in->get_data(in); - read_header(&message); - - while ((attribute = read_attribute(&message, &data)) != AT_END) - { - switch (attribute) - { - case AT_RAND: - { - rands = chunk_skip(data, 2); - break; - } - case AT_MAC: - { - /* backup MAC, zero it inline for later verification */ - data = chunk_skip(data, 2); - mac = chunk_clonea(data); - memset(data.ptr, 0, data.len); - break; - } - case AT_NOTIFICATION: - { - u_int16_t code = 0; - if (data.len == 2) - { - code = ntohs(*(u_int16_t*)data.ptr); - } - if (code <= 32767) /* no success bit */ - { - DBG1(DBG_IKE, "received %N error %d", - sim_attribute_names, attribute, code); - *out = build_payload(this, - in->get_identifier(in), SIM_CLIENT_ERROR, - AT_CLIENT_ERROR_CODE, client_error_general, - AT_END); - return NEED_MORE; - } - else - { - DBG1(DBG_IKE, "received %N code %d", - sim_attribute_names, attribute, code); - } - break; - } - default: - DBG1(DBG_IKE, "ignoring EAP_SIM attribute %N", - sim_attribute_names, attribute); - break; - } - } - - /* excepting two or three RAND, each 16 bytes. We require two valid - * and different RANDs */ - if ((rands.len != 2 * RAND_LEN && rands.len != 3 * RAND_LEN) || - memeq(rands.ptr, rands.ptr + RAND_LEN, RAND_LEN)) - { - DBG1(DBG_IKE, "no valid AT_RAND received"); - *out = build_payload(this, identifier, SIM_CLIENT_ERROR, - AT_CLIENT_ERROR_CODE, client_error_insufficient, - AT_END); - return NEED_MORE; - } - if (mac.len != MAC_LEN) - { - DBG1(DBG_IKE, "no valid AT_MAC received"); - *out = build_payload(this, identifier, SIM_CLIENT_ERROR, - AT_CLIENT_ERROR_CODE, client_error_general, - AT_END); - return NEED_MORE; - } - - /* get two or three KCs/SRESes from SIM using RANDs */ - kcs = kc = chunk_alloca(rands.len / 2); - sreses = sres = chunk_alloca(rands.len / 4); - while (rands.len >= RAND_LEN) - { - if (!get_card_triplet(this, rands.ptr, sres.ptr, kc.ptr)) - { - DBG1(DBG_IKE, "unable to get EAP-SIM triplet"); - *out = build_payload(this, identifier, SIM_CLIENT_ERROR, - AT_CLIENT_ERROR_CODE, client_error_general, - AT_END); - return NEED_MORE; - } - DBG3(DBG_IKE, "got triplet for RAND %b\n Kc %b\n SRES %b", - rands.ptr, RAND_LEN, sres.ptr, SRES_LEN, kc.ptr, KC_LEN); - kc = chunk_skip(kc, KC_LEN); - sres = chunk_skip(sres, SRES_LEN); - rands = chunk_skip(rands, RAND_LEN); - } - - derive_keys(this, kcs); - - /* verify AT_MAC attribute, signature is over "EAP packet | NONCE_MT" */ - this->signer->set_key(this->signer, this->k_auth); - tmp = chunk_cata("cc", in->get_data(in), this->nonce); - if (!this->signer->verify_signature(this->signer, tmp, mac)) - { - DBG1(DBG_IKE, "AT_MAC verification failed"); - *out = build_payload(this, identifier, SIM_CLIENT_ERROR, - AT_CLIENT_ERROR_CODE, client_error_general, - AT_END); - return NEED_MORE; - } - - /* build response, AT_MAC is built over "EAP packet | n*SRES" */ - *out = build_payload(this, identifier, SIM_CHALLENGE, - AT_MAC, sreses, - AT_END); - return NEED_MORE; -} - -/** - * process an EAP-SIM/Response/Challenge message - */ -static status_t server_process_challenge(private_eap_sim_t *this, - eap_payload_t *in, eap_payload_t **out) -{ - chunk_t message, data; - sim_attribute_t attribute; - chunk_t mac = chunk_empty, tmp; - - message = in->get_data(in); - read_header(&message); - - while ((attribute = read_attribute(&message, &data)) != AT_END) - { - switch (attribute) - { - case AT_MAC: - /* MAC has two reserved bytes */ - if (data.len == MAC_LEN + 2) - { /* clone and zero MAC for verification */ - mac = chunk_clonea(chunk_skip(data, 2)); - memset(data.ptr, 0, data.len); - } - break; - default: - DBG1(DBG_IKE, "ignoring EAP_SIM attribute %N", - sim_attribute_names, attribute); - break; - } - } - if (!mac.ptr) - { - DBG1(DBG_IKE, "no valid AT_MAC attribute received"); - return FAILED; - } - /* verify AT_MAC attribute, signature is over "EAP packet | n*SRES" */ - this->signer->set_key(this->signer, this->k_auth); - tmp = chunk_cata("cc", in->get_data(in), this->sreses); - if (!this->signer->verify_signature(this->signer, tmp, mac)) - { - DBG1(DBG_IKE, "AT_MAC verification failed"); - return FAILED; - } - return SUCCESS; -} - -/** - * Fetch a triplet from a provider - */ -static bool get_provider_triplet(private_eap_sim_t *this, - char *rand, char *sres, char *kc) -{ - enumerator_t *enumerator; - sim_provider_t *provider; - int tried = 0; - - enumerator = charon->sim->create_provider_enumerator(charon->sim); - while (enumerator->enumerate(enumerator, &provider)) - { - if (provider->get_triplet(provider, this->peer, rand, sres, kc)) - { - enumerator->destroy(enumerator); - return TRUE; - } - tried++; - } - enumerator->destroy(enumerator); - DBG1(DBG_IKE, "tried %d SIM providers, but none had a triplet for '%Y'", - tried, this->peer); - return FALSE; -} - -/** - * process an EAP-SIM/Response/Start message - */ -static status_t server_process_start(private_eap_sim_t *this, - eap_payload_t *in, eap_payload_t **out) -{ - chunk_t message, data; - sim_attribute_t attribute; - bool supported = FALSE; - chunk_t rands, rand, kcs, kc, sreses, sres; - int i; - - message = in->get_data(in); - read_header(&message); - - while ((attribute = read_attribute(&message, &data)) != AT_END) - { - switch (attribute) - { - case AT_NONCE_MT: - if (data.len == NONCE_LEN + 2) - { - this->nonce = chunk_clone(chunk_skip(data, 2)); - } - break; - case AT_SELECTED_VERSION: - if (chunk_equals(data, this->version)) - { - supported = TRUE; - } - break; - default: - DBG1(DBG_IKE, "ignoring EAP_SIM attribute %N", - sim_attribute_names, attribute); - break; - } - } - if (!supported || !this->nonce.ptr) - { - DBG1(DBG_IKE, "received incomplete EAP-SIM/Response/Start"); - return FAILED; - } - - /* read triplets from provider */ - rand = rands = chunk_alloca(RAND_LEN * TRIPLET_COUNT); - kc = kcs = chunk_alloca(KC_LEN * TRIPLET_COUNT); - sres = sreses = chunk_alloca(SRES_LEN * TRIPLET_COUNT); - rands.len = 0; - kcs.len = 0; - sreses.len = 0; - for (i = 0; i < TRIPLET_COUNT; i++) - { - if (!get_provider_triplet(this, rand.ptr, sres.ptr, kc.ptr)) - { - DBG1(DBG_IKE, "getting EAP-SIM triplet %d failed", i); - return FAILED; - } - rands.len += RAND_LEN; - sreses.len += SRES_LEN; - kcs.len += KC_LEN; - rand = chunk_skip(rand, RAND_LEN); - sres = chunk_skip(sres, SRES_LEN); - kc = chunk_skip(kc, KC_LEN); - } - derive_keys(this, kcs); - - /* build MAC over "EAP packet | NONCE_MT" */ - *out = build_payload(this, this->identifier++, SIM_CHALLENGE, AT_RAND, - rands, AT_MAC, this->nonce, AT_END); - this->sreses = chunk_clone(sreses); - return NEED_MORE; -} - -/** - * process an EAP-SIM/Request/Notification message - */ -static status_t peer_process_notification(private_eap_sim_t *this, - eap_payload_t *in, eap_payload_t **out) -{ - chunk_t message, data; - sim_attribute_t attribute; - - message = in->get_data(in); - read_header(&message); - - while ((attribute = read_attribute(&message, &data)) != AT_END) - { - switch (attribute) - { - case AT_NOTIFICATION: - { - u_int16_t code = 0; - if (data.len == 2) - { - code = ntohs(*(u_int16_t*)data.ptr); - } - if (code <= 32767) /* no success bit */ - { - DBG1(DBG_IKE, "received %N error %d", - sim_attribute_names, attribute, code); - *out = build_payload(this, - in->get_identifier(in), SIM_CLIENT_ERROR, - AT_CLIENT_ERROR_CODE, client_error_general, - AT_END); - return NEED_MORE; - } - else - { - DBG1(DBG_IKE, "received %N code %d", - sim_attribute_names, attribute, code); - } - break; - } - default: - DBG1(DBG_IKE, "ignoring EAP_SIM attribute %N", - sim_attribute_names, attribute); - break; - } - } - /* reply with empty notification */ - *out = build_payload(this, in->get_identifier(in), SIM_NOTIFICATION, AT_END); - return NEED_MORE; -} - -/** - * Process a client error - */ -static status_t server_process_client_error(private_eap_sim_t *this, - eap_payload_t *in, eap_payload_t **out) -{ - chunk_t message, data; - sim_attribute_t attribute; - - message = in->get_data(in); - read_header(&message); - - while ((attribute = read_attribute(&message, &data)) != AT_END) - { - if (attribute == AT_CLIENT_ERROR_CODE) - { - u_int16_t code = 0; - if (data.len == 2) - { - code = ntohs(*(u_int16_t*)data.ptr); - } - DBG1(DBG_IKE, "received %N error %d", - sim_attribute_names, attribute, code); - } - else - { - DBG1(DBG_IKE, "ignoring EAP_SIM attribute %N", - sim_attribute_names, attribute); - } - } - return FAILED; -} - -/** - * Implementation of eap_method_t.process for the peer - */ -static status_t peer_process(private_eap_sim_t *this, - eap_payload_t *in, eap_payload_t **out) -{ - sim_subtype_t type; - chunk_t message; - - message = in->get_data(in); - type = read_header(&message); - - switch (type) - { - case SIM_START: - return peer_process_start(this, in, out); - case SIM_CHALLENGE: - return peer_process_challenge(this, in, out); - case SIM_NOTIFICATION: - return peer_process_notification(this, in, out); - default: - DBG1(DBG_IKE, "unable to process EAP_SIM subtype %N", - sim_subtype_names, type); - *out = build_payload(this, in->get_identifier(in), SIM_CLIENT_ERROR, - AT_CLIENT_ERROR_CODE, client_error_general, AT_END); - return NEED_MORE; - } -} - -/** - * Implementation of eap_method_t.process for the server - */ -static status_t server_process(private_eap_sim_t *this, - eap_payload_t *in, eap_payload_t **out) -{ - sim_subtype_t type; - chunk_t message; - - message = in->get_data(in); - type = read_header(&message); - - switch (type) - { - case SIM_START: - return server_process_start(this, in, out); - case SIM_CHALLENGE: - return server_process_challenge(this, in, out); - case SIM_CLIENT_ERROR: - return server_process_client_error(this, in, out); - default: - DBG1(DBG_IKE, "unable to process EAP_SIM subtype %N", - sim_subtype_names, type); - return FAILED; - } -} - -/** - * Implementation of eap_method_t.initiate for the peer - */ -static status_t peer_initiate(private_eap_sim_t *this, eap_payload_t **out) -{ - /* peer never initiates */ - return FAILED; -} - -/** - * Implementation of eap_method_t.initiate for the server - */ -static status_t server_initiate(private_eap_sim_t *this, eap_payload_t **out) -{ - /* version_list to derive MK, no padding */ - this->version_list = chunk_clone(this->version); - /* build_payloads adds padding itself */ - *out = build_payload(this, this->identifier++, SIM_START, - AT_VERSION_LIST, this->version, AT_END); - return NEED_MORE; -} - -/** - * Implementation of eap_method_t.get_type. - */ -static eap_type_t get_type(private_eap_sim_t *this, u_int32_t *vendor) -{ - *vendor = 0; - return EAP_SIM; -} - -/** - * Implementation of eap_method_t.get_msk. - */ -static status_t get_msk(private_eap_sim_t *this, chunk_t *msk) -{ - if (this->msk.ptr) - { - *msk = this->msk; - return SUCCESS; - } - return FAILED; -} - -/** - * Implementation of eap_method_t.is_mutual. - */ -static bool is_mutual(private_eap_sim_t *this) -{ - return TRUE; -} - -/** - * Implementation of eap_method_t.destroy. - */ -static void destroy(private_eap_sim_t *this) -{ - this->peer->destroy(this->peer); - DESTROY_IF(this->hasher); - DESTROY_IF(this->prf); - DESTROY_IF(this->signer); - chunk_free(&this->nonce); - chunk_free(&this->sreses); - chunk_free(&this->version_list); - chunk_free(&this->k_auth); - chunk_free(&this->k_encr); - chunk_free(&this->msk); - chunk_free(&this->emsk); - free(this); -} - -/** - * Generic constructor for both roles - */ -eap_sim_t *eap_sim_create_generic(eap_role_t role, identification_t *server, - identification_t *peer) -{ - private_eap_sim_t *this = malloc_thing(private_eap_sim_t); - rng_t *rng; - - this->nonce = chunk_empty; - this->sreses = chunk_empty; - this->peer = peer->clone(peer); - this->tries = MAX_TRIES; - this->version.ptr = version; - this->version.len = sizeof(version); - this->version_list = chunk_empty; - this->k_auth = chunk_empty; - this->k_encr = chunk_empty; - this->msk = chunk_empty; - this->emsk = chunk_empty; - /* generate a non-zero identifier */ - do { - this->identifier = random(); - } while (!this->identifier); - - switch (role) - { - case EAP_SERVER: - this->public.eap_method_interface.initiate = (status_t(*)(eap_method_t*,eap_payload_t**))server_initiate; - this->public.eap_method_interface.process = (status_t(*)(eap_method_t*,eap_payload_t*,eap_payload_t**))server_process; - this->type = EAP_REQUEST; - break; - case EAP_PEER: - this->public.eap_method_interface.initiate = (status_t(*)(eap_method_t*,eap_payload_t**))peer_initiate; - this->public.eap_method_interface.process = (status_t(*)(eap_method_t*,eap_payload_t*,eap_payload_t**))peer_process; - this->type = EAP_RESPONSE; - rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK); - if (!rng) - { - DBG1(DBG_IKE, "unable to generate NONCE for EAP_SIM"); - free(this); - return NULL; - } - rng->allocate_bytes(rng, NONCE_LEN, &this->nonce); - rng->destroy(rng); - break; - default: - free(this); - return NULL; - } - this->public.eap_method_interface.get_type = (eap_type_t(*)(eap_method_t*,u_int32_t*))get_type; - this->public.eap_method_interface.is_mutual = (bool(*)(eap_method_t*))is_mutual; - this->public.eap_method_interface.get_msk = (status_t(*)(eap_method_t*,chunk_t*))get_msk; - this->public.eap_method_interface.destroy = (void(*)(eap_method_t*))destroy; - - this->hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1); - this->prf = lib->crypto->create_prf(lib->crypto, PRF_FIPS_SHA1_160); - this->signer = lib->crypto->create_signer(lib->crypto, AUTH_HMAC_SHA1_128); - if (!this->hasher || !this->prf || !this->signer) - { - DBG1(DBG_IKE, "initiating EAP-SIM failed, FIPS-PRF/SHA1 not supported"); - destroy(this); - return NULL; - } - return &this->public; -} - -/* - * Described in header. - */ -eap_sim_t *eap_sim_create_server(identification_t *server, - identification_t *peer) -{ - return eap_sim_create_generic(EAP_SERVER, server, peer); -} - -/* - * Described in header. - */ -eap_sim_t *eap_sim_create_peer(identification_t *server, - identification_t *peer) -{ - return eap_sim_create_generic(EAP_PEER, server, peer); -} - diff --git a/src/charon/plugins/eap_sim/eap_sim_peer.c b/src/charon/plugins/eap_sim/eap_sim_peer.c new file mode 100644 index 000000000..961cfd30d --- /dev/null +++ b/src/charon/plugins/eap_sim/eap_sim_peer.c @@ -0,0 +1,654 @@ +/* + * Copyright (C) 2007-2009 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "eap_sim_peer.h" + +#include <daemon.h> + +#include <simaka_message.h> + +/* number of tries we do authenticate */ +#define MAX_TRIES 3 + +/* number of triplets for one authentication */ +#define TRIPLET_COUNT 3 + +/** length of the AT_NONCE_MT nonce value */ +#define NONCE_LEN 16 + +typedef struct private_eap_sim_peer_t private_eap_sim_peer_t; + +/** + * Private data of an eap_sim_peer_t object. + */ +struct private_eap_sim_peer_t { + + /** + * Public authenticator_t interface. + */ + eap_sim_peer_t public; + + /** + * permanent ID of peer + */ + identification_t *permanent; + + /** + * Pseudonym identity the peer uses + */ + identification_t *pseudonym; + + /** + * Reauthentication identity the peer uses + */ + identification_t *reauth; + + /** + * EAP-SIM crypto helper + */ + simaka_crypto_t *crypto; + + /** + * how many times we try to authenticate + */ + int tries; + + /** + * version list received from server + */ + chunk_t version_list; + + /** + * Nonce value used in AT_NONCE_MT/AT_NONCE_S + */ + chunk_t nonce; + + /** + * MSK, used for EAP-SIM based IKEv2 authentication + */ + chunk_t msk; + + /** + * Master key, if reauthentication is used + */ + char mk[HASH_SIZE_SHA1]; + + /** + * Counter value if reauthentication is used + */ + u_int16_t counter; +}; + +/* version of SIM protocol we speak */ +static chunk_t version = chunk_from_chars(0x00,0x01); + +/** + * Create a SIM_CLIENT_ERROR + */ +static eap_payload_t* create_client_error(private_eap_sim_peer_t *this, + u_int8_t identifier, simaka_client_error_t code) +{ + simaka_message_t *message; + eap_payload_t *out; + u_int16_t encoded; + + DBG1(DBG_IKE, "sending client error '%N'", simaka_client_error_names, code); + + message = simaka_message_create(FALSE, identifier, EAP_SIM, + SIM_CLIENT_ERROR, this->crypto); + encoded = htons(code); + message->add_attribute(message, AT_CLIENT_ERROR_CODE, + chunk_create((char*)&encoded, sizeof(encoded))); + out = message->generate(message, chunk_empty); + message->destroy(message); + return out; +} + +/** + * process an EAP-SIM/Request/Start message + */ +static status_t process_start(private_eap_sim_peer_t *this, + simaka_message_t *in, eap_payload_t **out) +{ + simaka_message_t *message; + enumerator_t *enumerator; + simaka_attribute_t type; + chunk_t data, id = chunk_empty; + rng_t *rng; + bool supported = FALSE; + simaka_attribute_t id_req = 0; + + /* reset previously uses reauthentication/pseudonym data */ + this->crypto->clear_keys(this->crypto); + DESTROY_IF(this->pseudonym); + this->pseudonym = NULL; + DESTROY_IF(this->reauth); + this->reauth = NULL; + + enumerator = in->create_attribute_enumerator(in); + while (enumerator->enumerate(enumerator, &type, &data)) + { + switch (type) + { + case AT_VERSION_LIST: + { + free(this->version_list.ptr); + this->version_list = chunk_clone(data); + while (data.len >= version.len) + { + if (memeq(data.ptr, version.ptr, version.len)) + { + supported = TRUE; + break; + } + } + break; + } + case AT_ANY_ID_REQ: + case AT_FULLAUTH_ID_REQ: + case AT_PERMANENT_ID_REQ: + id_req = type; + break; + default: + if (!simaka_attribute_skippable(type)) + { + *out = create_client_error(this, in->get_identifier(in), + SIM_UNABLE_TO_PROCESS); + enumerator->destroy(enumerator); + return NEED_MORE; + } + break; + } + } + enumerator->destroy(enumerator); + + if (!supported) + { + DBG1(DBG_IKE, "server does not support EAP-SIM version number 1"); + *out = create_client_error(this, in->get_identifier(in), + SIM_UNSUPPORTED_VERSION); + return NEED_MORE; + } + + switch (id_req) + { + case AT_ANY_ID_REQ: + this->reauth = charon->sim->card_get_reauth(charon->sim, + this->permanent, this->mk, &this->counter); + if (this->reauth) + { + id = this->reauth->get_encoding(this->reauth); + break; + } + /* FALL */ + case AT_FULLAUTH_ID_REQ: + this->pseudonym = charon->sim->card_get_pseudonym(charon->sim, + this->permanent); + if (this->pseudonym) + { + id = this->pseudonym->get_encoding(this->pseudonym); + break; + } + /* FALL */ + case AT_PERMANENT_ID_REQ: + id = this->permanent->get_encoding(this->permanent); + break; + default: + break; + } + + /* generate AT_NONCE_MT value */ + rng = this->crypto->get_rng(this->crypto); + free(this->nonce.ptr); + rng->allocate_bytes(rng, NONCE_LEN, &this->nonce); + + message = simaka_message_create(FALSE, in->get_identifier(in), EAP_SIM, + SIM_START, this->crypto); + if (!this->reauth) + { + message->add_attribute(message, AT_SELECTED_VERSION, version); + message->add_attribute(message, AT_NONCE_MT, this->nonce); + } + if (id.len) + { + message->add_attribute(message, AT_IDENTITY, id); + } + *out = message->generate(message, chunk_empty); + message->destroy(message); + + return NEED_MORE; +} + +/** + * process an EAP-SIM/Request/Challenge message + */ +static status_t process_challenge(private_eap_sim_peer_t *this, + simaka_message_t *in, eap_payload_t **out) +{ + simaka_message_t *message; + enumerator_t *enumerator; + simaka_attribute_t type; + chunk_t data, rands = chunk_empty, kcs, kc, sreses, sres, mk; + identification_t *id; + + if (this->tries-- <= 0) + { + /* give up without notification. This hack is required as some buggy + * server implementations won't respect our client-error. */ + return FAILED; + } + + enumerator = in->create_attribute_enumerator(in); + while (enumerator->enumerate(enumerator, &type, &data)) + { + switch (type) + { + case AT_RAND: + rands = data; + break; + default: + if (!simaka_attribute_skippable(type)) + { + *out = create_client_error(this, in->get_identifier(in), + SIM_UNABLE_TO_PROCESS); + enumerator->destroy(enumerator); + return NEED_MORE; + } + break; + } + } + enumerator->destroy(enumerator); + + /* excepting two or three RAND, each 16 bytes. We require two valid + * and different RANDs */ + if ((rands.len != 2 * SIM_RAND_LEN && rands.len != 3 * SIM_RAND_LEN) || + memeq(rands.ptr, rands.ptr + SIM_RAND_LEN, SIM_RAND_LEN)) + { + DBG1(DBG_IKE, "no valid AT_RAND received"); + *out = create_client_error(this, in->get_identifier(in), + SIM_INSUFFICIENT_CHALLENGES); + return NEED_MORE; + } + /* get two or three KCs/SRESes from SIM using RANDs */ + kcs = kc = chunk_alloca(rands.len / 2); + sreses = sres = chunk_alloca(rands.len / 4); + while (rands.len >= SIM_RAND_LEN) + { + if (!charon->sim->card_get_triplet(charon->sim, this->permanent, + rands.ptr, sres.ptr, kc.ptr)) + { + DBG1(DBG_IKE, "unable to get EAP-SIM triplet"); + *out = create_client_error(this, in->get_identifier(in), + SIM_UNABLE_TO_PROCESS); + return NEED_MORE; + } + DBG3(DBG_IKE, "got triplet for RAND %b\n Kc %b\n SRES %b", + rands.ptr, SIM_RAND_LEN, sres.ptr, SIM_SRES_LEN, kc.ptr, SIM_KC_LEN); + kc = chunk_skip(kc, SIM_KC_LEN); + sres = chunk_skip(sres, SIM_SRES_LEN); + rands = chunk_skip(rands, SIM_RAND_LEN); + } + + id = this->permanent; + if (this->pseudonym) + { + id = this->pseudonym; + } + data = chunk_cata("cccc", kcs, this->nonce, this->version_list, version); + free(this->msk.ptr); + this->msk = this->crypto->derive_keys_full(this->crypto, id, data, &mk); + memcpy(this->mk, mk.ptr, mk.len); + free(mk.ptr); + + /* Verify AT_MAC attribute, signature is over "EAP packet | NONCE_MT", and + * parse() again after key derivation, reading encrypted attributes */ + if (!in->verify(in, this->nonce) || !in->parse(in)) + { + *out = create_client_error(this, in->get_identifier(in), + SIM_UNABLE_TO_PROCESS); + return NEED_MORE; + } + + enumerator = in->create_attribute_enumerator(in); + while (enumerator->enumerate(enumerator, &type, &data)) + { + switch (type) + { + case AT_NEXT_REAUTH_ID: + this->counter = 0; + id = identification_create_from_data(data); + charon->sim->card_set_reauth(charon->sim, this->permanent, id, + this->mk, this->counter); + id->destroy(id); + break; + case AT_NEXT_PSEUDONYM: + id = identification_create_from_data(data); + charon->sim->card_set_pseudonym(charon->sim, this->permanent, id); + id->destroy(id); + break; + default: + break; + } + } + enumerator->destroy(enumerator); + + /* build response with AT_MAC, built over "EAP packet | n*SRES" */ + message = simaka_message_create(FALSE, in->get_identifier(in), EAP_SIM, + SIM_CHALLENGE, this->crypto); + *out = message->generate(message, sreses); + message->destroy(message); + return NEED_MORE; +} + +/** + * Check if a received counter value is acceptable + */ +static bool counter_too_small(private_eap_sim_peer_t *this, chunk_t chunk) +{ + u_int16_t counter; + + memcpy(&counter, chunk.ptr, sizeof(counter)); + counter = htons(counter); + return counter < this->counter; +} + +/** + * process an EAP-SIM/Request/Re-Authentication message + */ +static status_t process_reauthentication(private_eap_sim_peer_t *this, + simaka_message_t *in, eap_payload_t **out) +{ + simaka_message_t *message; + enumerator_t *enumerator; + simaka_attribute_t type; + chunk_t data, counter = chunk_empty, nonce = chunk_empty, id = chunk_empty; + + if (!this->reauth) + { + DBG1(DBG_IKE, "received %N, but not expected", + simaka_subtype_names, SIM_REAUTHENTICATION); + *out = create_client_error(this, in->get_identifier(in), + SIM_UNABLE_TO_PROCESS); + return NEED_MORE; + } + + this->crypto->derive_keys_reauth(this->crypto, + chunk_create(this->mk, HASH_SIZE_SHA1)); + + /* verify MAC and parse again with decryption key */ + if (!in->verify(in, chunk_empty) || !in->parse(in)) + { + *out = create_client_error(this, in->get_identifier(in), + SIM_UNABLE_TO_PROCESS); + return NEED_MORE; + } + + enumerator = in->create_attribute_enumerator(in); + while (enumerator->enumerate(enumerator, &type, &data)) + { + switch (type) + { + case AT_COUNTER: + counter = data; + break; + case AT_NONCE_S: + nonce = data; + break; + case AT_NEXT_REAUTH_ID: + id = data; + break; + default: + if (!simaka_attribute_skippable(type)) + { + *out = create_client_error(this, in->get_identifier(in), + SIM_UNABLE_TO_PROCESS); + enumerator->destroy(enumerator); + return NEED_MORE; + } + break; + } + } + enumerator->destroy(enumerator); + + if (!nonce.len || !counter.len) + { + DBG1(DBG_IKE, "EAP-SIM/Request/Re-Authentication message incomplete"); + *out = create_client_error(this, in->get_identifier(in), + SIM_UNABLE_TO_PROCESS); + return NEED_MORE; + } + + message = simaka_message_create(FALSE, in->get_identifier(in), EAP_SIM, + SIM_REAUTHENTICATION, this->crypto); + if (counter_too_small(this, counter)) + { + DBG1(DBG_IKE, "reauthentication counter too small"); + message->add_attribute(message, AT_COUNTER_TOO_SMALL, chunk_empty); + } + else + { + free(this->msk.ptr); + this->msk = this->crypto->derive_keys_reauth_msk(this->crypto, + this->reauth, counter, nonce, + chunk_create(this->mk, HASH_SIZE_SHA1)); + if (id.len) + { + identification_t *reauth; + + reauth = identification_create_from_data(data); + charon->sim->card_set_reauth(charon->sim, this->permanent, reauth, + this->mk, this->counter); + reauth->destroy(reauth); + } + } + message->add_attribute(message, AT_COUNTER, counter); + *out = message->generate(message, nonce); + message->destroy(message); + return NEED_MORE; +} + +/** + * process an EAP-SIM/Request/Notification message + */ +static status_t process_notification(private_eap_sim_peer_t *this, + simaka_message_t *in, eap_payload_t **out) +{ + simaka_message_t *message; + enumerator_t *enumerator; + simaka_attribute_t type; + chunk_t data; + bool success = TRUE; + + enumerator = in->create_attribute_enumerator(in); + while (enumerator->enumerate(enumerator, &type, &data)) + { + if (type == AT_NOTIFICATION) + { + u_int16_t code; + + memcpy(&code, data.ptr, sizeof(code)); + code = ntohs(code); + + /* test success bit */ + if (!(data.ptr[0] & 0x80)) + { + success = FALSE; + DBG1(DBG_IKE, "received EAP-SIM notification error '%N'", + simaka_notification_names, code); + } + else + { + DBG1(DBG_IKE, "received EAP-SIM notification '%N'", + simaka_notification_names, code); + } + } + else if (!simaka_attribute_skippable(type)) + { + success = FALSE; + break; + } + } + enumerator->destroy(enumerator); + + if (success) + { /* empty notification reply */ + message = simaka_message_create(FALSE, in->get_identifier(in), EAP_SIM, + SIM_NOTIFICATION, this->crypto); + *out = message->generate(message, chunk_empty); + message->destroy(message); + } + else + { + *out = create_client_error(this, in->get_identifier(in), + SIM_UNABLE_TO_PROCESS); + } + return NEED_MORE; +} + +/** + * Implementation of eap_method_t.process + */ +static status_t process(private_eap_sim_peer_t *this, + eap_payload_t *in, eap_payload_t **out) +{ + simaka_message_t *message; + status_t status; + + message = simaka_message_create_from_payload(in, this->crypto); + if (!message) + { + *out = create_client_error(this, in->get_identifier(in), + SIM_UNABLE_TO_PROCESS); + return NEED_MORE; + } + if (!message->parse(message)) + { + message->destroy(message); + *out = create_client_error(this, in->get_identifier(in), + SIM_UNABLE_TO_PROCESS); + return NEED_MORE; + } + switch (message->get_subtype(message)) + { + case SIM_START: + status = process_start(this, message, out); + break; + case SIM_CHALLENGE: + status = process_challenge(this, message, out); + break; + case SIM_REAUTHENTICATION: + status = process_reauthentication(this, message, out); + break; + case SIM_NOTIFICATION: + status = process_notification(this, message, out); + break; + default: + DBG1(DBG_IKE, "unable to process EAP-SIM subtype %N", + simaka_subtype_names, message->get_subtype(message)); + *out = create_client_error(this, in->get_identifier(in), + SIM_UNABLE_TO_PROCESS); + status = NEED_MORE; + break; + } + message->destroy(message); + return status; +} + +/** + * Implementation of eap_method_t.initiate + */ +static status_t initiate(private_eap_sim_peer_t *this, eap_payload_t **out) +{ + /* peer never initiates */ + return FAILED; +} + +/** + * Implementation of eap_method_t.get_type. + */ +static eap_type_t get_type(private_eap_sim_peer_t *this, u_int32_t *vendor) +{ + *vendor = 0; + return EAP_SIM; +} + +/** + * Implementation of eap_method_t.get_msk. + */ +static status_t get_msk(private_eap_sim_peer_t *this, chunk_t *msk) +{ + if (this->msk.ptr) + { + *msk = this->msk; + return SUCCESS; + } + return FAILED; +} + +/** + * Implementation of eap_method_t.is_mutual. + */ +static bool is_mutual(private_eap_sim_peer_t *this) +{ + return TRUE; +} + +/** + * Implementation of eap_method_t.destroy. + */ +static void destroy(private_eap_sim_peer_t *this) +{ + this->permanent->destroy(this->permanent); + DESTROY_IF(this->pseudonym); + DESTROY_IF(this->reauth); + this->crypto->destroy(this->crypto); + free(this->version_list.ptr); + free(this->nonce.ptr); + free(this->msk.ptr); + free(this); +} + +/* + * Described in header. + */ +eap_sim_peer_t *eap_sim_peer_create(identification_t *server, + identification_t *peer) +{ + private_eap_sim_peer_t *this = malloc_thing(private_eap_sim_peer_t); + + this->public.interface.initiate = (status_t(*)(eap_method_t*,eap_payload_t**))initiate; + this->public.interface.process = (status_t(*)(eap_method_t*,eap_payload_t*,eap_payload_t**))process; + this->public.interface.get_type = (eap_type_t(*)(eap_method_t*,u_int32_t*))get_type; + this->public.interface.is_mutual = (bool(*)(eap_method_t*))is_mutual; + this->public.interface.get_msk = (status_t(*)(eap_method_t*,chunk_t*))get_msk; + this->public.interface.destroy = (void(*)(eap_method_t*))destroy; + + this->crypto = simaka_crypto_create(); + if (!this->crypto) + { + free(this); + return NULL; + } + this->permanent = peer->clone(peer); + this->pseudonym = NULL; + this->reauth = NULL; + this->tries = MAX_TRIES; + this->version_list = chunk_empty; + this->nonce = chunk_empty; + this->msk = chunk_empty; + + return &this->public; +} + diff --git a/src/charon/plugins/eap_sim/eap_sim_peer.h b/src/charon/plugins/eap_sim/eap_sim_peer.h new file mode 100644 index 000000000..89f81301e --- /dev/null +++ b/src/charon/plugins/eap_sim/eap_sim_peer.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2009 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup eap_sim_peer eap_sim_peer + * @{ @ingroup eap_sim + */ + +#ifndef EAP_SIM_PEER_H_ +#define EAP_SIM_PEER_H_ + +#include <sa/authenticators/eap/eap_method.h> + +typedef struct eap_sim_peer_t eap_sim_peer_t; + +/** + * EAP-SIM peer implementation. + * + * This EAP-SIM module uses sim_card_t implementations for triplet calculation, + * found via the eap_sim_manager_t. + */ +struct eap_sim_peer_t { + + /** + * Implemented eap_method_t interface. + */ + eap_method_t interface; + + /** + * Destroy a eap_sim_peer_t. + */ + void (*destroy)(eap_sim_peer_t *this); +}; + +/** + * Creates the EAP method EAP-SIM acting as peer. + * + * @param server ID of the EAP server + * @param peer ID of the EAP peer + * @return eap_sim_t object + */ +eap_sim_peer_t *eap_sim_peer_create(identification_t *server, + identification_t *peer); + +#endif /** EAP_SIM_PEER_H_ @}*/ diff --git a/src/charon/plugins/eap_sim/eap_sim_plugin.c b/src/charon/plugins/eap_sim/eap_sim_plugin.c index cf18007c0..1d2b9cf4f 100644 --- a/src/charon/plugins/eap_sim/eap_sim_plugin.c +++ b/src/charon/plugins/eap_sim/eap_sim_plugin.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Martin Willi + * Copyright (C) 2008-2009 Martin Willi * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -15,7 +15,8 @@ #include "eap_sim_plugin.h" -#include "eap_sim.h" +#include "eap_sim_server.h" +#include "eap_sim_peer.h" #include <daemon.h> @@ -25,9 +26,9 @@ static void destroy(eap_sim_plugin_t *this) { charon->eap->remove_method(charon->eap, - (eap_constructor_t)eap_sim_create_server); + (eap_constructor_t)eap_sim_server_create); charon->eap->remove_method(charon->eap, - (eap_constructor_t)eap_sim_create_peer); + (eap_constructor_t)eap_sim_peer_create); free(this); } @@ -37,14 +38,14 @@ static void destroy(eap_sim_plugin_t *this) plugin_t *plugin_create() { eap_sim_plugin_t *this = malloc_thing(eap_sim_plugin_t); - + this->plugin.destroy = (void(*)(plugin_t*))destroy; - + charon->eap->add_method(charon->eap, EAP_SIM, 0, EAP_SERVER, - (eap_constructor_t)eap_sim_create_server); + (eap_constructor_t)eap_sim_server_create); charon->eap->add_method(charon->eap, EAP_SIM, 0, EAP_PEER, - (eap_constructor_t)eap_sim_create_peer); - + (eap_constructor_t)eap_sim_peer_create); + return &this->plugin; } diff --git a/src/charon/plugins/eap_sim/eap_sim_server.c b/src/charon/plugins/eap_sim/eap_sim_server.c new file mode 100644 index 000000000..f6d5df09b --- /dev/null +++ b/src/charon/plugins/eap_sim/eap_sim_server.c @@ -0,0 +1,611 @@ +/* + * Copyright (C) 2007-2009 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "eap_sim_server.h" + +#include <daemon.h> + +#include <simaka_message.h> +#include <simaka_crypto.h> + +/* number of triplets for one authentication */ +#define TRIPLET_COUNT 3 + +/** length of the AT_NONCE_S value */ +#define NONCE_LEN 16 + +typedef struct private_eap_sim_server_t private_eap_sim_server_t; + +/** + * Private data of an eap_sim_server_t object. + */ +struct private_eap_sim_server_t { + + /** + * Public authenticator_t interface. + */ + eap_sim_server_t public; + + /** + * permanent ID of peer + */ + identification_t *permanent; + + /** + * pseudonym ID of peer + */ + identification_t *pseudonym; + + /** + * reauthentication ID of peer + */ + identification_t *reauth; + + /** + * EAP-SIM/AKA crypto helper + */ + simaka_crypto_t *crypto; + + /** + * unique EAP identifier + */ + u_int8_t identifier; + + /** + * concatenated SRES values + */ + chunk_t sreses; + + /** + * Nonce value used in AT_NONCE_S + */ + chunk_t nonce; + + /** + * Counter value negotiated, network order + */ + chunk_t counter; + + /** + * MSK, used for EAP-SIM based IKEv2 authentication + */ + chunk_t msk; + + /** + * Do we request fast reauthentication? + */ + bool use_reauth; + + /** + * Do we request pseudonym identities? + */ + bool use_pseudonym; + + /** + * Do we request permanent identities? + */ + bool use_permanent; + + /** + * EAP-SIM message we have initiated + */ + simaka_subtype_t pending; +}; + +/* version of SIM protocol we speak */ +static chunk_t version = chunk_from_chars(0x00,0x01); + +/** + * Implementation of eap_method_t.initiate + */ +static status_t initiate(private_eap_sim_server_t *this, eap_payload_t **out) +{ + simaka_message_t *message; + + message = simaka_message_create(TRUE, this->identifier++, EAP_SIM, + SIM_START, this->crypto); + message->add_attribute(message, AT_VERSION_LIST, version); + if (this->use_reauth) + { + message->add_attribute(message, AT_ANY_ID_REQ, chunk_empty); + } + else if (this->use_pseudonym) + { + message->add_attribute(message, AT_FULLAUTH_ID_REQ, chunk_empty); + } + else if (this->use_permanent) + { + message->add_attribute(message, AT_PERMANENT_ID_REQ, chunk_empty); + } + *out = message->generate(message, chunk_empty); + message->destroy(message); + + this->pending = SIM_START; + return NEED_MORE; +} + +/** + * Initiate EAP-SIM/Request/Re-authentication message + */ +static status_t reauthenticate(private_eap_sim_server_t *this, + char mk[HASH_SIZE_SHA1], u_int16_t counter, + eap_payload_t **out) +{ + simaka_message_t *message; + identification_t *next; + chunk_t mkc; + rng_t *rng; + + DBG1(DBG_IKE, "initiating EAP-SIM reauthentication"); + + rng = this->crypto->get_rng(this->crypto); + rng->allocate_bytes(rng, NONCE_LEN, &this->nonce); + + mkc = chunk_create(mk, HASH_SIZE_SHA1); + counter = htons(counter); + this->counter = chunk_clone(chunk_create((char*)&counter, sizeof(counter))); + + this->crypto->derive_keys_reauth(this->crypto, mkc); + this->msk = this->crypto->derive_keys_reauth_msk(this->crypto, + this->reauth, this->counter, this->nonce, mkc); + + message = simaka_message_create(TRUE, this->identifier++, EAP_SIM, + SIM_REAUTHENTICATION, this->crypto); + message->add_attribute(message, AT_COUNTER, this->counter); + message->add_attribute(message, AT_NONCE_S, this->nonce); + next = charon->sim->provider_gen_reauth(charon->sim, this->permanent, mk); + if (next) + { + message->add_attribute(message, AT_NEXT_REAUTH_ID, + next->get_encoding(next)); + next->destroy(next); + } + *out = message->generate(message, chunk_empty); + message->destroy(message); + + this->pending = SIM_REAUTHENTICATION; + return NEED_MORE; +} + +/** + * process an EAP-SIM/Response/Reauthentication message + */ +static status_t process_reauthentication(private_eap_sim_server_t *this, + simaka_message_t *in, eap_payload_t **out) +{ + enumerator_t *enumerator; + simaka_attribute_t type; + chunk_t data, counter = chunk_empty; + bool too_small = FALSE; + + if (this->pending != SIM_REAUTHENTICATION) + { + DBG1(DBG_IKE, "received %N, but not expected", + simaka_subtype_names, SIM_REAUTHENTICATION); + return FAILED; + } + /* verify AT_MAC attribute, signature is over "EAP packet | NONCE_S" */ + if (!in->verify(in, this->nonce)) + { + return FAILED; + } + + enumerator = in->create_attribute_enumerator(in); + while (enumerator->enumerate(enumerator, &type, &data)) + { + switch (type) + { + case AT_COUNTER: + counter = data; + break; + case AT_COUNTER_TOO_SMALL: + too_small = TRUE; + break; + default: + if (!simaka_attribute_skippable(type)) + { + enumerator->destroy(enumerator); + return FAILED; + } + break; + } + } + enumerator->destroy(enumerator); + + if (too_small) + { + DBG1(DBG_IKE, "received %N, initiating full authentication", + simaka_attribute_names, AT_COUNTER_TOO_SMALL); + this->use_reauth = FALSE; + this->crypto->clear_keys(this->crypto); + return initiate(this, out); + } + if (!chunk_equals(counter, this->counter)) + { + DBG1(DBG_IKE, "received counter does not match"); + return FAILED; + } + return SUCCESS; +} + +/** + * process an EAP-SIM/Response/Start message + */ +static status_t process_start(private_eap_sim_server_t *this, + simaka_message_t *in, eap_payload_t **out) +{ + simaka_message_t *message; + enumerator_t *enumerator; + simaka_attribute_t type; + chunk_t data, identity = chunk_empty, nonce = chunk_empty, mk; + chunk_t rands, rand, kcs, kc, sreses, sres; + bool supported = FALSE; + identification_t *id; + int i; + + if (this->pending != SIM_START) + { + DBG1(DBG_IKE, "received %N, but not expected", + simaka_subtype_names, SIM_START); + return FAILED; + } + + enumerator = in->create_attribute_enumerator(in); + while (enumerator->enumerate(enumerator, &type, &data)) + { + switch (type) + { + case AT_NONCE_MT: + nonce = data; + break; + case AT_SELECTED_VERSION: + if (chunk_equals(data, version)) + { + supported = TRUE; + } + break; + case AT_IDENTITY: + identity = data; + break; + default: + if (!simaka_attribute_skippable(type)) + { + enumerator->destroy(enumerator); + return FAILED; + } + break; + } + } + enumerator->destroy(enumerator); + + if (identity.len) + { + identification_t *permanent; + + id = identification_create_from_data(identity); + if (this->use_reauth && !nonce.len) + { + char mk[HASH_SIZE_SHA1]; + u_int16_t counter; + + permanent = charon->sim->provider_is_reauth(charon->sim, id, + mk, &counter); + if (permanent) + { + this->permanent->destroy(this->permanent); + this->permanent = permanent; + this->reauth = id; + return reauthenticate(this, mk, counter, out); + } + DBG1(DBG_IKE, "received unknown reauthentication identity '%Y', " + "initiating full authentication", id); + this->use_reauth = FALSE; + id->destroy(id); + return initiate(this, out); + } + if (this->use_pseudonym) + { + permanent = charon->sim->provider_is_pseudonym(charon->sim, id); + if (permanent) + { + this->permanent->destroy(this->permanent); + this->permanent = permanent; + this->pseudonym = id->clone(id); + /* we already have a new permanent identity now */ + this->use_permanent = FALSE; + } + } + if (!this->pseudonym && this->use_permanent) + { + DBG1(DBG_IKE, "received %spermanent identity '%Y'", + this->use_pseudonym ? "pseudonym or " : "", id); + this->permanent->destroy(this->permanent); + this->permanent = id->clone(id); + } + id->destroy(id); + } + + if (!supported || !nonce.len) + { + DBG1(DBG_IKE, "received incomplete EAP-SIM/Response/Start"); + return FAILED; + } + + /* read triplets from provider */ + rand = rands = chunk_alloca(SIM_RAND_LEN * TRIPLET_COUNT); + kc = kcs = chunk_alloca(SIM_KC_LEN * TRIPLET_COUNT); + sres = sreses = chunk_alloca(SIM_SRES_LEN * TRIPLET_COUNT); + rands.len = kcs.len = sreses.len = 0; + for (i = 0; i < TRIPLET_COUNT; i++) + { + if (!charon->sim->provider_get_triplet(charon->sim, this->permanent, + rand.ptr, sres.ptr, kc.ptr)) + { + if (this->use_pseudonym) + { + /* probably received a pseudonym we couldn't map */ + DBG1(DBG_IKE, "failed to map pseudonym identity '%Y', " + "fallback to permanent identity request", this->permanent); + this->use_pseudonym = FALSE; + DESTROY_IF(this->pseudonym); + this->pseudonym = NULL; + return initiate(this, out); + } + return FAILED; + } + rands.len += SIM_RAND_LEN; + sreses.len += SIM_SRES_LEN; + kcs.len += SIM_KC_LEN; + rand = chunk_skip(rand, SIM_RAND_LEN); + sres = chunk_skip(sres, SIM_SRES_LEN); + kc = chunk_skip(kc, SIM_KC_LEN); + } + free(this->sreses.ptr); + this->sreses = chunk_clone(sreses); + + data = chunk_cata("cccc", kcs, nonce, version, version); + free(this->msk.ptr); + id = this->permanent; + if (this->pseudonym) + { + id = this->pseudonym; + } + this->msk = this->crypto->derive_keys_full(this->crypto, id, data, &mk); + + /* build response with AT_MAC, built over "EAP packet | NONCE_MT" */ + message = simaka_message_create(TRUE, this->identifier++, EAP_SIM, + SIM_CHALLENGE, this->crypto); + message->add_attribute(message, AT_RAND, rands); + id = charon->sim->provider_gen_reauth(charon->sim, this->permanent, mk.ptr); + if (id) + { + message->add_attribute(message, AT_NEXT_REAUTH_ID, + id->get_encoding(id)); + id->destroy(id); + } + else + { + id = charon->sim->provider_gen_pseudonym(charon->sim, this->permanent); + if (id) + { + message->add_attribute(message, AT_NEXT_PSEUDONYM, + id->get_encoding(id)); + id->destroy(id); + } + } + *out = message->generate(message, nonce); + message->destroy(message); + + free(mk.ptr); + this->pending = SIM_CHALLENGE; + return NEED_MORE; +} + +/** + * process an EAP-SIM/Response/Challenge message + */ +static status_t process_challenge(private_eap_sim_server_t *this, + simaka_message_t *in, eap_payload_t **out) +{ + enumerator_t *enumerator; + simaka_attribute_t type; + chunk_t data; + + if (this->pending != SIM_CHALLENGE) + { + DBG1(DBG_IKE, "received %N, but not expected", + simaka_subtype_names, SIM_CHALLENGE); + return FAILED; + } + /* verify AT_MAC attribute, signature is over "EAP packet | n*SRES" */ + if (!in->verify(in, this->sreses)) + { + return FAILED; + } + + enumerator = in->create_attribute_enumerator(in); + while (enumerator->enumerate(enumerator, &type, &data)) + { + if (!simaka_attribute_skippable(type)) + { + enumerator->destroy(enumerator); + return FAILED; + } + } + enumerator->destroy(enumerator); + + return SUCCESS; +} + +/** + * EAP-SIM/Response/ClientErrorCode message + */ +static status_t process_client_error(private_eap_sim_server_t *this, + simaka_message_t *in) +{ + enumerator_t *enumerator; + simaka_attribute_t type; + chunk_t data; + + enumerator = in->create_attribute_enumerator(in); + while (enumerator->enumerate(enumerator, &type, &data)) + { + if (type == AT_CLIENT_ERROR_CODE) + { + u_int16_t code; + + memcpy(&code, data.ptr, sizeof(code)); + DBG1(DBG_IKE, "received EAP-SIM client error '%N'", + simaka_client_error_names, ntohs(code)); + } + else if (!simaka_attribute_skippable(type)) + { + break; + } + } + enumerator->destroy(enumerator); + return FAILED; +} + +/** + * Implementation of eap_method_t.process + */ +static status_t process(private_eap_sim_server_t *this, + eap_payload_t *in, eap_payload_t **out) +{ + simaka_message_t *message; + status_t status; + + message = simaka_message_create_from_payload(in, this->crypto); + if (!message) + { + return FAILED; + } + if (!message->parse(message)) + { + message->destroy(message); + return FAILED; + } + switch (message->get_subtype(message)) + { + case SIM_START: + status = process_start(this, message, out); + break; + case SIM_CHALLENGE: + status = process_challenge(this, message, out); + break; + case SIM_REAUTHENTICATION: + status = process_reauthentication(this, message, out); + break; + case SIM_CLIENT_ERROR: + status = process_client_error(this, message); + break; + default: + DBG1(DBG_IKE, "unable to process EAP-SIM subtype %N", + simaka_subtype_names, message->get_subtype(message)); + status = FAILED; + break; + } + message->destroy(message); + return status; +} + +/** + * Implementation of eap_method_t.get_type. + */ +static eap_type_t get_type(private_eap_sim_server_t *this, u_int32_t *vendor) +{ + *vendor = 0; + return EAP_SIM; +} + +/** + * Implementation of eap_method_t.get_msk. + */ +static status_t get_msk(private_eap_sim_server_t *this, chunk_t *msk) +{ + if (this->msk.ptr) + { + *msk = this->msk; + return SUCCESS; + } + return FAILED; +} + +/** + * Implementation of eap_method_t.is_mutual. + */ +static bool is_mutual(private_eap_sim_server_t *this) +{ + return TRUE; +} + +/** + * Implementation of eap_method_t.destroy. + */ +static void destroy(private_eap_sim_server_t *this) +{ + this->crypto->destroy(this->crypto); + this->permanent->destroy(this->permanent); + DESTROY_IF(this->pseudonym); + DESTROY_IF(this->reauth); + free(this->sreses.ptr); + free(this->nonce.ptr); + free(this->msk.ptr); + free(this->counter.ptr); + free(this); +} + +/* + * Described in header. + */ +eap_sim_server_t *eap_sim_server_create(identification_t *server, + identification_t *peer) +{ + private_eap_sim_server_t *this = malloc_thing(private_eap_sim_server_t); + + this->public.interface.initiate = (status_t(*)(eap_method_t*,eap_payload_t**))initiate; + this->public.interface.process = (status_t(*)(eap_method_t*,eap_payload_t*,eap_payload_t**))process; + this->public.interface.get_type = (eap_type_t(*)(eap_method_t*,u_int32_t*))get_type; + this->public.interface.is_mutual = (bool(*)(eap_method_t*))is_mutual; + this->public.interface.get_msk = (status_t(*)(eap_method_t*,chunk_t*))get_msk; + this->public.interface.destroy = (void(*)(eap_method_t*))destroy; + + this->crypto = simaka_crypto_create(); + if (!this->crypto) + { + free(this); + return NULL; + } + this->permanent = peer->clone(peer); + this->pseudonym = NULL; + this->reauth = NULL; + this->sreses = chunk_empty; + this->nonce = chunk_empty; + this->msk = chunk_empty; + this->counter = chunk_empty; + this->pending = 0; + this->use_reauth = this->use_pseudonym = this->use_permanent = + lib->settings->get_bool(lib->settings, + "charon.plugins.eap-sim.request_identity", TRUE); + + /* generate a non-zero identifier */ + do { + this->identifier = random(); + } while (!this->identifier); + + return &this->public; +} + diff --git a/src/charon/plugins/eap_sim/eap_sim.h b/src/charon/plugins/eap_sim/eap_sim_server.h index af1aa2aa5..978e1e1e9 100644 --- a/src/charon/plugins/eap_sim/eap_sim.h +++ b/src/charon/plugins/eap_sim/eap_sim_server.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007-2008 Martin Willi + * Copyright (C) 2009 Martin Willi * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -14,48 +14,44 @@ */ /** - * @defgroup eap_sim_i eap_sim + * @defgroup eap_sim_server eap_sim_server * @{ @ingroup eap_sim */ -#ifndef EAP_SIM_H_ -#define EAP_SIM_H_ - -typedef struct eap_sim_t eap_sim_t; +#ifndef EAP_SIM_SERVER_H_ +#define EAP_SIM_SERVER_H_ #include <sa/authenticators/eap/eap_method.h> +typedef struct eap_sim_server_t eap_sim_server_t; + /** - * Implementation of the eap_method_t interface using EAP-SIM. + * EAP-SIM server implementation. * - * This EAP-SIM client implementation handles the protocol level of EAP-SIM - * only, it does not provide triplet calculation/fetching. Other plugins may - * provide these services using the sim_manager_t of charon. + * This EAP-SIM module uses sim_provider_t implementations for triplet + * calculation, found via the eap_sim_manager_t. */ -struct eap_sim_t { +struct eap_sim_server_t { /** * Implemented eap_method_t interface. */ - eap_method_t eap_method_interface; + eap_method_t interface; + + /** + * Destroy a eap_sim_server_t. + */ + void (*destroy)(eap_sim_server_t *this); }; /** * Creates the EAP method EAP-SIM acting as server. * * @param server ID of the EAP server - * @param peer ID of the EAP client - * @return eap_sim_t object - */ -eap_sim_t *eap_sim_create_server(identification_t *server, identification_t *peer); - -/** - * Creates the EAP method EAP-SIM acting as peer. - * - * @param server ID of the EAP server - * @param peer ID of the EAP client + * @param peer ID of the EAP peer * @return eap_sim_t object */ -eap_sim_t *eap_sim_create_peer(identification_t *server, identification_t *peer); +eap_sim_server_t *eap_sim_server_create(identification_t *server, + identification_t *peer); -#endif /** EAP_SIM_H_ @}*/ +#endif /** EAP_SIM_SERVER_H_ @}*/ |