[git] GnuPG - branch, master, updated. gnupg-2.2.7-299-gba46a35

by Werner Koch cvs at cvs.gnupg.org
Tue Dec 4 15:33:03 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, master has been updated
       via  ba46a359b9d6549b74ec8401ea39bad434d87564 (commit)
       via  0e8bf204791ebfd0c9a8e4b49fbadf998ec62e49 (commit)
       via  73e5b0ec9b9ba5e04e55f8c42d81e23df7c3afe0 (commit)
       via  602b1909632925d5a2e0778c102d66109795c627 (commit)
       via  99094c992c20dd22971beb3527cfda109cd1df89 (commit)
      from  802b23289cc9b43a56e5032c2681eb21d4014784 (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 ba46a359b9d6549b74ec8401ea39bad434d87564
Author: Werner Koch <wk at gnupg.org>
Date:   Tue Dec 4 15:27:19 2018 +0100

    wks: Allow reading of --install-key arguments from stdin.
    
    * tools/wks-util.c (install_key_from_spec_file): New.
    (wks_cmd_install_key): Call it.
    * tools/gpg-wks-client.c (main): Allow --install-key w/o arguments.
    * tools/gpg-wks-server.c (main): Ditto.
    
    Signed-off-by: Werner Koch <wk at gnupg.org>

diff --git a/doc/wks.texi b/doc/wks.texi
index 021fe5b..a0b2a34 100644
--- a/doc/wks.texi
+++ b/doc/wks.texi
@@ -95,8 +95,11 @@ local directory (see option @option{-C}) reflecting the structure of a
 WKD.  The arguments are a file with the keyblock and the user-id to
 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} removes a
-key from that directory, its only argument is a user-id.
+first argument with "./".  If no arguments are given the parameters
+are read from stdin; the expected format are lines with the
+fingerprint and the mailbox separated by a space.  The command
+ at option{--remove-key} removes a key from that directory, its only
+argument is a user-id.
 
 @command{gpg-wks-client} is not commonly invoked directly and thus it
 is not installed in the bin directory.  Here is an example how it can
@@ -280,7 +283,9 @@ 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.  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 "./".
+first argument with "./".  If no arguments are given the parameters
+are read from stdin; the expected format are lines with the
+fingerprint and the mailbox separated by a space.
 
 The command @option{--remove-key} uninstalls a key from the WKD.  The
 process returns success in this case; to also print a diagnostic, use
diff --git a/tools/gpg-wks-client.c b/tools/gpg-wks-client.c
index 5535a68..0dee1a2 100644
--- a/tools/gpg-wks-client.c
+++ b/tools/gpg-wks-client.c
@@ -363,9 +363,12 @@ main (int argc, char **argv)
       break;
 
     case aInstallKey:
-      if (argc != 2)
-        wrong_args ("--install-key FILE|FINGERPRINT USER-ID");
-      err = wks_cmd_install_key (*argv, argv[1]);
+      if (!argc)
+        err = wks_cmd_install_key (NULL, NULL);
+      else if (argc == 2)
+        err = wks_cmd_install_key (*argv, argv[1]);
+      else
+        wrong_args ("--install-key [FILE|FINGERPRINT USER-ID]");
       break;
 
     case aRemoveKey:
diff --git a/tools/gpg-wks-server.c b/tools/gpg-wks-server.c
index eae93b3..1a0ba8f 100644
--- a/tools/gpg-wks-server.c
+++ b/tools/gpg-wks-server.c
@@ -381,9 +381,12 @@ main (int argc, char **argv)
       break;
 
     case aInstallKey:
-      if (argc != 2)
-        wrong_args ("--install-key FILE USER-ID");
-      err = wks_cmd_install_key (*argv, argv[1]);
+      if (!argc)
+        err = wks_cmd_install_key (NULL, NULL);
+      else if (argc == 2)
+        err = wks_cmd_install_key (*argv, argv[1]);
+      else
+        wrong_args ("--install-key [FILE|FINGERPRINT USER-ID]");
       break;
 
     case aRemoveKey:
