summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
Diffstat (limited to 'common')
-rw-r--r--common/Makefile.am9
-rw-r--r--common/Makefile.in167
-rw-r--r--common/compliance.c135
-rw-r--r--common/compliance.h1
-rw-r--r--common/dotlock.c22
-rw-r--r--common/dotlock.h1
-rw-r--r--common/exechelp-posix.c7
-rw-r--r--common/exechelp-w32.c188
-rw-r--r--common/init.c94
-rw-r--r--common/keyserver.h73
-rw-r--r--common/name-value.c1
-rw-r--r--common/openpgp-fpr.c283
-rw-r--r--common/openpgp-oid.c12
-rw-r--r--common/openpgpdefs.h22
-rw-r--r--common/sexputil.c490
-rw-r--r--common/t-sexputil.c304
-rw-r--r--common/t-w32-cmdline.c250
-rw-r--r--common/tlv.c4
-rw-r--r--common/tlv.h2
-rw-r--r--common/ttyio.c631
-rw-r--r--common/util.h20
-rw-r--r--common/w32-cmdline.c450
-rw-r--r--common/w32help.h9
-rw-r--r--common/xasprintf.c53
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;
+}