aboutsummaryrefslogtreecommitdiffstats
path: root/g10/mainproc.c
diff options
context:
space:
mode:
Diffstat (limited to 'g10/mainproc.c')
-rw-r--r--g10/mainproc.c72
1 files changed, 61 insertions, 11 deletions
diff --git a/g10/mainproc.c b/g10/mainproc.c
index e9e886f59..07366b068 100644
--- a/g10/mainproc.c
+++ b/g10/mainproc.c
@@ -1,6 +1,7 @@
/* mainproc.c - handle packets
* Copyright (C) 1998-2009 Free Software Foundation, Inc.
* Copyright (C) 2013-2014 Werner Koch
+ * Copyright (C) 2020 g10 Code GmbH
*
* This file is part of GnuPG.
*
@@ -956,10 +957,13 @@ proc_compressed (CTX c, PACKET *pkt)
/*
* Check the signature. If R_PK is not NULL a copy of the public key
* used to verify the signature will be stored there, or NULL if not
- * found. Returns: 0 = valid signature or an error code
+ * 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
*/
static int
-do_check_sig (CTX c, kbnode_t node, int *is_selfsig,
+do_check_sig (CTX c, kbnode_t node,
+ PKT_public_key *forced_pk, int *is_selfsig,
int *is_expkey, int *is_revkey, PKT_public_key **r_pk)
{
PKT_signature *sig;
@@ -1045,14 +1049,18 @@ do_check_sig (CTX c, kbnode_t node, int *is_selfsig,
/* We only get here if we are checking the signature of a binary
(0x00) or text document (0x01). */
- rc = check_signature2 (c->ctrl, sig, md, NULL, is_expkey, is_revkey, r_pk);
+ rc = check_signature2 (c->ctrl, sig, md,
+ forced_pk,
+ NULL, is_expkey, is_revkey, r_pk);
if (! rc)
md_good = md;
else if (gpg_err_code (rc) == GPG_ERR_BAD_SIGNATURE && md2)
{
PKT_public_key *pk2;
- rc = check_signature2 (c->ctrl, sig, md2, NULL, is_expkey, is_revkey,
+ rc = check_signature2 (c->ctrl, sig, md2,
+ forced_pk,
+ NULL, is_expkey, is_revkey,
r_pk? &pk2 : NULL);
if (!rc)
{
@@ -1215,7 +1223,7 @@ list_node (CTX c, kbnode_t node)
if (opt.check_sigs)
{
fflush (stdout);
- rc2 = do_check_sig (c, node, &is_selfsig, NULL, NULL, NULL);
+ rc2 = do_check_sig (c, node, NULL, &is_selfsig, NULL, NULL, NULL);
switch (gpg_err_code (rc2))
{
case 0: sigrc = '!'; break;
@@ -1746,6 +1754,7 @@ check_sig_and_print (CTX c, kbnode_t node)
int is_revkey = 0;
char *issuer_fpr = NULL;
PKT_public_key *pk = NULL; /* The public key for the signature or NULL. */
+ kbnode_t included_keyblock = NULL;
if (opt.skip_verify)
{
@@ -1894,7 +1903,39 @@ check_sig_and_print (CTX c, kbnode_t node)
if (sig->signers_uid)
log_info (_(" issuer \"%s\"\n"), sig->signers_uid);
- rc = do_check_sig (c, node, NULL, &is_expkey, &is_revkey, &pk);
+ rc = do_check_sig (c, node, NULL, NULL, &is_expkey, &is_revkey, &pk);
+
+ /* If the key is not found but the signaure includes a key bnlock we
+ * import that key block and trry again. We keep this key block
+ * only if the signature verifies. */
+ /* FIXME: Shall we add an option to disable it or use it only if
+ * --auto-key-retriueve is set? */
+ if (gpg_err_code (rc) == GPG_ERR_NO_PUBKEY
+ && sig->flags.key_block)
+ /* && (opt.keyserver_options.options & KEYSERVER_AUTO_KEY_RETRIEVE)) */
+ {
+ PKT_public_key *included_pk;
+ const byte *kblock;
+ size_t kblock_len;
+
+ included_pk = xcalloc (1, sizeof *included_pk);
+ kblock = parse_sig_subpkt (sig->hashed, SIGSUBPKT_KEY_BLOCK, &kblock_len);
+ if (kblock && kblock_len > 1
+ && !get_pubkey_from_buffer (c->ctrl, included_pk,
+ kblock+1, kblock_len-1,
+ sig->keyid, &included_keyblock))
+ {
+ rc = do_check_sig (c, node, included_pk,
+ NULL, &is_expkey, &is_revkey, &pk);
+ if (!rc)
+ {
+ /* The keyblock has been verified, we now import it. */
+ rc = import_included_key_block (c->ctrl, included_keyblock);
+ }
+
+ }
+ free_public_key (included_pk);
+ }
/* If the key isn't found, check for a preferred keyserver. Note
* that this is only done if honor-keyserver-url has been set. We
@@ -1940,7 +1981,7 @@ check_sig_and_print (CTX c, kbnode_t node)
glo_ctrl.in_auto_key_retrieve--;
if (!res)
rc = do_check_sig (c, node, NULL,
- &is_expkey, &is_revkey, &pk);
+ NULL, &is_expkey, &is_revkey, &pk);
else if (DBG_LOOKUP)
log_debug ("lookup via %s failed: %s\n", "Pref-KS",
gpg_strerror (res));
@@ -1980,7 +2021,7 @@ 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, NULL, &is_expkey, &is_revkey, &pk);
+ rc = do_check_sig (c, node, NULL, NULL, &is_expkey, &is_revkey, &pk);
else if (DBG_LOOKUP)
log_debug ("lookup via %s failed: %s\n", "WKD", gpg_strerror (res));
}
@@ -2014,7 +2055,8 @@ check_sig_and_print (CTX c, kbnode_t node)
glo_ctrl.in_auto_key_retrieve--;
free_keyserver_spec (spec);
if (!res)
- rc = do_check_sig (c, node, NULL, &is_expkey, &is_revkey, &pk);
+ rc = do_check_sig (c, node, NULL,
+ NULL, &is_expkey, &is_revkey, &pk);
else if (DBG_LOOKUP)
log_debug ("lookup via %s failed: %s\n", "PKA",
gpg_strerror (res));
@@ -2046,7 +2088,8 @@ check_sig_and_print (CTX c, kbnode_t node)
res = keyserver_import_fprint (c->ctrl, p, n, opt.keyserver, 1);
glo_ctrl.in_auto_key_retrieve--;
if (!res)
- rc = do_check_sig (c, node, NULL, &is_expkey, &is_revkey, &pk);
+ rc = do_check_sig (c, node, NULL,
+ NULL, &is_expkey, &is_revkey, &pk);
else if (DBG_LOOKUP)
log_debug ("lookup via %s failed: %s\n", "KS", gpg_strerror (res));
}
@@ -2075,7 +2118,13 @@ check_sig_and_print (CTX c, kbnode_t node)
* 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. */
- keyblock = get_pubkeyblock_for_sig (c->ctrl, sig);
+ 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]);
@@ -2388,6 +2437,7 @@ check_sig_and_print (CTX c, kbnode_t node)
}
free_public_key (pk);
+ release_kbnode (included_keyblock);
xfree (issuer_fpr);
return rc;
}