diff --git a/tools/wks-util.c b/tools/wks-util.c
index c0ea06a..73cced9 100644
--- a/tools/wks-util.c
+++ b/tools/wks-util.c
@@ -855,8 +855,65 @@ wks_compute_hu_fname (char **r_fname, const char *addrspec)
 }
 
 
+
+/* Helper form wks_cmd_install_key.  */
+static gpg_error_t
+install_key_from_spec_file (const char *fname)
+{
+  gpg_error_t err;
+  estream_t fp;
+  char *line = NULL;
+  size_t linelen = 0;
+  char *fields[2];
+  unsigned int lnr = 0;
+
+  if (!fname || !strcmp (fname, ""))
+    fp = es_stdin;
+  else
+    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;
+    }
+
+  while (es_getline (&line, &linelen, fp) >= 0)
+    {
+      lnr++;
+      trim_spaces (line);
+      log_debug ("got line='%s'\n", line);
+      if (!*line ||  *line == '#')
+        continue;
+      if (split_fields (line, fields, DIM(fields)) < 2)
+        {
+          log_error ("error reading '%s': syntax error at line %u\n",
+                     fname, lnr);
+          continue;
+        }
+      err = wks_cmd_install_key (fields[0], fields[1]);
+      if (err)
+        goto leave;
+    }
+  if (es_ferror (fp))
+    {
+      err = gpg_error_from_syserror ();
+      log_error ("error reading '%s': %s\n", fname, gpg_strerror (err));
+      goto leave;
+    }
+
+ leave:
+  if (fp != es_stdin)
+    es_fclose (fp);
+  es_free (line);
+  return err;
+}
+
+
 /* Install a single key into the WKD by reading FNAME and extracting
- * USERID.  */
+ * USERID.  If USERID is NULL FNAME is expected to be a list of fpr
+ * mbox lines and for each line the respective key will be
+ * installed.  */
 gpg_error_t
 wks_cmd_install_key (const char *fname, const char *userid)
 {
@@ -871,6 +928,9 @@ wks_cmd_install_key (const char *fname, const char *userid)
   char *huname = NULL;
   int any;
 
+  if (!userid)
+    return install_key_from_spec_file (fname);
+
   addrspec = mailbox_from_userid (userid, 0);
   if (!addrspec)
     {

commit 0e8bf204791ebfd0c9a8e4b49fbadf998ec62e49
Author: Werner Koch <wk at gnupg.org>
Date:   Tue Dec 4 12:32:28 2018 +0100

    gpg: New list-option "show-only-fpr-mbox".
    
    * g10/gpg.c (parse_list_options): Add option "show-only-fpr-mbox".
    * g10/options.h (LIST_SHOW_ONLY_FPR_MBOX): New.
    * g10/keylist.c (list_keyblock_simple): New.
    (list_keyblock): Call it.
    (list_all): Do not print the keyring name in LIST_SHOW_ONLY_FPR_MBOX
    mode.
    
    Signed-off-by: Werner Koch <wk at gnupg.org>

diff --git a/doc/gpg.texi b/doc/gpg.texi
index 58672c9..a5c172b 100644
--- a/doc/gpg.texi
+++ b/doc/gpg.texi
@@ -1328,6 +1328,10 @@ give the opposite meaning.  The options are:
   meaningful when using @option{--with-colons} along with
   @option{--check-signatures}.
 
+  @item show-only-fpr-mbox
+  @opindex list-options:show-only-fpr-mbox
+  For each valid user-id which also has a valid mail address print
+  only the fingerprint and the mail address.
 @end table
 
 @item --verify-options @var{parameters}
diff --git a/g10/gpg.c b/g10/gpg.c
index 9f96ef4..ddf8c86 100644
--- a/g10/gpg.c
+++ b/g10/gpg.c
@@ -2009,6 +2009,8 @@ parse_list_options(char *str)
        N_("show expiration dates during signature listings")},
       {"show-sig-subpackets",LIST_SHOW_SIG_SUBPACKETS,NULL,
        NULL},
+      {"show-only-fpr-mbox",LIST_SHOW_ONLY_FPR_MBOX, NULL,
+       NULL},
       {NULL,0,NULL,NULL}
     };
 
