diff options
Diffstat (limited to 'g10/mainproc.c')
-rw-r--r-- | g10/mainproc.c | 92 |
1 files changed, 59 insertions, 33 deletions
diff --git a/g10/mainproc.c b/g10/mainproc.c index 6494f60ed..ebbe4a6a7 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -1173,12 +1173,15 @@ proc_compressed (CTX c, PACKET *pkt) * used to verify the signature will be stored there, or NULL if not * found. If FORCED_PK is not NULL, this public key is used to verify * _data signatures_ and no key lookup is done. Returns: 0 = valid - * signature or an error code + * signature or an error code. If R_KEYBLOCK is not NULL the keyblock + * carries the used PK is stored there. The caller should always free + * the return value using release_kbnode. */ static int do_check_sig (CTX c, kbnode_t node, const void *extrahash, size_t extrahashlen, PKT_public_key *forced_pk, int *is_selfsig, - int *is_expkey, int *is_revkey, PKT_public_key **r_pk) + int *is_expkey, int *is_revkey, + PKT_public_key **r_pk, kbnode_t *r_keyblock) { PKT_signature *sig; gcry_md_hd_t md = NULL; @@ -1188,6 +1191,8 @@ do_check_sig (CTX c, kbnode_t node, const void *extrahash, size_t extrahashlen, if (r_pk) *r_pk = NULL; + if (r_keyblock) + *r_keyblock = NULL; log_assert (node->pkt->pkttype == PKT_SIGNATURE); if (is_selfsig) @@ -1264,16 +1269,19 @@ do_check_sig (CTX c, kbnode_t node, const void *extrahash, size_t extrahashlen, /* We only get here if we are checking the signature of a binary (0x00) or text document (0x01). */ rc = check_signature (c->ctrl, sig, md, extrahash, extrahashlen, - forced_pk, NULL, is_expkey, is_revkey, r_pk); + forced_pk, NULL, is_expkey, is_revkey, + r_pk, r_keyblock); if (! rc) md_good = md; else if (gpg_err_code (rc) == GPG_ERR_BAD_SIGNATURE && md2) { PKT_public_key *pk2; + if (r_keyblock) + release_kbnode (*r_keyblock); rc = check_signature (c->ctrl, sig, md2, extrahash, extrahashlen, forced_pk, NULL, is_expkey, is_revkey, - r_pk? &pk2 : NULL); + r_pk? &pk2 : NULL, r_keyblock); if (!rc) { md_good = md2; @@ -1436,7 +1444,7 @@ list_node (CTX c, kbnode_t node) { fflush (stdout); rc2 = do_check_sig (c, node, NULL, 0, NULL, - &is_selfsig, NULL, NULL, NULL); + &is_selfsig, NULL, NULL, NULL, NULL); switch (gpg_err_code (rc2)) { case 0: sigrc = '!'; break; @@ -1935,7 +1943,7 @@ check_sig_and_print (CTX c, kbnode_t node) PKT_public_key *pk = NULL; /* The public key for the signature or NULL. */ const void *extrahash = NULL; size_t extrahashlen = 0; - kbnode_t included_keyblock = NULL; + kbnode_t keyblock = NULL; char pkstrbuf[PUBKEY_STRING_SIZE] = { 0 }; @@ -2056,7 +2064,8 @@ check_sig_and_print (CTX c, kbnode_t node) { ambiguous: log_error(_("can't handle this ambiguous signature data\n")); - return 0; + rc = 0; + goto leave; } } /* End checking signature packet composition. */ @@ -2092,7 +2101,7 @@ check_sig_and_print (CTX c, kbnode_t node) log_info (_(" issuer \"%s\"\n"), sig->signers_uid); rc = do_check_sig (c, node, extrahash, extrahashlen, NULL, - NULL, &is_expkey, &is_revkey, &pk); + NULL, &is_expkey, &is_revkey, &pk, &keyblock); /* If the key is not found but the signature includes a key block we * use that key block for verification and on success import it. */ @@ -2100,6 +2109,7 @@ check_sig_and_print (CTX c, kbnode_t node) && sig->flags.key_block && opt.flags.auto_key_import) { + kbnode_t included_keyblock = NULL; PKT_public_key *included_pk; const byte *kblock; size_t kblock_len; @@ -2111,10 +2121,12 @@ check_sig_and_print (CTX c, kbnode_t node) kblock+1, kblock_len-1, sig->keyid, &included_keyblock)) { + /* Note: This is the only place where we use the forced_pk + * arg (ie. included_pk) with do_check_sig. */ rc = do_check_sig (c, node, extrahash, extrahashlen, included_pk, - NULL, &is_expkey, &is_revkey, &pk); + NULL, &is_expkey, &is_revkey, &pk, NULL); if (opt.verbose) - log_debug ("checked signature using included key block: %s\n", + log_info ("checked signature using included key block: %s\n", gpg_strerror (rc)); if (!rc) { @@ -2124,6 +2136,18 @@ check_sig_and_print (CTX c, kbnode_t node) } free_public_key (included_pk); + release_kbnode (included_keyblock); + + /* To make sure that nothing strange happened we check the + * signature again now using our own key store. This also + * returns the keyblock which we use later on. */ + if (!rc) + { + release_kbnode (keyblock); + keyblock = NULL; + rc = do_check_sig (c, node, extrahash, extrahashlen, NULL, + NULL, &is_expkey, &is_revkey, &pk, &keyblock); + } } /* If the key isn't found, check for a preferred keyserver. Note @@ -2170,8 +2194,13 @@ check_sig_and_print (CTX c, kbnode_t node) KEYSERVER_IMPORT_FLAG_QUICK); glo_ctrl.in_auto_key_retrieve--; if (!res) - rc = do_check_sig (c, node, extrahash, extrahashlen, NULL, - NULL, &is_expkey, &is_revkey, &pk); + { + release_kbnode (keyblock); + keyblock = NULL; + rc = do_check_sig (c, node, extrahash, extrahashlen, NULL, + NULL, &is_expkey, &is_revkey, &pk, + &keyblock); + } else if (DBG_LOOKUP) log_debug ("lookup via %s failed: %s\n", "Pref-KS", gpg_strerror (res)); @@ -2212,8 +2241,12 @@ check_sig_and_print (CTX c, kbnode_t node) /* Fixme: If the fingerprint is embedded in the signature, * compare it to the fingerprint of the returned key. */ if (!res) - rc = do_check_sig (c, node, extrahash, extrahashlen, NULL, - NULL, &is_expkey, &is_revkey, &pk); + { + release_kbnode (keyblock); + keyblock = NULL; + rc = do_check_sig (c, node, extrahash, extrahashlen, NULL, + NULL, &is_expkey, &is_revkey, &pk, &keyblock); + } else if (DBG_LOOKUP) log_debug ("lookup via %s failed: %s\n", "WKD", gpg_strerror (res)); } @@ -2243,8 +2276,13 @@ check_sig_and_print (CTX c, kbnode_t node) KEYSERVER_IMPORT_FLAG_QUICK); glo_ctrl.in_auto_key_retrieve--; if (!res) - rc = do_check_sig (c, node, extrahash, extrahashlen, NULL, - NULL, &is_expkey, &is_revkey, &pk); + { + release_kbnode (keyblock); + keyblock = NULL; + rc = do_check_sig (c, node, extrahash, extrahashlen, NULL, + NULL, &is_expkey, &is_revkey, &pk, + &keyblock); + } else if (DBG_LOOKUP) log_debug ("lookup via %s failed: %s\n", "KS", gpg_strerror (res)); } @@ -2255,7 +2293,7 @@ check_sig_and_print (CTX c, kbnode_t node) { /* We have checked the signature and the result is either a good * signature or a bad signature. Further examination follows. */ - kbnode_t un, keyblock; + kbnode_t un; int count = 0; int keyblock_has_pk = 0; /* For failsafe check. */ int statno; @@ -2273,18 +2311,6 @@ check_sig_and_print (CTX c, kbnode_t node) else statno = STATUS_GOODSIG; - /* FIXME: We should have the public key in PK and thus the - * keyblock has already been fetched. Thus we could use the - * fingerprint or PK itself to lookup the entire keyblock. That - * would best be done with a cache. */ - if (included_keyblock) - { - keyblock = included_keyblock; - included_keyblock = NULL; - } - else - keyblock = get_pubkeyblock_for_sig (c->ctrl, sig); - snprintf (keyid_str, sizeof keyid_str, "%08lX%08lX [uncertain] ", (ulong)sig->keyid[0], (ulong)sig->keyid[1]); @@ -2350,10 +2376,10 @@ check_sig_and_print (CTX c, kbnode_t node) * contained in the keyring.*/ } - log_assert (mainpk); - if (!keyblock_has_pk) + if (!mainpk || !keyblock_has_pk) { - log_error ("signature key lost from keyblock\n"); + log_error ("signature key lost from keyblock (%p,%p,%d)\n", + keyblock, mainpk, keyblock_has_pk); rc = gpg_error (GPG_ERR_INTERNAL); } @@ -2623,8 +2649,8 @@ check_sig_and_print (CTX c, kbnode_t node) log_error (_("Can't check signature: %s\n"), gpg_strerror (rc)); } + leave: free_public_key (pk); - release_kbnode (included_keyblock); xfree (issuer_fpr); return rc; } |