diff --git a/configure.ac b/configure.ac index 22f082ed9..ebd0c2f07 100644 --- a/configure.ac +++ b/configure.ac @@ -89,12 +89,6 @@ AB_INIT AC_GNU_SOURCE -# Before we do anything with the C compiler, we first save the user's -# CFLAGS (they are restored at the end of the configure script). This -# is because some configure checks don't work with -Werror, but we'd -# like to use -Werror with our build. -CFLAGS_orig=$CFLAGS -CFLAGS= # Some status variables. have_gpg_error=no @@ -1693,6 +1687,15 @@ if test "$enable_log_clock" = yes ; then AC_DEFINE(ENABLE_LOG_CLOCK,1,[Defined to use log_clock timestamps]) fi +# Add -Werror to CFLAGS. This hack can be used to avoid problems with +# misbehaving autoconf tests in case the user supplied -Werror. +# +AC_ARG_ENABLE(werror, + AC_HELP_STRING([--enable-werror], + [append -Werror to CFLAGS]), + [if test $enableval = yes ; then + CFLAGS="$CFLAGS -Werror" + fi]) # # Configure option --enable-all-tests @@ -1723,11 +1726,6 @@ if test x"$gnupg_builddir_envvar" = x"yes"; then [This is only used with "make distcheck"]) fi -# -# Add user CFLAGS. -# -CFLAGS="$CFLAGS $CFLAGS_orig" - # # Decide what to build # diff --git a/dirmngr/ks-engine-http.c b/dirmngr/ks-engine-http.c index 7fb77312d..6492dda8a 100644 --- a/dirmngr/ks-engine-http.c +++ b/dirmngr/ks-engine-http.c @@ -73,12 +73,13 @@ ks_http_fetch (ctrl_t ctrl, const char *url, estream_t *r_fp) estream_t fp = NULL; char *request_buffer = NULL; parsed_uri_t uri = NULL; - int is_onion; + int is_onion, is_https; err = http_parse_uri (&uri, url, 0); if (err) goto leave; is_onion = uri->onion; + is_https = uri->use_tls; once_more: /* Note that we only use the system provided certificates with the @@ -152,17 +153,18 @@ ks_http_fetch (ctrl_t ctrl, const char *url, estream_t *r_fp) url, s?s:"[none]", http_get_status_code (http)); if (s && *s && redirects_left-- ) { - if (is_onion) + if (is_onion || is_https) { /* Make sure that an onion address only redirects to - * another onion address. */ + * another onion address, or that a https address + * only redirects to a https address. */ http_release_parsed_uri (uri); uri = NULL; err = http_parse_uri (&uri, s, 0); if (err) goto leave; - if (! uri->onion) + if ((is_onion && ! uri->onion) || (is_https && ! uri->use_tls)) { err = gpg_error (GPG_ERR_FORBIDDEN); goto leave; diff --git a/doc/gpg.texi b/doc/gpg.texi index b14cb371b..bd45b0422 100644 --- a/doc/gpg.texi +++ b/doc/gpg.texi @@ -2306,7 +2306,8 @@ opposite meaning. The options are: Show a listing of the key as imported right before it is stored. This can be combined with the option @option{--dry-run} to only look at keys; the option @option{show-only} is a shortcut for this - combination. + combination. Note that suffixes like '#' for "sec" and "sbb" lines + may or may not be printed. @item import-export Run the entire import code but instead of storing the key to the diff --git a/doc/gpgv.texi b/doc/gpgv.texi index 5336c98db..a05286171 100644 --- a/doc/gpgv.texi +++ b/doc/gpgv.texi @@ -187,6 +187,6 @@ The default keyring with the allowed keys. @end table @mansect see also -@command{gpg2}(1) +@command{gpg}(1) @include see-also-note.texi diff --git a/g10/import.c b/g10/import.c index 8dd6b501e..71e39557c 100644 --- a/g10/import.c +++ b/g10/import.c @@ -1778,7 +1778,7 @@ import_one (ctrl_t ctrl, merge_keys_done = 1; /* Note that we do not want to show the validity because the key * has not yet imported. */ - list_keyblock_direct (ctrl, keyblock, 0, 0, + list_keyblock_direct (ctrl, keyblock, from_sk, 0, opt.fingerprint || opt.with_fingerprint, 1); es_fflush (es_stdout); } @@ -2532,7 +2532,8 @@ import_secret_one (ctrl_t ctrl, kbnode_t keyblock, /* At least we cancel the secret key import when the public key import was skipped due to MERGE_ONLY option and a new key. */ - if (stats->skipped_new_keys <= nr_prev) + if (!(opt.dry_run || (options & IMPORT_DRY_RUN)) + && stats->skipped_new_keys <= nr_prev) { /* Read the keyblock again to get the effects of a merge. */ /* Fixme: we should do this based on the fingerprint or diff --git a/g10/key-check.c b/g10/key-check.c index d32067b99..86b1e769d 100644 --- a/g10/key-check.c +++ b/g10/key-check.c @@ -32,6 +32,27 @@ #include "key-check.h" + +/* Print PREFIX followed by TEXT. With mode > 0 use log_info, with + * mode < 0 use ttyio, else print to stdout. If TEXT is not NULL, it + * may be modified by this function. */ +static void +print_info (int mode, const char *prefix, char *text) +{ + char *p; + + if (!text) + text = ""; + else if ((p = strchr (text,'\n'))) + *p = 0; /* Strip LF. */ + + if (mode > 0) + log_info ("%s %s\n", prefix, text); + else + tty_fprintf (mode? NULL:es_stdout, "%s %s\n", prefix, text); +} + + /* Order two signatures. The actual ordering isn't important. Our * goal is to ensure that identical signatures occur together. */ static int @@ -100,7 +121,6 @@ key_check_all_keysigs (ctrl_t ctrl, int mode, kbnode_t kb, int only_selected, int only_selfsigs) { gpg_error_t err; - estream_t fp = mode < 0? NULL : mode ? log_get_stream () : es_stdout; PKT_public_key *pk; KBNODE n, n_next, *n_prevp, n2; char *pending_desc = NULL; @@ -476,8 +496,9 @@ key_check_all_keysigs (ctrl_t ctrl, int mode, kbnode_t kb, has_selfsig = 1; } - if ((n2 && n2 != last_printed_component) - || (! n2 && last_printed_component != current_component)) + if (DBG_PACKET + && ((n2 && n2 != last_printed_component) + || (! n2 && last_printed_component != current_component))) { int is_reordered = n2 && n2 != current_component; if (n2) @@ -489,36 +510,34 @@ key_check_all_keysigs (ctrl_t ctrl, int mode, kbnode_t kb, ; else if (last_printed_component->pkt->pkttype == PKT_USER_ID) { - tty_fprintf (fp, "uid "); - tty_print_utf8_string2 (fp, - last_printed_component - ->pkt->pkt.user_id->name, - last_printed_component - ->pkt->pkt.user_id->len, 0); + log_debug ("uid "); + print_utf8_buffer (log_get_stream (), + last_printed_component + ->pkt->pkt.user_id->name, + last_printed_component + ->pkt->pkt.user_id->len); + log_flush (); } else if (last_printed_component->pkt->pkttype == PKT_PUBLIC_KEY) - tty_fprintf (fp, "pub %s", - pk_keyid_str (last_printed_component + log_debug ("pub %s\n", + pk_keyid_str (last_printed_component ->pkt->pkt.public_key)); else - tty_fprintf (fp, "sub %s", - pk_keyid_str (last_printed_component - ->pkt->pkt.public_key)); + log_debug ("sub %s\n", + pk_keyid_str (last_printed_component + ->pkt->pkt.public_key)); if (modified) { if (is_reordered) - tty_fprintf (fp, _(" (reordered signatures follow)")); - if (mode > 0) - log_printf ("\n"); - else - tty_fprintf (fp, "\n"); + log_debug ("%s\n", _(" (reordered signatures follow)")); } } - if (modified) - keyedit_print_one_sig (ctrl, fp, rc, kb, n, NULL, NULL, NULL, + if (DBG_PACKET && modified) + keyedit_print_one_sig (ctrl, log_get_stream (), + rc, kb, n, NULL, NULL, NULL, has_selfsig, 0, only_selfsigs); } @@ -624,32 +643,62 @@ key_check_all_keysigs (ctrl_t ctrl, int mode, kbnode_t kb, } } - if (dups || missing_issuer || bad_signature || reordered) - tty_fprintf (fp, _("key %s:\n"), pk_keyid_str (pk)); + if (!opt.quiet) + { + char prefix[100]; + char *p; - if (dups) - tty_fprintf (fp, - ngettext ("%d duplicate signature removed\n", - "%d duplicate signatures removed\n", dups), dups); - if (missing_issuer) - tty_fprintf (fp, - ngettext ("%d signature not checked due to a missing key\n", - "%d signatures not checked due to missing keys\n", - missing_issuer), missing_issuer); - if (bad_signature) - tty_fprintf (fp, - ngettext ("%d bad signature\n", - "%d bad signatures\n", - bad_signature), bad_signature); - if (reordered) - tty_fprintf (fp, - ngettext ("%d signature reordered\n", - "%d signatures reordered\n", - reordered), reordered); + /* To avoid string changes in 2.2 we strip the LF here. */ + snprintf (prefix, sizeof prefix, _("key %s:\n"), pk_keyid_str (pk)); + p = strrchr (prefix, '\n'); + if (p) + *p = 0; - if (only_selfsigs && (bad_signature || reordered)) - tty_fprintf (fp, _("Warning: errors found and only checked self-signatures," - " run '%s' to check all signatures.\n"), "check"); + if (dups) + { + p = xtryasprintf + (ngettext ("%d duplicate signature removed\n", + "%d duplicate signatures removed\n", dups), dups); + print_info (mode, prefix, p); + xfree (p); + } + + if (missing_issuer) + { + p = xtryasprintf + (ngettext ("%d signature not checked due to a missing key\n", + "%d signatures not checked due to missing keys\n", + missing_issuer), missing_issuer); + print_info (mode, prefix, p); + xfree (p); + } + if (bad_signature) + { + p = xtryasprintf (ngettext ("%d bad signature\n", + "%d bad signatures\n", + bad_signature), bad_signature); + print_info (mode, prefix, p); + xfree (p); + } + + if (reordered) + { + p = xtryasprintf (ngettext ("%d signature reordered\n", + "%d signatures reordered\n", + reordered), reordered); + print_info (mode, prefix, p); + xfree (p); + } + + if (only_selfsigs && (bad_signature || reordered)) + { + p = xtryasprintf + (_("Warning: errors found and only checked self-signatures," + " run '%s' to check all signatures.\n"), "check"); + print_info (mode, prefix, p); + xfree (p); + } + } return modified; } diff --git a/g10/keyedit.c b/g10/keyedit.c index 38cdbce3a..4acb2de5f 100644 --- a/g10/keyedit.c +++ b/g10/keyedit.c @@ -1223,10 +1223,8 @@ parse_sign_type (const char *str, int *localsig, int *nonrevokesig, /* Need an SK for this command */ #define KEYEDIT_NEED_SK 1 -/* Cannot be viewing the SK for this command */ -#define KEYEDIT_NOT_SK 2 -/* Must be viewing the SK for this command */ -#define KEYEDIT_ONLY_SK 4 +/* Need an SUB KEY for this command */ +#define KEYEDIT_NEED_SUBSK 2 /* Match the tail of the string */ #define KEYEDIT_TAIL_MATCH 8 @@ -1268,12 +1266,12 @@ static struct { "key", cmdSELKEY, 0, N_("select subkey N")}, { "check", cmdCHECK, 0, N_("check signatures")}, { "c", cmdCHECK, 0, NULL}, - { "change-usage", cmdCHANGEUSAGE, KEYEDIT_NOT_SK | KEYEDIT_NEED_SK, NULL}, - { "cross-certify", cmdBACKSIGN, KEYEDIT_NOT_SK | KEYEDIT_NEED_SK, NULL}, - { "backsign", cmdBACKSIGN, KEYEDIT_NOT_SK | KEYEDIT_NEED_SK, NULL}, - { "sign", cmdSIGN, KEYEDIT_NOT_SK | KEYEDIT_TAIL_MATCH, + { "change-usage", cmdCHANGEUSAGE, KEYEDIT_NEED_SK, NULL}, + { "cross-certify", cmdBACKSIGN, KEYEDIT_NEED_SK, NULL}, + { "backsign", cmdBACKSIGN, KEYEDIT_NEED_SK, NULL}, + { "sign", cmdSIGN, KEYEDIT_TAIL_MATCH, N_("sign selected user IDs [* see below for related commands]")}, - { "s", cmdSIGN, KEYEDIT_NOT_SK, NULL}, + { "s", cmdSIGN, 0, NULL}, /* "lsign" and friends will never match since "sign" comes first and it is a tail match. They are just here so they show up in the help menu. */ @@ -1282,62 +1280,62 @@ static struct { "nrsign", cmdNOP, 0, N_("sign selected user IDs with a non-revocable signature")}, { "debug", cmdDEBUG, 0, NULL}, - { "adduid", cmdADDUID, KEYEDIT_NOT_SK | KEYEDIT_NEED_SK, N_("add a user ID")}, - { "addphoto", cmdADDPHOTO, KEYEDIT_NOT_SK | KEYEDIT_NEED_SK, + { "adduid", cmdADDUID, KEYEDIT_NEED_SK, N_("add a user ID")}, + { "addphoto", cmdADDPHOTO, KEYEDIT_NEED_SK, N_("add a photo ID")}, - { "deluid", cmdDELUID, KEYEDIT_NOT_SK, N_("delete selected user IDs")}, + { "deluid", cmdDELUID, 0, N_("delete selected user IDs")}, /* delphoto is really deluid in disguise */ - { "delphoto", cmdDELUID, KEYEDIT_NOT_SK, NULL}, - { "addkey", cmdADDKEY, KEYEDIT_NOT_SK | KEYEDIT_NEED_SK, N_("add a subkey")}, + { "delphoto", cmdDELUID, 0, NULL}, + { "addkey", cmdADDKEY, KEYEDIT_NEED_SK, N_("add a subkey")}, #ifdef ENABLE_CARD_SUPPORT - { "addcardkey", cmdADDCARDKEY, KEYEDIT_NOT_SK | KEYEDIT_NEED_SK, + { "addcardkey", cmdADDCARDKEY, KEYEDIT_NEED_SK, N_("add a key to a smartcard")}, - { "keytocard", cmdKEYTOCARD, KEYEDIT_NEED_SK | KEYEDIT_ONLY_SK, + { "keytocard", cmdKEYTOCARD, KEYEDIT_NEED_SK | KEYEDIT_NEED_SUBSK, N_("move a key to a smartcard")}, - { "bkuptocard", cmdBKUPTOCARD, KEYEDIT_NEED_SK | KEYEDIT_ONLY_SK, + { "bkuptocard", cmdBKUPTOCARD, KEYEDIT_NEED_SK | KEYEDIT_NEED_SUBSK, N_("move a backup key to a smartcard")}, #endif /*ENABLE_CARD_SUPPORT */ - { "delkey", cmdDELKEY, KEYEDIT_NOT_SK, N_("delete selected subkeys")}, - { "addrevoker", cmdADDREVOKER, KEYEDIT_NOT_SK | KEYEDIT_NEED_SK, + { "delkey", cmdDELKEY, 0, N_("delete selected subkeys")}, + { "addrevoker", cmdADDREVOKER, KEYEDIT_NEED_SK, N_("add a revocation key")}, - { "delsig", cmdDELSIG, KEYEDIT_NOT_SK, + { "delsig", cmdDELSIG, 0, N_("delete signatures from the selected user IDs")}, - { "expire", cmdEXPIRE, KEYEDIT_NOT_SK | KEYEDIT_NEED_SK, + { "expire", cmdEXPIRE, KEYEDIT_NEED_SK | KEYEDIT_NEED_SUBSK, N_("change the expiration date for the key or selected subkeys")}, - { "primary", cmdPRIMARY, KEYEDIT_NOT_SK | KEYEDIT_NEED_SK, + { "primary", cmdPRIMARY, KEYEDIT_NEED_SK, N_("flag the selected user ID as primary")}, { "toggle", cmdTOGGLE, KEYEDIT_NEED_SK, NULL}, /* Dummy command. */ { "t", cmdTOGGLE, KEYEDIT_NEED_SK, NULL}, - { "pref", cmdPREF, KEYEDIT_NOT_SK, N_("list preferences (expert)")}, - { "showpref", cmdSHOWPREF, KEYEDIT_NOT_SK, N_("list preferences (verbose)")}, - { "setpref", cmdSETPREF, KEYEDIT_NOT_SK | KEYEDIT_NEED_SK, + { "pref", cmdPREF, 0, N_("list preferences (expert)")}, + { "showpref", cmdSHOWPREF, 0, N_("list preferences (verbose)")}, + { "setpref", cmdSETPREF, KEYEDIT_NEED_SK, N_("set preference list for the selected user IDs")}, - { "updpref", cmdSETPREF, KEYEDIT_NOT_SK | KEYEDIT_NEED_SK, NULL}, - { "keyserver", cmdPREFKS, KEYEDIT_NOT_SK | KEYEDIT_NEED_SK, + { "updpref", cmdSETPREF, KEYEDIT_NEED_SK, NULL}, + { "keyserver", cmdPREFKS, KEYEDIT_NEED_SK, N_("set the preferred keyserver URL for the selected user IDs")}, - { "notation", cmdNOTATION, KEYEDIT_NOT_SK | KEYEDIT_NEED_SK, + { "notation", cmdNOTATION, KEYEDIT_NEED_SK, N_("set a notation for the selected user IDs")}, - { "passwd", cmdPASSWD, KEYEDIT_NOT_SK | KEYEDIT_NEED_SK, + { "passwd", cmdPASSWD, KEYEDIT_NEED_SK | KEYEDIT_NEED_SUBSK, N_("change the passphrase")}, - { "password", cmdPASSWD, KEYEDIT_NOT_SK | KEYEDIT_NEED_SK, NULL}, + { "password", cmdPASSWD, KEYEDIT_NEED_SK | KEYEDIT_NEED_SUBSK, NULL}, #ifndef NO_TRUST_MODELS - { "trust", cmdTRUST, KEYEDIT_NOT_SK, N_("change the ownertrust")}, + { "trust", cmdTRUST, 0, N_("change the ownertrust")}, #endif /*!NO_TRUST_MODELS*/ - { "revsig", cmdREVSIG, KEYEDIT_NOT_SK, + { "revsig", cmdREVSIG, 0, N_("revoke signatures on the selected user IDs")}, - { "revuid", cmdREVUID, KEYEDIT_NOT_SK | KEYEDIT_NEED_SK, + { "revuid", cmdREVUID, KEYEDIT_NEED_SK, N_("revoke selected user IDs")}, - { "revphoto", cmdREVUID, KEYEDIT_NOT_SK | KEYEDIT_NEED_SK, NULL}, - { "revkey", cmdREVKEY, KEYEDIT_NOT_SK | KEYEDIT_NEED_SK, + { "revphoto", cmdREVUID, KEYEDIT_NEED_SK, NULL}, + { "revkey", cmdREVKEY, KEYEDIT_NEED_SK, N_("revoke key or selected subkeys")}, #ifndef NO_TRUST_MODELS - { "enable", cmdENABLEKEY, KEYEDIT_NOT_SK, N_("enable key")}, - { "disable", cmdDISABLEKEY, KEYEDIT_NOT_SK, N_("disable key")}, + { "enable", cmdENABLEKEY, 0, N_("enable key")}, + { "disable", cmdDISABLEKEY, 0, N_("disable key")}, #endif /*!NO_TRUST_MODELS*/ { "showphoto", cmdSHOWPHOTO, 0, N_("show selected photo IDs")}, - { "clean", cmdCLEAN, KEYEDIT_NOT_SK, + { "clean", cmdCLEAN, 0, N_("compact unusable user IDs and remove unusable signatures from key")}, - { "minimize", cmdMINIMIZE, KEYEDIT_NOT_SK, + { "minimize", cmdMINIMIZE, 0, N_("compact unusable user IDs and remove all signatures from key")}, { NULL, cmdNONE, 0, NULL} @@ -1406,6 +1404,7 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr, KBNODE keyblock = NULL; KEYDB_HANDLE kdbhd = NULL; int have_seckey = 0; + int have_anyseckey = 0; char *answer = NULL; int redisplay = 1; int modified = 0; @@ -1448,9 +1447,18 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr, /* See whether we have a matching secret key. */ if (seckey_check) { - have_seckey = !agent_probe_any_secret_key (ctrl, keyblock); + have_anyseckey = !agent_probe_any_secret_key (ctrl, keyblock); + if (have_anyseckey + && !agent_probe_secret_key (ctrl, keyblock->pkt->pkt.public_key)) + { + /* The primary key is also available. */ + have_seckey = 1; + } + if (have_seckey && !quiet) - tty_printf (_("Secret key is available.\n")); + tty_printf (_("Secret key is available.\n")); + else if (have_anyseckey && !quiet) + tty_printf (_("Secret subkeys are available.\n")); } /* Main command loop. */ @@ -1548,12 +1556,14 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr, else if (!ascii_strcasecmp (answer, cmds[i].name)) break; } - if ((cmds[i].flags & KEYEDIT_NEED_SK) && !have_seckey) + if ((cmds[i].flags & (KEYEDIT_NEED_SK|KEYEDIT_NEED_SUBSK)) + && !(((cmds[i].flags & KEYEDIT_NEED_SK) && have_seckey) + || ((cmds[i].flags & KEYEDIT_NEED_SUBSK) && have_anyseckey))) { tty_printf (_("Need the secret key to do this.\n")); cmd = cmdNOP; } - else + else cmd = cmds[i].id; } @@ -1563,7 +1573,9 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr, case cmdHELP: for (i = 0; cmds[i].name; i++) { - if ((cmds[i].flags & KEYEDIT_NEED_SK) && !have_seckey) + if ((cmds[i].flags & (KEYEDIT_NEED_SK|KEYEDIT_NEED_SUBSK)) + && !(((cmds[i].flags & KEYEDIT_NEED_SK) && have_seckey) + ||((cmds[i].flags&KEYEDIT_NEED_SUBSK)&&have_anyseckey))) ; /* Skip those item if we do not have the secret key. */ else if (cmds[i].desc) tty_printf ("%-11s %s\n", cmds[i].name, _(cmds[i].desc)); diff --git a/g10/keygen.c b/g10/keygen.c index e959ee901..1dddfeeda 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -5050,6 +5050,9 @@ generate_subkeypair (ctrl_t ctrl, kbnode_t keyblock, const char *algostr, err = agent_passwd (ctrl, hexgrip, desc, 1 /*=verify*/, &cache_nonce, &passwd_nonce); xfree (desc); + if (gpg_err_code (err) == GPG_ERR_NOT_IMPLEMENTED + && gpg_err_source (err) == GPG_ERR_SOURCE_GPGAGENT) + err = 0; /* Very likely that the key is on a card. */ if (err) goto leave; } diff --git a/g10/trust.c b/g10/trust.c index ee6078b5a..6d4f0e74b 100644 --- a/g10/trust.c +++ b/g10/trust.c @@ -66,6 +66,26 @@ register_trusted_key (const char *string) #ifdef NO_TRUST_MODELS (void)string; #else + + /* Some users have conf files with entries like + * trusted-key 0x1234567812345678 # foo + * That is obviously wrong. Before fixing bug#1206 trailing garbage + * on a key specification if was ignored. We detect the above use case + * here and cut off the junk-looking-like-a comment. */ + if (strchr (string, '#')) + { + char *buf; + + buf = xtrystrdup (string); + if (buf) + { + *strchr (buf, '#') = 0; + tdb_register_trusted_key (buf); + xfree (buf); + return; + } + } + tdb_register_trusted_key (string); #endif } diff --git a/sm/call-dirmngr.c b/sm/call-dirmngr.c index 930194076..e94311892 100644 --- a/sm/call-dirmngr.c +++ b/sm/call-dirmngr.c @@ -415,7 +415,7 @@ inq_certificate (void *opaque, const char *line) ksba_cert_t cert; - err = gpgsm_find_cert (parm->ctrl, line, ski, &cert); + err = gpgsm_find_cert (parm->ctrl, line, ski, &cert, 1); if (err) { log_error ("certificate not found: %s\n", gpg_strerror (err)); @@ -936,7 +936,7 @@ run_command_inq_cb (void *opaque, const char *line) if (!*line) return gpg_error (GPG_ERR_ASS_PARAMETER); - err = gpgsm_find_cert (parm->ctrl, line, NULL, &cert); + err = gpgsm_find_cert (parm->ctrl, line, NULL, &cert, 1); if (err) { log_error ("certificate not found: %s\n", gpg_strerror (err)); diff --git a/sm/certlist.c b/sm/certlist.c index 39ab03c5d..c9e275e9d 100644 --- a/sm/certlist.c +++ b/sm/certlist.c @@ -489,7 +489,8 @@ gpgsm_release_certlist (certlist_t list) subjectKeyIdentifier. */ int gpgsm_find_cert (ctrl_t ctrl, - const char *name, ksba_sexp_t keyid, ksba_cert_t *r_cert) + const char *name, ksba_sexp_t keyid, ksba_cert_t *r_cert, + int allow_ambiguous) { int rc; KEYDB_SEARCH_DESC desc; @@ -537,6 +538,16 @@ gpgsm_find_cert (ctrl_t ctrl, won't lead to ambiguous names. */ if (!rc && !keyid) { + ksba_isotime_t notbefore = ""; + const unsigned char *image = NULL; + size_t length = 0; + if (allow_ambiguous) + { + /* We want to return the newest certificate */ + if (ksba_cert_get_validity (*r_cert, 0, notbefore)) + *notbefore = '\0'; + image = ksba_cert_get_image (*r_cert, &length); + } next_ambiguous: rc = keydb_search (ctrl, kh, &desc, 1); if (rc == -1) @@ -546,6 +557,10 @@ gpgsm_find_cert (ctrl_t ctrl, if (!rc) { ksba_cert_t cert2 = NULL; + ksba_isotime_t notbefore2 = ""; + const unsigned char *image2 = NULL; + size_t length2 = 0; + int cmp = 0; if (!keydb_get_cert (kh, &cert2)) { @@ -554,6 +569,29 @@ gpgsm_find_cert (ctrl_t ctrl, ksba_cert_release (cert2); goto next_ambiguous; } + if (allow_ambiguous) + { + if (ksba_cert_get_validity (cert2, 0, notbefore2)) + *notbefore2 = '\0'; + image2 = ksba_cert_get_image (cert2, &length2); + cmp = strcmp (notbefore, notbefore2); + /* use certificate image bits as last resort for stable ordering */ + if (!cmp) + cmp = memcmp (image, image2, length < length2 ? length : length2); + if (!cmp) + cmp = length < length2 ? -1 : length > length2 ? 1 : 0; + if (cmp < 0) + { + ksba_cert_release (*r_cert); + *r_cert = cert2; + strcpy (notbefore, notbefore2); + image = image2; + length = length2; + } + else + ksba_cert_release (cert2); + goto next_ambiguous; + } ksba_cert_release (cert2); } rc = gpg_error (GPG_ERR_AMBIGUOUS_NAME); diff --git a/sm/gpgsm.c b/sm/gpgsm.c index bd701ab7f..e80de6378 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -2058,7 +2058,7 @@ main ( int argc, char **argv) ksba_cert_t cert = NULL; char *grip = NULL; - rc = gpgsm_find_cert (&ctrl, *argv, NULL, &cert); + rc = gpgsm_find_cert (&ctrl, *argv, NULL, &cert, 0); if (rc) ; else if (!(grip = gpgsm_get_keygrip_hexstring (cert))) diff --git a/sm/gpgsm.h b/sm/gpgsm.h index 0421b97bb..3e2f95fb3 100644 --- a/sm/gpgsm.h +++ b/sm/gpgsm.h @@ -331,7 +331,7 @@ int gpgsm_add_to_certlist (ctrl_t ctrl, const char *name, int secret, certlist_t *listaddr, int is_encrypt_to); void gpgsm_release_certlist (certlist_t list); int gpgsm_find_cert (ctrl_t ctrl, const char *name, ksba_sexp_t keyid, - ksba_cert_t *r_cert); + ksba_cert_t *r_cert, int allow_ambiguous); /*-- keylist.c --*/ gpg_error_t gpgsm_list_keys (ctrl_t ctrl, strlist_t names, diff --git a/sm/server.c b/sm/server.c index 64a3add9a..568e51b17 100644 --- a/sm/server.c +++ b/sm/server.c @@ -1179,7 +1179,7 @@ cmd_passwd (assuan_context_t ctx, char *line) line = skip_options (line); - err = gpgsm_find_cert (ctrl, line, NULL, &cert); + err = gpgsm_find_cert (ctrl, line, NULL, &cert, 0); if (err) ; else if (!(grip = gpgsm_get_keygrip_hexstring (cert))) diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index e6ef4f4e3..9ce752b18 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -2085,9 +2085,12 @@ get_config_filename (gc_component_t component, gc_backend_t backend) /* Retrieve the options for the component COMPONENT from backend - BACKEND, which we already know is a program-type backend. */ + * BACKEND, which we already know is a program-type backend. With + * ONLY_INSTALLED set components which are not installed are silently + * ignored. */ static void -retrieve_options_from_program (gc_component_t component, gc_backend_t backend) +retrieve_options_from_program (gc_component_t component, gc_backend_t backend, + int only_installed) { gpg_error_t err; const char *pgmname; @@ -2107,6 +2110,11 @@ retrieve_options_from_program (gc_component_t component, gc_backend_t backend) argv[0] = "--gpgconf-list"; argv[1] = NULL; + if (only_installed && access (pgmname, X_OK)) + { + return; /* The component is not installed. */ + } + err = gnupg_spawn_process (pgmname, argv, NULL, NULL, 0, NULL, &outfp, NULL, &pid); if (err) @@ -2378,7 +2386,7 @@ retrieve_options_from_file (gc_component_t component, gc_backend_t backend) /* Retrieve the currently active options and their defaults from all involved backends for this component. Using -1 for component will - retrieve all options from all components. */ + retrieve all options from all installed components. */ void gc_component_retrieve_options (int component) { @@ -2420,7 +2428,8 @@ gc_component_retrieve_options (int component) assert (backend != GC_BACKEND_ANY); if (gc_backend[backend].program) - retrieve_options_from_program (component, backend); + retrieve_options_from_program (component, backend, + process_all); else retrieve_options_from_file (component, backend); }