diff --git a/g10/keylist.c b/g10/keylist.c
index 793f7da..9a21663 100644
--- a/g10/keylist.c
+++ b/g10/keylist.c
@@ -541,7 +541,7 @@ list_all (ctrl_t ctrl, int secret, int mark_secret)
         ; /* Secret key listing requested but this isn't one.  */
       else
         {
-          if (!opt.with_colons)
+          if (!opt.with_colons && !(opt.list_options & LIST_SHOW_ONLY_FPR_MBOX))
             {
               resname = keydb_get_resource_name (hd);
               if (lastresname != resname)
@@ -1254,6 +1254,57 @@ list_keyblock_print (ctrl_t ctrl, kbnode_t keyblock, int secret, int fpr,
   xfree (hexgrip);
 }
 
+
+/* Do a simple key listing printing only the fingerprint and the mail
+ * address of valid keys.  */
+static void
+list_keyblock_simple (ctrl_t ctrl, kbnode_t keyblock)
+{
+  gpg_err_code_t ec;
+  kbnode_t kbctx;
+  kbnode_t node;
+  char hexfpr[2*MAX_FINGERPRINT_LEN+1];
+  char *mbox;
+
+  (void)ctrl;
+
+  node = find_kbnode (keyblock, PKT_PUBLIC_KEY);
+  if (!node)
+    {
+      log_error ("Oops; key lost!\n");
+      dump_kbnode (keyblock);
+      return;
+    }
+  hexfingerprint (node->pkt->pkt.public_key, hexfpr, sizeof hexfpr);
+
+  for (kbctx = NULL; (node = walk_kbnode (keyblock, &kbctx, 0));)
+    {
+      if (node->pkt->pkttype == PKT_USER_ID)
+	{
+	  PKT_user_id *uid = node->pkt->pkt.user_id;
+
+	  if (uid->attrib_data)
+	    continue;
+
+	  if (uid->flags.expired || uid->flags.revoked)
+            continue;
+
+          mbox = mailbox_from_userid (uid->name, 0);
+          if (!mbox)
+            {
+              ec = gpg_err_code_from_syserror ();
+              if (ec != GPG_ERR_EINVAL)
+                log_error ("error getting mailbox from user-id: %s\n",
+                           gpg_strerror (ec));
+              continue;
+            }
+          es_fprintf (es_stdout, "%s %s\n", hexfpr, mbox);
+          xfree (mbox);
+	}
+    }
+}
+
+
 void
 print_revokers (estream_t fp, PKT_public_key * pk)
 {
@@ -1807,6 +1858,12 @@ list_keyblock (ctrl_t ctrl,
 
   if (opt.with_colons)
     list_keyblock_colon (ctrl, keyblock, secret, has_secret);
+  else if ((opt.list_options & LIST_SHOW_ONLY_FPR_MBOX))
+    {
+      if (!listctx->no_validity)
+        check_trustdb_stale (ctrl);
+      list_keyblock_simple (ctrl, keyblock);
+    }
   else
     list_keyblock_print (ctrl, keyblock, secret, fpr, listctx);
 
diff --git a/g10/options.h b/g10/options.h
index faaf535..8adf09f 100644
--- a/g10/options.h
+++ b/g10/options.h
@@ -386,6 +386,7 @@ EXTERN_UNLESS_MAIN_MODULE int memory_stat_debug_mode;
 #define LIST_SHOW_SIG_EXPIRE             (1<<9)
 #define LIST_SHOW_SIG_SUBPACKETS         (1<<10)
 #define LIST_SHOW_USAGE                  (1<<11)
+#define LIST_SHOW_ONLY_FPR_MBOX          (1<<12)
 
 #define VERIFY_SHOW_PHOTOS               (1<<0)
 #define VERIFY_SHOW_POLICY_URLS          (1<<1)

commit 73e5b0ec9b9ba5e04e55f8c42d81e23df7c3afe0
Author: Werner Koch <wk at gnupg.org>
Date:   Tue Dec 4 11:37:54 2018 +0100

    wks: Create sub-directories
    
    * tools/wks-util.c (wks_compute_hu_fname): Stat and create directory
    if needed.
    
    Signed-off-by: Werner Koch <wk at gnupg.org>

diff --git a/tools/wks-util.c b/tools/wks-util.c
index 6041943..c0ea06a 100644
--- a/tools/wks-util.c
+++ b/tools/wks-util.c
@@ -19,6 +19,8 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 
 #include "../common/util.h"
 #include "../common/status.h"
@@ -811,6 +813,8 @@ wks_compute_hu_fname (char **r_fname, const char *addrspec)
   char *hash;
   const char *domain;
   char sha1buf[20];
+  char *fname;
+  struct stat sb;
 
   *r_fname = NULL;
 
@@ -824,12 +828,28 @@ wks_compute_hu_fname (char **r_fname, const char *addrspec)
   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;
+  /* Try to create missing directories below opt.directory.  */
+  fname = make_filename_try (opt.directory, domain, NULL);
+  if (fname && stat (fname, &sb)
+      && gpg_err_code_from_syserror () == GPG_ERR_ENOENT)
+    if (!gnupg_mkdir (fname, "-rwxr--r--") && opt.verbose)
+      log_info ("directory '%s' created\n", fname);
+  xfree (fname);
+  fname = make_filename_try (opt.directory, domain, "hu", NULL);
+  if (fname && stat (fname, &sb)
+      && gpg_err_code_from_syserror () == GPG_ERR_ENOENT)
+    if (!gnupg_mkdir (fname, "-rwxr--r--") && opt.verbose)
+      log_info ("directory '%s' created\n", fname);
+  xfree (fname);
+
+  /* Create the filename.  */
+  fname = make_filename_try (opt.directory, domain, "hu", hash, NULL);
+  err = fname? 0 : gpg_error_from_syserror ();
 
+  if (err)
+    xfree (fname);
+  else
+    *r_fname = fname; /* Okay.  */
   xfree (hash);
   return err;
 }

commit 602b1909632925d5a2e0778c102d66109795c627
Author: Werner Koch <wk at gnupg.org>
Date:   Tue Dec 4 10:31:42 2018 +0100

    wks: Add new commands --install-key and --remove-key to the client.
    
    * tools/gpg-wks-client.c (aInstallKey, aRemoveKey, oDirectory): New.
    (opts): Add "--install-key", "--remove-key" and "-C".
    (parse_arguments): Parse them.
    (main): Check that the given directory exists.  Implement the new
    commands.
    --
    
    These commands maybe useful to prepare a WKD directory on a non-Unix
    box using the standard wks client.
    
    Signed-off-by: Werner Koch <wk at gnupg.org>

diff --git a/doc/wks.texi b/doc/wks.texi
index 03d7482..021fe5b 100644
--- a/doc/wks.texi
+++ b/doc/wks.texi
@@ -90,6 +90,14 @@ decrypted MIME message.  The result of these commands are another mail
 which can be send in the same way as the mail created with
 @option{--create}.
 
+The command @option{--install-key} manually installs a key into a
+local directory (see option @option{-C}) reflecting the structure of a
+WKD.  The arguments are a file with the keyblock and the user-id to
+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} removes a
+key from that directory, its only argument is a user-id.
+
 @command{gpg-wks-client} is not commonly invoked directly and thus it
 is not installed in the bin directory.  Here is an example how it can
 be invoked manually to check for a Web Key Directory entry for
@@ -161,6 +169,13 @@ This program returns only the status messages SUCCESS or FAILURE which
 are helpful when the caller uses a double fork approach and can't
 easily get the return code of the process.
 
+ at item -C @var{dir}
+ at itemx --directory @var{dir}
+ at opindex directory
+Use @var{dir} as top level directory for the commands
+ at option{--install-key} and @option{--remove-key}.  The default is
+ at file{openpgpkey}.
+
 @item --verbose
 @opindex verbose
 Enable extra informational output.
diff --git a/tools/gpg-wks-client.c b/tools/gpg-wks-client.c
index 0be5ea8..5535a68 100644
--- a/tools/gpg-wks-client.c
+++ b/tools/gpg-wks-client.c
@@ -22,6 +22,8 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 
 #include "../common/util.h"
 #include "../common/status.h"
@@ -48,6 +50,7 @@ enum cmd_and_opt_values
     oQuiet      = 'q',
     oVerbose	= 'v',
     oOutput     = 'o',
+    oDirectory  = 'C',
 
     oDebug      = 500,
 
@@ -56,6 +59,8 @@ enum cmd_and_opt_values
     aCreate,
     aReceive,
     aRead,
+    aInstallKey,
+    aRemoveKey,
 
     oGpgProgram,
     oSend,
@@ -81,6 +86,10 @@ static ARGPARSE_OPTS opts[] = {
               ("receive a MIME confirmation request")),
   ARGPARSE_c (aRead,      "read",
               ("receive a plain text confirmation request")),
+  ARGPARSE_c (aInstallKey, "install-key",
+              "install a key into a directory"),
+  ARGPARSE_c (aRemoveKey, "remove-key",
+              "remove a key from a directory"),
 
   ARGPARSE_group (301, ("@\nOptions:\n ")),
 
@@ -92,6 +101,7 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_s_s (oOutput, "output", "|FILE|write the mail to FILE"),
   ARGPARSE_s_i (oStatusFD, "status-fd", N_("|FD|write status info to this FD")),
   ARGPARSE_s_n (oWithColons, "with-colons", "@"),
+  ARGPARSE_s_s (oDirectory, "directory", "@"),
 
   ARGPARSE_s_s (oFakeSubmissionAddr, "fake-submission-addr", "@"),
 
@@ -194,6 +204,9 @@ parse_arguments (ARGPARSE_ARGS *pargs, ARGPARSE_OPTS *popts)
         case oGpgProgram:
           opt.gpg_program = pargs->r.ret_str;
           break;
+        case oDirectory:
+          opt.directory = pargs->r.ret_str;
+          break;
         case oSend:
           opt.use_sendmail = 1;
           break;
@@ -215,6 +228,8 @@ parse_arguments (ARGPARSE_ARGS *pargs, ARGPARSE_OPTS *popts)
 	case aReceive:
 	case aRead:
         case aCheck:
+        case aInstallKey:
+        case aRemoveKey:
           cmd = pargs->r_opt;
           break;
 
@@ -269,9 +284,34 @@ main (int argc, char **argv)
   if (!opt.gpg_program)
     opt.gpg_program = gnupg_module_name (GNUPG_MODULE_NAME_GPG);
 
+  if (!opt.directory)
+    opt.directory = "openpgpkey";
+
   /* Tell call-dirmngr what options we want.  */
   set_dirmngr_options (opt.verbose, (opt.debug & DBG_IPC_VALUE), 1);
 
+
+  /* Check that the top directory exists.  */
+  if (cmd == aInstallKey || cmd == aRemoveKey)
+    {
+      struct stat sb;
+
+      if (stat (opt.directory, &sb))
+        {
+          err = gpg_error_from_syserror ();
+          log_error ("error accessing directory '%s': %s\n",
+                     opt.directory, gpg_strerror (err));
+          goto leave;
+        }
+      if (!S_ISDIR(sb.st_mode))
+        {
+          log_error ("error accessing directory '%s': %s\n",
+                     opt.directory, "not a directory");
+          err = gpg_error (GPG_ERR_ENOENT);
+          goto leave;
+        }
+    }
+
   /* Run the selected command.  */
   switch (cmd)
     {
@@ -322,12 +362,25 @@ main (int argc, char **argv)
       err = command_check (argv[0]);
       break;
 
+    case aInstallKey:
+      if (argc != 2)
+        wrong_args ("--install-key FILE|FINGERPRINT USER-ID");
+      err = wks_cmd_install_key (*argv, argv[1]);
+      break;
+
+    case aRemoveKey:
+      if (argc != 1)
+        wrong_args ("--remove-key USER-ID");
+      err = wks_cmd_remove_key (*argv);
+      break;
+
     default:
       usage (1);
       err = 0;
       break;
     }
 
+ leave:
   if (err)
     wks_write_status (STATUS_FAILURE, "- %u", err);
   else if (log_get_errorcount (0))

commit 99094c992c20dd22971beb3527cfda109cd1df89
Author: Werner Koch <wk at gnupg.org>
Date:   Tue Dec 4 09:45:42 2018 +0100

    wks: Move a few server functions to wks-util.
    
    * tools/gpg-wks-server.c (write_to_file): Move to ...
    * tools/wks-util.c: here.
    * tools/gpg-wks-server.c (compute_hu_fname): Move to ...
    * tools/wks-util.c (wks_compute_hu_fname): here.
    * tools/gpg-wks-server.c (fname_from_userid): Move to ...
    * tools/wks-util.c (wks_fname_from_userid): here.
    * tools/gpg-wks-server.c (command_install_key): Move to ...
    * tools/wks-util.c (wks_cmd_install_key): here and change caller.
    * tools/gpg-wks-server.c (command_remove_key): Move to ...
    * tools/wks-util.c (wks_cmd_remove_key): here and change callers.
    
    Signed-off-by: Werner Koch <wk at gnupg.org>

diff --git a/tools/gpg-wks-server.c b/tools/gpg-wks-server.c
index 1b53312..eae93b3 100644
--- a/tools/gpg-wks-server.c
+++ b/tools/gpg-wks-server.c
@@ -157,8 +157,6 @@ 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, 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);
 static gpg_error_t command_cron (void);
@@ -385,13 +383,13 @@ main (int argc, char **argv)
     case aInstallKey:
       if (argc != 2)
         wrong_args ("--install-key FILE USER-ID");
-      err = command_install_key (*argv, argv[1]);
+      err = wks_cmd_install_key (*argv, argv[1]);
       break;
 
     case aRemoveKey:
       if (argc != 1)
         wrong_args ("--remove-key USER-ID");
-      err = command_remove_key (*argv);
+      err = wks_cmd_remove_key (*argv);
       break;
 
     case aRevokeKey:
@@ -1346,81 +1344,6 @@ 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)
@@ -1495,7 +1418,7 @@ check_and_publish (server_ctx_t ctx, const char *address, const char *nonce)
     }
 
   /* Hash user ID and create filename.  */
