wks: Add special mode to --install-key.
authorWerner Koch <wk@gnupg.org>
Tue, 20 Feb 2018 14:23:19 +0000 (15:23 +0100)
committerWerner Koch <wk@gnupg.org>
Tue, 20 Feb 2018 14:23:19 +0000 (15:23 +0100)
* tools/gpg-wks-client.c (get_key_status_parm_s)
(get_key_status_cb, get_key): Move to ...
* tools/wks-util.c: ...here.
(get_key): Rename to wks_get_key.
* tools/gpg-wks-server.c: Include userids.h.
(command_install_key): Allow use of a fingerprint.

Signed-off-by: Werner Koch <wk@gnupg.org>
doc/wks.texi
tools/gpg-wks-client.c
tools/gpg-wks-server.c
tools/gpg-wks.h
tools/wks-util.c

index 2960c67..6d62282 100644 (file)
@@ -224,7 +224,9 @@ the process returns failure; to suppress the diagnostic, use option
 
 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.
+install.  If the first argument resembles a fingerprint the key is
+taken from the current keyring; to force the use of a file, prefix the
+first argument with "./".
 
 The command @option{--remove-key} uninstalls a key from the WKD.  The
 process returns success in this case; to also print a diagnostic, use
@@ -330,7 +332,7 @@ the submission address:
 
 @example
   $ gpg --batch --passphrase '' --quick-gen-key key-submission@@example.net
-  $ gpg --with-wkd-hash -K key-submission@@example.net
+  $ gpg -K key-submission@@example.net
 @end example
 
 The output of the last command looks similar to this:
@@ -339,21 +341,16 @@ The output of the last command looks similar to this:
   sec   rsa2048 2016-08-30 [SC]
         C0FCF8642D830C53246211400346653590B3795B
   uid           [ultimate] key-submission@@example.net
-                bxzcxpxk8h87z1k7bzk86xn5aj47intu@@example.net
   ssb   rsa2048 2016-08-30 [E]
 @end example
 
-Take the hash of the string "key-submission", which is
-"bxzcxpxk8h87z1k7bzk86xn5aj47intu" and manually publish that key:
+Take the fingerprint from that output and manually publish the key:
 
 @example
-  $ gpg --export-options export-minimal --export \
-  >  -o /var/lib/gnupg/wks/example.net/hu/bxzcxpxk8h87z1k7bzk86xn5aj47intu \
-  >  key-submission@@example.new
+  $ gpg-wks-server --install-key C0FCF8642D830C53246211400346653590B3795B \
+  >                key-submission@@example.net
 @end example
 
-Make sure that the created file is world readable.
-
 Finally that submission address needs to be redirected to a script
 running @command{gpg-wks-server}.  The @command{procmail} command can
 be used for this: Redirect the submission address to the user "webkey"
index 3b19c76..73945ff 100644 (file)
@@ -325,119 +325,6 @@ main (int argc, char **argv)
 
 
 \f
-struct get_key_status_parm_s
-{
-  const char *fpr;
-  int found;
-  int count;
-};
-
-static void
-get_key_status_cb (void *opaque, const char *keyword, char *args)
-{
-  struct get_key_status_parm_s *parm = opaque;
-
-  /*log_debug ("%s: %s\n", keyword, args);*/
-  if (!strcmp (keyword, "EXPORTED"))
-    {
-      parm->count++;
-      if (!ascii_strcasecmp (args, parm->fpr))
-        parm->found = 1;
-    }
-}
-
-
-/* Get a key by fingerprint from gpg's keyring and make sure that the
- * 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.  */
-static gpg_error_t
-get_key (estream_t *r_key, const char *fingerprint, const char *addrspec,
-         int exact)
-{
-  gpg_error_t err;
-  ccparray_t ccp;
-  const char **argv = NULL;
-  estream_t key = NULL;
-  struct get_key_status_parm_s parm;
-  char *filterexp = NULL;
-
-  memset (&parm, 0, sizeof parm);
-
-  *r_key = NULL;
-
-  key = es_fopenmem (0, "w+b");
-  if (!key)
-    {
-      err = gpg_error_from_syserror ();
-      log_error ("error allocating memory buffer: %s\n", gpg_strerror (err));
-      goto leave;
-    }
-
-  /* Prefix the key with the MIME content type.  */
-  es_fputs ("Content-Type: application/pgp-keys\n"
-            "\n", key);
-
-  filterexp = es_bsprintf ("keep-uid=%s=%s", exact? "uid":"mbox", 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)
-    ccparray_put (&ccp, "--quiet");
-  else if (opt.verbose > 1)
-    ccparray_put (&ccp, "--verbose");
-  ccparray_put (&ccp, "--batch");
-  ccparray_put (&ccp, "--status-fd=2");
-  ccparray_put (&ccp, "--always-trust");
-  ccparray_put (&ccp, "--armor");
-  ccparray_put (&ccp, "--export-options=export-minimal");
-  ccparray_put (&ccp, "--export-filter");
-  ccparray_put (&ccp, filterexp);
-  ccparray_put (&ccp, "--export");
-  ccparray_put (&ccp, "--");
-  ccparray_put (&ccp, fingerprint);
-
-  ccparray_put (&ccp, NULL);
-  argv = ccparray_get (&ccp, NULL);
-  if (!argv)
-    {
-      err = gpg_error_from_syserror ();
-      goto leave;
-    }
-  parm.fpr = fingerprint;
-  err = gnupg_exec_tool_stream (opt.gpg_program, argv, NULL,
-                                NULL, key,
-                                get_key_status_cb, &parm);
-  if (!err && parm.count > 1)
-    err = gpg_error (GPG_ERR_TOO_MANY);
-  else if (!err && !parm.found)
-    err = gpg_error (GPG_ERR_NOT_FOUND);
-  if (err)
-    {
-      log_error ("export failed: %s\n", gpg_strerror (err));
-      goto leave;
-    }
-
-  es_rewind (key);
-  *r_key = key;
-  key = NULL;
-
- leave:
-  es_fclose (key);
-  xfree (argv);
-  xfree (filterexp);
-  return err;
-}
-
-
 /* Add the user id UID to the key identified by FINGERPRINT.  */
 static gpg_error_t
 add_user_id (const char *fingerprint, const char *uid)
@@ -767,7 +654,7 @@ command_send (const char *fingerprint, const char *userid)
       err = gpg_error (GPG_ERR_INV_USER_ID);
       goto leave;
     }
-  err = get_key (&key, fingerprint, addrspec, 0);
+  err = wks_get_key (&key, fingerprint, addrspec, 0);
   if (err)
     goto leave;
 
@@ -897,7 +784,7 @@ command_send (const char *fingerprint, const char *userid)
        * the key again.  */
       es_fclose (key);
       key = NULL;
-      err = get_key (&key, fingerprint, addrspec, 1);
+      err = wks_get_key (&key, fingerprint, addrspec, 1);
       if (err)
         goto leave;
     }
index e2b8306..a588155 100644 (file)
@@ -35,6 +35,7 @@
 #include "../common/util.h"
 #include "../common/init.h"
 #include "../common/sysutils.h"
+#include "../common/userids.h"
 #include "../common/ccparray.h"
 #include "../common/exectool.h"
 #include "../common/zb32.h"
@@ -2002,7 +2003,8 @@ static gpg_error_t
 command_install_key (const char *fname, const char *userid)
 {
   gpg_error_t err;
-  estream_t fp;
+  KEYDB_SEARCH_DESC desc;
+  estream_t fp = NULL;
   char *addrspec = NULL;
   char *fpr = NULL;
   uidinfo_list_t uidlist = NULL;
@@ -2011,14 +2013,6 @@ command_install_key (const char *fname, const char *userid)
   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)
     {
@@ -2027,6 +2021,31 @@ command_install_key (const char *fname, const char *userid)
       goto leave;
     }
 
+  if (!classify_user_id (fname, &desc, 1)
+      && (desc.mode == KEYDB_SEARCH_MODE_FPR
+          || desc.mode == KEYDB_SEARCH_MODE_FPR20))
+    {
+      /* FNAME looks like a fingerprint.  Get the key from the
+       * standard keyring.  */
+      err = wks_get_key (&fp, fname, addrspec, 0);
+      if (err)
+        {
+          log_error ("error getting key '%s' (uid='%s'): %s\n",
+                     fname, addrspec, gpg_strerror (err));
+          goto leave;
+        }
+    }
+  else /* Take it from the file */
+    {
+      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;
+        }
+    }
+
   /* List the key so that we can figure out the newest UID with the
    * requested addrspec.  */
   err = wks_list_key (fp, &fpr, &uidlist);
