aboutsummaryrefslogtreecommitdiffstats
path: root/g10/mainproc.c
diff options
context:
space:
mode:
Diffstat (limited to 'g10/mainproc.c')
-rw-r--r--g10/mainproc.c92
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;
}