diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index 21beb29c7..a1964ece8 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -136,6 +136,7 @@ enum cmd_and_opt_values oDisableCheckOwnSocket, oS2KCount, oAutoExpandSecmem, + oListenBacklog, oWriteEnvFile }; @@ -255,6 +256,8 @@ static ARGPARSE_OPTS opts[] = { ARGPARSE_op_u (oAutoExpandSecmem, "auto-expand-secmem", "@"), + ARGPARSE_s_i (oListenBacklog, "listen-backlog", "@"), + /* Dummy options for backward compatibility. */ ARGPARSE_o_s (oWriteEnvFile, "write-env-file", "@"), ARGPARSE_s_n (oUseStandardSocket, "use-standard-socket", "@"), @@ -371,6 +374,10 @@ static assuan_sock_nonce_t socket_nonce_extra; static assuan_sock_nonce_t socket_nonce_browser; static assuan_sock_nonce_t socket_nonce_ssh; +/* Value for the listen() backlog argument. We use the same value for + * all sockets - 64 is on current Linux half of the default maximum. + * Let's try this as default. Change at runtime with --listen-backlog. */ +static int listen_backlog = 64; /* Default values for options passed to the pinentry. */ static char *default_display; @@ -1245,6 +1252,10 @@ main (int argc, char **argv ) (unsigned int)pargs.r.ret_ulong, 0); break; + case oListenBacklog: + listen_backlog = pargs.r.ret_int; + break; + case oDebugQuickRandom: /* Only used by the first stage command line parser. */ break; @@ -2248,9 +2259,10 @@ create_server_socket (char *name, int primary, int cygwin, log_error (_("can't set permissions of '%s': %s\n"), unaddr->sun_path, strerror (errno)); - if (listen (FD2INT(fd), 5 ) == -1) + if (listen (FD2INT(fd), listen_backlog ) == -1) { - log_error (_("listen() failed: %s\n"), strerror (errno)); + log_error ("listen(fd,%d) failed: %s\n", + listen_backlog, strerror (errno)); *name = 0; /* Inhibit removal of the socket by cleanup(). */ assuan_sock_close (fd); xfree (unaddr); diff --git a/common/homedir.c b/common/homedir.c index 149e1ec62..a598900b9 100644 --- a/common/homedir.c +++ b/common/homedir.c @@ -541,7 +541,17 @@ _gnupg_socketdir_internal (int skip_checks, unsigned *r_info) #else /* Unix and stat(2) available. */ - static const char * const bases[] = { "/run", "/var/run", NULL}; + static const char * const bases[] = { +#ifdef USE_RUN_GNUPG_USER_SOCKET + "/run/gnupg", +#endif + "/run", +#ifdef USE_RUN_GNUPG_USER_SOCKET + "/var/run/gnupg", +#endif + "/var/run", + NULL + }; int i; struct stat sb; char prefix[13 + 1 + 20 + 6 + 1]; @@ -559,7 +569,7 @@ _gnupg_socketdir_internal (int skip_checks, unsigned *r_info) * as a background process with no (desktop) user logged in. Thus * we better don't do that. */ - /* Check whether we have a /run/user dir. */ + /* Check whether we have a /run/[gnupg/]user dir. */ for (i=0; bases[i]; i++) { snprintf (prefix, sizeof prefix, "%s/user/%u", diff --git a/configure.ac b/configure.ac index 98d18e455..311979ab8 100644 --- a/configure.ac +++ b/configure.ac @@ -1738,6 +1738,22 @@ if test x"$gnupg_builddir_envvar" = x"yes"; then [This is only used with "make distcheck"]) fi + +# +# To avoid problems with systemd cleaning up the /run/user directory, +# this option will make GnuPG try to use /run/gnupg/user as socket dir +# before /run/user +# +AC_ARG_ENABLE(run-gnupg-user-socket, + AC_HELP_STRING([--enable-run-gnupg-user-socket], + [try /run/gnupg/user for sockets prior to /run/user]), + use_run_gnupg_user_socket=$enableval) +if test x"$use_run_gnupg_user_socket" = x"yes"; then + AC_DEFINE(USE_RUN_GNUPG_USER_SOCKET, 1, + [If defined try /run/gnupg/user before /run/user]) +fi + + # # Decide what to build # diff --git a/dirmngr/dirmngr.c b/dirmngr/dirmngr.c index 25716e2b5..00caf0686 100644 --- a/dirmngr/dirmngr.c +++ b/dirmngr/dirmngr.c @@ -151,6 +151,7 @@ enum cmd_and_opt_values { oResolverTimeout, oConnectTimeout, oConnectQuickTimeout, + oListenBacklog, aTest }; @@ -256,6 +257,7 @@ static ARGPARSE_OPTS opts[] = { ARGPARSE_s_i (oResolverTimeout, "resolver-timeout", "@"), ARGPARSE_s_i (oConnectTimeout, "connect-timeout", "@"), ARGPARSE_s_i (oConnectQuickTimeout, "connect-quick-timeout", "@"), + ARGPARSE_s_i (oListenBacklog, "listen-backlog", "@"), ARGPARSE_group (302,N_("@\n(See the \"info\" manual for a complete listing " "of all commands and options)\n")), @@ -296,6 +298,10 @@ static const char *redir_socket_name; POSIX systems). */ static assuan_sock_nonce_t socket_nonce; +/* Value for the listen() backlog argument. + * Change at runtime with --listen-backlog. */ +static int listen_backlog = 64; + /* Only if this flag has been set will we remove the socket file. */ static int cleanup_socket; @@ -1019,6 +1025,10 @@ main (int argc, char **argv) case oSocketName: socket_name = pargs.r.ret_str; break; + case oListenBacklog: + listen_backlog = pargs.r.ret_int; + break; + default : pargs.err = configfp? 1:2; break; } } @@ -1271,9 +1281,10 @@ main (int argc, char **argv) log_error (_("can't set permissions of '%s': %s\n"), serv_addr.sun_path, strerror (errno)); - if (listen (FD2INT (fd), 5) == -1) + if (listen (FD2INT (fd), listen_backlog) == -1) { - log_error (_("listen() failed: %s\n"), strerror (errno)); + log_error ("listen(fd,%d) failed: %s\n", + listen_backlog, strerror (errno)); assuan_sock_close (fd); dirmngr_exit (1); } diff --git a/doc/dirmngr.texi b/doc/dirmngr.texi index 9654a0e74..800955c52 100644 --- a/doc/dirmngr.texi +++ b/doc/dirmngr.texi @@ -282,6 +282,10 @@ default values are 15 and 2 seconds. Note that the timeout values are for each connection attempt; the connection code will attempt to connect all addresses listed for a server. +@item --listen-backlog @var{n} +@opindex listen-backlog +Set the size of the queue for pending connections. The default is 64. + @item --allow-version-check @opindex allow-version-check Allow Dirmngr to connect to @code{https://versions.gnupg.org} to get diff --git a/doc/examples/gpgconf.conf b/doc/examples/gpgconf.conf index f40160249..95e463b6e 100644 --- a/doc/examples/gpgconf.conf +++ b/doc/examples/gpgconf.conf @@ -31,8 +31,7 @@ # # Example file: #========== -# :staff gpg-agent allow-mark-trusted [change] -# gpg-agent min-passphrase-len 6 +# :staff gpg-agent min-passphrase-len 6 [change] # # * gpg-agent min-passphrase-len [no-change] 8 # gpg-agent min-passphrase-nonalpha [no-change] 1 @@ -42,9 +41,9 @@ # gpg-agent enforce-passphrase-constraints [no-change] # gpg-agent max-cache-ttl [no-change] 10800 # gpg-agent max-cache-ttl-ssh [no-change] 10800 -# gpg-agent allow-mark-trusted [default] -# gpg-agent allow-mark-trusted [no-change] # gpgsm enable-ocsp +# gpg compliance [no-change] +# gpgsm compliance [no-change] #=========== # All users in the group "staff" are allowed to change the value for # --allow-mark-trusted; gpgconf's default is not to allow a change diff --git a/doc/gpg-agent.texi b/doc/gpg-agent.texi index 65df9708b..3e8bd894d 100644 --- a/doc/gpg-agent.texi +++ b/doc/gpg-agent.texi @@ -563,6 +563,9 @@ Ignore requests to change the current @code{tty} or X window system's @code{DISPLAY} variable respectively. This is useful to lock the pinentry to pop up at the @code{tty} or display you started the agent. +@item --listen-backlog @var{n} +@opindex listen-backlog +Set the size of the queue for pending connections. The default is 64. @anchor{option --extra-socket} @item --extra-socket @var{name} diff --git a/doc/scdaemon.texi b/doc/scdaemon.texi index 4c6bb93b6..a9e6d1e7a 100644 --- a/doc/scdaemon.texi +++ b/doc/scdaemon.texi @@ -236,6 +236,12 @@ a list of categories see the Libassuan manual. Don't detach the process from the console. This is mainly useful for debugging. +@item --listen-backlog @var{n} +@opindex listen-backlog +Set the size of the queue for pending connections. The default is 64. +This option has an effect only if @option{--multi-server} is also +used. + @item --log-file @var{file} @opindex log-file Append all logging output to @var{file}. This is very helpful in diff --git a/g10/cipher.c b/g10/cipher.c index 7031d93eb..b950d0c3f 100644 --- a/g10/cipher.c +++ b/g10/cipher.c @@ -1,6 +1,6 @@ /* cipher.c - En-/De-ciphering filter - * Copyright (C) 1998, 1999, 2000, 2001, 2003, - * 2006, 2009 Free Software Foundation, Inc. + * Copyright (C) 1998-2003, 2006, 2009 Free Software Foundation, Inc. + * Copyright (C) 1998-2003, 2006, 2009, 2017 Werner koch * * This file is part of GnuPG. * @@ -16,6 +16,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, see . + * SPDX-License-Identifier: GPL-3.0+ */ #include @@ -39,124 +40,145 @@ static void -write_header( cipher_filter_context_t *cfx, IOBUF a ) +write_header (cipher_filter_context_t *cfx, iobuf_t a) { - gcry_error_t err; - PACKET pkt; - PKT_encrypted ed; - byte temp[18]; - unsigned int blocksize; - unsigned int nprefix; + gcry_error_t err; + PACKET pkt; + PKT_encrypted ed; + byte temp[18]; + unsigned int blocksize; + unsigned int nprefix; - blocksize = openpgp_cipher_get_algo_blklen (cfx->dek->algo); - if ( blocksize < 8 || blocksize > 16 ) - log_fatal("unsupported blocksize %u\n", blocksize ); - - memset( &ed, 0, sizeof ed ); - ed.len = cfx->datalen; - ed.extralen = blocksize+2; - ed.new_ctb = !ed.len; - if( cfx->dek->use_mdc ) { - ed.mdc_method = DIGEST_ALGO_SHA1; - gcry_md_open (&cfx->mdc_hash, DIGEST_ALGO_SHA1, 0); - if ( DBG_HASHING ) - gcry_md_debug (cfx->mdc_hash, "creatmdc"); - } + blocksize = openpgp_cipher_get_algo_blklen (cfx->dek->algo); + if ( blocksize < 8 || blocksize > 16 ) + log_fatal ("unsupported blocksize %u\n", blocksize); + memset (&ed, 0, sizeof ed); + ed.len = cfx->datalen; + ed.extralen = blocksize + 2; + ed.new_ctb = !ed.len; + if (cfx->dek->use_mdc) { - char buf[20]; - - snprintf (buf, sizeof buf, "%d %d", ed.mdc_method, cfx->dek->algo); - write_status_text (STATUS_BEGIN_ENCRYPTION, buf); + ed.mdc_method = DIGEST_ALGO_SHA1; + gcry_md_open (&cfx->mdc_hash, DIGEST_ALGO_SHA1, 0); + if (DBG_HASHING) + gcry_md_debug (cfx->mdc_hash, "creatmdc"); + } + else if (!opt.no_mdc_warn) + { + log_info ("WARNING: " + "encrypting without integrity protection is dangerous\n"); } - init_packet( &pkt ); - pkt.pkttype = cfx->dek->use_mdc? PKT_ENCRYPTED_MDC : PKT_ENCRYPTED; - pkt.pkt.encrypted = &ed; - if( build_packet( a, &pkt )) - log_bug("build_packet(ENCR_DATA) failed\n"); - nprefix = blocksize; - gcry_randomize (temp, nprefix, GCRY_STRONG_RANDOM ); - temp[nprefix] = temp[nprefix-2]; - temp[nprefix+1] = temp[nprefix-1]; - print_cipher_algo_note( cfx->dek->algo ); - err = openpgp_cipher_open (&cfx->cipher_hd, - cfx->dek->algo, - GCRY_CIPHER_MODE_CFB, - (GCRY_CIPHER_SECURE - | ((cfx->dek->use_mdc || cfx->dek->algo >= 100)? - 0 : GCRY_CIPHER_ENABLE_SYNC))); - if (err) { - /* We should never get an error here cause we already checked, - * that the algorithm is available. */ - BUG(); + write_status_printf (STATUS_BEGIN_ENCRYPTION, "%d %d", + ed.mdc_method, cfx->dek->algo); + + init_packet (&pkt); + pkt.pkttype = cfx->dek->use_mdc? PKT_ENCRYPTED_MDC : PKT_ENCRYPTED; + pkt.pkt.encrypted = &ed; + if (build_packet( a, &pkt)) + log_bug ("build_packet(ENCR_DATA) failed\n"); + nprefix = blocksize; + gcry_randomize (temp, nprefix, GCRY_STRONG_RANDOM ); + temp[nprefix] = temp[nprefix-2]; + temp[nprefix+1] = temp[nprefix-1]; + print_cipher_algo_note (cfx->dek->algo); + err = openpgp_cipher_open (&cfx->cipher_hd, + cfx->dek->algo, + GCRY_CIPHER_MODE_CFB, + (GCRY_CIPHER_SECURE + | ((cfx->dek->use_mdc || cfx->dek->algo >= 100)? + 0 : GCRY_CIPHER_ENABLE_SYNC))); + if (err) + { + /* We should never get an error here cause we already checked, + * that the algorithm is available. */ + BUG(); } + /* log_hexdump ("thekey", cfx->dek->key, cfx->dek->keylen); */ + gcry_cipher_setkey (cfx->cipher_hd, cfx->dek->key, cfx->dek->keylen); + gcry_cipher_setiv (cfx->cipher_hd, NULL, 0); + /* log_hexdump ("prefix", temp, nprefix+2); */ + if (cfx->mdc_hash) /* Hash the "IV". */ + gcry_md_write (cfx->mdc_hash, temp, nprefix+2 ); + gcry_cipher_encrypt (cfx->cipher_hd, temp, nprefix+2, NULL, 0); + gcry_cipher_sync (cfx->cipher_hd); + iobuf_write (a, temp, nprefix+2); -/* log_hexdump( "thekey", cfx->dek->key, cfx->dek->keylen );*/ - gcry_cipher_setkey( cfx->cipher_hd, cfx->dek->key, cfx->dek->keylen ); - gcry_cipher_setiv( cfx->cipher_hd, NULL, 0 ); -/* log_hexdump( "prefix", temp, nprefix+2 ); */ - if (cfx->mdc_hash) /* Hash the "IV". */ - gcry_md_write (cfx->mdc_hash, temp, nprefix+2 ); - gcry_cipher_encrypt (cfx->cipher_hd, temp, nprefix+2, NULL, 0); - gcry_cipher_sync (cfx->cipher_hd); - iobuf_write(a, temp, nprefix+2); - cfx->header=1; + cfx->short_blklen_warn = (blocksize < 16); + cfx->short_blklen_count = nprefix+2; + + cfx->wrote_header = 1; } - -/**************** - * This filter is used to en/de-cipher data with a conventional algorithm +/* + * This filter is used to en/de-cipher data with a symmetric algorithm */ int -cipher_filter( void *opaque, int control, - IOBUF a, byte *buf, size_t *ret_len) +cipher_filter (void *opaque, int control, iobuf_t a, byte *buf, size_t *ret_len) { - size_t size = *ret_len; - cipher_filter_context_t *cfx = opaque; - int rc=0; + cipher_filter_context_t *cfx = opaque; + size_t size = *ret_len; + int rc = 0; - if( control == IOBUFCTRL_UNDERFLOW ) { /* decrypt */ - rc = -1; /* not yet used */ + if (control == IOBUFCTRL_UNDERFLOW) /* decrypt */ + { + rc = -1; /* not yet used */ } - else if( control == IOBUFCTRL_FLUSH ) { /* encrypt */ - log_assert(a); - if( !cfx->header ) { - write_header( cfx, a ); + else if (control == IOBUFCTRL_FLUSH) /* encrypt */ + { + log_assert (a); + if (!cfx->wrote_header) + write_header (cfx, a); + if (cfx->mdc_hash) + gcry_md_write (cfx->mdc_hash, buf, size); + gcry_cipher_encrypt (cfx->cipher_hd, buf, size, NULL, 0); + if (cfx->short_blklen_warn) + { + cfx->short_blklen_count += size; + if (cfx->short_blklen_count > (150 * 1024 * 1024)) + { + log_info ("WARNING: encrypting more than %d MiB with algorithm " + "%s should be avoided\n", 150, + openpgp_cipher_algo_name (cfx->dek->algo)); + cfx->short_blklen_warn = 0; /* Don't show again. */ + } + } + + rc = iobuf_write (a, buf, size); + } + else if (control == IOBUFCTRL_FREE) + { + if (cfx->mdc_hash) + { + byte *hash; + int hashlen = gcry_md_get_algo_dlen (gcry_md_get_algo(cfx->mdc_hash)); + byte temp[22]; + + log_assert (hashlen == 20); + /* We must hash the prefix of the MDC packet here. */ + temp[0] = 0xd3; + temp[1] = 0x14; + gcry_md_putc (cfx->mdc_hash, temp[0]); + gcry_md_putc (cfx->mdc_hash, temp[1]); + + gcry_md_final (cfx->mdc_hash); + hash = gcry_md_read (cfx->mdc_hash, 0); + memcpy(temp+2, hash, 20); + gcry_cipher_encrypt (cfx->cipher_hd, temp, 22, NULL, 0); + gcry_md_close (cfx->mdc_hash); cfx->mdc_hash = NULL; + if (iobuf_write( a, temp, 22)) + log_error ("writing MDC packet failed\n"); } - if (cfx->mdc_hash) - gcry_md_write (cfx->mdc_hash, buf, size); - gcry_cipher_encrypt (cfx->cipher_hd, buf, size, NULL, 0); - rc = iobuf_write( a, buf, size ); - } - else if( control == IOBUFCTRL_FREE ) { - if( cfx->mdc_hash ) { - byte *hash; - int hashlen = gcry_md_get_algo_dlen (gcry_md_get_algo - (cfx->mdc_hash)); - byte temp[22]; - log_assert( hashlen == 20 ); - /* We must hash the prefix of the MDC packet here. */ - temp[0] = 0xd3; - temp[1] = 0x14; - gcry_md_putc (cfx->mdc_hash, temp[0]); - gcry_md_putc (cfx->mdc_hash, temp[1]); + gcry_cipher_close (cfx->cipher_hd); + } + else if (control == IOBUFCTRL_DESC) + { + mem2str (buf, "cipher_filter", *ret_len); + } - gcry_md_final (cfx->mdc_hash); - hash = gcry_md_read (cfx->mdc_hash, 0); - memcpy(temp+2, hash, 20); - gcry_cipher_encrypt (cfx->cipher_hd, temp, 22, NULL, 0); - gcry_md_close (cfx->mdc_hash); cfx->mdc_hash = NULL; - if( iobuf_write( a, temp, 22 ) ) - log_error("writing MDC packet failed\n" ); - } - gcry_cipher_close (cfx->cipher_hd); - } - else if( control == IOBUFCTRL_DESC ) { - mem2str (buf, "cipher_filter", *ret_len); - } - return rc; + return rc; } diff --git a/g10/export.c b/g10/export.c index 8f6371b30..c538dc1f1 100644 --- a/g10/export.c +++ b/g10/export.c @@ -1430,6 +1430,11 @@ print_pka_or_dane_records (iobuf_t out, kbnode_t keyblock, PKT_public_key *pk, char *hexfpr; hexfpr = hexfingerprint (pk, NULL, 0); + if (!hexfpr) + { + err = gpg_error_from_syserror (); + goto leave; + } hexdata = bin2hex (data, datalen, NULL); if (!hexdata) { diff --git a/g10/filter.h b/g10/filter.h index 275608d4a..9e4b1e538 100644 --- a/g10/filter.h +++ b/g10/filter.h @@ -92,10 +92,11 @@ typedef struct { DEK *dek; u32 datalen; gcry_cipher_hd_t cipher_hd; - int header; + unsigned int wrote_header : 1; + unsigned int short_blklen_warn : 1; + unsigned long short_blklen_count; gcry_md_hd_t mdc_hash; byte enchash[20]; - int create_mdc; /* flag will be set by the cipher filter */ } cipher_filter_context_t; diff --git a/g10/getkey.c b/g10/getkey.c index 0a741cb2d..dabd052e0 100644 --- a/g10/getkey.c +++ b/g10/getkey.c @@ -413,34 +413,35 @@ pubkeys_free (pubkey_t keys) } } + /* Returns all keys that match the search specification SEARCH_TERMS. - - This function also checks for and warns about duplicate entries in - the keydb, which can occur if the user has configured multiple - keyrings or keyboxes or if a keyring or keybox was corrupted. - - Note: SEARCH_TERMS will not be expanded (i.e., it may not be a - group). - - USE is the operation for which the key is required. It must be - either PUBKEY_USAGE_ENC, PUBKEY_USAGE_SIG, PUBKEY_USAGE_CERT or - PUBKEY_USAGE_AUTH. - - XXX: Currently, only PUBKEY_USAGE_ENC and PUBKEY_USAGE_SIG are - implemented. - - INCLUDE_UNUSABLE indicates whether disabled keys are allowed. - (Recipients specified with --encrypt-to and --hidden-encrypt-to may - be disabled. It is possible to edit disabled keys.) - - SOURCE is the context in which SEARCH_TERMS was specified, e.g., - "--encrypt-to", etc. If this function is called interactively, - then this should be NULL. - - If WARN_POSSIBLY_AMBIGUOUS is set, then emits a warning if the user - does not specify a long key id or a fingerprint. - - The results are placed in *KEYS. *KEYS must be NULL! */ + * + * This function also checks for and warns about duplicate entries in + * the keydb, which can occur if the user has configured multiple + * keyrings or keyboxes or if a keyring or keybox was corrupted. + * + * Note: SEARCH_TERMS will not be expanded (i.e., it may not be a + * group). + * + * USE is the operation for which the key is required. It must be + * either PUBKEY_USAGE_ENC, PUBKEY_USAGE_SIG, PUBKEY_USAGE_CERT or + * PUBKEY_USAGE_AUTH. + * + * INCLUDE_UNUSABLE indicates whether disabled keys are allowed. + * (Recipients specified with --encrypt-to and --hidden-encrypt-to may + * be disabled. It is possible to edit disabled keys.) + * + * SOURCE is the context in which SEARCH_TERMS was specified, e.g., + * "--encrypt-to", etc. If this function is called interactively, + * then this should be NULL. + * + * If WARN_POSSIBLY_AMBIGUOUS is set, then emits a warning if the user + * does not specify a long key id or a fingerprint. + * + * The results are placed in *KEYS. *KEYS must be NULL! + * + * Fixme: Currently, only PUBKEY_USAGE_ENC and PUBKEY_USAGE_SIG are + * implemented. */ gpg_error_t get_pubkeys (ctrl_t ctrl, char *search_terms, int use, int include_unusable, char *source, @@ -448,30 +449,23 @@ get_pubkeys (ctrl_t ctrl, pubkey_t *r_keys) { /* We show a warning when a key appears multiple times in the DB. - This can happen for two reasons: - - - The user has configured multiple keyrings or keyboxes. - - - The keyring or keybox has been corrupted in some way, e.g., a - bug or a random process changing them. - - For each duplicate, we only want to show the key once. Hence, - this list. */ + * This can happen for two reasons: + * + * - The user has configured multiple keyrings or keyboxes. + * + * - The keyring or keybox has been corrupted in some way, e.g., a + * bug or a random process changing them. + * + * For each duplicate, we only want to show the key once. Hence, + * this list. */ static strlist_t key_dups; - - /* USE transformed to a string. */ - char *use_str; - gpg_error_t err; - + char *use_str; /* USE transformed to a string. */ KEYDB_SEARCH_DESC desc; - GETKEY_CTX ctx; pubkey_t results = NULL; pubkey_t r; - int count; - char fingerprint[2 * MAX_FINGERPRINT_LEN + 1]; if (DBG_LOOKUP) @@ -503,7 +497,7 @@ get_pubkeys (ctrl_t ctrl, search_terms, gpg_strerror (err)); if (!opt.quiet && source) log_info (_("(check argument of option '%s')\n"), source); - goto out; + goto leave; } if (warn_possibly_ambiguous @@ -523,8 +517,16 @@ get_pubkeys (ctrl_t ctrl, count = 0; do { - PKT_public_key *pk = xmalloc_clear (sizeof *pk); + PKT_public_key *pk; KBNODE kb; + + pk = xtrycalloc (1, sizeof *pk); + if (!pk) + { + err = gpg_error_from_syserror (); + goto leave; + } + pk->req_usage = use; if (! ctx) @@ -533,17 +535,14 @@ get_pubkeys (ctrl_t ctrl, else err = getkey_next (ctrl, ctx, pk, &kb); - if (gpg_err_code (err) == GPG_ERR_NOT_FOUND) - /* No more results. */ + if (gpg_err_code (err) == GPG_ERR_NOT_FOUND) /* No more results. */ { xfree (pk); break; } - else if (err) - /* An error (other than "not found"). */ + else if (err) /* An error (other than "not found"). */ { - log_error (_("error looking up: %s\n"), - gpg_strerror (err)); + log_error (_("error looking up: %s\n"), gpg_strerror (err)); xfree (pk); break; } @@ -551,7 +550,13 @@ get_pubkeys (ctrl_t ctrl, /* Another result! */ count ++; - r = xmalloc_clear (sizeof (*r)); + r = xtrycalloc (1, sizeof (*r)); + if (!r) + { + err = gpg_error_from_syserror (); + xfree (pk); + goto leave; + } r->pk = pk; r->keyblock = kb; r->next = results; @@ -570,8 +575,7 @@ get_pubkeys (ctrl_t ctrl, } if (! results && gpg_err_code (err) == GPG_ERR_NOT_FOUND) - /* No match. */ - { + { /* No match. */ if (DBG_LOOKUP) log_debug ("%s: '%s' not found.\n", __func__, search_terms); @@ -579,15 +583,15 @@ get_pubkeys (ctrl_t ctrl, if (!opt.quiet && source) log_info (_("(check argument of option '%s')\n"), source); - goto out; + goto leave; } else if (gpg_err_code (err) == GPG_ERR_NOT_FOUND) - /* No more matches. */ - ; + ; /* No more matches. */ else if (err) - /* Some other error. An error message was already printed - out. Free RESULTS and continue. */ - goto out; + { /* Some other error. An error message was already printed out. + * Free RESULTS and continue. */ + goto leave; + } /* Check for duplicates. */ if (DBG_LOOKUP) @@ -607,8 +611,7 @@ get_pubkeys (ctrl_t ctrl, { if (cmp_public_keys (r->keyblock->pkt->pkt.public_key, r2->keyblock->pkt->pkt.public_key) != 0) - /* Not a dup. */ - { + { /* Not a dup. */ prevp = &r2->next; next = r2->next; continue; @@ -652,7 +655,7 @@ get_pubkeys (ctrl_t ctrl, fingerprint, sizeof fingerprint)); } - out: + leave: if (err) pubkeys_free (results); else @@ -723,8 +726,13 @@ get_pubkey (ctrl_t ctrl, PKT_public_key * pk, u32 * keyid) /* More init stuff. */ if (!pk) { - pk = xmalloc_clear (sizeof *pk); internal++; + pk = xtrycalloc (1, sizeof *pk); + if (!pk) + { + rc = gpg_error_from_syserror (); + goto leave; + } } diff --git a/g10/keygen.c b/g10/keygen.c index 12815744f..912fa390c 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -383,19 +383,36 @@ keygen_set_std_prefs (const char *string,int personal) strcat(dummy_string,"S7 "); strcat(dummy_string,"S2 "); /* 3DES */ - /* The default hash algo order is: - SHA-256, SHA-384, SHA-512, SHA-224, SHA-1. - */ - if (!openpgp_md_test_algo (DIGEST_ALGO_SHA256)) - strcat (dummy_string, "H8 "); + if (personal) + { + /* The default internal hash algo order is: + * SHA-256, SHA-384, SHA-512, SHA-224, SHA-1. + */ + if (!openpgp_md_test_algo (DIGEST_ALGO_SHA256)) + strcat (dummy_string, "H8 "); - if (!openpgp_md_test_algo (DIGEST_ALGO_SHA384)) - strcat (dummy_string, "H9 "); + if (!openpgp_md_test_algo (DIGEST_ALGO_SHA384)) + strcat (dummy_string, "H9 "); - if (!openpgp_md_test_algo (DIGEST_ALGO_SHA512)) - strcat (dummy_string, "H10 "); + if (!openpgp_md_test_algo (DIGEST_ALGO_SHA512)) + strcat (dummy_string, "H10 "); + } + else + { + /* The default advertised hash algo order is: + * SHA-512, SHA-384, SHA-256, SHA-224, SHA-1. + */ + if (!openpgp_md_test_algo (DIGEST_ALGO_SHA512)) + strcat (dummy_string, "H10 "); - if (!openpgp_md_test_algo (DIGEST_ALGO_SHA224)) + if (!openpgp_md_test_algo (DIGEST_ALGO_SHA384)) + strcat (dummy_string, "H9 "); + + if (!openpgp_md_test_algo (DIGEST_ALGO_SHA256)) + strcat (dummy_string, "H8 "); + } + + if (!openpgp_md_test_algo (DIGEST_ALGO_SHA224)) strcat (dummy_string, "H11 "); strcat (dummy_string, "H2 "); /* SHA-1 */ @@ -4466,6 +4483,11 @@ card_write_key_to_backup_file (PKT_public_key *sk, const char *backup_dir) log_info (_("Note: backup of card key saved to '%s'\n"), fname); fprbuf = hexfingerprint (sk, NULL, 0); + if (!fprbuf) + { + err = gpg_error_from_syserror (); + goto leave; + } write_status_text_and_buffer (STATUS_BACKUP_KEY_CREATED, fprbuf, fname, strlen (fname), 0); xfree (fprbuf); diff --git a/g10/keyid.c b/g10/keyid.c index 460c02982..a9034ee46 100644 --- a/g10/keyid.c +++ b/g10/keyid.c @@ -790,12 +790,12 @@ fingerprint_from_pk (PKT_public_key *pk, byte *array, size_t *ret_len) /* Return an allocated buffer with the fingerprint of PK formatted as - a plain hexstring. If BUFFER is NULL the result is a malloc'd - string. If BUFFER is not NULL the result will be copied into this - buffer. In the latter case BUFLEN describes the length of the - buffer; if this is too short the function terminates the process. - Returns a malloc'ed string or BUFFER. A suitable length for BUFFER - is (2*MAX_FINGERPRINT_LEN + 1). */ + * a plain hexstring. If BUFFER is NULL the result is a malloc'd + * string. If BUFFER is not NULL the result will be copied into this + * buffer. In the latter case BUFLEN describes the length of the + * buffer; if this is too short the function terminates the process. + * Returns a malloc'ed string or BUFFER. A suitable length for BUFFER + * is (2*MAX_FINGERPRINT_LEN + 1). */ char * hexfingerprint (PKT_public_key *pk, char *buffer, size_t buflen) { @@ -804,7 +804,11 @@ hexfingerprint (PKT_public_key *pk, char *buffer, size_t buflen) fingerprint_from_pk (pk, fpr, &len); if (!buffer) - buffer = xmalloc (2 * len + 1); + { + buffer = xtrymalloc (2 * len + 1); + if (!buffer) + return NULL; + } else if (buflen < 2*len+1) log_fatal ("%s: buffer too short (%zu)\n", __func__, buflen); bin2hex (fpr, len, buffer); diff --git a/g10/pkclist.c b/g10/pkclist.c index 220936c56..581cae407 100644 --- a/g10/pkclist.c +++ b/g10/pkclist.c @@ -730,40 +730,35 @@ key_present_in_pk_list(PK_LIST pk_list, PKT_public_key *pk) } -/**************** +/* * Return a malloced string with a default recipient if there is any + * Fixme: We don't distinguish between malloc failure and no-default-recipient. */ static char * -default_recipient(ctrl_t ctrl) +default_recipient (ctrl_t ctrl) { - PKT_public_key *pk; - byte fpr[MAX_FINGERPRINT_LEN+1]; - size_t n; - char *p; - int i; + PKT_public_key *pk; + char *result; - if( opt.def_recipient ) - return xstrdup( opt.def_recipient ); - if( !opt.def_recipient_self ) - return NULL; - pk = xmalloc_clear( sizeof *pk ); - i = get_seckey_default (ctrl, pk); - if( i ) { - free_public_key( pk ); - return NULL; + if (opt.def_recipient) + return xtrystrdup (opt.def_recipient); + + if (!opt.def_recipient_self) + return NULL; + pk = xtrycalloc (1, sizeof *pk ); + if (!pk) + return NULL; + if (get_seckey_default (ctrl, pk)) + { + free_public_key (pk); + return NULL; } - n = MAX_FINGERPRINT_LEN; - fingerprint_from_pk( pk, fpr, &n ); - free_public_key( pk ); - p = xmalloc( 2*n+3 ); - *p++ = '0'; - *p++ = 'x'; - for(i=0; i < n; i++ ) - sprintf( p+2*i, "%02X", fpr[i] ); - p -= 2; - return p; + result = hexfingerprint (pk, NULL, 0); + free_public_key (pk); + return result; } + static int expand_id(const char *id,strlist_t *into,unsigned int flags) { diff --git a/g10/revoke.c b/g10/revoke.c index 457870082..846523295 100644 --- a/g10/revoke.c +++ b/g10/revoke.c @@ -536,7 +536,20 @@ gen_standard_revoke (ctrl_t ctrl, PKT_public_key *psk, const char *cache_nonce) dir = get_openpgp_revocdir (gnupg_homedir ()); tmpstr = hexfingerprint (psk, NULL, 0); - fname = xstrconcat (dir, DIRSEP_S, tmpstr, NULL); + if (!tmpstr) + { + rc = gpg_error_from_syserror (); + xfree (dir); + return rc; + } + fname = strconcat (dir, DIRSEP_S, tmpstr, NULL); + if (!fname) + { + rc = gpg_error_from_syserror (); + xfree (tmpstr); + xfree (dir); + return rc; + } xfree (tmpstr); xfree (dir); diff --git a/g10/tofu.c b/g10/tofu.c index 8f729a2b2..762b19b7a 100644 --- a/g10/tofu.c +++ b/g10/tofu.c @@ -3336,8 +3336,8 @@ tofu_register_signature (ctrl_t ctrl, char *fingerprint = NULL; strlist_t user_id; char *email = NULL; - char *err = NULL; - char *sig_digest; + char *sqlerr = NULL; + char *sig_digest = NULL; unsigned long c; dbs = opendbs (ctrl); @@ -3358,11 +3358,20 @@ tofu_register_signature (ctrl_t ctrl, log_assert (pk_is_primary (pk)); sig_digest = make_radix64_string (sig_digest_bin, sig_digest_bin_len); + if (!sig_digest) + { + rc = gpg_error_from_syserror (); + goto leave; + } fingerprint = hexfingerprint (pk, NULL, 0); + if (!fingerprint) + { + rc = gpg_error_from_syserror (); + goto leave; + } if (! origin) - /* The default origin is simply "unknown". */ - origin = "unknown"; + origin = "unknown"; /* The default origin is simply "unknown". */ for (user_id = user_id_list; user_id; user_id = user_id->next) { @@ -3388,7 +3397,7 @@ tofu_register_signature (ctrl_t ctrl, it again. */ rc = gpgsql_stepx (dbs->db, &dbs->s.register_already_seen, - get_single_unsigned_long_cb2, &c, &err, + get_single_unsigned_long_cb2, &c, &sqlerr, "select count (*)\n" " from signatures left join bindings\n" " on signatures.binding = bindings.oid\n" @@ -3400,9 +3409,9 @@ tofu_register_signature (ctrl_t ctrl, GPGSQL_ARG_END); if (rc) { - log_error (_("error reading TOFU database: %s\n"), err); + log_error (_("error reading TOFU database: %s\n"), sqlerr); print_further_info ("checking existence"); - sqlite3_free (err); + sqlite3_free (sqlerr); rc = gpg_error (GPG_ERR_GENERAL); } else if (c > 1) @@ -3440,7 +3449,7 @@ tofu_register_signature (ctrl_t ctrl, log_assert (c == 0); rc = gpgsql_stepx - (dbs->db, &dbs->s.register_signature, NULL, NULL, &err, + (dbs->db, &dbs->s.register_signature, NULL, NULL, &sqlerr, "insert into signatures\n" " (binding, sig_digest, origin, sig_time, time)\n" " values\n" @@ -3454,9 +3463,9 @@ tofu_register_signature (ctrl_t ctrl, GPGSQL_ARG_END); if (rc) { - log_error (_("error updating TOFU database: %s\n"), err); + log_error (_("error updating TOFU database: %s\n"), sqlerr); print_further_info ("insert signatures"); - sqlite3_free (err); + sqlite3_free (sqlerr); rc = gpg_error (GPG_ERR_GENERAL); } } @@ -3467,6 +3476,7 @@ tofu_register_signature (ctrl_t ctrl, break; } + leave: if (rc) rollback_transaction (ctrl); else @@ -3490,7 +3500,8 @@ tofu_register_encryption (ctrl_t ctrl, int free_user_id_list = 0; char *fingerprint = NULL; strlist_t user_id; - char *err = NULL; + char *sqlerr = NULL; + int in_batch = 0; dbs = opendbs (ctrl); if (! dbs) @@ -3535,8 +3546,14 @@ tofu_register_encryption (ctrl_t ctrl, } fingerprint = hexfingerprint (pk, NULL, 0); + if (!fingerprint) + { + rc = gpg_error_from_syserror (); + goto leave; + } tofu_begin_batch_update (ctrl); + in_batch = 1; tofu_resume_batch_transaction (ctrl); for (user_id = user_id_list; user_id; user_id = user_id->next) @@ -3554,7 +3571,7 @@ tofu_register_encryption (ctrl_t ctrl, /* An error. */ rc = gpg_error (GPG_ERR_GENERAL); xfree (email); - goto die; + goto leave; } @@ -3580,7 +3597,7 @@ tofu_register_encryption (ctrl_t ctrl, free_strlist (conflict_set); rc = gpgsql_stepx - (dbs->db, &dbs->s.register_encryption, NULL, NULL, &err, + (dbs->db, &dbs->s.register_encryption, NULL, NULL, &sqlerr, "insert into encryptions\n" " (binding, time)\n" " values\n" @@ -3592,24 +3609,22 @@ tofu_register_encryption (ctrl_t ctrl, GPGSQL_ARG_END); if (rc) { - log_error (_("error updating TOFU database: %s\n"), err); + log_error (_("error updating TOFU database: %s\n"), sqlerr); print_further_info ("insert encryption"); - sqlite3_free (err); + sqlite3_free (sqlerr); rc = gpg_error (GPG_ERR_GENERAL); } xfree (email); } - die: - tofu_end_batch_update (ctrl); - - if (kb) - release_kbnode (kb); + leave: + if (in_batch) + tofu_end_batch_update (ctrl); + release_kbnode (kb); if (free_user_id_list) free_strlist (user_id_list); - xfree (fingerprint); return rc; @@ -3685,10 +3700,10 @@ tofu_write_tfs_record (ctrl_t ctrl, estream_t fp, PKT_public_key *pk, const char *user_id) { time_t now = gnupg_get_time (); - gpg_error_t err; + gpg_error_t err = 0; tofu_dbs_t dbs; char *fingerprint; - char *email; + char *email = NULL; enum tofu_policy policy; if (!*user_id) @@ -3703,14 +3718,20 @@ tofu_write_tfs_record (ctrl_t ctrl, estream_t fp, } fingerprint = hexfingerprint (pk, NULL, 0); + if (!fingerprint) + { + err = gpg_error_from_syserror (); + goto leave; + } email = email_from_user_id (user_id); policy = get_policy (ctrl, dbs, pk, fingerprint, user_id, email, NULL, now); show_statistics (dbs, fingerprint, email, policy, fp, 0, now); + leave: xfree (email); xfree (fingerprint); - return 0; + return err; } @@ -3724,7 +3745,10 @@ tofu_write_tfs_record (ctrl_t ctrl, estream_t fp, will be prompted to choose a policy. If MAY_ASK is 0 and the policy is TOFU_POLICY_ASK, then TRUST_UNKNOWN is returned. - Returns TRUST_UNDEFINED if an error occurs. */ + Returns TRUST_UNDEFINED if an error occurs. + + Fixme: eturn an error code + */ int tofu_get_validity (ctrl_t ctrl, PKT_public_key *pk, strlist_t user_id_list, int may_ask) @@ -3748,6 +3772,8 @@ tofu_get_validity (ctrl_t ctrl, PKT_public_key *pk, strlist_t user_id_list, } fingerprint = hexfingerprint (pk, NULL, 0); + if (!fingerprint) + log_fatal ("%s: malloc failed\n", __func__); tofu_begin_batch_update (ctrl); /* Start the batch transaction now. */ @@ -3893,6 +3919,8 @@ tofu_set_policy (ctrl_t ctrl, kbnode_t kb, enum tofu_policy policy) log_bug ("%s: Passed a subkey, but expecting a primary key.\n", __func__); fingerprint = hexfingerprint (pk, NULL, 0); + if (!fingerprint) + return gpg_error_from_syserror (); begin_transaction (ctrl, 0); @@ -3962,6 +3990,8 @@ tofu_get_policy (ctrl_t ctrl, PKT_public_key *pk, PKT_user_id *user_id, } fingerprint = hexfingerprint (pk, NULL, 0); + if (!fingerprint) + return gpg_error_from_syserror (); email = email_from_user_id (user_id->name); @@ -3998,6 +4028,8 @@ tofu_notice_key_changed (ctrl_t ctrl, kbnode_t kb) } fingerprint = hexfingerprint (pk, NULL, 0); + if (!fingerprint) + return gpg_error_from_syserror (); rc = gpgsql_stepx (dbs->db, NULL, NULL, NULL, &sqlerr, "update bindings set effective_policy = ?" diff --git a/scd/scdaemon.c b/scd/scdaemon.c index 0bedb8de2..3ad265781 100644 --- a/scd/scdaemon.c +++ b/scd/scdaemon.c @@ -99,6 +99,7 @@ enum cmd_and_opt_values oDenyAdmin, oDisableApplication, oEnablePinpadVarlen, + oListenBacklog }; @@ -156,6 +157,7 @@ static ARGPARSE_OPTS opts[] = { ARGPARSE_s_n (oEnablePinpadVarlen, "enable-pinpad-varlen", N_("use variable length input for pinpad")), ARGPARSE_s_s (oHomedir, "homedir", "@"), + ARGPARSE_s_i (oListenBacklog, "listen-backlog", "@"), ARGPARSE_end () }; @@ -224,6 +226,10 @@ static char *redir_socket_name; POSIX systems). */ static assuan_sock_nonce_t socket_nonce; +/* Value for the listen() backlog argument. Change at runtime with + * --listen-backlog. */ +static int listen_backlog = 64; + #ifdef HAVE_W32_SYSTEM static HANDLE the_event; #else @@ -594,6 +600,10 @@ main (int argc, char **argv ) case oEnablePinpadVarlen: opt.enable_pinpad_varlen = 1; break; + case oListenBacklog: + listen_backlog = pargs.r.ret_int; + break; + default: pargs.err = configfp? ARGPARSE_PRINT_WARNING:ARGPARSE_PRINT_ERROR; break; @@ -1128,10 +1138,10 @@ create_server_socket (const char *name, char **r_redir_name, log_error (_("can't set permissions of '%s': %s\n"), unaddr->sun_path, strerror (errno)); - if (listen (FD2INT(fd), 5 ) == -1) + if (listen (FD2INT(fd), listen_backlog) == -1) { - log_error (_("listen() failed: %s\n"), - gpg_strerror (gpg_error_from_syserror ())); + log_error ("listen(fd, %d) failed: %s\n", + listen_backlog, gpg_strerror (gpg_error_from_syserror ())); assuan_sock_close (fd); scd_exit (2); } diff --git a/sm/gpgsm.c b/sm/gpgsm.c index e80de6378..650b13030 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -1456,6 +1456,7 @@ main ( int argc, char **argv) { struct gnupg_compliance_option compliance_options[] = { + { "gnupg", CO_GNUPG }, { "de-vs", CO_DE_VS } }; int compliance = gnupg_parse_compliance_option (pargs.r.ret_str, diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index bf54303d6..c799143cd 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -714,7 +714,7 @@ static gc_option_t gc_options_gpg[] = { "options", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE, NULL, NULL, GC_ARG_TYPE_FILENAME, GC_BACKEND_GPG }, - { "compliance", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE, + { "compliance", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT, NULL, NULL, GC_ARG_TYPE_STRING, GC_BACKEND_GPG }, { "default-new-key-algo", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE, @@ -833,6 +833,9 @@ static gc_option_t gc_options_gpgsm[] = (GC_OPT_FLAG_ARG_OPT|GC_OPT_FLAG_NO_CHANGE), GC_LEVEL_INVISIBLE, NULL, NULL, GC_ARG_TYPE_STRING, GC_BACKEND_GPGSM }, + { "compliance", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT, + NULL, NULL, + GC_ARG_TYPE_STRING, GC_BACKEND_GPGSM }, { "Debug", GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED,