diff options
author | Werner Koch <wk@gnupg.org> | 2022-10-28 09:29:30 +0200 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2022-10-28 09:30:49 +0200 |
commit | 7aaedfb10767c74f3e6868dd1563cbbf1282ab2f (patch) | |
tree | d84a6c0554e0ce44715ddf73694f8ba53c41e7bc /g10/import.c | |
parent | agent: Automatically convert to extended key format by KEYATTR. (diff) | |
download | gnupg2-7aaedfb10767c74f3e6868dd1563cbbf1282ab2f.tar.xz gnupg2-7aaedfb10767c74f3e6868dd1563cbbf1282ab2f.zip |
gpg: Import stray revocation certificates.
* g10/kbnode.c (new_kbnode2): New.
* g10/import.c (delete_inv_parts): New arg r_otherrevsigs to store
misplaced revocations.
(import_revoke_cert): Allow to pass an entire list.
(import_one): Import revocations found by delete_inv_parts.
--
It might be useful to distribute revocations of old keys along with
new keys. This is in particicualrr useful for WKD stored keys. This
patch allows to put unrelated standalone revocations into a key. For
example they can simply appended to a keyblock. Right now it is a bit
inaesthetic to see diagnostics about misplaced or bad revocation
signatures.
Diffstat (limited to 'g10/import.c')
-rw-r--r-- | g10/import.c | 64 |
1 files changed, 51 insertions, 13 deletions
diff --git a/g10/import.c b/g10/import.c index bb0bf6793..c3ef89323 100644 --- a/g10/import.c +++ b/g10/import.c @@ -126,7 +126,8 @@ static int import_revoke_cert (ctrl_t ctrl, kbnode_t node, unsigned int options, static int chk_self_sigs (ctrl_t ctrl, kbnode_t keyblock, u32 *keyid, int *non_self); static int delete_inv_parts (ctrl_t ctrl, kbnode_t keyblock, - u32 *keyid, unsigned int options); + u32 *keyid, unsigned int options, + kbnode_t *r_otherrevsigs); static int any_uid_left (kbnode_t keyblock); static void remove_all_non_self_sigs (kbnode_t *keyblock, u32 *keyid); static int merge_blocks (ctrl_t ctrl, unsigned int options, @@ -438,7 +439,7 @@ read_key_from_file_or_buffer (ctrl_t ctrl, const char *fname, goto leave; } - if (!delete_inv_parts (ctrl, keyblock, keyid, 0) ) + if (!delete_inv_parts (ctrl, keyblock, keyid, 0, NULL) ) { err = gpg_error (GPG_ERR_NO_USER_ID); goto leave; @@ -1871,8 +1872,9 @@ update_key_origin (kbnode_t keyblock, u32 curtime, int origin, const char *url) * even most error messages are suppressed. ORIGIN is the origin of * the key (0 for unknown) and URL the corresponding URL. FROM_SK * indicates that the key has been made from a secret key. If R_SAVED - * is not NULL a boolean will be stored indicating whether the keyblock - * has valid parts. + * is not NULL a boolean will be stored indicating whether the + * keyblock has valid parts. Unless OTHERREVSIGS is NULL it is + * updated with encountered new revocation signatures. */ static gpg_error_t import_one_real (ctrl_t ctrl, @@ -1880,7 +1882,8 @@ import_one_real (ctrl_t ctrl, unsigned char **fpr, size_t *fpr_len, unsigned int options, int from_sk, int silent, import_screener_t screener, void *screener_arg, - int origin, const char *url, int *r_valid) + int origin, const char *url, int *r_valid, + kbnode_t *otherrevsigs) { gpg_error_t err = 0; PKT_public_key *pk; @@ -2021,7 +2024,7 @@ import_one_real (ctrl_t ctrl, } /* Delete invalid parts and bail out if there are no user ids left. */ - if (!delete_inv_parts (ctrl, keyblock, keyid, options)) + if (!delete_inv_parts (ctrl, keyblock, keyid, options, otherrevsigs)) { if (!silent) { @@ -2413,10 +2416,12 @@ import_one (ctrl_t ctrl, int origin, const char *url, int *r_valid) { gpg_error_t err; + kbnode_t otherrevsigs = NULL; + kbnode_t node; err = import_one_real (ctrl, keyblock, stats, fpr, fpr_len, options, from_sk, silent, screener, screener_arg, - origin, url, r_valid); + origin, url, r_valid, &otherrevsigs); if (gpg_err_code (err) == GPG_ERR_TOO_LARGE && gpg_err_source (err) == GPG_ERR_SOURCE_KEYBOX && ((options & (IMPORT_SELF_SIGS_ONLY | IMPORT_CLEAN)) @@ -2432,8 +2437,17 @@ import_one (ctrl_t ctrl, options |= IMPORT_SELF_SIGS_ONLY | IMPORT_CLEAN; err = import_one_real (ctrl, keyblock, stats, fpr, fpr_len, options, from_sk, silent, screener, screener_arg, - origin, url, r_valid); + origin, url, r_valid, &otherrevsigs); } + + /* Finally try to import other revocation certificates. For example + * those of a former key appended to the current key. */ + if (!err) + { + for (node = otherrevsigs; node; node = node->next) + import_revoke_cert (ctrl, node, options, stats); + } + release_kbnode (otherrevsigs); return err; } @@ -3422,9 +3436,8 @@ list_standalone_revocation (ctrl_t ctrl, PKT_signature *sig, int sigrc) } -/**************** - * Import a revocation certificate; this is a single signature packet. - */ +/* Import a revocation certificate; only the first packet in the + * NODE-list is considered. */ static int import_revoke_cert (ctrl_t ctrl, kbnode_t node, unsigned int options, struct import_stats_s *stats) @@ -3441,10 +3454,12 @@ import_revoke_cert (ctrl_t ctrl, kbnode_t node, unsigned int options, /* No error output for --show-keys. */ silent = (options & (IMPORT_SHOW | IMPORT_DRY_RUN)); - log_assert (!node->next ); log_assert (node->pkt->pkttype == PKT_SIGNATURE ); log_assert (IS_KEY_REV (node->pkt->pkt.signature)); + /* FIXME: We can do better here by using the issuer fingerprint if + * available. We should also make use of get_keyblock_byfprint_fast. */ + keyid[0] = node->pkt->pkt.signature->keyid[0]; keyid[1] = node->pkt->pkt.signature->keyid[1]; @@ -3788,12 +3803,15 @@ chk_self_sigs (ctrl_t ctrl, kbnode_t keyblock, u32 *keyid, int *non_self) /* Delete all parts which are invalid and those signatures whose * public key algorithm is not available in this implementation; but * consider RSA as valid, because parse/build_packets knows about it. + * If R_OTHERREVSIGS is not NULL, it is used to return a list of + * revocation certificates which have been deleted from KEYBLOCK but + * should be handled later. * * Returns: True if at least one valid user-id is left over. */ static int delete_inv_parts (ctrl_t ctrl, kbnode_t keyblock, u32 *keyid, - unsigned int options) + unsigned int options, kbnode_t *r_otherrevsigs) { kbnode_t node; int nvalid=0, uid_seen=0, subkey_seen=0; @@ -3883,6 +3901,16 @@ delete_inv_parts (ctrl_t ctrl, kbnode_t keyblock, u32 *keyid, if(opt.verbose) log_info( _("key %s: revocation certificate" " at wrong place - skipped\n"),keystr(keyid)); + if (r_otherrevsigs) + { + PACKET *pkt; + + pkt = xcalloc (1, sizeof *pkt); + pkt->pkttype = PKT_SIGNATURE; + pkt->pkt.signature = copy_signature + (NULL, node->pkt->pkt.signature); + *r_otherrevsigs = new_kbnode2 (*r_otherrevsigs, pkt); + } delete_kbnode( node ); } else @@ -3905,6 +3933,16 @@ delete_inv_parts (ctrl_t ctrl, kbnode_t keyblock, u32 *keyid, delete_kbnode( node ); } } + else if (r_otherrevsigs) + { + PACKET *pkt; + + pkt = xcalloc (1, sizeof *pkt); + pkt->pkttype = PKT_SIGNATURE; + pkt->pkt.signature = copy_signature + (NULL, node->pkt->pkt.signature); + *r_otherrevsigs = new_kbnode2 (*r_otherrevsigs, pkt); + } } } else if (node->pkt->pkttype == PKT_SIGNATURE |