index a5a73c5..1b91b65 100644 (file)
@@ -86,6 +86,8 @@ typedef struct uidinfo_list_s *uidinfo_list_t;
 void wks_set_status_fd (int fd);
 void wks_write_status (int no, const char *format, ...) GPGRT_ATTR_PRINTF(2,3);
 void free_uidinfo_list (uidinfo_list_t list);
+gpg_error_t wks_get_key (estream_t *r_key, const char *fingerprint,
+                         const char *addrspec, int exact);
 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,
index 33f1ae7..3fd824c 100644 (file)
@@ -133,6 +133,120 @@ free_uidinfo_list (uidinfo_list_t list)
 
 
 \f
+struct get_key_status_parm_s
+{
+  const char *fpr;
+  int found;
+  int count;
+};
+
+
+static void
+get_key_status_cb (void *opaque, const char *keyword, char *args)
+{
+  struct get_key_status_parm_s *parm = opaque;
+
+  /*log_debug ("%s: %s\n", keyword, args);*/
+  if (!strcmp (keyword, "EXPORTED"))
+    {
+      parm->count++;
+      if (!ascii_strcasecmp (args, parm->fpr))
+        parm->found = 1;
+    }
+}
+
+/* Get a key by fingerprint from gpg's keyring and make sure that the
+ * 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.  */
+gpg_error_t
+wks_get_key (estream_t *r_key, const char *fingerprint, const char *addrspec,
+             int exact)
+{
+  gpg_error_t err;
+  ccparray_t ccp;
+  const char **argv = NULL;
+  estream_t key = NULL;
+  struct get_key_status_parm_s parm;
+  char *filterexp = NULL;
+
+  memset (&parm, 0, sizeof parm);
+
+  *r_key = NULL;
+
+  key = es_fopenmem (0, "w+b");
+  if (!key)
+    {
+      err = gpg_error_from_syserror ();
+      log_error ("error allocating memory buffer: %s\n", gpg_strerror (err));
+      goto leave;
+    }
+
+  /* Prefix the key with the MIME content type.  */
+  es_fputs ("Content-Type: application/pgp-keys\n"
+            "\n", key);
+
+  filterexp = es_bsprintf ("keep-uid=%s=%s", exact? "uid":"mbox", 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)
+    ccparray_put (&ccp, "--quiet");
+  else if (opt.verbose > 1)
+    ccparray_put (&ccp, "--verbose");
+  ccparray_put (&ccp, "--batch");
+  ccparray_put (&ccp, "--status-fd=2");
+  ccparray_put (&ccp, "--always-trust");
+  ccparray_put (&ccp, "--armor");
+  ccparray_put (&ccp, "--export-options=export-minimal");
+  ccparray_put (&ccp, "--export-filter");
+  ccparray_put (&ccp, filterexp);
+  ccparray_put (&ccp, "--export");
+  ccparray_put (&ccp, "--");
+  ccparray_put (&ccp, fingerprint);
+
+  ccparray_put (&ccp, NULL);
+  argv = ccparray_get (&ccp, NULL);
+  if (!argv)
+    {
+      err = gpg_error_from_syserror ();
+      goto leave;
+    }
+  parm.fpr = fingerprint;
+  err = gnupg_exec_tool_stream (opt.gpg_program, argv, NULL,
+                                NULL, key,
+                                get_key_status_cb, &parm);
+  if (!err && parm.count > 1)
+    err = gpg_error (GPG_ERR_TOO_MANY);
+  else if (!err && !parm.found)
+    err = gpg_error (GPG_ERR_NOT_FOUND);
+  if (err)
+    {
+      log_error ("export failed: %s\n", gpg_strerror (err));
+      goto leave;
+    }
+
+  es_rewind (key);
+  *r_key = key;
+  key = NULL;
+
+ leave:
+  es_fclose (key);
+  xfree (argv);
+  xfree (filterexp);
+  return err;
+}
+
+
+\f
 /* Helper for wks_list_key and wks_filter_uid.  */
 static void
 key_status_cb (void *opaque, const char *keyword, char *args)