diff options
author | Werner Koch <wk@gnupg.org> | 2020-03-13 17:14:34 +0100 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2020-03-13 17:14:34 +0100 |
commit | 6a4443c8425fd548020553b22d5a16ffad98371f (patch) | |
tree | 75da2b6c4ce956ef3923abef180ba079a40d770e /g10/import.c | |
parent | gpg: New option --include-key-block. (diff) | |
download | gnupg2-6a4443c8425fd548020553b22d5a16ffad98371f.tar.xz gnupg2-6a4443c8425fd548020553b22d5a16ffad98371f.zip |
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>
Diffstat (limited to 'g10/import.c')
-rw-r--r-- | g10/import.c | 102 |
1 files changed, 74 insertions, 28 deletions
diff --git a/g10/import.c b/g10/import.c index 77c05c1f1..b7101a9bf 100644 --- a/g10/import.c +++ b/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,36 +336,46 @@ 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))) + log_assert (!!fname ^ !!buffer); + + if (fname) { - iobuf_close (inp); - inp = NULL; - err = gpg_error (GPG_ERR_EPERM); + 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 - err = 0; - if (err) + else /* Read from buffer (No armor expected). */ { - 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; + inp = iobuf_temp_with_content (buffer, buflen); } - /* 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); - } - /* 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. |