-  err = compute_hu_fname (&fnewname, address);
+  err = wks_compute_hu_fname (&fnewname, address);
   if (err)
     goto leave;
 
@@ -2004,195 +1927,6 @@ command_cron (void)
 }
 
 
-/* Install a single key into the WKD by reading FNAME and extracting
- * USERID.  */
-static gpg_error_t
-command_install_key (const char *fname, const char *userid)
-{
-  gpg_error_t err;
-  KEYDB_SEARCH_DESC desc;
-  estream_t fp = NULL;
-  char *addrspec = NULL;
-  char *fpr = NULL;
-  uidinfo_list_t uidlist = NULL;
-  uidinfo_list_t uid, thisuid;
-  time_t thistime;
-  char *huname = NULL;
-  int any;
-
-  addrspec = mailbox_from_userid (userid, 0);
-  if (!addrspec)
-    {
-      log_error ("\"%s\" is not a proper mail address\n", userid);
-      err = gpg_error (GPG_ERR_INV_USER_ID);
-      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);
-  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 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)
-{
-  gpg_error_t err;
-  char *addrspec = NULL;
-  const char *domain;
-  char *hash = NULL;
-  const char *s;
-  char shaxbuf[32]; /* Used for SHA-1 and SHA-256 */
-
-  *r_fname = NULL;
-  if (r_addrspec)
-    *r_addrspec = NULL;
-
-  addrspec = mailbox_from_userid (userid, 0);
-  if (!addrspec)
-    {
-      if (opt.verbose)
-        log_info ("\"%s\" is not a proper mail address\n", userid);
-      err = gpg_error (GPG_ERR_INV_USER_ID);
-      goto leave;
-    }
-
-  domain = strchr (addrspec, '@');
-  log_assert (domain);
-  domain++;
-
-  /* Hash user ID and create filename.  */
-  s = strchr (addrspec, '@');
-  log_assert (s);
-  gcry_md_hash_buffer (GCRY_MD_SHA1, shaxbuf, addrspec, s - addrspec);
-  hash = zb32_encode (shaxbuf, 8*20);
-  if (!hash)
-    {
-      err = gpg_error_from_syserror ();
-      goto leave;
-    }
-
-  *r_fname = make_filename_try (opt.directory, domain, "hu", hash, NULL);
-  if (!*r_fname)
-    err = gpg_error_from_syserror ();
-  else
-    err = 0;
-
- leave:
-  if (r_addrspec && addrspec)
-    *r_addrspec = addrspec;
-  else
-    xfree (addrspec);
-  xfree (hash);
-  return err;
-}
-
-
 /* Check whether the key with USER_ID is installed.  */
 static gpg_error_t
 command_check_key (const char *userid)
