wks: Add new commands --install-key and --remove-key to the client.
authorWerner Koch <wk@gnupg.org>
Tue, 4 Dec 2018 09:31:42 +0000 (10:31 +0100)
committerWerner Koch <wk@gnupg.org>
Tue, 4 Dec 2018 14:31:41 +0000 (15:31 +0100)
* 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@gnupg.org>
doc/wks.texi
tools/gpg-wks-client.c

index 03d7482..021fe5b 100644 (file)
@@ -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.
 
+@item -C @var{dir}
+@itemx --directory @var{dir}
+@opindex directory
+Use @var{dir} as top level directory for the commands
+@option{--install-key} and @option{--remove-key}.  The default is
+@file{openpgpkey}.
+
 @item --verbose
 @opindex verbose
 Enable extra informational output.
index 0be5ea8..5535a68 100644 (file)
@@ -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))