diff options
author | Werner Koch <[email protected]> | 2022-11-29 15:47:44 +0000 |
---|---|---|
committer | Werner Koch <[email protected]> | 2022-11-29 16:17:50 +0000 |
commit | c3f9f2d497b174ceb12c2dde35225a6ba016c835 (patch) | |
tree | ad62605e086af0dcc4d57f73ed95001550ae6128 /tools/wks-util.c | |
parent | doc: Comment typo fix (diff) | |
download | gnupg-c3f9f2d497b174ceb12c2dde35225a6ba016c835.tar.gz gnupg-c3f9f2d497b174ceb12c2dde35225a6ba016c835.zip |
wkd: New option --add-revocs and some fixes.
* tools/gpg-wks.h (opt): Add add_revocs.
* tools/wks-util.c (wks_get_key): Add arg 'binary'.
(wks_armor_key): New.
(wks_find_add_revocs): New.
(wks_cmd_install_key): Get key in binary mode and add revocations if
enabled.
* tools/gpg-wks-client.c (oAddRevocs): New.
(opts): Add --add-revocs.
(parse_arguments): Set option,
(command_send): Get key in binary mode, add revocations if enabled,
and explictly armor key. Remove kludge to skip the Content-type line
in no_encrypt mode.
(mirror_one_keys_userid): Always filter the key to get rid of the
armor as received from dirmngr. Add revocations from the local
keyring.
--
Note that this also fixes an oddity of the new mirror command which
used to store the keys armored as received from dirmngr.
Diffstat (limited to 'tools/wks-util.c')
-rw-r--r-- | tools/wks-util.c | 151 |
1 files changed, 145 insertions, 6 deletions
diff --git a/tools/wks-util.c b/tools/wks-util.c index a25ca47a5..1472f7035 100644 --- a/tools/wks-util.c +++ b/tools/wks-util.c @@ -193,10 +193,11 @@ get_key_status_cb (void *opaque, const char *keyword, char *args) * mail address ADDRSPEC is included in the key. If EXACT is set the * returned user id must match Addrspec exactly and not just in the * addr-spec (mailbox) part. The key is returned as a new memory - * stream at R_KEY. */ + * stream at R_KEY. If BINARY is set the returned key is + * non-armored. */ gpg_error_t wks_get_key (estream_t *r_key, const char *fingerprint, const char *addrspec, - int exact) + int exact, int binary) { gpg_error_t err; ccparray_t ccp; @@ -218,8 +219,9 @@ wks_get_key (estream_t *r_key, const char *fingerprint, const char *addrspec, } /* Prefix the key with the MIME content type. */ - es_fputs ("Content-Type: application/pgp-keys\n" - "\n", key); + if (!binary) + es_fputs ("Content-Type: application/pgp-keys\n" + "\n", key); filterexp = es_bsprintf ("keep-uid=%s= %s", exact? "uid":"mbox", addrspec); if (!filterexp) @@ -239,7 +241,8 @@ wks_get_key (estream_t *r_key, const char *fingerprint, const char *addrspec, ccparray_put (&ccp, "--batch"); ccparray_put (&ccp, "--status-fd=2"); ccparray_put (&ccp, "--always-trust"); - ccparray_put (&ccp, "--armor"); + if (!binary) + ccparray_put (&ccp, "--armor"); ccparray_put (&ccp, "--export-options=export-minimal"); ccparray_put (&ccp, "--export-filter"); ccparray_put (&ccp, filterexp); @@ -550,6 +553,124 @@ wks_filter_uid (estream_t *r_newkey, estream_t key, const char *uid, } +/* Put the ascii-armor around KEY and return that as a new estream + * object at R_NEWKEY. Caller must make sure that KEY has been seeked + * to the right position (usually by calling es_rewind). The + * resulting NEWKEY has already been rewound. If PREFIX is not NULL, + * its content is written to NEWKEY propr to the armor; this may be + * used for MIME headers. */ +gpg_error_t +wks_armor_key (estream_t *r_newkey, estream_t key, const char *prefix) +{ + gpg_error_t err; + estream_t newkey; + struct b64state b64state; + char buffer[4096]; + size_t nread; + + *r_newkey = NULL; + + newkey = es_fopenmem (0, "w+b"); + if (!newkey) + { + err = gpg_error_from_syserror (); + return err; + } + + if (prefix) + es_fputs (prefix, newkey); + + err = b64enc_start_es (&b64state, newkey, "PGP PUBLIC KEY BLOCK"); + if (err) + goto leave; + + do + { + nread = es_fread (buffer, 1, sizeof buffer, key); + if (!nread) + break; + err = b64enc_write (&b64state, buffer, nread); + if (err) + goto leave; + } + while (!es_feof (key) && !es_ferror (key)); + if (!es_feof (key) || es_ferror (key)) + { + err = gpg_error_from_syserror (); + goto leave; + } + + err = b64enc_finish (&b64state); + if (err) + goto leave; + + es_rewind (newkey); + *r_newkey = newkey; + newkey = NULL; + + leave: + es_fclose (newkey); + return err; +} + + +/* Run gpg to export the revocation certificates for ADDRSPEC. Add + * them to KEY which is expected to be non-armored keyblock. */ +gpg_error_t +wks_find_add_revocs (estream_t key, const char *addrspec) +{ + gpg_error_t err; + ccparray_t ccp; + const char **argv = NULL; + char *filterexp = NULL; + + filterexp = es_bsprintf ("select=mbox= %s", addrspec); + if (!filterexp) + { + err = gpg_error_from_syserror (); + log_error ("error allocating memory buffer: %s\n", gpg_strerror (err)); + goto leave; + } + + ccparray_init (&ccp, 0); + + ccparray_put (&ccp, "--no-options"); + if (opt.verbose < 2) + ccparray_put (&ccp, "--quiet"); + else + ccparray_put (&ccp, "--verbose"); + ccparray_put (&ccp, "--batch"); + ccparray_put (&ccp, "--status-fd=2"); + ccparray_put (&ccp, "--export-options=export-revocs"); + ccparray_put (&ccp, "--export-filter"); + ccparray_put (&ccp, filterexp); + ccparray_put (&ccp, "--export"); + ccparray_put (&ccp, addrspec); + + ccparray_put (&ccp, NULL); + argv = ccparray_get (&ccp, NULL); + if (!argv) + { + err = gpg_error_from_syserror (); + goto leave; + } + debug_gpg_invocation (__func__, argv); + err = gnupg_exec_tool_stream (opt.gpg_program, argv, NULL, + NULL, key, + key_status_cb, NULL); + if (err) + { + log_error ("exporting revocs failed: %s\n", gpg_strerror (err)); + goto leave; + } + + leave: + xfree (filterexp); + xfree (argv); + return err; +} + + /* Helper to write mail to the output(s). */ gpg_error_t wks_send_mime (mime_maker_t mime) @@ -1121,7 +1242,7 @@ wks_cmd_install_key (const char *fname, const char *userid) { /* FNAME looks like a fingerprint. Get the key from the * standard keyring. */ - err = wks_get_key (&fp, fname, addrspec, 0); + err = wks_get_key (&fp, fname, addrspec, 0, 1); if (err) { log_error ("error getting key '%s' (uid='%s'): %s\n", @@ -1193,6 +1314,24 @@ wks_cmd_install_key (const char *fname, const char *userid) fp = fp2; } + if (opt.add_revocs) + { + if (es_fseek (fp, 0, SEEK_END)) + { + err = gpg_error_from_syserror (); + log_error ("error seeking stream: %s\n", gpg_strerror (err)); + goto leave; + } + err = wks_find_add_revocs (fp, addrspec); + if (err) + { + log_error ("error finding revocations for '%s': %s\n", + addrspec, gpg_strerror (err)); + goto leave; + } + es_rewind (fp); + } + err = wks_install_key_core (fp, addrspec); if (!opt.quiet) log_info ("key %s published for '%s'\n", fpr, addrspec); |