@@ -2201,7 +1935,7 @@ command_check_key (const char *userid)
   char *addrspec = NULL;
   char *fname = NULL;
 
-  err = fname_from_userid (userid, &fname, &addrspec);
+  err = wks_fname_from_userid (userid, &fname, &addrspec);
   if (err)
     goto leave;
 
@@ -2236,49 +1970,11 @@ command_check_key (const char *userid)
 }
 
 
-/* Remove the key with mail address in USERID.  */
-static gpg_error_t
-command_remove_key (const char *userid)
-{
-  gpg_error_t err;
-  char *addrspec = NULL;
-  char *fname = NULL;
-
-  err = fname_from_userid (userid, &fname, &addrspec);
-  if (err)
-    goto leave;
-
-  if (gnupg_remove (fname))
-    {
-      err = gpg_error_from_syserror ();
-      if (gpg_err_code (err) == GPG_ERR_ENOENT)
-        {
-          if (!opt.quiet)
-            log_info ("key for '%s' is not installed\n", addrspec);
-          log_inc_errorcount ();
-          err = 0;
-        }
-      else
-        log_error ("error removing '%s': %s\n", fname, gpg_strerror (err));
-      goto leave;
-    }
-
-  if (opt.verbose)
-    log_info ("key for '%s' removed\n", addrspec);
-  err = 0;
-
- leave:
-  xfree (fname);
-  xfree (addrspec);
-  return err;
-}
-
-
 /* Revoke the key with mail address MAILADDR.  */
 static gpg_error_t
 command_revoke_key (const char *mailaddr)
 {
   /* Remove should be different from removing but we have not yet
    * defined a suitable way to do this.  */
-  return command_remove_key (mailaddr);
+  return wks_cmd_remove_key (mailaddr);
 }
