diff options
Diffstat (limited to '')
-rw-r--r-- | tools/Makefile.am | 41 | ||||
-rw-r--r-- | tools/Makefile.in | 59 | ||||
-rw-r--r-- | tools/gpg-check-pattern.c | 2 | ||||
-rw-r--r-- | tools/gpg-check-pattern.w32-manifest.in | 7 | ||||
-rw-r--r-- | tools/gpg-connect-agent.w32-manifest.in | 7 | ||||
-rw-r--r-- | tools/gpg-wks-client.c | 133 | ||||
-rw-r--r-- | tools/gpg-wks-client.w32-manifest.in | 7 | ||||
-rw-r--r-- | tools/gpg-wks.h | 8 | ||||
-rw-r--r-- | tools/gpgconf.c | 303 | ||||
-rw-r--r-- | tools/gpgconf.w32-manifest.in | 7 | ||||
-rw-r--r-- | tools/gpgtar-create.c | 128 | ||||
-rw-r--r-- | tools/gpgtar-extract.c | 69 | ||||
-rw-r--r-- | tools/gpgtar-list.c | 6 | ||||
-rw-r--r-- | tools/gpgtar.c | 76 | ||||
-rw-r--r-- | tools/gpgtar.h | 10 | ||||
-rw-r--r-- | tools/gpgtar.w32-manifest.in | 7 | ||||
-rw-r--r-- | tools/wks-util.c | 226 |
17 files changed, 854 insertions, 242 deletions
diff --git a/tools/Makefile.am b/tools/Makefile.am index acc649c..262876f 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -32,23 +32,20 @@ AM_CPPFLAGS = include $(top_srcdir)/am/cmacros.am if HAVE_W32_SYSTEM -gpgconf_robjs = $(resource_objs) gpgconf-w32info.o -gpgtar_robjs = $(resource_objs) gpgtar-w32info.o -gpg_connect_agent_robjs = $(resource_objs) gpg-connect-agent-w32info.o -gpg_check_pattern_robjs = $(resource_objs) gpg-check-pattern-w32info.o -gpg_wks_client_robjs = $(resource_objs) gpg-wks-client-w32info.o - -gpgconf-w32info.o: gpgconf.w32-manifest -gpgtar-w32info.o: gpgtar.w32-manifest -gpg-connect-agent-w32info.o: gpg-connect-agent.w32-manifest -gpg-check-pattern-w32info.o: gpg-check-pattern.w32-manifest -gpg-wks-client-w32info.o: gpg-wks-client.w32-manifest -else -gpg_connect_agent_robjs = -gpgconf_robjs = -gpg_check_pattern_robjs = -gpgtar_robjs = -gpg_wks_client_robjs = +gpgconf_rc_objs = $(resource_objs) gpgconf-w32info.o +gpgtar_rc_objs = $(resource_objs) gpgtar-w32info.o +gpg_connect_agent_rc_objs = $(resource_objs) gpg-connect-agent-w32info.o +gpg_check_pattern_rc_objs = $(resource_objs) gpg-check-pattern-w32info.o +gpg_wks_client_rc_objs = $(resource_objs) gpg-wks-client-w32info.o + +gpg-connect-agent-w32info.o : gpg-connect-agent.w32-manifest \ + ../common/w32info-rc.h +gpgconf-w32info.o : gpgconf.w32-manifest ../common/w32info-rc.h +gpgtar-w32info.o : gpgtar.w32-manifest ../common/w32info-rc.h +gpg-check-pattern-w32info.o : gpg-check-pattern.w32-manifest \ + ../common/w32info-rc.h +gpg-wks-client-w32info.o : gpg-wks-client.w32-manifest \ + ../common/w32info-rc.h endif AM_CFLAGS = $(LIBGCRYPT_CFLAGS) $(GPG_ERROR_CFLAGS) $(LIBASSUAN_CFLAGS) @@ -123,7 +120,7 @@ gpgconf_SOURCES = gpgconf.c gpgconf.h gpgconf-comp.c gpgconf_LDADD = $(maybe_commonpth_libs) $(opt_libassuan_libs) \ $(LIBINTL) $(LIBGCRYPT_LIBS) $(GPG_ERROR_LIBS) $(NETLIBS) \ $(LIBICONV) $(W32SOCKLIBS) \ - $(gpgconf_robjs) + $(gpgconf_rc_objs) gpgconf_LDFLAGS = $(extra_bin_ldflags) gpgconf_w32_SOURCES = $(gpgconf_SOURCES) @@ -141,14 +138,14 @@ gpg_connect_agent_LDADD = ../common/libgpgrl.a $(common_libs) \ $(LIBASSUAN_LIBS) $(LIBGCRYPT_LIBS) \ $(GPG_ERROR_LIBS) \ $(LIBREADLINE) $(LIBINTL) $(NETLIBS) $(LIBICONV) \ - $(gpg_connect_agent_robjs) + $(gpg_connect_agent_rc_objs) gpg_check_pattern_SOURCES = gpg-check-pattern.c gpg_check_pattern_CFLAGS = $(LIBGCRYPT_CFLAGS) $(GPG_ERROR_CFLAGS) $(INCICONV) gpg_check_pattern_LDADD = $(common_libs) $(regexp_libs) $(LIBGCRYPT_LIBS) \ $(GPG_ERROR_LIBS) \ $(LIBINTL) $(NETLIBS) $(LIBICONV) $(W32SOCKLIBS) \ - $(LIBICONV) $(gpg_check_pattern_robjs) + $(LIBICONV) $(gpg_check_pattern_rc_objs) gpgtar_SOURCES = \ gpgtar.c gpgtar.h \ @@ -158,7 +155,7 @@ gpgtar_SOURCES = \ gpgtar_CFLAGS = $(LIBGCRYPT_CFLAGS) $(GPG_ERROR_CFLAGS) gpgtar_LDADD = $(libcommon) $(LIBGCRYPT_LIBS) $(GPG_ERROR_LIBS) \ $(LIBINTL) $(NETLIBS) $(LIBICONV) $(W32SOCKLIBS) \ - $(gpgtar_robjs) + $(gpgtar_rc_objs) gpg_wks_server_SOURCES = \ gpg-wks-server.c \ @@ -190,7 +187,7 @@ gpg_wks_client_CFLAGS = $(LIBASSUAN_CFLAGS) $(LIBGCRYPT_CFLAGS) \ gpg_wks_client_LDADD = $(libcommon) \ $(LIBASSUAN_LIBS) $(LIBGCRYPT_LIBS) $(GPG_ERROR_LIBS) \ $(LIBINTL) $(LIBICONV) $(NETLIBS) \ - $(gpg_wks_client_robjs) + $(gpg_wks_client_rc_objs) # Make sure that all libs are build before we use them. This is diff --git a/tools/Makefile.in b/tools/Makefile.in index e1b7da9..e1b3082 100644 --- a/tools/Makefile.in +++ b/tools/Makefile.in @@ -157,17 +157,16 @@ ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/autobuild.m4 \ $(top_srcdir)/m4/codeset.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/gpg-error.m4 $(top_srcdir)/m4/iconv.m4 \ - $(top_srcdir)/m4/isc-posix.m4 $(top_srcdir)/m4/ksba.m4 \ - $(top_srcdir)/m4/lcmessage.m4 $(top_srcdir)/m4/ldap.m4 \ - $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ - $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libassuan.m4 \ - $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/nls.m4 \ - $(top_srcdir)/m4/npth.m4 $(top_srcdir)/m4/ntbtls.m4 \ - $(top_srcdir)/m4/pkg.m4 $(top_srcdir)/m4/po.m4 \ - $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/readline.m4 \ - $(top_srcdir)/m4/socklen.m4 $(top_srcdir)/m4/sys_socket_h.m4 \ - $(top_srcdir)/m4/tar-ustar.m4 $(top_srcdir)/acinclude.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/m4/ksba.m4 $(top_srcdir)/m4/lcmessage.m4 \ + $(top_srcdir)/m4/ldap.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libassuan.m4 $(top_srcdir)/m4/libgcrypt.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/npth.m4 \ + $(top_srcdir)/m4/ntbtls.m4 $(top_srcdir)/m4/pkg.m4 \ + $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ + $(top_srcdir)/m4/readline.m4 $(top_srcdir)/m4/socklen.m4 \ + $(top_srcdir)/m4/sys_socket_h.m4 $(top_srcdir)/m4/tar-ustar.m4 \ + $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) @@ -641,16 +640,11 @@ libcommon = ../common/libcommon.a libcommonpth = ../common/libcommonpth.a libcommontls = ../common/libcommontls.a libcommontlsnpth = ../common/libcommontlsnpth.a -@HAVE_W32_SYSTEM_FALSE@gpgconf_robjs = -@HAVE_W32_SYSTEM_TRUE@gpgconf_robjs = $(resource_objs) gpgconf-w32info.o -@HAVE_W32_SYSTEM_FALSE@gpgtar_robjs = -@HAVE_W32_SYSTEM_TRUE@gpgtar_robjs = $(resource_objs) gpgtar-w32info.o -@HAVE_W32_SYSTEM_FALSE@gpg_connect_agent_robjs = -@HAVE_W32_SYSTEM_TRUE@gpg_connect_agent_robjs = $(resource_objs) gpg-connect-agent-w32info.o -@HAVE_W32_SYSTEM_FALSE@gpg_check_pattern_robjs = -@HAVE_W32_SYSTEM_TRUE@gpg_check_pattern_robjs = $(resource_objs) gpg-check-pattern-w32info.o -@HAVE_W32_SYSTEM_FALSE@gpg_wks_client_robjs = -@HAVE_W32_SYSTEM_TRUE@gpg_wks_client_robjs = $(resource_objs) gpg-wks-client-w32info.o +@HAVE_W32_SYSTEM_TRUE@gpgconf_rc_objs = $(resource_objs) gpgconf-w32info.o +@HAVE_W32_SYSTEM_TRUE@gpgtar_rc_objs = $(resource_objs) gpgtar-w32info.o +@HAVE_W32_SYSTEM_TRUE@gpg_connect_agent_rc_objs = $(resource_objs) gpg-connect-agent-w32info.o +@HAVE_W32_SYSTEM_TRUE@gpg_check_pattern_rc_objs = $(resource_objs) gpg-check-pattern-w32info.o +@HAVE_W32_SYSTEM_TRUE@gpg_wks_client_rc_objs = $(resource_objs) gpg-wks-client-w32info.o AM_CFLAGS = $(LIBGCRYPT_CFLAGS) $(GPG_ERROR_CFLAGS) $(LIBASSUAN_CFLAGS) sbin_SCRIPTS = addgnupghome applygnupgdefaults @@ -679,7 +673,7 @@ gpgconf_SOURCES = gpgconf.c gpgconf.h gpgconf-comp.c gpgconf_LDADD = $(maybe_commonpth_libs) $(opt_libassuan_libs) \ $(LIBINTL) $(LIBGCRYPT_LIBS) $(GPG_ERROR_LIBS) $(NETLIBS) \ $(LIBICONV) $(W32SOCKLIBS) \ - $(gpgconf_robjs) + $(gpgconf_rc_objs) gpgconf_LDFLAGS = $(extra_bin_ldflags) gpgconf_w32_SOURCES = $(gpgconf_SOURCES) @@ -694,14 +688,14 @@ gpg_connect_agent_LDADD = ../common/libgpgrl.a $(common_libs) \ $(LIBASSUAN_LIBS) $(LIBGCRYPT_LIBS) \ $(GPG_ERROR_LIBS) \ $(LIBREADLINE) $(LIBINTL) $(NETLIBS) $(LIBICONV) \ - $(gpg_connect_agent_robjs) + $(gpg_connect_agent_rc_objs) gpg_check_pattern_SOURCES = gpg-check-pattern.c gpg_check_pattern_CFLAGS = $(LIBGCRYPT_CFLAGS) $(GPG_ERROR_CFLAGS) $(INCICONV) gpg_check_pattern_LDADD = $(common_libs) $(regexp_libs) $(LIBGCRYPT_LIBS) \ $(GPG_ERROR_LIBS) \ $(LIBINTL) $(NETLIBS) $(LIBICONV) $(W32SOCKLIBS) \ - $(LIBICONV) $(gpg_check_pattern_robjs) + $(LIBICONV) $(gpg_check_pattern_rc_objs) gpgtar_SOURCES = \ gpgtar.c gpgtar.h \ @@ -712,7 +706,7 @@ gpgtar_SOURCES = \ gpgtar_CFLAGS = $(LIBGCRYPT_CFLAGS) $(GPG_ERROR_CFLAGS) gpgtar_LDADD = $(libcommon) $(LIBGCRYPT_LIBS) $(GPG_ERROR_LIBS) \ $(LIBINTL) $(NETLIBS) $(LIBICONV) $(W32SOCKLIBS) \ - $(gpgtar_robjs) + $(gpgtar_rc_objs) gpg_wks_server_SOURCES = \ gpg-wks-server.c \ @@ -745,7 +739,7 @@ gpg_wks_client_CFLAGS = $(LIBASSUAN_CFLAGS) $(LIBGCRYPT_CFLAGS) \ gpg_wks_client_LDADD = $(libcommon) \ $(LIBASSUAN_LIBS) $(LIBGCRYPT_LIBS) $(GPG_ERROR_LIBS) \ $(LIBINTL) $(LIBICONV) $(NETLIBS) \ - $(gpg_wks_client_robjs) + $(gpg_wks_client_rc_objs) all: all-am @@ -1574,11 +1568,14 @@ uninstall-am: uninstall-binPROGRAMS uninstall-libexecPROGRAMS \ @HAVE_W32_SYSTEM_TRUE@.rc.o: @HAVE_W32_SYSTEM_TRUE@ $(WINDRES) $(DEFAULT_INCLUDES) $(INCLUDES) "$<" "$@" -@HAVE_W32_SYSTEM_TRUE@gpgconf-w32info.o: gpgconf.w32-manifest -@HAVE_W32_SYSTEM_TRUE@gpgtar-w32info.o: gpgtar.w32-manifest -@HAVE_W32_SYSTEM_TRUE@gpg-connect-agent-w32info.o: gpg-connect-agent.w32-manifest -@HAVE_W32_SYSTEM_TRUE@gpg-check-pattern-w32info.o: gpg-check-pattern.w32-manifest -@HAVE_W32_SYSTEM_TRUE@gpg-wks-client-w32info.o: gpg-wks-client.w32-manifest +@HAVE_W32_SYSTEM_TRUE@gpg-connect-agent-w32info.o : gpg-connect-agent.w32-manifest \ +@HAVE_W32_SYSTEM_TRUE@ ../common/w32info-rc.h +@HAVE_W32_SYSTEM_TRUE@gpgconf-w32info.o : gpgconf.w32-manifest ../common/w32info-rc.h +@HAVE_W32_SYSTEM_TRUE@gpgtar-w32info.o : gpgtar.w32-manifest ../common/w32info-rc.h +@HAVE_W32_SYSTEM_TRUE@gpg-check-pattern-w32info.o : gpg-check-pattern.w32-manifest \ +@HAVE_W32_SYSTEM_TRUE@ ../common/w32info-rc.h +@HAVE_W32_SYSTEM_TRUE@gpg-wks-client-w32info.o : gpg-wks-client.w32-manifest \ +@HAVE_W32_SYSTEM_TRUE@ ../common/w32info-rc.h # Make sure that all libs are build before we use them. This is # important for things like make -j2. diff --git a/tools/gpg-check-pattern.c b/tools/gpg-check-pattern.c index 77176cc..c2e3b5f 100644 --- a/tools/gpg-check-pattern.c +++ b/tools/gpg-check-pattern.c @@ -286,7 +286,7 @@ read_file (const char *fname, size_t *r_length) buflen = st.st_size; buf = xmalloc (buflen+1); - if (es_fread (buf, buflen, 1, fp) != 1) + if (buflen && es_fread (buf, buflen, 1, fp) != 1) { log_error ("error reading '%s': %s\n", fname, strerror (errno)); es_fclose (fp); diff --git a/tools/gpg-check-pattern.w32-manifest.in b/tools/gpg-check-pattern.w32-manifest.in index 2a5f8ec..acb7c91 100644 --- a/tools/gpg-check-pattern.w32-manifest.in +++ b/tools/gpg-check-pattern.w32-manifest.in @@ -15,4 +15,11 @@ <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/><!-- Vista --> </application> </compatibility> +<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2"> + <security> + <requestedPrivileges> + <requestedExecutionLevel level="asInvoker"/> + </requestedPrivileges> + </security> +</trustInfo> </assembly> diff --git a/tools/gpg-connect-agent.w32-manifest.in b/tools/gpg-connect-agent.w32-manifest.in index aba5420..c222a67 100644 --- a/tools/gpg-connect-agent.w32-manifest.in +++ b/tools/gpg-connect-agent.w32-manifest.in @@ -15,4 +15,11 @@ <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/><!-- Vista --> </application> </compatibility> +<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2"> + <security> + <requestedPrivileges> + <requestedExecutionLevel level="asInvoker"/> + </requestedPrivileges> + </security> +</trustInfo> </assembly> diff --git a/tools/gpg-wks-client.c b/tools/gpg-wks-client.c index 3aa8f98..6f593ff 100644 --- a/tools/gpg-wks-client.c +++ b/tools/gpg-wks-client.c @@ -74,6 +74,8 @@ enum cmd_and_opt_values oWithColons, oBlacklist, oNoAutostart, + oAddRevocs, + oNoAddRevocs, oDummy }; @@ -100,9 +102,9 @@ static ARGPARSE_OPTS opts[] = { ARGPARSE_c (aRemoveKey, "remove-key", "remove a key from a directory"), ARGPARSE_c (aPrintWKDHash, "print-wkd-hash", - "Print the WKD identifier for the given user ids"), + "print the WKD identifier for the given user ids"), ARGPARSE_c (aPrintWKDURL, "print-wkd-url", - "Print the WKD URL for the given user id"), + "print the WKD URL for the given user id"), ARGPARSE_group (301, ("@\nOptions:\n ")), @@ -117,6 +119,8 @@ static ARGPARSE_OPTS opts[] = { ARGPARSE_s_n (oWithColons, "with-colons", "@"), ARGPARSE_s_s (oBlacklist, "blacklist", "@"), ARGPARSE_s_s (oDirectory, "directory", "@"), + ARGPARSE_s_n (oAddRevocs, "add-revocs", "add revocation certificates"), + ARGPARSE_s_n (oNoAddRevocs, "no-add-revocs", "do not add revocation certificates"), ARGPARSE_s_s (oFakeSubmissionAddr, "fake-submission-addr", "@"), @@ -154,7 +158,7 @@ static gpg_error_t proc_userid_from_stdin (gpg_error_t (*func)(const char *), const char *text); static gpg_error_t command_supported (char *userid); static gpg_error_t command_check (char *userid); -static gpg_error_t command_send (const char *fingerprint, const char *userid); +static gpg_error_t command_create (const char *fingerprint, const char *userid); static gpg_error_t encrypt_response (estream_t *r_output, estream_t input, const char *addrspec, const char *fingerprint); @@ -254,6 +258,12 @@ parse_arguments (ARGPARSE_ARGS *pargs, ARGPARSE_OPTS *popts) case oBlacklist: add_blacklist (pargs->r.ret_str); break; + case oAddRevocs: + opt.add_revocs = 1; + break; + case oNoAddRevocs: + opt.add_revocs = 0; + break; case aSupported: case aCreate: @@ -296,6 +306,8 @@ main (int argc, char **argv) assuan_set_gpg_err_source (GPG_ERR_SOURCE_DEFAULT); setup_libassuan_logging (&opt.debug, NULL); + opt.add_revocs = 1; /* Default add revocation certs. */ + /* Parse the command line. */ pargs.argc = &argc; pargs.argv = &argv; @@ -372,7 +384,7 @@ main (int argc, char **argv) case aCreate: if (argc != 2) wrong_args ("--create FINGERPRINT USER-ID"); - err = command_send (argv[0], argv[1]); + err = command_create (argv[0], argv[1]); if (err) log_error ("creating request failed: %s\n", gpg_strerror (err)); break; @@ -1090,6 +1102,9 @@ command_check (char *userid) log_info (" created: %s\n", asctimestamp (sl->created)); if (sl->mbox) log_info (" addr-spec: %s\n", sl->mbox); + if (sl->expired || sl->revoked) + log_info (" flags:%s%s\n", + sl->expired? " expired":"", sl->revoked?" revoked":""); } } if (!found) @@ -1112,7 +1127,7 @@ command_check (char *userid) /* Locate the key by fingerprint and userid and send a publication * request. */ static gpg_error_t -command_send (const char *fingerprint, const char *userid) +command_create (const char *fingerprint, const char *userid) { gpg_error_t err; KEYDB_SEARCH_DESC desc; @@ -1128,6 +1143,7 @@ command_send (const char *fingerprint, const char *userid) uidinfo_list_t uidlist = NULL; uidinfo_list_t uid, thisuid; time_t thistime; + int any; if (classify_user_id (fingerprint, &desc, 1) || !(desc.mode == KEYDB_SEARCH_MODE_FPR @@ -1145,7 +1161,7 @@ command_send (const char *fingerprint, const char *userid) err = gpg_error (GPG_ERR_INV_USER_ID); goto leave; } - err = wks_get_key (&key, fingerprint, addrspec, 0); + err = wks_get_key (&key, fingerprint, addrspec, 0, 1); if (err) goto leave; @@ -1189,12 +1205,20 @@ command_send (const char *fingerprint, const char *userid) } thistime = 0; thisuid = NULL; + any = 0; for (uid = uidlist; uid; uid = uid->next) { if (!uid->mbox) continue; /* Should not happen anyway. */ if (policy->mailbox_only && ascii_strcasecmp (uid->uid, uid->mbox)) continue; /* UID has more than just the mailbox. */ + if (uid->expired) + { + if (opt.verbose) + log_info ("ignoring expired user id '%s'\n", uid->uid); + continue; + } + any = 1; if (uid->created > thistime) { thistime = uid->created; @@ -1203,6 +1227,14 @@ command_send (const char *fingerprint, const char *userid) } if (!thisuid) thisuid = uidlist; /* This is the case for a missing timestamp. */ + if (!any) + { + log_error ("public key %s has no mail address '%s'\n", + fingerprint, addrspec); + err = gpg_error (GPG_ERR_INV_USER_ID); + goto leave; + } + if (opt.verbose) log_info ("submitting key with user id '%s'\n", thisuid->uid); @@ -1213,7 +1245,7 @@ command_send (const char *fingerprint, const char *userid) estream_t newkey; es_rewind (key); - err = wks_filter_uid (&newkey, key, thisuid->uid, 0); + err = wks_filter_uid (&newkey, key, thisuid->uid, 1); if (err) { log_error ("error filtering key: %s\n", gpg_strerror (err)); @@ -1238,11 +1270,47 @@ command_send (const char *fingerprint, const char *userid) * the key again. */ es_fclose (key); key = NULL; - err = wks_get_key (&key, fingerprint, addrspec, 1); + err = wks_get_key (&key, fingerprint, addrspec, 1, 1); if (err) goto leave; } + if (opt.add_revocs) + { + if (es_fseek (key, 0, SEEK_END)) + { + err = gpg_error_from_syserror (); + log_error ("error seeking stream: %s\n", gpg_strerror (err)); + goto leave; + } + err = wks_find_add_revocs (key, addrspec); + if (err) + { + log_error ("error finding revocations for '%s': %s\n", + addrspec, gpg_strerror (err)); + goto leave; + } + } + + + /* Now put the armor around the key. */ + { + estream_t newkey; + + es_rewind (key); + err = wks_armor_key (&newkey, key, + no_encrypt? NULL + /* */ : ("Content-Type: application/pgp-keys\n" + "\n")); + if (err) + { + log_error ("error armoring key: %s\n", gpg_strerror (err)); + goto leave; + } + es_fclose (key); + key = newkey; + } + /* Hack to support posteo but let them disable this by setting the * new policy-version flag. */ if (policy->protocol_version < 3 @@ -1287,7 +1355,7 @@ command_send (const char *fingerprint, const char *userid) if (no_encrypt) { void *data; - size_t datalen, n; + size_t datalen; if (posteo_hack) { @@ -1312,16 +1380,7 @@ command_send (const char *fingerprint, const char *userid) goto leave; } key = NULL; - /* We need to skip over the first line which has a content-type - * header not needed here. */ - for (n=0; n < datalen ; n++) - if (((const char *)data)[n] == '\n') - { - n++; - break; - } - - err = mime_maker_add_body_data (mime, (char*)data + n, datalen - n); + err = mime_maker_add_body_data (mime, data, datalen); xfree (data); if (err) goto leave; @@ -1808,7 +1867,7 @@ domain_matches_mbox (const char *domain, const char *mbox) /* Core of mirror_one_key with the goal of mirroring just one uid. * UIDLIST is used to figure out whether the given MBOX occurs several - * times in UIDLIST and then to single out the newwest one. This is + * times in UIDLIST and then to single out the newest one. This is * so that for a key with * uid: Joe Someone <joe@example.org> * uid: Joe <joe@example.org> @@ -1849,24 +1908,36 @@ mirror_one_keys_userid (estream_t key, const char *mbox, uidinfo_list_t uidlist, err = gpg_error (GPG_ERR_NO_USER_ID); goto leave; } - /* FIXME: Consult blacklist. */ - - /* Only if we have more than one user id we bother to run the - * filter. In this case the result will be put into NEWKEY*/ + /* Always filter the key so that the result will be non-armored. */ es_rewind (key); - if (uidlist->next) + err = wks_filter_uid (&newkey, key, thisuid->uid, 1); + if (err) { - err = wks_filter_uid (&newkey, key, thisuid->uid, 0); + log_error ("error filtering key %s: %s\n", fpr, gpg_strerror (err)); + err = gpg_error (GPG_ERR_NO_PUBKEY); + goto leave; + } + + if (opt.add_revocs) + { + if (es_fseek (newkey, 0, SEEK_END)) + { + err = gpg_error_from_syserror (); + log_error ("error seeking stream: %s\n", gpg_strerror (err)); + goto leave; + } + err = wks_find_add_revocs (newkey, mbox); if (err) { - log_error ("error filtering key %s: %s\n", fpr, gpg_strerror (err)); - err = gpg_error (GPG_ERR_NO_PUBKEY); + log_error ("error finding revocations for '%s': %s\n", + mbox, gpg_strerror (err)); goto leave; } + es_rewind (newkey); } - err = wks_install_key_core (newkey? newkey : key, mbox); + err = wks_install_key_core (newkey, mbox); if (opt.verbose) log_info ("key %s published for '%s'\n", fpr, mbox); mirror_one_key_parm.nuids++; @@ -1905,7 +1976,9 @@ mirror_one_key (estream_t key) { if (!uid->mbox || (uid->flags & 1)) continue; /* No mail box or already processed. */ - if (!domain_matches_mbox (domain, uid->mbox)) + if (uid->expired) + continue; + if (*domain && !domain_matches_mbox (domain, uid->mbox)) continue; /* We don't want this one. */ if (is_in_blacklist (uid->mbox)) continue; diff --git a/tools/gpg-wks-client.w32-manifest.in b/tools/gpg-wks-client.w32-manifest.in index ba2508e..c44620f 100644 --- a/tools/gpg-wks-client.w32-manifest.in +++ b/tools/gpg-wks-client.w32-manifest.in @@ -15,4 +15,11 @@ <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/><!-- Vista --> </application> </compatibility> +<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2"> + <security> + <requestedPrivileges> + <requestedExecutionLevel level="asInvoker"/> + </requestedPrivileges> + </security> +</trustInfo> </assembly> diff --git a/tools/gpg-wks.h b/tools/gpg-wks.h index 32aa8c3..a7c17ca 100644 --- a/tools/gpg-wks.h +++ b/tools/gpg-wks.h @@ -39,6 +39,7 @@ struct int use_sendmail; int with_colons; int no_autostart; + int add_revocs; const char *output; const char *gpg_program; const char *directory; @@ -80,6 +81,8 @@ struct uidinfo_list_s time_t created; /* Time the userid was created. */ char *mbox; /* NULL or the malloced mailbox from UID. */ unsigned int flags; /* These flags are cleared on creation. */ + unsigned int expired:1; + unsigned int revoked:1; char uid[1]; }; typedef struct uidinfo_list_s *uidinfo_list_t; @@ -91,11 +94,14 @@ void wks_set_status_fd (int fd); void wks_write_status (int no, const char *format, ...) GPGRT_ATTR_PRINTF(2,3); void free_uidinfo_list (uidinfo_list_t list); gpg_error_t wks_get_key (estream_t *r_key, const char *fingerprint, - const char *addrspec, int exact); + const char *addrspec, int exact, int binary); gpg_error_t wks_list_key (estream_t key, char **r_fpr, uidinfo_list_t *r_mboxes); gpg_error_t wks_filter_uid (estream_t *r_newkey, estream_t key, const char *uid, int binary); +gpg_error_t wks_armor_key (estream_t *r_newkey, estream_t key, + const char *prefix); +gpg_error_t wks_find_add_revocs (estream_t key, const char *addrspec); gpg_error_t wks_send_mime (mime_maker_t mime); gpg_error_t wks_parse_policy (policy_flags_t flags, estream_t stream, int ignore_unknown); diff --git a/tools/gpgconf.c b/tools/gpgconf.c index 1b3f2be..d12a2c6 100644 --- a/tools/gpgconf.c +++ b/tools/gpgconf.c @@ -77,49 +77,53 @@ enum cmd_and_opt_values /* The list of commands and options. */ static ARGPARSE_OPTS opts[] = { - { 300, NULL, 0, N_("@Commands:\n ") }, - - { aListComponents, "list-components", 256, N_("list all components") }, - { aCheckPrograms, "check-programs", 256, N_("check all programs") }, - { aListOptions, "list-options", 256, N_("|COMPONENT|list options") }, - { aChangeOptions, "change-options", 256, N_("|COMPONENT|change options") }, - { aCheckOptions, "check-options", 256, N_("|COMPONENT|check options") }, - { aApplyDefaults, "apply-defaults", 256, - N_("apply global default values") }, - { aApplyProfile, "apply-profile", 256, - N_("|FILE|update configuration files using FILE") }, - { aListDirs, "list-dirs", 256, - N_("get the configuration directories for @GPGCONF@") }, - { aListConfig, "list-config", 256, - N_("list global configuration file") }, - { aCheckConfig, "check-config", 256, - N_("check global configuration file") }, - { aQuerySWDB, "query-swdb", 256, - N_("query the software version database") }, - { aReload, "reload", 256, N_("reload all or a given component")}, - { aLaunch, "launch", 256, N_("launch a given component")}, - { aKill, "kill", 256, N_("kill a given component")}, - { aCreateSocketDir, "create-socketdir", 256, "@"}, - { aRemoveSocketDir, "remove-socketdir", 256, "@"}, + ARGPARSE_group (300, N_("@Commands:\n ")), + + ARGPARSE_c (aListComponents, "list-components", N_("list all components")), + ARGPARSE_c (aCheckPrograms, "check-programs", N_("check all programs")), + ARGPARSE_c (aListOptions, "list-options", N_("|COMPONENT|list options")), + ARGPARSE_c (aChangeOptions, "change-options", + N_("|COMPONENT|change options")), + ARGPARSE_c (aCheckOptions, "check-options", N_("|COMPONENT|check options")), + ARGPARSE_c (aApplyDefaults, "apply-defaults", + N_("apply global default values")), + ARGPARSE_c (aApplyProfile, "apply-profile", + N_("|FILE|update configuration files using FILE")), + ARGPARSE_c (aListDirs, "list-dirs", + N_("get the configuration directories for @GPGCONF@")), + ARGPARSE_c (aListConfig, "list-config", + N_("list global configuration file")), + ARGPARSE_c (aCheckConfig, "check-config", + N_("check global configuration file")), + ARGPARSE_c (aQuerySWDB, "query-swdb", + N_("query the software version database")), + ARGPARSE_c (aReload, "reload", N_("reload all or a given component")), + ARGPARSE_c (aLaunch, "launch", N_("launch a given component")), + ARGPARSE_c (aKill, "kill", N_("kill a given component")), + ARGPARSE_c (aCreateSocketDir, "create-socketdir", "@"), + ARGPARSE_c (aRemoveSocketDir, "remove-socketdir", "@"), ARGPARSE_c (aShowVersions, "show-versions", ""), ARGPARSE_c (aShowConfigs, "show-configs", ""), - { 301, NULL, 0, N_("@\nOptions:\n ") }, + ARGPARSE_header (NULL, N_("@\nOptions:\n ")), + + ARGPARSE_s_s (oOutput, "output", N_("use as output file")), + ARGPARSE_s_n (oVerbose, "verbose", N_("verbose")), + ARGPARSE_s_n (oQuiet, "quiet", N_("quiet")), + ARGPARSE_s_n (oDryRun, "dry-run", N_("do not make any changes")), + ARGPARSE_s_n (oRuntime, "runtime", + N_("activate changes at runtime, if possible")), + ARGPARSE_s_i (oStatusFD, "status-fd", + N_("|FD|write status info to this FD")), - { oOutput, "output", 2, N_("use as output file") }, - { oVerbose, "verbose", 0, N_("verbose") }, - { oQuiet, "quiet", 0, N_("quiet") }, - { oDryRun, "dry-run", 0, N_("do not make any changes") }, - { oRuntime, "runtime", 0, N_("activate changes at runtime, if possible") }, - ARGPARSE_s_i (oStatusFD, "status-fd", N_("|FD|write status info to this FD")), /* hidden options */ - { oHomedir, "homedir", 2, "@" }, - { oBuilddir, "build-prefix", 2, "@" }, - { oNull, "null", 0, "@" }, - { oNoVerbose, "no-verbose", 0, "@"}, + ARGPARSE_s_s (oHomedir, "homedir", "@"), + ARGPARSE_s_s (oBuilddir, "build-prefix", "@"), + ARGPARSE_s_n (oNull, "null", "@"), + ARGPARSE_s_n (oNoVerbose, "no-verbose", "@"), ARGPARSE_s_n (oShowSocket, "show-socket", "@"), - ARGPARSE_end(), + ARGPARSE_end () }; @@ -243,10 +247,10 @@ gpgconf_write_status (int no, const char *format, ...) static void -list_dirs (estream_t fp, char **names, int special) +list_dirs (estream_t fp, char **names, int show_config_mode) { static struct { - const char *name; + const char *name; /* If NULL only a file check will be done. */ const char *(*fnc)(void); const char *extra; } list[] = { @@ -262,13 +266,16 @@ list_dirs (estream_t fp, char **names, int special) { "agent-extra-socket", gnupg_socketdir, GPG_AGENT_EXTRA_SOCK_NAME }, { "agent-browser-socket",gnupg_socketdir, GPG_AGENT_BROWSER_SOCK_NAME }, { "agent-socket", gnupg_socketdir, GPG_AGENT_SOCK_NAME }, + { NULL, gnupg_socketdir, "S.uiserver" }, { "homedir", gnupg_homedir, NULL } }; int idx, j; char *tmp; const char *s; + gpg_error_t err; - + if (show_config_mode) + es_fprintf (fp, "#+begin_example\n"); for (idx = 0; idx < DIM (list); idx++) { s = list[idx].fnc (); @@ -279,20 +286,45 @@ list_dirs (estream_t fp, char **names, int special) } else tmp = NULL; - if (!names) - es_fprintf (fp, "%s:%s\n", list[idx].name, gc_percent_escape (s)); + + if (!list[idx].name) + ; + else if (!names) + es_fprintf (fp, "%s%s:%s\n", show_config_mode? " ":"", + list[idx].name, gc_percent_escape (s)); else { for (j=0; names[j]; j++) if (!strcmp (names[j], list[idx].name)) { + if (show_config_mode) + es_fputs (" ", fp); es_fputs (s, fp); es_putc (opt.null? '\0':'\n', fp); } } + /* In show config mode check that the socket files are accessible. */ + if (list[idx].extra && show_config_mode) + { + estream_t tmpfp; + + tmpfp = es_fopen (s, "rb"); + if (tmpfp) + es_fclose (tmpfp); /* All fine - we can read that file. */ + else if ((err=gpg_error_from_syserror ()) == GPG_ERR_ENOENT + || err == GPG_ERR_ENXIO) + ; /* No such file/ No such device or address - this is okay. */ + else + es_fprintf (fp, + "# Warning: error reading existing file '%s': %s\n", + s, gpg_strerror (err)); + } + xfree (tmp); } + if (show_config_mode) + es_fprintf (fp, "#+end_example\n"); #ifdef HAVE_W32_SYSTEM @@ -321,9 +353,9 @@ list_dirs (estream_t fp, char **names, int special) } es_fflush (fp); - if (special) + if (show_config_mode) es_fprintf (fp, "\n" - "### Note: homedir taken from registry key %s%s\\%s:%s\n" + "Note: homedir taken from registry key %s%s\\%s:%s\n" "\n", hkcu?" HKCU":"", hklm?" HKLM":"", GNUPG_REGISTRY_DIR, "HomeDir"); @@ -339,9 +371,9 @@ list_dirs (estream_t fp, char **names, int special) { xfree (tmp); es_fflush (fp); - if (special) + if (show_config_mode) es_fprintf (fp, "\n" - "### Note: registry key %s without value in HKCU or HKLM\n" + "Note: registry key %s without value in HKCU or HKLM\n" "\n", GNUPG_REGISTRY_DIR); else log_info ("Warning: registry key (%s) without value in HKCU or HKLM\n", @@ -349,7 +381,7 @@ list_dirs (estream_t fp, char **names, int special) } #else /*!HAVE_W32_SYSTEM*/ - (void)special; + (void)show_config_mode; #endif /*!HAVE_W32_SYSTEM*/ } @@ -1042,16 +1074,18 @@ get_revision_from_blurb (const char *blurb, int *r_len) static void show_version_gnupg (estream_t fp, const char *prefix) { - char *fname, *p; + char *fname, *p, *p0; size_t n; estream_t verfp; - char line[100]; + char *line = NULL; + size_t line_len = 0; + ssize_t length; es_fprintf (fp, "%s%sGnuPG %s (%s)\n%s%s\n", prefix, *prefix?"":"* ", strusage (13), BUILD_REVISION, prefix, strusage (17)); /* Show the GnuPG VS-Desktop version in --show-configs mode */ - if (prefix && *prefix == '#') + if (prefix && *prefix) { fname = make_filename (gnupg_bindir (), NULL); n = strlen (fname); @@ -1064,20 +1098,46 @@ show_version_gnupg (estream_t fp, const char *prefix) verfp = es_fopen (fname, "r"); if (!verfp) es_fprintf (fp, "%s[VERSION file not found]\n", prefix); - else if (!es_fgets (line, sizeof line, verfp)) - es_fprintf (fp, "%s[VERSION file is empty]\n", prefix); else { - trim_spaces (line); - for (p=line; *p; p++) - if (*p < ' ' || *p > '~' || *p == '[') - *p = '?'; - es_fprintf (fp, "%s%s\n", prefix, line); + int lnr = 0; + + p0 = NULL; + while ((length = es_read_line (verfp, &line, &line_len, NULL))>0) + { + lnr++; + trim_spaces (line); + if (lnr == 1 && *line != '[') + { + /* Old file format where we look only at the + * first line. */ + p0 = line; + break; + } + else if (!strncmp (line, "version=", 8)) + { + p0 = line + 8; + break; + } + } + if (length < 0 || es_ferror (verfp)) + es_fprintf (fp, "%s[VERSION file read error]\n", prefix); + else if (p0) + { + for (p=p0; *p; p++) + if (*p < ' ' || *p > '~' || *p == '[') + *p = '?'; + es_fprintf (fp, "%s%s\n", prefix, p0); + } + else + es_fprintf (fp, "%s[VERSION file is empty]\n", prefix); + + es_fclose (verfp); } - es_fclose (verfp); } xfree (fname); } + xfree (line); #ifdef HAVE_W32_SYSTEM { @@ -1203,7 +1263,7 @@ show_versions (estream_t fp) /* Copy data from file SRC to DST. Returns 0 on success or an error * code on failure. If LISTP is not NULL, that strlist is updated - * with the variabale or registry key names detected. Flag bit 0 + * with the variable or registry key names detected. Flag bit 0 * indicates a registry entry. */ static gpg_error_t my_copy_file (estream_t src, estream_t dst, strlist_t *listp) @@ -1216,7 +1276,14 @@ my_copy_file (estream_t src, estream_t dst, strlist_t *listp) while ((length = es_read_line (src, &line, &line_len, NULL)) > 0) { - /* Strip newline and carriage return, if present. */ + /* Prefix each line with two spaces but use a comma if the line + * starts with a special org-mode character. */ + if (*line == '*' || (*line == '#' && line[1] == '+')) + es_fputc (',', dst); + else + es_fputc (' ', dst); + es_fputc (' ', dst); + written = gpgrt_fwrite (line, 1, length, dst); if (written != length) return gpg_error_from_syserror (); @@ -1284,21 +1351,19 @@ show_configs_one_file (const char *fname, int global, estream_t outfp, if (!fp) { err = gpg_error_from_syserror (); - es_fprintf (outfp, "###\n### %s config \"%s\": %s\n###\n", - global? "global":"local", fname, - (gpg_err_code (err) == GPG_ERR_ENOENT)? - "not installed" : gpg_strerror (err)); + if (gpg_err_code (err) != GPG_ERR_ENOENT) + es_fprintf (outfp, "** %s config \"%s\": %s\n", + global? "global":"local", fname, gpg_strerror (err)); } else { - es_fprintf (outfp, "###\n### %s config \"%s\"\n###\n", + es_fprintf (outfp, "** %s config \"%s\"\n#+begin_src\n", global? "global":"local", fname); - es_fprintf (outfp, CUTLINE_FMT, "start"); err = my_copy_file (fp, outfp, listp); + es_fprintf (outfp, "\n#+end_src\n"); if (err) - log_error ("error copying file \"%s\": %s\n", + log_error ("Error copying file \"%s\": %s\n", fname, gpg_strerror (err)); - es_fprintf (outfp, CUTLINE_FMT, "end--"); es_fclose (fp); } } @@ -1315,9 +1380,10 @@ show_other_registry_entries (estream_t outfp) const char *name; } names[] = { - { 1, "HKLM\\Software\\Gpg4win:Install Directory" }, { 1, "HKLM\\Software\\Gpg4win:Desktop-Version" }, { 1, "HKLM\\Software\\Gpg4win:VS-Desktop-Version" }, + { 1, "\\Software\\Gpg4win:Install Directory" }, + { 1, "\\Software\\GnuPG:Install Directory" }, { 1, "\\" GNUPG_REGISTRY_DIR ":HomeDir" }, { 1, "\\" GNUPG_REGISTRY_DIR ":DefaultLogFile" }, { 2, "\\Software\\Microsoft\\Office\\Outlook\\Addins\\GNU.GpgOL" @@ -1373,7 +1439,7 @@ show_other_registry_entries (estream_t outfp) if (names[idx].group != group) { group = names[idx].group; - es_fprintf (outfp, "###\n### %s related:\n", + es_fprintf (outfp, "\n%s related:\n", group == 1 ? "GnuPG Desktop" : group == 2 ? "Outlook" : group == 3 ? "\\Software\\GNU\\GpgOL" @@ -1381,16 +1447,15 @@ show_other_registry_entries (estream_t outfp) } if (group == 3) - es_fprintf (outfp, "### %s=%s%s\n", names[idx].name, value, + es_fprintf (outfp, " %s=%s%s\n", names[idx].name, value, from_hklm? " [hklm]":""); else - es_fprintf (outfp, "### %s\n### ->%s<-%s\n", name, value, + es_fprintf (outfp, " %s\n ->%s<-%s\n", name, value, from_hklm? " [hklm]":""); xfree (value); } - es_fprintf (outfp, "###\n"); xfree (namebuf); } @@ -1441,10 +1506,10 @@ show_registry_entries_from_file (estream_t outfp) if (!any) { any = 1; - es_fprintf (outfp, "### Taken from gpgconf.rnames:\n"); + es_fprintf (outfp, "Taken from gpgconf.rnames:\n"); } - es_fprintf (outfp, "### %s\n### ->%s<-%s\n", line, value, + es_fprintf (outfp, " %s\n ->%s<-%s\n", line, value, from_hklm? " [hklm]":""); } @@ -1455,8 +1520,6 @@ show_registry_entries_from_file (estream_t outfp) } leave: - if (any) - es_fprintf (outfp, "###\n"); xfree (value); xfree (line); es_fclose (fp); @@ -1472,23 +1535,32 @@ show_configs (estream_t outfp) static const char *names[] = { "common.conf", "gpg-agent.conf", "scdaemon.conf", "dirmngr.conf", "gpg.conf", "gpgsm.conf" }; + static const char *envvars[] = { "PATH", + "http_proxy", "HTTP_PROXY", + "https_proxy", "HTTPS_PROXY", + "LD_LIBRARY_PATH", "LD_PRELOAD", + "LD_AUDIT", "LD_ORIGIN_PATH" }; gpg_error_t err; int idx; char *fname; gnupg_dir_t dir; gnupg_dirent_t dir_entry; size_t n; - int any; + int any, anywarn; strlist_t list = NULL; strlist_t sl; const char *s; - - es_fprintf (outfp, "### Dump of all standard config files\n"); - show_version_gnupg (outfp, "### "); - es_fprintf (outfp, "### Libgcrypt %s\n", gcry_check_version (NULL)); - es_fprintf (outfp, "### GpgRT %s\n", gpg_error_check_version (NULL)); + int got_gpgconfconf = 0; + + es_fprintf (outfp, "# gpgconf -X invoked %s%*s-*- org -*-\n\n", + isotimestamp (time (NULL)), 28, ""); + es_fprintf (outfp, "* General information\n"); + es_fprintf (outfp, "** Versions\n"); + show_version_gnupg (outfp, " "); + es_fprintf (outfp, " Libgcrypt %s\n", gcry_check_version (NULL)); + es_fprintf (outfp, " GpgRT %s\n", gpg_error_check_version (NULL)); #ifdef HAVE_W32_SYSTEM - es_fprintf (outfp, "### Codepages:"); + es_fprintf (outfp, " Codepages:"); if (GetConsoleCP () != GetConsoleOutputCP ()) es_fprintf (outfp, " %u/%u", GetConsoleCP (), GetConsoleOutputCP ()); else @@ -1496,11 +1568,28 @@ show_configs (estream_t outfp) es_fprintf (outfp, " %u", GetACP ()); es_fprintf (outfp, " %u\n", GetOEMCP ()); #endif - es_fprintf (outfp, "###\n\n"); + es_fprintf (outfp, "\n\n"); + es_fprintf (outfp, "** Directories\n"); list_dirs (outfp, NULL, 1); es_fprintf (outfp, "\n"); + es_fprintf (outfp, "** Environment\n#+begin_example\n"); + for (idx=0; idx < DIM(envvars); idx++) + if ((s = getenv (envvars[idx]))) + es_fprintf (outfp, "%s=%s\n", envvars[idx], s); + es_fprintf (outfp, "#+end_example\n"); + + es_fprintf (outfp, "* Config files\n"); + fname = make_filename (gnupg_sysconfdir (), "gpgconf.conf", NULL); + if (!gnupg_access (fname, F_OK)) + { + got_gpgconfconf = 1; + show_configs_one_file (fname, 1, outfp, &list); + es_fprintf (outfp, "\n"); + } + xfree (fname); + for (idx = 0; idx < DIM (names); idx++) { fname = make_filename (gnupg_sysconfdir (), names[idx], NULL); @@ -1513,6 +1602,7 @@ show_configs (estream_t outfp) } /* Print the encountered registry values and envvars. */ + es_fprintf (outfp, "* Other info\n"); if (list) { any = 0; @@ -1523,20 +1613,21 @@ show_configs (estream_t outfp) { any = 1; es_fprintf (outfp, - "###\n" - "### List of encountered environment variables:\n"); + "** List of encountered environment variables\n" + "#+begin_example\n"); } if ((s = getenv (sl->d))) - es_fprintf (outfp, "### %-12s ->%s<-\n", sl->d, s); + es_fprintf (outfp, " %-12s ->%s<-\n", sl->d, s); else - es_fprintf (outfp, "### %-12s [not set]\n", sl->d); + es_fprintf (outfp, " %-12s [not set]\n", sl->d); } if (any) - es_fprintf (outfp, "###\n"); + es_fprintf (outfp, "#+end_example\n"); } #ifdef HAVE_W32_SYSTEM - es_fprintf (outfp, "###\n### Registry entries:\n"); + es_fprintf (outfp, "** Registry entries\n"); + es_fprintf (outfp, "#+begin_example\n"); any = 0; if (list) { @@ -1549,24 +1640,33 @@ show_configs (estream_t outfp) if (!any) { any = 1; - es_fprintf (outfp, "###\n### Encountered in config files:\n"); + es_fprintf (outfp, "Encountered in config files:\n"); } if ((p = read_w32_reg_string (sl->d, &from_hklm))) - es_fprintf (outfp, "### %s ->%s<-%s\n", sl->d, p, + es_fprintf (outfp, " %s ->%s<-%s\n", sl->d, p, from_hklm? " [hklm]":""); else - es_fprintf (outfp, "### %s [not set]\n", sl->d); + es_fprintf (outfp, " %s [not set]\n", sl->d); xfree (p); } } - if (!any) - es_fprintf (outfp, "###\n"); show_other_registry_entries (outfp); show_registry_entries_from_file (outfp); + es_fprintf (outfp, "#+end_example\n"); #endif /*HAVE_W32_SYSTEM*/ free_strlist (list); + /* Additional warning. */ + anywarn = 0; + if (got_gpgconfconf) + { + anywarn = 1; + es_fprintf (outfp, "* Warnings\n"); + es_fprintf (outfp, + "- Legacy config file \"gpgconf.conf\" found\n"); + } + /* Check for uncommon files in the home directory. */ dir = gnupg_opendir (gnupg_homedir ()); if (!dir) @@ -1587,19 +1687,22 @@ show_configs (estream_t outfp) && dir_entry->d_name[n] == '-' && ascii_strncasecmp (dir_entry->d_name, "gpg.conf-1", 10)) { + if (!anywarn) + { + anywarn = 1; + es_fprintf (outfp, "* Warnings\n"); + } if (!any) { any = 1; es_fprintf (outfp, - "###\n" - "### Warning: suspicious files in \"%s\":\n", + "- Suspicious files in \"%s\":\n", gnupg_homedir ()); } - es_fprintf (outfp, "### %s\n", dir_entry->d_name); + es_fprintf (outfp, " - %s\n", dir_entry->d_name); } } } - if (any) - es_fprintf (outfp, "###\n"); gnupg_closedir (dir); + es_fprintf (outfp, "# eof #\n"); } diff --git a/tools/gpgconf.w32-manifest.in b/tools/gpgconf.w32-manifest.in index d7a1b01..ab5f17d 100644 --- a/tools/gpgconf.w32-manifest.in +++ b/tools/gpgconf.w32-manifest.in @@ -15,4 +15,11 @@ <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/><!-- Vista --> </application> </compatibility> +<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2"> + <security> + <requestedPrivileges> + <requestedExecutionLevel level="asInvoker"/> + </requestedPrivileges> + </security> +</trustInfo> </assembly> diff --git a/tools/gpgtar-create.c b/tools/gpgtar-create.c index e642da0..8cb65c7 100644 --- a/tools/gpgtar-create.c +++ b/tools/gpgtar-create.c @@ -1,5 +1,5 @@ /* gpgtar-create.c - Create a TAR archive - * Copyright (C) 2016-2017, 2019-2022 g10 Code GmbH + * Copyright (C) 2016-2017, 2019-2023 g10 Code GmbH * Copyright (C) 2010, 2012, 2013 Werner Koch * Copyright (C) 2010 Free Software Foundation, Inc. * @@ -49,10 +49,19 @@ #define lstat(a,b) gnupg_stat ((a), (b)) #endif +/* Number of files to be write. */ +static unsigned long global_total_files; + +/* Count the number of written file and thus headers. Extended + * headers are not counted. */ +static unsigned long global_written_files; + +/* Total data expected to be written. */ +static unsigned long long global_total_data; + +/* Number of data bytes written so far. */ +static unsigned long long global_written_data; -/* Count the number of written headers. Extended headers are not - * counted. */ -static unsigned long global_header_count; /* Object to control the file scanning. */ @@ -62,10 +71,62 @@ struct scanctrl_s { tar_header_t flist; tar_header_t *flist_tail; + unsigned long file_count; int nestlevel; }; +/* See ../g10/progress.c:write_status_progress for some background. */ +static void +write_progress (int countmode, unsigned long long current, + unsigned long long total_arg) +{ + char units[] = "BKMGTPEZY?"; + int unitidx = 0; + uint64_t total = total_arg; + + if (!opt.status_stream) + return; /* Not enabled. */ + + if (countmode) + { + if (total && current > total) + current = total; + } + else if (total) /* Size mode: This may use units. */ + { + if (current > total) + current = total; + + while (total > 1024*1024) + { + total /= 1024; + current /= 1024; + unitidx++; + } + } + else /* Size mode */ + { + while (current > 1024*1024) + { + current /= 1024; + unitidx++; + } + } + + if (unitidx > sizeof units - 1) + unitidx = sizeof units - 1; + + if (countmode) + es_fprintf (opt.status_stream, "[GNUPG:] PROGRESS gpgtar c %zu %zu\n", + (size_t)current, (size_t)total); + else + es_fprintf (opt.status_stream, "[GNUPG:] PROGRESS gpgtar s %zu %zu %c%s\n", + (size_t)current, (size_t)total, + units[unitidx], + unitidx? "iB" : ""); +} + /* On Windows convert name to UTF8 and return it; caller must release * the result. On Unix or if ALREADY_UTF8 is set, this function is a @@ -300,6 +361,12 @@ add_entry (const char *dname, const char *entryname, scanctrl_t scanctrl) gpgtar_print_header (hdr, NULL, log_get_stream ()); *scanctrl->flist_tail = hdr; scanctrl->flist_tail = &hdr->next; + scanctrl->file_count++; + /* Print a progress line during scnanning in increments of 5000 + * and not of 100 as we doing during write: Scanning is of + * course much faster. */ + if (!(scanctrl->file_count % 5000)) + write_progress (1, scanctrl->file_count, 0); } return 0; @@ -709,7 +776,7 @@ build_header (void *record, tar_header_t hdr, strlist_t *r_exthdr) * will do. To ease testing we also put in the PID. The * count is bumped after the header has been written. */ snprintf (raw->name, sizeof raw->name-1, "_@paxheader.%u.%lu", - (unsigned int)getpid(), global_header_count + 1); + (unsigned int)getpid(), global_written_files + 1); } } @@ -881,7 +948,7 @@ write_extended_header (estream_t stream, const void *record, strlist_t exthdr) static gpg_error_t -write_file (estream_t stream, tar_header_t hdr) +write_file (estream_t stream, tar_header_t hdr, unsigned int *skipped_open) { gpg_error_t err; char record[RECORDSIZE]; @@ -895,7 +962,7 @@ write_file (estream_t stream, tar_header_t hdr) { if (gpg_err_code (err) == GPG_ERR_NOT_SUPPORTED) { - log_info ("skipping unsupported file '%s'\n", hdr->name); + log_info ("silently skipping unsupported file '%s'\n", hdr->name); err = 0; } return err; @@ -907,9 +974,12 @@ write_file (estream_t stream, tar_header_t hdr) if (!infp) { err = gpg_error_from_syserror (); - log_error ("can't open '%s': %s - skipped\n", + log_info ("can't open '%s': %s - skipped\n", hdr->name, gpg_strerror (err)); - return err; + ++*skipped_open; + if (!*skipped_open) /* Protect against overflow. */ + --*skipped_open; + return 0; } } else @@ -920,7 +990,9 @@ write_file (estream_t stream, tar_header_t hdr) err = write_record (stream, record); if (err) goto leave; - global_header_count++; + global_written_files++; + if (!(global_written_files % 100)) + write_progress (1, global_written_files, global_total_files); if (hdr->typeflag == TF_REGULAR) { @@ -946,6 +1018,9 @@ write_file (estream_t stream, tar_header_t hdr) err = write_record (stream, record); if (err) goto leave; + global_written_data += nbytes; + if (!((global_written_data/nbytes) % (2048*100))) + write_progress (0, global_written_data, global_total_data); } nread = es_fread (record, 1, 1, infp); if (nread) @@ -995,6 +1070,7 @@ gpgtar_create (char **inpattern, const char *files_from, int null_names, estream_t outstream = NULL; int eof_seen = 0; pid_t pid = (pid_t)(-1); + unsigned int skipped_open = 0; memset (scanctrl, 0, sizeof *scanctrl); scanctrl->flist_tail = &scanctrl->flist; @@ -1147,10 +1223,22 @@ gpgtar_create (char **inpattern, const char *files_from, int null_names, if (files_from_stream && files_from_stream != es_stdin) es_fclose (files_from_stream); + global_total_files = global_total_data = 0; + global_written_files = global_written_data = 0; + for (hdr = scanctrl->flist; hdr; hdr = hdr->next) + { + global_total_files++; + global_total_data += hdr->size; + } + write_progress (1, 0, global_total_files); + write_progress (0, 0, global_total_data); + + if (encrypt || sign) { strlist_t arg; ccparray_t ccp; + int except[2] = { -1, -1 }; const char **argv; /* '--encrypt' may be combined with '--symmetric', but 'encrypt' @@ -1174,6 +1262,7 @@ gpgtar_create (char **inpattern, const char *files_from, int null_names, snprintf (tmpbuf, sizeof tmpbuf, "--status-fd=%d", opt.status_fd); ccparray_put (&ccp, tmpbuf); + except[0] = opt.status_fd; } ccparray_put (&ccp, "--output"); @@ -1194,6 +1283,8 @@ gpgtar_create (char **inpattern, const char *files_from, int null_names, ccparray_put (&ccp, "--recipient"); ccparray_put (&ccp, arg->d); } + if (opt.no_compress) + ccparray_put (&ccp, "-z0"); for (arg = opt.gpg_arguments; arg; arg = arg->next) ccparray_put (&ccp, arg->d); @@ -1205,7 +1296,9 @@ gpgtar_create (char **inpattern, const char *files_from, int null_names, goto leave; } - err = gnupg_spawn_process (opt.gpg_program, argv, NULL, NULL, + err = gnupg_spawn_process (opt.gpg_program, argv, + except[0] == -1? NULL : except, + NULL, (GNUPG_SPAWN_KEEP_STDOUT | GNUPG_SPAWN_KEEP_STDERR), &outstream, NULL, NULL, &pid); @@ -1235,17 +1328,20 @@ gpgtar_create (char **inpattern, const char *files_from, int null_names, es_set_binary (outstream); } - + skipped_open = 0; for (hdr = scanctrl->flist; hdr; hdr = hdr->next) { - err = write_file (outstream, hdr); + err = write_file (outstream, hdr, &skipped_open); if (err) goto leave; } + err = write_eof_mark (outstream); if (err) goto leave; + write_progress (1, global_written_files, global_total_files); + write_progress (0, global_written_data, global_total_data); if (pid != (pid_t)(-1)) { @@ -1266,6 +1362,12 @@ gpgtar_create (char **inpattern, const char *files_from, int null_names, } } + if (skipped_open) + { + log_info ("number of skipped files: %u\n", skipped_open); + log_error ("exiting with failure status due to previous errors\n"); + } + leave: if (!err) { diff --git a/tools/gpgtar-extract.c b/tools/gpgtar-extract.c index 832039b..cdf726d 100644 --- a/tools/gpgtar-extract.c +++ b/tools/gpgtar-extract.c @@ -37,7 +37,7 @@ #include "gpgtar.h" static gpg_error_t -check_suspicious_name (const char *name) +check_suspicious_name (const char *name, tarinfo_t info) { size_t n; @@ -47,6 +47,7 @@ check_suspicious_name (const char *name) { log_error ("filename '%s' contains a backslash - " "can't extract on this system\n", name); + info->skipped_badname++; return gpg_error (GPG_ERR_INV_NAME); } #endif /*HAVE_DOSISH_SYSTEM*/ @@ -59,6 +60,7 @@ check_suspicious_name (const char *name) { log_error ("filename '%s' has suspicious parts - not extracting\n", name); + info->skipped_suspicious++; return gpg_error (GPG_ERR_INV_NAME); } @@ -83,7 +85,7 @@ extract_regular (estream_t stream, const char *dirname, if (sl->flags == 1) fname = sl->d; - err = check_suspicious_name (fname); + err = check_suspicious_name (fname, info); if (err) goto leave; @@ -131,8 +133,12 @@ extract_regular (estream_t stream, const char *dirname, /* Fixme: Set permissions etc. */ leave: - if (!err && opt.verbose) - log_info ("extracted '%s'\n", fname); + if (!err) + { + if (opt.verbose) + log_info ("extracted '%s'\n", fname); + info->nextracted++; + } es_fclose (outfp); if (err && fname && outfp) { @@ -146,7 +152,8 @@ extract_regular (estream_t stream, const char *dirname, static gpg_error_t -extract_directory (const char *dirname, tar_header_t hdr, strlist_t exthdr) +extract_directory (const char *dirname, tarinfo_t info, + tar_header_t hdr, strlist_t exthdr) { gpg_error_t err; const char *name; @@ -158,7 +165,7 @@ extract_directory (const char *dirname, tar_header_t hdr, strlist_t exthdr) if (sl->flags == 1) name = sl->d; - err = check_suspicious_name (name); + err = check_suspicious_name (name, info); if (err) goto leave; @@ -198,6 +205,9 @@ extract_directory (const char *dirname, tar_header_t hdr, strlist_t exthdr) { *p = 0; rc = gnupg_mkdir (fname, "-rwx------"); + if (rc && (gpg_err_code (gpg_error_from_syserror ()) + == GPG_ERR_EEXIST)) + rc = 0; *p = '/'; if (rc) break; @@ -228,13 +238,19 @@ extract (estream_t stream, const char *dirname, tarinfo_t info, if (hdr->typeflag == TF_REGULAR || hdr->typeflag == TF_UNKNOWN) err = extract_regular (stream, dirname, info, hdr, exthdr); else if (hdr->typeflag == TF_DIRECTORY) - err = extract_directory (dirname, hdr, exthdr); + err = extract_directory (dirname, info, hdr, exthdr); else { char record[RECORDSIZE]; log_info ("unsupported file type %d for '%s' - skipped\n", (int)hdr->typeflag, hdr->name); + if (hdr->typeflag == TF_SYMLINK) + info->skipped_symlinks++; + else if (hdr->typeflag == TF_HARDLINK) + info->skipped_hardlinks++; + else + info->skipped_other++; for (err = 0, n=0; !err && n < hdr->nrecords; n++) { err = read_record (stream, record); @@ -326,7 +342,7 @@ gpgtar_extract (const char *filename, int decrypt) tarinfo_t tarinfo = &tarinfo_buffer; pid_t pid = (pid_t)(-1); char *logfilename = NULL; - + unsigned long long notextracted; memset (&tarinfo_buffer, 0, sizeof tarinfo_buffer); @@ -369,6 +385,7 @@ gpgtar_extract (const char *filename, int decrypt) { strlist_t arg; ccparray_t ccp; + int except[2] = { -1, -1 }; const char **argv; ccparray_init (&ccp, 0); @@ -382,6 +399,7 @@ gpgtar_extract (const char *filename, int decrypt) snprintf (tmpbuf, sizeof tmpbuf, "--status-fd=%d", opt.status_fd); ccparray_put (&ccp, tmpbuf); + except[0] = opt.status_fd; } if (opt.with_log) { @@ -408,7 +426,9 @@ gpgtar_extract (const char *filename, int decrypt) goto leave; } - err = gnupg_spawn_process (opt.gpg_program, argv, NULL, NULL, + err = gnupg_spawn_process (opt.gpg_program, argv, + except[0] == -1? NULL : except, + NULL, ((filename? 0 : GNUPG_SPAWN_KEEP_STDIN) | GNUPG_SPAWN_KEEP_STDERR), NULL, &stream, NULL, &pid); @@ -473,8 +493,37 @@ gpgtar_extract (const char *filename, int decrypt) } } - leave: + notextracted = tarinfo->skipped_badname; + notextracted += tarinfo->skipped_suspicious; + notextracted += tarinfo->skipped_symlinks; + notextracted += tarinfo->skipped_hardlinks; + notextracted += tarinfo->skipped_other; + if (opt.status_stream) + es_fprintf (opt.status_stream, "[GNUPG:] GPGTAR_EXTRACT" + " %llu %llu %lu %lu %lu %lu %lu\n", + tarinfo->nextracted, + notextracted, + tarinfo->skipped_badname, + tarinfo->skipped_suspicious, + tarinfo->skipped_symlinks, + tarinfo->skipped_hardlinks, + tarinfo->skipped_other); + if (notextracted && !opt.quiet) + { + log_info ("Number of files not extracted: %llu\n", notextracted); + if (tarinfo->skipped_badname) + log_info (" invalid name: %lu\n", tarinfo->skipped_badname); + if (tarinfo->skipped_suspicious) + log_info (" suspicious name: %lu\n", tarinfo->skipped_suspicious); + if (tarinfo->skipped_symlinks) + log_info (" symlink: %lu\n", tarinfo->skipped_symlinks); + if (tarinfo->skipped_hardlinks) + log_info (" hardlink: %lu\n", tarinfo->skipped_hardlinks); + if (tarinfo->skipped_other) + log_info (" other reason: %lu\n", tarinfo->skipped_other); + } + free_strlist (extheader); xfree (header); xfree (dirname); diff --git a/tools/gpgtar-list.c b/tools/gpgtar-list.c index 08ab967..37951d6 100644 --- a/tools/gpgtar-list.c +++ b/tools/gpgtar-list.c @@ -468,6 +468,7 @@ gpgtar_list (const char *filename, int decrypt) { strlist_t arg; ccparray_t ccp; + int except[2] = { -1, -1 }; const char **argv; ccparray_init (&ccp, 0); @@ -481,6 +482,7 @@ gpgtar_list (const char *filename, int decrypt) snprintf (tmpbuf, sizeof tmpbuf, "--status-fd=%d", opt.status_fd); ccparray_put (&ccp, tmpbuf); + except[0] = opt.status_fd; } ccparray_put (&ccp, "--output"); ccparray_put (&ccp, "-"); @@ -501,7 +503,9 @@ gpgtar_list (const char *filename, int decrypt) goto leave; } - err = gnupg_spawn_process (opt.gpg_program, argv, NULL, NULL, + err = gnupg_spawn_process (opt.gpg_program, argv, + except[0] == -1? NULL : except, + NULL, ((filename? 0 : GNUPG_SPAWN_KEEP_STDIN) | GNUPG_SPAWN_KEEP_STDERR), NULL, &stream, NULL, &pid); diff --git a/tools/gpgtar.c b/tools/gpgtar.c index e86ed32..e4ae0ea 100644 --- a/tools/gpgtar.c +++ b/tools/gpgtar.c @@ -75,6 +75,7 @@ enum cmd_and_opt_values oSetFilename, oNull, oUtf8Strings, + oNoCompress, oBatch, oAnswerYes, @@ -118,6 +119,7 @@ static ARGPARSE_OPTS opts[] = { ARGPARSE_s_s (oSetFilename, "set-filename", "@"), ARGPARSE_s_n (oOpenPGP, "openpgp", "@"), ARGPARSE_s_n (oCMS, "cms", "@"), + ARGPARSE_s_n (oNoCompress, "no-compress", "@"), ARGPARSE_s_n (oBatch, "batch", "@"), ARGPARSE_s_n (oAnswerYes, "yes", "@"), @@ -344,6 +346,7 @@ parse_arguments (ARGPARSE_ARGS *pargs, ARGPARSE_OPTS *popts) case oFilesFrom: files_from = pargs->r.ret_str; break; case oNull: null_names = 1; break; case oUtf8Strings: opt.utf8strings = 1; break; + case oNoCompress: opt.no_compress = 1; break; case aList: case aDecrypt: @@ -453,7 +456,7 @@ main (int argc, char **argv) gnupg_reopen_std (GPGTAR_NAME); set_strusage (my_strusage); - log_set_prefix (GPGTAR_NAME, GPGRT_LOG_WITH_PREFIX); + log_set_prefix (GPGTAR_NAME, GPGRT_LOG_WITH_PREFIX|GPGRT_LOG_NO_REGISTRY); /* Make sure that our subsystems are ready. */ i18n_init(); @@ -485,6 +488,36 @@ main (int argc, char **argv) log_info (_("NOTE: '%s' is not considered an option\n"), argv[i]); } + /* Set status stream for our own use of --status-fd. The original + * status fd is passed verbatim to gpg. */ + if (opt.status_fd != -1) + { + int fd = translate_sys2libc_fd_int (opt.status_fd, 1); + + if (!gnupg_fd_valid (fd)) + log_fatal ("status-fd is invalid: %s\n", strerror (errno)); + + if (fd == 1) + { + opt.status_stream = es_stdout; + if (!skip_crypto) + log_fatal ("using stdout for the status-fd is not possible\n"); + } + else if (fd == 2) + opt.status_stream = es_stderr; + else + { + opt.status_stream = es_fdopen (fd, "w"); + if (opt.status_stream) + es_setvbuf (opt.status_stream, NULL, _IOLBF, 0); + } + if (!opt.status_stream) + { + log_fatal ("can't open fd %d for status output: %s\n", + fd, strerror (errno)); + } + } + if (! opt.gpg_program) opt.gpg_program = gnupg_module_name (GNUPG_MODULE_NAME_GPG); @@ -493,17 +526,27 @@ main (int argc, char **argv) switch (cmd) { + case aDecrypt: case aList: if (argc > 1) usage (1); - fname = argc ? *argv : NULL; + fname = (argc && strcmp (*argv, "-"))? *argv : NULL; if (opt.filename) log_info ("note: ignoring option --set-filename\n"); if (files_from) log_info ("note: ignoring option --files-from\n"); - err = gpgtar_list (fname, !skip_crypto); - if (err && log_get_errorcount (0) == 0) - log_error ("listing archive failed: %s\n", gpg_strerror (err)); + if (cmd == aDecrypt) + { + err = gpgtar_extract (fname, !skip_crypto); + if (err && !log_get_errorcount (0)) + log_error ("extracting archive failed: %s\n", gpg_strerror (err)); + } + else + { + err = gpgtar_list (fname, !skip_crypto); + if (err && !log_get_errorcount (0)) + log_error ("listing archive failed: %s\n", gpg_strerror (err)); + } break; case aEncrypt: @@ -524,24 +567,21 @@ main (int argc, char **argv) log_error ("creating archive failed: %s\n", gpg_strerror (err)); break; - case aDecrypt: - if (argc != 1) - usage (1); - if (opt.outfile) - log_info ("note: ignoring option --output\n"); - if (files_from) - log_info ("note: ignoring option --files-from\n"); - fname = argc ? *argv : NULL; - err = gpgtar_extract (fname, !skip_crypto); - if (err && log_get_errorcount (0) == 0) - log_error ("extracting archive failed: %s\n", gpg_strerror (err)); - break; - default: log_error (_("invalid command (there is no implicit command)\n")); + err = 0; break; } + if (opt.status_stream) + { + if (err || log_get_errorcount (0)) + es_fprintf (opt.status_stream, "[GNUPG:] FAILURE - %u\n", + err? err : gpg_error (GPG_ERR_GENERAL)); + else + es_fprintf (opt.status_stream, "[GNUPG:] SUCCESS\n"); + } + return log_get_errorcount (0)? 1:0; } diff --git a/tools/gpgtar.h b/tools/gpgtar.h index 9f3c90f..0b6fa2b 100644 --- a/tools/gpgtar.h +++ b/tools/gpgtar.h @@ -33,6 +33,7 @@ struct int quiet; int dry_run; int utf8strings; + int no_compress; const char *gpg_program; strlist_t gpg_arguments; const char *outfile; @@ -45,6 +46,7 @@ struct int answer_yes; int answer_no; int status_fd; + estream_t status_stream; int require_compliance; int with_log; } opt; @@ -53,8 +55,14 @@ struct /* An info structure to avoid global variables. */ struct tarinfo_s { - unsigned long long nblocks; /* Count of processed blocks. */ + unsigned long long nblocks; /* Count of processed blocks. */ unsigned long long headerblock; /* Number of current header block. */ + unsigned long long nextracted; /* Number of extracted files. */ + unsigned long skipped_badname; + unsigned long skipped_suspicious; + unsigned long skipped_symlinks; + unsigned long skipped_hardlinks; + unsigned long skipped_other; }; typedef struct tarinfo_s *tarinfo_t; diff --git a/tools/gpgtar.w32-manifest.in b/tools/gpgtar.w32-manifest.in index 62d5937..b949a6b 100644 --- a/tools/gpgtar.w32-manifest.in +++ b/tools/gpgtar.w32-manifest.in @@ -15,4 +15,11 @@ <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/><!-- Vista --> </application> </compatibility> +<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2"> + <security> + <requestedPrivileges> + <requestedExecutionLevel level="asInvoker"/> + </requestedPrivileges> + </security> +</trustInfo> </assembly> diff --git a/tools/wks-util.c b/tools/wks-util.c index 3044fe2..2660c93 100644 --- a/tools/wks-util.c +++ b/tools/wks-util.c @@ -101,7 +101,8 @@ wks_write_status (int no, const char *format, ...) * updated. C-style escaping is removed from UID. On error ERRNO is * set and NULL returned. */ static uidinfo_list_t -append_to_uidinfo_list (uidinfo_list_t *list, const char *uid, time_t created) +append_to_uidinfo_list (uidinfo_list_t *list, const char *uid, time_t created, + int expired, int revoked) { uidinfo_list_t r, sl; char *plainuid; @@ -121,6 +122,8 @@ append_to_uidinfo_list (uidinfo_list_t *list, const char *uid, time_t created) sl->created = created; sl->flags = 0; sl->mbox = mailbox_from_userid (plainuid); + sl->expired = !!expired; + sl->revoked = !!revoked; sl->next = NULL; if (!*list) *list = sl; @@ -150,6 +153,21 @@ free_uidinfo_list (uidinfo_list_t list) } +static void +debug_gpg_invocation (const char *func, const char **argv) +{ + int i; + + if (!(opt.debug & DBG_EXTPROG_VALUE)) + return; + + log_debug ("%s: exec '%s' with", func, opt.gpg_program); + for (i=0; argv[i]; i++) + log_printf (" '%s'", argv[i]); + log_printf ("\n"); +} + + struct get_key_status_parm_s { @@ -164,7 +182,8 @@ get_key_status_cb (void *opaque, const char *keyword, char *args) { struct get_key_status_parm_s *parm = opaque; - /*log_debug ("%s: %s\n", keyword, args);*/ + if (DBG_CRYPTO) + log_debug ("%s: %s\n", keyword, args); if (!strcmp (keyword, "EXPORTED")) { parm->count++; @@ -177,10 +196,11 @@ get_key_status_cb (void *opaque, const char *keyword, char *args) * mail address ADDRSPEC is included in the key. If EXACT is set the * returned user id must match Addrspec exactly and not just in the * addr-spec (mailbox) part. The key is returned as a new memory - * stream at R_KEY. */ + * stream at R_KEY. If BINARY is set the returned key is + * non-armored. */ gpg_error_t wks_get_key (estream_t *r_key, const char *fingerprint, const char *addrspec, - int exact) + int exact, int binary) { gpg_error_t err; ccparray_t ccp; @@ -202,8 +222,9 @@ wks_get_key (estream_t *r_key, const char *fingerprint, const char *addrspec, } /* Prefix the key with the MIME content type. */ - es_fputs ("Content-Type: application/pgp-keys\n" - "\n", key); + if (!binary) + es_fputs ("Content-Type: application/pgp-keys\n" + "\n", key); filterexp = es_bsprintf ("keep-uid=%s= %s", exact? "uid":"mbox", addrspec); if (!filterexp) @@ -223,8 +244,9 @@ wks_get_key (estream_t *r_key, const char *fingerprint, const char *addrspec, ccparray_put (&ccp, "--batch"); ccparray_put (&ccp, "--status-fd=2"); ccparray_put (&ccp, "--always-trust"); - ccparray_put (&ccp, "--armor"); - ccparray_put (&ccp, "--export-options=export-minimal"); + if (!binary) + ccparray_put (&ccp, "--armor"); + ccparray_put (&ccp, "--export-options=export-clean"); ccparray_put (&ccp, "--export-filter"); ccparray_put (&ccp, filterexp); ccparray_put (&ccp, "--export"); @@ -239,6 +261,7 @@ wks_get_key (estream_t *r_key, const char *fingerprint, const char *addrspec, goto leave; } parm.fpr = fingerprint; + debug_gpg_invocation (__func__, argv); err = gnupg_exec_tool_stream (opt.gpg_program, argv, NULL, NULL, key, get_key_status_cb, &parm); @@ -276,6 +299,22 @@ key_status_cb (void *opaque, const char *keyword, char *args) } +/* Parse field 1 and set revoked and expired on return. */ +static void +set_expired_revoked (const char *string, int *expired, int *revoked) +{ + *expired = *revoked = 0; + /* Look at letters and stop at the first digit. */ + for ( ;*string && !digitp (string); string++) + { + if (*string == 'e') + *expired = 1; + else if (*string == 'r') + *revoked = 1; + } +} + + /* Run gpg on KEY and store the primary fingerprint at R_FPR and the * list of mailboxes at R_MBOXES. Returns 0 on success; on error NULL * is stored at R_FPR and R_MBOXES and an error code is returned. @@ -296,6 +335,7 @@ wks_list_key (estream_t key, char **r_fpr, uidinfo_list_t *r_mboxes) int lnr; char *fpr = NULL; uidinfo_list_t mboxes = NULL; + int expired, revoked; if (r_fpr) *r_fpr = NULL; @@ -332,6 +372,7 @@ wks_list_key (estream_t key, char **r_fpr, uidinfo_list_t *r_mboxes) err = gpg_error_from_syserror (); goto leave; } + debug_gpg_invocation (__func__, argv); err = gnupg_exec_tool_stream (opt.gpg_program, argv, key, NULL, listing, key_status_cb, NULL); @@ -343,6 +384,7 @@ wks_list_key (estream_t key, char **r_fpr, uidinfo_list_t *r_mboxes) es_rewind (listing); lnr = 0; + expired = revoked = 0; maxlen = 2048; /* Set limit. */ while ((len = es_read_line (listing, &line, &length_of_line, &maxlen)) > 0) { @@ -387,12 +429,20 @@ wks_list_key (estream_t key, char **r_fpr, uidinfo_list_t *r_mboxes) err = gpg_error (GPG_ERR_INV_ENGINE); goto leave; } - if (lnr > 1 && !strcmp (fields[0], "pub")) + if (!strcmp (fields[0], "pub")) { - /* More than one public key. */ - err = gpg_error (GPG_ERR_TOO_MANY); - goto leave; + if (lnr > 1) + { + /* More than one public key. */ + err = gpg_error (GPG_ERR_TOO_MANY); + goto leave; + } + if (nfields > 1) + set_expired_revoked (fields[1], &expired, &revoked); + else + expired = revoked = 0; } + if (!strcmp (fields[0], "sub") || !strcmp (fields[0], "ssb")) break; /* We can stop parsing here. */ @@ -407,8 +457,13 @@ wks_list_key (estream_t key, char **r_fpr, uidinfo_list_t *r_mboxes) } else if (!strcmp (fields[0], "uid") && nfields > 9) { + int uidexpired, uidrevoked; + + set_expired_revoked (fields[1], &uidexpired, &uidrevoked); if (!append_to_uidinfo_list (&mboxes, fields[9], - parse_timestamp (fields[5], NULL))) + parse_timestamp (fields[5], NULL), + expired || uidexpired, + revoked || uidrevoked)) { err = gpg_error_from_syserror (); goto leave; @@ -510,6 +565,7 @@ wks_filter_uid (estream_t *r_newkey, estream_t key, const char *uid, err = gpg_error_from_syserror (); goto leave; } + debug_gpg_invocation (__func__, argv); err = gnupg_exec_tool_stream (opt.gpg_program, argv, key, NULL, newkey, key_status_cb, NULL); @@ -531,6 +587,124 @@ wks_filter_uid (estream_t *r_newkey, estream_t key, const char *uid, } +/* Put the ascii-armor around KEY and return that as a new estream + * object at R_NEWKEY. Caller must make sure that KEY has been seeked + * to the right position (usually by calling es_rewind). The + * resulting NEWKEY has already been rewound. If PREFIX is not NULL, + * its content is written to NEWKEY propr to the armor; this may be + * used for MIME headers. */ +gpg_error_t +wks_armor_key (estream_t *r_newkey, estream_t key, const char *prefix) +{ + gpg_error_t err; + estream_t newkey; + struct b64state b64state; + char buffer[4096]; + size_t nread; + + *r_newkey = NULL; + + newkey = es_fopenmem (0, "w+b"); + if (!newkey) + { + err = gpg_error_from_syserror (); + return err; + } + + if (prefix) + es_fputs (prefix, newkey); + + err = b64enc_start_es (&b64state, newkey, "PGP PUBLIC KEY BLOCK"); + if (err) + goto leave; + + do + { + nread = es_fread (buffer, 1, sizeof buffer, key); + if (!nread) + break; + err = b64enc_write (&b64state, buffer, nread); + if (err) + goto leave; + } + while (!es_feof (key) && !es_ferror (key)); + if (!es_feof (key) || es_ferror (key)) + { + err = gpg_error_from_syserror (); + goto leave; + } + + err = b64enc_finish (&b64state); + if (err) + goto leave; + + es_rewind (newkey); + *r_newkey = newkey; + newkey = NULL; + + leave: + es_fclose (newkey); + return err; +} + + +/* Run gpg to export the revocation certificates for ADDRSPEC. Add + * them to KEY which is expected to be non-armored keyblock. */ +gpg_error_t +wks_find_add_revocs (estream_t key, const char *addrspec) +{ + gpg_error_t err; + ccparray_t ccp; + const char **argv = NULL; + char *filterexp = NULL; + + filterexp = es_bsprintf ("select=mbox= %s", addrspec); + if (!filterexp) + { + err = gpg_error_from_syserror (); + log_error ("error allocating memory buffer: %s\n", gpg_strerror (err)); + goto leave; + } + + ccparray_init (&ccp, 0); + + ccparray_put (&ccp, "--no-options"); + if (opt.verbose < 2) + ccparray_put (&ccp, "--quiet"); + else + ccparray_put (&ccp, "--verbose"); + ccparray_put (&ccp, "--batch"); + ccparray_put (&ccp, "--status-fd=2"); + ccparray_put (&ccp, "--export-options=export-revocs"); + ccparray_put (&ccp, "--export-filter"); + ccparray_put (&ccp, filterexp); + ccparray_put (&ccp, "--export"); + ccparray_put (&ccp, addrspec); + + ccparray_put (&ccp, NULL); + argv = ccparray_get (&ccp, NULL); + if (!argv) + { + err = gpg_error_from_syserror (); + goto leave; + } + debug_gpg_invocation (__func__, argv); + err = gnupg_exec_tool_stream (opt.gpg_program, argv, NULL, + NULL, key, + key_status_cb, NULL); + if (err) + { + log_error ("exporting revocs failed: %s\n", gpg_strerror (err)); + goto leave; + } + + leave: + xfree (filterexp); + xfree (argv); + return err; +} + + /* Helper to write mail to the output(s). */ gpg_error_t wks_send_mime (mime_maker_t mime) @@ -1103,7 +1277,7 @@ wks_cmd_install_key (const char *fname, const char *userid) { /* FNAME looks like a fingerprint. Get the key from the * standard keyring. */ - err = wks_get_key (&fp, fname, addrspec, 0); + err = wks_get_key (&fp, fname, addrspec, 0, 1); if (err) { log_error ("error getting key '%s' (uid='%s'): %s\n", @@ -1140,6 +1314,12 @@ wks_cmd_install_key (const char *fname, const char *userid) continue; /* Should not happen anyway. */ if (ascii_strcasecmp (uid->mbox, addrspec)) continue; /* Not the requested addrspec. */ + if (uid->expired) + { + if (opt.verbose) + log_info ("ignoring expired user id '%s'\n", uid->uid); + continue; + } any = 1; if (uid->created > thistime) { @@ -1175,6 +1355,24 @@ wks_cmd_install_key (const char *fname, const char *userid) fp = fp2; } + if (opt.add_revocs) + { + if (es_fseek (fp, 0, SEEK_END)) + { + err = gpg_error_from_syserror (); + log_error ("error seeking stream: %s\n", gpg_strerror (err)); + goto leave; + } + err = wks_find_add_revocs (fp, addrspec); + if (err) + { + log_error ("error finding revocations for '%s': %s\n", + addrspec, gpg_strerror (err)); + goto leave; + } + es_rewind (fp); + } + err = wks_install_key_core (fp, addrspec); if (!opt.quiet) log_info ("key %s published for '%s'\n", fpr, addrspec); |