diff options
Diffstat (limited to 'common')
-rw-r--r-- | common/Makefile.am | 9 | ||||
-rw-r--r-- | common/Makefile.in | 167 | ||||
-rw-r--r-- | common/compliance.c | 135 | ||||
-rw-r--r-- | common/compliance.h | 1 | ||||
-rw-r--r-- | common/dotlock.c | 22 | ||||
-rw-r--r-- | common/dotlock.h | 1 | ||||
-rw-r--r-- | common/exechelp-posix.c | 7 | ||||
-rw-r--r-- | common/exechelp-w32.c | 188 | ||||
-rw-r--r-- | common/init.c | 94 | ||||
-rw-r--r-- | common/keyserver.h | 73 | ||||
-rw-r--r-- | common/name-value.c | 1 | ||||
-rw-r--r-- | common/openpgp-fpr.c | 283 | ||||
-rw-r--r-- | common/openpgp-oid.c | 12 | ||||
-rw-r--r-- | common/openpgpdefs.h | 22 | ||||
-rw-r--r-- | common/sexputil.c | 490 | ||||
-rw-r--r-- | common/t-sexputil.c | 304 | ||||
-rw-r--r-- | common/t-w32-cmdline.c | 250 | ||||
-rw-r--r-- | common/tlv.c | 4 | ||||
-rw-r--r-- | common/tlv.h | 2 | ||||
-rw-r--r-- | common/ttyio.c | 631 | ||||
-rw-r--r-- | common/util.h | 20 | ||||
-rw-r--r-- | common/w32-cmdline.c | 450 | ||||
-rw-r--r-- | common/w32help.h | 9 | ||||
-rw-r--r-- | common/xasprintf.c | 53 |
24 files changed, 2724 insertions, 504 deletions
diff --git a/common/Makefile.am b/common/Makefile.am index 97e30da..cca1018 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -60,7 +60,6 @@ common_sources = \ shareddefs.h \ openpgpdefs.h \ gc-opt-flags.h \ - keyserver.h \ sexp-parse.h \ tlv.c tlv.h \ init.c init.h \ @@ -98,11 +97,12 @@ common_sources = \ name-value.c name-value.h \ recsel.c recsel.h \ ksba-io-support.c ksba-io-support.h \ + openpgp-fpr.c \ compliance.c compliance.h if HAVE_W32_SYSTEM -common_sources += w32-reg.c +common_sources += w32-reg.c w32-cmdline.c endif # To make the code easier to read we have split home some code into @@ -168,7 +168,7 @@ module_tests = t-stringhelp t-timestuff \ t-convert t-percent t-gettime t-sysutils t-sexputil \ t-session-env t-openpgp-oid t-ssh-utils \ t-mapstrings t-zb32 t-mbox-util t-iobuf t-strlist \ - t-name-value t-ccparray t-recsel + t-name-value t-ccparray t-recsel t-w32-cmdline if !HAVE_W32CE_SYSTEM module_tests += t-exechelp t-exectool endif @@ -222,6 +222,9 @@ t_name_value_LDADD = $(t_common_ldadd) t_ccparray_LDADD = $(t_common_ldadd) t_recsel_LDADD = $(t_common_ldadd) +t_w32_cmdline_SOURCES = t-w32-cmdline.c w32-cmdline.c $(t_extra_src) +t_w32_cmdline_LDADD = $(t_common_ldadd) + # System specific test if HAVE_W32_SYSTEM t_w32_reg_SOURCES = t-w32-reg.c $(t_extra_src) diff --git a/common/Makefile.in b/common/Makefile.in index 8b30d4a..11e4c23 100644 --- a/common/Makefile.in +++ b/common/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.16.1 from Makefile.am. +# Makefile.in generated by automake 1.16.3 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2018 Free Software Foundation, Inc. +# Copyright (C) 1994-2020 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -145,7 +145,7 @@ noinst_PROGRAMS = $(am__EXEEXT_3) $(am__EXEEXT_4) @GNUPG_DIRMNGR_PGM_TRUE@am__append_6 = -DGNUPG_DEFAULT_DIRMNGR="\"@GNUPG_DIRMNGR_PGM@\"" @GNUPG_PROTECT_TOOL_PGM_TRUE@am__append_7 = -DGNUPG_DEFAULT_PROTECT_TOOL="\"@GNUPG_PROTECT_TOOL_PGM@\"" @GNUPG_DIRMNGR_LDAP_PGM_TRUE@am__append_8 = -DGNUPG_DEFAULT_DIRMNGR_LDAP="\"@GNUPG_DIRMNGR_LDAP_PGM@\"" -@HAVE_W32_SYSTEM_TRUE@am__append_9 = w32-reg.c +@HAVE_W32_SYSTEM_TRUE@am__append_9 = w32-reg.c w32-cmdline.c # To make the code easier to read we have split home some code into # separate source files. @@ -186,8 +186,8 @@ am__EXEEXT_3 = t-stringhelp$(EXEEXT) t-timestuff$(EXEEXT) \ t-openpgp-oid$(EXEEXT) t-ssh-utils$(EXEEXT) \ t-mapstrings$(EXEEXT) t-zb32$(EXEEXT) t-mbox-util$(EXEEXT) \ t-iobuf$(EXEEXT) t-strlist$(EXEEXT) t-name-value$(EXEEXT) \ - t-ccparray$(EXEEXT) t-recsel$(EXEEXT) $(am__EXEEXT_1) \ - $(am__EXEEXT_2) + t-ccparray$(EXEEXT) t-recsel$(EXEEXT) t-w32-cmdline$(EXEEXT) \ + $(am__EXEEXT_1) $(am__EXEEXT_2) @MAINTAINER_MODE_TRUE@am__EXEEXT_4 = t-helpfile$(EXEEXT) \ @MAINTAINER_MODE_TRUE@ t-b64$(EXEEXT) PROGRAMS = $(noinst_PROGRAMS) @@ -204,7 +204,7 @@ am__libcommon_a_SOURCES_DIST = common-defs.h util.h utilproto.h \ mapstrings.c stringhelp.c stringhelp.h strlist.c strlist.h \ utf8conv.c utf8conv.h argparse.c argparse.h logging.c \ logging.h dotlock.c dotlock.h mischelp.c mischelp.h status.c \ - status.h shareddefs.h openpgpdefs.h gc-opt-flags.h keyserver.h \ + status.h shareddefs.h openpgpdefs.h gc-opt-flags.h \ sexp-parse.h tlv.c tlv.h init.c init.h sexputil.c sysutils.c \ sysutils.h homedir.c gettime.c gettime.h yesno.c b64enc.c \ b64dec.c zb32.c zb32.h convert.c percent.c mbox-util.c \ @@ -215,10 +215,12 @@ am__libcommon_a_SOURCES_DIST = common-defs.h util.h utilproto.h \ userids.h openpgp-oid.c ssh-utils.c ssh-utils.h agent-opt.c \ helpfile.c mkdir_p.c mkdir_p.h exectool.c exectool.h \ server-help.c server-help.h name-value.c name-value.h recsel.c \ - recsel.h ksba-io-support.c ksba-io-support.h compliance.c \ - compliance.h w32-reg.c exechelp-w32ce.c exechelp-w32.c \ - exechelp-posix.c get-passphrase.c get-passphrase.h -@HAVE_W32_SYSTEM_TRUE@am__objects_1 = libcommon_a-w32-reg.$(OBJEXT) + recsel.h ksba-io-support.c ksba-io-support.h openpgp-fpr.c \ + compliance.c compliance.h w32-reg.c w32-cmdline.c \ + exechelp-w32ce.c exechelp-w32.c exechelp-posix.c \ + get-passphrase.c get-passphrase.h +@HAVE_W32_SYSTEM_TRUE@am__objects_1 = libcommon_a-w32-reg.$(OBJEXT) \ +@HAVE_W32_SYSTEM_TRUE@ libcommon_a-w32-cmdline.$(OBJEXT) @HAVE_W32CE_SYSTEM_TRUE@@HAVE_W32_SYSTEM_TRUE@am__objects_2 = libcommon_a-exechelp-w32ce.$(OBJEXT) @HAVE_W32CE_SYSTEM_FALSE@@HAVE_W32_SYSTEM_TRUE@am__objects_3 = libcommon_a-exechelp-w32.$(OBJEXT) @HAVE_W32_SYSTEM_FALSE@am__objects_4 = \ @@ -253,6 +255,7 @@ am__objects_5 = libcommon_a-i18n.$(OBJEXT) \ libcommon_a-server-help.$(OBJEXT) \ libcommon_a-name-value.$(OBJEXT) libcommon_a-recsel.$(OBJEXT) \ libcommon_a-ksba-io-support.$(OBJEXT) \ + libcommon_a-openpgp-fpr.$(OBJEXT) \ libcommon_a-compliance.$(OBJEXT) $(am__objects_1) \ $(am__objects_2) $(am__objects_3) $(am__objects_4) am__objects_6 = libcommon_a-get-passphrase.$(OBJEXT) @@ -265,7 +268,7 @@ am__libcommonpth_a_SOURCES_DIST = common-defs.h util.h utilproto.h \ mapstrings.c stringhelp.c stringhelp.h strlist.c strlist.h \ utf8conv.c utf8conv.h argparse.c argparse.h logging.c \ logging.h dotlock.c dotlock.h mischelp.c mischelp.h status.c \ - status.h shareddefs.h openpgpdefs.h gc-opt-flags.h keyserver.h \ + status.h shareddefs.h openpgpdefs.h gc-opt-flags.h \ sexp-parse.h tlv.c tlv.h init.c init.h sexputil.c sysutils.c \ sysutils.h homedir.c gettime.c gettime.h yesno.c b64enc.c \ b64dec.c zb32.c zb32.h convert.c percent.c mbox-util.c \ @@ -276,11 +279,13 @@ am__libcommonpth_a_SOURCES_DIST = common-defs.h util.h utilproto.h \ userids.h openpgp-oid.c ssh-utils.c ssh-utils.h agent-opt.c \ helpfile.c mkdir_p.c mkdir_p.h exectool.c exectool.h \ server-help.c server-help.h name-value.c name-value.h recsel.c \ - recsel.h ksba-io-support.c ksba-io-support.h compliance.c \ - compliance.h w32-reg.c exechelp-w32ce.c exechelp-w32.c \ - exechelp-posix.c call-gpg.c call-gpg.h + recsel.h ksba-io-support.c ksba-io-support.h openpgp-fpr.c \ + compliance.c compliance.h w32-reg.c w32-cmdline.c \ + exechelp-w32ce.c exechelp-w32.c exechelp-posix.c call-gpg.c \ + call-gpg.h @HAVE_W32_SYSTEM_TRUE@am__objects_7 = \ -@HAVE_W32_SYSTEM_TRUE@ libcommonpth_a-w32-reg.$(OBJEXT) +@HAVE_W32_SYSTEM_TRUE@ libcommonpth_a-w32-reg.$(OBJEXT) \ +@HAVE_W32_SYSTEM_TRUE@ libcommonpth_a-w32-cmdline.$(OBJEXT) @HAVE_W32CE_SYSTEM_TRUE@@HAVE_W32_SYSTEM_TRUE@am__objects_8 = libcommonpth_a-exechelp-w32ce.$(OBJEXT) @HAVE_W32CE_SYSTEM_FALSE@@HAVE_W32_SYSTEM_TRUE@am__objects_9 = libcommonpth_a-exechelp-w32.$(OBJEXT) @HAVE_W32_SYSTEM_FALSE@am__objects_10 = libcommonpth_a-exechelp-posix.$(OBJEXT) @@ -327,6 +332,7 @@ am__objects_11 = libcommonpth_a-i18n.$(OBJEXT) \ libcommonpth_a-name-value.$(OBJEXT) \ libcommonpth_a-recsel.$(OBJEXT) \ libcommonpth_a-ksba-io-support.$(OBJEXT) \ + libcommonpth_a-openpgp-fpr.$(OBJEXT) \ libcommonpth_a-compliance.$(OBJEXT) $(am__objects_7) \ $(am__objects_8) $(am__objects_9) $(am__objects_10) am__objects_12 = libcommonpth_a-call-gpg.$(OBJEXT) @@ -412,6 +418,10 @@ t_sysutils_DEPENDENCIES = $(am__DEPENDENCIES_2) am_t_timestuff_OBJECTS = t-timestuff.$(OBJEXT) $(am__objects_13) t_timestuff_OBJECTS = $(am_t_timestuff_OBJECTS) t_timestuff_DEPENDENCIES = $(am__DEPENDENCIES_2) +am_t_w32_cmdline_OBJECTS = t-w32-cmdline.$(OBJEXT) \ + w32-cmdline.$(OBJEXT) $(am__objects_13) +t_w32_cmdline_OBJECTS = $(am_t_w32_cmdline_OBJECTS) +t_w32_cmdline_DEPENDENCIES = $(am__DEPENDENCIES_2) am__t_w32_reg_SOURCES_DIST = t-w32-reg.c t-support.h @HAVE_W32_SYSTEM_TRUE@am_t_w32_reg_OBJECTS = t-w32-reg.$(OBJEXT) \ @HAVE_W32_SYSTEM_TRUE@ $(am__objects_13) @@ -468,6 +478,7 @@ am__depfiles_remade = ./$(DEPDIR)/gpgrlhelp.Po \ ./$(DEPDIR)/libcommon_a-mischelp.Po \ ./$(DEPDIR)/libcommon_a-mkdir_p.Po \ ./$(DEPDIR)/libcommon_a-name-value.Po \ + ./$(DEPDIR)/libcommon_a-openpgp-fpr.Po \ ./$(DEPDIR)/libcommon_a-openpgp-oid.Po \ ./$(DEPDIR)/libcommon_a-percent.Po \ ./$(DEPDIR)/libcommon_a-recsel.Po \ @@ -484,6 +495,7 @@ am__depfiles_remade = ./$(DEPDIR)/gpgrlhelp.Po \ ./$(DEPDIR)/libcommon_a-ttyio.Po \ ./$(DEPDIR)/libcommon_a-userids.Po \ ./$(DEPDIR)/libcommon_a-utf8conv.Po \ + ./$(DEPDIR)/libcommon_a-w32-cmdline.Po \ ./$(DEPDIR)/libcommon_a-w32-reg.Po \ ./$(DEPDIR)/libcommon_a-xasprintf.Po \ ./$(DEPDIR)/libcommon_a-xreadline.Po \ @@ -521,6 +533,7 @@ am__depfiles_remade = ./$(DEPDIR)/gpgrlhelp.Po \ ./$(DEPDIR)/libcommonpth_a-mischelp.Po \ ./$(DEPDIR)/libcommonpth_a-mkdir_p.Po \ ./$(DEPDIR)/libcommonpth_a-name-value.Po \ + ./$(DEPDIR)/libcommonpth_a-openpgp-fpr.Po \ ./$(DEPDIR)/libcommonpth_a-openpgp-oid.Po \ ./$(DEPDIR)/libcommonpth_a-percent.Po \ ./$(DEPDIR)/libcommonpth_a-recsel.Po \ @@ -537,6 +550,7 @@ am__depfiles_remade = ./$(DEPDIR)/gpgrlhelp.Po \ ./$(DEPDIR)/libcommonpth_a-ttyio.Po \ ./$(DEPDIR)/libcommonpth_a-userids.Po \ ./$(DEPDIR)/libcommonpth_a-utf8conv.Po \ + ./$(DEPDIR)/libcommonpth_a-w32-cmdline.Po \ ./$(DEPDIR)/libcommonpth_a-w32-reg.Po \ ./$(DEPDIR)/libcommonpth_a-xasprintf.Po \ ./$(DEPDIR)/libcommonpth_a-xreadline.Po \ @@ -554,8 +568,9 @@ am__depfiles_remade = ./$(DEPDIR)/gpgrlhelp.Po \ ./$(DEPDIR)/t-session-env.Po ./$(DEPDIR)/t-sexputil.Po \ ./$(DEPDIR)/t-ssh-utils.Po ./$(DEPDIR)/t-stringhelp.Po \ ./$(DEPDIR)/t-strlist.Po ./$(DEPDIR)/t-sysutils.Po \ - ./$(DEPDIR)/t-timestuff.Po ./$(DEPDIR)/t-w32-reg.Po \ - ./$(DEPDIR)/t-zb32.Po + ./$(DEPDIR)/t-timestuff.Po ./$(DEPDIR)/t-w32-cmdline.Po \ + ./$(DEPDIR)/t-w32-reg.Po ./$(DEPDIR)/t-zb32.Po \ + ./$(DEPDIR)/w32-cmdline.Po am__mv = mv -f AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) @@ -580,7 +595,8 @@ SOURCES = $(libcommon_a_SOURCES) $(libcommonpth_a_SOURCES) \ t-name-value.c t-openpgp-oid.c t-percent.c t-recsel.c \ t-session-env.c t-sexputil.c t-ssh-utils.c \ $(t_stringhelp_SOURCES) t-strlist.c t-sysutils.c \ - $(t_timestuff_SOURCES) $(t_w32_reg_SOURCES) $(t_zb32_SOURCES) + $(t_timestuff_SOURCES) $(t_w32_cmdline_SOURCES) \ + $(t_w32_reg_SOURCES) $(t_zb32_SOURCES) DIST_SOURCES = $(am__libcommon_a_SOURCES_DIST) \ $(am__libcommonpth_a_SOURCES_DIST) $(libgpgrl_a_SOURCES) \ $(am__libsimple_pwquery_a_SOURCES_DIST) t-b64.c t-ccparray.c \ @@ -588,7 +604,7 @@ DIST_SOURCES = $(am__libcommon_a_SOURCES_DIST) \ t-iobuf.c t-mapstrings.c t-mbox-util.c t-name-value.c \ t-openpgp-oid.c t-percent.c t-recsel.c t-session-env.c \ t-sexputil.c t-ssh-utils.c $(t_stringhelp_SOURCES) t-strlist.c \ - t-sysutils.c $(t_timestuff_SOURCES) \ + t-sysutils.c $(t_timestuff_SOURCES) $(t_w32_cmdline_SOURCES) \ $(am__t_w32_reg_SOURCES_DIST) $(t_zb32_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ @@ -862,18 +878,18 @@ common_sources = common-defs.h util.h utilproto.h fwddecl.h i18n.c \ stringhelp.c stringhelp.h strlist.c strlist.h utf8conv.c \ utf8conv.h argparse.c argparse.h logging.c logging.h dotlock.c \ dotlock.h mischelp.c mischelp.h status.c status.h shareddefs.h \ - openpgpdefs.h gc-opt-flags.h keyserver.h sexp-parse.h tlv.c \ - tlv.h init.c init.h sexputil.c sysutils.c sysutils.h homedir.c \ - gettime.c gettime.h yesno.c b64enc.c b64dec.c zb32.c zb32.h \ - convert.c percent.c mbox-util.c mbox-util.h miscellaneous.c \ - xasprintf.c xreadline.c membuf.c membuf.h ccparray.c \ - ccparray.h iobuf.c iobuf.h ttyio.c ttyio.h asshelp.c \ - asshelp2.c asshelp.h exechelp.h signal.c audit.c audit.h \ - localename.c session-env.c session-env.h userids.c userids.h \ - openpgp-oid.c ssh-utils.c ssh-utils.h agent-opt.c helpfile.c \ - mkdir_p.c mkdir_p.h strlist.c strlist.h exectool.c exectool.h \ - server-help.c server-help.h name-value.c name-value.h recsel.c \ - recsel.h ksba-io-support.c ksba-io-support.h compliance.c \ + openpgpdefs.h gc-opt-flags.h sexp-parse.h tlv.c tlv.h init.c \ + init.h sexputil.c sysutils.c sysutils.h homedir.c gettime.c \ + gettime.h yesno.c b64enc.c b64dec.c zb32.c zb32.h convert.c \ + percent.c mbox-util.c mbox-util.h miscellaneous.c xasprintf.c \ + xreadline.c membuf.c membuf.h ccparray.c ccparray.h iobuf.c \ + iobuf.h ttyio.c ttyio.h asshelp.c asshelp2.c asshelp.h \ + exechelp.h signal.c audit.c audit.h localename.c session-env.c \ + session-env.h userids.c userids.h openpgp-oid.c ssh-utils.c \ + ssh-utils.h agent-opt.c helpfile.c mkdir_p.c mkdir_p.h \ + strlist.c strlist.h exectool.c exectool.h server-help.c \ + server-help.h name-value.c name-value.h recsel.c recsel.h \ + ksba-io-support.c ksba-io-support.h openpgp-fpr.c compliance.c \ compliance.h $(am__append_9) $(am__append_10) $(am__append_11) \ $(am__append_12) @@ -904,7 +920,8 @@ libgpgrl_a_SOURCES = \ module_tests = t-stringhelp t-timestuff t-convert t-percent t-gettime \ t-sysutils t-sexputil t-session-env t-openpgp-oid t-ssh-utils \ t-mapstrings t-zb32 t-mbox-util t-iobuf t-strlist t-name-value \ - t-ccparray t-recsel $(am__append_13) $(am__append_14) + t-ccparray t-recsel t-w32-cmdline $(am__append_13) \ + $(am__append_14) @MAINTAINER_MODE_FALSE@module_maint_tests = @MAINTAINER_MODE_TRUE@module_maint_tests = t-helpfile t-b64 t_extra_src = t-support.h @@ -942,6 +959,8 @@ t_strlist_LDADD = $(t_common_ldadd) t_name_value_LDADD = $(t_common_ldadd) t_ccparray_LDADD = $(t_common_ldadd) t_recsel_LDADD = $(t_common_ldadd) +t_w32_cmdline_SOURCES = t-w32-cmdline.c w32-cmdline.c $(t_extra_src) +t_w32_cmdline_LDADD = $(t_common_ldadd) # System specific test @HAVE_W32_SYSTEM_TRUE@t_w32_reg_SOURCES = t-w32-reg.c $(t_extra_src) @@ -1094,6 +1113,10 @@ t-timestuff$(EXEEXT): $(t_timestuff_OBJECTS) $(t_timestuff_DEPENDENCIES) $(EXTRA @rm -f t-timestuff$(EXEEXT) $(AM_V_CCLD)$(LINK) $(t_timestuff_OBJECTS) $(t_timestuff_LDADD) $(LIBS) +t-w32-cmdline$(EXEEXT): $(t_w32_cmdline_OBJECTS) $(t_w32_cmdline_DEPENDENCIES) $(EXTRA_t_w32_cmdline_DEPENDENCIES) + @rm -f t-w32-cmdline$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(t_w32_cmdline_OBJECTS) $(t_w32_cmdline_LDADD) $(LIBS) + t-w32-reg$(EXEEXT): $(t_w32_reg_OBJECTS) $(t_w32_reg_DEPENDENCIES) $(EXTRA_t_w32_reg_DEPENDENCIES) @rm -f t-w32-reg$(EXEEXT) $(AM_V_CCLD)$(LINK) $(t_w32_reg_OBJECTS) $(t_w32_reg_LDADD) $(LIBS) @@ -1141,6 +1164,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcommon_a-mischelp.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcommon_a-mkdir_p.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcommon_a-name-value.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcommon_a-openpgp-fpr.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcommon_a-openpgp-oid.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcommon_a-percent.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcommon_a-recsel.Po@am__quote@ # am--include-marker @@ -1157,6 +1181,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcommon_a-ttyio.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcommon_a-userids.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcommon_a-utf8conv.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcommon_a-w32-cmdline.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcommon_a-w32-reg.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcommon_a-xasprintf.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcommon_a-xreadline.Po@am__quote@ # am--include-marker @@ -1194,6 +1219,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcommonpth_a-mischelp.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcommonpth_a-mkdir_p.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcommonpth_a-name-value.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcommonpth_a-openpgp-fpr.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcommonpth_a-openpgp-oid.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcommonpth_a-percent.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcommonpth_a-recsel.Po@am__quote@ # am--include-marker @@ -1210,6 +1236,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcommonpth_a-ttyio.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcommonpth_a-userids.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcommonpth_a-utf8conv.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcommonpth_a-w32-cmdline.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcommonpth_a-w32-reg.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcommonpth_a-xasprintf.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcommonpth_a-xreadline.Po@am__quote@ # am--include-marker @@ -1238,8 +1265,10 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-strlist.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-sysutils.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-timestuff.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-w32-cmdline.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-w32-reg.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-zb32.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/w32-cmdline.Po@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @@ -1919,6 +1948,20 @@ libcommon_a-ksba-io-support.obj: ksba-io-support.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcommon_a_CFLAGS) $(CFLAGS) -c -o libcommon_a-ksba-io-support.obj `if test -f 'ksba-io-support.c'; then $(CYGPATH_W) 'ksba-io-support.c'; else $(CYGPATH_W) '$(srcdir)/ksba-io-support.c'; fi` +libcommon_a-openpgp-fpr.o: openpgp-fpr.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcommon_a_CFLAGS) $(CFLAGS) -MT libcommon_a-openpgp-fpr.o -MD -MP -MF $(DEPDIR)/libcommon_a-openpgp-fpr.Tpo -c -o libcommon_a-openpgp-fpr.o `test -f 'openpgp-fpr.c' || echo '$(srcdir)/'`openpgp-fpr.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcommon_a-openpgp-fpr.Tpo $(DEPDIR)/libcommon_a-openpgp-fpr.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='openpgp-fpr.c' object='libcommon_a-openpgp-fpr.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcommon_a_CFLAGS) $(CFLAGS) -c -o libcommon_a-openpgp-fpr.o `test -f 'openpgp-fpr.c' || echo '$(srcdir)/'`openpgp-fpr.c + +libcommon_a-openpgp-fpr.obj: openpgp-fpr.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcommon_a_CFLAGS) $(CFLAGS) -MT libcommon_a-openpgp-fpr.obj -MD -MP -MF $(DEPDIR)/libcommon_a-openpgp-fpr.Tpo -c -o libcommon_a-openpgp-fpr.obj `if test -f 'openpgp-fpr.c'; then $(CYGPATH_W) 'openpgp-fpr.c'; else $(CYGPATH_W) '$(srcdir)/openpgp-fpr.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcommon_a-openpgp-fpr.Tpo $(DEPDIR)/libcommon_a-openpgp-fpr.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='openpgp-fpr.c' object='libcommon_a-openpgp-fpr.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcommon_a_CFLAGS) $(CFLAGS) -c -o libcommon_a-openpgp-fpr.obj `if test -f 'openpgp-fpr.c'; then $(CYGPATH_W) 'openpgp-fpr.c'; else $(CYGPATH_W) '$(srcdir)/openpgp-fpr.c'; fi` + libcommon_a-compliance.o: compliance.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcommon_a_CFLAGS) $(CFLAGS) -MT libcommon_a-compliance.o -MD -MP -MF $(DEPDIR)/libcommon_a-compliance.Tpo -c -o libcommon_a-compliance.o `test -f 'compliance.c' || echo '$(srcdir)/'`compliance.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcommon_a-compliance.Tpo $(DEPDIR)/libcommon_a-compliance.Po @@ -1947,6 +1990,20 @@ libcommon_a-w32-reg.obj: w32-reg.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcommon_a_CFLAGS) $(CFLAGS) -c -o libcommon_a-w32-reg.obj `if test -f 'w32-reg.c'; then $(CYGPATH_W) 'w32-reg.c'; else $(CYGPATH_W) '$(srcdir)/w32-reg.c'; fi` +libcommon_a-w32-cmdline.o: w32-cmdline.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcommon_a_CFLAGS) $(CFLAGS) -MT libcommon_a-w32-cmdline.o -MD -MP -MF $(DEPDIR)/libcommon_a-w32-cmdline.Tpo -c -o libcommon_a-w32-cmdline.o `test -f 'w32-cmdline.c' || echo '$(srcdir)/'`w32-cmdline.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcommon_a-w32-cmdline.Tpo $(DEPDIR)/libcommon_a-w32-cmdline.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='w32-cmdline.c' object='libcommon_a-w32-cmdline.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcommon_a_CFLAGS) $(CFLAGS) -c -o libcommon_a-w32-cmdline.o `test -f 'w32-cmdline.c' || echo '$(srcdir)/'`w32-cmdline.c + +libcommon_a-w32-cmdline.obj: w32-cmdline.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcommon_a_CFLAGS) $(CFLAGS) -MT libcommon_a-w32-cmdline.obj -MD -MP -MF $(DEPDIR)/libcommon_a-w32-cmdline.Tpo -c -o libcommon_a-w32-cmdline.obj `if test -f 'w32-cmdline.c'; then $(CYGPATH_W) 'w32-cmdline.c'; else $(CYGPATH_W) '$(srcdir)/w32-cmdline.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcommon_a-w32-cmdline.Tpo $(DEPDIR)/libcommon_a-w32-cmdline.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='w32-cmdline.c' object='libcommon_a-w32-cmdline.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcommon_a_CFLAGS) $(CFLAGS) -c -o libcommon_a-w32-cmdline.obj `if test -f 'w32-cmdline.c'; then $(CYGPATH_W) 'w32-cmdline.c'; else $(CYGPATH_W) '$(srcdir)/w32-cmdline.c'; fi` + libcommon_a-exechelp-w32ce.o: exechelp-w32ce.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcommon_a_CFLAGS) $(CFLAGS) -MT libcommon_a-exechelp-w32ce.o -MD -MP -MF $(DEPDIR)/libcommon_a-exechelp-w32ce.Tpo -c -o libcommon_a-exechelp-w32ce.o `test -f 'exechelp-w32ce.c' || echo '$(srcdir)/'`exechelp-w32ce.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcommon_a-exechelp-w32ce.Tpo $(DEPDIR)/libcommon_a-exechelp-w32ce.Po @@ -2661,6 +2718,20 @@ libcommonpth_a-ksba-io-support.obj: ksba-io-support.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcommonpth_a_CFLAGS) $(CFLAGS) -c -o libcommonpth_a-ksba-io-support.obj `if test -f 'ksba-io-support.c'; then $(CYGPATH_W) 'ksba-io-support.c'; else $(CYGPATH_W) '$(srcdir)/ksba-io-support.c'; fi` +libcommonpth_a-openpgp-fpr.o: openpgp-fpr.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcommonpth_a_CFLAGS) $(CFLAGS) -MT libcommonpth_a-openpgp-fpr.o -MD -MP -MF $(DEPDIR)/libcommonpth_a-openpgp-fpr.Tpo -c -o libcommonpth_a-openpgp-fpr.o `test -f 'openpgp-fpr.c' || echo '$(srcdir)/'`openpgp-fpr.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcommonpth_a-openpgp-fpr.Tpo $(DEPDIR)/libcommonpth_a-openpgp-fpr.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='openpgp-fpr.c' object='libcommonpth_a-openpgp-fpr.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcommonpth_a_CFLAGS) $(CFLAGS) -c -o libcommonpth_a-openpgp-fpr.o `test -f 'openpgp-fpr.c' || echo '$(srcdir)/'`openpgp-fpr.c + +libcommonpth_a-openpgp-fpr.obj: openpgp-fpr.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcommonpth_a_CFLAGS) $(CFLAGS) -MT libcommonpth_a-openpgp-fpr.obj -MD -MP -MF $(DEPDIR)/libcommonpth_a-openpgp-fpr.Tpo -c -o libcommonpth_a-openpgp-fpr.obj `if test -f 'openpgp-fpr.c'; then $(CYGPATH_W) 'openpgp-fpr.c'; else $(CYGPATH_W) '$(srcdir)/openpgp-fpr.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcommonpth_a-openpgp-fpr.Tpo $(DEPDIR)/libcommonpth_a-openpgp-fpr.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='openpgp-fpr.c' object='libcommonpth_a-openpgp-fpr.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcommonpth_a_CFLAGS) $(CFLAGS) -c -o libcommonpth_a-openpgp-fpr.obj `if test -f 'openpgp-fpr.c'; then $(CYGPATH_W) 'openpgp-fpr.c'; else $(CYGPATH_W) '$(srcdir)/openpgp-fpr.c'; fi` + libcommonpth_a-compliance.o: compliance.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcommonpth_a_CFLAGS) $(CFLAGS) -MT libcommonpth_a-compliance.o -MD -MP -MF $(DEPDIR)/libcommonpth_a-compliance.Tpo -c -o libcommonpth_a-compliance.o `test -f 'compliance.c' || echo '$(srcdir)/'`compliance.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcommonpth_a-compliance.Tpo $(DEPDIR)/libcommonpth_a-compliance.Po @@ -2689,6 +2760,20 @@ libcommonpth_a-w32-reg.obj: w32-reg.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcommonpth_a_CFLAGS) $(CFLAGS) -c -o libcommonpth_a-w32-reg.obj `if test -f 'w32-reg.c'; then $(CYGPATH_W) 'w32-reg.c'; else $(CYGPATH_W) '$(srcdir)/w32-reg.c'; fi` +libcommonpth_a-w32-cmdline.o: w32-cmdline.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcommonpth_a_CFLAGS) $(CFLAGS) -MT libcommonpth_a-w32-cmdline.o -MD -MP -MF $(DEPDIR)/libcommonpth_a-w32-cmdline.Tpo -c -o libcommonpth_a-w32-cmdline.o `test -f 'w32-cmdline.c' || echo '$(srcdir)/'`w32-cmdline.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcommonpth_a-w32-cmdline.Tpo $(DEPDIR)/libcommonpth_a-w32-cmdline.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='w32-cmdline.c' object='libcommonpth_a-w32-cmdline.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcommonpth_a_CFLAGS) $(CFLAGS) -c -o libcommonpth_a-w32-cmdline.o `test -f 'w32-cmdline.c' || echo '$(srcdir)/'`w32-cmdline.c + +libcommonpth_a-w32-cmdline.obj: w32-cmdline.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcommonpth_a_CFLAGS) $(CFLAGS) -MT libcommonpth_a-w32-cmdline.obj -MD -MP -MF $(DEPDIR)/libcommonpth_a-w32-cmdline.Tpo -c -o libcommonpth_a-w32-cmdline.obj `if test -f 'w32-cmdline.c'; then $(CYGPATH_W) 'w32-cmdline.c'; else $(CYGPATH_W) '$(srcdir)/w32-cmdline.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcommonpth_a-w32-cmdline.Tpo $(DEPDIR)/libcommonpth_a-w32-cmdline.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='w32-cmdline.c' object='libcommonpth_a-w32-cmdline.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcommonpth_a_CFLAGS) $(CFLAGS) -c -o libcommonpth_a-w32-cmdline.obj `if test -f 'w32-cmdline.c'; then $(CYGPATH_W) 'w32-cmdline.c'; else $(CYGPATH_W) '$(srcdir)/w32-cmdline.c'; fi` + libcommonpth_a-exechelp-w32ce.o: exechelp-w32ce.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcommonpth_a_CFLAGS) $(CFLAGS) -MT libcommonpth_a-exechelp-w32ce.o -MD -MP -MF $(DEPDIR)/libcommonpth_a-exechelp-w32ce.Tpo -c -o libcommonpth_a-exechelp-w32ce.o `test -f 'exechelp-w32ce.c' || echo '$(srcdir)/'`exechelp-w32ce.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcommonpth_a-exechelp-w32ce.Tpo $(DEPDIR)/libcommonpth_a-exechelp-w32ce.Po @@ -2959,7 +3044,8 @@ all-am: Makefile $(PROGRAMS) $(LIBRARIES) installdirs: install: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) install-am -install-exec: install-exec-am +install-exec: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data: install-data-am uninstall: uninstall-am @@ -3029,6 +3115,7 @@ distclean: distclean-am -rm -f ./$(DEPDIR)/libcommon_a-mischelp.Po -rm -f ./$(DEPDIR)/libcommon_a-mkdir_p.Po -rm -f ./$(DEPDIR)/libcommon_a-name-value.Po + -rm -f ./$(DEPDIR)/libcommon_a-openpgp-fpr.Po -rm -f ./$(DEPDIR)/libcommon_a-openpgp-oid.Po -rm -f ./$(DEPDIR)/libcommon_a-percent.Po -rm -f ./$(DEPDIR)/libcommon_a-recsel.Po @@ -3045,6 +3132,7 @@ distclean: distclean-am -rm -f ./$(DEPDIR)/libcommon_a-ttyio.Po -rm -f ./$(DEPDIR)/libcommon_a-userids.Po -rm -f ./$(DEPDIR)/libcommon_a-utf8conv.Po + -rm -f ./$(DEPDIR)/libcommon_a-w32-cmdline.Po -rm -f ./$(DEPDIR)/libcommon_a-w32-reg.Po -rm -f ./$(DEPDIR)/libcommon_a-xasprintf.Po -rm -f ./$(DEPDIR)/libcommon_a-xreadline.Po @@ -3082,6 +3170,7 @@ distclean: distclean-am -rm -f ./$(DEPDIR)/libcommonpth_a-mischelp.Po -rm -f ./$(DEPDIR)/libcommonpth_a-mkdir_p.Po -rm -f ./$(DEPDIR)/libcommonpth_a-name-value.Po + -rm -f ./$(DEPDIR)/libcommonpth_a-openpgp-fpr.Po -rm -f ./$(DEPDIR)/libcommonpth_a-openpgp-oid.Po -rm -f ./$(DEPDIR)/libcommonpth_a-percent.Po -rm -f ./$(DEPDIR)/libcommonpth_a-recsel.Po @@ -3098,6 +3187,7 @@ distclean: distclean-am -rm -f ./$(DEPDIR)/libcommonpth_a-ttyio.Po -rm -f ./$(DEPDIR)/libcommonpth_a-userids.Po -rm -f ./$(DEPDIR)/libcommonpth_a-utf8conv.Po + -rm -f ./$(DEPDIR)/libcommonpth_a-w32-cmdline.Po -rm -f ./$(DEPDIR)/libcommonpth_a-w32-reg.Po -rm -f ./$(DEPDIR)/libcommonpth_a-xasprintf.Po -rm -f ./$(DEPDIR)/libcommonpth_a-xreadline.Po @@ -3126,8 +3216,10 @@ distclean: distclean-am -rm -f ./$(DEPDIR)/t-strlist.Po -rm -f ./$(DEPDIR)/t-sysutils.Po -rm -f ./$(DEPDIR)/t-timestuff.Po + -rm -f ./$(DEPDIR)/t-w32-cmdline.Po -rm -f ./$(DEPDIR)/t-w32-reg.Po -rm -f ./$(DEPDIR)/t-zb32.Po + -rm -f ./$(DEPDIR)/w32-cmdline.Po -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags @@ -3206,6 +3298,7 @@ maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/libcommon_a-mischelp.Po -rm -f ./$(DEPDIR)/libcommon_a-mkdir_p.Po -rm -f ./$(DEPDIR)/libcommon_a-name-value.Po + -rm -f ./$(DEPDIR)/libcommon_a-openpgp-fpr.Po -rm -f ./$(DEPDIR)/libcommon_a-openpgp-oid.Po -rm -f ./$(DEPDIR)/libcommon_a-percent.Po -rm -f ./$(DEPDIR)/libcommon_a-recsel.Po @@ -3222,6 +3315,7 @@ maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/libcommon_a-ttyio.Po -rm -f ./$(DEPDIR)/libcommon_a-userids.Po -rm -f ./$(DEPDIR)/libcommon_a-utf8conv.Po + -rm -f ./$(DEPDIR)/libcommon_a-w32-cmdline.Po -rm -f ./$(DEPDIR)/libcommon_a-w32-reg.Po -rm -f ./$(DEPDIR)/libcommon_a-xasprintf.Po -rm -f ./$(DEPDIR)/libcommon_a-xreadline.Po @@ -3259,6 +3353,7 @@ maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/libcommonpth_a-mischelp.Po -rm -f ./$(DEPDIR)/libcommonpth_a-mkdir_p.Po -rm -f ./$(DEPDIR)/libcommonpth_a-name-value.Po + -rm -f ./$(DEPDIR)/libcommonpth_a-openpgp-fpr.Po -rm -f ./$(DEPDIR)/libcommonpth_a-openpgp-oid.Po -rm -f ./$(DEPDIR)/libcommonpth_a-percent.Po -rm -f ./$(DEPDIR)/libcommonpth_a-recsel.Po @@ -3275,6 +3370,7 @@ maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/libcommonpth_a-ttyio.Po -rm -f ./$(DEPDIR)/libcommonpth_a-userids.Po -rm -f ./$(DEPDIR)/libcommonpth_a-utf8conv.Po + -rm -f ./$(DEPDIR)/libcommonpth_a-w32-cmdline.Po -rm -f ./$(DEPDIR)/libcommonpth_a-w32-reg.Po -rm -f ./$(DEPDIR)/libcommonpth_a-xasprintf.Po -rm -f ./$(DEPDIR)/libcommonpth_a-xreadline.Po @@ -3303,8 +3399,10 @@ maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/t-strlist.Po -rm -f ./$(DEPDIR)/t-sysutils.Po -rm -f ./$(DEPDIR)/t-timestuff.Po + -rm -f ./$(DEPDIR)/t-w32-cmdline.Po -rm -f ./$(DEPDIR)/t-w32-reg.Po -rm -f ./$(DEPDIR)/t-zb32.Po + -rm -f ./$(DEPDIR)/w32-cmdline.Po -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic @@ -3322,7 +3420,8 @@ ps-am: uninstall-am: -.MAKE: all check check-am install install-am install-strip +.MAKE: all check check-am install install-am install-exec \ + install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-TESTS \ check-am clean clean-generic clean-noinstLIBRARIES \ diff --git a/common/compliance.c b/common/compliance.c index e77b1af..1cda1ec 100644 --- a/common/compliance.c +++ b/common/compliance.c @@ -40,6 +40,38 @@ static int initialized; static int module; + +/* Return the address of a compliance cache variable for COMPLIANCE. + * If no such variable exists NULL is returned. FOR_RNG returns the + * cache variable for the RNG compliance check. */ +static int * +get_compliance_cache (enum gnupg_compliance_mode compliance, int for_rng) +{ + static int r_gnupg = -1, s_gnupg = -1; + static int r_rfc4880 = -1, s_rfc4880 = -1; + static int r_rfc2440 = -1, s_rfc2440 = -1; + static int r_pgp6 = -1, s_pgp6 = -1; + static int r_pgp7 = -1, s_pgp7 = -1; + static int r_pgp8 = -1, s_pgp8 = -1; + static int r_de_vs = -1, s_de_vs = -1; + + int *ptr = NULL; + + switch (compliance) + { + case CO_GNUPG: ptr = for_rng? &r_gnupg : &s_gnupg ; break; + case CO_RFC4880: ptr = for_rng? &r_rfc4880 : &s_rfc4880; break; + case CO_RFC2440: ptr = for_rng? &r_rfc2440 : &s_rfc2440; break; + case CO_PGP6: ptr = for_rng? &r_pgp6 : &s_pgp6 ; break; + case CO_PGP7: ptr = for_rng? &r_pgp7 : &s_pgp7 ; break; + case CO_PGP8: ptr = for_rng? &r_pgp8 : &s_pgp8 ; break; + case CO_DE_VS: ptr = for_rng? &r_de_vs : &s_de_vs ; break; + } + + return ptr; +} + + /* Initializes the module. Must be called with the current * GNUPG_MODULE_NAME. Checks a few invariants, and tunes the policies * for the given module. */ @@ -386,7 +418,8 @@ gnupg_cipher_is_allowed (enum gnupg_compliance_mode compliance, int producer, || mode == GCRY_CIPHER_MODE_CFB); case GNUPG_MODULE_NAME_GPGSM: return (mode == GCRY_CIPHER_MODE_NONE - || mode == GCRY_CIPHER_MODE_CBC); + || mode == GCRY_CIPHER_MODE_CBC + || (mode == GCRY_CIPHER_MODE_GCM && !producer)); } log_assert (!"reached"); @@ -490,34 +523,94 @@ gnupg_digest_is_allowed (enum gnupg_compliance_mode compliance, int producer, int gnupg_rng_is_compliant (enum gnupg_compliance_mode compliance) { - static int result = -1; + int *result; + int res; - if (result != -1) - ; /* Use cached result. */ + result = get_compliance_cache (compliance, 1); + + if (result && *result != -1) + res = *result; /* Use cached result. */ else if (compliance == CO_DE_VS) { - /* In DE_VS mode under Windows we require that the JENT RNG - * is active. */ + /* We also check whether the library is at all compliant. */ + res = gnupg_gcrypt_is_compliant (compliance); + + /* In DE_VS mode under Windows we also require that the JENT RNG + * is active. Check it here. */ #ifdef HAVE_W32_SYSTEM - char *buf; - char *fields[5]; - - buf = gcry_get_config (0, "rng-type"); - if (buf - && split_fields_colon (buf, fields, DIM (fields)) >= 5 - && atoi (fields[4]) > 0) - result = 1; + if (res == 1) + { + char *buf; + char *fields[5]; + + buf = gcry_get_config (0, "rng-type"); + if (buf + && split_fields_colon (buf, fields, DIM (fields)) >= 5 + && atoi (fields[4]) > 0) + ; /* Field 5 > 0 := Jent is active. */ + else + result = 0; /* Force non-compliance. */ + gcry_free (buf); + } +#endif /*HAVE_W32_SYSTEM*/ + } + else + res = 1; + + if (result) + *result = res; + + return res; +} + + +/* Return true if the used Libgcrypt is compliant in COMPLIANCE + * mode. */ +int +gnupg_gcrypt_is_compliant (enum gnupg_compliance_mode compliance) +{ + int *result; + int res; + + result = get_compliance_cache (compliance, 0); + + if (result && *result != -1) + res = *result; /* Use cached result. */ + else if (compliance == CO_DE_VS) + { + int is19orlater = !!gcry_check_version ("1.9.0"); + + /* A compliant version of GnuPG requires Libgcrypt >= 1.8.1 and + * less than 1.9.0. Version 1.9.0 requires a re-evaluation and + * can thus not be used for de-vs. */ + if (gcry_check_version ("1.8.1") && !is19orlater) + res = 1; /* Compliant version of Libgcrypt. */ + else if (is19orlater) + { + /* Libgcrypt might be nice enough to tell us whether it is + * compliant. */ + char *buf; + char *fields[3]; + + buf = gcry_get_config (0, "compliance"); + if (buf + && split_fields_colon (buf, fields, DIM (fields)) >= 2 + && strstr (fields[1], "de-vs")) + res = 1; /* Compliant. */ + else + res = 0; /* Non-compliant. */ + gcry_free (buf); + } else - result = 0; - gcry_free (buf); -#else /*!HAVE_W32_SYSTEM*/ - result = 1; /* Not Windows - RNG is good. */ -#endif /*!HAVE_W32_SYSTEM*/ + res = 0; /* Non-compliant version of Libgcrypt. */ } else - result = 1; + res = 1; - return result; + if (result) + *result = res; + + return res; } diff --git a/common/compliance.h b/common/compliance.h index 21bd230..20b562e 100644 --- a/common/compliance.h +++ b/common/compliance.h @@ -73,6 +73,7 @@ int gnupg_digest_is_allowed (enum gnupg_compliance_mode compliance, int producer, digest_algo_t digest); int gnupg_rng_is_compliant (enum gnupg_compliance_mode compliance); +int gnupg_gcrypt_is_compliant (enum gnupg_compliance_mode compliance); const char *gnupg_status_compliance_flag (enum gnupg_compliance_mode compliance); diff --git a/common/dotlock.c b/common/dotlock.c index da3f09e..4320c54 100644 --- a/common/dotlock.c +++ b/common/dotlock.c @@ -1012,6 +1012,14 @@ dotlock_destroy (dotlock_t h) } +/* Return true if H has been taken. */ +int +dotlock_is_locked (dotlock_t h) +{ + return h && !!h->locked; +} + + #ifdef HAVE_POSIX_SYSTEM /* Unix specific code of make_dotlock. Returns 0 on success and -1 on @@ -1250,11 +1258,14 @@ dotlock_take (dotlock_t h, long timeout) int ret; if ( h->disable ) - return 0; /* Locks are completely disabled. Return success. */ + { + h->locked = 1; + return 0; /* Locks are completely disabled. Return success. */ + } if ( h->locked ) { - my_debug_1 ("Oops, '%s' is already locked\n", h->lockname); + /* my_debug_1 ("'%s' is already locked (%s)\n", h->lockname); */ return 0; } @@ -1346,11 +1357,14 @@ dotlock_release (dotlock_t h) return 0; if ( h->disable ) - return 0; + { + h->locked = 0; + return 0; + } if ( !h->locked ) { - my_debug_1 ("Oops, '%s' is not locked\n", h->lockname); + /* my_debug_1 ("Oops, '%s' is not locked (%s)\n", h->lockname); */ return 0; } diff --git a/common/dotlock.h b/common/dotlock.h index 03131bb..9869739 100644 --- a/common/dotlock.h +++ b/common/dotlock.h @@ -102,6 +102,7 @@ dotlock_t dotlock_create (const char *file_to_lock, unsigned int flags); void dotlock_set_fd (dotlock_t h, int fd); int dotlock_get_fd (dotlock_t h); void dotlock_destroy (dotlock_t h); +int dotlock_is_locked (dotlock_t h); int dotlock_take (dotlock_t h, long timeout); int dotlock_release (dotlock_t h); void dotlock_remove_lockfiles (void); diff --git a/common/exechelp-posix.c b/common/exechelp-posix.c index 0782152..347a11b 100644 --- a/common/exechelp-posix.c +++ b/common/exechelp-posix.c @@ -722,8 +722,13 @@ gnupg_wait_processes (const char **pgmnames, pid_t *pids, size_t count, { int status = -1; + /* Skip invalid PID. */ if (pids[i] == (pid_t)(-1)) - return my_error (GPG_ERR_INV_VALUE); + { + r_exitcodes[i] = -1; + left -= 1; + continue; + } /* See if there was a previously stored result for this pid. */ if (get_result (pids[i], &status)) diff --git a/common/exechelp-w32.c b/common/exechelp-w32.c index 7bd9d22..08e4d3a 100644 --- a/common/exechelp-w32.c +++ b/common/exechelp-w32.c @@ -414,9 +414,11 @@ gnupg_spawn_process (const char *pgmname, const char *argv[], 0, /* Returns pid. */ 0 /* Returns tid. */ }; - STARTUPINFO si; + STARTUPINFOW si; int cr_flags; char *cmdline; + wchar_t *wcmdline = NULL; + wchar_t *wpgmname = NULL; HANDLE inpipe[2] = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE}; HANDLE outpipe[2] = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE}; HANDLE errpipe[2] = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE}; @@ -426,7 +428,7 @@ gnupg_spawn_process (const char *pgmname, const char *argv[], HANDLE nullhd[3] = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE}; - int i; + int i, rc; es_syshd_t syshd; gpg_err_source_t errsource = default_errsource; int nonblock = !!(flags & GNUPG_SPAWN_NONBLOCK); @@ -564,20 +566,34 @@ gnupg_spawn_process (const char *pgmname, const char *argv[], | ((flags & GNUPG_SPAWN_DETACHED)? DETACHED_PROCESS : 0) | GetPriorityClass (GetCurrentProcess ()) | CREATE_SUSPENDED); -/* log_debug ("CreateProcess, path='%s' cmdline='%s'\n", pgmname, cmdline); */ - if (!CreateProcess (pgmname, /* Program to start. */ - cmdline, /* Command line arguments. */ - &sec_attr, /* Process security attributes. */ - &sec_attr, /* Thread security attributes. */ - TRUE, /* Inherit handles. */ - cr_flags, /* Creation flags. */ - NULL, /* Environment. */ - NULL, /* Use current drive/directory. */ - &si, /* Startup information. */ - &pi /* Returns process information. */ - )) + /* log_debug ("CreateProcess, path='%s' cmdline='%s'\n", */ + /* pgmname, cmdline); */ + /* Take care: CreateProcessW may modify wpgmname */ + if (!(wpgmname = utf8_to_wchar (pgmname))) + rc = 0; + else if (!(wcmdline = utf8_to_wchar (cmdline))) + rc = 0; + else + rc = CreateProcessW (wpgmname, /* Program to start. */ + wcmdline, /* Command line arguments. */ + &sec_attr, /* Process security attributes. */ + &sec_attr, /* Thread security attributes. */ + TRUE, /* Inherit handles. */ + cr_flags, /* Creation flags. */ + NULL, /* Environment. */ + NULL, /* Use current drive/directory. */ + &si, /* Startup information. */ + &pi /* Returns process information. */ + ); + if (!rc) { - log_error ("CreateProcess failed: %s\n", w32_strerror (-1)); + if (!wpgmname || !wcmdline) + log_error ("CreateProcess failed (utf8_to_wchar): %s\n", + strerror (errno)); + else + log_error ("CreateProcess failed: %s\n", w32_strerror (-1)); + xfree (wpgmname); + xfree (wcmdline); xfree (cmdline); if (infp) es_fclose (infp); @@ -599,6 +615,8 @@ gnupg_spawn_process (const char *pgmname, const char *argv[], CloseHandle (errpipe[1]); return gpg_err_make (errsource, GPG_ERR_GENERAL); } + xfree (wpgmname); + xfree (wcmdline); xfree (cmdline); cmdline = NULL; @@ -660,9 +678,11 @@ gnupg_spawn_process_fd (const char *pgmname, const char *argv[], gpg_error_t err; SECURITY_ATTRIBUTES sec_attr; PROCESS_INFORMATION pi = { NULL, 0, 0, 0 }; - STARTUPINFO si; + STARTUPINFOW si; char *cmdline; - int i; + wchar_t *wcmdline = NULL; + wchar_t *wpgmname = NULL; + int i, rc; HANDLE stdhd[3]; /* Setup return values. */ @@ -690,25 +710,38 @@ gnupg_spawn_process_fd (const char *pgmname, const char *argv[], si.hStdError = errfd == -1? stdhd[2] : (void*)_get_osfhandle (errfd); /* log_debug ("CreateProcess, path='%s' cmdline='%s'\n", pgmname, cmdline); */ - if (!CreateProcess (pgmname, /* Program to start. */ - cmdline, /* Command line arguments. */ - &sec_attr, /* Process security attributes. */ - &sec_attr, /* Thread security attributes. */ - TRUE, /* Inherit handles. */ - (CREATE_DEFAULT_ERROR_MODE - | GetPriorityClass (GetCurrentProcess ()) - | CREATE_SUSPENDED | DETACHED_PROCESS), - NULL, /* Environment. */ - NULL, /* Use current drive/directory. */ - &si, /* Startup information. */ - &pi /* Returns process information. */ - )) + /* Take care: CreateProcessW may modify wpgmname */ + if (!(wpgmname = utf8_to_wchar (pgmname))) + rc = 0; + else if (!(wcmdline = utf8_to_wchar (cmdline))) + rc = 0; + else + rc = CreateProcessW (wpgmname, /* Program to start. */ + wcmdline, /* Command line arguments. */ + &sec_attr, /* Process security attributes. */ + &sec_attr, /* Thread security attributes. */ + TRUE, /* Inherit handles. */ + (CREATE_DEFAULT_ERROR_MODE + | GetPriorityClass (GetCurrentProcess ()) + | CREATE_SUSPENDED | DETACHED_PROCESS), + NULL, /* Environment. */ + NULL, /* Use current drive/directory. */ + &si, /* Startup information. */ + &pi /* Returns process information. */ + ); + if (!rc) { - log_error ("CreateProcess failed: %s\n", w32_strerror (-1)); + if (!wpgmname || !wcmdline) + log_error ("CreateProcess failed (utf8_to_wchar): %s\n", + strerror (errno)); + else + log_error ("CreateProcess failed: %s\n", w32_strerror (-1)); err = my_error (GPG_ERR_GENERAL); } else err = 0; + xfree (wpgmname); + xfree (wcmdline); xfree (cmdline); for (i=0; i < 3; i++) if (stdhd[i] != INVALID_HANDLE_VALUE) @@ -852,10 +885,14 @@ gnupg_spawn_process_detached (const char *pgmname, const char *argv[], 0, /* Returns pid. */ 0 /* Returns tid. */ }; - STARTUPINFO si; + STARTUPINFOW si; int cr_flags; char *cmdline; + wchar_t *wcmdline = NULL; + wchar_t *wpgmname = NULL; + BOOL in_job = FALSE; gpg_err_code_t ec; + int rc; /* We don't use ENVP. */ (void)envp; @@ -883,24 +920,83 @@ gnupg_spawn_process_detached (const char *pgmname, const char *argv[], | GetPriorityClass (GetCurrentProcess ()) | CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS); -/* log_debug ("CreateProcess(detached), path='%s' cmdline='%s'\n", */ -/* pgmname, cmdline); */ - if (!CreateProcess (pgmname, /* Program to start. */ - cmdline, /* Command line arguments. */ - &sec_attr, /* Process security attributes. */ - &sec_attr, /* Thread security attributes. */ - FALSE, /* Inherit handles. */ - cr_flags, /* Creation flags. */ - NULL, /* Environment. */ - NULL, /* Use current drive/directory. */ - &si, /* Startup information. */ - &pi /* Returns process information. */ - )) + + /* Check if we were spawned as part of a Job. + * In a job we need to add CREATE_BREAKAWAY_FROM_JOB + * to the cr_flags, otherwise our child processes + * are killed when we terminate. */ + if (!IsProcessInJob (GetCurrentProcess(), NULL, &in_job)) { - log_error ("CreateProcess(detached) failed: %s\n", w32_strerror (-1)); + log_error ("IsProcessInJob() failed: %s\n", w32_strerror (-1)); + in_job = FALSE; + } + + if (in_job) + { + /* Only try to break away from job if it is allowed, otherwise + * CreateProcess() would fail with an "Access is denied" error. */ + JOBOBJECT_EXTENDED_LIMIT_INFORMATION info; + if (!QueryInformationJobObject (NULL, JobObjectExtendedLimitInformation, + &info, sizeof info, NULL)) + { + log_error ("QueryInformationJobObject() failed: %s\n", + w32_strerror (-1)); + } + else if ((info.BasicLimitInformation.LimitFlags & + JOB_OBJECT_LIMIT_BREAKAWAY_OK)) + { + log_debug ("Using CREATE_BREAKAWAY_FROM_JOB flag\n"); + cr_flags |= CREATE_BREAKAWAY_FROM_JOB; + } + else if ((info.BasicLimitInformation.LimitFlags & + JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK)) + { + /* The child process should automatically detach from the job. */ + log_debug ("Not using CREATE_BREAKAWAY_FROM_JOB flag; " + "JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK is set\n"); + } + else + { + /* It seems that the child process must remain in the job. + * This is not necessarily an error, although it can cause premature + * termination of the child process when the job is closed. */ + log_debug ("Not using CREATE_BREAKAWAY_FROM_JOB flag\n"); + } + } + + /* log_debug ("CreateProcess(detached), path='%s' cmdline='%s'\n", */ + /* pgmname, cmdline); */ + /* Take care: CreateProcessW may modify wpgmname */ + if (!(wpgmname = utf8_to_wchar (pgmname))) + rc = 0; + else if (!(wcmdline = utf8_to_wchar (cmdline))) + rc = 0; + else + rc = CreateProcessW (wpgmname, /* Program to start. */ + wcmdline, /* Command line arguments. */ + &sec_attr, /* Process security attributes. */ + &sec_attr, /* Thread security attributes. */ + FALSE, /* Inherit handles. */ + cr_flags, /* Creation flags. */ + NULL, /* Environment. */ + NULL, /* Use current drive/directory. */ + &si, /* Startup information. */ + &pi /* Returns process information. */ + ); + if (!rc) + { + if (!wpgmname || !wcmdline) + log_error ("CreateProcess failed (utf8_to_wchar): %s\n", + strerror (errno)); + else + log_error ("CreateProcess(detached) failed: %s\n", w32_strerror (-1)); + xfree (wpgmname); + xfree (wcmdline); xfree (cmdline); return my_error (GPG_ERR_GENERAL); } + xfree (wpgmname); + xfree (wcmdline); xfree (cmdline); cmdline = NULL; diff --git a/common/init.c b/common/init.c index bcd0236..0a12b25 100644 --- a/common/init.c +++ b/common/init.c @@ -42,6 +42,7 @@ #include <gcrypt.h> #include "util.h" #include "i18n.h" +#include "w32help.h" /* This object is used to register memory cleanup functions. Technically they are not needed but they can avoid frequent @@ -79,6 +80,11 @@ sleep_on_exit (void) } #endif /*HAVE_W32CE_SYSTEM*/ +#if HAVE_W32_SYSTEM +static void prepare_w32_commandline (int *argcp, char ***argvp); +#endif /*HAVE_W32_SYSTEM*/ + + static void run_mem_cleanup (void) @@ -190,13 +196,21 @@ _init_common_subsystems (gpg_err_source_t errsource, int *argcp, char ***argvp) gpgrt_init (); gpgrt_set_alloc_func (gcry_realloc); +#ifdef HAVE_W32CE_SYSTEM /* Special hack for Windows CE: We extract some options from arg to setup the standard handles. */ -#ifdef HAVE_W32CE_SYSTEM parse_std_file_handles (argcp, argvp); -#else - (void)argcp; - (void)argvp; +#endif + +#ifdef HAVE_W32_SYSTEM + /* We want gettext to always output UTF-8 and we put the console in + * utf-8 mode. */ + gettext_use_utf8 (1); + if (!SetConsoleCP (CP_UTF8) || !SetConsoleOutputCP (CP_UTF8)) + { + log_info ("SetConsoleCP failed: %s\n", w32_strerror (-1)); + log_info ("Warning: Garbled console data possible\n"); + } #endif /* Access the standard estreams as early as possible. If we don't @@ -217,6 +231,16 @@ _init_common_subsystems (gpg_err_source_t errsource, int *argcp, char ***argvp) /* Logging shall use the standard socket directory as fallback. */ log_set_socket_dir_cb (gnupg_socketdir); + +#if HAVE_W32_SYSTEM + /* For Standard Windows we use our own parser for the command line + * so that we can return an array of utf-8 encoded strings. */ + prepare_w32_commandline (argcp, argvp); +#else + (void)argcp; + (void)argvp; +#endif + } @@ -290,3 +314,65 @@ parse_std_file_handles (int *argcp, char ***argvp) } #endif /*HAVE_W32CE_SYSTEM*/ + + +/* For Windows we need to parse the command line so that we can + * provide an UTF-8 encoded argv. If there is any Unicode character + * we return a new array but if there is no Unicode character we do + * nothing. */ +#ifdef HAVE_W32_SYSTEM +static void +prepare_w32_commandline (int *r_argc, char ***r_argv) +{ + const wchar_t *wcmdline, *ws; + char *cmdline; + int argc; + char **argv; + const char *s; + int i, globing, itemsalloced; + + s = strusage (95); + globing = (s && *s == '1'); + + wcmdline = GetCommandLineW (); + if (!wcmdline) + { + log_error ("GetCommandLineW failed\n"); + return; /* Ooops. */ + } + + if (!globing) + { + /* If globbing is not enabled we use our own parser only if + * there are any non-ASCII characters. */ + for (ws=wcmdline; *ws; ws++) + if (!iswascii (*ws)) + break; + if (!*ws) + return; /* No Unicode - return directly. */ + } + + cmdline = wchar_to_utf8 (wcmdline); + if (!cmdline) + { + log_error ("parsing command line failed: %s\n", strerror (errno)); + return; /* Ooops. */ + } + gpgrt_annotate_leaked_object (cmdline); + + argv = w32_parse_commandline (cmdline, globing, &argc, &itemsalloced); + if (!argv) + { + log_error ("parsing command line failed: %s\n", "internal error"); + return; /* Ooops. */ + } + gpgrt_annotate_leaked_object (argv); + if (itemsalloced) + { + for (i=0; i < argc; i++) + gpgrt_annotate_leaked_object (argv[i]); + } + *r_argv = argv; + *r_argc = argc; +} +#endif /*HAVE_W32_SYSTEM*/ diff --git a/common/keyserver.h b/common/keyserver.h deleted file mode 100644 index 850798e..0000000 --- a/common/keyserver.h +++ /dev/null @@ -1,73 +0,0 @@ -/* keyserver.h - Public definitions for gpg keyserver helpers. - * Copyright (C) 2001, 2002, 2011 Free Software Foundation, Inc. - * - * This file is part of GnuPG. - * - * This file is free software; you can redistribute it and/or modify - * it under the terms of either - * - * - the GNU Lesser General Public License as published by the Free - * Software Foundation; either version 3 of the License, or (at - * your option) any later version. - * - * or - * - * - 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. - * - * or both in parallel, as here. - * - * This file 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see <https://www.gnu.org/licenses/>. - */ - -#ifndef GNUPG_COMMON_KEYSERVER_H -#define GNUPG_COMMON_KEYSERVER_H - -#define KEYSERVER_PROTO_VERSION 1 - -/* These are usable for return codes for the gpgkeys_ process, and - also KEY FAILED codes. */ -#define KEYSERVER_OK 0 /* not an error */ -#define KEYSERVER_INTERNAL_ERROR 1 /* gpgkeys_ internal error */ -#define KEYSERVER_NOT_SUPPORTED 2 /* operation not supported */ -#define KEYSERVER_VERSION_ERROR 3 /* VERSION mismatch */ -#define KEYSERVER_GENERAL_ERROR 4 /* keyserver internal error */ -#define KEYSERVER_NO_MEMORY 5 /* out of memory */ -#define KEYSERVER_KEY_NOT_FOUND 6 /* key not found */ -#define KEYSERVER_KEY_EXISTS 7 /* key already exists */ -#define KEYSERVER_KEY_INCOMPLETE 8 /* key incomplete (EOF) */ -#define KEYSERVER_UNREACHABLE 9 /* unable to contact keyserver */ - -/* Must be 127 due to shell internal magic. */ -#define KEYSERVER_SCHEME_NOT_FOUND 127 - -/* Object to hold information pertaining to a keyserver; it also - allows building a list of keyservers. Note that g10/options.h has - a typedef for this. FIXME: We should make use of the - parse_uri_t. */ -struct keyserver_spec -{ - struct keyserver_spec *next; - char *uri; - char *scheme; - char *auth; - char *host; - char *port; - char *path; - char *opaque; - strlist_t options; - struct - { - unsigned int direct_uri:1; - } flags; -}; - - -#endif /*GNUPG_COMMON_KEYSERVER_H*/ diff --git a/common/name-value.c b/common/name-value.c index 0129f1b..f97396b 100644 --- a/common/name-value.c +++ b/common/name-value.c @@ -690,6 +690,7 @@ do_nvc_parse (nvc_t *result, int *errlinep, estream_t stream, if (raw_value) { err = _nvc_add (*result, name, NULL, raw_value, 1); + name = NULL; if (err) goto leave; } diff --git a/common/openpgp-fpr.c b/common/openpgp-fpr.c new file mode 100644 index 0000000..7b11008 --- /dev/null +++ b/common/openpgp-fpr.c @@ -0,0 +1,283 @@ +/* openpgp-fpr.c - OpenPGP Fingerprint computation + * Copyright (C) 2021 g10 Code GmbH + * + * This file is part of GnuPG. + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of either + * + * - the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * or + * + * - 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. + * + * or both in parallel, as here. + * + * This file 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses/>. + * SPDX-License-Identifier: (LGPL-3.0-or-later OR GPL-2.0-or-later) + */ + +#include <config.h> +#include <stdlib.h> +#include <errno.h> +#include <ctype.h> + +#include "util.h" +#include "openpgpdefs.h" + +/* Count the number of bits, assuming the A represents an unsigned big + * integer of length LEN bytes. */ +static unsigned int +count_bits (const unsigned char *a, size_t len) +{ + unsigned int n = len * 8; + int i; + + for (; len && !*a; len--, a++, n -=8) + ; + if (len) + { + for (i=7; i && !(*a & (1<<i)); i--) + n--; + } + return n; +} + +/* Variant of count_bits for simple octet strings. */ +static unsigned int +count_sos_bits (const unsigned char *a, size_t len) +{ + unsigned int n = len * 8; + int i; + + if (len == 0 || *a == 0) + return n; + + for (i=7; i && !(*a & (1<<i)); i--) + n--; + + return n; +} + + +gpg_error_t +compute_openpgp_fpr (int keyversion, int pgpalgo, unsigned long timestamp, + gcry_buffer_t *iov, int iovcnt, + unsigned char *result, unsigned int *r_resultlen) +{ + gpg_error_t err; + int hashalgo; + unsigned char prefix[15]; + size_t n; + int i; + + if (r_resultlen) + *r_resultlen = 0; + + if (iovcnt < 2) + return gpg_error (GPG_ERR_INV_ARG); + + /* Note that iov[0] is reserved. */ + for (n=0, i=1; i < iovcnt; i++) + n += iov[i].len; + + i = 0; + if (keyversion == 5) + { + hashalgo = GCRY_MD_SHA256; + n += 10; /* Add the prefix length. */ + prefix[i++] = 0x9a; + prefix[i++] = (n >> 24); + prefix[i++] = (n >> 16); + } + else if (keyversion == 4) + { + hashalgo = GCRY_MD_SHA1; + n += 6; /* Add the prefix length. */ + prefix[i++] = 0x99; + } + else + return gpg_error (GPG_ERR_UNKNOWN_VERSION); + + prefix[i++] = (n >> 8); + prefix[i++] = n; + prefix[i++] = keyversion; + prefix[i++] = (timestamp >> 24); + prefix[i++] = (timestamp >> 16); + prefix[i++] = (timestamp >> 8); + prefix[i++] = (timestamp); + prefix[i++] = pgpalgo; + if (keyversion == 5) + { + prefix[i++] = ((n-10) >> 24); + prefix[i++] = ((n-10) >> 16); + prefix[i++] = ((n-10) >> 8); + prefix[i++] = (n-10); + } + log_assert (i <= sizeof prefix); + /* The first element is reserved for our use; set it. */ + iov[0].size = 0; + iov[0].off = 0; + iov[0].len = i; + iov[0].data = prefix; + + /* for (i=0; i < iovcnt; i++) */ + /* log_printhex (iov[i].data, iov[i].len, "cmpfpr i=%d: ", i); */ + + err = gcry_md_hash_buffers (hashalgo, 0, result, iov, iovcnt); + /* log_printhex (result, 20, "fingerpint: "); */ + + /* Better clear the first element because it was set by us. */ + iov[0].size = 0; + iov[0].off = 0; + iov[0].len = 0; + iov[0].data = NULL; + + if (!err && r_resultlen) + *r_resultlen = (hashalgo == GCRY_MD_SHA1)? 20 : 32; + + return err; +} + + +gpg_error_t +compute_openpgp_fpr_rsa (int keyversion, unsigned long timestamp, + const unsigned char *m, unsigned int mlen, + const unsigned char *e, unsigned int elen, + unsigned char *result, unsigned int *r_resultlen) +{ + gcry_buffer_t iov[5] = { {0} }; + unsigned char nbits_m[2], nbits_e[2]; + unsigned int n; + + /* Strip leading zeroes. */ + for (; mlen && !*m; mlen--, m++) + ; + for (; elen && !*e; elen--, e++) + ; + + /* Count bits. */ + n = count_bits (m, mlen); + nbits_m[0] = n >> 8; + nbits_m[1] = n; + + n = count_bits (e, elen); + nbits_e[0] = n >> 8; + nbits_e[1] = n; + + /* Put parms into the array. Note that iov[0] is reserved. */ + iov[1].len = 2; + iov[1].data = nbits_m; + iov[2].len = mlen; + iov[2].data = (void*)m; + iov[3].len = 2; + iov[3].data = nbits_e; + iov[4].len = elen; + iov[4].data = (void*)e; + + return compute_openpgp_fpr (keyversion, PUBKEY_ALGO_RSA, timestamp, + iov, 5, result, r_resultlen); +} + + +/* Determine KDF hash algorithm and KEK encryption algorithm by CURVE. + * The returned buffer has a length of 4. + * Note: This needs to be kept in sync with the table in g10/ecdh.c */ +static const unsigned char* +default_ecdh_params (unsigned int nbits) +{ + /* See RFC-6637 for those constants. + 0x03: Number of bytes + 0x01: Version for this parameter format + KEK digest algorithm + KEK cipher algorithm + */ + if (nbits <= 256) + return (const unsigned char*)"\x03\x01\x08\x07"; + else if (nbits <= 384) + return (const unsigned char*)"\x03\x01\x09\x09"; + else + return (const unsigned char*)"\x03\x01\x0a\x09"; +} + + +gpg_error_t +compute_openpgp_fpr_ecc (int keyversion, unsigned long timestamp, + const char *curvename, int for_encryption, + const unsigned char *q, unsigned int qlen, + const unsigned char *kdf, unsigned int kdflen, + unsigned char *result, unsigned int *r_resultlen) +{ + gpg_error_t err; + const char *curveoidstr; + gcry_mpi_t curveoid = NULL; + unsigned int curvebits; + int pgpalgo; + const unsigned char *oidraw; + size_t oidrawlen; + gcry_buffer_t iov[5] = { {0} }; + unsigned int iovlen; + unsigned char nbits_q[2]; + unsigned int n; + + curveoidstr = openpgp_curve_to_oid (curvename, &curvebits, &pgpalgo); + err = openpgp_oid_from_str (curveoidstr, &curveoid); + if (err) + goto leave; + oidraw = gcry_mpi_get_opaque (curveoid, &n); + if (!oidraw) + { + err = gpg_error_from_syserror (); + goto leave; + } + oidrawlen = (n+7)/8; + + /* If the curve does not enforce a certain algorithm, we use the + * for_encryption flag to decide which algo to use. */ + if (!pgpalgo) + pgpalgo = for_encryption? PUBKEY_ALGO_ECDH : PUBKEY_ALGO_ECDSA; + + /* Count bits. */ + n = count_sos_bits (q, qlen); + nbits_q[0] = n >> 8; + nbits_q[1] = n; + + /* Put parms into the array. Note that iov[0] is reserved. */ + iov[1].len = oidrawlen; + iov[1].data = (void*)oidraw; + iov[2].len = 2; + iov[2].data = nbits_q; + iov[3].len = qlen; + iov[3].data = (void*)q; + iovlen = 4; + if (pgpalgo == PUBKEY_ALGO_ECDH) + { + if (!kdf || !kdflen || !kdf[0]) + { + /* No KDF given - use the default. */ + kdflen = 4; + kdf = default_ecdh_params (curvebits); + } + iov[4].len = kdflen; + iov[4].data = (void*)kdf; + iovlen++; + } + + err = compute_openpgp_fpr (keyversion, pgpalgo, timestamp, + iov, iovlen, result, r_resultlen); + + leave: + gcry_mpi_release (curveoid); + return err; +} diff --git a/common/openpgp-oid.c b/common/openpgp-oid.c index 18c5710..943fe3e 100644 --- a/common/openpgp-oid.c +++ b/common/openpgp-oid.c @@ -337,13 +337,17 @@ openpgp_oid_is_cv25519 (gcry_mpi_t a) /* Map the Libgcrypt ECC curve NAME to an OID. If R_NBITS is not NULL store the bit size of the curve there. Returns NULL for unknown - curve names. */ + curve names. If R_ALGO is not NULL and a specific ECC algorithm is + required for this curve its OpenPGP algorithm number is stored + there; otherwise 0 is stored which indicates that ECDSA or ECDH can + be used. */ const char * -openpgp_curve_to_oid (const char *name, unsigned int *r_nbits) +openpgp_curve_to_oid (const char *name, unsigned int *r_nbits, int *r_algo) { int i; unsigned int nbits = 0; const char *oidstr = NULL; + int algo = 0; if (name) { @@ -353,6 +357,7 @@ openpgp_curve_to_oid (const char *name, unsigned int *r_nbits) { oidstr = oidtable[i].oidstr; nbits = oidtable[i].nbits; + algo = oidtable[i].pubkey_algo; break; } if (!oidtable[i].name) @@ -364,6 +369,7 @@ openpgp_curve_to_oid (const char *name, unsigned int *r_nbits) { oidstr = oidtable[i].oidstr; nbits = oidtable[i].nbits; + algo = oidtable[i].pubkey_algo; break; } } @@ -371,6 +377,8 @@ openpgp_curve_to_oid (const char *name, unsigned int *r_nbits) if (r_nbits) *r_nbits = nbits; + if (r_algo) + *r_algo = algo; return oidstr; } diff --git a/common/openpgpdefs.h b/common/openpgpdefs.h index 5cc437a..05f3621 100644 --- a/common/openpgpdefs.h +++ b/common/openpgpdefs.h @@ -205,4 +205,26 @@ compress_algo_t; #define OPENPGP_MAX_NENC 2 /* Maximum number of encryption parameters. */ +/*-- openpgp-fpr.c --*/ +gpg_error_t compute_openpgp_fpr (int keyversion, int pgpalgo, + unsigned long timestamp, + gcry_buffer_t *iov, int iovcnt, + unsigned char *result, + unsigned int *r_resultlen); +gpg_error_t compute_openpgp_fpr_rsa (int keyversion, + unsigned long timestamp, + const unsigned char *m, unsigned int mlen, + const unsigned char *e, unsigned int elen, + unsigned char *result, + unsigned int *r_resultlen); +gpg_error_t compute_openpgp_fpr_ecc (int keyversion, + unsigned long timestamp, + const char *curvename, int for_encryption, + const unsigned char *q, unsigned int qlen, + const unsigned char *kdf, + unsigned int kdflen, + unsigned char *result, + unsigned int *r_resultlen); + + #endif /*GNUPG_COMMON_OPENPGPDEFS_H*/ diff --git a/common/sexputil.c b/common/sexputil.c index 9a79c05..68388e1 100644 --- a/common/sexputil.c +++ b/common/sexputil.c @@ -263,6 +263,96 @@ cmp_simple_canon_sexp (const unsigned char *a_orig, } + +/* Helper for cmp_canon_sexp. */ +static int +cmp_canon_sexp_def_tcmp (void *ctx, int depth, + const unsigned char *aval, size_t alen, + const unsigned char *bval, size_t blen) +{ + (void)ctx; + (void)depth; + + if (alen > blen) + return 1; + else if (alen < blen) + return -1; + else + return memcmp (aval, bval, alen); +} + + +/* Compare the two canonical encoded s-expressions A with maximum + * length ALEN and B with maximum length BLEN. + * + * Returns 0 if they match. + * + * If TCMP is NULL, this is not different really different from a + * memcmp but does not consider any garbage after the last closing + * parentheses. + * + * If TCMP is not NULL, it is expected to be a function to compare the + * values of each token. TCMP is called for each token while parsing + * the s-expressions until TCMP return a non-zero value. Here the CTX + * receives the provided value TCMPCTX, DEPTH is the number of + * currently open parentheses and (AVAL,ALEN) and (BVAL,BLEN) the + * values of the current token. TCMP needs to return zero to indicate + * that the tokens match. */ +int +cmp_canon_sexp (const unsigned char *a, size_t alen, + const unsigned char *b, size_t blen, + int (*tcmp)(void *ctx, int depth, + const unsigned char *aval, size_t avallen, + const unsigned char *bval, size_t bvallen), + void *tcmpctx) +{ + const unsigned char *a_buf, *a_tok; + const unsigned char *b_buf, *b_tok; + size_t a_buflen, a_toklen; + size_t b_buflen, b_toklen; + int a_depth, b_depth, ret; + + if ((!a && !b) || (!alen && !blen)) + return 0; /* Both are NULL, they are identical. */ + if (!a || !b) + return !!a - !!b; /* One is NULL, they are not identical. */ + if (*a != '(' || *b != '(') + log_bug ("invalid S-exp in %s\n", __func__); + + if (!tcmp) + tcmp = cmp_canon_sexp_def_tcmp; + + a_depth = 0; + a_buf = a; + a_buflen = alen; + b_depth = 0; + b_buf = b; + b_buflen = blen; + + for (;;) + { + if (parse_sexp (&a_buf, &a_buflen, &a_depth, &a_tok, &a_toklen)) + return -1; /* A is invalid. */ + if (parse_sexp (&b_buf, &b_buflen, &b_depth, &b_tok, &b_toklen)) + return -1; /* B is invalid. */ + if (!a_depth && !b_depth) + return 0; /* End of both expressions - they match. */ + if (a_depth != b_depth) + return a_depth - b_depth; /* Not the same structure */ + if (!a_tok && !b_tok) + ; /* parens */ + else if (a_tok && b_tok) + { + ret = tcmp (tcmpctx, a_depth, a_tok, a_toklen, b_tok, b_toklen); + if (ret) + return ret; /* Mismatch */ + } + else /* One has a paren other has not. */ + return !!a_tok - !!b_tok; + } +} + + /* Create a simple S-expression from the hex string at LINE. Returns a newly allocated buffer with that canonical encoded S-expression or NULL in case of an error. On return the number of characters @@ -512,6 +602,388 @@ get_rsa_pk_from_canon_sexp (const unsigned char *keydata, size_t keydatalen, } +/* Return the public key parameter Q of a public RSA or ECC key + * expressed as an canonical encoded S-expression. */ +gpg_error_t +get_ecc_q_from_canon_sexp (const unsigned char *keydata, size_t keydatalen, + unsigned char const **r_q, size_t *r_qlen) +{ + gpg_error_t err; + const unsigned char *buf, *tok; + size_t buflen, toklen; + int depth, last_depth1, last_depth2; + const unsigned char *ecc_q = NULL; + size_t ecc_q_len; + + *r_q = NULL; + *r_qlen = 0; + + buf = keydata; + buflen = keydatalen; + depth = 0; + if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))) + return err; + if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))) + return err; + if (!tok || toklen != 10 || memcmp ("public-key", tok, toklen)) + return gpg_error (GPG_ERR_BAD_PUBKEY); + if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))) + return err; + if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))) + return err; + if (tok && toklen == 3 && !memcmp ("ecc", tok, toklen)) + ; + else if (tok && toklen == 5 && (!memcmp ("ecdsa", tok, toklen) + || !memcmp ("eddsa", tok, toklen))) + ; + else + return gpg_error (GPG_ERR_WRONG_PUBKEY_ALGO); + + last_depth1 = depth; + while (!(err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)) + && depth && depth >= last_depth1) + { + if (tok) + return gpg_error (GPG_ERR_UNKNOWN_SEXP); + if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))) + return err; + if (tok && toklen == 1) + { + const unsigned char **mpi; + size_t *mpi_len; + + switch (*tok) + { + case 'q': mpi = &ecc_q; mpi_len = &ecc_q_len; break; + default: mpi = NULL; mpi_len = NULL; break; + } + if (mpi && *mpi) + return gpg_error (GPG_ERR_DUP_VALUE); + + if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))) + return err; + if (tok && mpi) + { + *mpi = tok; + *mpi_len = toklen; + } + } + + /* Skip to the end of the list. */ + last_depth2 = depth; + while (!(err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)) + && depth && depth >= last_depth2) + ; + if (err) + return err; + } + + if (err) + return err; + + if (!ecc_q || !ecc_q_len) + return gpg_error (GPG_ERR_BAD_PUBKEY); + + *r_q = ecc_q; + *r_qlen = ecc_q_len; + return 0; +} + + +/* Return an uncompressed point (X,Y) in P at R_BUF as a malloced + * buffer with its byte length stored at R_BUFLEN. May not be used + * for sensitive data. */ +static gpg_error_t +ec2os (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t p, + unsigned char **r_buf, unsigned int *r_buflen) +{ + gpg_error_t err; + int pbytes = (mpi_get_nbits (p)+7)/8; + size_t n; + unsigned char *buf, *ptr; + + *r_buf = NULL; + *r_buflen = 0; + + buf = xtrymalloc (1 + 2*pbytes); + if (!buf) + return gpg_error_from_syserror (); + *buf = 04; /* Uncompressed point. */ + ptr = buf+1; + err = gcry_mpi_print (GCRYMPI_FMT_USG, ptr, pbytes, &n, x); + if (err) + { + xfree (buf); + return err; + } + if (n < pbytes) + { + memmove (ptr+(pbytes-n), ptr, n); + memset (ptr, 0, (pbytes-n)); + } + ptr += pbytes; + err = gcry_mpi_print (GCRYMPI_FMT_USG, ptr, pbytes, &n, y); + if (err) + { + xfree (buf); + return err; + } + if (n < pbytes) + { + memmove (ptr+(pbytes-n), ptr, n); + memset (ptr, 0, (pbytes-n)); + } + + *r_buf = buf; + *r_buflen = 1 + 2*pbytes; + return 0; +} + + +/* Convert the ECC parameter Q in the canonical s-expression + * (KEYDATA,KEYDATALEN) to uncompressed form. On success and if a + * conversion was done, the new canonical encoded s-expression is + * returned at (R_NEWKEYDAT,R_NEWKEYDATALEN); if a conversion was not + * required (NULL,0) is stored there. On error an error code is + * returned. The function may take any kind of key but will only do + * the conversion for ECC curves where compression is supported. */ +gpg_error_t +uncompress_ecc_q_in_canon_sexp (const unsigned char *keydata, + size_t keydatalen, + unsigned char **r_newkeydata, + size_t *r_newkeydatalen) +{ + gpg_error_t err; + const unsigned char *buf, *tok; + size_t buflen, toklen, n; + int depth, last_depth1, last_depth2; + const unsigned char *q_ptr; /* Points to the value of "q". */ + size_t q_ptrlen; /* Remaining length in KEYDATA. */ + size_t q_toklen; /* Q's length including prefix. */ + const unsigned char *curve_ptr; /* Points to the value of "curve". */ + size_t curve_ptrlen; /* Remaining length in KEYDATA. */ + gcry_mpi_t x, y; /* Point Q */ + gcry_mpi_t p, a, b; /* Curve parameters. */ + gcry_mpi_t x3, t, p1_4; /* Helper */ + int y_bit; + unsigned char *qvalue; /* Q in uncompressed form. */ + unsigned int qvaluelen; + unsigned char *dst; /* Helper */ + char lenstr[35]; /* Helper for a length prefix. */ + + *r_newkeydata = NULL; + *r_newkeydatalen = 0; + + buf = keydata; + buflen = keydatalen; + depth = 0; + if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))) + return err; + if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))) + return err; + if (!tok) + return gpg_error (GPG_ERR_BAD_PUBKEY); + else if (toklen == 10 || !memcmp ("public-key", tok, toklen)) + ; + else if (toklen == 11 || !memcmp ("private-key", tok, toklen)) + ; + else if (toklen == 20 || !memcmp ("shadowed-private-key", tok, toklen)) + ; + else + return gpg_error (GPG_ERR_BAD_PUBKEY); + + if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))) + return err; + if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))) + return err; + + if (tok && toklen == 3 && !memcmp ("ecc", tok, toklen)) + ; + else if (tok && toklen == 5 && !memcmp ("ecdsa", tok, toklen)) + ; + else + return 0; /* Other algo - no need for conversion. */ + + last_depth1 = depth; + q_ptr = curve_ptr = NULL; + q_ptrlen = 0; /*(silence cc warning)*/ + while (!(err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)) + && depth && depth >= last_depth1) + { + if (tok) + return gpg_error (GPG_ERR_UNKNOWN_SEXP); + if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))) + return err; + if (tok && toklen == 1 && *tok == 'q' && !q_ptr) + { + q_ptr = buf; + q_ptrlen = buflen; + } + else if (tok && toklen == 5 && !memcmp (tok, "curve", 5) && !curve_ptr) + { + curve_ptr = buf; + curve_ptrlen = buflen; + } + + if (q_ptr && curve_ptr) + break; /* We got all what we need. */ + + /* Skip to the end of the list. */ + last_depth2 = depth; + while (!(err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)) + && depth && depth >= last_depth2) + ; + if (err) + return err; + } + if (err) + return err; + + if (!q_ptr) + return 0; /* No Q - nothing to do. */ + + /* Get Q's value and check whether uncompressing is at all required. */ + buf = q_ptr; + buflen = q_ptrlen; + if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))) + return err; + if (toklen < 2 || !(*tok == 0x02 || *tok == 0x03)) + return 0; /* Invalid length or not compressed. */ + q_toklen = buf - q_ptr; /* We want the length with the prefix. */ + + /* Put the x-coordinate of q into X and remember the y bit */ + y_bit = (*tok == 0x03); + err = gcry_mpi_scan (&x, GCRYMPI_FMT_USG, tok+1, toklen-1, NULL); + if (err) + return err; + + /* For uncompressing we need to know the curve. */ + if (!curve_ptr) + { + gcry_mpi_release (x); + return gpg_error (GPG_ERR_INV_CURVE); + } + buf = curve_ptr; + buflen = curve_ptrlen; + if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))) + { + gcry_mpi_release (x); + return err; + } + + { + char name[50]; + gcry_sexp_t curveparam; + + if (toklen + 1 > sizeof name) + { + gcry_mpi_release (x); + return gpg_error (GPG_ERR_TOO_LARGE); + } + mem2str (name, tok, toklen+1); + curveparam = gcry_pk_get_param (GCRY_PK_ECC, name); + if (!curveparam) + { + gcry_mpi_release (x); + return gpg_error (GPG_ERR_UNKNOWN_CURVE); + } + + err = gcry_sexp_extract_param (curveparam, NULL, "pab", &p, &a, &b, NULL); + gcry_sexp_release (curveparam); + if (err) + { + gcry_mpi_release (x); + return gpg_error (GPG_ERR_INTERNAL); + } + } + + if (!mpi_test_bit (p, 1)) + { + /* No support for point compression for this curve. */ + gcry_mpi_release (x); + gcry_mpi_release (p); + gcry_mpi_release (a); + gcry_mpi_release (b); + return gpg_error (GPG_ERR_NOT_IMPLEMENTED); + } + + /* + * Recover Y. The Weierstrass curve: y^2 = x^3 + a*x + b + */ + + x3 = mpi_new (0); + t = mpi_new (0); + p1_4 = mpi_new (0); + y = mpi_new (0); + + /* Compute right hand side. */ + mpi_powm (x3, x, GCRYMPI_CONST_THREE, p); + mpi_mul (t, a, x); + mpi_mod (t, t, p); + mpi_add (t, t, b); + mpi_mod (t, t, p); + mpi_add (t, t, x3); + mpi_mod (t, t, p); + + /* + * When p mod 4 = 3, modular square root of A can be computed by + * A^((p+1)/4) mod p + */ + + /* Compute (p+1)/4 into p1_4 */ + mpi_rshift (p1_4, p, 2); + mpi_add_ui (p1_4, p1_4, 1); + + mpi_powm (y, t, p1_4, p); + + if (y_bit != mpi_test_bit (y, 0)) + mpi_sub (y, p, y); + + gcry_mpi_release (p1_4); + gcry_mpi_release (t); + gcry_mpi_release (x3); + gcry_mpi_release (a); + gcry_mpi_release (b); + + err = ec2os (x, y, p, &qvalue, &qvaluelen); + gcry_mpi_release (x); + gcry_mpi_release (y); + gcry_mpi_release (p); + if (err) + return err; + + snprintf (lenstr, sizeof lenstr, "%u:", (unsigned int)qvaluelen); + /* Note that for simplicity we do not subtract the old length of Q + * for the new buffer. */ + *r_newkeydata = xtrymalloc (qvaluelen + strlen(lenstr) + qvaluelen); + if (!*r_newkeydata) + return gpg_error_from_syserror (); + dst = *r_newkeydata; + + n = q_ptr - keydata; + memcpy (dst, keydata, n); /* Copy first part of original data. */ + dst += n; + + n = strlen (lenstr); + memcpy (dst, lenstr, n); /* Copy new prefix of Q's value. */ + dst += n; + + memcpy (dst, qvalue, qvaluelen); /* Copy new value of Q. */ + dst += qvaluelen; + + log_assert (q_toklen < q_ptrlen); + n = q_ptrlen - q_toklen; + memcpy (dst, q_ptr + q_toklen, n);/* Copy rest of original data. */ + dst += n; + + *r_newkeydatalen = dst - *r_newkeydata; + + xfree (qvalue); + + return 0; +} + + /* Return the algo of a public KEY of SEXP. */ int get_pk_algo_from_key (gcry_sexp_t key) @@ -623,7 +1095,7 @@ pubkey_algo_string (gcry_sexp_t s_pkey, enum gcry_pk_algos *r_algoid) { const char *curve = gcry_pk_get_curve (s_pkey, 0, NULL); const char *name = openpgp_oid_to_curve - (openpgp_curve_to_oid (curve, NULL), 0); + (openpgp_curve_to_oid (curve, NULL, NULL), 0); if (name) result = xtrystrdup (name); @@ -698,3 +1170,19 @@ hash_algo_to_string (int algo) return hashnames[i].name; return "?"; } + + +/* Map cipher modes to a string. */ +const char * +cipher_mode_to_string (int mode) +{ + switch (mode) + { + case GCRY_CIPHER_MODE_CFB: return "CFB"; + case GCRY_CIPHER_MODE_CBC: return "CBC"; + case GCRY_CIPHER_MODE_GCM: return "GCM"; + case GCRY_CIPHER_MODE_OCB: return "OCB"; + case 14: return "EAX"; /* Only in gcrypt 1.9 */ + default: return "[?]"; + } +} diff --git a/common/t-sexputil.c b/common/t-sexputil.c index ceb8280..a1a9d89 100644 --- a/common/t-sexputil.c +++ b/common/t-sexputil.c @@ -28,6 +28,10 @@ __FILE__,__LINE__, (a)); \ exit (1); \ } while(0) +#define fail2(a,e) do { fprintf (stderr, "%s:%d: test %d failed: %s\n", \ + __FILE__,__LINE__, (a), gpg_strerror ((e))); \ + exit (1); \ + } while(0) static void @@ -178,6 +182,304 @@ test_make_canon_sexp_from_rsa_pk (void) } +/* Communiacation object for tcmp. */ +struct tcmp_parm_s { + int curve_seen; +}; + +/* Helper for test_cmp_canon_sexp. */ +static int +tcmp1 (void *opaque, int depth, + const unsigned char *aval, size_t alen, + const unsigned char *bval, size_t blen) +{ + struct tcmp_parm_s *parm = opaque; + + (void)depth; + + if (parm->curve_seen) + { + /* Last token was "curve", canonicalize its argument. */ + parm->curve_seen = 0; + + if (alen == 8 && !memcmp (aval, "nistp256", alen)) + { + alen = 19; + aval = "1.2.840.10045.3.1.7"; + } + + if (blen == 8 && !memcmp (bval, "nistp256", blen)) + { + blen = 19; + bval = "1.2.840.10045.3.1.7"; + } + } + else if (alen == 5 && !memcmp (aval, "curve", 5)) + parm->curve_seen = 1; + else + parm->curve_seen = 0; + + if (alen > blen) + return 1; + else if (alen < blen) + return -1; + else + return memcmp (aval, bval, alen); +} + + +static void +test_cmp_canon_sexp (void) +{ + struct { + unsigned char *a; + unsigned char *b; + int expected0; /* Expected result without compare function. */ + int expected1; /* Expected result with compare function tcmp1. */ + } + tests[] = { + { + "(10:public-key(3:ecc(5:curve8:nistp256)(1:q10:qqqqqqqqqq)))", + "(10:public-key(3:ecc(5:curve8:nistp256)(1:q10:qqqqqqqqqq)))", + 0, 0 + }, + { + "(10:public-key(3:ecc(5:curve19:1.2.840.10045.3.1.7)(1:q10:qqqqqqqqqq)))", + "(10:public-key(3:ecc(5:curve19:1.2.840.10045.3.1.7)(1:q10:qqqqqqqqqq)))", + 0, 0 + }, + { + "(10:public-key(3:ecc(5:curve8:nistp256)(1:q10:qqqqqqqqqq)))", + "(10:public-key(3:ecc(5:curve19:1.2.840.10045.3.1.7)(1:q10:qqqqqqqqqq)))", + -1, 0 + }, + { + "(10:public-key(3:ecc(5:curve19:1.2.840.10045.3.1.7)(1:q10:qqqqqqqqqq)))", + "(10:public-key(3:ecc(5:curve8:nistp256)(1:q10:qqqqqqqqqq)))", + 1, 0 + }, + { + NULL + } + }; + struct tcmp_parm_s parm = {0}; + int idx; + int res; + + for (idx=0; tests[idx].a; idx++) + { + res = cmp_canon_sexp (tests[idx].a, strlen (tests[idx].a), + tests[idx].b, strlen (tests[idx].b), + NULL, NULL); + if (res != tests[idx].expected0) + fail (idx); + res = cmp_canon_sexp (tests[idx].a, strlen (tests[idx].a), + tests[idx].b, strlen (tests[idx].b), + tcmp1, &parm); + if (res != tests[idx].expected1) + fail (idx); + } +} + + +static void +test_ecc_uncompress (void) +{ + struct { + const char *a; /* Uncompressed. */ + const char *b; /* Compressed. */ + } + tests[] = { + { + "(public-key" + " (ecc" + " (curve brainpoolP256r1)" + " (q #042ECD8679930BE2DB4AD42B8600BA3F80" + /* */"2D4D539BFF2F69B83EC9B7BBAA7F3406" + /* */"436DD11A1756AFE56CD93408410FCDA9" + /* */"BA95024EB613BD481A14FCFEC27A448A#)))", + /* The same in compressed form. */ + "(public-key" + " (ecc" + " (curve brainpoolP256r1)" + " (q #022ECD8679930BE2DB4AD42B8600BA3F80" + /* */"2D4D539BFF2F69B83EC9B7BBAA7F3406#)))" + }, + { + "(public-key" + " (ecc" + " (curve brainpoolP256r1)" + " (q #045B784CA008EE64AB3D85017EE0D2BE87" + /* */"558762C7300E0C8E06B1F9AF7C031458" + /* */"9EBBA41915313417BA54218EB0569C59" + /* */"0B156C76DBCAB6E84575E6EF68CE7B87#)))", + /* The same in compressed form. */ + "(public-key" + " (ecc" + " (curve brainpoolP256r1)" + " (q #035B784CA008EE64AB3D85017EE0D2BE87" + /* */"558762C7300E0C8E06B1F9AF7C031458#)))" + }, + { /* A key which does not require a conversion. */ + "(public-key" + " (ecdsa" + " (p #00FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF#)" + " (curve \"NIST P-256\")" + " (b #5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B#)" + " (g #046B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C2964FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5#)" + " (n #00FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551#)" + " (h #000000000000000000000000000000000000000000000000000000000000000001#)" + " (q #04C8A4CEC2E9A9BC8E173531A67B0840DF345C32E261ADD780E6D83D56EFADFD5DE872F8B854819B59543CE0B7F822330464FBC4E6324DADDCD9D059554F63B344#)))" + }, + { /* Nothing to do for an RSA private key. */ + "(private-key" + " (rsa" + " (n #00B6B509596A9ECABC939212F891E656A626BA07DA8521A9CAD4C08E640C04052FBB87F424EF1A0275A48A9299AC9DB69ABE3D0124E6C756B1F7DFB9B842D6251AEA6EE85390495CADA73D671537FCE5850A932F32BAB60AB1AC1F852C1F83C625E7A7D70CDA9EF16D5C8E47739D77DF59261ABE8454807FF441E143FBD37F8545#)" + " (e #010001#)" + " (d #077AD3DE284245F4806A1B82B79E616FBDE821C82D691A65665E57B5FAD3F34E67F401E7BD2E28699E89D9C496CF821945AE83AC7A1231176A196BA6027E77D85789055D50404A7A2A95B1512F91F190BBAEF730ED550D227D512F89C0CDB31AC06FA9A19503DDF6B66D0B42B9691BFD6140EC1720FFC48AE00C34796DC899E5#)" + " (p #00D586C78E5F1B4BF2E7CD7A04CA091911706F19788B93E44EE20AAF462E8363E98A72253ED845CCBF2481BB351E8557C85BCFFF0DABDBFF8E26A79A0938096F27#)" + " (q #00DB0CDF60F26F2A296C88D6BF9F8E5BE45C0DDD713C96CC73EBCB48B061740943F21D2A93D6E42A7211E7F02A95DCED6C390A67AD21ECF739AE8A0CA46FF2EBB3#)" + " (u #33149195F16912DB20A48D020DBC3B9E3881B39D722BF79378F6340F43148A6E9FC5F53E2853B7387BA4443BA53A52FCA8173DE6E85B42F9783D4A7817D0680B#)))" + }, + { /* Nothing to do dor a DSA key. */ + " (public-key" + " (dsa" + " (p #0084E4C626E16005770BD9509ABF7354492E85B8C0060EFAAAEC617F725B592FAA59DF5460575F41022776A9718CE62EDD542AB73C7720869EBDBC834D174ADCD7136827DF51E2613545A25CA573BC502A61B809000B6E35F5EB7FD6F18C35678C23EA1C3638FB9CFDBA2800EE1B62F41A4479DE824F2834666FBF8DC5B53C2617#)" + " (q #00B0E6F710051002A9F425D98A677B18E0E5B038AB#)" + " (g #44370CEE0FE8609994183DBFEBA7EEA97D466838BCF65EFF506E35616DA93FA4E572A2F08886B74977BC00CA8CD3DBEA7AEB7DB8CBB180E6975E0D2CA76E023E6DE9F8CCD8826EBA2F72B8516532F6001DEFFAE76AA5E59E0FA33DBA3999B4E92D1703098CDEDCC416CF008801964084CDE1980132B2B78CB4CE9C15A559528B#)" + " (y #3D5DD14AFA2BF24A791E285B90232213D0E3BA74AB1109E768AED19639A322F84BB7D959E2BA92EF73DE4C7F381AA9F4053CFA3CD4527EF9043E304E5B95ED0A3A5A9D590AA641C13DB2B6E32B9B964A6A2C730DD3EA7C8E13F7A140AFF1A91CE375E9B9B960384779DC4EA180FA1F827C52288F366C0770A220F50D6D8FD6F6#)))" + }, + { /* Nothing to do for an ECDSA key w/o curvename. */ + "(public-key" + " (ecdsa(flags param)" + " (p #00FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF#)" + " (a #00FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC#)" + " (b #5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B#)" + " (g #046B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C2964FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5#)" + " (n #00FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551#)" + " (h #000000000000000000000000000000000000000000000000000000000000000001#)" + " (q #04C8A4CEC2E9A9BC8E173531A67B0840DF345C32E261ADD780E6D83D56EFADFD5DE872F8B854819B59543CE0B7F822330464FBC4E6324DADDCD9D059554F63B344#)))" + }, + { /* Nothing to do for Ed25519 key. */ + "(public-key" + " (ecc" + " (curve Ed25519)" + " (q #04" + " 1CC662926E7EFF4982B7FB8B928E61CD74CCDD85277CC57196C3AD20B611085F" + " 47BD24842905C049257673B3F5249524E0A41FAA17B25B818D0F97E625F1A1D0#)" + " ))" + }, + { /* Nothing to do for Ed25519 with EdDSA key. */ + "(public-key" + " (ecc" + " (curve Ed25519)(flags eddsa)" + " (q #773E72848C1FD5F9652B29E2E7AF79571A04990E96F2016BF4E0EC1890C2B7DB#)" + " ))" + }, + { /* Nothing to do for Ed25519 with EdDSA key with prefix. */ + "(public-key" + " (ecc" + " (curve Ed25519)(flags eddsa)" + " (q #40" + " 773E72848C1FD5F9652B29E2E7AF79571A04990E96F2016BF4E0EC1890C2B7DB#)" + " ))" + }, + { /* Nothing to do for Ed25519 with EdDSA key with uncompress prefix. */ + "(public-key" + " (ecc" + " (curve Ed25519)(flags eddsa)" + " (q #04" + " 629ad237d1ed04dcd4abe1711dd699a1cf51b1584c4de7a4ef8b8a640180b26f" + " 5bb7c29018ece0f46b01f2960e99041a5779afe7e2292b65f9d51f8c84723e77#)" + " ))" + }, + { /* Noting to do for a Cv25519 tweaked key. */ + "(public-key" + " (ecc" + " (curve Curve25519)(flags djb-tweak)" + " (q #40" + " 918C1733127F6BF2646FAE3D081A18AE77111C903B906310B077505EFFF12740#)" + " ))" + }, + { /* Nothing to do for a shadowed key. */ + "(shadowed-private-key" + " (rsa" + " (n #00B493C79928398DA9D99AC0E949FE6EB62F683CB974FFFBFBC01066F5C9A89B" + " D3DC48EAD7C65F36EA943C2B2C865C26C4884FF9EDFDA8C99C855B737D77EEF6" + " B85DBC0CCEC0E900C1F89A6893A2A93E8B31028469B6927CEB2F08687E547C68" + " 6B0A2F7E50A194FF7AB7637E03DE0912EF7F6E5F1EC37625BD1620CCC2E7A564" + " 31E168CDAFBD1D9E61AE47A69A6FA03EF22F844528A710B2392F262B95A3078C" + " F321DC8325F92A5691EF69F34FD0DE0B22C79D29DC87723FCADE463829E8E5F7" + " D196D73D6C9C180F6A6A0DDBF7B9D8F7FA293C36163B12199EF6A1A95CAE4051" + " E3069C522CC6C4A7110F663A5DAD20F66C13A1674D050088208FAE4F33B3AB51" + " 03#)" + " (e #00010001#)" + " (shadowed t1-v1" + " (#D2760001240102000005000123350000# OPENPGP.1)" + ")))" + }, + { + NULL + }}; + gpg_error_t err; + int idx; + gcry_sexp_t sexp; + unsigned char *abuf, *bbuf, *rbuf; + size_t abuflen, bbuflen, rbuflen; + + + for (idx=0; tests[idx].a; idx++) + { + err = gcry_sexp_new (&sexp, tests[idx].a, 0, 1); + if (err) + fail2 (idx,err); + err = make_canon_sexp (sexp, &abuf, &abuflen); + if (err) + fail2 (idx,err); + gcry_sexp_release (sexp); + + if (tests[idx].b) + { + err = gcry_sexp_new (&sexp, tests[idx].b, 0, 1); + if (err) + fail2 (idx,err); + err = make_canon_sexp (sexp, &bbuf, &bbuflen); + if (err) + fail2 (idx,err); + gcry_sexp_release (sexp); + } + else + bbuf = NULL; + + err = uncompress_ecc_q_in_canon_sexp (abuf, abuflen, &rbuf, &rbuflen); + if (err) + fail2 (idx,err); + if (rbuf) + fail (idx); /* Converted without a need. */ + + if (bbuf) + { + err = uncompress_ecc_q_in_canon_sexp (bbuf, bbuflen, &rbuf, &rbuflen); + if (err) + fail2 (idx,err); + if (!rbuf) + fail (idx); /* Not converted despite a need for it. */ + + /* log_printcanon (" orig:", abuf, abuflen); */ + /* log_printcanon (" comp:", bbuf, bbuflen); */ + /* log_printcanon ("uncomp:", rbuf, rbuflen); */ + + if (rbuflen != abuflen || memcmp (rbuf, abuf, abuflen)) + fail (idx); + } + + xfree (abuf); + xfree (bbuf); + xfree (rbuf); + } +} + + int main (int argc, char **argv) { @@ -186,6 +488,8 @@ main (int argc, char **argv) test_hash_algo_from_sigval (); test_make_canon_sexp_from_rsa_pk (); + test_cmp_canon_sexp (); + test_ecc_uncompress (); return 0; } diff --git a/common/t-w32-cmdline.c b/common/t-w32-cmdline.c new file mode 100644 index 0000000..a1039d0 --- /dev/null +++ b/common/t-w32-cmdline.c @@ -0,0 +1,250 @@ +/* t-w32-cmdline.c - Test the parser for the Windows command line + * Copyright (C) 2021 g10 Code GmbH + * + * This file is part of GnuPG. + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of either + * + * - the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * or + * + * - 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. + * + * or both in parallel, as here. + * + * This file 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses/>. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> +#include <unistd.h> +#ifdef HAVE_W32_SYSTEM +# define WIN32_LEAN_AND_MEAN +# include <windows.h> +#endif + +#include "t-support.h" +#include "utf8conv.h" +#include "w32help.h" + +#define PGM "t-w32-cmdline" + +static int verbose; +static int debug; +static int errcount; + + +static void +test_all (void) +{ + static struct { + const char *cmdline; + int argc; /* Expected number of args. */ + char *argv[10]; /* Expected results. */ + int use_glob; + } tests[] = { + /* Examples from "Parsing C++ Command-Line Arguments" dated 11/18/2006. + * https://docs.microsoft.com/en-us/previous-versions/17w5ykft(v=vs.85) + */ + { "\"abc\" d e", 3, { "abc", "d", "e" }}, + { "a\\\\\\b d\"e f\"g h", 3, { "a\\\\\\b", "de fg", "h" }}, + { "a\\\\\\\"b c d", 3, { "a\\\"b", "c", "d" }}, + { "a\\\\\\\\\"b c\" d e", 3, { "a\\\\b c", "d", "e" }}, + /* Examples from "Parsing C Command-Line Arguments" dated 11/09/2020. + * https://docs.microsoft.com/en-us/cpp/c-language/\ + * parsing-c-command-line-arguments?view=msvc-160 + */ + { "\"a b c\" d e", 3, { "a b c", "d", "e" }}, + { "\"ab\\\"c\" \"\\\\\" d", 3, { "ab\"c", "\\", "d" }}, + { "a\\\\\\b d\"e f\"g h", 3, { "a\\\\\\b", "de fg", "h" }}, + { "a\\\\\\\"b c d", 3, { "a\\\"b", "c", "d" }}, + { "a\\\\\\\\\"b c\" d e", 3, { "a\\\\b c", "d", "e" }}, + { "a\"b\"\" c d", 1, { "ab\" c d" }}, + /* Some arbitrary tests created using mingw. + * But I am not sure whether their parser is fully correct. + */ + { "e:a a b\"c\" ", 3, { "e:a", "a", "bc" }}, + /* { "e:a a b\"c\"\" d\"\"e \" ", */ + /* 5, { "e:a", "a", "bc\"", "de", " " }}, */ + /* { "e:a a b\"c\"\" d\"\"e\" f\\gh ", */ + /* 4, { "e:a", "a", "bc\"", "de f\\gh "}}, */ + /* { "e:a a b\"c\"\" d\"\"e\" f\\\"gh \" ", */ + /* 4, { "e:a", "a", "bc\"", "de f\"gh " }},*/ + + { "\"foo bar\"", 1 , { "foo bar" }}, + +#ifndef HAVE_W32_SYSTEM + /* We actually don't use this code on Unix but we provide a way to + * test some of the blobing code. */ + { "foo", 1, { "foo" }, 1 }, + { "foo*", 2, { "[* follows]", "foo*" }, 1 }, + { "foo?", 2, { "[? follows]", "foo?" }, 1 }, + { "? \"*\" *", 5, { "[? follows]", "?", "*", "[* follows]", "*" }, 1 }, +#endif /*!HAVE_W32_SYSTEM*/ + { "", 1 , { "" }} + }; + int tidx; + int i, any, itemsalloced, argc; + char *cmdline; + char **argv; + + for (tidx = 0; tidx < DIM(tests); tidx++) + { + cmdline = xstrdup (tests[tidx].cmdline); + if (verbose && tidx) + putchar ('\n'); + if (verbose) + printf ("test %d: line ->%s<-\n", tidx, cmdline); + argv = w32_parse_commandline (cmdline, tests[tidx].use_glob, + &argc, &itemsalloced); + if (!argv) + { + fail (tidx); + xfree (cmdline); + continue; + } + if (tests[tidx].argc != argc) + { + fprintf (stderr, PGM": test %d: argc wrong (want %d, got %d)\n", + tidx, tests[tidx].argc, argc); + any = 1; + } + else + any = 0; + for (i=0; i < tests[tidx].argc; i++) + { + if (verbose) + printf ("test %d: argv[%d] ->%s<-\n", + tidx, i, tests[tidx].argv[i]); + if (i < argc && strcmp (tests[tidx].argv[i], argv[i])) + { + if (verbose) + printf ("test %d: got[%d] ->%s<- ERROR\n", + tidx, i, argv[i]); + any = 1; + } + } + if (any) + { + fprintf (stderr, PGM": test %d: error%s\n", + tidx, verbose? "":" (use --verbose)"); + errcount++; + } + + if (itemsalloced) + { + for (i=0; i < argc; i++) + xfree (argv[i]); + } + xfree (argv); + xfree (cmdline); + } +} + + + +int +main (int argc, char **argv) +{ + int last_argc = -1; + + no_exit_on_fail = 1; + + if (argc) + { argc--; argv++; } + while (argc && last_argc != argc ) + { + last_argc = argc; + if (!strcmp (*argv, "--")) + { + argc--; argv++; + break; + } + else if (!strcmp (*argv, "--help")) + { + fputs ("usage: " PGM " [test args]\n" + "Options:\n" + " --verbose Print timings etc.\n" + " --debug Flyswatter\n" + , stdout); + exit (0); + } + else if (!strcmp (*argv, "--verbose")) + { + verbose++; + argc--; argv++; + } + else if (!strcmp (*argv, "--debug")) + { + verbose += 2; + debug++; + argc--; argv++; + } + else if (!strncmp (*argv, "--", 2)) + { + fprintf (stderr, PGM ": unknown option '%s'\n", *argv); + exit (1); + } + } + + if (argc) + { +#ifdef HAVE_W32_SYSTEM + const wchar_t *wcmdline; + char *cmdline; + int i, myargc; + char **myargv; + + wcmdline = GetCommandLineW (); + if (!wcmdline) + { + fprintf (stderr, PGM ": GetCommandLine failed\n"); + exit (1); + } + + cmdline = wchar_to_utf8 (wcmdline); + if (!cmdline) + { + fprintf (stderr, PGM ": wchar_to_utf8 failed\n"); + exit (1); + } + + printf ("cmdline ->%s<\n", cmdline); + myargv = w32_parse_commandline (cmdline, 1, &myargc, NULL); + if (!myargv) + { + fprintf (stderr, PGM ": w32_parse_commandline failed\n"); + exit (1); + } + + for (i=0; i < myargc; i++) + printf ("argv[%d] ->%s<-\n", i, myargv[i]); + fflush (stdout); + + xfree (myargv); + xfree (cmdline); +#else + fprintf (stderr, PGM ": manual test mode not available on Unix\n"); + errcount++; +#endif + } + else + test_all (); + + return !!errcount; +} diff --git a/common/tlv.c b/common/tlv.c index 0058b67..7fb7bde 100644 --- a/common/tlv.c +++ b/common/tlv.c @@ -250,8 +250,8 @@ parse_ber_header (unsigned char const **buffer, size_t *size, returned as a pointer into the original buffer at TOK and TOKLEN. If a parentheses is the next token, TOK will be set to NULL. TOKLEN is checked to be within the bounds. On error an error code - is returned and no pointer is not guaranteed to point to - a meaningful value. DEPTH should be initialized to 0 and will + is returned and pointers are not guaranteed to point to + meaningful values. DEPTH should be initialized to 0 and will reflect on return the actual depth of the tree. To detect the end of the S-expression it is advisable to check DEPTH after a successful return. diff --git a/common/tlv.h b/common/tlv.h index ba4ea2e..0894e5d 100644 --- a/common/tlv.h +++ b/common/tlv.h @@ -30,6 +30,8 @@ #ifndef SCD_TLV_H #define SCD_TLV_H 1 +#include "membuf.h" + enum tlv_tag_class { CLASS_UNIVERSAL = 0, diff --git a/common/ttyio.c b/common/ttyio.c index c7c9d85..c385700 100644 --- a/common/ttyio.c +++ b/common/ttyio.c @@ -1,6 +1,7 @@ /* ttyio.c - tty i/O functions - * Copyright (C) 1998,1999,2000,2001,2002,2003,2004,2006,2007, - * 2009, 2010 Free Software Foundation, Inc. + * Copyright (C) 1997-2019 Werner Koch + * Copyright (C) 1998-2020 Free Software Foundation, Inc. + * Copyright (C) 2015-2020 g10 Code GmbH * * This file is part of GnuPG. * @@ -26,6 +27,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, see <https://www.gnu.org/licenses/>. + * SPDX-License-Identifier: (LGPL-3.0-or-later OR GPL-2.0-or-later) */ #include <config.h> @@ -35,24 +37,20 @@ #include <stdarg.h> #include <unistd.h> -#if defined(HAVE_W32_SYSTEM) && !defined(HAVE_W32CE_SYSTEM) -# define USE_W32_CONSOLE 1 -#endif - #ifdef HAVE_TCGETATTR -#include <termios.h> +# include <termios.h> #else -#ifdef HAVE_TERMIO_H +# ifdef HAVE_TERMIO_H /* simulate termios with termio */ -#include <termio.h> -#define termios termio -#define tcsetattr ioctl -#define TCSAFLUSH TCSETAF -#define tcgetattr(A,B) ioctl(A,TCGETA,B) -#define HAVE_TCGETATTR -#endif +# include <termio.h> +# define termios termio +# define tcsetattr ioctl +# define TCSAFLUSH TCSETAF +# define tcgetattr(A,B) ioctl(A,TCGETA,B) +# define HAVE_TCGETATTR +# endif #endif -#ifdef USE_W32_CONSOLE +#ifdef HAVE_W32_SYSTEM # ifdef HAVE_WINSOCK2_H # include <winsock2.h> # endif @@ -66,23 +64,24 @@ #include "util.h" #include "ttyio.h" +#include "i18n.h" #include "common-defs.h" #define CONTROL_D ('D' - 'A' + 1) -#ifdef USE_W32_CONSOLE +#ifdef HAVE_W32_SYSTEM static struct { HANDLE in, out; } con; #define DEF_INPMODE (ENABLE_LINE_INPUT|ENABLE_ECHO_INPUT \ - |ENABLE_PROCESSED_INPUT ) + |ENABLE_PROCESSED_INPUT ) #define HID_INPMODE (ENABLE_LINE_INPUT|ENABLE_PROCESSED_INPUT ) #define DEF_OUTMODE (ENABLE_WRAP_AT_EOL_OUTPUT|ENABLE_PROCESSED_OUTPUT) -#else /* yeah, we have a real OS */ +#else /* Unix */ static FILE *ttyfp = NULL; -#endif +#endif /* Unix */ static int initialized; static int last_prompt_len; @@ -145,120 +144,136 @@ tty_get_ttyname (void) static void cleanup(void) { - if( restore_termios ) { - restore_termios = 0; /* do it prios in case it is interrupted again */ - if( tcsetattr(fileno(ttyfp), TCSAFLUSH, &termsave) ) - log_error("tcsetattr() failed: %s\n", strerror(errno) ); + if (restore_termios) + { + restore_termios = 0; /* do it prior in case it is interrupted again */ + if (tcsetattr(fileno(ttyfp), TCSAFLUSH, &termsave)) + log_error ("tcsetattr() failed: %s\n", strerror (errno)); } } -#endif +#endif /*HAVE_TCGETATTR*/ + static void init_ttyfp(void) { - if( initialized ) - return; + if (initialized) + return; -#if defined(USE_W32_CONSOLE) +#ifdef HAVE_W32_SYSTEM + { + SECURITY_ATTRIBUTES sa; + + memset (&sa, 0, sizeof(sa)); + sa.nLength = sizeof(sa); + sa.bInheritHandle = TRUE; + con.out = CreateFileA ("CONOUT$", GENERIC_READ|GENERIC_WRITE, + FILE_SHARE_READ|FILE_SHARE_WRITE, + &sa, OPEN_EXISTING, 0, 0 ); + if (con.out == INVALID_HANDLE_VALUE) + log_fatal ("open(CONOUT$) failed: %s\n", w32_strerror (-1)); + + memset (&sa, 0, sizeof(sa)); + sa.nLength = sizeof(sa); + sa.bInheritHandle = TRUE; + con.in = CreateFileA ("CONIN$", GENERIC_READ|GENERIC_WRITE, + FILE_SHARE_READ|FILE_SHARE_WRITE, + &sa, OPEN_EXISTING, 0, 0 ); + if (con.in == INVALID_HANDLE_VALUE) + log_fatal ("open(CONIN$) failed: %s\n", w32_strerror (-1)); + } + SetConsoleMode (con.in, DEF_INPMODE); + SetConsoleMode (con.out, DEF_OUTMODE); + +#else /* Unix */ + ttyfp = batchmode? stderr : fopen (tty_get_ttyname (), "r+"); + if (!ttyfp) { - SECURITY_ATTRIBUTES sa; - - memset(&sa, 0, sizeof(sa)); - sa.nLength = sizeof(sa); - sa.bInheritHandle = TRUE; - con.out = CreateFileA( "CONOUT$", GENERIC_READ|GENERIC_WRITE, - FILE_SHARE_READ|FILE_SHARE_WRITE, - &sa, OPEN_EXISTING, 0, 0 ); - if( con.out == INVALID_HANDLE_VALUE ) - log_fatal("open(CONOUT$) failed: rc=%d", (int)GetLastError() ); - memset(&sa, 0, sizeof(sa)); - sa.nLength = sizeof(sa); - sa.bInheritHandle = TRUE; - con.in = CreateFileA( "CONIN$", GENERIC_READ|GENERIC_WRITE, - FILE_SHARE_READ|FILE_SHARE_WRITE, - &sa, OPEN_EXISTING, 0, 0 ); - if( con.in == INVALID_HANDLE_VALUE ) - log_fatal("open(CONIN$) failed: rc=%d", (int)GetLastError() ); + log_error ("cannot open '%s': %s\n", tty_get_ttyname (), strerror(errno)); + exit (2); } - SetConsoleMode(con.in, DEF_INPMODE ); - SetConsoleMode(con.out, DEF_OUTMODE ); - -#elif defined(__EMX__) - ttyfp = stdout; /* Fixme: replace by the real functions: see wklib */ - if (my_rl_init_stream) - my_rl_init_stream (ttyfp); -#elif defined (HAVE_W32CE_SYSTEM) - ttyfp = stderr; -#else - ttyfp = batchmode? stderr : fopen (tty_get_ttyname (), "r+"); - if( !ttyfp ) { - log_error("cannot open '%s': %s\n", tty_get_ttyname (), - strerror(errno) ); - exit(2); - } - if (my_rl_init_stream) - my_rl_init_stream (ttyfp); -#endif - + if (my_rl_init_stream) + my_rl_init_stream (ttyfp); +#endif /* Unix */ #ifdef HAVE_TCGETATTR - atexit( cleanup ); + atexit (cleanup); #endif - initialized = 1; + + initialized = 1; } int tty_batchmode( int onoff ) { - int old = batchmode; - if( onoff != -1 ) - batchmode = onoff; - return old; + int old = batchmode; + if (onoff != -1) + batchmode = onoff; + return old; } int tty_no_terminal(int onoff) { - int old = no_terminal; - no_terminal = onoff ? 1 : 0; - return old; + int old = no_terminal; + no_terminal = onoff ? 1 : 0; + return old; } + +#ifdef HAVE_W32_SYSTEM +/* Write the UTF-8 encoded STRING to the console. */ +static void +w32_write_console (const char *string) +{ + wchar_t *wstring; + DWORD n, nwritten; + + wstring = utf8_to_wchar (string); + if (!wstring) + log_fatal ("w32_write_console failed: %s", strerror (errno)); + n = wcslen (wstring); + + if (!WriteConsoleW (con.out, wstring, n, &nwritten, NULL)) + log_fatal ("WriteConsole failed: %s", w32_strerror (-1)); + if (n != nwritten) + log_fatal ("WriteConsole failed: %lu != %lu\n", + (unsigned long)n, (unsigned long)nwritten); + last_prompt_len += n; + xfree (wstring); +} +#endif /*HAVE_W32_SYSTEM*/ + + void -tty_printf( const char *fmt, ... ) +tty_printf (const char *fmt, ... ) { - va_list arg_ptr; + va_list arg_ptr; + + if (no_terminal) + return; - if (no_terminal) - return; + if (!initialized) + init_ttyfp (); - if( !initialized ) - init_ttyfp(); + va_start (arg_ptr, fmt); - va_start( arg_ptr, fmt ) ; -#ifdef USE_W32_CONSOLE - { - char *buf = NULL; - int n; - DWORD nwritten; - - n = vasprintf(&buf, fmt, arg_ptr); - if( !buf ) - log_bug("vasprintf() failed\n"); - - if( !WriteConsoleA( con.out, buf, n, &nwritten, NULL ) ) - log_fatal("WriteConsole failed: rc=%d", (int)GetLastError() ); - if( n != nwritten ) - log_fatal("WriteConsole failed: %d != %d\n", n, (int)nwritten ); - last_prompt_len += n; - xfree (buf); - } -#else - last_prompt_len += vfprintf(ttyfp,fmt,arg_ptr) ; - fflush(ttyfp); -#endif - va_end(arg_ptr); +#ifdef HAVE_W32_SYSTEM + { + char *buf = NULL; + + vasprintf(&buf, fmt, arg_ptr); + if (!buf) + log_bug ("vasprintf() failed\n"); + w32_write_console (buf); + xfree (buf); + } +#else /* Unix */ + last_prompt_len += vfprintf (ttyfp, fmt, arg_ptr) ; + fflush (ttyfp); +#endif /* Unix */ + va_end(arg_ptr); } @@ -284,27 +299,22 @@ tty_fprintf (estream_t fp, const char *fmt, ... ) init_ttyfp (); va_start (arg_ptr, fmt); -#ifdef USE_W32_CONSOLE + +#ifdef HAVE_W32_SYSTEM { char *buf = NULL; - int n; - DWORD nwritten; - n = vasprintf(&buf, fmt, arg_ptr); + vasprintf (&buf, fmt, arg_ptr); if (!buf) - log_bug("vasprintf() failed\n"); - - if (!WriteConsoleA( con.out, buf, n, &nwritten, NULL )) - log_fatal("WriteConsole failed: rc=%d", (int)GetLastError() ); - if (n != nwritten) - log_fatal("WriteConsole failed: %d != %d\n", n, (int)nwritten ); - last_prompt_len += n; + log_bug ("vasprintf() failed\n"); + w32_write_console (buf); xfree (buf); } -#else +#else /* Unix */ last_prompt_len += vfprintf(ttyfp,fmt,arg_ptr) ; fflush(ttyfp); -#endif +#endif /* Unix */ + va_end(arg_ptr); } @@ -326,7 +336,7 @@ do_print_string (estream_t fp, const byte *p, size_t n ) return; } -#ifdef USE_W32_CONSOLE +#ifdef HAVE_W32_SYSTEM /* Not so effective, change it if you want */ for (; n; n--, p++) { @@ -342,7 +352,7 @@ do_print_string (estream_t fp, const byte *p, size_t n ) else tty_printf ("%c", *p); } -#else +#else /* Unix */ for (; n; n--, p++) { if (iscntrl (*p)) @@ -358,209 +368,203 @@ do_print_string (estream_t fp, const byte *p, size_t n ) else putc (*p, ttyfp); } -#endif +#endif /* Unix */ } void tty_print_utf8_string2 (estream_t fp, const byte *p, size_t n, size_t max_n) { - size_t i; - char *buf; + size_t i; + char *buf; - if (no_terminal && !fp) - return; + if (no_terminal && !fp) + return; - /* we can handle plain ascii simpler, so check for it first */ - for(i=0; i < n; i++ ) { - if( p[i] & 0x80 ) - break; + /* We can handle plain ascii simpler, so check for it first. */ + for(i=0; i < n; i++ ) + { + if (p[i] & 0x80) + break; } - if( i < n ) { - buf = utf8_to_native( (const char *)p, n, 0 ); - if( max_n && (strlen( buf ) > max_n )) { - buf[max_n] = 0; - } - /*(utf8 conversion already does the control character quoting)*/ - tty_fprintf (fp, "%s", buf); - xfree (buf); + if (i < n) + { + buf = utf8_to_native ((const char *)p, n, 0); + if (max_n && (strlen (buf) > max_n)) + buf[max_n] = 0; + /* (utf8_to_native already did the control character quoting) */ + tty_fprintf (fp, "%s", buf); + xfree (buf); } - else { - if( max_n && (n > max_n) ) { - n = max_n; - } - do_print_string (fp, p, n ); + else + { + if (max_n && (n > max_n)) + n = max_n; + do_print_string (fp, p, n ); } } void -tty_print_utf8_string( const byte *p, size_t n ) +tty_print_utf8_string (const byte *p, size_t n) { tty_print_utf8_string2 (NULL, p, n, 0); } +/* Read a string from the tty using PROMPT. If HIDDEN is set the + * input is not echoed. */ static char * -do_get( const char *prompt, int hidden ) +do_get (const char *prompt, int hidden) { - char *buf; -#ifndef __riscos__ - byte cbuf[1]; + char *buf; + int n; /* Allocated size of BUF. */ + int i; /* Number of bytes in BUF. */ + int c; +#ifdef HAVE_W32_SYSTEM + char *utf8buf; + int errcount = 0; +#else + byte cbuf[1]; #endif - int c, n, i; - if( batchmode ) { - log_error("Sorry, we are in batchmode - can't get input\n"); - exit(2); + if (batchmode) + { + log_error (_("Sorry, we are in batchmode - can't get input\n")); + exit (2); } - if (no_terminal) { - log_error("Sorry, no terminal at all requested - can't get input\n"); - exit(2); + if (no_terminal) + { + log_error (_("Sorry, no terminal at all requested - can't get input\n")); + exit (2); } - if( !initialized ) - init_ttyfp(); + if( !initialized ) + init_ttyfp(); - last_prompt_len = 0; - tty_printf( "%s", prompt ); - buf = xmalloc((n=50)); - i = 0; - -#ifdef USE_W32_CONSOLE - if( hidden ) - SetConsoleMode(con.in, HID_INPMODE ); - - for(;;) { - DWORD nread; - - if( !ReadConsoleA( con.in, cbuf, 1, &nread, NULL ) ) - log_fatal("ReadConsole failed: rc=%d", (int)GetLastError() ); - if( !nread ) - continue; - if( *cbuf == '\n' ) - break; - - if( !hidden ) - last_prompt_len++; - c = *cbuf; - if( c == '\t' ) - c = ' '; - else if( c > 0xa0 ) - ; /* we don't allow 0xa0, as this is a protected blank which may - * confuse the user */ - else if( iscntrl(c) ) - continue; - if( !(i < n-1) ) { - n += 50; - buf = xrealloc (buf, n); - } - buf[i++] = c; - } + last_prompt_len = 0; + tty_printf( "%s", prompt ); + buf = xmalloc((n=50)); + i = 0; - if( hidden ) - SetConsoleMode(con.in, DEF_INPMODE ); - -#elif defined(__riscos__) || defined(HAVE_W32CE_SYSTEM) - do { -#ifdef HAVE_W32CE_SYSTEM - /* Using getchar is not a correct solution but for now it - doesn't matter because we have no real console at all. We - should rework this as soon as we have switched this entire - module to estream. */ - c = getchar(); -#else - c = riscos_getchar(); -#endif - if (c == 0xa || c == 0xd) { /* Return || Enter */ - c = (int) '\n'; - } else if (c == 0x8 || c == 0x7f) { /* Backspace || Delete */ - if (i>0) { - i--; - if (!hidden) { - last_prompt_len--; - fputc(8, ttyfp); - fputc(32, ttyfp); - fputc(8, ttyfp); - fflush(ttyfp); - } - } else { - fputc(7, ttyfp); - fflush(ttyfp); - } - continue; - } else if (c == (int) '\t') { /* Tab */ - c = ' '; - } else if (c > 0xa0) { - ; /* we don't allow 0xa0, as this is a protected blank which may - * confuse the user */ - } else if (iscntrl(c)) { - continue; +#ifdef HAVE_W32_SYSTEM + if (hidden) + SetConsoleMode(con.in, HID_INPMODE ); + + utf8buf = NULL; + for (;;) + { + DWORD nread; + wchar_t wbuf[2]; + const unsigned char *s; + + if (!ReadConsoleW (con.in, wbuf, 1, &nread, NULL)) + log_fatal ("ReadConsole failed: %s", w32_strerror (-1)); + if (!nread) + continue; + + wbuf[1] = 0; + xfree (utf8buf); + utf8buf = wchar_to_utf8 (wbuf); + if (!utf8buf) + { + log_info ("wchar_to_utf8 failed: %s\n", strerror (errno)); + if (++errcount > 10) + log_fatal (_("too many errors; giving up\n")); + continue; } - if(!(i < n-1)) { - n += 50; - buf = xrealloc (buf, n); + if (*utf8buf == '\n') + { + if (utf8buf[1]) + { + log_info ("ReadConsole returned more than requested" + " (0x0a,0x%02x)\n", utf8buf[1]); + if (++errcount > 10) + log_fatal (_("too many errors; giving up\n")); + } + break; } - buf[i++] = c; - if (!hidden) { - last_prompt_len++; - fputc(c, ttyfp); - fflush(ttyfp); + if (!hidden) + last_prompt_len++; + + for (s=utf8buf; *s; s++) + { + c = *s; + if (c == '\t') + c = ' '; /* Map tab to a space. */ + else if ((c >= 0 && c <= 0x1f) || c == 0x7f) + continue; /* Remove control characters. */ + if (!(i < n-1)) + { + n += 50; + buf = xrealloc (buf, n); + } + buf[i++] = c; } - } while (c != '\n'); - i = (i>0) ? i-1 : 0; -#else /* Other systems. */ - if( hidden ) { + } + xfree (utf8buf); + + if (hidden) + SetConsoleMode(con.in, DEF_INPMODE ); + +#else /* Unix */ + + if (hidden) + { #ifdef HAVE_TCGETATTR - struct termios term; - - if( tcgetattr(fileno(ttyfp), &termsave) ) - log_fatal("tcgetattr() failed: %s\n", strerror(errno) ); - restore_termios = 1; - term = termsave; - term.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL); - if( tcsetattr( fileno(ttyfp), TCSAFLUSH, &term ) ) - log_fatal("tcsetattr() failed: %s\n", strerror(errno) ); -#endif + struct termios term; + + if (tcgetattr(fileno(ttyfp), &termsave)) + log_fatal ("tcgetattr() failed: %s\n", strerror(errno)); + restore_termios = 1; + term = termsave; + term.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL); + if (tcsetattr( fileno(ttyfp), TCSAFLUSH, &term ) ) + log_fatal("tcsetattr() failed: %s\n", strerror(errno)); +#endif /*HAVE_TCGETATTR*/ } - /* fixme: How can we avoid that the \n is echoed w/o disabling - * canonical mode - w/o this kill_prompt can't work */ - while( read(fileno(ttyfp), cbuf, 1) == 1 && *cbuf != '\n' ) { - if( !hidden ) - last_prompt_len++; - c = *cbuf; - if( c == CONTROL_D ) - log_info("control d found\n"); - if( c == '\t' ) - c = ' '; - else if( c > 0xa0 ) - ; /* we don't allow 0xa0, as this is a protected blank which may - * confuse the user */ - else if( iscntrl(c) ) - continue; - if( !(i < n-1) ) { - n += 50; - buf = xrealloc (buf, n ); - } - buf[i++] = c; + /* fixme: How can we avoid that the \n is echoed w/o disabling + * canonical mode - w/o this kill_prompt can't work */ + while (read(fileno(ttyfp), cbuf, 1) == 1 && *cbuf != '\n') + { + if (!hidden) + last_prompt_len++; + c = *cbuf; + if (c == CONTROL_D) + log_info (_("Control-D detected\n")); + + if (c == '\t') /* Map tab to a space. */ + c = ' '; + else if ( (c >= 0 && c <= 0x1f) || c == 0x7f) + continue; /* Skip all other ASCII control characters. */ + if (!(i < n-1)) + { + n += 50; + buf = xrealloc (buf, n); + } + buf[i++] = c; } - if( *cbuf != '\n' ) { - buf[0] = CONTROL_D; - i = 1; + + if (*cbuf != '\n') + { + buf[0] = CONTROL_D; + i = 1; } - if( hidden ) { + if (hidden) + { #ifdef HAVE_TCGETATTR - if( tcsetattr(fileno(ttyfp), TCSAFLUSH, &termsave) ) - log_error("tcsetattr() failed: %s\n", strerror(errno) ); - restore_termios = 0; -#endif + if (tcsetattr (fileno(ttyfp), TCSAFLUSH, &termsave)) + log_error ("tcsetattr() failed: %s\n", strerror(errno)); + restore_termios = 0; +#endif /*HAVE_TCGETATTR*/ } -#endif /* end unix version */ - buf[i] = 0; - return buf; +#endif /* Unix */ + + buf[i] = 0; + return buf; } @@ -602,8 +606,9 @@ tty_get( const char *prompt ) return do_get ( prompt, 0 ); } + /* Variable argument version of tty_get. The prompt is actually a - format string with arguments. */ + * format string with arguments. */ char * tty_getf (const char *promptfmt, ... ) { @@ -621,52 +626,54 @@ tty_getf (const char *promptfmt, ... ) } - char * tty_get_hidden( const char *prompt ) { - return do_get( prompt, 1 ); + return do_get (prompt, 1); } void -tty_kill_prompt() +tty_kill_prompt (void) { - if ( no_terminal ) - return; + if (no_terminal) + return; - if( !initialized ) - init_ttyfp(); + if (!initialized) + init_ttyfp (); - if( batchmode ) - last_prompt_len = 0; - if( !last_prompt_len ) - return; -#ifdef USE_W32_CONSOLE - tty_printf("\r%*s\r", last_prompt_len, ""); -#else - { - int i; - putc('\r', ttyfp); - for(i=0; i < last_prompt_len; i ++ ) - putc(' ', ttyfp); - putc('\r', ttyfp); - fflush(ttyfp); - } -#endif + if (batchmode) last_prompt_len = 0; + if (!last_prompt_len) + return; +#ifdef HAVE_W32_SYSTEM + tty_printf ("\r%*s\r", last_prompt_len, ""); +#else /* Unix */ + { + int i; + putc ('\r', ttyfp); + for (i=0; i < last_prompt_len; i ++ ) + putc (' ', ttyfp); + putc ('\r', ttyfp); + fflush (ttyfp); + } +#endif /* Unix */ + last_prompt_len = 0; } int tty_get_answer_is_yes( const char *prompt ) { - int yes; - char *p = tty_get( prompt ); - tty_kill_prompt(); - yes = answer_is_yes(p); - xfree(p); - return yes; + int yes; + char *p; + + p = tty_get (prompt); + tty_kill_prompt (); + yes = answer_is_yes (p); + xfree (p); + + return yes; } @@ -712,7 +719,7 @@ tty_disable_completion (void) my_rl_inhibit_completion (1); } -#endif +#endif /* HAVE_LIBREADLINE */ void tty_cleanup_after_signal (void) diff --git a/common/util.h b/common/util.h index 75cdee0..ed0355f 100644 --- a/common/util.h +++ b/common/util.h @@ -183,6 +183,12 @@ gpg_error_t make_canon_sexp_pad (gcry_sexp_t sexp, int secure, gpg_error_t keygrip_from_canon_sexp (const unsigned char *key, size_t keylen, unsigned char *grip); int cmp_simple_canon_sexp (const unsigned char *a, const unsigned char *b); +int cmp_canon_sexp (const unsigned char *a, size_t alen, + const unsigned char *b, size_t blen, + int (*tcmp)(void *ctx, int depth, + const unsigned char *aval, size_t avallen, + const unsigned char *bval, size_t bvallen), + void *tcmpctx); unsigned char *make_simple_sexp_from_hexstr (const char *line, size_t *nscanned); int hash_algo_from_sigval (const unsigned char *sigval); @@ -195,6 +201,14 @@ gpg_error_t get_rsa_pk_from_canon_sexp (const unsigned char *keydata, size_t *r_nlen, unsigned char const **r_e, size_t *r_elen); +gpg_error_t get_ecc_q_from_canon_sexp (const unsigned char *keydata, + size_t keydatalen, + unsigned char const **r_q, + size_t *r_qlen); +gpg_error_t uncompress_ecc_q_in_canon_sexp (const unsigned char *keydata, + size_t keydatalen, + unsigned char **r_newkeydata, + size_t *r_newkeydatalen); int get_pk_algo_from_key (gcry_sexp_t key); int get_pk_algo_from_canon_sexp (const unsigned char *keydata, @@ -202,6 +216,7 @@ int get_pk_algo_from_canon_sexp (const unsigned char *keydata, char *pubkey_algo_string (gcry_sexp_t s_pkey, enum gcry_pk_algos *r_algoid); const char *pubkey_algo_to_string (int algo); const char *hash_algo_to_string (int algo); +const char *cipher_mode_to_string (int mode); /*-- convert.c --*/ int hex2bin (const char *string, void *buffer, size_t length); @@ -230,7 +245,8 @@ int openpgp_oidbuf_is_ed25519 (const void *buf, size_t len); int openpgp_oid_is_ed25519 (gcry_mpi_t a); int openpgp_oidbuf_is_cv25519 (const void *buf, size_t len); int openpgp_oid_is_cv25519 (gcry_mpi_t a); -const char *openpgp_curve_to_oid (const char *name, unsigned int *r_nbits); +const char *openpgp_curve_to_oid (const char *name, + unsigned int *r_nbits, int *r_algo); const char *openpgp_oid_to_curve (const char *oid, int canon); const char *openpgp_enum_curves (int *idxp); const char *openpgp_is_curve_supported (const char *name, @@ -303,6 +319,8 @@ char *xasprintf (const char *fmt, ...) GPGRT_ATTR_PRINTF(1,2); /* This is now an alias to estream_asprintf. */ char *xtryasprintf (const char *fmt, ...) GPGRT_ATTR_PRINTF(1,2); +void *xtryreallocarray (void *a, size_t oldnmemb, size_t nmemb, size_t size); + /* Replacement for gcry_cipher_algo_name. */ const char *gnupg_cipher_algo_name (int algo); diff --git a/common/w32-cmdline.c b/common/w32-cmdline.c new file mode 100644 index 0000000..85d5752 --- /dev/null +++ b/common/w32-cmdline.c @@ -0,0 +1,450 @@ +/* w32-cmdline.c - Command line helper functions needed in Windows + * Copyright (C) 2021 g10 Code GmbH + * + * This file is part of GnuPG. + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of either + * + * - the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * or + * + * - 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. + * + * or both in parallel, as here. + * + * This file 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses/>. + */ + +#include <config.h> + +#ifdef HAVE_W32_SYSTEM +# define WIN32_LEAN_AND_MEAN +# include <windows.h> +#endif /*!HAVE_W32_SYSTEM*/ + +#include "util.h" +#include "w32help.h" + + +/* Helper object for add_arg. */ +struct add_arg_s +{ + char **argv; /* Calloced array. */ + int argc; /* Number of items in argc. */ + int size; /* Allocated size of argv. */ +}; + + +/* Add STRING to the argv of PARM. Returns 0 on success; on error + * sets ERRNO and returns -1. */ +static int +add_arg (struct add_arg_s *parm, const char *string) +{ + if (parm->argc == parm->size) + { + char **newargv; + int newsize; + + if (parm->size < 256) + newsize = ((parm->size + 31) / 32 + 1) * 32; + else + newsize = ((parm->size + 255) / 256 + 1) * 256; + /* We allocate one more item for the trailing NULL. */ + newargv = xtryreallocarray (parm->argv, parm->size, newsize+1, + sizeof *newargv); + if (!newargv) + return -1; + parm->argv = newargv; + parm->size = newsize; + } + parm->argv[parm->argc] = xtrystrdup (string); + if (!parm->argv[parm->argc]) + return -1; + parm->argc++; + return 0; +} + + +/* Glob PATTERN and add to the argv of PARM. Returns 0 on success; on + * error sets ERRNO and returns -1. */ +static int +glob_arg (struct add_arg_s *parm, const char *pattern) +{ + int rc; + const char *s; + +#ifdef HAVE_W32_SYSTEM + HANDLE hd; + WIN32_FIND_DATAW dir; + uintptr_t pos; /* Offset to the last slash in pattern/buffer or 0. */ + char *buffer, *p; + int any = 0; + + s = strpbrk (pattern, "*?"); + if (!s) + { + /* Called without wildcards. */ + return add_arg (parm, pattern); + } + for (; s != pattern && *s != '/' && *s != '\\'; s--) + ; + pos = s - pattern; + if (*s == '/' || *s == L'\\') + pos++; + + { + wchar_t *wpattern; + + wpattern = utf8_to_wchar (pattern); + if (!wpattern) + return -1; + + hd = FindFirstFileW (wpattern, &dir); + xfree (wpattern); + } + if (hd == INVALID_HANDLE_VALUE) + return add_arg (parm, pattern); + + /* We allocate enough space to hold all kind of UTF-8 strings. */ + buffer = xtrymalloc (strlen (pattern) + MAX_PATH*6 + 1); + if (!buffer) + { + FindClose (hd); + return -1; + } + mem2str (buffer, pattern, pos+1); + for (p=buffer; *p; p++) + if (*p == '\\') + *p = '/'; + + do + { + if (!(dir.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) + { + char *name; + + name = wchar_to_utf8 (dir.cFileName); + if (!name) + rc = -1; + else + { + mem2str (buffer + pos, name, MAX_PATH*6); + xfree (name); + rc = add_arg (parm, buffer); + } + if (rc) + { + FindClose (hd); + xfree (buffer); + return rc; + } + any = 1; + } + } + while (FindNextFileW (hd, &dir)); + + FindClose (hd); + xfree (buffer); + + rc = any? 0 : add_arg (parm, pattern); + +#else /* Unix */ + + /* We use some dummy code here because this is only used in the Unix + * test suite. */ + s = strpbrk (pattern, "*?"); + if (!s) + { + /* Called without wildcards. */ + return add_arg (parm, pattern); + } + + if (strchr (pattern, '?')) + rc = add_arg (parm, "[? follows]"); + else if (strchr (pattern, '*')) + rc = add_arg (parm, "[* follows]"); + else + rc = add_arg (parm, "[no glob!]"); /* Should not happen. */ + if (!rc) + rc = add_arg (parm, pattern); + +#endif /* Unix */ + + return rc; +} + + +/* Return the number of backslashes. */ +static unsigned int +count_backslashes (const char *s) +{ + unsigned int count = 0; + + for ( ;*s == '\\'; s++) + count++; + return count; +} + + +static void +strip_one_arg (char *string, int endquote) +{ + char *s, *d; + unsigned int n, i; + + for (s=d=string; *s; s++) + if (*s == '\\') + { + n = count_backslashes (s); + if (s[n] == '"') + { + for (i=0; i < n/2; i++) + *d++ = '\\'; + if ((n&1)) /* Odd number of backslashes. */ + *d++ = '"'; /* Print the quote. */ + } + else if (!s[n] && endquote) + { + for (i=0; i < n/2; i++) + *d++ = '\\'; + s--; + } + else /* Print all backslashes. */ + { + for (i=0; i < n; i++) + *d++ = '\\'; + n--; /* Adjust for the increment in the for. */ + } + s += n; + } + else if (*s == '"' && s[1]) + *d++ = *++s; + else + *d++ = *s; + *d = 0; +} + + +/* Helper for parse_w32_commandline. If ARGV and ARGVFLAGS are not + * NULL, ARGVFLAGS is expected to be allocated at the same size of + * ARGV and zeroed; on return 1 is stored for all arguments which are + * quoted (args like (foo"bar"baz") also count as quoted. */ +static int +parse_cmdstring (char *string, char **argv, unsigned char *argvflags) +{ + int argc = 0; + int inquote = 0; + char *p0, *p; + unsigned int n; + + p0 = string; + for (p=string; *p; p++) + { + if (inquote) + { + if (*p == '\\' && p[1] == '"') + p++; + else if (*p == '\\' && p[1] == '\\') + p++; + else if (*p == '"') + { + if (p[1] == ' ' || p[1] == '\t' || !p[1]) + { + if (argv) + { + *p = 0; + strip_one_arg (p0, 1); + argv[argc] = p0; + if (argvflags) + argvflags[argc] = 1; + } + argc++; + p0 = NULL; + } + inquote = 0; + } + } + else if (*p == '\\' && (n=count_backslashes (p))) + { + if (!p0) /* First non-WS; set start. */ + p0 = p; + if (p[n] == '"') + { + if (!(n&1)) /* Even number. */ + inquote = 1; + p++; + } + p += n; + } + else if (*p == '"') + { + inquote = 1; + if (!p0 || p == string) /* First non-WS or first char; set start. */ + p0 = p + 1; + } + else if (*p == ' ' || *p == '\t') + { + if (p0) /* We are in an argument and reached WS. */ + { + if (argv) + { + *p = 0; + strip_one_arg (p0, inquote); + argv[argc] = p0; + if (argvflags && inquote) + argvflags[argc] = 1; + } + argc++; + p0 = NULL; + } + } + else if (!p0) /* First non-WS; set start. */ + p0 = p; + } + + if (inquote || p0) + { + /* Closing quote missing (we accept this as argument anyway) or + * an open argument. */ + if (argv) + { + *p = 0; + strip_one_arg (p0, inquote); + argv[argc] = p0; + if (argvflags && inquote) + argvflags[argc] = 1; + } + argc++; + } + + return argc; +} + +/* This is a Windows command line parser, returning an array with + * strings and its count. The argument CMDLINE is expected to be + * utf-8 encoded and may be modified after returning from this + * function. The returned array points into CMDLINE, so this should + * not be freed. If GLOBING is set to true globing is done for all + * items. Returns NULL on error. The number of items in the array is + * returned at R_ARGC. If R_ITEMSALLOCED is NOT NULL, it's value is + * set to true if the items at R_ALLOC are allocated and not point + * into to CMDLINE. */ +char ** +w32_parse_commandline (char *cmdline, int globing, int *r_argc, + int *r_itemsalloced) +{ + int argc, i; + char **argv; + char *argvflags; + + if (r_itemsalloced) + *r_itemsalloced = 0; + + argc = parse_cmdstring (cmdline, NULL, NULL); + if (!argc) + { + log_error ("%s failed: %s\n", __func__, "internal error"); + return NULL; /* Ooops. */ + } + argv = xtrycalloc (argc+1, sizeof *argv); + if (!argv) + { + log_error ("%s failed: %s\n", __func__, + gpg_strerror (gpg_error_from_syserror ())); + return NULL; /* Ooops. */ + } + if (globing) + { + argvflags = xtrycalloc (argc+1, sizeof *argvflags); + if (!argvflags) + { + log_error ("%s failed: %s\n", __func__, + gpg_strerror (gpg_error_from_syserror ())); + xfree (argv); + return NULL; /* Ooops. */ + } + } + else + argvflags = NULL; + + i = parse_cmdstring (cmdline, argv, argvflags); + if (argc != i) + { + log_error ("%s failed (argc=%d i=%d)\n", __func__, argc, i); + xfree (argv); + xfree (argvflags); + return NULL; /* Ooops. */ + } + + if (globing) + { + for (i=0; i < argc; i++) + if (argvflags[i] != 1 && strpbrk (argv[i], "*?")) + break; + if (i < argc) + { + /* Indeed some unquoted arguments contain wildcards. We + * need to do the globing and thus a dynamically re-allocate + * the argv array and strdup all items. */ + struct add_arg_s parm; + int rc; + + if (argc < 32) + parm.size = ((argc + 31) / 32 + 1) * 32; + else + parm.size = ((argc + 255) / 256 + 1) * 256; + parm.argc = 0; + /* We allocate one more item for the trailing NULL. */ + parm.argv = xtryreallocarray (NULL, 0, parm.size + 1, + sizeof *parm.argv); + if (!parm.argv) + { + log_error ("%s: error allocating array: %s\n", __func__, + gpg_strerror (gpg_error_from_syserror ())); + xfree (argv); + xfree (argvflags); + return NULL; /* Ooops. */ + } + rc = 0; + for (i=0; i < argc; i++) + { + if (argvflags[i] != 1) + rc = glob_arg (&parm, argv[i]); + else + rc = add_arg (&parm, argv[i]); + if (rc) + { + log_error ("%s: error adding or blobing: %s\n", __func__, + gpg_strerror (gpg_error_from_syserror ())); + for (i=0; i < parm.argc; i++) + xfree (parm.argv[i]); + xfree (parm.argv); + xfree (argv); + xfree (argvflags); + return NULL; /* Ooops. */ + } + } + xfree (argv); + argv = parm.argv; + argc = parm.argc; + if (r_itemsalloced) + *r_itemsalloced = 1; + } + } + + xfree (argvflags); + *r_argc = argc; + return argv; +} diff --git a/common/w32help.h b/common/w32help.h index 177efbc..edb51b8 100644 --- a/common/w32help.h +++ b/common/w32help.h @@ -30,6 +30,15 @@ #ifndef GNUPG_COMMON_W32HELP_H #define GNUPG_COMMON_W32HELP_H + +/*-- w32-cmdline.c --*/ + +/* This module is also part of the Unix tests. */ +char **w32_parse_commandline (char *cmdline, int globing, int *r_argv, + int *r_itemsalloced); + + + #ifdef HAVE_W32_SYSTEM /*-- w32-reg.c --*/ diff --git a/common/xasprintf.c b/common/xasprintf.c index 00ff66a..7e37e5b 100644 --- a/common/xasprintf.c +++ b/common/xasprintf.c @@ -1,5 +1,6 @@ /* xasprintf.c * Copyright (C) 2003, 2005 Free Software Foundation, Inc. + * Copyright (C) 2020 g10 Code GmbH * * This file is part of GnuPG. * @@ -68,3 +69,55 @@ xtryasprintf (const char *fmt, ...) return NULL; return buf; } + + +/* This is safe version of realloc useful for reallocing a calloced + * array. There are two ways to call it: The first example + * reallocates the array A to N elements each of SIZE but does not + * clear the newly allocated elements: + * + * p = xtryreallocarray (a, n, n, nsize); + * + * Note that when NOLD is larger than N no cleaning is needed anyway. + * The second example reallocates an array of size NOLD to N elements + * each of SIZE but clear the newly allocated elements: + * + * p = xtryreallocarray (a, nold, n, nsize); + * + * Note that xtryreallocarray (NULL, 0, n, nsize) is equivalent to + * xtrycalloc (n, nsize). + * + * The same function under the name gpgrt_reallocarray exists in + * libgpg-error but only since version 1.38 and thus we use a copy + * here. + */ +void * +xtryreallocarray (void *a, size_t oldnmemb, size_t nmemb, size_t size) +{ + size_t oldbytes, bytes; + char *p; + + bytes = nmemb * size; /* size_t is unsigned so the behavior on overflow + * is defined. */ + if (size && bytes / size != nmemb) + { + gpg_err_set_errno (ENOMEM); + return NULL; + } + + p = xtryrealloc (a, bytes); + if (p && oldnmemb < nmemb) + { + /* OLDNMEMBS is lower than NMEMB thus the user asked for a + calloc. Clear all newly allocated members. */ + oldbytes = oldnmemb * size; + if (size && oldbytes / size != oldnmemb) + { + xfree (p); + gpg_err_set_errno (ENOMEM); + return NULL; + } + memset (p + oldbytes, 0, bytes - oldbytes); + } + return p; +} |