[git] GnuPG - branch, STABLE-BRANCH-2-2, updated. gnupg-2.2.4-31-gee47485
by Werner Koch
cvs at cvs.gnupg.org
Tue Feb 20 11:52:00 CET 2018
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "The GNU Privacy Guard".
The branch, STABLE-BRANCH-2-2 has been updated
via ee474856ec16ff11d922d8503fb3ede77129c4aa (commit)
from 1877603761911ea5b1c15f4aef11a2cf86a8682c (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit ee474856ec16ff11d922d8503fb3ede77129c4aa
Author: Werner Koch <wk at gnupg.org>
Date: Tue Feb 20 11:45:58 2018 +0100
wks: Implement server command --install-key.
* tools/wks-util.c (wks_filter_uid): Add arg 'binary'.
* tools/gpg-wks-server.c (main): Expect 2 args for --install-key.
(write_to_file): New.
(check_and_publish): Factor some code out to ...
(compute_hu_fname): ... new.
(command_install_key): Implement.
Signed-off-by: Werner Koch <wk at gnupg.org>
diff --git a/doc/wks.texi b/doc/wks.texi
index 7f7d515..2960c67 100644
--- a/doc/wks.texi
+++ b/doc/wks.texi
@@ -181,6 +181,7 @@ Display a brief help page and exit.
.RI [ options ]
.B \-\-install-key
.I file
+.I user-id
.br
.B gpg-wks-server
.RI [ options ]
@@ -221,14 +222,17 @@ the process returns failure; to suppress the diagnostic, use option
@option{-q}. More than one user-id can be given; see also option
@option{with-file}.
+The command @option{--install-key} manually installs a key into the
+WKD. The arguments are a file with the keyblock and the user-id to
+install.
+
The command @option{--remove-key} uninstalls a key from the WKD. The
-process return success in this case; to also print a diagnostic, use
-option @option{-v}. If the key is not installed a diagnostics is
+process returns success in this case; to also print a diagnostic, use
+option @option{-v}. If the key is not installed a diagnostic is
printed and the process returns failure; to suppress the diagnostic,
use option @option{-q}.
-The commands @option{--install-key} and @option{--revoke-key} are not
-yet functional.
+The command @option{--revoke-key} is not yet functional.
@mansect options
diff --git a/tools/gpg-wks-client.c b/tools/gpg-wks-client.c
index b86491e..3b19c76 100644
--- a/tools/gpg-wks-client.c
+++ b/tools/gpg-wks-client.c
@@ -872,7 +872,7 @@ command_send (const char *fingerprint, const char *userid)
estream_t newkey;
es_rewind (key);
- err = wks_filter_uid (&newkey, key, thisuid->uid);
+ err = wks_filter_uid (&newkey, key, thisuid->uid, 0);
if (err)
{
log_error ("error filtering key: %s\n", gpg_strerror (err));
diff --git a/tools/gpg-wks-server.c b/tools/gpg-wks-server.c
index 008c266..e2b8306 100644
--- a/tools/gpg-wks-server.c
+++ b/tools/gpg-wks-server.c
@@ -1,5 +1,5 @@
/* gpg-wks-server.c - A server for the Web Key Service protocols.
- * Copyright (C) 2016 Werner Koch
+ * Copyright (C) 2016, 2018 Werner Koch
* Copyright (C) 2016 Bundesamt für Sicherheit in der Informationstechnik
*
* This file is part of GnuPG.
@@ -20,7 +20,7 @@
/* The Web Key Service I-D defines an update protocol to store a
* public key in the Web Key Directory. The current specification is
- * draft-koch-openpgp-webkey-service-01.txt.
+ * draft-koch-openpgp-webkey-service-05.txt.
*/
#include <config.h>
@@ -154,7 +154,7 @@ static gpg_error_t command_receive_cb (void *opaque,
const char *mediatype, estream_t fp,
unsigned int flags);
static gpg_error_t command_list_domains (void);
-static gpg_error_t command_install_key (const char *fname);
+static gpg_error_t command_install_key (const char *fname, const char *userid);
static gpg_error_t command_remove_key (const char *mailaddr);
static gpg_error_t command_revoke_key (const char *mailaddr);
static gpg_error_t command_check_key (const char *mailaddr);
@@ -376,9 +376,9 @@ main (int argc, char **argv)
break;
case aInstallKey:
- if (argc != 1)
- wrong_args ("--install-key FILE");
- err = command_install_key (*argv);
+ if (argc != 2)
+ wrong_args ("--install-key FILE USER-ID");
+ err = command_install_key (*argv, argv[1]);
break;
case aRemoveKey:
@@ -1339,6 +1339,81 @@ send_congratulation_message (const char *mbox, const char *keyfile)
}
+/* Write the content of SRC to the new file FNAME. */
+static gpg_error_t
+write_to_file (estream_t src, const char *fname)
+{
+ gpg_error_t err;
+ estream_t dst;
+ char buffer[4096];
+ size_t nread, written;
+
+ dst = es_fopen (fname, "wb");
+ if (!dst)
+ return gpg_error_from_syserror ();
+
+ do
+ {
+ nread = es_fread (buffer, 1, sizeof buffer, src);
+ if (!nread)
+ break;
+ written = es_fwrite (buffer, 1, nread, dst);
+ if (written != nread)
+ break;
+ }
+ while (!es_feof (src) && !es_ferror (src) && !es_ferror (dst));
+ if (!es_feof (src) || es_ferror (src) || es_ferror (dst))
+ {
+ err = gpg_error_from_syserror ();
+ es_fclose (dst);
+ gnupg_remove (fname);
+ return err;
+ }
+
+ if (es_fclose (dst))
+ {
+ err = gpg_error_from_syserror ();
+ log_error ("error closing '%s': %s\n", fname, gpg_strerror (err));
+ return err;
+ }
+
+ return 0;
+}
+
+
+/* Compute the the full file name for the key with ADDRSPEC and return
+ * it at R_FNAME. */
+static gpg_error_t
+compute_hu_fname (char **r_fname, const char *addrspec)
+{
+ gpg_error_t err;
+ char *hash;
+ const char *domain;
+ char sha1buf[20];
+
+ *r_fname = NULL;
+
+ domain = strchr (addrspec, '@');
+ if (!domain || !domain[1] || domain == addrspec)
+ return gpg_error (GPG_ERR_INV_ARG);
+ domain++;
+
+ gcry_md_hash_buffer (GCRY_MD_SHA1, sha1buf, addrspec, domain - addrspec - 1);
+ hash = zb32_encode (sha1buf, 8*20);
+ if (!hash)
+ return gpg_error_from_syserror ();
+
+ *r_fname = make_filename_try (opt.directory, domain, "hu", hash, NULL);
+ if (!*r_fname)
+ err = gpg_error_from_syserror ();
+ else
+ err = 0;
+
+ xfree (hash);
+ return err;
+}
+
+
/* Check that we have send a request with NONCE and publish the key. */
static gpg_error_t
check_and_publish (server_ctx_t ctx, const char *address, const char *nonce)
@@ -1412,24 +1487,10 @@ check_and_publish (server_ctx_t ctx, const char *address, const char *nonce)
goto leave;
}
-
/* Hash user ID and create filename. */
- s = strchr (address, '@');
- log_assert (s);
- gcry_md_hash_buffer (GCRY_MD_SHA1, shaxbuf, address, s - address);
- hash = zb32_encode (shaxbuf, 8*20);
- if (!hash)
- {
- err = gpg_error_from_syserror ();
- goto leave;
- }
-
- fnewname = make_filename_try (opt.directory, domain, "hu", hash, NULL);
- if (!fnewname)
- {
- err = gpg_error_from_syserror ();
- goto leave;
- }
+ err = compute_hu_fname (&fnewname, address);
+ if (err)
+ goto leave;
/* Publish. */
err = copy_key_as_binary (fname, fnewname, address);
@@ -1935,16 +1996,122 @@ command_cron (void)
}
-/* Install a single key into the WKD by reading FNAME. */
+/* Install a single key into the WKD by reading FNAME and extracting
+ * USERID. */
static gpg_error_t
-command_install_key (const char *fname)
+command_install_key (const char *fname, const char *userid)
{
- (void)fname;
- return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+ gpg_error_t err;
+ estream_t fp;
+ char *addrspec = NULL;
+ char *fpr = NULL;
+ uidinfo_list_t uidlist = NULL;
+ uidinfo_list_t uid, thisuid;
+ time_t thistime;
+ char *huname = NULL;
+ int any;
+
+ fp = es_fopen (fname, "rb");
+ if (!fp)
+ {
+ err = gpg_error_from_syserror ();
+ log_error ("error reading '%s': %s\n", fname, gpg_strerror (err));
+ goto leave;
+ }
+
+ addrspec = mailbox_from_userid (userid);
+ if (!addrspec)
+ {
+ log_error ("\"%s\" is not a proper mail address\n", userid);
+ err = gpg_error (GPG_ERR_INV_USER_ID);
+ goto leave;
+ }
+
+ /* List the key so that we can figure out the newest UID with the
+ * requested addrspec. */
+ err = wks_list_key (fp, &fpr, &uidlist);
+ if (err)
+ {
+ log_error ("error parsing key: %s\n", gpg_strerror (err));
+ err = gpg_error (GPG_ERR_NO_PUBKEY);
+ goto leave;
+ }
+ thistime = 0;
+ thisuid = NULL;
+ any = 0;
+ for (uid = uidlist; uid; uid = uid->next)
+ {
+ if (!uid->mbox)
+ continue; /* Should not happen anyway. */
+ if (ascii_strcasecmp (uid->mbox, addrspec))
+ continue; /* Not the requested addrspec. */
+ any = 1;
+ if (uid->created > thistime)
+ {
+ thistime = uid->created;
+ thisuid = uid;
+ }
+ }
+ if (!thisuid)
+ thisuid = uidlist; /* This is the case for a missing timestamp. */
+ if (!any)
+ {
+ log_error ("public key in '%s' has no mail address '%s'\n",
+ fname, addrspec);
+ err = gpg_error (GPG_ERR_INV_USER_ID);
+ goto leave;
+ }
+
+ if (opt.verbose)
+ log_info ("using key with user id '%s'\n", thisuid->uid);
+
+ {
+ estream_t fp2;
+
+ es_rewind (fp);
+ err = wks_filter_uid (&fp2, fp, thisuid->uid, 1);
+ if (err)
+ {
+ log_error ("error filtering key: %s\n", gpg_strerror (err));
+ err = gpg_error (GPG_ERR_NO_PUBKEY);
+ goto leave;
+ }
+ es_fclose (fp);
+ fp = fp2;
+ }
+
+ /* Hash user ID and create filename. */
+ err = compute_hu_fname (&huname, addrspec);
+ if (err)
+ goto leave;
+
+ /* Publish. */
+ err = write_to_file (fp, huname);
+ if (err)
+ {
+ log_error ("copying key to '%s' failed: %s\n", huname,gpg_strerror (err));
+ goto leave;
+ }
+
+ /* Make sure it is world readable. */
+ if (gnupg_chmod (huname, "-rwxr--r--"))
+ log_error ("can't set permissions of '%s': %s\n",
+ huname, gpg_strerror (gpg_err_code_from_syserror()));
+
+ if (!opt.quiet)
+ log_info ("key %s published for '%s'\n", fpr, addrspec);
+
+ leave:
+ xfree (huname);
+ free_uidinfo_list (uidlist);
+ xfree (fpr);
+ xfree (addrspec);
+ es_fclose (fp);
+ return err;
}
-/* Return the filename and optioanlly the addrspec for USERID at
+/* Return the filename and optionally the addrspec for USERID at
* R_FNAME and R_ADDRSPEC. R_ADDRSPEC might also be set on error. */
static gpg_error_t
fname_from_userid (const char *userid, char **r_fname, char **r_addrspec)
diff --git a/tools/gpg-wks.h b/tools/gpg-wks.h
index 1522b72..a5a73c5 100644
--- a/tools/gpg-wks.h
+++ b/tools/gpg-wks.h
@@ -89,7 +89,7 @@ void free_uidinfo_list (uidinfo_list_t list);
gpg_error_t wks_list_key (estream_t key, char **r_fpr,
uidinfo_list_t *r_mboxes);
gpg_error_t wks_filter_uid (estream_t *r_newkey, estream_t key,
- const char *uid);
+ const char *uid, int binary);
gpg_error_t wks_send_mime (mime_maker_t mime);
gpg_error_t wks_parse_policy (policy_flags_t flags, estream_t stream,
int ignore_unknown);
diff --git a/tools/wks-util.c b/tools/wks-util.c
index 9c0f489..33f1ae7 100644
--- a/tools/wks-util.c
+++ b/tools/wks-util.c
@@ -317,10 +317,13 @@ wks_list_key (estream_t key, char **r_fpr, uidinfo_list_t *r_mboxes)
/* Run gpg as a filter on KEY and write the output to a new stream
- * stored at R_NEWKEY. The new key will containn only the user id
- * UID. Returns 0 on success. Only one key is expected in KEY. */
+ * stored at R_NEWKEY. The new key will contain only the user id UID.
+ * Returns 0 on success. Only one key is expected in KEY. If BINARY
+ * is set the resulting key is returned as a binary (non-armored)
+ * keyblock. */
gpg_error_t
-wks_filter_uid (estream_t *r_newkey, estream_t key, const char *uid)
+wks_filter_uid (estream_t *r_newkey, estream_t key, const char *uid,
+ int binary)
{
gpg_error_t err;
ccparray_t ccp;
@@ -340,8 +343,9 @@ wks_filter_uid (estream_t *r_newkey, estream_t key, const char *uid)
}
/* Prefix the key with the MIME content type. */
- es_fputs ("Content-Type: application/pgp-keys\n"
- "\n", newkey);
+ if (!binary)
+ es_fputs ("Content-Type: application/pgp-keys\n"
+ "\n", newkey);
filterexp = es_bsprintf ("keep-uid=uid=%s", uid);
if (!filterexp)
@@ -361,7 +365,8 @@ wks_filter_uid (estream_t *r_newkey, estream_t key, const char *uid)
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, "--import-options=import-export");
ccparray_put (&ccp, "--import-filter");
ccparray_put (&ccp, filterexp);
-----------------------------------------------------------------------
Summary of changes:
doc/wks.texi | 12 ++-
tools/gpg-wks-client.c | 2 +-
tools/gpg-wks-server.c | 223 ++++++++++++++++++++++++++++++++++++++++++-------
tools/gpg-wks.h | 2 +-
tools/wks-util.c | 17 ++--
5 files changed, 216 insertions(+), 40 deletions(-)
hooks/post-receive
--
The GNU Privacy Guard
http://git.gnupg.org
More information about the Gnupg-commits
mailing list