mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
gpg: Make use of the included key block in a signature.
* g10/import.c (read_key_from_file): Rename to ... (read_key_from_file_or_buffer): this and add new parameters. Adjust callers. (import_included_key_block): New. * g10/packet.h (PKT_signature): Add field flags.key_block. * g10/parse-packet.c (parse_signature): Set that flags. * g10/sig-check.c (check_signature2): Add parm forced_pk and change all callers. * g10/mainproc.c (do_check_sig): Ditto. (check_sig_and_print): Try the included key block if no key is available. -- This is is the second part to support the new Key Block subpacket. The idea is that after having received a signed mail, it is instantly possible to reply encrypted - without the need for any centralized infrastructure. There is one case where this does not work: A signed mail is received using a specified signer ID (e.g. using gpg --sender option) and the key block with only that user ID is thus imported. The next time a mail is received using the same key but with a different user ID; the signatures checks out using the key imported the last time. However, the new user id is not imported. Now when trying to reply to that last mail, no key will be found. We need to see whether we can update a key in such a case. GnuPG-bug-id: 4856 Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
parent
865d485180
commit
6a4443c842
64
g10/getkey.c
64
g10/getkey.c
@ -309,13 +309,21 @@ pk_from_block (PKT_public_key *pk, kbnode_t keyblock, kbnode_t found_key)
|
||||
|
||||
|
||||
/* Specialized version of get_pubkey which retrieves the key based on
|
||||
* information in SIG. In contrast to get_pubkey PK is required. */
|
||||
* information in SIG. In contrast to get_pubkey PK is required. IF
|
||||
* FORCED_PK is not NULL, this public key is used and copied to PK. */
|
||||
gpg_error_t
|
||||
get_pubkey_for_sig (ctrl_t ctrl, PKT_public_key *pk, PKT_signature *sig)
|
||||
get_pubkey_for_sig (ctrl_t ctrl, PKT_public_key *pk, PKT_signature *sig,
|
||||
PKT_public_key *forced_pk)
|
||||
{
|
||||
const byte *fpr;
|
||||
size_t fprlen;
|
||||
|
||||
if (forced_pk)
|
||||
{
|
||||
copy_public_key (pk, forced_pk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* First try the new ISSUER_FPR info. */
|
||||
fpr = issuer_fpr_raw (sig, &fprlen);
|
||||
if (fpr && !get_pubkey_byfprint (ctrl, pk, NULL, fpr, fprlen))
|
||||
@ -1594,7 +1602,7 @@ get_pubkey_fromfile (ctrl_t ctrl, PKT_public_key *pk, const char *fname)
|
||||
kbnode_t found_key;
|
||||
unsigned int infoflags;
|
||||
|
||||
err = read_key_from_file (ctrl, fname, &keyblock);
|
||||
err = read_key_from_file_or_buffer (ctrl, fname, NULL, 0, &keyblock);
|
||||
if (!err)
|
||||
{
|
||||
/* Warning: node flag bits 0 and 1 should be preserved by
|
||||
@ -1613,6 +1621,56 @@ get_pubkey_fromfile (ctrl_t ctrl, PKT_public_key *pk, const char *fname)
|
||||
}
|
||||
|
||||
|
||||
/* Return a public key from the buffer (BUFFER, BUFLEN). The key is
|
||||
* onlyretruned if it matches the keyid given in WANT_KEYID. On
|
||||
* success the key is stored at the caller provided PKBUF structure.
|
||||
* The caller must release the content of PK by calling
|
||||
* release_public_key_parts (or, if PKBUF was malloced, using
|
||||
* free_public_key). If R_KEYBLOCK is not NULL the full keyblock is
|
||||
* also stored there. */
|
||||
gpg_error_t
|
||||
get_pubkey_from_buffer (ctrl_t ctrl, PKT_public_key *pkbuf,
|
||||
const void *buffer, size_t buflen, u32 *want_keyid,
|
||||
kbnode_t *r_keyblock)
|
||||
{
|
||||
gpg_error_t err;
|
||||
kbnode_t keyblock;
|
||||
kbnode_t node;
|
||||
PKT_public_key *pk;
|
||||
|
||||
if (r_keyblock)
|
||||
*r_keyblock = NULL;
|
||||
|
||||
err = read_key_from_file_or_buffer (ctrl, NULL, buffer, buflen, &keyblock);
|
||||
if (!err)
|
||||
{
|
||||
merge_selfsigs (ctrl, keyblock);
|
||||
for (node = keyblock; node; node = node->next)
|
||||
{
|
||||
if (node->pkt->pkttype == PKT_PUBLIC_KEY
|
||||
|| node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
|
||||
{
|
||||
pk = node->pkt->pkt.public_key;
|
||||
keyid_from_pk (pk, NULL);
|
||||
if (pk->keyid[0] == want_keyid[0]
|
||||
&& pk->keyid[1] == want_keyid[1])
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (node)
|
||||
copy_public_key (pkbuf, pk);
|
||||
else
|
||||
err = gpg_error (GPG_ERR_NO_PUBKEY);
|
||||
}
|
||||
|
||||
if (!err && r_keyblock)
|
||||
*r_keyblock = keyblock;
|
||||
else
|
||||
release_kbnode (keyblock);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/* Lookup a key with the specified fingerprint.
|
||||
*
|
||||
* If PK is not NULL, the public key of the first result is returned
|
||||
|
14
g10/gpgv.c
14
g10/gpgv.c
@ -484,14 +484,26 @@ keyserver_import_ldap (const char *name)
|
||||
|
||||
|
||||
gpg_error_t
|
||||
read_key_from_file (ctrl_t ctrl, const char *fname, kbnode_t *r_keyblock)
|
||||
read_key_from_file_or_buffer (ctrl_t ctrl, const char *fname,
|
||||
const void *buffer, size_t buflen,
|
||||
kbnode_t *r_keyblock)
|
||||
{
|
||||
(void)ctrl;
|
||||
(void)fname;
|
||||
(void)buffer;
|
||||
(void)buflen;
|
||||
(void)r_keyblock;
|
||||
return -1;
|
||||
}
|
||||
|
||||
gpg_error_t
|
||||
import_included_key_block (ctrl_t ctrl, kbnode_t keyblock)
|
||||
{
|
||||
(void)ctrl;
|
||||
(void)keyblock;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* Stub:
|
||||
* No encryption here but mainproc links to these functions.
|
||||
|
108
g10/import.c
108
g10/import.c
@ -320,7 +320,9 @@ import_release_stats_handle (import_stats_t p)
|
||||
* file.
|
||||
*/
|
||||
gpg_error_t
|
||||
read_key_from_file (ctrl_t ctrl, const char *fname, kbnode_t *r_keyblock)
|
||||
read_key_from_file_or_buffer (ctrl_t ctrl, const char *fname,
|
||||
const void *buffer, size_t buflen,
|
||||
kbnode_t *r_keyblock)
|
||||
{
|
||||
gpg_error_t err;
|
||||
iobuf_t inp;
|
||||
@ -334,35 +336,45 @@ read_key_from_file (ctrl_t ctrl, const char *fname, kbnode_t *r_keyblock)
|
||||
|
||||
*r_keyblock = NULL;
|
||||
|
||||
inp = iobuf_open (fname);
|
||||
if (!inp)
|
||||
err = gpg_error_from_syserror ();
|
||||
else if (is_secured_file (iobuf_get_fd (inp)))
|
||||
{
|
||||
iobuf_close (inp);
|
||||
inp = NULL;
|
||||
err = gpg_error (GPG_ERR_EPERM);
|
||||
}
|
||||
else
|
||||
err = 0;
|
||||
if (err)
|
||||
{
|
||||
log_error (_("can't open '%s': %s\n"),
|
||||
iobuf_is_pipe_filename (fname)? "[stdin]": fname,
|
||||
gpg_strerror (err));
|
||||
if (gpg_err_code (err) == GPG_ERR_ENOENT)
|
||||
err = gpg_error (GPG_ERR_NO_PUBKEY);
|
||||
goto leave;
|
||||
}
|
||||
log_assert (!!fname ^ !!buffer);
|
||||
|
||||
/* Push the armor filter. */
|
||||
{
|
||||
armor_filter_context_t *afx;
|
||||
afx = new_armor_context ();
|
||||
afx->only_keyblocks = 1;
|
||||
push_armor_filter (afx, inp);
|
||||
release_armor_context (afx);
|
||||
}
|
||||
if (fname)
|
||||
{
|
||||
inp = iobuf_open (fname);
|
||||
if (!inp)
|
||||
err = gpg_error_from_syserror ();
|
||||
else if (is_secured_file (iobuf_get_fd (inp)))
|
||||
{
|
||||
iobuf_close (inp);
|
||||
inp = NULL;
|
||||
err = gpg_error (GPG_ERR_EPERM);
|
||||
}
|
||||
else
|
||||
err = 0;
|
||||
if (err)
|
||||
{
|
||||
log_error (_("can't open '%s': %s\n"),
|
||||
iobuf_is_pipe_filename (fname)? "[stdin]": fname,
|
||||
gpg_strerror (err));
|
||||
if (gpg_err_code (err) == GPG_ERR_ENOENT)
|
||||
err = gpg_error (GPG_ERR_NO_PUBKEY);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* Push the armor filter. */
|
||||
{
|
||||
armor_filter_context_t *afx;
|
||||
afx = new_armor_context ();
|
||||
afx->only_keyblocks = 1;
|
||||
push_armor_filter (afx, inp);
|
||||
release_armor_context (afx);
|
||||
}
|
||||
|
||||
}
|
||||
else /* Read from buffer (No armor expected). */
|
||||
{
|
||||
inp = iobuf_temp_with_content (buffer, buflen);
|
||||
}
|
||||
|
||||
/* Read the first non-v3 keyblock. */
|
||||
while (!(err = read_block (inp, 0, &pending_pkt, &keyblock, &v3keys)))
|
||||
@ -377,7 +389,8 @@ read_key_from_file (ctrl_t ctrl, const char *fname, kbnode_t *r_keyblock)
|
||||
{
|
||||
if (gpg_err_code (err) != GPG_ERR_INV_KEYRING)
|
||||
log_error (_("error reading '%s': %s\n"),
|
||||
iobuf_is_pipe_filename (fname)? "[stdin]": fname,
|
||||
fname? (iobuf_is_pipe_filename (fname)? "[stdin]": fname)
|
||||
/* */ : "[buffer]",
|
||||
gpg_strerror (err));
|
||||
goto leave;
|
||||
}
|
||||
@ -413,7 +426,8 @@ read_key_from_file (ctrl_t ctrl, const char *fname, kbnode_t *r_keyblock)
|
||||
{
|
||||
iobuf_close (inp);
|
||||
/* Must invalidate that ugly cache to actually close the file. */
|
||||
iobuf_ioctl (NULL, IOBUF_IOCTL_INVALIDATE_CACHE, 0, (char*)fname);
|
||||
if (fname)
|
||||
iobuf_ioctl (NULL, IOBUF_IOCTL_INVALIDATE_CACHE, 0, (char*)fname);
|
||||
}
|
||||
release_kbnode (keyblock);
|
||||
/* FIXME: Do we need to free PENDING_PKT ? */
|
||||
@ -421,6 +435,38 @@ read_key_from_file (ctrl_t ctrl, const char *fname, kbnode_t *r_keyblock)
|
||||
}
|
||||
|
||||
|
||||
/* Import an already checked public key which was included in a
|
||||
* signature and the signature verified out using this key. */
|
||||
gpg_error_t
|
||||
import_included_key_block (ctrl_t ctrl, kbnode_t keyblock)
|
||||
{
|
||||
gpg_error_t err;
|
||||
struct import_stats_s *stats;
|
||||
import_filter_t save_filt;
|
||||
int save_armor = opt.armor;
|
||||
|
||||
opt.armor = 0;
|
||||
stats = import_new_stats_handle ();
|
||||
save_filt = save_and_clear_import_filter ();
|
||||
if (!save_filt)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* FIXME: Should we introduce a dedicated KEYORG ? */
|
||||
err = import_one (ctrl, keyblock,
|
||||
stats, NULL, 0, 0, 0, 0,
|
||||
NULL, NULL, KEYORG_UNKNOWN, NULL, NULL);
|
||||
|
||||
leave:
|
||||
restore_import_filter (save_filt);
|
||||
import_release_stats_handle (stats);
|
||||
opt.armor = save_armor;
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Import the public keys from the given filename. Input may be armored.
|
||||
|
@ -328,7 +328,8 @@ void getkey_disable_caches(void);
|
||||
|
||||
/* Return the public key used for signature SIG and store it at PK. */
|
||||
gpg_error_t get_pubkey_for_sig (ctrl_t ctrl,
|
||||
PKT_public_key *pk, PKT_signature *sig);
|
||||
PKT_public_key *pk, PKT_signature *sig,
|
||||
PKT_public_key *forced_pk);
|
||||
|
||||
/* Return the public key with the key id KEYID and store it at PK. */
|
||||
int get_pubkey (ctrl_t ctrl, PKT_public_key *pk, u32 *keyid);
|
||||
@ -385,6 +386,11 @@ gpg_error_t get_best_pubkey_byname (ctrl_t ctrl, enum get_pubkey_modes mode,
|
||||
gpg_error_t get_pubkey_fromfile (ctrl_t ctrl,
|
||||
PKT_public_key *pk, const char *fname);
|
||||
|
||||
/* Get a public key from a buffer. */
|
||||
gpg_error_t get_pubkey_from_buffer (ctrl_t ctrl, PKT_public_key *pkbuf,
|
||||
const void *buffer, size_t buflen,
|
||||
u32 *want_keyid, kbnode_t *r_keyblock);
|
||||
|
||||
/* Return the public key with the key id KEYID iff the secret key is
|
||||
* available and store it at PK. */
|
||||
gpg_error_t get_seckey (ctrl_t ctrl, PKT_public_key *pk, u32 *keyid);
|
||||
|
@ -370,8 +370,10 @@ gpg_error_t parse_and_set_import_filter (const char *string);
|
||||
import_filter_t save_and_clear_import_filter (void);
|
||||
void restore_import_filter (import_filter_t filt);
|
||||
|
||||
gpg_error_t read_key_from_file (ctrl_t ctrl, const char *fname,
|
||||
kbnode_t *r_keyblock);
|
||||
gpg_error_t read_key_from_file_or_buffer (ctrl_t ctrl, const char *fname,
|
||||
const void *buffer, size_t buflen,
|
||||
kbnode_t *r_keyblock);
|
||||
gpg_error_t import_included_key_block (ctrl_t ctrl, kbnode_t keyblock);
|
||||
void import_keys (ctrl_t ctrl, char **fnames, int nnames,
|
||||
import_stats_t stats_hd, unsigned int options,
|
||||
int origin, const char *url);
|
||||
|
@ -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.
|
||||
*
|
||||
@ -1050,11 +1051,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, const void *extrahash, size_t extrahashlen,
|
||||
int *is_selfsig,
|
||||
PKT_public_key *forced_pk, int *is_selfsig,
|
||||
int *is_expkey, int *is_revkey, PKT_public_key **r_pk)
|
||||
{
|
||||
PKT_signature *sig;
|
||||
@ -1141,6 +1144,7 @@ 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_signature2 (c->ctrl, sig, md, extrahash, extrahashlen,
|
||||
forced_pk,
|
||||
NULL, is_expkey, is_revkey, r_pk);
|
||||
if (! rc)
|
||||
md_good = md;
|
||||
@ -1149,6 +1153,7 @@ do_check_sig (CTX c, kbnode_t node, const void *extrahash, size_t extrahashlen,
|
||||
PKT_public_key *pk2;
|
||||
|
||||
rc = check_signature2 (c->ctrl, sig, md2, extrahash, extrahashlen,
|
||||
forced_pk,
|
||||
NULL, is_expkey, is_revkey,
|
||||
r_pk? &pk2 : NULL);
|
||||
if (!rc)
|
||||
@ -1312,7 +1317,8 @@ list_node (CTX c, kbnode_t node)
|
||||
if (opt.check_sigs)
|
||||
{
|
||||
fflush (stdout);
|
||||
rc2 = do_check_sig (c, node, NULL, 0, &is_selfsig, NULL, NULL, NULL);
|
||||
rc2 = do_check_sig (c, node, NULL, 0, NULL,
|
||||
&is_selfsig, NULL, NULL, NULL);
|
||||
switch (gpg_err_code (rc2))
|
||||
{
|
||||
case 0: sigrc = '!'; break;
|
||||
@ -1849,6 +1855,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;
|
||||
|
||||
if (opt.skip_verify)
|
||||
{
|
||||
@ -2002,9 +2009,43 @@ 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, extrahash, extrahashlen,
|
||||
rc = do_check_sig (c, node, extrahash, extrahashlen, 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, 1, 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, extrahash, extrahashlen, included_pk,
|
||||
NULL, &is_expkey, &is_revkey, &pk);
|
||||
log_debug ("checked signature using included key block: %s\n",
|
||||
gpg_strerror (rc));
|
||||
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
|
||||
* test for this in the loop so that we can show info about the
|
||||
@ -2048,7 +2089,7 @@ check_sig_and_print (CTX c, kbnode_t node)
|
||||
res = keyserver_import_keyid (c->ctrl, sig->keyid,spec, 1);
|
||||
glo_ctrl.in_auto_key_retrieve--;
|
||||
if (!res)
|
||||
rc = do_check_sig (c, node, extrahash, extrahashlen,
|
||||
rc = do_check_sig (c, node, extrahash, extrahashlen, NULL,
|
||||
NULL, &is_expkey, &is_revkey, &pk);
|
||||
else if (DBG_LOOKUP)
|
||||
log_debug ("lookup via %s failed: %s\n", "Pref-KS",
|
||||
@ -2089,7 +2130,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, extrahash, extrahashlen,
|
||||
rc = do_check_sig (c, node, extrahash, extrahashlen, NULL,
|
||||
NULL, &is_expkey, &is_revkey, &pk);
|
||||
else if (DBG_LOOKUP)
|
||||
log_debug ("lookup via %s failed: %s\n", "WKD", gpg_strerror (res));
|
||||
@ -2124,7 +2165,7 @@ 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, extrahash, extrahashlen,
|
||||
rc = do_check_sig (c, node, extrahash, extrahashlen, NULL,
|
||||
NULL, &is_expkey, &is_revkey, &pk);
|
||||
else if (DBG_LOOKUP)
|
||||
log_debug ("lookup via %s failed: %s\n", "PKA",
|
||||
@ -2157,7 +2198,7 @@ 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, extrahash, extrahashlen,
|
||||
rc = do_check_sig (c, node, extrahash, extrahashlen, NULL,
|
||||
NULL, &is_expkey, &is_revkey, &pk);
|
||||
else if (DBG_LOOKUP)
|
||||
log_debug ("lookup via %s failed: %s\n", "KS", gpg_strerror (res));
|
||||
@ -2187,7 +2228,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]);
|
||||
@ -2500,6 +2547,7 @@ check_sig_and_print (CTX c, kbnode_t node)
|
||||
}
|
||||
|
||||
free_public_key (pk);
|
||||
release_kbnode (included_keyblock);
|
||||
xfree (issuer_fpr);
|
||||
return rc;
|
||||
}
|
||||
|
@ -224,6 +224,7 @@ typedef struct
|
||||
unsigned policy_url:1; /* At least one policy URL is present */
|
||||
unsigned notation:1; /* At least one notation is present */
|
||||
unsigned pref_ks:1; /* At least one preferred keyserver is present */
|
||||
unsigned key_block:1; /* A key block subpacket is present. */
|
||||
unsigned expired:1;
|
||||
unsigned pka_tried:1; /* Set if we tried to retrieve the PKA record. */
|
||||
} flags;
|
||||
@ -909,10 +910,11 @@ int check_signature (ctrl_t ctrl, PKT_signature *sig, gcry_md_hd_t digest);
|
||||
* R_PK is not NULL, it is stored at RET_PK.) DIGEST contains a
|
||||
* valid hash context that already includes the signed data. This
|
||||
* function adds the relevant meta-data to the hash before finalizing
|
||||
* it and verifying the signature. */
|
||||
* it and verifying the signature. FOCRED_PK is usually NULL. */
|
||||
gpg_error_t check_signature2 (ctrl_t ctrl,
|
||||
PKT_signature *sig, gcry_md_hd_t digest,
|
||||
const void *extrahash, size_t extrahashlen,
|
||||
PKT_public_key *forced_pk,
|
||||
u32 *r_expiredate, int *r_expired, int *r_revoked,
|
||||
PKT_public_key **r_pk);
|
||||
|
||||
|
@ -2195,6 +2195,10 @@ parse_signature (IOBUF inp, int pkttype, unsigned long pktlen,
|
||||
}
|
||||
}
|
||||
|
||||
p = parse_sig_subpkt (sig, 1, SIGSUBPKT_KEY_BLOCK, NULL);
|
||||
if (p)
|
||||
sig->flags.key_block = 1;
|
||||
|
||||
p = parse_sig_subpkt (sig, 1, SIGSUBPKT_NOTATION, NULL);
|
||||
if (p)
|
||||
sig->flags.notation = 1;
|
||||
|
@ -548,7 +548,7 @@ check_signatures_trust (ctrl_t ctrl, PKT_signature *sig)
|
||||
unsigned int trustlevel = TRUST_UNKNOWN;
|
||||
int rc=0;
|
||||
|
||||
rc = get_pubkey_for_sig (ctrl, pk, sig);
|
||||
rc = get_pubkey_for_sig (ctrl, pk, sig, NULL);
|
||||
if (rc)
|
||||
{ /* this should not happen */
|
||||
log_error("Ooops; the key vanished - can't check the trust\n");
|
||||
|
@ -72,7 +72,8 @@ sig_check_dump_stats (void)
|
||||
int
|
||||
check_signature (ctrl_t ctrl, PKT_signature *sig, gcry_md_hd_t digest)
|
||||
{
|
||||
return check_signature2 (ctrl, sig, digest, NULL, 0, NULL, NULL, NULL, NULL);
|
||||
return check_signature2 (ctrl, sig, digest, NULL, 0, NULL,
|
||||
NULL, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
@ -101,6 +102,9 @@ check_signature (ctrl_t ctrl, PKT_signature *sig, gcry_md_hd_t digest)
|
||||
* EXTRAHASH and EXTRAHASHLEN is additional data which is hashed with
|
||||
* v5 signatures. They may be NULL to use the default.
|
||||
*
|
||||
* If FORCED_PK is not NULL this public key is used to verify the
|
||||
* signature and no other public key is looked up.
|
||||
*
|
||||
* If R_EXPIREDATE is not NULL, R_EXPIREDATE is set to the key's
|
||||
* expiry.
|
||||
*
|
||||
@ -120,6 +124,7 @@ gpg_error_t
|
||||
check_signature2 (ctrl_t ctrl,
|
||||
PKT_signature *sig, gcry_md_hd_t digest,
|
||||
const void *extrahash, size_t extrahashlen,
|
||||
PKT_public_key *forced_pk,
|
||||
u32 *r_expiredate,
|
||||
int *r_expired, int *r_revoked, PKT_public_key **r_pk)
|
||||
{
|
||||
@ -164,7 +169,7 @@ check_signature2 (ctrl_t ctrl,
|
||||
log_info(_("WARNING: signature digest conflict in message\n"));
|
||||
rc = gpg_error (GPG_ERR_GENERAL);
|
||||
}
|
||||
else if (get_pubkey_for_sig (ctrl, pk, sig))
|
||||
else if (get_pubkey_for_sig (ctrl, pk, sig, forced_pk))
|
||||
rc = gpg_error (GPG_ERR_NO_PUBKEY);
|
||||
else if (!gnupg_pk_is_allowed (opt.compliance, PK_USE_VERIFICATION,
|
||||
pk->pubkey_algo, pk->pkey,
|
||||
@ -970,7 +975,7 @@ check_signature_over_key_or_uid (ctrl_t ctrl, PKT_public_key *signer,
|
||||
if (IS_CERT (sig))
|
||||
signer->req_usage = PUBKEY_USAGE_CERT;
|
||||
|
||||
rc = get_pubkey_for_sig (ctrl, signer, sig);
|
||||
rc = get_pubkey_for_sig (ctrl, signer, sig, NULL);
|
||||
if (rc)
|
||||
{
|
||||
xfree (signer);
|
||||
|
@ -241,14 +241,27 @@ keyserver_import_ldap (const char *name)
|
||||
}
|
||||
|
||||
gpg_error_t
|
||||
read_key_from_file (ctrl_t ctrl, const char *fname, kbnode_t *r_keyblock)
|
||||
read_key_from_file_or_buffer (ctrl_t ctrl, const char *fname,
|
||||
const void *buffer, size_t buflen,
|
||||
kbnode_t *r_keyblock)
|
||||
{
|
||||
(void)ctrl;
|
||||
(void)fname;
|
||||
(void)buffer;
|
||||
(void)buflen;
|
||||
(void)r_keyblock;
|
||||
return -1;
|
||||
}
|
||||
|
||||
gpg_error_t
|
||||
import_included_key_block (ctrl_t ctrl, kbnode_t keyblock)
|
||||
{
|
||||
(void)ctrl;
|
||||
(void)keyblock;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* Stub:
|
||||
* No encryption here but mainproc links to these functions.
|
||||
*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user