diff --git a/tools/gpg-wks.h b/tools/gpg-wks.h
index fba73f0..e369430 100644
--- a/tools/gpg-wks.h
+++ b/tools/gpg-wks.h
@@ -98,6 +98,13 @@ gpg_error_t wks_parse_policy (policy_flags_t flags, estream_t stream,
                               int ignore_unknown);
 void wks_free_policy (policy_flags_t policy);
 
+gpg_error_t wks_fname_from_userid (const char *userid,
+                                   char **r_fname, char **r_addrspec);
+gpg_error_t wks_compute_hu_fname (char **r_fname, const char *addrspec);
+gpg_error_t wks_cmd_install_key (const char *fname, const char *userid);
+gpg_error_t wks_cmd_remove_key (const char *userid);
+
+
 /*-- wks-receive.c --*/
 
 /* Flag values for the receive callback.  */
diff --git a/tools/wks-util.c b/tools/wks-util.c
index cf80a25..6041943 100644
--- a/tools/wks-util.c
+++ b/tools/wks-util.c
@@ -24,7 +24,10 @@
 #include "../common/status.h"
 #include "../common/ccparray.h"
 #include "../common/exectool.h"
+#include "../common/zb32.h"
+#include "../common/userids.h"
 #include "../common/mbox-util.h"
