From f8e868d9dfb6fc1390e421e7993a1d076309ed83 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Sat, 27 Jan 2018 19:46:19 +0100 Subject: [PATCH 01/25] dirmngr: Improve assuan error comment for cmd keyserver. * dirmngr/server.c: Add error comment in case --resolve fails in ensure_keyserver. -- GnuPG-bug-id: 3756 Signed-off-by: Werner Koch --- dirmngr/server.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/dirmngr/server.c b/dirmngr/server.c index 3d0768b2a..ab2ca852f 100644 --- a/dirmngr/server.c +++ b/dirmngr/server.c @@ -2134,8 +2134,13 @@ cmd_keyserver (assuan_context_t ctx, char *line) if (resolve_flag) { err = ensure_keyserver (ctrl); - if (!err) - err = ks_action_resolve (ctrl, ctrl->server_local->keyservers); + if (err) + { + assuan_set_error (ctx, err, + "Bad keyserver configuration in dirmngr.conf"); + goto leave; + } + err = ks_action_resolve (ctrl, ctrl->server_local->keyservers); if (err) goto leave; } From 64aa98c8a05513d9c00f53a2b880d80f9035333e Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Mon, 29 Jan 2018 09:34:37 +0900 Subject: [PATCH 02/25] tests: Fix for NetBSD with __func__. * tests/asschk.c: Don't define __func__ if available. -- NetBSD 7.0 has __func__ defined. Signed-off-by: NIIBE Yutaka --- tests/asschk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/asschk.c b/tests/asschk.c index 2595c0a99..65828e5b2 100644 --- a/tests/asschk.c +++ b/tests/asschk.c @@ -116,7 +116,7 @@ #endif #if __STDC_VERSION__ < 199901L -# if __GNUC__ >= 2 +# if __GNUC__ >= 2 && !defined (__func__) # define __func__ __FUNCTION__ # else /* Let's try our luck here. Some systems may provide __func__ without From f98e193c84250bbc49d5d1c625f54f2c14501ae3 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Thu, 1 Feb 2018 12:05:19 +0100 Subject: [PATCH 03/25] gpg: Update list of card vendors from master -- Signed-off-by: Werner Koch --- g10/card-util.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/g10/card-util.c b/g10/card-util.c index a396b7df4..759dde8e8 100644 --- a/g10/card-util.c +++ b/g10/card-util.c @@ -212,9 +212,11 @@ get_manufacturer (unsigned int no) case 0x000A: return "Dangerous Things"; case 0x002A: return "Magrathea"; + case 0x0042: return "GnuPG e.V."; case 0x1337: return "Warsaw Hackerspace"; case 0x2342: return "warpzone"; /* hackerspace Muenster. */ + case 0xBD0E: return "Paranoidlabs"; case 0xF517: return "FSIJ"; /* 0x0000 and 0xFFFF are defined as test cards per spec, From 015fe1c47b91da340e9df6bed908e0747ae8c60b Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Wed, 7 Feb 2018 12:43:07 +0900 Subject: [PATCH 04/25] scd: Use pipe to kick the loop on NetBSD. * configure.ac (HAVE_PSELECT_NO_EINTR): New. * scd/scdaemon.c (scd_kick_the_loop): Write to pipe. (handle_connections): Use pipe. -- On NetBSD, signal to the same process cannot unblock pselect, with unknown reason. Use pipe instead, for such systems. GnuPG-bug-id: 3778 Signed-off-by: NIIBE Yutaka --- configure.ac | 16 ++++++++++++++-- scd/scdaemon.c | 39 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 52 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index 420af92f9..bdb614696 100644 --- a/configure.ac +++ b/configure.ac @@ -639,6 +639,7 @@ have_android_system=no use_simple_gettext=no use_ldapwrapper=yes mmap_needed=yes +require_pipe_to_unblock_pselect=no case "${host}" in *-mingw32*) # special stuff for Windoze NT @@ -715,10 +716,20 @@ case "${host}" in AC_DEFINE(_DARWIN_C_SOURCE, 900000L, Expose all libc features (__DARWIN_C_FULL).) ;; + *-*-netbsd*) + require_pipe_to_unblock_pselect=yes + ;; *) - ;; + ;; esac +if test "$require_pipe_to_unblock_pselect" = yes; then + AC_DEFINE(HAVE_PSELECT_NO_EINTR, 1, + [Defined if we run on systems like NetBSD, where + pselect cannot be unblocked by signal from a thread + within the same process. We use pipe in this case, instead.]) +fi + if test "$have_dosish_system" = yes; then AC_DEFINE(HAVE_DOSISH_SYSTEM,1, [Defined if we run on some of the PCDOS like systems @@ -820,7 +831,8 @@ if test x"$LIBUSB_NAME" != x ; then have_libusb=yes ]) AC_MSG_CHECKING([libusb include dir]) usb_incdir_found="no" - for _incdir in "" "/usr/include/libusb-1.0" "/usr/local/include/libusb-1.0"; do + for _incdir in "" "/usr/include/libusb-1.0" \ + "/usr/local/include/libusb-1.0" "/usr/pkg/include/libusb-1.0"; do _libusb_save_cppflags=$CPPFLAGS if test -n "${_incdir}"; then CPPFLAGS="-I${_incdir} ${CPPFLAGS}" diff --git a/scd/scdaemon.c b/scd/scdaemon.c index 3ad265781..cebeea9d3 100644 --- a/scd/scdaemon.c +++ b/scd/scdaemon.c @@ -236,6 +236,10 @@ static HANDLE the_event; /* PID to notify update of usb devices. */ static pid_t main_thread_pid; #endif +#ifdef HAVE_PSELECT_NO_EINTR +/* FD to notify changes. */ +static int notify_fd; +#endif static char *create_socket_name (char *standard_name); static gnupg_fd_t create_server_socket (const char *name, @@ -1210,6 +1214,8 @@ scd_kick_the_loop (void) if (ret == 0) log_error ("SetEvent for scd_kick_the_loop failed: %s\n", w32_strerror (-1)); +#elif defined(HAVE_PSELECT_NO_EINTR) + write (notify_fd, "", 1); #else ret = kill (main_thread_pid, SIGCONT); if (ret < 0) @@ -1241,6 +1247,17 @@ handle_connections (int listen_fd) #else int signo; #endif +#ifdef HAVE_PSELECT_NO_EINTR + int pipe_fd[2]; + + ret = gnupg_create_pipe (pipe_fd); + if (ret) + { + log_error ("pipe creation failed: %s\n", gpg_strerror (ret)); + return; + } + notify_fd = pipe_fd[1]; +#endif ret = npth_attr_init(&tattr); if (ret) @@ -1298,6 +1315,7 @@ handle_connections (int listen_fd) for (;;) { int periodical_check; + int max_fd = nfd; if (shutdown_pending) { @@ -1326,8 +1344,14 @@ handle_connections (int listen_fd) thus a simple assignment is fine to copy the entire set. */ read_fdset = fdset; +#ifdef HAVE_PSELECT_NO_EINTR + FD_SET (pipe_fd[0], &read_fdset); + if (max_fd < pipe_fd[0]) + max_fd = pipe_fd[0]; +#endif + #ifndef HAVE_W32_SYSTEM - ret = npth_pselect (nfd+1, &read_fdset, NULL, NULL, t, + ret = npth_pselect (max_fd+1, &read_fdset, NULL, NULL, t, npth_sigev_sigmask ()); saved_errno = errno; @@ -1353,6 +1377,15 @@ handle_connections (int listen_fd) /* Timeout. Will be handled when calculating the next timeout. */ continue; +#ifdef HAVE_PSELECT_NO_EINTR + if (FD_ISSET (pipe_fd[0], &read_fdset)) + { + char buf[256]; + + read (pipe_fd[0], buf, sizeof buf); + } +#endif + if (listen_fd != -1 && FD_ISSET (listen_fd, &read_fdset)) { ctrl_t ctrl; @@ -1393,6 +1426,10 @@ handle_connections (int listen_fd) #ifdef HAVE_W32_SYSTEM if (the_event != INVALID_HANDLE_VALUE) CloseHandle (the_event); +#endif +#ifdef HAVE_PSELECT_NO_EINTR + close (pipe_fd[0]); + close (pipe_fd[1]); #endif cleanup (); log_info (_("%s %s stopped\n"), strusage(11), strusage(13)); From e0658b19d93b38ed9ebd07734c4678acdde1607d Mon Sep 17 00:00:00 2001 From: Andre Heinecke Date: Fri, 9 Feb 2018 09:45:28 +0100 Subject: [PATCH 05/25] doc: Add compliance de-vs to gpgsm in vsnfd.prf * doc/examples/vsnfd.prf: Set complaince mode for gpgsm. --- doc/examples/vsnfd.prf | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/examples/vsnfd.prf b/doc/examples/vsnfd.prf index e8732de00..1dc21e0a7 100644 --- a/doc/examples/vsnfd.prf +++ b/doc/examples/vsnfd.prf @@ -6,6 +6,7 @@ default-new-key-algo rsa3072/cert,sign+rsa3072/encr [gpgsm] enable-crl-checks +compliance de-vs [gpg-agent] enable-extended-key-format From 0a3bec2c2525935362f87dce93d7df2c8d498498 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Mon, 12 Feb 2018 18:56:58 +0900 Subject: [PATCH 06/25] scd: Fix handling for Data Object with no data. * scd/app-openpgp.c (get_cached_data): Return NULL for Data Object with no data. -- When GET_DATA returns no data with success (90 00), this routine firstly returned buffer with length zero, and secondly (with cache) returned NULL, which is inconsistent. Now, it returns NULL for both cases. Signed-off-by: NIIBE Yutaka --- scd/app-openpgp.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index c9f2840e6..5b1b0d339 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -348,7 +348,8 @@ get_cached_data (app_t app, int tag, err = iso7816_get_data (app->slot, exmode, tag, &p, &len); if (err) return err; - *result = p; + if (len) + *result = p; *resultlen = len; /* Check whether we should cache this object. */ @@ -370,7 +371,10 @@ get_cached_data (app_t app, int tag, c = xtrymalloc (sizeof *c + len); if (c) { - memcpy (c->data, p, len); + if (len) + memcpy (c->data, p, len); + else + xfree (p); c->length = len; c->tag = tag; c->next = app->app_local->cache; From 25f3b69129015c54392636818c8846e236f5cb2c Mon Sep 17 00:00:00 2001 From: Arnaud Fontaine Date: Thu, 8 Feb 2018 19:03:08 +0100 Subject: [PATCH 07/25] scd: Improve KDF-DO support * scd/app-openpgp.c (pin2hash_if_kdf): Check the content of KDF DO. -- Length check added by gniibe. Signed-off-by: Arnaud Fontaine --- scd/app-openpgp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index 5b1b0d339..f3065edf0 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -2072,7 +2072,8 @@ pin2hash_if_kdf (app_t app, int chvno, char *pinvalue, int *r_pinlen) size_t buflen; if (app->app_local->extcap.kdf_do - && (relptr = get_one_do (app, 0x00F9, &buffer, &buflen, NULL))) + && (relptr = get_one_do (app, 0x00F9, &buffer, &buflen, NULL)) + && buflen == 110 && (buffer[2] == 0x03)) { char *salt; unsigned long s2k_count; From f19ff78f0fbfc2793d8a9ab0173486bf712871ac Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Wed, 14 Feb 2018 12:21:23 +0100 Subject: [PATCH 08/25] common: Use new function to print status strings. * common/asshelp2.c (vprint_assuan_status_strings): New. (print_assuan_status_strings): New. * agent/command.c (agent_write_status): Replace by call to new function. * dirmngr/server.c (dirmngr_status): Ditto. * g13/server.c (g13_status): Ditto. * g13/sh-cmd.c (g13_status): Ditto. * sm/server.c (gpgsm_status2): Ditto. * scd/command.c (send_status_info): Bump up N. -- This fixes a potential overflow if LFs are passed to the status string functions. This is actually not the case and would be wrong because neither the truncating in libassuan or our escaping is not the Right Thing. In any case the functions need to be more robust and comply to the promised interface. Thus the code has been factored out to a helper function and N has been bumped up correctly and checked in all cases. For some uses this changes the behaviour in the error case (i.e. CR or LF passed): It will now always be C-escaped and not passed to libassuan which would truncate the line at the first LF. Reported-by: private_pers --- agent/command.c | 43 +++++--------------------------- common/asshelp.h | 7 ++++++ common/asshelp2.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++ dirmngr/server.c | 19 +------------- g13/server.c | 21 +++------------- g13/sh-cmd.c | 28 +++------------------ scd/command.c | 4 ++- sm/server.c | 21 +++------------- 8 files changed, 90 insertions(+), 116 deletions(-) diff --git a/agent/command.c b/agent/command.c index 0916f886a..3a547ffaa 100644 --- a/agent/command.c +++ b/agent/command.c @@ -293,50 +293,19 @@ parse_keygrip (assuan_context_t ctx, const char *string, unsigned char *buf) /* Write an Assuan status line. KEYWORD is the first item on the - status line. The following arguments are all separated by a space - in the output. The last argument must be a NULL. Linefeeds and - carriage returns characters (which are not allowed in an Assuan - status line) are silently quoted in C-style. */ + * status line. The following arguments are all separated by a space + * in the output. The last argument must be a NULL. Linefeeds and + * carriage returns characters (which are not allowed in an Assuan + * status line) are silently quoted in C-style. */ gpg_error_t agent_write_status (ctrl_t ctrl, const char *keyword, ...) { - gpg_error_t err = 0; + gpg_error_t err; va_list arg_ptr; - const char *text; assuan_context_t ctx = ctrl->server_local->assuan_ctx; - char buf[950], *p; - size_t n; va_start (arg_ptr, keyword); - - p = buf; - n = 0; - while ( (text = va_arg (arg_ptr, const char *)) ) - { - if (n) - { - *p++ = ' '; - n++; - } - for ( ; *text && n < DIM (buf)-3; n++, text++) - { - if (*text == '\n') - { - *p++ = '\\'; - *p++ = 'n'; - } - else if (*text == '\r') - { - *p++ = '\\'; - *p++ = 'r'; - } - else - *p++ = *text; - } - } - *p = 0; - err = assuan_write_status (ctx, keyword, buf); - + err = vprint_assuan_status_strings (ctx, keyword, arg_ptr); va_end (arg_ptr); return err; } diff --git a/common/asshelp.h b/common/asshelp.h index f169d8774..bf1bd1705 100644 --- a/common/asshelp.h +++ b/common/asshelp.h @@ -93,5 +93,12 @@ gpg_error_t vprint_assuan_status (assuan_context_t ctx, const char *format, va_list arg_ptr) GPGRT_ATTR_PRINTF(3,0); +gpg_error_t vprint_assuan_status_strings (assuan_context_t ctx, + const char *keyword, + va_list arg_ptr); +gpg_error_t print_assuan_status_strings (assuan_context_t ctx, + const char *keyword, + ...) GPGRT_ATTR_SENTINEL(1); + #endif /*GNUPG_COMMON_ASSHELP_H*/ diff --git a/common/asshelp2.c b/common/asshelp2.c index f85c1e67e..0a7c4549d 100644 --- a/common/asshelp2.c +++ b/common/asshelp2.c @@ -71,3 +71,66 @@ print_assuan_status (assuan_context_t ctx, va_end (arg_ptr); return err; } + + +/* Helper function to print a list of strings as an assuan status + * line. KEYWORD is the first item on the status line. ARG_PTR is a + * list of strings which are all separated by a space in the output. + * The last argument must be a NULL. Linefeeds and carriage returns + * characters (which are not allowed in an Assuan status line) are + * silently quoted in C-style. */ +gpg_error_t +vprint_assuan_status_strings (assuan_context_t ctx, + const char *keyword, va_list arg_ptr) +{ + gpg_error_t err = 0; + const char *text; + char buf[950], *p; + size_t n; + + p = buf; + n = 0; + while ((text = va_arg (arg_ptr, const char *)) && n < DIM (buf)-3 ) + { + if (n) + { + *p++ = ' '; + n++; + } + for ( ; *text && n < DIM (buf)-3; n++, text++) + { + if (*text == '\n') + { + *p++ = '\\'; + *p++ = 'n'; + n++; + } + else if (*text == '\r') + { + *p++ = '\\'; + *p++ = 'r'; + n++; + } + else + *p++ = *text; + } + } + *p = 0; + err = assuan_write_status (ctx, keyword, buf); + + return err; +} + + +/* See vprint_assuan_status_strings. */ +gpg_error_t +print_assuan_status_strings (assuan_context_t ctx, const char *keyword, ...) +{ + va_list arg_ptr; + gpg_error_t err; + + va_start (arg_ptr, keyword); + err = vprint_assuan_status_strings (ctx, keyword, arg_ptr); + va_end (arg_ptr); + return err; +} diff --git a/dirmngr/server.c b/dirmngr/server.c index ab2ca852f..60d980211 100644 --- a/dirmngr/server.c +++ b/dirmngr/server.c @@ -2834,30 +2834,13 @@ dirmngr_status (ctrl_t ctrl, const char *keyword, ...) { gpg_error_t err = 0; va_list arg_ptr; - const char *text; assuan_context_t ctx; va_start (arg_ptr, keyword); if (ctrl->server_local && (ctx = ctrl->server_local->assuan_ctx)) { - char buf[950], *p; - size_t n; - - p = buf; - n = 0; - while ( (text = va_arg (arg_ptr, const char *)) ) - { - if (n) - { - *p++ = ' '; - n++; - } - for ( ; *text && n < DIM (buf)-2; n++) - *p++ = *text++; - } - *p = 0; - err = assuan_write_status (ctx, keyword, buf); + err = vprint_assuan_status_strings (ctx, keyword, arg_ptr); } va_end (arg_ptr); diff --git a/g13/server.c b/g13/server.c index bbe42d4f6..defde6c02 100644 --- a/g13/server.c +++ b/g13/server.c @@ -34,6 +34,7 @@ #include "mount.h" #include "suspend.h" #include "../common/server-help.h" +#include "../common/asshelp.h" #include "../common/call-gpg.h" @@ -737,24 +738,8 @@ g13_status (ctrl_t ctrl, int no, ...) } else { - assuan_context_t ctx = ctrl->server_local->assuan_ctx; - char buf[950], *p; - size_t n; - - p = buf; - n = 0; - while ( (text = va_arg (arg_ptr, const char *)) ) - { - if (n) - { - *p++ = ' '; - n++; - } - for ( ; *text && n < DIM (buf)-2; n++) - *p++ = *text++; - } - *p = 0; - err = assuan_write_status (ctx, get_status_string (no), buf); + err = vprint_assuan_status_strings (ctrl->server_local->assuan_ctx, + get_status_string (no), arg_ptr); } va_end (arg_ptr); diff --git a/g13/sh-cmd.c b/g13/sh-cmd.c index b57369d9c..791e3b7f4 100644 --- a/g13/sh-cmd.c +++ b/g13/sh-cmd.c @@ -28,6 +28,7 @@ #include "g13-syshelp.h" #include #include "../common/i18n.h" +#include "../common/asshelp.h" #include "keyblob.h" @@ -904,34 +905,13 @@ sh_encrypt_keyblob (ctrl_t ctrl, const void *keyblob, size_t keybloblen, gpg_error_t g13_status (ctrl_t ctrl, int no, ...) { - gpg_error_t err = 0; + gpg_error_t err; va_list arg_ptr; - const char *text; va_start (arg_ptr, no); - if (1) - { - assuan_context_t ctx = ctrl->server_local->assuan_ctx; - char buf[950], *p; - size_t n; - - p = buf; - n = 0; - while ( (text = va_arg (arg_ptr, const char *)) ) - { - if (n) - { - *p++ = ' '; - n++; - } - for ( ; *text && n < DIM (buf)-2; n++) - *p++ = *text++; - } - *p = 0; - err = assuan_write_status (ctx, get_status_string (no), buf); - } - + err = vprint_assuan_status_strings (ctrl->server_local->assuan_ctx, + get_status_string (no), arg_ptr); va_end (arg_ptr); return err; } diff --git a/scd/command.c b/scd/command.c index 6bcbce4fc..701151894 100644 --- a/scd/command.c +++ b/scd/command.c @@ -1848,7 +1848,8 @@ send_status_info (ctrl_t ctrl, const char *keyword, ...) p = buf; n = 0; - while ( (value = va_arg (arg_ptr, const unsigned char *)) ) + while ( (value = va_arg (arg_ptr, const unsigned char *)) + && n < DIM (buf)-2 ) { valuelen = va_arg (arg_ptr, size_t); if (!valuelen) @@ -1865,6 +1866,7 @@ send_status_info (ctrl_t ctrl, const char *keyword, ...) { sprintf (p, "%%%02X", *value); p += 3; + n += 2; } else if (*value == ' ') *p++ = '+'; diff --git a/sm/server.c b/sm/server.c index 568e51b17..721f3faf0 100644 --- a/sm/server.c +++ b/sm/server.c @@ -31,6 +31,7 @@ #include #include "../common/sysutils.h" #include "../common/server-help.h" +#include "../common/asshelp.h" #define set_error(e,t) assuan_set_error (ctx, gpg_error (e), (t)) @@ -1426,24 +1427,8 @@ gpgsm_status2 (ctrl_t ctrl, int no, ...) } else { - assuan_context_t ctx = ctrl->server_local->assuan_ctx; - char buf[950], *p; - size_t n; - - p = buf; - n = 0; - while ( (text = va_arg (arg_ptr, const char *)) ) - { - if (n) - { - *p++ = ' '; - n++; - } - for ( ; *text && n < DIM (buf)-2; n++) - *p++ = *text++; - } - *p = 0; - err = assuan_write_status (ctx, get_status_string (no), buf); + err = vprint_assuan_status_strings (ctrl->server_local->assuan_ctx, + get_status_string (no), arg_ptr); } va_end (arg_ptr); From 29aac7798085ee38da5107698618890ae7593c96 Mon Sep 17 00:00:00 2001 From: Katsuhiro Ueno Date: Wed, 7 Feb 2018 18:46:54 +0900 Subject: [PATCH 09/25] sm: Fix a wrong key parameter in an exported private key file * sm/export.c (sexp_to_kparms): Fix the computation of array[6], which must be 'd mod (q-1)' but was 'p mod (q-1)'. -- This bug is not serious but makes some consistency checks fail. For example, 'openssl rsa -check' reports the following error: $ gpgsm --out my.key --export-secret-key-raw 0xXXXXXXXX $ openssl rsa -check -noout -inform DER -in my.key RSA key error: dmq1 not congruent to d -- Let me(wk) add this: This bug was introduced with Fixes-commit: 91056b1976bfb7b755e53b1302f4ede2b5cbc05d right at the start of GnuPG 2.1 in July 2010. Before that (in 2.0) we used gpg-protect-tool which got it right. We probably never noticed this because gpgsm, and maybe other tools too, fix things up during import. Signed-off-by: Werner Koch --- sm/export.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sm/export.c b/sm/export.c index 29a5ac32e..a8c9a4afc 100644 --- a/sm/export.c +++ b/sm/export.c @@ -603,7 +603,7 @@ sexp_to_kparms (gcry_sexp_t sexp) array[6] = gcry_mpi_snew (0); /* compute d mod (p-1) */ gcry_mpi_sub_ui (array[6], array[4], 1); - gcry_mpi_mod (array[6], array[3], array[6]); + gcry_mpi_mod (array[6], array[2], array[6]); return array; } From 80719612b7e92aff5887f2a68d550a24f350722c Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Wed, 14 Feb 2018 14:54:51 +0100 Subject: [PATCH 10/25] sm: Fix minor memory leak in --export-p12. * sm/export.c (gpgsm_p12_export): Free KEYGRIP. Signed-off-by: Werner Koch --- sm/export.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sm/export.c b/sm/export.c index a8c9a4afc..7bea9ccc5 100644 --- a/sm/export.c +++ b/sm/export.c @@ -479,6 +479,7 @@ gpgsm_p12_export (ctrl_t ctrl, const char *name, estream_t stream, int rawmode) leave: gnupg_ksba_destroy_writer (b64writer); ksba_cert_release (cert); + xfree (keygrip); xfree (desc); keydb_release (hd); } From df97fe24807826ddc2af0e45e416fb81c5666f88 Mon Sep 17 00:00:00 2001 From: Katsuhiro Ueno Date: Wed, 7 Feb 2018 18:52:37 +0900 Subject: [PATCH 11/25] agent: Avoid appending a '\0' byte to the response of READKEY * agent/command.c (cmd_readkey): Set pkbuflen to the length of the output without an extra '\0' byte. --- agent/command.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/agent/command.c b/agent/command.c index 3a547ffaa..f9bc6ca96 100644 --- a/agent/command.c +++ b/agent/command.c @@ -1031,7 +1031,8 @@ cmd_readkey (assuan_context_t ctx, char *line) rc = gpg_error_from_syserror (); else { - gcry_sexp_sprint (s_pkey, GCRYSEXP_FMT_CANON, pkbuf, pkbuflen); + pkbuflen = gcry_sexp_sprint (s_pkey, GCRYSEXP_FMT_CANON, + pkbuf, pkbuflen); rc = assuan_send_data (ctx, pkbuf, pkbuflen); } } From ca138d5bf36accde2fd755249b470a8dc8743c95 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 15 Feb 2018 14:22:06 +0900 Subject: [PATCH 12/25] gpg: Fix reversed messages for --only-sign-text-ids. * g10/keyedit.c (keyedit_menu): Fix messages. -- GnuPG-bug-id: 3787 Fixes-commit: a74aeb5dae1f673fcd98b39a6a0496f3c622709a Signed-off-by: NIIBE Yutaka --- g10/keyedit.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/g10/keyedit.c b/g10/keyedit.c index 4acb2de5f..17cf7d6ea 100644 --- a/g10/keyedit.c +++ b/g10/keyedit.c @@ -1664,11 +1664,11 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr, if (opt.only_sign_text_ids) result = cpr_get_answer_is_yes ("keyedit.sign_all.okay", - _("Really sign all user IDs? (y/N) ")); + _("Really sign all text user IDs? (y/N) ")); else result = cpr_get_answer_is_yes ("keyedit.sign_all.okay", - _("Really sign all text user IDs? (y/N) ")); + _("Really sign all user IDs? (y/N) ")); if (! result) { From 5e3679ae395e7a7e44f218f07bbe487429f1b279 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Thu, 15 Feb 2018 11:17:28 +0100 Subject: [PATCH 13/25] kbx: Fix detection of corrupted keyblocks on 32 bit systems. * kbx/keybox-search.c (blob_cmp_fpr): Avoid overflow in OFF+LEN checking. (blob_cmp_fpr_part): Ditto. (blob_cmp_name): Ditto. (blob_cmp_mail): Ditto. (blob_x509_has_grip): Ditto. (keybox_get_keyblock): Check OFF and LEN using a 64 bit var. (keybox_get_cert): Ditto. -- On most 32 bit systems size_t is 32 bit and thus the check size_t cert_off = get32 (buffer+8); size_t cert_len = get32 (buffer+12); if (cert_off+cert_len > length) return gpg_error (GPG_ERR_TOO_SHORT); does not work as intended for all supplied values. The simplest solution here is to cast them to 64 bit. In general it will be better to avoid size_t at all and work with uint64_t. We did not do this in the past because uint64_t was not universally available. GnuPG-bug-id: 3770 Signed-off-by: Werner Koch --- kbx/keybox-search.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/kbx/keybox-search.c b/kbx/keybox-search.c index a5fc7fa9d..e309cce98 100644 --- a/kbx/keybox-search.c +++ b/kbx/keybox-search.c @@ -247,7 +247,7 @@ blob_cmp_fpr (KEYBOXBLOB blob, const unsigned char *fpr) if (keyinfolen < 28) return 0; /* invalid blob */ pos = 20; - if (pos + keyinfolen*nkeys > length) + if (pos + (uint64_t)keyinfolen*nkeys > (uint64_t)length) return 0; /* out of bounds */ for (idx=0; idx < nkeys; idx++) @@ -279,7 +279,7 @@ blob_cmp_fpr_part (KEYBOXBLOB blob, const unsigned char *fpr, if (keyinfolen < 28) return 0; /* invalid blob */ pos = 20; - if (pos + keyinfolen*nkeys > length) + if (pos + (uint64_t)keyinfolen*nkeys > (uint64_t)length) return 0; /* out of bounds */ for (idx=0; idx < nkeys; idx++) @@ -313,7 +313,7 @@ blob_cmp_name (KEYBOXBLOB blob, int idx, if (keyinfolen < 28) return 0; /* invalid blob */ pos = 20 + keyinfolen*nkeys; - if (pos+2 > length) + if ((uint64_t)pos+2 > (uint64_t)length) return 0; /* out of bounds */ /*serial*/ @@ -340,7 +340,7 @@ blob_cmp_name (KEYBOXBLOB blob, int idx, mypos += idx*uidinfolen; off = get32 (buffer+mypos); len = get32 (buffer+mypos+4); - if (off+len > length) + if ((uint64_t)off+(uint64_t)len > (uint64_t)length) return 0; /* error: better stop here out of bounds */ if (len < 1) continue; /* empty name */ @@ -439,7 +439,7 @@ blob_cmp_mail (KEYBOXBLOB blob, const char *name, size_t namelen, int substr, mypos += idx*uidinfolen; off = get32 (buffer+mypos); len = get32 (buffer+mypos+4); - if (off+len > length) + if ((uint64_t)off+(uint64_t)len > (uint64_t)length) return 0; /* error: better stop here - out of bounds */ if (x509) { @@ -522,7 +522,7 @@ blob_x509_has_grip (KEYBOXBLOB blob, const unsigned char *grip) return 0; /* Too short. */ cert_off = get32 (buffer+8); cert_len = get32 (buffer+12); - if (cert_off+cert_len > length) + if ((uint64_t)cert_off+(uint64_t)cert_len > (uint64_t)length) return 0; /* Too short. */ rc = ksba_reader_new (&reader); @@ -1097,7 +1097,7 @@ keybox_get_keyblock (KEYBOX_HANDLE hd, iobuf_t *r_iobuf, return gpg_error (GPG_ERR_TOO_SHORT); image_off = get32 (buffer+8); image_len = get32 (buffer+12); - if (image_off+image_len > length) + if ((uint64_t)image_off+(uint64_t)image_len > (uint64_t)length) return gpg_error (GPG_ERR_TOO_SHORT); err = _keybox_get_flag_location (buffer, length, KEYBOX_FLAG_SIG_INFO, @@ -1139,7 +1139,7 @@ keybox_get_cert (KEYBOX_HANDLE hd, ksba_cert_t *r_cert) return gpg_error (GPG_ERR_TOO_SHORT); cert_off = get32 (buffer+8); cert_len = get32 (buffer+12); - if (cert_off+cert_len > length) + if ((uint64_t)cert_off+(uint64_t)cert_len > (uint64_t)length) return gpg_error (GPG_ERR_TOO_SHORT); rc = ksba_reader_new (&reader); From 7b928c256426c4ff3d2d883c163a9ff2afa221a6 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Mon, 19 Feb 2018 10:51:27 +0100 Subject: [PATCH 14/25] speedo: Add new option STATIC=1 -- This can be used to build GnuPG with static versions of the core gnupg libraries. For example: make -f build-aux/speedo.mk STATIC=1 SELFCHECK=0 \ INSTALL_PREFIX=/somewhere/gnupg22 native The SELFCHECK=0 is only needed to build from a non-released version. You don't need it with a released tarball. Signed-off-by: Werner Koch --- build-aux/speedo.mk | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/build-aux/speedo.mk b/build-aux/speedo.mk index 2b3b72b86..ce338dd2f 100644 --- a/build-aux/speedo.mk +++ b/build-aux/speedo.mk @@ -63,6 +63,7 @@ help: @echo 'You may append INSTALL_PREFIX= for native builds.' @echo 'Prepend TARGET with "git-" to build from GIT repos.' @echo 'Prepend TARGET with "this-" to build from the source tarball.' + @echo 'Use STATIC=1 to build with statically linked libraries.' @echo 'Use SELFCHECK=0 for a non-released version.' @echo 'Use CUSTOM_SWDB=1 for an already downloaded swdb.lst.' @@ -140,6 +141,9 @@ UPD_SWDB=0 # Set to 0 to skip the GnuPG version self-check SELFCHECK=1 +# Set to 1 to build with statically linked libraries. +STATIC=0 + # Set to the location of the directory with tarballs of # external packages. TARBALLS=$(shell pwd)/../tarballs @@ -208,8 +212,10 @@ speedo_spkgs += \ endif endif +ifeq ($(STATIC),0) speedo_spkgs += \ gpgme +endif ifeq ($(TARGETOS),w32) ifeq ($(WITH_GUI),1) @@ -461,6 +467,8 @@ speedo_pkg_gtk__tar = $(pkg2rep)/gtk+-$(gtk__ver).tar.xz # Package build options # +speedo_pkg_npth_configure = --enable-static + speedo_pkg_libgpg_error_configure = --enable-static speedo_pkg_w64_libgpg_error_configure = --enable-static @@ -471,8 +479,23 @@ speedo_pkg_libgcrypt_configure = --disable-static speedo_pkg_libksba_configure = --disable-static +speedo_pkg_ntbtls_configure = --enable-static + + +ifeq ($(STATIC),1) +speedo_pkg_npth_configure += --disable-shared + +speedo_pkg_libgpg_error_configure += --disable-shared + +speedo_pkg_libassuan_configure += --disable-shared + +speedo_pkg_libgcrypt_configure += --disable-shared + +speedo_pkg_libksba_configure += --disable-shared +endif + # For now we build ntbtls only static -speedo_pkg_ntbtls_configure = --enable-static --disable-shared +speedo_pkg_ntbtls_configure = --disable-shared ifeq ($(TARGETOS),w32) speedo_pkg_gnupg_configure = \ From fffefd3c98dfcd2c75c7572c4e6fb32b73de5978 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Tue, 20 Feb 2018 08:57:28 +0100 Subject: [PATCH 15/25] speedo: Use --enable-wks-tools for non-W32 builds. -- Signed-off-by: Werner Koch --- build-aux/speedo.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build-aux/speedo.mk b/build-aux/speedo.mk index ce338dd2f..320d4403d 100644 --- a/build-aux/speedo.mk +++ b/build-aux/speedo.mk @@ -502,7 +502,7 @@ speedo_pkg_gnupg_configure = \ --disable-g13 --enable-ntbtls \ --enable-build-timestamp else -speedo_pkg_gnupg_configure = --disable-g13 +speedo_pkg_gnupg_configure = --disable-g13 --enable-wks-tools endif speedo_pkg_gnupg_extracflags = -g From 1877603761911ea5b1c15f4aef11a2cf86a8682c Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Tue, 20 Feb 2018 09:00:00 +0100 Subject: [PATCH 16/25] wks: Support alternative submission address. * tools/gpg-wks.h (policy_flags_s): Add field 'submission_address'. * tools/wks-util.c (wks_parse_policy): Parse that field. (wks_free_policy): New. * tools/gpg-wks-client.c (command_send): Also try to take the submission-address from the policy file. Free POLICY. * tools/gpg-wks-server.c (process_new_key): Free POLICYBUF. (command_list_domains): Free POLICY. Signed-off-by: Werner Koch --- tools/gpg-wks-client.c | 48 ++++++++++++++++++++++++++++++------------ tools/gpg-wks-server.c | 4 ++++ tools/gpg-wks.h | 2 ++ tools/wks-util.c | 27 ++++++++++++++++++++++++ 4 files changed, 67 insertions(+), 14 deletions(-) diff --git a/tools/gpg-wks-client.c b/tools/gpg-wks-client.c index 73a8a1f43..b86491e7c 100644 --- a/tools/gpg-wks-client.c +++ b/tools/gpg-wks-client.c @@ -782,27 +782,19 @@ command_send (const char *fingerprint, const char *userid) err = 0; } else - err = wkd_get_submission_address (addrspec, &submission_to); - if (err) - { - log_error (_("error looking up submission address for domain '%s': %s\n"), - domain, gpg_strerror (err)); - if (gpg_err_code (err) == GPG_ERR_NO_DATA) - log_error (_("this domain probably doesn't support WKS.\n")); - goto leave; - } - log_info ("submitting request to '%s'\n", submission_to); - - /* Get the policy flags. */ - if (!fake_submission_addr) { + /* We first try to get the submission address from the policy + * file (this is the new method). If both are available we + * check that they match and print a warning if not. In the + * latter case we keep on using the one from the + * submission-address file. */ estream_t mbuf; err = wkd_get_policy_flags (addrspec, &mbuf); if (err && gpg_err_code (err) != GPG_ERR_NO_DATA) { log_error ("error reading policy flags for '%s': %s\n", - submission_to, gpg_strerror (err)); + domain, gpg_strerror (err)); goto leave; } if (mbuf) @@ -812,8 +804,35 @@ command_send (const char *fingerprint, const char *userid) if (err) goto leave; } + + err = wkd_get_submission_address (addrspec, &submission_to); + if (err && !policy.submission_address) + { + log_error (_("error looking up submission address for domain '%s'" + ": %s\n"), domain, gpg_strerror (err)); + if (gpg_err_code (err) == GPG_ERR_NO_DATA) + log_error (_("this domain probably doesn't support WKS.\n")); + goto leave; + } + + if (submission_to && policy.submission_address + && ascii_strcasecmp (submission_to, policy.submission_address)) + log_info ("Warning: different submission addresses (sa=%s, po=%s)\n", + submission_to, policy.submission_address); + + if (!submission_to) + { + submission_to = xtrystrdup (policy.submission_address); + if (!submission_to) + { + err = gpg_error_from_syserror (); + goto leave; + } + } } + log_info ("submitting request to '%s'\n", submission_to); + if (policy.auth_submit) log_info ("no confirmation required for '%s'\n", addrspec); @@ -1002,6 +1021,7 @@ command_send (const char *fingerprint, const char *userid) free_uidinfo_list (uidlist); es_fclose (keyenc); es_fclose (key); + wks_free_policy (&policy); xfree (addrspec); return err; } diff --git a/tools/gpg-wks-server.c b/tools/gpg-wks-server.c index 0b1d64261..008c26639 100644 --- a/tools/gpg-wks-server.c +++ b/tools/gpg-wks-server.c @@ -1135,6 +1135,8 @@ process_new_key (server_ctx_t ctx, estream_t key) char *fname = NULL; struct policy_flags_s policybuf; + memset (&policybuf, 0, sizeof policybuf); + /* First figure out the user id from the key. */ xfree (ctx->fpr); free_uidinfo_list (ctx->mboxes); @@ -1206,6 +1208,7 @@ process_new_key (server_ctx_t ctx, estream_t key) xfree (nonce); xfree (fname); xfree (dname); + wks_free_policy (&policybuf); return err; } @@ -1897,6 +1900,7 @@ command_list_domains (void) if (!memcmp (&empty_policy, &policy, sizeof policy)) log_error ("domain %s: empty policy file\n", domain); } + wks_free_policy (&policy); } diff --git a/tools/gpg-wks.h b/tools/gpg-wks.h index ece7add5f..1522b7288 100644 --- a/tools/gpg-wks.h +++ b/tools/gpg-wks.h @@ -60,6 +60,7 @@ struct /* The parsed policy flags. */ struct policy_flags_s { + char *submission_address; unsigned int mailbox_only : 1; unsigned int dane_only : 1; unsigned int auth_submit : 1; @@ -92,6 +93,7 @@ gpg_error_t wks_filter_uid (estream_t *r_newkey, estream_t key, 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); +void wks_free_policy (policy_flags_t policy); /*-- wks-receive.c --*/ diff --git a/tools/wks-util.c b/tools/wks-util.c index 889ca36dc..9c0f489a9 100644 --- a/tools/wks-util.c +++ b/tools/wks-util.c @@ -443,6 +443,7 @@ gpg_error_t wks_parse_policy (policy_flags_t flags, estream_t stream, int ignore_unknown) { enum tokens { + TOK_SUBMISSION_ADDRESS, TOK_MAILBOX_ONLY, TOK_DANE_ONLY, TOK_AUTH_SUBMIT, @@ -453,6 +454,7 @@ wks_parse_policy (policy_flags_t flags, estream_t stream, int ignore_unknown) const char *name; enum tokens token; } keywords[] = { + { "submission-address", TOK_SUBMISSION_ADDRESS }, { "mailbox-only", TOK_MAILBOX_ONLY }, { "dane-only", TOK_DANE_ONLY }, { "auth-submit", TOK_AUTH_SUBMIT }, @@ -519,6 +521,20 @@ wks_parse_policy (policy_flags_t flags, estream_t stream, int ignore_unknown) switch (keywords[i].token) { + case TOK_SUBMISSION_ADDRESS: + if (!value || !*value) + { + err = gpg_error (GPG_ERR_SYNTAX); + goto leave; + } + xfree (flags->submission_address); + flags->submission_address = xtrystrdup (value); + if (!flags->submission_address) + { + err = gpg_error_from_syserror (); + goto leave; + } + break; case TOK_MAILBOX_ONLY: flags->mailbox_only = 1; break; case TOK_DANE_ONLY: flags->dane_only = 1; break; case TOK_AUTH_SUBMIT: flags->auth_submit = 1; break; @@ -553,3 +569,14 @@ wks_parse_policy (policy_flags_t flags, estream_t stream, int ignore_unknown) return err; } + + +void +wks_free_policy (policy_flags_t policy) +{ + if (policy) + { + xfree (policy->submission_address); + memset (policy, 0, sizeof *policy); + } +} From ee474856ec16ff11d922d8503fb3ede77129c4aa Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Tue, 20 Feb 2018 11:45:58 +0100 Subject: [PATCH 17/25] wks: Implement server command --install-key. * tools/wks-util.c (wks_filter_uid): Add arg 'binary'. * tools/gpg-wks-server.c (main): Expect 2 args for --install-key. (write_to_file): New. (check_and_publish): Factor some code out to ... (compute_hu_fname): ... new. (command_install_key): Implement. Signed-off-by: Werner Koch --- doc/wks.texi | 12 ++- tools/gpg-wks-client.c | 2 +- tools/gpg-wks-server.c | 223 +++++++++++++++++++++++++++++++++++------ tools/gpg-wks.h | 2 +- tools/wks-util.c | 17 ++-- 5 files changed, 216 insertions(+), 40 deletions(-) diff --git a/doc/wks.texi b/doc/wks.texi index 7f7d515b7..2960c6717 100644 --- a/doc/wks.texi +++ b/doc/wks.texi @@ -181,6 +181,7 @@ Display a brief help page and exit. .RI [ options ] .B \-\-install-key .I file +.I user-id .br .B gpg-wks-server .RI [ options ] @@ -221,14 +222,17 @@ the process returns failure; to suppress the diagnostic, use option @option{-q}. More than one user-id can be given; see also option @option{with-file}. +The command @option{--install-key} manually installs a key into the +WKD. The arguments are a file with the keyblock and the user-id to +install. + The command @option{--remove-key} uninstalls a key from the WKD. The -process return success in this case; to also print a diagnostic, use -option @option{-v}. If the key is not installed a diagnostics is +process returns success in this case; to also print a diagnostic, use +option @option{-v}. If the key is not installed a diagnostic is printed and the process returns failure; to suppress the diagnostic, use option @option{-q}. -The commands @option{--install-key} and @option{--revoke-key} are not -yet functional. +The command @option{--revoke-key} is not yet functional. @mansect options diff --git a/tools/gpg-wks-client.c b/tools/gpg-wks-client.c index b86491e7c..3b19c765d 100644 --- a/tools/gpg-wks-client.c +++ b/tools/gpg-wks-client.c @@ -872,7 +872,7 @@ command_send (const char *fingerprint, const char *userid) estream_t newkey; es_rewind (key); - err = wks_filter_uid (&newkey, key, thisuid->uid); + err = wks_filter_uid (&newkey, key, thisuid->uid, 0); if (err) { log_error ("error filtering key: %s\n", gpg_strerror (err)); diff --git a/tools/gpg-wks-server.c b/tools/gpg-wks-server.c index 008c26639..e2b830648 100644 --- a/tools/gpg-wks-server.c +++ b/tools/gpg-wks-server.c @@ -1,5 +1,5 @@ /* gpg-wks-server.c - A server for the Web Key Service protocols. - * Copyright (C) 2016 Werner Koch + * Copyright (C) 2016, 2018 Werner Koch * Copyright (C) 2016 Bundesamt für Sicherheit in der Informationstechnik * * This file is part of GnuPG. @@ -20,7 +20,7 @@ /* The Web Key Service I-D defines an update protocol to store a * public key in the Web Key Directory. The current specification is - * draft-koch-openpgp-webkey-service-01.txt. + * draft-koch-openpgp-webkey-service-05.txt. */ #include @@ -154,7 +154,7 @@ static gpg_error_t command_receive_cb (void *opaque, const char *mediatype, estream_t fp, unsigned int flags); static gpg_error_t command_list_domains (void); -static gpg_error_t command_install_key (const char *fname); +static gpg_error_t command_install_key (const char *fname, const char *userid); static gpg_error_t command_remove_key (const char *mailaddr); static gpg_error_t command_revoke_key (const char *mailaddr); static gpg_error_t command_check_key (const char *mailaddr); @@ -376,9 +376,9 @@ main (int argc, char **argv) break; case aInstallKey: - if (argc != 1) - wrong_args ("--install-key FILE"); - err = command_install_key (*argv); + if (argc != 2) + wrong_args ("--install-key FILE USER-ID"); + err = command_install_key (*argv, argv[1]); break; case aRemoveKey: @@ -1339,6 +1339,81 @@ send_congratulation_message (const char *mbox, const char *keyfile) } +/* Write the content of SRC to the new file FNAME. */ +static gpg_error_t +write_to_file (estream_t src, const char *fname) +{ + gpg_error_t err; + estream_t dst; + char buffer[4096]; + size_t nread, written; + + dst = es_fopen (fname, "wb"); + if (!dst) + return gpg_error_from_syserror (); + + do + { + nread = es_fread (buffer, 1, sizeof buffer, src); + if (!nread) + break; + written = es_fwrite (buffer, 1, nread, dst); + if (written != nread) + break; + } + while (!es_feof (src) && !es_ferror (src) && !es_ferror (dst)); + if (!es_feof (src) || es_ferror (src) || es_ferror (dst)) + { + err = gpg_error_from_syserror (); + es_fclose (dst); + gnupg_remove (fname); + return err; + } + + if (es_fclose (dst)) + { + err = gpg_error_from_syserror (); + log_error ("error closing '%s': %s\n", fname, gpg_strerror (err)); + return err; + } + + return 0; +} + + +/* Compute the the full file name for the key with ADDRSPEC and return + * it at R_FNAME. */ +static gpg_error_t +compute_hu_fname (char **r_fname, const char *addrspec) +{ + gpg_error_t err; + char *hash; + const char *domain; + char sha1buf[20]; + + *r_fname = NULL; + + domain = strchr (addrspec, '@'); + if (!domain || !domain[1] || domain == addrspec) + return gpg_error (GPG_ERR_INV_ARG); + domain++; + + gcry_md_hash_buffer (GCRY_MD_SHA1, sha1buf, addrspec, domain - addrspec - 1); + hash = zb32_encode (sha1buf, 8*20); + if (!hash) + return gpg_error_from_syserror (); + + *r_fname = make_filename_try (opt.directory, domain, "hu", hash, NULL); + if (!*r_fname) + err = gpg_error_from_syserror (); + else + err = 0; + + xfree (hash); + return err; +} + + /* Check that we have send a request with NONCE and publish the key. */ static gpg_error_t check_and_publish (server_ctx_t ctx, const char *address, const char *nonce) @@ -1412,24 +1487,10 @@ check_and_publish (server_ctx_t ctx, const char *address, const char *nonce) goto leave; } - /* Hash user ID and create filename. */ - s = strchr (address, '@'); - log_assert (s); - gcry_md_hash_buffer (GCRY_MD_SHA1, shaxbuf, address, s - address); - hash = zb32_encode (shaxbuf, 8*20); - if (!hash) - { - err = gpg_error_from_syserror (); - goto leave; - } - - fnewname = make_filename_try (opt.directory, domain, "hu", hash, NULL); - if (!fnewname) - { - err = gpg_error_from_syserror (); - goto leave; - } + err = compute_hu_fname (&fnewname, address); + if (err) + goto leave; /* Publish. */ err = copy_key_as_binary (fname, fnewname, address); @@ -1935,16 +1996,122 @@ command_cron (void) } -/* Install a single key into the WKD by reading FNAME. */ +/* Install a single key into the WKD by reading FNAME and extracting + * USERID. */ static gpg_error_t -command_install_key (const char *fname) +command_install_key (const char *fname, const char *userid) { - (void)fname; - return gpg_error (GPG_ERR_NOT_IMPLEMENTED); + gpg_error_t err; + estream_t fp; + char *addrspec = NULL; + char *fpr = NULL; + uidinfo_list_t uidlist = NULL; + uidinfo_list_t uid, thisuid; + time_t thistime; + char *huname = NULL; + int any; + + fp = es_fopen (fname, "rb"); + if (!fp) + { + err = gpg_error_from_syserror (); + log_error ("error reading '%s': %s\n", fname, gpg_strerror (err)); + goto leave; + } + + addrspec = mailbox_from_userid (userid); + if (!addrspec) + { + log_error ("\"%s\" is not a proper mail address\n", userid); + err = gpg_error (GPG_ERR_INV_USER_ID); + goto leave; + } + + /* List the key so that we can figure out the newest UID with the + * requested addrspec. */ + err = wks_list_key (fp, &fpr, &uidlist); + if (err) + { + log_error ("error parsing key: %s\n", gpg_strerror (err)); + err = gpg_error (GPG_ERR_NO_PUBKEY); + goto leave; + } + thistime = 0; + thisuid = NULL; + any = 0; + for (uid = uidlist; uid; uid = uid->next) + { + if (!uid->mbox) + continue; /* Should not happen anyway. */ + if (ascii_strcasecmp (uid->mbox, addrspec)) + continue; /* Not the requested addrspec. */ + any = 1; + if (uid->created > thistime) + { + thistime = uid->created; + thisuid = uid; + } + } + if (!thisuid) + thisuid = uidlist; /* This is the case for a missing timestamp. */ + if (!any) + { + log_error ("public key in '%s' has no mail address '%s'\n", + fname, addrspec); + err = gpg_error (GPG_ERR_INV_USER_ID); + goto leave; + } + + if (opt.verbose) + log_info ("using key with user id '%s'\n", thisuid->uid); + + { + estream_t fp2; + + es_rewind (fp); + err = wks_filter_uid (&fp2, fp, thisuid->uid, 1); + if (err) + { + log_error ("error filtering key: %s\n", gpg_strerror (err)); + err = gpg_error (GPG_ERR_NO_PUBKEY); + goto leave; + } + es_fclose (fp); + fp = fp2; + } + + /* Hash user ID and create filename. */ + err = compute_hu_fname (&huname, addrspec); + if (err) + goto leave; + + /* Publish. */ + err = write_to_file (fp, huname); + if (err) + { + log_error ("copying key to '%s' failed: %s\n", huname,gpg_strerror (err)); + goto leave; + } + + /* Make sure it is world readable. */ + if (gnupg_chmod (huname, "-rwxr--r--")) + log_error ("can't set permissions of '%s': %s\n", + huname, gpg_strerror (gpg_err_code_from_syserror())); + + if (!opt.quiet) + log_info ("key %s published for '%s'\n", fpr, addrspec); + + leave: + xfree (huname); + free_uidinfo_list (uidlist); + xfree (fpr); + xfree (addrspec); + es_fclose (fp); + return err; } -/* Return the filename and optioanlly the addrspec for USERID at +/* Return the filename and optionally the addrspec for USERID at * R_FNAME and R_ADDRSPEC. R_ADDRSPEC might also be set on error. */ static gpg_error_t fname_from_userid (const char *userid, char **r_fname, char **r_addrspec) diff --git a/tools/gpg-wks.h b/tools/gpg-wks.h index 1522b7288..a5a73c575 100644 --- a/tools/gpg-wks.h +++ b/tools/gpg-wks.h @@ -89,7 +89,7 @@ void free_uidinfo_list (uidinfo_list_t list); 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); + const char *uid, int binary); 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/wks-util.c b/tools/wks-util.c index 9c0f489a9..33f1ae7dd 100644 --- a/tools/wks-util.c +++ b/tools/wks-util.c @@ -317,10 +317,13 @@ wks_list_key (estream_t key, char **r_fpr, uidinfo_list_t *r_mboxes) /* Run gpg as a filter on KEY and write the output to a new stream - * stored at R_NEWKEY. The new key will containn only the user id - * UID. Returns 0 on success. Only one key is expected in KEY. */ + * stored at R_NEWKEY. The new key will contain only the user id UID. + * Returns 0 on success. Only one key is expected in KEY. If BINARY + * is set the resulting key is returned as a binary (non-armored) + * keyblock. */ gpg_error_t -wks_filter_uid (estream_t *r_newkey, estream_t key, const char *uid) +wks_filter_uid (estream_t *r_newkey, estream_t key, const char *uid, + int binary) { gpg_error_t err; ccparray_t ccp; @@ -340,8 +343,9 @@ wks_filter_uid (estream_t *r_newkey, estream_t key, const char *uid) } /* Prefix the key with the MIME content type. */ - es_fputs ("Content-Type: application/pgp-keys\n" - "\n", newkey); + if (!binary) + es_fputs ("Content-Type: application/pgp-keys\n" + "\n", newkey); filterexp = es_bsprintf ("keep-uid=uid=%s", uid); if (!filterexp) @@ -361,7 +365,8 @@ wks_filter_uid (estream_t *r_newkey, estream_t key, const char *uid) ccparray_put (&ccp, "--batch"); ccparray_put (&ccp, "--status-fd=2"); ccparray_put (&ccp, "--always-trust"); - ccparray_put (&ccp, "--armor"); + if (!binary) + ccparray_put (&ccp, "--armor"); ccparray_put (&ccp, "--import-options=import-export"); ccparray_put (&ccp, "--import-filter"); ccparray_put (&ccp, filterexp); From 685a5e1558b2252ac895637fb857f6f7bb85ea7b Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Tue, 20 Feb 2018 15:23:19 +0100 Subject: [PATCH 18/25] wks: Add special mode to --install-key. * tools/gpg-wks-client.c (get_key_status_parm_s) (get_key_status_cb, get_key): Move to ... * tools/wks-util.c: ...here. (get_key): Rename to wks_get_key. * tools/gpg-wks-server.c: Include userids.h. (command_install_key): Allow use of a fingerprint. Signed-off-by: Werner Koch --- doc/wks.texi | 17 +++--- tools/gpg-wks-client.c | 117 +---------------------------------------- tools/gpg-wks-server.c | 37 +++++++++---- tools/gpg-wks.h | 2 + tools/wks-util.c | 114 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 153 insertions(+), 134 deletions(-) diff --git a/doc/wks.texi b/doc/wks.texi index 2960c6717..6d622828f 100644 --- a/doc/wks.texi +++ b/doc/wks.texi @@ -224,7 +224,9 @@ the process returns failure; to suppress the diagnostic, use option The command @option{--install-key} manually installs a key into the WKD. The arguments are a file with the keyblock and the user-id to -install. +install. If the first argument resembles a fingerprint the key is +taken from the current keyring; to force the use of a file, prefix the +first argument with "./". The command @option{--remove-key} uninstalls a key from the WKD. The process returns success in this case; to also print a diagnostic, use @@ -330,7 +332,7 @@ the submission address: @example $ gpg --batch --passphrase '' --quick-gen-key key-submission@@example.net - $ gpg --with-wkd-hash -K key-submission@@example.net + $ gpg -K key-submission@@example.net @end example The output of the last command looks similar to this: @@ -339,21 +341,16 @@ The output of the last command looks similar to this: sec rsa2048 2016-08-30 [SC] C0FCF8642D830C53246211400346653590B3795B uid [ultimate] key-submission@@example.net - bxzcxpxk8h87z1k7bzk86xn5aj47intu@@example.net ssb rsa2048 2016-08-30 [E] @end example -Take the hash of the string "key-submission", which is -"bxzcxpxk8h87z1k7bzk86xn5aj47intu" and manually publish that key: +Take the fingerprint from that output and manually publish the key: @example - $ gpg --export-options export-minimal --export \ - > -o /var/lib/gnupg/wks/example.net/hu/bxzcxpxk8h87z1k7bzk86xn5aj47intu \ - > key-submission@@example.new + $ gpg-wks-server --install-key C0FCF8642D830C53246211400346653590B3795B \ + > key-submission@@example.net @end example -Make sure that the created file is world readable. - Finally that submission address needs to be redirected to a script running @command{gpg-wks-server}. The @command{procmail} command can be used for this: Redirect the submission address to the user "webkey" diff --git a/tools/gpg-wks-client.c b/tools/gpg-wks-client.c index 3b19c765d..73945ff30 100644 --- a/tools/gpg-wks-client.c +++ b/tools/gpg-wks-client.c @@ -325,119 +325,6 @@ main (int argc, char **argv) -struct get_key_status_parm_s -{ - const char *fpr; - int found; - int count; -}; - -static void -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 (!strcmp (keyword, "EXPORTED")) - { - parm->count++; - if (!ascii_strcasecmp (args, parm->fpr)) - parm->found = 1; - } -} - - -/* Get a key by fingerprint from gpg's keyring and make sure that the - * 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. */ -static gpg_error_t -get_key (estream_t *r_key, const char *fingerprint, const char *addrspec, - int exact) -{ - gpg_error_t err; - ccparray_t ccp; - const char **argv = NULL; - estream_t key = NULL; - struct get_key_status_parm_s parm; - char *filterexp = NULL; - - memset (&parm, 0, sizeof parm); - - *r_key = NULL; - - key = es_fopenmem (0, "w+b"); - if (!key) - { - err = gpg_error_from_syserror (); - log_error ("error allocating memory buffer: %s\n", gpg_strerror (err)); - goto leave; - } - - /* Prefix the key with the MIME content type. */ - es_fputs ("Content-Type: application/pgp-keys\n" - "\n", key); - - filterexp = es_bsprintf ("keep-uid=%s=%s", exact? "uid":"mbox", 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) - ccparray_put (&ccp, "--quiet"); - else if (opt.verbose > 1) - ccparray_put (&ccp, "--verbose"); - 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"); - ccparray_put (&ccp, "--export-filter"); - ccparray_put (&ccp, filterexp); - ccparray_put (&ccp, "--export"); - ccparray_put (&ccp, "--"); - ccparray_put (&ccp, fingerprint); - - ccparray_put (&ccp, NULL); - argv = ccparray_get (&ccp, NULL); - if (!argv) - { - err = gpg_error_from_syserror (); - goto leave; - } - parm.fpr = fingerprint; - err = gnupg_exec_tool_stream (opt.gpg_program, argv, NULL, - NULL, key, - get_key_status_cb, &parm); - if (!err && parm.count > 1) - err = gpg_error (GPG_ERR_TOO_MANY); - else if (!err && !parm.found) - err = gpg_error (GPG_ERR_NOT_FOUND); - if (err) - { - log_error ("export failed: %s\n", gpg_strerror (err)); - goto leave; - } - - es_rewind (key); - *r_key = key; - key = NULL; - - leave: - es_fclose (key); - xfree (argv); - xfree (filterexp); - return err; -} - - /* Add the user id UID to the key identified by FINGERPRINT. */ static gpg_error_t add_user_id (const char *fingerprint, const char *uid) @@ -767,7 +654,7 @@ command_send (const char *fingerprint, const char *userid) err = gpg_error (GPG_ERR_INV_USER_ID); goto leave; } - err = get_key (&key, fingerprint, addrspec, 0); + err = wks_get_key (&key, fingerprint, addrspec, 0); if (err) goto leave; @@ -897,7 +784,7 @@ command_send (const char *fingerprint, const char *userid) * the key again. */ es_fclose (key); key = NULL; - err = get_key (&key, fingerprint, addrspec, 1); + err = wks_get_key (&key, fingerprint, addrspec, 1); if (err) goto leave; } diff --git a/tools/gpg-wks-server.c b/tools/gpg-wks-server.c index e2b830648..a5881557f 100644 --- a/tools/gpg-wks-server.c +++ b/tools/gpg-wks-server.c @@ -35,6 +35,7 @@ #include "../common/util.h" #include "../common/init.h" #include "../common/sysutils.h" +#include "../common/userids.h" #include "../common/ccparray.h" #include "../common/exectool.h" #include "../common/zb32.h" @@ -2002,7 +2003,8 @@ static gpg_error_t command_install_key (const char *fname, const char *userid) { gpg_error_t err; - estream_t fp; + KEYDB_SEARCH_DESC desc; + estream_t fp = NULL; char *addrspec = NULL; char *fpr = NULL; uidinfo_list_t uidlist = NULL; @@ -2011,14 +2013,6 @@ command_install_key (const char *fname, const char *userid) char *huname = NULL; int any; - fp = es_fopen (fname, "rb"); - if (!fp) - { - err = gpg_error_from_syserror (); - log_error ("error reading '%s': %s\n", fname, gpg_strerror (err)); - goto leave; - } - addrspec = mailbox_from_userid (userid); if (!addrspec) { @@ -2027,6 +2021,31 @@ command_install_key (const char *fname, const char *userid) goto leave; } + if (!classify_user_id (fname, &desc, 1) + && (desc.mode == KEYDB_SEARCH_MODE_FPR + || desc.mode == KEYDB_SEARCH_MODE_FPR20)) + { + /* FNAME looks like a fingerprint. Get the key from the + * standard keyring. */ + err = wks_get_key (&fp, fname, addrspec, 0); + if (err) + { + log_error ("error getting key '%s' (uid='%s'): %s\n", + fname, addrspec, gpg_strerror (err)); + goto leave; + } + } + else /* Take it from the file */ + { + fp = es_fopen (fname, "rb"); + if (!fp) + { + err = gpg_error_from_syserror (); + log_error ("error reading '%s': %s\n", fname, gpg_strerror (err)); + goto leave; + } + } + /* List the key so that we can figure out the newest UID with the * requested addrspec. */ err = wks_list_key (fp, &fpr, &uidlist); diff --git a/tools/gpg-wks.h b/tools/gpg-wks.h index a5a73c575..1b91b6504 100644 --- a/tools/gpg-wks.h +++ b/tools/gpg-wks.h @@ -86,6 +86,8 @@ typedef struct uidinfo_list_s *uidinfo_list_t; 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); 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, diff --git a/tools/wks-util.c b/tools/wks-util.c index 33f1ae7dd..3fd824c1a 100644 --- a/tools/wks-util.c +++ b/tools/wks-util.c @@ -132,6 +132,120 @@ free_uidinfo_list (uidinfo_list_t list) } + +struct get_key_status_parm_s +{ + const char *fpr; + int found; + int count; +}; + + +static void +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 (!strcmp (keyword, "EXPORTED")) + { + parm->count++; + if (!ascii_strcasecmp (args, parm->fpr)) + parm->found = 1; + } +} + +/* Get a key by fingerprint from gpg's keyring and make sure that the + * 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. */ +gpg_error_t +wks_get_key (estream_t *r_key, const char *fingerprint, const char *addrspec, + int exact) +{ + gpg_error_t err; + ccparray_t ccp; + const char **argv = NULL; + estream_t key = NULL; + struct get_key_status_parm_s parm; + char *filterexp = NULL; + + memset (&parm, 0, sizeof parm); + + *r_key = NULL; + + key = es_fopenmem (0, "w+b"); + if (!key) + { + err = gpg_error_from_syserror (); + log_error ("error allocating memory buffer: %s\n", gpg_strerror (err)); + goto leave; + } + + /* Prefix the key with the MIME content type. */ + es_fputs ("Content-Type: application/pgp-keys\n" + "\n", key); + + filterexp = es_bsprintf ("keep-uid=%s=%s", exact? "uid":"mbox", 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) + ccparray_put (&ccp, "--quiet"); + else if (opt.verbose > 1) + ccparray_put (&ccp, "--verbose"); + 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"); + ccparray_put (&ccp, "--export-filter"); + ccparray_put (&ccp, filterexp); + ccparray_put (&ccp, "--export"); + ccparray_put (&ccp, "--"); + ccparray_put (&ccp, fingerprint); + + ccparray_put (&ccp, NULL); + argv = ccparray_get (&ccp, NULL); + if (!argv) + { + err = gpg_error_from_syserror (); + goto leave; + } + parm.fpr = fingerprint; + err = gnupg_exec_tool_stream (opt.gpg_program, argv, NULL, + NULL, key, + get_key_status_cb, &parm); + if (!err && parm.count > 1) + err = gpg_error (GPG_ERR_TOO_MANY); + else if (!err && !parm.found) + err = gpg_error (GPG_ERR_NOT_FOUND); + if (err) + { + log_error ("export failed: %s\n", gpg_strerror (err)); + goto leave; + } + + es_rewind (key); + *r_key = key; + key = NULL; + + leave: + es_fclose (key); + xfree (argv); + xfree (filterexp); + return err; +} + + /* Helper for wks_list_key and wks_filter_uid. */ static void From c4d8efb8942fe1d5644c5b2cb8bc73a06ac500df Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Wed, 21 Feb 2018 10:17:20 +0100 Subject: [PATCH 19/25] doc: Add extra hint on unattended use of gpg. -- --- doc/gpg.texi | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/doc/gpg.texi b/doc/gpg.texi index 927d77d35..ddebc692c 100644 --- a/doc/gpg.texi +++ b/doc/gpg.texi @@ -3781,6 +3781,19 @@ If you are going to verify detached signatures, make sure that the program knows about it; either give both filenames on the command line or use @samp{-} to specify STDIN. +For scripted or other unattended use of @command{gpg} make sure to use +the machine-parseable interface and not the default interface which is +intended for direct use by humans. The machine-parseable interface +provides a stable and well documented API independent of the locale or +future changes of @command{gpg}. To enable this interface use the +options @option{--with-colons} and @option{--status-fd}. For certain +operations the option @option{--command-fd} may come handy too. See +this man page and the file @file{DETAILS} for the specification of the +interface. Note that the GnuPG ``info'' pages as well as the PDF +version of the GnuPG manual features a chapter on unattended use of +GnuPG. As an alternative the library @command{GPGME} can be used as a +high-level abstraction on top of that interface. + @mansect interoperability @chapheading INTEROPERABILITY WITH OTHER OPENPGP PROGRAMS From a70502e93f06b394760fe671913c283018718ced Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Wed, 21 Feb 2018 17:56:40 +0100 Subject: [PATCH 20/25] build: Update autogen.sh -- Now installs a git patch prefix. Signed-off-by: Werner Koch --- autogen.rc | 2 ++ autogen.sh | 7 +++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/autogen.rc b/autogen.rc index 68359299b..3ea03e08f 100644 --- a/autogen.rc +++ b/autogen.rc @@ -1,5 +1,7 @@ # autogen.sh configuration for GnuPG -*- sh -*- +display_name=GnuPG + #version_parts=3 case "$myhost:$myhostsub" in diff --git a/autogen.sh b/autogen.sh index e5ba5bf05..b23855061 100755 --- a/autogen.sh +++ b/autogen.sh @@ -1,6 +1,6 @@ #! /bin/sh # autogen.sh -# Copyright (C) 2003, 2014, 2017 g10 Code GmbH +# Copyright (C) 2003, 2014, 2017, 2018 g10 Code GmbH # # This file is free software; as a special exception the author gives # unlimited permission to copy and/or distribute it, with or without @@ -15,7 +15,7 @@ # configure it for the respective package. It is maintained as part of # GnuPG and source copied by other packages. # -# Version: 2017-01-17 +# Version: 2018-02-21 configure_ac="configure.ac" @@ -467,6 +467,9 @@ EOF EOF $CP build-aux/git-hooks/commit-msg .git/hooks/commit-msg chmod +x .git/hooks/commit-msg + if [ x"${display_name}" != x ]; then + git config format.subjectPrefix "PATCH ${display_name}" + fi fi fi From cf006cbf733889c20ee313ff93fce838ca77229e Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Thu, 22 Feb 2018 10:24:24 +0100 Subject: [PATCH 21/25] doc: Clarify -export-secret-key-p12 -- GnuPG-bug-id: 3788 Signed-off-by: Werner Koch --- doc/gpgsm.texi | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/gpgsm.texi b/doc/gpgsm.texi index 5d79ce54e..cd2a74165 100644 --- a/doc/gpgsm.texi +++ b/doc/gpgsm.texi @@ -257,10 +257,10 @@ fingerprints or keygrips. @item --export-secret-key-p12 @var{key-id} @opindex export-secret-key-p12 Export the private key and the certificate identified by @var{key-id} in -a PKCS#12 format. When used with the @code{--armor} option a few +using the PKCS#12 format. When used with the @code{--armor} option a few informational lines are prepended to the output. Note, that the PKCS#12 -format is not very secure and this command is only provided if there is -no other way to exchange the private key. (@xref{option --p12-charset}.) +format is not very secure and proper transport security should be used +to convey the exported key. (@xref{option --p12-charset}.) @item --export-secret-key-p8 @var{key-id} @itemx --export-secret-key-raw @var{key-id} From 88e766d3915c2919e9968148ebb30463d4a673e4 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 26 Sep 2017 11:02:05 +0900 Subject: [PATCH 22/25] g10: Select a secret key by checking availability under gpg-agent. * g10/getkey.c (finish_lookup): Add WANT_SECRET argument to confirm by agent_probe_secret_key. (get_pubkey_fromfile, lookup): Supply WANT_SECRET argument. -- GnuPG-bug-id: 1967 Signed-off-by: NIIBE Yutaka (cherry picked from commit 0a76611294998ae34b9d9ebde484ef8ad3a9a3a6) --- g10/getkey.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/g10/getkey.c b/g10/getkey.c index e31e0232e..dabd052e0 100644 --- a/g10/getkey.c +++ b/g10/getkey.c @@ -144,7 +144,7 @@ static int lookup (ctrl_t ctrl, getkey_ctx_t ctx, int want_secret, kbnode_t *ret_keyblock, kbnode_t *ret_found_key); static kbnode_t finish_lookup (kbnode_t keyblock, unsigned int req_usage, int want_exact, - unsigned int *r_flags); + int want_secret, unsigned int *r_flags); static void print_status_key_considered (kbnode_t keyblock, unsigned int flags); @@ -1743,7 +1743,7 @@ get_pubkey_fromfile (ctrl_t ctrl, PKT_public_key *pk, const char *fname) /* Warning: node flag bits 0 and 1 should be preserved by * merge_selfsigs. FIXME: Check whether this still holds. */ merge_selfsigs (ctrl, keyblock); - found_key = finish_lookup (keyblock, pk->req_usage, 0, &infoflags); + found_key = finish_lookup (keyblock, pk->req_usage, 0, 0, &infoflags); print_status_key_considered (keyblock, infoflags); if (found_key) pk_from_block (pk, keyblock, found_key); @@ -3494,7 +3494,7 @@ merge_selfsigs (ctrl_t ctrl, kbnode_t keyblock) */ static kbnode_t finish_lookup (kbnode_t keyblock, unsigned int req_usage, int want_exact, - unsigned int *r_flags) + int want_secret, unsigned int *r_flags) { kbnode_t k; @@ -3636,6 +3636,13 @@ finish_lookup (kbnode_t keyblock, unsigned int req_usage, int want_exact, continue; } + if (want_secret && agent_probe_secret_key (NULL, pk)) + { + if (DBG_LOOKUP) + log_debug ("\tno secret key\n"); + continue; + } + if (DBG_LOOKUP) log_debug ("\tsubkey might be fine\n"); /* In case a key has a timestamp of 0 set, we make sure @@ -3823,7 +3830,7 @@ lookup (ctrl_t ctrl, getkey_ctx_t ctx, int want_secret, * merge_selfsigs. */ merge_selfsigs (ctrl, keyblock); found_key = finish_lookup (keyblock, ctx->req_usage, ctx->exact, - &infoflags); + want_secret, &infoflags); print_status_key_considered (keyblock, infoflags); if (found_key) { From b375d50ee4ce52c9b0f0855ec155be027642fb05 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Thu, 22 Feb 2018 14:23:01 +0100 Subject: [PATCH 23/25] gpg: Don't let gpg return failure on an invalid packet in a keyblock. * g10/keydb.c (parse_keyblock_image): Use log_info instead of log_error for skipped packets. * g10/keyring.c (keyring_get_keyblock): Ditto. -- log_info should be sufficient and makes this more robust. Some tools (e.g. Enigmail) are too picky on return codes from gpg. Signed-off-by: Werner Koch --- g10/keydb.c | 5 +---- g10/keyring.c | 4 ++-- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/g10/keydb.c b/g10/keydb.c index 58a14a83d..03fadfd54 100644 --- a/g10/keydb.c +++ b/g10/keydb.c @@ -1269,10 +1269,7 @@ parse_keyblock_image (iobuf_t iobuf, int pk_no, int uid_no, break; /* Allowed per RFC. */ default: - /* Note that can't allow ring trust packets here and some of - the other GPG specific packets don't make sense either. */ - log_error ("skipped packet of type %d in keybox\n", - (int)pkt->pkttype); + log_info ("skipped packet of type %d in keybox\n", (int)pkt->pkttype); free_packet(pkt, &parsectx); init_packet(pkt); continue; diff --git a/g10/keyring.c b/g10/keyring.c index 50f1b824c..25ef50747 100644 --- a/g10/keyring.c +++ b/g10/keyring.c @@ -459,8 +459,8 @@ keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb) break; /* Allowed by us. */ default: - log_error ("skipped packet of type %d in keyring\n", - (int)pkt->pkttype); + log_info ("skipped packet of type %d in keyring\n", + (int)pkt->pkttype); free_packet(pkt, &parsectx); init_packet(pkt); continue; From 9581a65ccc10daededc05c55391a04022f794a4a Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Thu, 22 Feb 2018 15:32:36 +0100 Subject: [PATCH 24/25] Release 2.2.5 Signed-off-by: Werner Koch --- AUTHORS | 10 +++++----- NEWS | 45 +++++++++++++++++++++++++++++++++++++++++- README | 4 ++-- common/argparse.c | 2 +- common/w32info-rc.h.in | 2 +- configure.ac | 4 ++-- 6 files changed, 55 insertions(+), 12 deletions(-) diff --git a/AUTHORS b/AUTHORS index d27dfb6f9..473b94c45 100644 --- a/AUTHORS +++ b/AUTHORS @@ -15,9 +15,9 @@ copyrightable year that would otherwise be listed individually. List of Copyright holders ========================= - Copyright (C) 1997-2017 Werner Koch - Copyright (C) 1994-2017 Free Software Foundation, Inc. - Copyright (C) 2003-2013,2015-2017 g10 Code GmbH + Copyright (C) 1997-2018 Werner Koch + Copyright (C) 1994-2018 Free Software Foundation, Inc. + Copyright (C) 2003-2013,2015-2018 g10 Code GmbH Copyright (C) 2002 Klarälvdalens Datakonsult AB Copyright (C) 1995-1997, 2000-2007 Ulrich Drepper Copyright (C) 1994 X Consortium @@ -91,8 +91,8 @@ domain. ========= - Copyright 1998-2017 Free Software Foundation, Inc. - Copyright 1997-2017 Werner Koch + Copyright 1998-2018 Free Software Foundation, Inc. + Copyright 1997-2018 Werner Koch This file is free software; as a special exception the author gives unlimited permission to copy and/or distribute it, with or without diff --git a/NEWS b/NEWS index f924176ab..5c8b499e0 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,47 @@ -Noteworthy changes in version 2.2.5 (unreleased) +Noteworthy changes in version 2.2.5 (2018-02-22) ------------------------------------------------ + * gpg: Allow the use of the "cv25519" and "ed25519" short names in + addition to the canonical curve names in --batch --gen-key. + + * gpg: Make sure to print all secret keys with option --list-only + and --decrypt. [#3718] + + * gpg: Fix the use of future-default with --quick-add-key for + signing keys. [#3747] + + * gpg: Select a secret key by checking availability under gpg-agent. + [#1967] + + * gpg: Fix reversed prompt texts for --only-sign-text-ids. [#3787] + + * gpg,gpgsm: Fix detection of bogus keybox blobs on 32 bit systems. + [#3770] + + * gpgsm: Fix regression since 2.1 in --export-secret-key-raw which + got $d mod (q-1)$ wrong. Note that most tools automatically fixup + that parameter anyway. + + * ssh: Fix a regression in getting the client'd PID on *BSD and + macOS. + + * scd: Support the KDF Data Object of the OpenPGP card 3.3. [#3152] + + * scd: Fix a regression in the internal CCID driver for certain card + readers. [#3508] + + * scd: Fix a problem on NetBSD killing scdaemon on gpg-agent + shutdown. [#3778] + + * dirmngr: Improve returned error description on failure of DNS + resolving. [#3756] + + * wks: Implement command --install-key for gpg-wks-server. + + * Add option STATIC=1 to the Speedo build system to allow a build + with statically linked versions of the core GnuPG libraries. Also + use --enable-wks-tools by default by Speedo builds for Unix. + Noteworthy changes in version 2.2.4 (2017-12-20) ------------------------------------------------ @@ -32,6 +73,8 @@ Noteworthy changes in version 2.2.4 (2017-12-20) * New configure option --enable-run-gnupg-user-socket to first try a socket directory which is not removed by systemd at session end. + See-also: gnupg-announce/2017q4/000419.html + Noteworthy changes in version 2.2.3 (2017-11-20) ------------------------------------------------ diff --git a/README b/README index 23f705a60..d46efd934 100644 --- a/README +++ b/README @@ -2,8 +2,8 @@ ========================= Version 2.2 - Copyright 1997-2017 Werner Koch - Copyright 1998-2017 Free Software Foundation, Inc. + Copyright 1997-2018 Werner Koch + Copyright 1998-2018 Free Software Foundation, Inc. * INTRODUCTION diff --git a/common/argparse.c b/common/argparse.c index f5e4ceb9d..90d0ff7f3 100644 --- a/common/argparse.c +++ b/common/argparse.c @@ -71,7 +71,7 @@ #else /* Used by GnuPG */ # define ARGPARSE_GPL_VERSION 3 -# define ARGPARSE_CRIGHT_STR "Copyright (C) 2017 Free Software Foundation, Inc." +# define ARGPARSE_CRIGHT_STR "Copyright (C) 2018 Free Software Foundation, Inc." #endif /*GNUPG_MAJOR_VERSION*/ diff --git a/common/w32info-rc.h.in b/common/w32info-rc.h.in index 4e46b978a..2ff686321 100644 --- a/common/w32info-rc.h.in +++ b/common/w32info-rc.h.in @@ -29,4 +29,4 @@ built on @BUILD_HOSTNAME@ at @BUILD_TIMESTAMP@\0" #define W32INFO_PRODUCTVERSION "@VERSION@\0" #define W32INFO_LEGALCOPYRIGHT "Copyright \xa9 \ -2017 Free Software Foundation, Inc.\0" +2018 Free Software Foundation, Inc.\0" diff --git a/configure.ac b/configure.ac index bdb614696..e24936179 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ # configure.ac - for GnuPG 2.1 -# Copyright (C) 1998-2017 Free Software Foundation, Inc. -# Copyright (C) 1998-2017 Werner Koch +# Copyright (C) 1998-2018 Free Software Foundation, Inc. +# Copyright (C) 1998-2018 Werner Koch # # This file is part of GnuPG. # From 59ee87aae8743dd99690b6026566e104de6e24d6 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Thu, 22 Feb 2018 16:10:20 +0100 Subject: [PATCH 25/25] Post release updates. -- --- NEWS | 4 ++++ configure.ac | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 5c8b499e0..4a4f87e28 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,7 @@ +Noteworthy changes in version 2.2.6 (unreleased) +------------------------------------------------ + + Noteworthy changes in version 2.2.5 (2018-02-22) ------------------------------------------------ diff --git a/configure.ac b/configure.ac index e24936179..8252db9a1 100644 --- a/configure.ac +++ b/configure.ac @@ -28,7 +28,7 @@ min_automake_version="1.14" m4_define([mym4_package],[gnupg]) m4_define([mym4_major], [2]) m4_define([mym4_minor], [2]) -m4_define([mym4_micro], [5]) +m4_define([mym4_micro], [6]) # To start a new development series, i.e a new major or minor number # you need to mark an arbitrary commit before the first beta release