diff options
Diffstat (limited to 'src/scepclient')
-rw-r--r-- | src/scepclient/Makefile.am | 54 | ||||
-rw-r--r-- | src/scepclient/Makefile.in | 227 | ||||
-rw-r--r-- | src/scepclient/loglite.c | 350 | ||||
-rw-r--r-- | src/scepclient/scep.c | 480 | ||||
-rw-r--r-- | src/scepclient/scep.h | 46 | ||||
-rw-r--r-- | src/scepclient/scepclient.8 | 172 | ||||
-rw-r--r-- | src/scepclient/scepclient.c | 969 |
7 files changed, 1100 insertions, 1198 deletions
diff --git a/src/scepclient/Makefile.am b/src/scepclient/Makefile.am index 897b49ac3..c911be1c4 100644 --- a/src/scepclient/Makefile.am +++ b/src/scepclient/Makefile.am @@ -1,54 +1,16 @@ ipsec_PROGRAMS = scepclient -scepclient_SOURCES = scepclient.c scep.c scep.h loglite.c +scepclient_SOURCES = \ +scepclient.c scep.c scep.h scepclient.o : $(top_builddir)/config.status -PLUTODIR=$(top_srcdir)/src/pluto -OPENACDIR=$(top_srcdir)/src/openac -WHACKDIR=$(top_srcdir)/src/whack -LIBFREESWANDIR=$(top_srcdir)/src/libfreeswan -LIBSTRONGSWANDIR=$(top_srcdir)/src/libstrongswan -LIBHYDRADIR=$(top_srcdir)/src/libhydra -LIBCRYPTODIR=$(top_srcdir)/src/libcrypto - -INCLUDES = \ --I$(LIBFREESWANDIR) \ --I$(LIBSTRONGSWANDIR) \ --I$(LIBHYDRADIR) \ --I$(PLUTODIR) \ --I$(LIBCRYPTODIR) \ --I$(WHACKDIR) - -AM_CFLAGS = \ --DIPSEC_CONFDIR=\"${sysconfdir}\" \ --DPLUGINS=\""${scepclient_plugins}\"" \ --DDEBUG -DNO_PLUTO - -LIBSTRONGSWANBUILDDIR=$(top_builddir)/src/libstrongswan -LIBFREESWANBUILDDIR=$(top_builddir)/src/libfreeswan +AM_CPPFLAGS = \ + -I$(top_srcdir)/src/libstrongswan \ + -I$(top_srcdir)/src/libhydra \ + -DIPSEC_CONFDIR=\"${sysconfdir}\" \ + -DPLUGINS=\""${scepclient_plugins}\"" scepclient_LDADD = \ -constants.o defs.o lex.o pkcs7.o \ -$(LIBSTRONGSWANBUILDDIR)/libstrongswan.la \ -$(LIBFREESWANBUILDDIR)/libfreeswan.a - -# This compile option activates smartcard support -if USE_SMARTCARD - AM_CFLAGS += -DSMARTCARD - scepclient_LDADD += $(DLLIB) -endif +$(top_builddir)/src/libstrongswan/libstrongswan.la dist_man_MANS = scepclient.8 - -constants.o : $(PLUTODIR)/constants.c $(PLUTODIR)/constants.h - $(COMPILE) $(INCLUDES) -c -o $@ $< - -defs.o : $(PLUTODIR)/defs.c $(PLUTODIR)/defs.h - $(COMPILE) $(INCLUDES) -c -o $@ $< - -lex.o : $(PLUTODIR)/lex.c $(PLUTODIR)/lex.h - $(COMPILE) $(INCLUDES) -c -o $@ $< - -pkcs7.o : $(PLUTODIR)/pkcs7.c $(PLUTODIR)/pkcs7.h - $(COMPILE) $(INCLUDES) -c -o $@ $< - diff --git a/src/scepclient/Makefile.in b/src/scepclient/Makefile.in index 576a8fb17..19a7a5d6b 100644 --- a/src/scepclient/Makefile.in +++ b/src/scepclient/Makefile.in @@ -1,9 +1,9 @@ -# Makefile.in generated by automake 1.11.1 from Makefile.am. +# Makefile.in generated by automake 1.11.6 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. +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 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,6 +16,23 @@ @SET_MAKE@ VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ @@ -35,10 +52,6 @@ POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ ipsec_PROGRAMS = scepclient$(EXEEXT) - -# This compile option activates smartcard support -@USE_SMARTCARD_TRUE@am__append_1 = -DSMARTCARD -@USE_SMARTCARD_TRUE@am__append_2 = $(DLLIB) subdir = src/scepclient DIST_COMMON = $(dist_man_MANS) $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in @@ -51,37 +64,55 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \ $(top_srcdir)/m4/macros/with.m4 \ $(top_srcdir)/m4/macros/enable-disable.m4 \ $(top_srcdir)/m4/macros/add-plugin.m4 \ - $(top_srcdir)/configure.in + $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(ipsecdir)" "$(DESTDIR)$(man8dir)" PROGRAMS = $(ipsec_PROGRAMS) -am_scepclient_OBJECTS = scepclient.$(OBJEXT) scep.$(OBJEXT) \ - loglite.$(OBJEXT) +am_scepclient_OBJECTS = scepclient.$(OBJEXT) scep.$(OBJEXT) scepclient_OBJECTS = $(am_scepclient_OBJECTS) -am__DEPENDENCIES_1 = -@USE_SMARTCARD_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) -scepclient_DEPENDENCIES = constants.o defs.o lex.o pkcs7.o \ - $(LIBSTRONGSWANBUILDDIR)/libstrongswan.la \ - $(LIBFREESWANBUILDDIR)/libfreeswan.a $(am__DEPENDENCIES_2) -DEFAULT_INCLUDES = -I.@am__isrc@ +scepclient_DEPENDENCIES = \ + $(top_builddir)/src/libstrongswan/libstrongswan.la +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) 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) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ CCLD = $(CC) -LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ - --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ - $(LDFLAGS) -o $@ +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; SOURCES = $(scepclient_SOURCES) DIST_SOURCES = $(scepclient_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ @@ -103,6 +134,12 @@ am__nobase_list = $(am__nobase_strip_setup); \ am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } man8dir = $(mandir)/man8 NROFF = nroff MANS = $(dist_man_MANS) @@ -112,21 +149,28 @@ DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ +BFDLIB = @BFDLIB@ BTLIB = @BTLIB@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ +CHECK_CFLAGS = @CHECK_CFLAGS@ +CHECK_LIBS = @CHECK_LIBS@ +COVERAGE_CFLAGS = @COVERAGE_CFLAGS@ +COVERAGE_LDFLAGS = @COVERAGE_LDFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLIB = @DLLIB@ +DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ @@ -135,13 +179,16 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +GENHTML = @GENHTML@ GPERF = @GPERF@ +GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ @@ -154,6 +201,7 @@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQLCFLAG = @MYSQLCFLAG@ MYSQLCONFIG = @MYSQLCONFIG@ @@ -181,11 +229,13 @@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ RUBYINCLUDE = @RUBYINCLUDE@ +RUBYLIB = @RUBYLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOCKLIB = @SOCKLIB@ STRIP = @STRIP@ +UNWINDLIB = @UNWINDLIB@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ @@ -193,6 +243,7 @@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ @@ -201,8 +252,6 @@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ attest_plugins = @attest_plugins@ -axis2c_CFLAGS = @axis2c_CFLAGS@ -axis2c_LIBS = @axis2c_LIBS@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ @@ -211,14 +260,19 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ c_plugins = @c_plugins@ +charon_natt_port = @charon_natt_port@ +charon_plugins = @charon_plugins@ +charon_udp_port = @charon_udp_port@ clearsilver_LIBS = @clearsilver_LIBS@ +cmd_plugins = @cmd_plugins@ datadir = @datadir@ datarootdir = @datarootdir@ dbusservicedir = @dbusservicedir@ -default_pkcs11 = @default_pkcs11@ +dev_headers = @dev_headers@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ +fips_mode = @fips_mode@ gtk_CFLAGS = @gtk_CFLAGS@ gtk_LIBS = @gtk_LIBS@ h_plugins = @h_plugins@ @@ -232,17 +286,17 @@ imcvdir = @imcvdir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ +ipsec_script = @ipsec_script@ +ipsec_script_upper = @ipsec_script_upper@ ipsecdir = @ipsecdir@ ipsecgroup = @ipsecgroup@ ipseclibdir = @ipseclibdir@ ipsecuser = @ipsecuser@ -libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ libexecdir = @libexecdir@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ -lt_ECHO = @lt_ECHO@ maemo_CFLAGS = @maemo_CFLAGS@ maemo_LIBS = @maemo_LIBS@ manager_plugins = @manager_plugins@ @@ -252,16 +306,15 @@ mkdir_p = @mkdir_p@ nm_CFLAGS = @nm_CFLAGS@ nm_LIBS = @nm_LIBS@ nm_ca_dir = @nm_ca_dir@ +nm_plugins = @nm_plugins@ oldincludedir = @oldincludedir@ openac_plugins = @openac_plugins@ -p_plugins = @p_plugins@ pcsclite_CFLAGS = @pcsclite_CFLAGS@ pcsclite_LIBS = @pcsclite_LIBS@ pdfdir = @pdfdir@ piddir = @piddir@ pki_plugins = @pki_plugins@ plugindir = @plugindir@ -pluto_plugins = @pluto_plugins@ pool_plugins = @pool_plugins@ prefix = @prefix@ program_transform_name = @program_transform_name@ @@ -289,30 +342,18 @@ top_srcdir = @top_srcdir@ urandom_device = @urandom_device@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ -scepclient_SOURCES = scepclient.c scep.c scep.h loglite.c -PLUTODIR = $(top_srcdir)/src/pluto -OPENACDIR = $(top_srcdir)/src/openac -WHACKDIR = $(top_srcdir)/src/whack -LIBFREESWANDIR = $(top_srcdir)/src/libfreeswan -LIBSTRONGSWANDIR = $(top_srcdir)/src/libstrongswan -LIBHYDRADIR = $(top_srcdir)/src/libhydra -LIBCRYPTODIR = $(top_srcdir)/src/libcrypto -INCLUDES = \ --I$(LIBFREESWANDIR) \ --I$(LIBSTRONGSWANDIR) \ --I$(LIBHYDRADIR) \ --I$(PLUTODIR) \ --I$(LIBCRYPTODIR) \ --I$(WHACKDIR) - -AM_CFLAGS = -DIPSEC_CONFDIR=\"${sysconfdir}\" \ - -DPLUGINS=\""${scepclient_plugins}\"" -DDEBUG -DNO_PLUTO \ - $(am__append_1) -LIBSTRONGSWANBUILDDIR = $(top_builddir)/src/libstrongswan -LIBFREESWANBUILDDIR = $(top_builddir)/src/libfreeswan -scepclient_LDADD = constants.o defs.o lex.o pkcs7.o \ - $(LIBSTRONGSWANBUILDDIR)/libstrongswan.la \ - $(LIBFREESWANBUILDDIR)/libfreeswan.a $(am__append_2) +scepclient_SOURCES = \ +scepclient.c scep.c scep.h + +AM_CPPFLAGS = \ + -I$(top_srcdir)/src/libstrongswan \ + -I$(top_srcdir)/src/libhydra \ + -DIPSEC_CONFDIR=\"${sysconfdir}\" \ + -DPLUGINS=\""${scepclient_plugins}\"" + +scepclient_LDADD = \ +$(top_builddir)/src/libstrongswan/libstrongswan.la + dist_man_MANS = scepclient.8 all: all-am @@ -350,8 +391,11 @@ $(ACLOCAL_M4): $(am__aclocal_m4_deps) $(am__aclocal_m4_deps): install-ipsecPROGRAMS: $(ipsec_PROGRAMS) @$(NORMAL_INSTALL) - test -z "$(ipsecdir)" || $(MKDIR_P) "$(DESTDIR)$(ipsecdir)" @list='$(ipsec_PROGRAMS)'; test -n "$(ipsecdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(ipsecdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(ipsecdir)" || exit 1; \ + fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p || test -f $$p1; \ @@ -391,9 +435,9 @@ clean-ipsecPROGRAMS: list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list -scepclient$(EXEEXT): $(scepclient_OBJECTS) $(scepclient_DEPENDENCIES) +scepclient$(EXEEXT): $(scepclient_OBJECTS) $(scepclient_DEPENDENCIES) $(EXTRA_scepclient_DEPENDENCIES) @rm -f scepclient$(EXEEXT) - $(LINK) $(scepclient_OBJECTS) $(scepclient_LDADD) $(LIBS) + $(AM_V_CCLD)$(LINK) $(scepclient_OBJECTS) $(scepclient_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) @@ -401,30 +445,29 @@ mostlyclean-compile: distclean-compile: -rm -f *.tab.c -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/loglite.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/scep.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/scepclient.Po@am__quote@ .c.o: -@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(COMPILE) -c $< +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(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@ +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(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@ +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo @@ -433,11 +476,18 @@ clean-libtool: -rm -rf .libs _libs install-man8: $(dist_man_MANS) @$(NORMAL_INSTALL) - test -z "$(man8dir)" || $(MKDIR_P) "$(DESTDIR)$(man8dir)" - @list=''; test -n "$(man8dir)" || exit 0; \ - { for i in $$list; do echo "$$i"; done; \ - l2='$(dist_man_MANS)'; for i in $$l2; do echo "$$i"; done | \ - sed -n '/\.8[a-z]*$$/p'; \ + @list1=''; \ + list2='$(dist_man_MANS)'; \ + test -n "$(man8dir)" \ + && test -n "`echo $$list1$$list2`" \ + || exit 0; \ + echo " $(MKDIR_P) '$(DESTDIR)$(man8dir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(man8dir)" || exit 1; \ + { for i in $$list1; do echo "$$i"; done; \ + if test -n "$$list2"; then \ + for i in $$list2; do echo "$$i"; done \ + | sed -n '/\.8[a-z]*$$/p'; \ + fi; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ @@ -466,9 +516,7 @@ uninstall-man8: sed -n '/\.8[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ - test -z "$$files" || { \ - echo " ( cd '$(DESTDIR)$(man8dir)' && rm -f" $$files ")"; \ - cd "$(DESTDIR)$(man8dir)" && rm -f $$files; } + dir='$(DESTDIR)$(man8dir)'; $(am__uninstall_files_from_dir) ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ @@ -582,10 +630,15 @@ install-am: all-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 + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi mostlyclean-generic: clean-generic: @@ -690,18 +743,6 @@ uninstall-man: uninstall-man8 scepclient.o : $(top_builddir)/config.status -constants.o : $(PLUTODIR)/constants.c $(PLUTODIR)/constants.h - $(COMPILE) $(INCLUDES) -c -o $@ $< - -defs.o : $(PLUTODIR)/defs.c $(PLUTODIR)/defs.h - $(COMPILE) $(INCLUDES) -c -o $@ $< - -lex.o : $(PLUTODIR)/lex.c $(PLUTODIR)/lex.h - $(COMPILE) $(INCLUDES) -c -o $@ $< - -pkcs7.o : $(PLUTODIR)/pkcs7.c $(PLUTODIR)/pkcs7.h - $(COMPILE) $(INCLUDES) -c -o $@ $< - # 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/scepclient/loglite.c b/src/scepclient/loglite.c deleted file mode 100644 index 96dc54390..000000000 --- a/src/scepclient/loglite.c +++ /dev/null @@ -1,350 +0,0 @@ -/* error logging functions - * Copyright (C) 1997 Angelos D. Keromytis. - * Copyright (C) 1998-2001 D. Hugh Redelmeier. - * - * 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 <stdio.h> -#include <stdlib.h> -#include <ctype.h> -#include <stdarg.h> -#include <syslog.h> -#include <errno.h> -#include <string.h> -#include <unistd.h> -#include <signal.h> /* used only if MSG_NOSIGNAL not defined */ -#include <libgen.h> -#include <sys/stat.h> -#include <sys/types.h> - -#include <freeswan.h> -#include <debug.h> - -#include <constants.h> -#include <defs.h> -#include <log.h> -#include <whack.h> - -bool - log_to_stderr = FALSE, /* should log go to stderr? */ - log_to_syslog = TRUE; /* should log go to syslog? */ - -/** - * @brief scepclient dbg function - */ -static void scepclient_dbg(debug_t group, level_t level, char *fmt, ...) -{ - int priority = LOG_INFO; - int debug_level; - char buffer[8192]; - char *current = buffer, *next; - va_list args; - - if (cur_debugging & DBG_PRIVATE) - { - debug_level = 4; - } - else if (cur_debugging & DBG_RAW) - { - debug_level = 3; - } - else if (cur_debugging & DBG_PARSING) - { - debug_level = 2; - } - else - { - debug_level = 1; - } - - if (level <= debug_level) - { - if (log_to_stderr) - { - if (level > 1) - { - fprintf(stderr, "| "); - } - va_start(args, fmt); - vfprintf(stderr, fmt, args); - va_end(args); - fprintf(stderr, "\n"); - } - if (log_to_syslog) - { - /* write in memory buffer first */ - va_start(args, fmt); - vsnprintf(buffer, sizeof(buffer), fmt, args); - va_end(args); - - /* do a syslog with every line */ - while (current) - { - next = strchr(current, '\n'); - if (next) - { - *(next++) = '\0'; - } - syslog(priority, "%s%s\n", (level > 1)? "| ":"", current); - current = next; - } - } - } -} - -void init_log(const char *program) -{ - /* enable scepclient bugging hook */ - dbg = scepclient_dbg; - - if (log_to_stderr) - { - setbuf(stderr, NULL); - } - if (log_to_syslog) - { - openlog(program, LOG_CONS | LOG_NDELAY | LOG_PID, LOG_AUTHPRIV); - } -} - -void close_log(void) -{ - if (log_to_syslog) - closelog(); -} - -void plog(const char *message, ...) -{ - va_list args; - char m[LOG_WIDTH]; /* longer messages will be truncated */ - - va_start(args, message); - vsnprintf(m, sizeof(m), message, args); - va_end(args); - - if (log_to_stderr) - fprintf(stderr, "%s\n", m); - if (log_to_syslog) - syslog(LOG_WARNING, "%s", m); -} - -void loglog(int mess_no, const char *message, ...) -{ - va_list args; - char m[LOG_WIDTH]; /* longer messages will be truncated */ - - va_start(args, message); - vsnprintf(m, sizeof(m), message, args); - va_end(args); - - if (log_to_stderr) - fprintf(stderr, "%s\n", m); - if (log_to_syslog) - syslog(LOG_WARNING, "%s", m); -} - -void log_errno_routine(int e, const char *message, ...) -{ - va_list args; - char m[LOG_WIDTH]; /* longer messages will be truncated */ - - va_start(args, message); - vsnprintf(m, sizeof(m), message, args); - va_end(args); - - if (log_to_stderr) - fprintf(stderr, "ERROR: %s. Errno %d: %s\n", m, e, strerror(e)); - if (log_to_syslog) - syslog(LOG_ERR, "ERROR: %s. Errno %d: %s", m, e, strerror(e)); -} - -void exit_log(const char *message, ...) -{ - va_list args; - char m[LOG_WIDTH]; /* longer messages will be truncated */ - - va_start(args, message); - vsnprintf(m, sizeof(m), message, args); - va_end(args); - - if (log_to_stderr) - fprintf(stderr, "FATAL ERROR: %s\n", m); - if (log_to_syslog) - syslog(LOG_ERR, "FATAL ERROR: %s", m); - exit(1); -} - -void exit_log_errno_routine(int e, const char *message, ...) -{ - va_list args; - char m[LOG_WIDTH]; /* longer messages will be truncated */ - - va_start(args, message); - vsnprintf(m, sizeof(m), message, args); - va_end(args); - - if (log_to_stderr) - fprintf(stderr, "FATAL ERROR: %s. Errno %d: %s\n", m, e, strerror(e)); - if (log_to_syslog) - syslog(LOG_ERR, "FATAL ERROR: %s. Errno %d: %s", m, e, strerror(e)); - exit(1); -} - -void whack_log(int mess_no, const char *message, ...) -{ - va_list args; - char m[LOG_WIDTH]; /* longer messages will be truncated */ - - va_start(args, message); - vsnprintf(m, sizeof(m), message, args); - va_end(args); - - fprintf(stderr, "%s\n", m); -} - -/* Build up a diagnostic in a static buffer. - * Although this would be a generally useful function, it is very - * hard to come up with a discipline that prevents different uses - * from interfering. It is intended that by limiting it to building - * diagnostics, we will avoid this problem. - * Juggling is performed to allow an argument to be a previous - * result: the new string may safely depend on the old one. This - * restriction is not checked in any way: violators will produce - * confusing results (without crashing!). - */ -char diag_space[sizeof(diag_space)]; - -err_t builddiag(const char *fmt, ...) -{ - static char diag_space[LOG_WIDTH]; /* longer messages will be truncated */ - char t[sizeof(diag_space)]; /* build result here first */ - va_list args; - - va_start(args, fmt); - t[0] = '\0'; /* in case nothing terminates string */ - vsnprintf(t, sizeof(t), fmt, args); - va_end(args); - strcpy(diag_space, t); - return diag_space; -} - -/* Debugging message support */ - -#ifdef DEBUG - -void switch_fail(int n, const char *file_str, unsigned long line_no) -{ - char buf[30]; - - snprintf(buf, sizeof(buf), "case %d unexpected", n); - passert_fail(buf, file_str, line_no); -} - -void passert_fail(const char *pred_str, const char *file_str, unsigned long line_no) -{ - /* we will get a possibly unplanned prefix. Hope it works */ - loglog(RC_LOG_SERIOUS, "ASSERTION FAILED at %s:%lu: %s", file_str, line_no, pred_str); - abort(); /* exiting correctly doesn't always work */ -} - -lset_t - base_debugging = DBG_NONE, /* default to reporting nothing */ - cur_debugging = DBG_NONE; - -void pexpect_log(const char *pred_str, const char *file_str, unsigned long line_no) -{ - /* we will get a possibly unplanned prefix. Hope it works */ - loglog(RC_LOG_SERIOUS, "EXPECTATION FAILED at %s:%lu: %s", file_str, line_no, pred_str); -} - -/* log a debugging message (prefixed by "| ") */ - -void DBG_log(const char *message, ...) -{ - va_list args; - char m[LOG_WIDTH]; /* longer messages will be truncated */ - - va_start(args, message); - vsnprintf(m, sizeof(m), message, args); - va_end(args); - - if (log_to_stderr) - fprintf(stderr, "| %s\n", m); - if (log_to_syslog) - syslog(LOG_DEBUG, "| %s", m); -} - -/* dump raw bytes in hex to stderr (for lack of any better destination) */ - -void DBG_dump(const char *label, const void *p, size_t len) -{ -# define DUMP_LABEL_WIDTH 20 /* arbitrary modest boundary */ -# define DUMP_WIDTH (4 * (1 + 4 * 3) + 1) - char buf[DUMP_LABEL_WIDTH + DUMP_WIDTH]; - char *bp; - const unsigned char *cp = p; - - bp = buf; - - if (label != NULL && label[0] != '\0') - { - /* Handle the label. Care must be taken to avoid buffer overrun. */ - size_t llen = strlen(label); - - if (llen + 1 > sizeof(buf)) - { - DBG_log("%s", label); - } - else - { - strcpy(buf, label); - if (buf[llen-1] == '\n') - { - buf[llen-1] = '\0'; /* get rid of newline */ - DBG_log("%s", buf); - } - else if (llen < DUMP_LABEL_WIDTH) - { - bp = buf + llen; - } - else - { - DBG_log("%s", buf); - } - } - } - - do { - int i, j; - - for (i = 0; len!=0 && i!=4; i++) - { - *bp++ = ' '; - for (j = 0; len!=0 && j!=4; len--, j++) - { - static const char hexdig[] = "0123456789abcdef"; - - *bp++ = ' '; - *bp++ = hexdig[(*cp >> 4) & 0xF]; - *bp++ = hexdig[*cp & 0xF]; - cp++; - } - } - *bp = '\0'; - DBG_log("%s", buf); - bp = buf; - } while (len != 0); -# undef DUMP_LABEL_WIDTH -# undef DUMP_WIDTH -} - -#endif /* DEBUG */ diff --git a/src/scepclient/scep.c b/src/scepclient/scep.c index 29f6eab70..5bb29bbd8 100644 --- a/src/scepclient/scep.c +++ b/src/scepclient/scep.c @@ -1,11 +1,5 @@ -/** - * @file scep.c - * @brief SCEP specific functions - * - * Contains functions to build SCEP request's and to parse SCEP reply's. - */ - /* + * Copyright (C) 2012 Tobias Brunner * Copyright (C) 2005 Jan Hutter, Martin Willi * Hochschule fuer Technik Rapperswil * @@ -23,32 +17,16 @@ #include <string.h> #include <stdlib.h> -#include <freeswan.h> - #include <library.h> +#include <utils/debug.h> #include <asn1/asn1.h> #include <asn1/asn1_parser.h> #include <asn1/oid.h> #include <crypto/rngs/rng.h> #include <crypto/hashers/hasher.h> -#include "../pluto/constants.h" -#include "../pluto/defs.h" -#include "../pluto/fetch.h" -#include "../pluto/log.h" - #include "scep.h" -static const chunk_t ASN1_messageType_oid = chunk_from_chars( - 0x06, 0x0A, 0x60, 0x86, 0x48, 0x01, 0x86, 0xF8, 0x45, 0x01, 0x09, 0x02 -); -static const chunk_t ASN1_senderNonce_oid = chunk_from_chars( - 0x06, 0x0A, 0x60, 0x86, 0x48, 0x01, 0x86, 0xF8, 0x45, 0x01, 0x09, 0x05 -); -static const chunk_t ASN1_transId_oid = chunk_from_chars( - 0x06, 0x0A, 0x60, 0x86, 0x48, 0x01, 0x86, 0xF8, 0x45, 0x01, 0x09, 0x07 -); - static const char *pkiStatus_values[] = { "0", "2", "3" }; static const char *pkiStatus_names[] = { @@ -86,170 +64,61 @@ const scep_attributes_t empty_scep_attributes = { { NULL, 0 } , /* recipientNonce */ }; -/* ASN.1 definition of the X.501 atttribute type */ - -static const asn1Object_t attributesObjects[] = { - { 0, "attributes", ASN1_SET, ASN1_LOOP }, /* 0 */ - { 1, "attribute", ASN1_SEQUENCE, ASN1_NONE }, /* 1 */ - { 2, "type", ASN1_OID, ASN1_BODY }, /* 2 */ - { 2, "values", ASN1_SET, ASN1_LOOP }, /* 3 */ - { 3, "value", ASN1_EOC, ASN1_RAW }, /* 4 */ - { 2, "end loop", ASN1_EOC, ASN1_END }, /* 5 */ - { 0, "end loop", ASN1_EOC, ASN1_END }, /* 6 */ - { 0, "exit", ASN1_EOC, ASN1_EXIT } -}; -#define ATTRIBUTE_OBJ_TYPE 2 -#define ATTRIBUTE_OBJ_VALUE 4 - /** - * Extract and store an attribute + * Extract X.501 attributes */ -static bool extract_attribute(int oid, chunk_t object, u_int level, - scep_attributes_t *attrs) +void extract_attributes(pkcs7_t *pkcs7, enumerator_t *enumerator, + scep_attributes_t *attrs) { - asn1_t type = ASN1_EOC; - const char *name = "none"; + chunk_t attr; - switch (oid) + if (pkcs7->get_attribute(pkcs7, OID_PKI_MESSAGE_TYPE, enumerator, &attr)) { - case OID_PKCS9_CONTENT_TYPE: - type = ASN1_OID; - name = "contentType"; - break; - case OID_PKCS9_SIGNING_TIME: - type = ASN1_UTCTIME; - name = "signingTime"; - break; - case OID_PKCS9_MESSAGE_DIGEST: - type = ASN1_OCTET_STRING; - name = "messageDigest"; - break; - case OID_PKI_MESSAGE_TYPE: - type = ASN1_PRINTABLESTRING; - name = "messageType"; - break; - case OID_PKI_STATUS: - type = ASN1_PRINTABLESTRING; - name = "pkiStatus"; - break; - case OID_PKI_FAIL_INFO: - type = ASN1_PRINTABLESTRING; - name = "failInfo"; - break; - case OID_PKI_SENDER_NONCE: - type = ASN1_OCTET_STRING; - name = "senderNonce"; - break; - case OID_PKI_RECIPIENT_NONCE: - type = ASN1_OCTET_STRING; - name = "recipientNonce"; - break; - case OID_PKI_TRANS_ID: - type = ASN1_PRINTABLESTRING; - name = "transID"; - break; - default: - break; - } - - if (type == ASN1_EOC) - return TRUE; - - if (!asn1_parse_simple_object(&object, type, level+1, name)) - return FALSE; + scep_msg_t m; - switch (oid) - { - case OID_PKCS9_CONTENT_TYPE: - break; - case OID_PKCS9_SIGNING_TIME: - break; - case OID_PKCS9_MESSAGE_DIGEST: - break; - case OID_PKI_MESSAGE_TYPE: + for (m = SCEP_CertRep_MSG; m < SCEP_Unknown_MSG; m++) { - scep_msg_t m; - - for (m = SCEP_CertRep_MSG; m < SCEP_Unknown_MSG; m++) + if (strncmp(msgType_values[m], attr.ptr, attr.len) == 0) { - if (strncmp(msgType_values[m], object.ptr, object.len) == 0) - attrs->msgType = m; + attrs->msgType = m; } - DBG(DBG_CONTROL, - DBG_log("messageType: %s", msgType_names[attrs->msgType]) - ) } - break; - case OID_PKI_STATUS: - { - pkiStatus_t s; + DBG2(DBG_APP, "messageType: %s", msgType_names[attrs->msgType]); + free(attr.ptr); + } + if (pkcs7->get_attribute(pkcs7, OID_PKI_STATUS, enumerator, &attr)) + { + pkiStatus_t s; - for (s = SCEP_SUCCESS; s < SCEP_UNKNOWN; s++) + for (s = SCEP_SUCCESS; s < SCEP_UNKNOWN; s++) + { + if (strncmp(pkiStatus_values[s], attr.ptr, attr.len) == 0) { - if (strncmp(pkiStatus_values[s], object.ptr, object.len) == 0) - attrs->pkiStatus = s; + attrs->pkiStatus = s; } - DBG(DBG_CONTROL, - DBG_log("pkiStatus: %s", pkiStatus_names[attrs->pkiStatus]) - ) } - break; - case OID_PKI_FAIL_INFO: - if (object.len == 1 - && *object.ptr >= '0' && *object.ptr <= '4') + DBG2(DBG_APP, "pkiStatus: %s", pkiStatus_names[attrs->pkiStatus]); + free(attr.ptr); + } + if (pkcs7->get_attribute(pkcs7, OID_PKI_FAIL_INFO, enumerator, &attr)) + { + if (attr.len == 1 && *attr.ptr >= '0' && *attr.ptr <= '4') { - attrs->failInfo = (failInfo_t)(*object.ptr - '0'); + attrs->failInfo = (failInfo_t)(*attr.ptr - '0'); } if (attrs->failInfo != SCEP_unknown_REASON) - plog("failInfo: %s", failInfo_reasons[attrs->failInfo]); - break; - case OID_PKI_SENDER_NONCE: - attrs->senderNonce = object; - break; - case OID_PKI_RECIPIENT_NONCE: - attrs->recipientNonce = object; - break; - case OID_PKI_TRANS_ID: - attrs->transID = object; - } - return TRUE; -} - -/** - * Parse X.501 attributes - */ -bool parse_attributes(chunk_t blob, scep_attributes_t *attrs) -{ - asn1_parser_t *parser; - chunk_t object; - int oid = OID_UNKNOWN; - int objectID; - bool success = FALSE; - - parser = asn1_parser_create(attributesObjects, blob); - DBG(DBG_CONTROL | DBG_PARSING, - DBG_log("parsing attributes") - ) - - while (parser->iterate(parser, &objectID, &object)) - { - switch (objectID) { - case ATTRIBUTE_OBJ_TYPE: - oid = asn1_known_oid(object); - break; - case ATTRIBUTE_OBJ_VALUE: - if (!extract_attribute(oid, object, parser->get_level(parser), attrs)) - { - goto end; - } + DBG1(DBG_APP, "failInfo: %s", failInfo_reasons[attrs->failInfo]); } + free(attr.ptr); } - success = parser->success(parser); -end: - parser->destroy(parser); - return success; + pkcs7->get_attribute(pkcs7, OID_PKI_SENDER_NONCE, enumerator, + &attrs->senderNonce); + pkcs7->get_attribute(pkcs7, OID_PKI_RECIPIENT_NONCE, enumerator, + &attrs->recipientNonce); + pkcs7->get_attribute(pkcs7, OID_PKI_TRANS_ID, enumerator, + &attrs->transID); } /** @@ -262,7 +131,11 @@ chunk_t scep_generate_pkcs10_fingerprint(chunk_t pkcs10) hasher_t *hasher; hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD5); - hasher->get_hash(hasher, pkcs10, digest.ptr); + if (!hasher || !hasher->get_hash(hasher, pkcs10, digest.ptr)) + { + DESTROY_IF(hasher); + return chunk_empty; + } hasher->destroy(hasher); return chunk_to_hex(digest, NULL, FALSE); @@ -278,8 +151,7 @@ void scep_generate_transaction_id(public_key_t *key, chunk_t *transID, chunk_t digest = chunk_alloca(HASH_SIZE_MD5); chunk_t keyEncoding = chunk_empty, keyInfo; hasher_t *hasher; - bool msb_set; - u_char *pos; + int zeros = 0, msb_set = 0; key->get_encoding(key, PUBKEY_ASN1_DER, &keyEncoding); @@ -288,108 +160,115 @@ void scep_generate_transaction_id(public_key_t *key, chunk_t *transID, asn1_bitstring("m", keyEncoding)); hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD5); - hasher->get_hash(hasher, keyInfo, digest.ptr); - hasher->destroy(hasher); + if (!hasher || !hasher->get_hash(hasher, keyInfo, digest.ptr)) + { + memset(digest.ptr, 0, digest.len); + } + DESTROY_IF(hasher); free(keyInfo.ptr); - /* is the most significant bit of the digest set? */ - msb_set = (*digest.ptr & 0x80) == 0x80; - - /* allocate space for the serialNumber */ - serialNumber->len = msb_set + digest.len; - serialNumber->ptr = malloc(serialNumber->len); - - /* the serial number as the two's complement of the digest */ - pos = serialNumber->ptr; + /* the serialNumber should be valid ASN1 integer content: + * remove leading zeros, add one if MSB is set (two's complement) */ + while (zeros < digest.len) + { + if (digest.ptr[zeros]) + { + if (digest.ptr[zeros] & 0x80) + { + msb_set = 1; + } + break; + } + zeros++; + } + *serialNumber = chunk_alloc(digest.len - zeros + msb_set); if (msb_set) { - *pos++ = 0x00; + serialNumber->ptr[0] = 0x00; } - memcpy(pos, digest.ptr, digest.len); + memcpy(serialNumber->ptr + msb_set, digest.ptr + zeros, + digest.len - zeros); /* the transaction id is the serial number in hex format */ - transID->len = 2*digest.len; - transID->ptr = malloc(transID->len + 1); - datatot(digest.ptr, digest.len, 16, transID->ptr, transID->len + 1); + *transID = chunk_to_hex(digest, NULL, TRUE); } /** - * Builds a transId attribute - */ -chunk_t scep_transId_attribute(chunk_t transID) -{ - return asn1_wrap(ASN1_SEQUENCE, "cm" - , ASN1_transId_oid - , asn1_wrap(ASN1_SET, "m" - , asn1_simple_object(ASN1_PRINTABLESTRING, transID) - ) - ); -} - -/** - * Builds a messageType attribute - */ -chunk_t scep_messageType_attribute(scep_msg_t m) -{ - chunk_t msgType = { - (u_char*)msgType_values[m], - strlen(msgType_values[m]) - }; - - return asn1_wrap(ASN1_SEQUENCE, "cm" - , ASN1_messageType_oid - , asn1_wrap(ASN1_SET, "m" - , asn1_simple_object(ASN1_PRINTABLESTRING, msgType) - ) - ); -} - -/** - * Builds a senderNonce attribute + * Builds a pkcs7 enveloped and signed scep request */ -chunk_t scep_senderNonce_attribute(void) +chunk_t scep_build_request(chunk_t data, chunk_t transID, scep_msg_t msg, + certificate_t *enc_cert, encryption_algorithm_t enc_alg, + size_t key_size, certificate_t *signer_cert, + hash_algorithm_t digest_alg, private_key_t *private_key) { - const size_t nonce_len = 16; - u_char nonce_buf[nonce_len]; - chunk_t senderNonce = { nonce_buf, nonce_len }; + chunk_t request; + container_t *container; + char nonce[16]; rng_t *rng; + chunk_t senderNonce, msgType; + /* generate senderNonce */ rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK); - rng->get_bytes(rng, nonce_len, nonce_buf); + if (!rng || !rng->get_bytes(rng, sizeof(nonce), nonce)) + { + DESTROY_IF(rng); + return chunk_empty; + } rng->destroy(rng); - return asn1_wrap(ASN1_SEQUENCE, "cm" - , ASN1_senderNonce_oid - , asn1_wrap(ASN1_SET, "m" - , asn1_simple_object(ASN1_OCTET_STRING, senderNonce) - ) - ); -} + /* encrypt data in enveloped-data PKCS#7 */ + container = lib->creds->create(lib->creds, + CRED_CONTAINER, CONTAINER_PKCS7_ENVELOPED_DATA, + BUILD_BLOB, data, + BUILD_CERT, enc_cert, + BUILD_ENCRYPTION_ALG, enc_alg, + BUILD_KEY_SIZE, (int)key_size, + BUILD_END); + if (!container) + { + return chunk_empty; + } + if (!container->get_encoding(container, &request)) + { + container->destroy(container); + return chunk_empty; + } + container->destroy(container); + + /* sign enveloped-data in a signed-data PKCS#7 */ + senderNonce = asn1_wrap(ASN1_OCTET_STRING, "c", chunk_from_thing(nonce)); + transID = asn1_wrap(ASN1_PRINTABLESTRING, "c", transID); + msgType = asn1_wrap(ASN1_PRINTABLESTRING, "c", + chunk_create((char*)msgType_values[msg], + strlen(msgType_values[msg]))); + + container = lib->creds->create(lib->creds, + CRED_CONTAINER, CONTAINER_PKCS7_SIGNED_DATA, + BUILD_BLOB, request, + BUILD_SIGNING_CERT, signer_cert, + BUILD_SIGNING_KEY, private_key, + BUILD_DIGEST_ALG, digest_alg, + BUILD_PKCS7_ATTRIBUTE, OID_PKI_SENDER_NONCE, senderNonce, + BUILD_PKCS7_ATTRIBUTE, OID_PKI_TRANS_ID, transID, + BUILD_PKCS7_ATTRIBUTE, OID_PKI_MESSAGE_TYPE, msgType, + BUILD_END); + + free(request.ptr); + free(senderNonce.ptr); + free(transID.ptr); + free(msgType.ptr); + + if (!container) + { + return chunk_empty; + } + if (!container->get_encoding(container, &request)) + { + container->destroy(container); + return chunk_empty; + } + container->destroy(container); -/** - * Builds a pkcs7 enveloped and signed scep request - */ -chunk_t scep_build_request(chunk_t data, chunk_t transID, scep_msg_t msg, - certificate_t *enc_cert, int enc_alg, - certificate_t *signer_cert, int digest_alg, - private_key_t *private_key) -{ - chunk_t envelopedData, attributes, request; - - envelopedData = pkcs7_build_envelopedData(data, enc_cert, enc_alg); - - attributes = asn1_wrap(ASN1_SET, "mmmmm" - , pkcs7_contentType_attribute() - , pkcs7_messageDigest_attribute(envelopedData - , digest_alg) - , scep_transId_attribute(transID) - , scep_messageType_attribute(msg) - , scep_senderNonce_attribute()); - - request = pkcs7_build_signedData(envelopedData, attributes - , signer_cert, digest_alg, private_key); - free(envelopedData.ptr); - free(attributes.ptr); return request; } @@ -406,11 +285,12 @@ static char* escape_http_request(chunk_t req) int n = 0; /* compute and allocate the size of the base64-encoded request */ - int len = 1 + 4*((req.len + 2)/3); + int len = 1 + 4 * ((req.len + 2) / 3); char *encoded_req = malloc(len); /* do the base64 conversion */ - len = datatot(req.ptr, req.len, 64, encoded_req, len); + chunk_t base64 = chunk_to_base64(req, encoded_req); + len = base64.len + 1; /* compute newline characters to be inserted every 64 characters */ lines = (len - 2) / 64; @@ -420,10 +300,12 @@ static char* escape_http_request(chunk_t req) while (*p1 != '\0') { if (*p1++ == '+') + { plus++; + } } - escaped_req = malloc(len + 3*(lines + plus)); + escaped_req = malloc(len + 3 * (lines + plus)); /* escape special characters in the request */ p1 = encoded_req; @@ -456,19 +338,24 @@ static char* escape_http_request(chunk_t req) /** * Send a SCEP request via HTTP and wait for a response */ -bool scep_http_request(const char *url, chunk_t pkcs7, scep_op_t op, - bool http_get_request, chunk_t *response) +bool scep_http_request(const char *url, chunk_t msg, scep_op_t op, + bool http_get_request, u_int timeout, char *src, + chunk_t *response) { int len; status_t status; char *complete_url = NULL; + host_t *srcip = NULL; /* initialize response */ *response = chunk_empty; - DBG(DBG_CONTROL, - DBG_log("sending scep request to '%s'", url) - ) + if (src) + { + srcip = host_create_from_string(src, 0); + } + + DBG2(DBG_APP, "sending scep request to '%s'", url); if (op == SCEP_PKI_OPERATION) { @@ -476,7 +363,7 @@ bool scep_http_request(const char *url, chunk_t pkcs7, scep_op_t op, if (http_get_request) { - char *escaped_req = escape_http_request(pkcs7); + char *escaped_req = escape_http_request(msg); /* form complete url */ len = strlen(url) + 20 + strlen(operation) + strlen(escaped_req) + 1; @@ -487,9 +374,11 @@ bool scep_http_request(const char *url, chunk_t pkcs7, scep_op_t op, status = lib->fetcher->fetch(lib->fetcher, complete_url, response, FETCH_HTTP_VERSION_1_0, + FETCH_TIMEOUT, timeout, FETCH_REQUEST_HEADER, "Pragma:", FETCH_REQUEST_HEADER, "Host:", FETCH_REQUEST_HEADER, "Accept:", + FETCH_SOURCEIP, srcip, FETCH_END); } else /* HTTP_POST */ @@ -500,46 +389,85 @@ bool scep_http_request(const char *url, chunk_t pkcs7, scep_op_t op, snprintf(complete_url, len, "%s?operation=%s", url, operation); status = lib->fetcher->fetch(lib->fetcher, complete_url, response, - FETCH_REQUEST_DATA, pkcs7, + FETCH_HTTP_VERSION_1_0, + FETCH_TIMEOUT, timeout, + FETCH_REQUEST_DATA, msg, FETCH_REQUEST_TYPE, "", FETCH_REQUEST_HEADER, "Expect:", + FETCH_SOURCEIP, srcip, FETCH_END); } } else /* SCEP_GET_CA_CERT */ { const char operation[] = "GetCACert"; + int i; + + /* escape spaces, TODO: complete URL escape */ + for (i = 0; i < msg.len; i++) + { + if (msg.ptr[i] == ' ') + { + msg.ptr[i] = '+'; + } + } /* form complete url */ - len = strlen(url) + 32 + strlen(operation) + 1; + len = strlen(url) + 32 + strlen(operation) + msg.len + 1; complete_url = malloc(len); - snprintf(complete_url, len, "%s?operation=%s&message=CAIdentifier" - , url, operation); + snprintf(complete_url, len, "%s?operation=%s&message=%.*s", + url, operation, (int)msg.len, msg.ptr); status = lib->fetcher->fetch(lib->fetcher, complete_url, response, + FETCH_HTTP_VERSION_1_0, + FETCH_TIMEOUT, timeout, + FETCH_SOURCEIP, srcip, FETCH_END); } + DESTROY_IF(srcip); free(complete_url); return (status == SUCCESS); } -err_t scep_parse_response(chunk_t response, chunk_t transID, contentInfo_t *data, - scep_attributes_t *attrs, certificate_t *signer_cert) +err_t scep_parse_response(chunk_t response, chunk_t transID, + container_t **out, scep_attributes_t *attrs) { - chunk_t attributes; - - if (!pkcs7_parse_signedData(response, data, NULL, &attributes, signer_cert)) + enumerator_t *enumerator; + bool verified = FALSE; + container_t *container; + auth_cfg_t *auth; + + container = lib->creds->create(lib->creds, CRED_CONTAINER, CONTAINER_PKCS7, + BUILD_BLOB_ASN1_DER, response, BUILD_END); + if (!container) { return "error parsing the scep response"; } - if (!parse_attributes(attributes, attrs)) + if (container->get_type(container) != CONTAINER_PKCS7_SIGNED_DATA) { - return "error parsing the scep response attributes"; + container->destroy(container); + return "scep response is not PKCS#7 signed-data"; + } + + enumerator = container->create_signature_enumerator(container); + while (enumerator->enumerate(enumerator, &auth)) + { + verified = TRUE; + extract_attributes((pkcs7_t*)container, enumerator, attrs); + if (!chunk_equals(transID, attrs->transID)) + { + enumerator->destroy(enumerator); + container->destroy(container); + return "transaction ID of scep response does not match"; + } } - if (!chunk_equals(transID, attrs->transID)) + enumerator->destroy(enumerator); + if (!verified) { - return "transaction ID of scep response does not match"; + container->destroy(container); + return "unable to verify PKCS#7 container"; } + *out = container; return NULL; } diff --git a/src/scepclient/scep.h b/src/scepclient/scep.h index f64c6b1cc..4ef5eaf8e 100644 --- a/src/scepclient/scep.h +++ b/src/scepclient/scep.h @@ -1,11 +1,5 @@ -/** - * @file scep.h - * @brief SCEP specific functions - * - * Contains functions to build and parse SCEP requests and replies - */ - /* + * Copyright (C) 2012 Tobias Brunner * Copyright (C) 2005 Jan Hutter, Martin Willi * Hochschule fuer Technik Rapperswil * @@ -23,11 +17,9 @@ #ifndef _SCEP_H #define _SCEP_H +#include <credentials/containers/pkcs7.h> #include <credentials/certificates/certificate.h> -#include "../pluto/defs.h" -#include "../pluto/pkcs7.h" - /* supported SCEP operation types */ typedef enum { SCEP_PKI_OPERATION, @@ -74,22 +66,22 @@ typedef struct { extern const scep_attributes_t empty_scep_attributes; -extern bool parse_attributes(chunk_t blob, scep_attributes_t *attrs); -extern void scep_generate_transaction_id(public_key_t *key, - chunk_t *transID, - chunk_t *serialNumber); -extern chunk_t scep_generate_pkcs10_fingerprint(chunk_t pkcs10); -extern chunk_t scep_transId_attribute(chunk_t transaction_id); -extern chunk_t scep_messageType_attribute(scep_msg_t m); -extern chunk_t scep_senderNonce_attribute(void); -extern chunk_t scep_build_request(chunk_t data, chunk_t transID, scep_msg_t msg, - certificate_t *enc_cert, int enc_alg, - certificate_t *signer_cert, int digest_alg, - private_key_t *private_key); -extern bool scep_http_request(const char *url, chunk_t pkcs7, scep_op_t op, - bool http_get_request, chunk_t *response); -extern err_t scep_parse_response(chunk_t response, chunk_t transID, - contentInfo_t *data, scep_attributes_t *attrs, - certificate_t *signer_cert); +bool parse_attributes(chunk_t blob, scep_attributes_t *attrs); +void scep_generate_transaction_id(public_key_t *key, + chunk_t *transID, + chunk_t *serialNumber); +chunk_t scep_generate_pkcs10_fingerprint(chunk_t pkcs10); +chunk_t scep_transId_attribute(chunk_t transaction_id); +chunk_t scep_messageType_attribute(scep_msg_t m); +chunk_t scep_senderNonce_attribute(void); +chunk_t scep_build_request(chunk_t data, chunk_t transID, scep_msg_t msg, + certificate_t *enc_cert, encryption_algorithm_t enc_alg, + size_t key_size, certificate_t *signer_cert, + hash_algorithm_t digest_alg, private_key_t *private_key); +bool scep_http_request(const char *url, chunk_t msg, scep_op_t op, + bool http_get_request, u_int timeout, char *src, + chunk_t *response); +err_t scep_parse_response(chunk_t response, chunk_t transID, + container_t **out, scep_attributes_t *attrs); #endif /* _SCEP_H */ diff --git a/src/scepclient/scepclient.8 b/src/scepclient/scepclient.8 index 72750e155..bf71bf85c 100644 --- a/src/scepclient/scepclient.8 +++ b/src/scepclient/scepclient.8 @@ -1,5 +1,5 @@ -.\" -.TH "IPSEC_SCEPCLIENT" "8" "29 September 2005" "Jan Hutter, Martin Willi" "" +.\" +.TH "IPSEC_SCEPCLIENT" "8" "2012-05-11" "strongSwan" "" .SH "NAME" ipsec scepclient \- Client for the SCEP protocol .SH "SYNOPSIS" @@ -7,7 +7,7 @@ ipsec scepclient \- Client for the SCEP protocol .sp .B ipsec scepclient .B \-\-help -.br +.br .B ipsec scepclient .B \-\-version .SH "DESCRIPTION" @@ -19,7 +19,7 @@ is designed to be used for certificate enrollment on machines using the OpenSour .SH "FEATURES" .BR scepclient implements the following features of SCEP: -.br +.br .IP "\-" 4 Automatic enrollment of client certificate using a preshared secret .IP "\-" 4 @@ -31,7 +31,7 @@ Acquisition of CA certificate(s) .B \-v, \-\-version .RS 4 Display the version of ipsec scepclient. -.PP +.PP .RE .B \-h, \-\-help .RS 4 @@ -43,17 +43,17 @@ Display usage of ipsec scepclient. .RS 4 Full HTTP URL of the SCEP server to be used for certificate enrollment and CA certificate acquisition. .RE -.PP +.PP .B \-+, \-\-optionsfrom \fIfilename\fP .RS 4 Reads additional options from \fIfilename\fP. .RE -.PP +.PP .B \-f, \-\-force .RS 4 Overwrite existing output file[s]. .RE -.PP +.PP .B \-q, \-\-quiet .RS 4 Do not write log output to stderr. @@ -62,7 +62,9 @@ Do not write log output to stderr. .SS Options for CA Certificate Acquisition .B \-o, \-\-out cacert[=\fIfilename\fP] .RS 4 -Output file of acquired CA certificate. If more then one CA certificate is available, \fIfilename\fP is used as prefix for the resulting files. +Output file of acquired CA certificate. If more then one CA certificate is +available, \fIfilename\fP is used as prefix for the resulting files (refer to +EXAMPLES below for details). .br The default \fIfilename\fP is $CONFDIR/ipsec.d/cacerts/caCert.der. .RE @@ -70,41 +72,50 @@ The default \fIfilename\fP is $CONFDIR/ipsec.d/cacerts/caCert.der. .SS Options For Certificate Enrollment .B \-i, \-\-in \fItype\fP[=\fIfilename\fP] .RS 4 -Input file for certificate enrollment. This option can be specified multiple times to specify input files for every \fItype\fP. -Input files can bei either DER or PEM encoded. -.PP +Input file for certificate enrollment. This option can be specified multiple times to specify input files for every \fItype\fP. +Input files can be either DER or PEM encoded. +.PP Supported values for \fItype\fP: .IP "\fBpkcs1\fP" 12 RSA private key in PKCS#1 file format. If no input of this type is specified, a RSA key gets generated. .br The default \fIfilename\fP is $CONFDIR/ipsec.d/private/myKey.der. +.IP "\fBpkcs10\fP" 12 +PKCS#10 certificate request to be used in the SCEP request. If no input of this type is specified, a request is generated. +.br +The default \fIfilename\fP is $CONFDIR/ipsec.d/req/myReq.der. .IP "\fBcacert\-enc\fP" 12 -CA certificate to encrypt the SCEP request. Has to be specified for certificate enrollment. -.br +CA certificate to encrypt the SCEP request. Has to be specified for certificate enrollment. +.br The default \fIfilename\fP is $CONFDIR/ipsec.d/cacerts/caCert.der. .IP "\fBcacert\-sig\fP" 12 -CA certificate to check signature of SCEP reply. Has to be specified for certificate enrollment. -.br +CA certificate to check signature of SCEP reply. Has to be specified for certificate enrollment. +.br The default \fIfilename\fP is $CONFDIR/ipsec.d/cacerts/caCert.der. +.IP "\fBcert-self\fP" 12 +Certificate to be used in the SCEP request. If it is not specified a +self-signed certificate is generated automatically. +.br +The default \fIfilename\fP is $CONFDIR/ipsec.d/certs/selfCert.der. .RE -.PP +.PP .B \-k, \-\-keylength \fIbits\fP .RS 4 sets the key length for RSA key generation. The default length for a generated rsa key is set to 2048 bit. .RE -.PP +.PP .B \-D, \-\-days \fIdays\fP .RS 4 Validity of the self-signed X.509 certificate in days. The default is 1825 days (5 years). .RE -.PP +.PP .B \-S, \-\-startdate \fIYYMMDDHHMMSS\fPZ .RS 4 -defines the \fBnotBefore\fP date when the X.509 certificate becomes valid. +defines the \fBnotBefore\fP date when the X.509 certificate becomes valid. The date has the format \fIYYMMDDHHMMSS\fP and must be specified in UTC (Zulu time). If the \fB--startdate\fP option is not specified then the current date is taken as a default. .RE -.PP +.PP .B \-E, \-\-enddate \fIYYMMDDHHMMSS\fPZ .RS 4 defines the \fBnotAfter\fP date when the X.509 certificate will expire. @@ -118,12 +129,12 @@ adding the validity interval specified by the \fB--days\fP option to the \fBnotB Distinguished name as comma separated list of relative distinguished names. Use quotation marks for a distinguished name containing spaces. If the \fB\-\-dn\fP parameter is missing then the default "C=CH, O=Linux strongSwan, CN=\fIhostname\fP" is used with \fIhostname\fP being the return value of the \fIgethostname\fP() function. .RE -.PP +.PP .B \-s, \-\-subjectAltName \fItype\fP=\fIvalue\fP .RS 4 Include subjectAltName in certificate request. This option can be specified multiple times to specify a subjectAltName for every \fItype\fP. -.PP +.PP Supported values for \fItype\fP: .IP "\fBemail\fP" 12 subjectAltName is a email address. @@ -132,25 +143,35 @@ subjectAltName is a hostname. .IP "\fBip\fP" 12 subjectAltName is a IP address. .RE -.PP +.PP .B \-p, \-\-password \fIpw\fP .RS 4 Password to be included as a \fIchallenge password\fP in SCEP request. If \fIpw\fP is \fB%prompt\fP', the password gets prompted for on the command line. .IP \- In automatic mode, this password corresponds to the preshared secret for the given enrollment. -.IP +.IP \- In manual mode, this password can be used to later revoke the corresponding certificate. .RE -.PP -.B \-a, \-\-algorithm \fIalgo\fP +.PP +.B \-a, \-\-algorithm [\fItype\fP=]\fIalgo\fP .RS 4 -Change symmetric algorithm to use for encryption of certificate Request. -The default is \fB3des\-cbc\fP. -.PP -Supported values for \fIalgo\fP: +Change the algorithms to be used when generating and transporting (PKCS#7) +certificate requests (PKCS#10). +.PP +Supported values for \fItype\fP: +.IP "\fBenc\fP" 12 +symmetric encryption algorithm in PKCS#7 +.IP "\fBdgst\fP" 12 +hash algorithm for message digest in PKCS#7 +.IP "\fBsig\fP" 12 +hash algorithm for the signature in PKCS#10 +.PP +If \fItype\fP is not specified \fBenc\fP is assumed. +.PP +Supported values for \fIalgo\fP (\fBenc\fP): .IP "\fBdes\fP" 12 -DES-CBC encryption (key size = 56 bit). +DES-CBC encryption (key size = 56 bit). Default. .IP "\fB3des\fP" 12 Triple DES-EDE-CBC encryption (key size = 168 bit). .IP "\fBaes128\fP" 12 @@ -165,56 +186,60 @@ Camellia-CBC encryption (key size = 128 bit). Camelllia-CBC encryption (key size = 192 bit). .IP "\fBcamellia256\fP" 12 Camellia-CBC encryption (key size = 256 bit). +.PP +Supported values for \fIalgo\fP (\fBdgst\fP or \fBsig\fP): +.PP +\fBmd5\fP (default), \fBsha1\fP, \fBsha256\fP, \fBsha384\fP, \fBsha512\fP .RE -.PP +.PP .B \-o, \-\-out \fItype\fP[=\fIfilename\fP] .RS 4 Output file for certificate enrollment. This option can be specified multiple times to specify output files for every \fItype\fP. -.PP +.PP Supported values for \fItype\fP: .IP "\fBpkcs1\fP" 12 RSA private key in PKCS#1 file format. If specified, the RSA key used for enrollment is stored in file \fIfilename\fP. If none of the \fItypes\fP listed below are specified, \fBscepclient\fP will stop after outputting this file. -.br +.br The default \fIfilename\fP is $CONFDIR/ipsec.d/private/myKey.der. .IP "\fBpkcs10\fP" 12 PKCS#10 certificate request. If specified, the PKCS#10 request used or certificate enrollment is stored in file \fIfilename\fP. -If none of the \fItypes\fP listed below are specified, \fBscepclient\fP will stop after outputting this file. -.br +If none of the \fItypes\fP listed below are specified, \fBscepclient\fP will stop after outputting this file. +.br The default \fIfilename\fP is $CONFDIR/ipsec.d/req/myReq.der. .IP "\fBpkcs7\fP" 12 PKCS#7 SCEP request as it is sent using HTTP to the SCEP server. If specified, this SCEP request is stored in file \fIfilename\fP. If none of \fItypes\fP listed below is not specified, \fBscepclient\fP will stop after outputting this file. -.br +.br The default \fIfilename\fP is $CONFDIR/ipsec.d/req/pkcs7.der. .IP "\fBcert-self\fP" 12 Self-signed certificate. If specified the self-signed certificate is stored in file \fIfilename\fP. -.br +.br The default \fIfilename\fP is $CONFDIR/ipsec.d/certs/selfCert.der. .IP "\fBcert\fP" 12 Enrolled certificate. This \fItype\fP must be specified for certificate enrollment. The enrolled certificate is stored in file \fIfilename\fP. -.br +.br The default \fIfilename\fP is set to $CONFDIR/ipsec.d/certs/myCert.der. .RE -.PP +.PP .B \-m, \-\-method \fImethod\fP .RS 4 Change HTTP request method for certificate enrollment. Default is \fBget\fP. -.PP +.PP Supported values for \fImethod\fP: .IP "\fBpost\fP" 12 Certificate enrollment using HTTP POST. Must be supported by the given SCEP server. .IP "\fBget\fP" 12 Certificate enrollment using HTTP GET. .RE -.PP +.PP .B \-t, \-\-interval \fIseconds\fP .RS 4 Set interval time in seconds when polling in manual mode. The default interval is set to 5 seconds. .RE -.PP +.PP .B \-x, \-\-maxpolltime \fIseconds\fP .RS 4 Set max time in seconds to poll in manual mode. @@ -222,64 +247,41 @@ The default max time is set to unlimited. .RE .SS Debugging Output Options: -.B \-A, \-\-debug\-all -.RS 4 -Log everything except private data. -.RE -.PP -.B \-P, \-\-debug\-parsing -.RS 4 -Log parsing relevant stuff. -.RE -.PP -.B \-R, \-\-debug\-raw +.B \-l, \-\-debug \fIlevel\fP .RS 4 -Log raw hex dumps. -.RE -.PP -.B \-C, \-\-debug\-control -.RS 4 -Log information about control flow. -.RE -.PP -.B \-M, \-\-debug\-controlmore -.RS 4 -Log more detailed information about control flow. -.RE -.PP -.B \-X, \-\-debug\-private -.RS 4 -Log sensitive data (e.g. private keys). +Changes the log level (-1..4, default: 1) .RE .SH "EXAMPLES" .B ipsec scepclient \-\-out caCert \-\-url http://scepserver/cgi\-bin/pkiclient.exe \-f .RS 4 Acquire CA certificate from SCEP server and store it in the default file $CONFDIR/ipsec.d/cacerts/caCert.der. -If more then one CA certificate is returned, store them in files named caCert.der\-1', caCert.der\-2', etc. -.br -Existing files are overwritten. +If more then one CA certificate is returned, store them in files named +\'caCert\-1.der\', \'caCert\-2.der\', etc. +If an RA certificate is returned, store it in a file named \'caCert\-ra.der\'. +If more than one RA certificate is returned, store them in files named +\'caCert\-ra\-1.der\', \'caCert\-ra\-2.der\', etc. .RE -.PP +.PP .B ipsec scepclient \-\-out pkcs1=joeKey.der \-k 1024 .RS 4 Generate RSA private key with key length of 1024 bit and store it in file joeKey.der. .RE -.PP +.PP .B ipsec scepclient \-\-in pkcs1=joeKey.der \-\-out pkcs10=joeReq.der \e -.br +.br .B \-\-dn \*(rqC=AT, CN=John Doe\*(rq \-s email=john@doe.com \-p mypassword .RS 4 Generate a PKCS#10 request and store it in file joeReq.der. Use the RSA private key joeKey.der -created earlier to sign the PKCS#10\-Request. In addition to the distinguished name include a +created earlier to sign the PKCS#10\-Request. In addition to the distinguished name include a email\-subjectAltName and a challenge password in the request. .RE -.PP +.PP .B ipsec scepclient \-\-out pkcs1=joeKey.der \-\-out cert==joeCert.der \e -.br +.br .B \-\-dn \*(rqC=CH, CN=John Doe\*(rq \-k 512 \-p 5xH2pnT7wq \e -.br +.br .B \-\-url http://scep.hsr.ch/cgi\-bin/pkiclient.exe \e -.br +.br .B \-\-in cacert\-enc=caCert.der \-\-in cacert\-sig=caCert.der .RS 4 Generate a new RSA key for the request and store it in joeKey.der. Then enroll a certificate and store as joeCert.der. @@ -292,9 +294,9 @@ caCert.der. \fB\-\-optionsfrom\fP seems to have parsing problems reading option files containing strings in quotation marks. .SH "COPYRIGHT" Copyright (C) 2005 Jan Hutter, Martin Willi -.br +.br Hochschule fuer Technik Rapperswil -.PP +.PP 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>. -.PP +.PP 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. diff --git a/src/scepclient/scepclient.c b/src/scepclient/scepclient.c index 0b54eeee3..1267370ba 100644 --- a/src/scepclient/scepclient.c +++ b/src/scepclient/scepclient.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2012 Tobias Brunner * Copyright (C) 2005 Jan Hutter, Martin Willi * Hochschule fuer Technik Rapperswil * @@ -13,17 +14,6 @@ * for more details. */ -/** - * @file main.c - * @brief scepclient main program - */ - -/** - * @mainpage SCEP for Linux strongSwan - * - * Documentation of SCEP for Linux StrongSwan - */ - #include <stdarg.h> #include <stdio.h> #include <stdlib.h> @@ -32,16 +22,16 @@ #include <ctype.h> #include <unistd.h> #include <time.h> - -#include <freeswan.h> +#include <limits.h> +#include <syslog.h> #include <library.h> -#include <debug.h> +#include <utils/debug.h> #include <asn1/asn1.h> #include <asn1/oid.h> #include <utils/optionsfrom.h> -#include <utils/enumerator.h> -#include <utils/linked_list.h> +#include <collections/enumerator.h> +#include <collections/linked_list.h> #include <crypto/hashers/hasher.h> #include <crypto/crypters/crypter.h> #include <crypto/proposal/proposal_keywords.h> @@ -50,20 +40,21 @@ #include <credentials/certificates/certificate.h> #include <credentials/certificates/x509.h> #include <credentials/certificates/pkcs10.h> +#include <credentials/sets/mem_cred.h> #include <plugins/plugin.h> -#include "../pluto/constants.h" -#include "../pluto/defs.h" -#include "../pluto/log.h" -#include "../pluto/certs.h" -#include "../pluto/pkcs7.h" - #include "scep.h" /* * definition of some defaults */ +/* some paths */ +#define REQ_PATH IPSEC_CONFDIR "/ipsec.d/reqs" +#define HOST_CERT_PATH IPSEC_CONFDIR "/ipsec.d/certs" +#define CA_CERT_PATH IPSEC_CONFDIR "/ipsec.d/cacerts" +#define PRIVATE_KEY_PATH IPSEC_CONFDIR "/ipsec.d/private" + /* default name of DER-encoded PKCS#1 private key file */ #define DEFAULT_FILENAME_PKCS1 "myKey.der" @@ -100,6 +91,9 @@ /* default distinguished name */ #define DEFAULT_DN "C=CH, O=Linux strongSwan, CN=" +/* minimum RSA key size */ +#define RSA_MIN_OCTETS (512 / BITS_PER_BYTE) + /* challenge password buffer size */ #define MAX_PASSWORD_LENGTH 256 @@ -119,13 +113,18 @@ long crl_check_interval = 0; /* by default pluto logs out after every smartcard use */ bool pkcs11_keep_state = FALSE; +/* by default HTTP fetch timeout is 30s */ +static u_int http_timeout = 30; + +/* address to bind for HTTP fetches */ +static char* http_bind = NULL; + /* options read by optionsfrom */ options_t *options; /* * Global variables */ - chunk_t pkcs1; chunk_t pkcs7; chunk_t challengePassword; @@ -148,16 +147,129 @@ certificate_t *x509_ca_enc = NULL; certificate_t *x509_ca_sig = NULL; certificate_t *pkcs10_req = NULL; +mem_cred_t *creds = NULL; + +/* logging */ +static bool log_to_stderr = TRUE; +static bool log_to_syslog = TRUE; +static level_t default_loglevel = 1; + +/** + * logging function for scepclient + */ +static void scepclient_dbg(debug_t group, level_t level, char *fmt, ...) +{ + char buffer[8192]; + char *current = buffer, *next; + va_list args; + + if (level <= default_loglevel) + { + if (log_to_stderr) + { + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); + fprintf(stderr, "\n"); + } + if (log_to_syslog) + { + /* write in memory buffer first */ + va_start(args, fmt); + vsnprintf(buffer, sizeof(buffer), fmt, args); + va_end(args); + + /* do a syslog with every line */ + while (current) + { + next = strchr(current, '\n'); + if (next) + { + *(next++) = '\0'; + } + syslog(LOG_INFO, "%s\n", current); + current = next; + } + } + } +} + +/** + * Initialize logging to stderr/syslog + */ +static void init_log(const char *program) +{ + dbg = scepclient_dbg; + + if (log_to_stderr) + { + setbuf(stderr, NULL); + } + if (log_to_syslog) + { + openlog(program, LOG_CONS | LOG_NDELAY | LOG_PID, LOG_AUTHPRIV); + } +} + +/** + * join two paths if filename is not absolute + */ +static void join_paths(char *target, size_t target_size, char *parent, + char *filename) +{ + if (*filename == '/' || *filename == '.') + { + snprintf(target, target_size, "%s", filename); + } + else + { + snprintf(target, target_size, "%s/%s", parent, filename); + } +} + +/** + * add a suffix to a given filename, properly handling extensions like '.der' + */ +static void add_path_suffix(char *target, size_t target_size, char *filename, + char *suffix_fmt, ...) +{ + char suffix[PATH_MAX], *start, *dot; + va_list args; + + va_start(args, suffix_fmt); + vsnprintf(suffix, sizeof(suffix), suffix_fmt, args); + va_end(args); + + start = strrchr(filename, '/'); + start = start ?: filename; + dot = strrchr(start, '.'); + + if (!dot || dot == start || dot[1] == '\0') + { /* no extension add suffix at the end */ + snprintf(target, target_size, "%s%s", filename, suffix); + } + else + { /* add the suffix between the filename and the extension */ + snprintf(target, target_size, "%.*s%s%s", (int)(dot - filename), + filename, suffix, dot); + } +} + /** * @brief exit scepclient * * @param status 0 = OK, 1 = general discomfort */ -static void -exit_scepclient(err_t message, ...) +static void exit_scepclient(err_t message, ...) { int status = 0; + if (creds) + { + lib->credmgr->remove_set(lib->credmgr, &creds->set); + creds->destroy(creds); + } + DESTROY_IF(subject); DESTROY_IF(private_key); DESTROY_IF(public_key); @@ -183,7 +295,7 @@ exit_scepclient(err_t message, ...) if (message != NULL && *message != '\0') { va_list args; - char m[LOG_WIDTH]; /* longer messages will be truncated */ + char m[8192]; va_start(args, message); vsnprintf(m, sizeof(m), message, args); @@ -193,7 +305,6 @@ exit_scepclient(err_t message, ...) status = -1; } library_deinit(); - close_log(); exit(status); } @@ -201,8 +312,7 @@ exit_scepclient(err_t message, ...) * @brief prints the program version and exits * */ -static void -version(void) +static void version(void) { printf("scepclient %s\n", scepclient_version); exit_scepclient(NULL); @@ -214,31 +324,38 @@ version(void) * If message is set, program is exitet with 1 (error) * @param message message in case of an error */ -static void -usage(const char *message) +static void usage(const char *message) { fprintf(stderr, "Usage: scepclient\n" " --help (-h) show usage and exit\n" " --version (-v) show version and exit\n" " --quiet (-q) do not write log output to stderr\n" - " --in (-i) <type>[=<filename>] use <filename> of <type> for input \n" - " <type> = pkcs1 | cacert-enc | cacert-sig\n" - " - if no pkcs1 input is defined, a \n" - " RSA key will be generated\n" + " --in (-i) <type>[=<filename>] use <filename> of <type> for input\n" + " <type> = pkcs1 | pkcs10 | cert-self\n" + " cacert-enc | cacert-sig\n" + " - if no pkcs1 input is defined, an RSA\n" + " key will be generated\n" + " - if no pkcs10 input is defined, a\n" + " PKCS#10 request will be generated\n" + " - if no cert-self input is defined, a\n" + " self-signed certificate will be generated\n" " - if no filename is given, default is used\n" " --out (-o) <type>[=<filename>] write output of <type> to <filename>\n" " multiple outputs are allowed\n" - " <type> = pkcs1 | pkcs10 | pkcs7 | cert-self | cert | cacert\n" + " <type> = pkcs1 | pkcs10 | pkcs7 | cert-self |\n" + " cert | cacert\n" " - type cacert defines filename prefix of\n" " received CA certificate(s)\n" " - if no filename is given, default is used\n" " --optionsfrom (-+) <filename> reads additional options from given file\n" " --force (-f) force existing file(s)\n" + " --httptimeout (-T) timeout for HTTP operations (default: 30s)\n" + " --bind (-b) source address to bind for HTTP operations\n" "\n" "Options for key generation (pkcs1):\n" " --keylength (-k) <bits> key length for RSA key generation\n" - "(default: 2048 bits)\n" + " (default: 2048 bits)\n" "\n" "Options for validity:\n" " --days (-D) <days> validity in days\n" @@ -250,27 +367,29 @@ usage(const char *message) " --subjectAltName (-s) <t>=<v> include subjectAltName in certificate request\n" " <t> = email | dns | ip \n" " --password (-p) <pw> challenge password\n" - " - if pw is '%%prompt', password gets prompted for\n" - " --algorithm (-a) <algo> use specified algorithm for PKCS#7 encryption\n" - " <algo> = des | 3des (default) | aes128| aes192 | \n" - " aes256 | camellia128 | camellia192 | camellia256\n" + " - use '%%prompt' as pw for a password prompt\n" + " --algorithm (-a) [<type>=]<algo> algorithm to be used for PKCS#7 encryption,\n" + " PKCS#7 digest or PKCS#10 signature\n" + " <type> = enc | dgst | sig\n" + " - if no type is given enc is assumed\n" + " <algo> = des (default) | 3des | aes128 |\n" + " aes192 | aes256 | camellia128 |\n" + " camellia192 | camellia256\n" + " <algo> = md5 (default) | sha1 | sha256 |\n" + " sha384 | sha512\n" "\n" + "Options for CA certificate acquisition:\n" + " --caname (-c) <name> name of CA to fetch CA certificate(s)\n" + " (default: CAIdentifier)\n" "Options for enrollment (cert):\n" " --url (-u) <url> url of the SCEP server\n" " --method (-m) post | get http request type\n" - " --interval (-t) <seconds> manual mode poll interval in seconds (default 20s)\n" + " --interval (-t) <seconds> poll interval in seconds (default 20s)\n" " --maxpolltime (-x) <seconds> max poll time in seconds when in manual mode\n" " (default: unlimited)\n" -#ifdef DEBUG "\n" "Debugging output:\n" - " --debug-all (-A) show everything except private\n" - " --debug-parsing (-P) show parsing relevant stuff\n" - " --debug-raw (-R) show raw hex dumps\n" - " --debug-control (-C) show control flow output\n" - " --debug-controlmore (-M) show more control flow\n" - " --debug-private (-X) show sensitive data (private keys, etc.)\n" -#endif + " --debug (-l) <level> changes the log level (-1..4, default: 1)\n" ); exit_scepclient(message); } @@ -295,7 +414,7 @@ int main(int argc, char **argv) CERT_SELF = 0x08, CERT = 0x10, CACERT_ENC = 0x20, - CACERT_SIG = 0x40 + CACERT_SIG = 0x40, } scep_filetype_t; /* filetype to read from, defaults to "generate a key" */ @@ -306,6 +425,8 @@ int main(int argc, char **argv) /* input files */ char *file_in_pkcs1 = DEFAULT_FILENAME_PKCS1; + char *file_in_pkcs10 = DEFAULT_FILENAME_PKCS10; + char *file_in_cert_self = DEFAULT_FILENAME_CERT_SELF; char *file_in_cacert_enc = DEFAULT_FILENAME_CACERT_ENC; char *file_in_cacert_sig = DEFAULT_FILENAME_CACERT_SIG; @@ -337,18 +458,22 @@ int main(int argc, char **argv) /* challenge password */ char challenge_password_buffer[MAX_PASSWORD_LENGTH]; - /* symmetric encryption algorithm used by pkcs7, default is 3DES */ - int pkcs7_symmetric_cipher = OID_3DES_EDE_CBC; + /* symmetric encryption algorithm used by pkcs7, default is DES */ + encryption_algorithm_t pkcs7_symmetric_cipher = ENCR_DES; + size_t pkcs7_key_size = 0; - /* digest algorithm used by pkcs7, default is SHA-1 */ - int pkcs7_digest_alg = OID_SHA1; + /* digest algorithm used by pkcs7, default is MD5 */ + hash_algorithm_t pkcs7_digest_alg = HASH_MD5; - /* signature algorithm used by pkcs10, default is SHA-1 */ - hash_algorithm_t pkcs10_signature_alg = HASH_SHA1; + /* signature algorithm used by pkcs10, default is MD5 */ + hash_algorithm_t pkcs10_signature_alg = HASH_MD5; /* URL of the SCEP-Server */ char *scep_url = NULL; + /* Name of CA to fetch CA certs for */ + char *ca_name = "CAIdentifier"; + /* http request method, default is GET */ bool http_get_request = TRUE; @@ -388,7 +513,6 @@ int main(int argc, char **argv) scep_response = chunk_empty; subjectAltNames = linked_list_create(); options = options_create(); - log_to_stderr = TRUE; for (;;) { @@ -398,9 +522,12 @@ int main(int argc, char **argv) { "version", no_argument, NULL, 'v' }, { "optionsfrom", required_argument, NULL, '+' }, { "quiet", no_argument, NULL, 'q' }, + { "debug", required_argument, NULL, 'l' }, { "in", required_argument, NULL, 'i' }, { "out", required_argument, NULL, 'o' }, { "force", no_argument, NULL, 'f' }, + { "httptimeout", required_argument, NULL, 'T' }, + { "bind", required_argument, NULL, 'b' }, { "keylength", required_argument, NULL, 'k' }, { "dn", required_argument, NULL, 'd' }, { "days", required_argument, NULL, 'D' }, @@ -410,39 +537,36 @@ int main(int argc, char **argv) { "password", required_argument, NULL, 'p' }, { "algorithm", required_argument, NULL, 'a' }, { "url", required_argument, NULL, 'u' }, + { "caname", required_argument, NULL, 'c'}, { "method", required_argument, NULL, 'm' }, { "interval", required_argument, NULL, 't' }, { "maxpolltime", required_argument, NULL, 'x' }, -#ifdef DEBUG - { "debug-all", no_argument, NULL, 'A' }, - { "debug-parsing", no_argument, NULL, 'P'}, - { "debug-raw", no_argument, NULL, 'R'}, - { "debug-control", no_argument, NULL, 'C'}, - { "debug-controlmore", no_argument, NULL, 'M'}, - { "debug-private", no_argument, NULL, 'X'}, -#endif { 0,0,0,0 } }; /* parse next option */ - int c = getopt_long(argc, argv, "hv+:qi:o:fk:d:s:p:a:u:m:t:x:APRCMS", long_opts, NULL); + int c = getopt_long(argc, argv, "hv+:qi:o:fk:d:s:p:a:u:c:m:t:x:APRCMS", long_opts, NULL); switch (c) { - case EOF: /* end of flags */ - break; + case EOF: /* end of flags */ + break; - case 'h': /* --help */ - usage(NULL); + case 'h': /* --help */ + usage(NULL); - case 'v': /* --version */ - version(); + case 'v': /* --version */ + version(); - case 'q': /* --quiet */ - log_to_stderr = FALSE; - continue; + case 'q': /* --quiet */ + log_to_stderr = FALSE; + continue; + + case 'l': /* --debug <level> */ + default_loglevel = atoi(optarg); + continue; - case 'i': /* --in <type> [= <filename>] */ + case 'i': /* --in <type> [= <filename>] */ { char *filename = strstr(optarg, "="); @@ -459,6 +583,12 @@ int main(int argc, char **argv) if (filename) file_in_pkcs1 = filename; } + else if (strcaseeq("pkcs10", optarg)) + { + filetype_in |= PKCS10; + if (filename) + file_in_pkcs10 = filename; + } else if (strcaseeq("cacert-enc", optarg)) { filetype_in |= CACERT_ENC; @@ -469,7 +599,13 @@ int main(int argc, char **argv) { filetype_in |= CACERT_SIG; if (filename) - file_in_cacert_sig = filename; + file_in_cacert_sig = filename; + } + else if (strcaseeq("cert-self", optarg)) + { + filetype_in |= CERT_SELF; + if (filename) + file_in_cert_self = filename; } else { @@ -478,7 +614,7 @@ int main(int argc, char **argv) continue; } - case 'o': /* --out <type> [= <filename>] */ + case 'o': /* --out <type> [= <filename>] */ { char *filename = strstr(optarg, "="); @@ -532,18 +668,30 @@ int main(int argc, char **argv) continue; } - case 'f': /* --force */ - force = TRUE; - continue; + case 'f': /* --force */ + force = TRUE; + continue; - case '+': /* --optionsfrom <filename> */ - if (!options->from(options, optarg, &argc, &argv, optind)) - { - exit_scepclient("optionsfrom failed"); - } - continue; + case 'T': /* --httptimeout */ + http_timeout = atoi(optarg); + if (http_timeout <= 0) + { + usage("invalid httptimeout specified"); + } + continue; + + case 'b': /* --bind */ + http_bind = optarg; + continue; + + case '+': /* --optionsfrom <filename> */ + if (!options->from(options, optarg, &argc, &argv, optind)) + { + exit_scepclient("optionsfrom failed"); + } + continue; - case 'k': /* --keylength <length> */ + case 'k': /* --keylength <length> */ { div_t q; @@ -561,45 +709,56 @@ int main(int argc, char **argv) continue; } - case 'D': /* --days */ - if (optarg == NULL || !isdigit(optarg[0])) - usage("missing number of days"); - { - char *endptr; - long days = strtol(optarg, &endptr, 0); + case 'D': /* --days */ + if (optarg == NULL || !isdigit(optarg[0])) + { + usage("missing number of days"); + } + else + { + char *endptr; + long days = strtol(optarg, &endptr, 0); - if (*endptr != '\0' || endptr == optarg - || days <= 0) - usage("<days> must be a positive number"); - validity = 24*3600*days; - } - continue; + if (*endptr != '\0' || endptr == optarg + || days <= 0) + usage("<days> must be a positive number"); + validity = 24*3600*days; + } + continue; - case 'S': /* --startdate */ - if (optarg == NULL || strlen(optarg) != 13 || optarg[12] != 'Z') - usage("date format must be YYMMDDHHMMSSZ"); - { - chunk_t date = { optarg, 13 }; - notBefore = asn1_to_time(&date, ASN1_UTCTIME); - } - continue; + case 'S': /* --startdate */ + if (optarg == NULL || strlen(optarg) != 13 || optarg[12] != 'Z') + { + usage("date format must be YYMMDDHHMMSSZ"); + } + else + { + chunk_t date = { optarg, 13 }; + notBefore = asn1_to_time(&date, ASN1_UTCTIME); + } + continue; - case 'E': /* --enddate */ - if (optarg == NULL || strlen(optarg) != 13 || optarg[12] != 'Z') - usage("date format must be YYMMDDHHMMSSZ"); - { - chunk_t date = { optarg, 13 }; - notAfter = asn1_to_time(&date, ASN1_UTCTIME); - } - continue; + case 'E': /* --enddate */ + if (optarg == NULL || strlen(optarg) != 13 || optarg[12] != 'Z') + { + usage("date format must be YYMMDDHHMMSSZ"); + } + else + { + chunk_t date = { optarg, 13 }; + notAfter = asn1_to_time(&date, ASN1_UTCTIME); + } + continue; - case 'd': /* --dn */ - if (distinguishedName) - usage("only one distinguished name allowed"); - distinguishedName = optarg; - continue; + case 'd': /* --dn */ + if (distinguishedName) + { + usage("only one distinguished name allowed"); + } + distinguishedName = optarg; + continue; - case 's': /* --subjectAltName */ + case 's': /* --subjectAltName */ { char *value = strstr(optarg, "="); @@ -612,7 +771,7 @@ int main(int argc, char **argv) } if (strcaseeq("email", optarg) || - strcaseeq("dns", optarg) || + strcaseeq("dns", optarg) || strcaseeq("ip", optarg)) { subjectAltNames->insert_last(subjectAltNames, @@ -626,126 +785,155 @@ int main(int argc, char **argv) } } - case 'p': /* --password */ - if (challengePassword.len > 0) - { - usage("only one challenge password allowed"); - } - if (strcaseeq("%prompt", optarg)) - { - printf("Challenge password: "); - if (fgets(challenge_password_buffer, sizeof(challenge_password_buffer)-1, stdin)) + case 'p': /* --password */ + if (challengePassword.len > 0) + { + usage("only one challenge password allowed"); + } + if (strcaseeq("%prompt", optarg)) { - challengePassword.ptr = challenge_password_buffer; - /* discard the terminating '\n' from the input */ - challengePassword.len = strlen(challenge_password_buffer) - 1; + printf("Challenge password: "); + if (fgets(challenge_password_buffer, + sizeof(challenge_password_buffer) - 1, stdin)) + { + challengePassword.ptr = challenge_password_buffer; + /* discard the terminating '\n' from the input */ + challengePassword.len = strlen(challenge_password_buffer) - 1; + } + else + { + usage("challenge password could not be read"); + } } else { - usage("challenge password could not be read"); + challengePassword.ptr = optarg; + challengePassword.len = strlen(optarg); } - } - else - { - challengePassword.ptr = optarg; - challengePassword.len = strlen(optarg); - } - continue; + continue; - case 'u': /* -- url */ - if (scep_url) - { - usage("only one URL argument allowed"); - } - scep_url = optarg; - continue; + case 'u': /* -- url */ + if (scep_url) + { + usage("only one URL argument allowed"); + } + scep_url = optarg; + continue; - case 'm': /* --method */ - if (strcaseeq("get", optarg)) - { - http_get_request = TRUE; - } - else if (strcaseeq("post", optarg)) - { - http_get_request = FALSE; - } - else - { - usage("invalid http request method specified"); - } - continue; + case 'c': /* -- caname */ + ca_name = optarg; + continue; - case 't': /* --interval */ - poll_interval = atoi(optarg); - if (poll_interval <= 0) - { - usage("invalid interval specified"); - } - continue; + case 'm': /* --method */ + if (strcaseeq("get", optarg)) + { + http_get_request = TRUE; + } + else if (strcaseeq("post", optarg)) + { + http_get_request = FALSE; + } + else + { + usage("invalid http request method specified"); + } + continue; - case 'x': /* --maxpolltime */ - max_poll_time = atoi(optarg); - continue; + case 't': /* --interval */ + poll_interval = atoi(optarg); + if (poll_interval <= 0) + { + usage("invalid interval specified"); + } + continue; - case 'a': /*--algorithm */ - { - const proposal_token_t *token; + case 'x': /* --maxpolltime */ + max_poll_time = atoi(optarg); + continue; - token = proposal_get_token(optarg, strlen(optarg)); - if (token == NULL || token->type != ENCRYPTION_ALGORITHM) + case 'a': /*--algorithm [<type>=]algo */ { - usage("invalid algorithm specified"); - } - pkcs7_symmetric_cipher = encryption_algorithm_to_oid( - token->algorithm, token->keysize); - if (pkcs7_symmetric_cipher == OID_UNKNOWN) - { - usage("unsupported encryption algorithm specified"); + const proposal_token_t *token; + char *type = optarg; + char *algo = strstr(optarg, "="); + + if (algo) + { + *algo = '\0'; + algo++; + } + else + { + type = "enc"; + algo = optarg; + } + + if (strcaseeq("enc", type)) + { + token = lib->proposal->get_token(lib->proposal, algo); + if (token == NULL || token->type != ENCRYPTION_ALGORITHM) + { + usage("invalid algorithm specified"); + } + pkcs7_symmetric_cipher = token->algorithm; + pkcs7_key_size = token->keysize; + if (encryption_algorithm_to_oid(token->algorithm, + token->keysize) == OID_UNKNOWN) + { + usage("unsupported encryption algorithm specified"); + } + } + else if (strcaseeq("dgst", type) || + strcaseeq("sig", type)) + { + hash_algorithm_t hash; + + token = lib->proposal->get_token(lib->proposal, algo); + if (token == NULL || token->type != INTEGRITY_ALGORITHM) + { + usage("invalid algorithm specified"); + } + hash = hasher_algorithm_from_integrity(token->algorithm, + NULL); + if (hash == OID_UNKNOWN) + { + usage("invalid algorithm specified"); + } + if (strcaseeq("dgst", type)) + { + pkcs7_digest_alg = hash; + } + else + { + pkcs10_signature_alg = hash; + } + } + else + { + usage("invalid --algorithm type"); + } + continue; } - continue; - } -#ifdef DEBUG - case 'A': /* --debug-all */ - base_debugging |= DBG_ALL; - continue; - case 'P': /* debug parsing */ - base_debugging |= DBG_PARSING; - continue; - case 'R': /* debug raw */ - base_debugging |= DBG_RAW; - continue; - case 'C': /* debug control */ - base_debugging |= DBG_CONTROL; - continue; - case 'M': /* debug control more */ - base_debugging |= DBG_CONTROLMORE; - continue; - case 'X': /* debug private */ - base_debugging |= DBG_PRIVATE; - continue; -#endif - default: - usage("unknown option"); + default: + usage("unknown option"); } /* break from loop */ break; } - cur_debugging = base_debugging; init_log("scepclient"); /* load plugins, further infrastructure may need it */ - if (!lib->plugins->load(lib->plugins, NULL, + if (!lib->plugins->load(lib->plugins, lib->settings->get_str(lib->settings, "scepclient.load", PLUGINS))) { exit_scepclient("plugin loading failed"); } - DBG1(DBG_LIB, " loaded plugins: %s", - lib->plugins->loaded_plugins(lib->plugins)); + lib->plugins->status(lib->plugins, LEVEL_DIAG); if ((filetype_out == 0) && (!request_ca_certificate)) { - usage ("--out filetype required"); + usage("--out filetype required"); } if (request_ca_certificate && (filetype_out > 0 || filetype_in > 0)) { @@ -767,27 +955,107 @@ int main(int argc, char **argv) /* get CA cert */ if (request_ca_certificate) { - char *path = concatenate_paths(CA_CERT_PATH, file_out_ca_cert); + char ca_path[PATH_MAX]; + container_t *container; + pkcs7_t *pkcs7; - if (!scep_http_request(scep_url, chunk_empty, SCEP_GET_CA_CERT, - http_get_request, &scep_response)) + if (!scep_http_request(scep_url, chunk_create(ca_name, strlen(ca_name)), + SCEP_GET_CA_CERT, http_get_request, + http_timeout, http_bind, &scep_response)) { exit_scepclient("did not receive a valid scep response"); } - if (!chunk_write(scep_response, path, "ca cert", 0022, force)) + join_paths(ca_path, sizeof(ca_path), CA_CERT_PATH, file_out_ca_cert); + + pkcs7 = lib->creds->create(lib->creds, CRED_CONTAINER, CONTAINER_PKCS7, + BUILD_BLOB_ASN1_DER, scep_response, BUILD_END); + + if (!pkcs7) + { /* no PKCS#7 encoded CA+RA certificates, assume simple CA cert */ + + DBG1(DBG_APP, "unable to parse PKCS#7, assuming plain CA cert"); + if (!chunk_write(scep_response, ca_path, "ca cert", 0022, force)) + { + exit_scepclient("could not write ca cert file '%s'", ca_path); + } + } + else { - exit_scepclient("could not write ca cert file '%s'", path); + enumerator_t *enumerator; + certificate_t *cert; + int ra_certs = 0, ca_certs = 0; + int ra_index = 1, ca_index = 1; + + enumerator = pkcs7->create_cert_enumerator(pkcs7); + while (enumerator->enumerate(enumerator, &cert)) + { + x509_t *x509 = (x509_t*)cert; + if (x509->get_flags(x509) & X509_CA) + { + ca_certs++; + } + else + { + ra_certs++; + } + } + enumerator->destroy(enumerator); + + enumerator = pkcs7->create_cert_enumerator(pkcs7); + while (enumerator->enumerate(enumerator, &cert)) + { + x509_t *x509 = (x509_t*)cert; + bool ca_cert = x509->get_flags(x509) & X509_CA; + char cert_path[PATH_MAX], *path = ca_path; + + if (ca_cert && ca_certs > 1) + { + add_path_suffix(cert_path, sizeof(cert_path), ca_path, + "-%.1d", ca_index++); + path = cert_path; + } + else if (!ca_cert) + { /* use CA name as base for RA certs */ + if (ra_certs > 1) + { + add_path_suffix(cert_path, sizeof(cert_path), ca_path, + "-ra-%.1d", ra_index++); + } + else + { + add_path_suffix(cert_path, sizeof(cert_path), ca_path, + "-ra"); + } + path = cert_path; + } + + if (!cert->get_encoding(cert, CERT_ASN1_DER, &encoding) || + !chunk_write(encoding, path, + ca_cert ? "ca cert" : "ra cert", 0022, force)) + { + exit_scepclient("could not write cert file '%s'", path); + } + chunk_free(&encoding); + } + enumerator->destroy(enumerator); + container = &pkcs7->container; + container->destroy(container); } exit_scepclient(NULL); /* no further output required */ } + creds = mem_cred_create(); + lib->credmgr->add_set(lib->credmgr, &creds->set); + /* * input of PKCS#1 file */ if (filetype_in & PKCS1) /* load an RSA key pair from file */ { - char *path = concatenate_paths(PRIVATE_KEY_PATH, file_in_pkcs1); + char path[PATH_MAX]; + + join_paths(path, sizeof(path), PRIVATE_KEY_PATH, file_in_pkcs1); private_key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA, BUILD_FROM_FILE, path, BUILD_END); @@ -802,13 +1070,14 @@ int main(int argc, char **argv) { exit_scepclient("no RSA private key available"); } + creds->add_key(creds, private_key->get_ref(private_key)); public_key = private_key->get_public_key(private_key); /* check for minimum key length */ if (private_key->get_keysize(private_key) < RSA_MIN_OCTETS / BITS_PER_BYTE) { - exit_scepclient("length of RSA key has to be at least %d bits" - ,RSA_MIN_OCTETS * BITS_PER_BYTE); + exit_scepclient("length of RSA key has to be at least %d bits", + RSA_MIN_OCTETS * BITS_PER_BYTE); } /* @@ -816,13 +1085,19 @@ int main(int argc, char **argv) */ if (filetype_in & PKCS10) { - /* user wants to load a pkcs10 request - * operation is not yet supported - * would require a PKCS#10 parsing function + char path[PATH_MAX]; - pkcs10 = pkcs10_read_from_file(file_in_pkcs10); + join_paths(path, sizeof(path), REQ_PATH, file_in_pkcs10); - */ + pkcs10_req = lib->creds->create(lib->creds, CRED_CERTIFICATE, + CERT_PKCS10_REQUEST, BUILD_FROM_FILE, + path, BUILD_END); + if (!pkcs10_req) + { + exit_scepclient("could not read certificate request '%s'", path); + } + subject = pkcs10_req->get_subject(pkcs10_req); + subject = subject->clone(subject); } else { @@ -840,41 +1115,39 @@ int main(int argc, char **argv) distinguishedName = buf; } - DBG(DBG_CONTROL, - DBG_log("dn: '%s'", distinguishedName); - ) + DBG2(DBG_APP, "dn: '%s'", distinguishedName); subject = identification_create_from_string(distinguishedName); if (subject->get_type(subject) != ID_DER_ASN1_DN) { exit_scepclient("parsing of distinguished name failed"); } - DBG(DBG_CONTROL, - DBG_log("building pkcs10 object:") - ) + DBG2(DBG_APP, "building pkcs10 object:"); pkcs10_req = lib->creds->create(lib->creds, CRED_CERTIFICATE, - CERT_PKCS10_REQUEST, - BUILD_SIGNING_KEY, private_key, - BUILD_SUBJECT, subject, - BUILD_SUBJECT_ALTNAMES, subjectAltNames, - BUILD_CHALLENGE_PWD, challengePassword, - BUILD_DIGEST_ALG, pkcs10_signature_alg, - BUILD_END); + CERT_PKCS10_REQUEST, + BUILD_SIGNING_KEY, private_key, + BUILD_SUBJECT, subject, + BUILD_SUBJECT_ALTNAMES, subjectAltNames, + BUILD_CHALLENGE_PWD, challengePassword, + BUILD_DIGEST_ALG, pkcs10_signature_alg, + BUILD_END); if (!pkcs10_req) { exit_scepclient("generating pkcs10 request failed"); } - pkcs10_req->get_encoding(pkcs10_req, CERT_ASN1_DER, &pkcs10_encoding); - fingerprint = scep_generate_pkcs10_fingerprint(pkcs10_encoding); - plog(" fingerprint: %s", fingerprint.ptr); } + pkcs10_req->get_encoding(pkcs10_req, CERT_ASN1_DER, &pkcs10_encoding); + fingerprint = scep_generate_pkcs10_fingerprint(pkcs10_encoding); + DBG1(DBG_APP, " fingerprint: %s", fingerprint.ptr); /* * output of PKCS#10 file */ if (filetype_out & PKCS10) { - char *path = concatenate_paths(REQ_PATH, file_out_pkcs10); + char path[PATH_MAX]; + + join_paths(path, sizeof(path), REQ_PATH, file_out_pkcs10); if (!chunk_write(pkcs10_encoding, path, "pkcs10", 0022, force)) { @@ -893,11 +1166,11 @@ int main(int argc, char **argv) */ if (filetype_out & PKCS1) { - char *path = concatenate_paths(PRIVATE_KEY_PATH, file_out_pkcs1); + char path[PATH_MAX]; - DBG(DBG_CONTROL, - DBG_log("building pkcs1 object:") - ) + join_paths(path, sizeof(path), PRIVATE_KEY_PATH, file_out_pkcs1); + + DBG2(DBG_APP, "building pkcs1 object:"); if (!private_key->get_encoding(private_key, PRIVKEY_ASN1_DER, &pkcs1) || !chunk_write(pkcs1, path, "pkcs1", 0066, force)) { @@ -912,32 +1185,52 @@ int main(int argc, char **argv) } scep_generate_transaction_id(public_key, &transID, &serialNumber); - plog(" transaction ID: %.*s", (int)transID.len, transID.ptr); - - notBefore = notBefore ? notBefore : time(NULL); - notAfter = notAfter ? notAfter : (notBefore + validity); - - /* generate a self-signed X.509 certificate */ - x509_signer = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, - BUILD_SIGNING_KEY, private_key, - BUILD_PUBLIC_KEY, public_key, - BUILD_SUBJECT, subject, - BUILD_NOT_BEFORE_TIME, notBefore, - BUILD_NOT_AFTER_TIME, notAfter, - BUILD_SERIAL, serialNumber, - BUILD_SUBJECT_ALTNAMES, subjectAltNames, - BUILD_END); - if (!x509_signer) + DBG1(DBG_APP, " transaction ID: %.*s", (int)transID.len, transID.ptr); + + /* + * read or generate self-signed X.509 certificate + */ + if (filetype_in & CERT_SELF) { - exit_scepclient("generating certificate failed"); + char path[PATH_MAX]; + + join_paths(path, sizeof(path), HOST_CERT_PATH, file_in_cert_self); + + x509_signer = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, + BUILD_FROM_FILE, path, BUILD_END); + if (!x509_signer) + { + exit_scepclient("could not read certificate file '%s'", path); + } } + else + { + notBefore = notBefore ? notBefore : time(NULL); + notAfter = notAfter ? notAfter : (notBefore + validity); + x509_signer = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, + BUILD_SIGNING_KEY, private_key, + BUILD_PUBLIC_KEY, public_key, + BUILD_SUBJECT, subject, + BUILD_NOT_BEFORE_TIME, notBefore, + BUILD_NOT_AFTER_TIME, notAfter, + BUILD_SERIAL, serialNumber, + BUILD_SUBJECT_ALTNAMES, subjectAltNames, + BUILD_END); + if (!x509_signer) + { + exit_scepclient("generating certificate failed"); + } + } + creds->add_cert(creds, TRUE, x509_signer->get_ref(x509_signer)); /* * output of self-signed X.509 certificate file */ if (filetype_out & CERT_SELF) { - char *path = concatenate_paths(HOST_CERT_PATH, file_out_cert_self); + char path[PATH_MAX]; + + join_paths(path, sizeof(path), HOST_CERT_PATH, file_out_cert_self); if (!x509_signer->get_encoding(x509_signer, CERT_ASN1_DER, &encoding)) { @@ -960,7 +1253,9 @@ int main(int argc, char **argv) * load ca encryption certificate */ { - char *path = concatenate_paths(CA_CERT_PATH, file_in_cacert_enc); + char path[PATH_MAX]; + + join_paths(path, sizeof(path), CA_CERT_PATH, file_in_cacert_enc); x509_ca_enc = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, BUILD_FROM_FILE, path, BUILD_END); @@ -985,13 +1280,15 @@ int main(int argc, char **argv) } else { - DBG(DBG_CONTROL, - DBG_log("building pkcs7 request") - ) + DBG2(DBG_APP, "building pkcs7 request"); pkcs7 = scep_build_request(pkcs10_encoding, - transID, SCEP_PKCSReq_MSG, - x509_ca_enc, pkcs7_symmetric_cipher, - x509_signer, pkcs7_digest_alg, private_key); + transID, SCEP_PKCSReq_MSG, x509_ca_enc, + pkcs7_symmetric_cipher, pkcs7_key_size, + x509_signer, pkcs7_digest_alg, private_key); + if (!pkcs7.ptr) + { + exit_scepclient("failed to build pkcs7 request"); + } } /* @@ -999,11 +1296,14 @@ int main(int argc, char **argv) */ if (filetype_out & PKCS7) { - char *path = concatenate_paths(REQ_PATH, file_out_pkcs7); + char path[PATH_MAX]; + + join_paths(path, sizeof(path), REQ_PATH, file_out_pkcs7); if (!chunk_write(pkcs7, path, "pkcs7 encrypted request", 0022, force)) + { exit_scepclient("could not write pkcs7 file '%s'", path); -; + } filetype_out &= ~PKCS7; /* delete PKCS7 flag */ } @@ -1020,14 +1320,14 @@ int main(int argc, char **argv) bool stored = FALSE; certificate_t *cert; enumerator_t *enumerator; - char *path = concatenate_paths(CA_CERT_PATH, file_in_cacert_sig); + char path[PATH_MAX]; time_t poll_start = 0; + pkcs7_t *p7; + container_t *container = NULL; + chunk_t chunk; + scep_attributes_t attrs = empty_scep_attributes; - linked_list_t *certs = linked_list_create(); - chunk_t envelopedData = chunk_empty; - chunk_t certData = chunk_empty; - contentInfo_t data = empty_contentInfo; - scep_attributes_t attrs = empty_scep_attributes; + join_paths(path, sizeof(path), CA_CERT_PATH, file_in_cacert_sig); x509_ca_sig = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, BUILD_FROM_FILE, path, BUILD_END); @@ -1036,13 +1336,14 @@ int main(int argc, char **argv) exit_scepclient("could not load signature cacert file '%s'", path); } + creds->add_cert(creds, TRUE, x509_ca_sig->get_ref(x509_ca_sig)); + if (!scep_http_request(scep_url, pkcs7, SCEP_PKI_OPERATION, - http_get_request, &scep_response)) + http_get_request, http_timeout, http_bind, &scep_response)) { exit_scepclient("did not receive a valid scep response"); } - ugh = scep_parse_response(scep_response, transID, &data, &attrs - , x509_ca_sig); + ugh = scep_parse_response(scep_response, transID, &container, &attrs); if (ugh != NULL) { exit_scepclient(ugh); @@ -1053,45 +1354,46 @@ int main(int argc, char **argv) { identification_t *issuer = x509_ca_sig->get_subject(x509_ca_sig); - plog(" scep request pending, polling every %d seconds" - , poll_interval); + DBG1(DBG_APP, " scep request pending, polling every %d seconds", + poll_interval); poll_start = time_monotonic(NULL); issuerAndSubject = asn1_wrap(ASN1_SEQUENCE, "cc", issuer->get_encoding(issuer), - subject); + subject->get_encoding(subject)); } while (attrs.pkiStatus == SCEP_PENDING) { - if (max_poll_time > 0 - && (time_monotonic(NULL) - poll_start >= max_poll_time)) + if (max_poll_time > 0 && + (time_monotonic(NULL) - poll_start >= max_poll_time)) { exit_scepclient("maximum poll time reached: %d seconds" , max_poll_time); } - DBG(DBG_CONTROL, - DBG_log("going to sleep for %d seconds", poll_interval) - ) + DBG2(DBG_APP, "going to sleep for %d seconds", poll_interval); sleep(poll_interval); free(scep_response.ptr); + container->destroy(container); - DBG(DBG_CONTROL, - DBG_log("fingerprint: %.*s", (int)fingerprint.len, fingerprint.ptr); - DBG_log("transaction ID: %.*s", (int)transID.len, transID.ptr) - ) + DBG2(DBG_APP, "fingerprint: %.*s", + (int)fingerprint.len, fingerprint.ptr); + DBG2(DBG_APP, "transaction ID: %.*s", + (int)transID.len, transID.ptr); chunk_free(&getCertInitial); - getCertInitial = scep_build_request(issuerAndSubject - , transID, SCEP_GetCertInitial_MSG - , x509_ca_enc, pkcs7_symmetric_cipher - , x509_signer, pkcs7_digest_alg, private_key); - + getCertInitial = scep_build_request(issuerAndSubject, + transID, SCEP_GetCertInitial_MSG, x509_ca_enc, + pkcs7_symmetric_cipher, pkcs7_key_size, + x509_signer, pkcs7_digest_alg, private_key); + if (!getCertInitial.ptr) + { + exit_scepclient("failed to build scep request"); + } if (!scep_http_request(scep_url, getCertInitial, SCEP_PKI_OPERATION, - http_get_request, &scep_response)) + http_get_request, http_timeout, http_bind, &scep_response)) { exit_scepclient("did not receive a valid scep response"); } - ugh = scep_parse_response(scep_response, transID, &data, &attrs - , x509_ca_sig); + ugh = scep_parse_response(scep_response, transID, &container, &attrs); if (ugh != NULL) { exit_scepclient(ugh); @@ -1100,31 +1402,53 @@ int main(int argc, char **argv) if (attrs.pkiStatus != SCEP_SUCCESS) { + container->destroy(container); exit_scepclient("reply status is not 'SUCCESS'"); } - envelopedData = data.content; - - if (data.type != OID_PKCS7_DATA - || !asn1_parse_simple_object(&envelopedData, ASN1_OCTET_STRING, 0, "data")) + if (!container->get_data(container, &chunk)) { - exit_scepclient("contentInfo is not of type 'data'"); + container->destroy(container); + exit_scepclient("extracting signed-data failed"); } - if (!pkcs7_parse_envelopedData(envelopedData, &certData - , serialNumber, private_key)) + container->destroy(container); + + /* decrypt enveloped-data container */ + container = lib->creds->create(lib->creds, + CRED_CONTAINER, CONTAINER_PKCS7, + BUILD_BLOB_ASN1_DER, chunk, + BUILD_END); + free(chunk.ptr); + if (!container) { exit_scepclient("could not decrypt envelopedData"); } - if (!pkcs7_parse_signedData(certData, NULL, certs, NULL, NULL)) + + if (!container->get_data(container, &chunk)) + { + container->destroy(container); + exit_scepclient("extracting encrypted-data failed"); + } + container->destroy(container); + + /* parse signed-data container */ + container = lib->creds->create(lib->creds, + CRED_CONTAINER, CONTAINER_PKCS7, + BUILD_BLOB_ASN1_DER, chunk, + BUILD_END); + free(chunk.ptr); + if (!container) { - exit_scepclient("error parsing the scep response"); + exit_scepclient("could not parse singed-data"); } - chunk_free(&certData); + /* no need to verify the signed-data container, the signature does NOT + * cover the contained certificates */ /* store the end entity certificate */ - path = concatenate_paths(HOST_CERT_PATH, file_out_cert); + join_paths(path, sizeof(path), HOST_CERT_PATH, file_out_cert); - enumerator = certs->create_enumerator(certs); + p7 = (pkcs7_t*)container; + enumerator = p7->create_cert_enumerator(p7); while (enumerator->enumerate(enumerator, &cert)) { x509_t *x509 = (x509_t*)cert; @@ -1144,12 +1468,15 @@ int main(int argc, char **argv) stored = TRUE; } } - certs->destroy_offset(certs, offsetof(certificate_t, destroy)); + enumerator->destroy(enumerator); + container->destroy(container); + chunk_free(&attrs.transID); + chunk_free(&attrs.senderNonce); + chunk_free(&attrs.recipientNonce); + filetype_out &= ~CERT; /* delete CERT flag */ } exit_scepclient(NULL); return -1; /* should never be reached */ } - - |