+#include "../common/sysutils.h"
 #include "mime-maker.h"
 #include "send-mail.h"
 #include "gpg-wks.h"
@@ -699,3 +702,305 @@ wks_free_policy (policy_flags_t policy)
       memset (policy, 0, sizeof *policy);
     }
 }
+
+
+/* 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;
+}
+
+
+/* Return the filename and optionally the addrspec for USERID at
+ * R_FNAME and R_ADDRSPEC.  R_ADDRSPEC might also be set on error.  */
+gpg_error_t
+wks_fname_from_userid (const char *userid, char **r_fname, char **r_addrspec)
+{
+  gpg_error_t err;
+  char *addrspec = NULL;
+  const char *domain;
+  char *hash = NULL;
+  const char *s;
+  char shaxbuf[32]; /* Used for SHA-1 and SHA-256 */
+
+  *r_fname = NULL;
+  if (r_addrspec)
+    *r_addrspec = NULL;
+
+  addrspec = mailbox_from_userid (userid, 0);
+  if (!addrspec)
+    {
+      if (opt.verbose)
+        log_info ("\"%s\" is not a proper mail address\n", userid);
+      err = gpg_error (GPG_ERR_INV_USER_ID);
+      goto leave;
+    }
+
+  domain = strchr (addrspec, '@');
+  log_assert (domain);
+  domain++;
+
+  /* Hash user ID and create filename.  */
+  s = strchr (addrspec, '@');
+  log_assert (s);
+  gcry_md_hash_buffer (GCRY_MD_SHA1, shaxbuf, addrspec, s - addrspec);
+  hash = zb32_encode (shaxbuf, 8*20);
+  if (!hash)
+    {
+      err = gpg_error_from_syserror ();
+      goto leave;
+    }
+
+  *r_fname = make_filename_try (opt.directory, domain, "hu", hash, NULL);
+  if (!*r_fname)
+    err = gpg_error_from_syserror ();
+  else
+    err = 0;
+
+ leave:
+  if (r_addrspec && addrspec)
+    *r_addrspec = addrspec;
+  else
+    xfree (addrspec);
+  xfree (hash);
+  return err;
+}
+
+
+/* Compute the the full file name for the key with ADDRSPEC and return
+ * it at R_FNAME.  */
+gpg_error_t
+wks_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;
+}
+
+
+/* Install a single key into the WKD by reading FNAME and extracting
+ * USERID.  */
+gpg_error_t
+wks_cmd_install_key (const char *fname, const char *userid)
+{
+  gpg_error_t err;
+  KEYDB_SEARCH_DESC desc;
+  estream_t fp = NULL;
+  char *addrspec = NULL;
+  char *fpr = NULL;
+  uidinfo_list_t uidlist = NULL;
+  uidinfo_list_t uid, thisuid;
+  time_t thistime;
+  char *huname = NULL;
+  int any;
+
+  addrspec = mailbox_from_userid (userid, 0);
+  if (!addrspec)
+    {
+      log_error ("\"%s\" is not a proper mail address\n", userid);
+      err = gpg_error (GPG_ERR_INV_USER_ID);
+      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);
+  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 = wks_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;
+}
+
+
+/* Remove the key with mail address in USERID.  */
+gpg_error_t
+wks_cmd_remove_key (const char *userid)
+{
+  gpg_error_t err;
+  char *addrspec = NULL;
+  char *fname = NULL;
+
+  err = wks_fname_from_userid (userid, &fname, &addrspec);
+  if (err)
+    goto leave;
+
+  if (gnupg_remove (fname))
+    {
+      err = gpg_error_from_syserror ();
+      if (gpg_err_code (err) == GPG_ERR_ENOENT)
+        {
+          if (!opt.quiet)
+            log_info ("key for '%s' is not installed\n", addrspec);
+          log_inc_errorcount ();
+          err = 0;
+        }
+      else
+        log_error ("error removing '%s': %s\n", fname, gpg_strerror (err));
+      goto leave;
+    }
+
+  if (opt.verbose)
+    log_info ("key for '%s' removed\n", addrspec);
+  err = 0;
+
+ leave:
+  xfree (fname);
+  xfree (addrspec);
+  return err;
+}

-----------------------------------------------------------------------

Summary of changes:
 doc/gpg.texi           |   4 +
 doc/wks.texi           |  22 ++-
 g10/gpg.c              |   2 +
 g10/keylist.c          |  59 +++++++-
 g10/options.h          |   1 +
 tools/gpg-wks-client.c |  56 +++++++
 tools/gpg-wks-server.c | 321 ++---------------------------------------
 tools/gpg-wks.h        |   7 +
 tools/wks-util.c       | 385 +++++++++++++++++++++++++++++++++++++++++++++++++
 9 files changed, 544 insertions(+), 313 deletions(-)


hooks/post-receive
-- 
The GNU Privacy Guard
http://git.gnupg.org




More information about the Gnupg-commits mailing list