diff --git a/g10/getkey.c b/g10/getkey.c index f0e33c596..68e6a1bf0 100644 --- a/g10/getkey.c +++ b/g10/getkey.c @@ -1543,7 +1543,7 @@ pubkey_cmp (ctrl_t ctrl, const char *name, struct pubkey_cmp_cookie *old, new->uid = scopy_user_id (uid); new->validity = - get_validity (ctrl, &new->key, uid, NULL, 0) & TRUST_MASK; + get_validity (ctrl, new_keyblock, &new->key, uid, NULL, 0) & TRUST_MASK; new->valid = 1; if (! old->valid) diff --git a/g10/gpgv.c b/g10/gpgv.c index da07989ea..0ecf232e2 100644 --- a/g10/gpgv.c +++ b/g10/gpgv.c @@ -292,19 +292,22 @@ check_trustdb_stale (ctrl_t ctrl) } int -get_validity_info (ctrl_t ctrl, PKT_public_key *pk, PKT_user_id *uid) +get_validity_info (ctrl_t ctrl, kbnode_t kb, PKT_public_key *pk, + PKT_user_id *uid) { (void)ctrl; + (void)kb; (void)pk; (void)uid; return '?'; } unsigned int -get_validity (ctrl_t ctrl, PKT_public_key *pk, PKT_user_id *uid, +get_validity (ctrl_t ctrl, kbnode_t kb, PKT_public_key *pk, PKT_user_id *uid, PKT_signature *sig, int may_ask) { (void)ctrl; + (void)kb; (void)pk; (void)uid; (void)sig; diff --git a/g10/keyedit.c b/g10/keyedit.c index 5b77ee747..94fa8c49a 100644 --- a/g10/keyedit.c +++ b/g10/keyedit.c @@ -3585,7 +3585,7 @@ show_key_with_all_names_colon (ctrl_t ctrl, estream_t fp, kbnode_t keyblock) es_putc ('e', fp); else if (!(opt.fast_list_mode || opt.no_expensive_trust_checks)) { - int trust = get_validity_info (ctrl, pk, NULL); + int trust = get_validity_info (ctrl, keyblock, pk, NULL); if (trust == 'u') ulti_hack = 1; es_putc (trust, fp); @@ -3644,7 +3644,7 @@ show_key_with_all_names_colon (ctrl_t ctrl, estream_t fp, kbnode_t keyblock) int uid_validity; if (primary && !ulti_hack) - uid_validity = get_validity_info (ctrl, primary, uid); + uid_validity = get_validity_info (ctrl, keyblock, primary, uid); else uid_validity = 'u'; es_fprintf (fp, "%c::::::::", uid_validity); @@ -3819,7 +3819,7 @@ show_key_with_all_names (ctrl_t ctrl, estream_t fp, /* Show a warning once */ if (!did_warn - && (get_validity (ctrl, pk, NULL, NULL, 0) + && (get_validity (ctrl, keyblock, pk, NULL, NULL, 0) & TRUST_FLAG_PENDING_CHECK)) { did_warn = 1; @@ -6304,7 +6304,8 @@ core_revuid (ctrl_t ctrl, kbnode_t keyblock, KBNODE node, /* If the trustdb has an entry for this key+uid then the trustdb needs an update. */ if (!update_trust - && ((get_validity (ctrl, pk, uid, NULL, 0) & TRUST_MASK) + && ((get_validity (ctrl, keyblock, pk, uid, NULL, 0) + & TRUST_MASK) >= TRUST_UNDEFINED)) update_trust = 1; #endif /*!NO_TRUST_MODELS*/ diff --git a/g10/keylist.c b/g10/keylist.c index 0523be090..a5fdc06a8 100644 --- a/g10/keylist.c +++ b/g10/keylist.c @@ -1228,7 +1228,7 @@ list_keyblock_colon (ctrl_t ctrl, kbnode_t keyblock, trustletter_print = 0; else { - trustletter = get_validity_info (ctrl, pk, NULL); + trustletter = get_validity_info (ctrl, keyblock, pk, NULL); if (trustletter == 'u') ulti_hack = 1; trustletter_print = trustletter; @@ -1309,7 +1309,7 @@ list_keyblock_colon (ctrl_t ctrl, kbnode_t keyblock, else if (ulti_hack) uid_validity = 'u'; else - uid_validity = get_validity_info (ctrl, pk, uid); + uid_validity = get_validity_info (ctrl, keyblock, pk, uid); es_fputs (uid->attrib_data? "uat:":"uid:", es_stdout); if (uid_validity) diff --git a/g10/mainproc.c b/g10/mainproc.c index c1819f004..30e19fe1f 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -1015,8 +1015,13 @@ list_node (CTX c, kbnode_t node) keyid_from_pk( pk, keyid ); if (pk->flags.primary) - c->trustletter = (opt.fast_list_mode? - 0 : get_validity_info (c->ctrl, pk, NULL)); + c->trustletter = (opt.fast_list_mode + ? 0 + : get_validity_info + (c->ctrl, + node->pkt->pkttype == PKT_PUBLIC_KEY + ? node : NULL, + pk, NULL)); es_printf ("%s:", pk->flags.primary? "pub":"sub" ); if (c->trustletter) es_putc (c->trustletter, es_stdout); @@ -1973,8 +1978,8 @@ check_sig_and_print (CTX c, kbnode_t node) does not print a LF we need to compute the validity before calling that function. */ if ((opt.verify_options & VERIFY_SHOW_UID_VALIDITY)) - valid = get_validity (c->ctrl, mainpk, un->pkt->pkt.user_id, - NULL, 0); + valid = get_validity (c->ctrl, keyblock, mainpk, + un->pkt->pkt.user_id, NULL, 0); else valid = 0; /* Not used. */ @@ -2075,7 +2080,7 @@ check_sig_and_print (CTX c, kbnode_t node) actually ask the user to update any trust information. */ valid = (trust_value_to_string - (get_validity (c->ctrl, mainpk, + (get_validity (c->ctrl, keyblock, mainpk, un->pkt->pkt.user_id, NULL, 0))); log_printf (" [%s]\n",valid); } diff --git a/g10/photoid.c b/g10/photoid.c index b61ed1bcd..8b193b3d4 100644 --- a/g10/photoid.c +++ b/g10/photoid.c @@ -304,7 +304,7 @@ show_photos (ctrl_t ctrl, const struct user_attribute *attrs, int count, memset (&args, 0, sizeof(args)); args.pk = pk; - args.validity_info = get_validity_info (ctrl, pk, uid); + args.validity_info = get_validity_info (ctrl, NULL, pk, uid); args.validity_string = get_validity_string (ctrl, pk, uid); namehash_from_uid (uid); args.namehash = uid->namehash; diff --git a/g10/pkclist.c b/g10/pkclist.c index 51e8f274c..0426da890 100644 --- a/g10/pkclist.c +++ b/g10/pkclist.c @@ -569,7 +569,7 @@ check_signatures_trust (ctrl_t ctrl, PKT_signature *sig) log_info(_("WARNING: this key might be revoked (revocation key" " not present)\n")); - trustlevel = get_validity (ctrl, pk, NULL, sig, 1); + trustlevel = get_validity (ctrl, NULL, pk, NULL, sig, 1); if ( (trustlevel & TRUST_FLAG_REVOKED) ) { @@ -872,7 +872,7 @@ find_and_check_key (ctrl_t ctrl, const char *name, unsigned int use, { int trustlevel; - trustlevel = get_validity (ctrl, pk, pk->user_id, NULL, 1); + trustlevel = get_validity (ctrl, NULL, pk, pk->user_id, NULL, 1); if ( (trustlevel & TRUST_FLAG_DISABLED) ) { /* Key has been disabled. */ @@ -1212,7 +1212,8 @@ build_pk_list (ctrl_t ctrl, strlist_t rcpts, PK_LIST *ret_pk_list) { /* Check validity of this key. */ int trustlevel; - trustlevel = get_validity (ctrl, pk, pk->user_id, NULL, 1); + trustlevel = + get_validity (ctrl, NULL, pk, pk->user_id, NULL, 1); if ( (trustlevel & TRUST_FLAG_DISABLED) ) { tty_printf (_("Public key is disabled.\n") ); diff --git a/g10/test-stubs.c b/g10/test-stubs.c index 2dc65ab4d..8752f8894 100644 --- a/g10/test-stubs.c +++ b/g10/test-stubs.c @@ -98,19 +98,22 @@ check_trustdb_stale (ctrl_t ctrl) } int -get_validity_info (ctrl_t ctrl, PKT_public_key *pk, PKT_user_id *uid) +get_validity_info (ctrl_t ctrl, kbnode_t kb, PKT_public_key *pk, + PKT_user_id *uid) { (void)ctrl; + (void)kb; (void)pk; (void)uid; return '?'; } unsigned int -get_validity (ctrl_t ctrl, PKT_public_key *pk, PKT_user_id *uid, +get_validity (ctrl_t ctrl, kbnode_t kb, PKT_public_key *pk, PKT_user_id *uid, PKT_signature *sig, int may_ask) { (void)ctrl; + (void)kb; (void)pk; (void)uid; (void)sig; diff --git a/g10/trust.c b/g10/trust.c index 2a829b8b4..080926a36 100644 --- a/g10/trust.c +++ b/g10/trust.c @@ -151,7 +151,7 @@ uid_trust_string_fixed (ctrl_t ctrl, PKT_public_key *key, PKT_user_id *uid) return _("[ expired]"); else if(key) { - switch (get_validity (ctrl, key, uid, NULL, 0) & TRUST_MASK) + switch (get_validity (ctrl, NULL, key, uid, NULL, 0) & TRUST_MASK) { case TRUST_UNKNOWN: return _("[ unknown]"); case TRUST_EXPIRED: return _("[ expired]"); @@ -297,12 +297,13 @@ check_or_update_trustdb (ctrl_t ctrl) /* - * Return the validity information for PK. If the namehash is not - * NULL, the validity of the corresponding user ID is returned, - * otherwise, a reasonable value for the entire key is returned. + * Return the validity information for KB/PK (at least one must be + * non-NULL). If the namehash is not NULL, the validity of the + * corresponding user ID is returned, otherwise, a reasonable value + * for the entire key is returned. */ unsigned int -get_validity (ctrl_t ctrl, PKT_public_key *pk, PKT_user_id *uid, +get_validity (ctrl_t ctrl, kbnode_t kb, PKT_public_key *pk, PKT_user_id *uid, PKT_signature *sig, int may_ask) { int rc; @@ -310,6 +311,16 @@ get_validity (ctrl_t ctrl, PKT_public_key *pk, PKT_user_id *uid, u32 kid[2]; PKT_public_key *main_pk; + if (kb && pk) + log_assert (keyid_cmp (pk_main_keyid (pk), + pk_main_keyid (kb->pkt->pkt.public_key)) == 0); + + if (! pk) + { + log_assert (kb); + pk = kb->pkt->pkt.public_key; + } + if (uid) namehash_from_uid (uid); @@ -317,17 +328,22 @@ get_validity (ctrl_t ctrl, PKT_public_key *pk, PKT_user_id *uid, if (pk->main_keyid[0] != kid[0] || pk->main_keyid[1] != kid[1]) { /* This is a subkey - get the mainkey. */ - main_pk = xmalloc_clear (sizeof *main_pk); - rc = get_pubkey (main_pk, pk->main_keyid); - if (rc) + if (kb) + main_pk = kb->pkt->pkt.public_key; + else { - char *tempkeystr = xstrdup (keystr (pk->main_keyid)); - log_error ("error getting main key %s of subkey %s: %s\n", - tempkeystr, keystr (kid), gpg_strerror (rc)); - xfree (tempkeystr); - validity = TRUST_UNKNOWN; - goto leave; - } + main_pk = xmalloc_clear (sizeof *main_pk); + rc = get_pubkey (main_pk, pk->main_keyid); + if (rc) + { + char *tempkeystr = xstrdup (keystr (pk->main_keyid)); + log_error ("error getting main key %s of subkey %s: %s\n", + tempkeystr, keystr (kid), gpg_strerror (rc)); + xfree (tempkeystr); + validity = TRUST_UNKNOWN; + goto leave; + } + } } else main_pk = pk; @@ -335,7 +351,7 @@ get_validity (ctrl_t ctrl, PKT_public_key *pk, PKT_user_id *uid, #ifdef NO_TRUST_MODELS validity = TRUST_UNKNOWN; #else - validity = tdb_get_validity_core (ctrl, pk, uid, main_pk, sig, may_ask); + validity = tdb_get_validity_core (ctrl, kb, pk, uid, main_pk, sig, may_ask); #endif leave: @@ -350,21 +366,28 @@ get_validity (ctrl_t ctrl, PKT_public_key *pk, PKT_user_id *uid, validity = ((validity & (~TRUST_MASK | TRUST_FLAG_PENDING_CHECK)) | TRUST_EXPIRED); - if (main_pk != pk) + if (main_pk != pk && !kb) free_public_key (main_pk); return validity; } int -get_validity_info (ctrl_t ctrl, PKT_public_key *pk, PKT_user_id *uid) +get_validity_info (ctrl_t ctrl, kbnode_t kb, PKT_public_key *pk, + PKT_user_id *uid) { int trustlevel; + if (kb && pk) + log_assert (keyid_cmp (pk_main_keyid (pk), + pk_main_keyid (kb->pkt->pkt.public_key)) == 0); + + if (! pk && kb) + pk = kb->pkt->pkt.public_key; if (!pk) return '?'; /* Just in case a NULL PK is passed. */ - trustlevel = get_validity (ctrl, pk, uid, NULL, 0); + trustlevel = get_validity (ctrl, kb, pk, uid, NULL, 0); if ((trustlevel & TRUST_FLAG_REVOKED)) return 'r'; return trust_letter (trustlevel); @@ -379,7 +402,7 @@ get_validity_string (ctrl_t ctrl, PKT_public_key *pk, PKT_user_id *uid) if (!pk) return "err"; /* Just in case a NULL PK is passed. */ - trustlevel = get_validity (ctrl, pk, uid, NULL, 0); + trustlevel = get_validity (ctrl, NULL, pk, uid, NULL, 0); if ((trustlevel & TRUST_FLAG_REVOKED)) return _("revoked"); return trust_value_to_string (trustlevel); diff --git a/g10/trustdb.c b/g10/trustdb.c index 51a8f2217..d402cb2ba 100644 --- a/g10/trustdb.c +++ b/g10/trustdb.c @@ -983,13 +983,15 @@ tdb_check_trustdb_stale (ctrl_t ctrl) } /* - * Return the validity information for PK. This is the core of - * get_validity. If SIG is not NULL, then the trust is being - * evaluated in the context of the provided signature. This is used - * by the TOFU code to record statistics. + * Return the validity information for KB/PK (at least one of them + * must be non-NULL). This is the core of get_validity. If SIG is + * not NULL, then the trust is being evaluated in the context of the + * provided signature. This is used by the TOFU code to record + * statistics. */ unsigned int tdb_get_validity_core (ctrl_t ctrl, + kbnode_t kb, PKT_public_key *pk, PKT_user_id *uid, PKT_public_key *main_pk, PKT_signature *sig, @@ -1002,6 +1004,17 @@ tdb_get_validity_core (ctrl_t ctrl, unsigned int tofu_validity = TRUST_UNKNOWN; #endif unsigned int validity = TRUST_UNKNOWN; + int free_kb = 0; + + if (kb && pk) + log_assert (keyid_cmp (pk_main_keyid (pk), + pk_main_keyid (kb->pkt->pkt.public_key)) == 0); + + if (! pk) + { + log_assert (kb); + pk = kb->pkt->pkt.public_key; + } #ifndef USE_TOFU (void)sig; @@ -1030,14 +1043,20 @@ tdb_get_validity_core (ctrl_t ctrl, #ifdef USE_TOFU if (opt.trust_model == TM_TOFU || opt.trust_model == TM_TOFU_PGP) { - kbnode_t kb = NULL; kbnode_t n = NULL; strlist_t user_id_list = NULL; int done = 0; /* If the caller didn't supply a user id then use all uids. */ if (! uid) - kb = n = get_pubkeyblock (main_pk->keyid); + { + if (! kb) + { + kb = get_pubkeyblock (main_pk->keyid); + free_kb = 1; + } + n = kb; + } if (DBG_TRUST && sig && sig->signers_uid) log_debug ("TOFU: only considering user id: '%s'\n", @@ -1132,7 +1151,8 @@ tdb_get_validity_core (ctrl_t ctrl, may_ask); free_strlist (user_id_list); - release_kbnode (kb); + if (free_kb) + release_kbnode (kb); } #endif /*USE_TOFU*/ diff --git a/g10/trustdb.h b/g10/trustdb.h index 45ecc56ab..6081d1088 100644 --- a/g10/trustdb.h +++ b/g10/trustdb.h @@ -94,9 +94,11 @@ void revalidation_mark (void); void check_trustdb_stale (ctrl_t ctrl); void check_or_update_trustdb (ctrl_t ctrl); -unsigned int get_validity (ctrl_t ctrl, PKT_public_key *pk, PKT_user_id *uid, +unsigned int get_validity (ctrl_t ctrl, kbnode_t kb, PKT_public_key *pk, + PKT_user_id *uid, PKT_signature *sig, int may_ask); -int get_validity_info (ctrl_t ctrl, PKT_public_key *pk, PKT_user_id *uid); +int get_validity_info (ctrl_t ctrl, kbnode_t kb, PKT_public_key *pk, + PKT_user_id *uid); const char *get_validity_string (ctrl_t ctrl, PKT_public_key *pk, PKT_user_id *uid); @@ -135,7 +137,7 @@ void tdb_check_or_update (ctrl_t ctrl); int tdb_cache_disabled_value (PKT_public_key *pk); -unsigned int tdb_get_validity_core (ctrl_t ctrl, +unsigned int tdb_get_validity_core (ctrl_t ctrl, kbnode_t kb, PKT_public_key *pk, PKT_user_id *uid, PKT_public_key *main_pk, PKT_signature *sig, int may_ask);