Impleemned gpgsm's IMPORT --re-import feature.
authorWerner Koch <wk@gnupg.org>
Tue, 7 Jul 2009 16:52:12 +0000 (16:52 +0000)
committerWerner Koch <wk@gnupg.org>
Tue, 7 Jul 2009 16:52:12 +0000 (16:52 +0000)
Typo fix.

NEWS
TODO
agent/command.c
doc/gpgsm.texi
sm/ChangeLog
sm/gpgsm.h
sm/import.c
sm/server.c

diff --git a/NEWS b/NEWS
index aa3e6d5..bdf2f87 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -8,6 +8,8 @@ Noteworthy changes in version 2.0.13
 
  * gpgsm --gen-key implements all features of gpgsm-gencert.sh.
 
+ * New option --re-import for gpgsm's IMPORT server command.
+
  * Minor bug fixes.
 
 
diff --git a/TODO b/TODO
index e590db8..5182fc8 100644 (file)
--- a/TODO
+++ b/TODO
@@ -82,9 +82,6 @@
 ** check that we issue NO_SECKEY xxx if a -u key was not found
    We don't. The messages returned are also wrong (recipient vs. signer).
 
-* jnlib/
-** Try to remove all jnlib_xmalloc.
-
 * g10/
 ** issue a NO_SECKEY xxxx if a -u key was not found.
 
index e3de085..90a7f34 100644 (file)
@@ -1802,7 +1802,7 @@ io_monitor (assuan_context_t ctx, int direction,
 }
 
 
-/* Return true if the commznd CMD implements the option OPT.  */
+/* Return true if the command CMD implements the option OPT.  */
 static int
 command_has_option (const char *cmd, const char *cmdopt)
 {
index e784f71..c107bf0 100644 (file)
@@ -1219,14 +1219,19 @@ in the same way as with the OUTPUT command.
 To import certificates into the internal key database, the command
 
 @example
-  IMPORT
+  IMPORT [--re-import]
 @end example
 
 is used.  The data is expected on the file descriptor set with the
 @code{INPUT} command.  Certain checks are performend on the
-certificate.  Note that the code will also handle PKCS\#12 files and
+certificate.  Note that the code will also handle PKCS#12 files and
 import private keys; a helper program is used for that.
 
+With the option @option{--re-import} the input data is expected to a be
+a linefeed separated list of fingerprints.  The command will re-import
+the corresponding certificates; that is they are made permanent by
+removing their ephemeral flag.
+
 
 @node GPGSM DELETE
 @subsection Delete certificates
@@ -1259,6 +1264,11 @@ The value of @var{what} specifies the kind of information returned:
 Return the version of the program.
 @item pid
 Return the process id of the process.
+@item agent-check
+Return success if the agent is running.
+@item cmd_has_option @var{cmd} @var{opt}
+Return success if the command @var{cmd} implements the option @var{opt}.
+The leading two dashes usually used with @var{opt} shall not be given.
 @end table
 
 @mansect see also
index a2c0675..954f88e 100644 (file)
@@ -1,5 +1,11 @@
 2009-07-07  Werner Koch  <wk@g10code.com>
 
+       * server.c (command_has_option): New.
+       (cmd_getinfo): Add subcommand "cmd_has_option".
+       (cmd_import): Implement option --re-import.
+       * import.c (gpgsm_import): Add arg reimport_mode.
+       (reimport_one): New.
+
        * gpgsm.h: Include session-env.h.
        (opt): Add field SESSION_ENV.  Remove obsolete fields.
        * server.c (option_handler): Rewrite setting of option fields.
index 900e6dd..b6c9a76 100644 (file)
@@ -333,7 +333,7 @@ gpg_error_t gpgsm_list_keys (ctrl_t ctrl, strlist_t names,
                              estream_t fp, unsigned int mode);
 
 /*-- import.c --*/
-int gpgsm_import (ctrl_t ctrl, int in_fd);
+int gpgsm_import (ctrl_t ctrl, int in_fd, int reimport_mode);
 int gpgsm_import_files (ctrl_t ctrl, int nfiles, char **files,
                         int (*of)(const char *fname));
 
index 5e8b429..5a0eded 100644 (file)
@@ -1,5 +1,5 @@
 /* import.c - Import certificates
- *     Copyright (C) 2001, 2003, 2004 Free Software Foundation, Inc.
+ * Copyright (C) 2001, 2003, 2004, 2009 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
@@ -34,6 +34,8 @@
 #include "exechelp.h"
 #include "i18n.h"
 #include "sysutils.h"
+#include "../kbx/keybox.h" /* for KEYBOX_FLAG_* */
+
 
 struct stats_s {
   unsigned long count;
@@ -405,14 +407,136 @@ import_one (ctrl_t ctrl, struct stats_s *stats, int in_fd)
 }
 
 
+\f
+/* Re-import certifciates.  IN_FD is a list of linefeed delimited
+   fingerprints t re-import.  The actual re-import is done by clearing
+   the ephemeral flag.  */
+static int
+reimport_one (ctrl_t ctrl, struct stats_s *stats, int in_fd)
+{
+  gpg_error_t err = 0;
+  estream_t fp = NULL;
+  char line[100];  /* Sufficient for a fingerprint.  */
+  KEYDB_HANDLE kh;
+  KEYDB_SEARCH_DESC desc;
+  ksba_cert_t cert = NULL;
+  unsigned int flags;
+
+  kh = keydb_new (0);
+  if (!kh)
+    {
+      err = gpg_error (GPG_ERR_ENOMEM);;
+      log_error (_("failed to allocate keyDB handle\n"));
+      goto leave;
+    }
+  keydb_set_ephemeral (kh, 1);
+   
+  fp = es_fdopen_nc (in_fd, "r");
+  if (!fp)
+    {
+      err = gpg_error_from_syserror ();
+      log_error ("es_fdopen(%d) failed: %s\n", in_fd, gpg_strerror (err));
+      goto leave;
+    }
+
+  while (es_fgets (line, DIM(line)-1, fp) )
+    {
+      if (*line && line[strlen(line)-1] != '\n')
+        {
+          err = gpg_error (GPG_ERR_LINE_TOO_LONG);
+          goto leave;
+       }
+      trim_spaces (line);
+      if (!*line)
+        continue;
+    
+      stats->count++;
+
+      err = keydb_classify_name (line, &desc);
+      if (err)
+        {
+          print_import_problem (ctrl, NULL, 0);
+          stats->not_imported++;
+          continue;
+        }
+
+      keydb_search_reset (kh);
+      err = keydb_search (kh, &desc, 1);
+      if (err)
+        {
+          print_import_problem (ctrl, NULL, 0);
+          stats->not_imported++;
+          continue;
+        }
+
+      ksba_cert_release (cert);
+      cert = NULL;
+      err = keydb_get_cert (kh, &cert);
+      if (err)
+        {
+          log_error ("keydb_get_cert() failed: %s\n", gpg_strerror (err));
+          print_import_problem (ctrl, NULL, 1);
+          stats->not_imported++;
+          continue;
+        }
+
+      err = keydb_get_flags (kh, KEYBOX_FLAG_BLOB, 0, &flags);
+      if (err)
+        {
+          log_error (_("error getting stored flags: %s\n"), gpg_strerror (err));
+          print_imported_status (ctrl, cert, 0);
+          stats->not_imported++;
+          continue;
+        }
+      if ( !(flags & KEYBOX_FLAG_BLOB_EPHEMERAL) )
+        {
+          print_imported_status (ctrl, cert, 0);
+          stats->unchanged++;
+          continue;
+        }
+
+      err = keydb_set_cert_flags (cert, 1, KEYBOX_FLAG_BLOB, 0,
+                                  KEYBOX_FLAG_BLOB_EPHEMERAL, 0);
+      if (err)
+        {
+          log_error ("clearing ephemeral flag failed: %s\n",
+                     gpg_strerror (err)); 
+          print_import_problem (ctrl, cert, 0);
+          stats->not_imported++;
+          continue;
+        }
+
+      print_imported_status (ctrl, cert, 1);
+      stats->imported++;
+    }
+  err = 0;
+  if (es_ferror (fp))
+    {
+      err = gpg_error_from_syserror ();
+      log_error ("error reading fd %d: %s\n", in_fd, gpg_strerror (err));
+      goto leave;
+    }
+
+ leave:
+  ksba_cert_release (cert);
+  keydb_release (kh);
+  es_fclose (fp);
+  return err;
+}
+
+
+\f
 int
-gpgsm_import (ctrl_t ctrl, int in_fd)
+gpgsm_import (ctrl_t ctrl, int in_fd, int reimport_mode)
 {
   int rc;
   struct stats_s stats;
 
   memset (&stats, 0, sizeof stats);
-  rc = import_one (ctrl, &stats, in_fd);
+  if (reimport_mode)
+    rc = reimport_one (ctrl, &stats, in_fd);
+  else
+    rc = import_one (ctrl, &stats, in_fd);
   print_imported_summary (ctrl, &stats);
   /* If we never printed an error message do it now so that a command
      line invocation will return with an error (log_error keeps a
index 7ba5b68..f6c8af9 100644 (file)
@@ -1,6 +1,6 @@
 /* server.c - Server mode and main entry point 
  * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006,
- *               2007, 2008 Free Software Foundation, Inc.
+ *               2007, 2008, 2009 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
@@ -68,6 +68,10 @@ static es_cookie_io_functions_t data_line_cookie_functions =
   };
 
 
+\f
+static int command_has_option (const char *cmd, const char *cmdopt);
+
+
 
 \f
 /* Note that it is sufficient to allocate the target string D as
@@ -638,25 +642,31 @@ cmd_sign (assuan_context_t ctx, char *line)
 }
 
 
-/* IMPORT
+/* IMPORT [--re-import]
 
-  Import the certificates read form the input-fd, return status
-  message for each imported one.  The import checks the validity of
-  the certificate but not of the entire chain.  It is possible to
-  import expired certificates.  */
+   Import the certificates read form the input-fd, return status
+   message for each imported one.  The import checks the validity of
+   the certificate but not of the entire chain.  It is possible to
+   import expired certificates.
+
+   With the option --re-import the input data is expected to a be a LF
+   separated list of fingerprints.  The command will re-import these
+   certificates, meaning that they are made permanent by removing
+   their ephemeral flag.   */
 static int 
 cmd_import (assuan_context_t ctx, char *line)
 {
   ctrl_t ctrl = assuan_get_pointer (ctx);
   int rc;
   int fd = translate_sys2libc_fd (assuan_get_input_fd (ctx), 0);
+  int reimport = has_option (line, "--re-import"); 
 
   (void)line;
 
   if (fd == -1)
     return set_error (GPG_ERR_ASS_NO_INPUT, NULL);
 
-  rc = gpgsm_import (assuan_get_pointer (ctx), fd);
+  rc = gpgsm_import (assuan_get_pointer (ctx), fd, reimport);
 
   /* close and reset the fd */
   close_message_fd (ctrl);
@@ -1029,12 +1039,14 @@ cmd_getauditlog (assuan_context_t ctx, char *line)
      version     - Return the version of the program.
      pid         - Return the process id of the server.
      agent-check - Return success if the agent is running.
+     cmd_has_option CMD OPT
+                 - Returns OK if the command CMD implements the option OPT.
 
  */
 static int
 cmd_getinfo (assuan_context_t ctx, char *line)
 {
-  int rc;
+  int rc = 0;
 
   if (!strcmp (line, "version"))
     {
@@ -1053,13 +1065,60 @@ cmd_getinfo (assuan_context_t ctx, char *line)
       ctrl_t ctrl = assuan_get_pointer (ctx);
       rc = gpgsm_agent_send_nop (ctrl);
     }
+  else if (!strncmp (line, "cmd_has_option", 14)
+           && (line[14] == ' ' || line[14] == '\t' || !line[14]))
+    {
+      char *cmd, *cmdopt;
+      line += 14;
+      while (*line == ' ' || *line == '\t')
+        line++;
+      if (!*line)
+        rc = gpg_error (GPG_ERR_MISSING_VALUE);
+      else
+        {
+          cmd = line;
+          while (*line && (*line != ' ' && *line != '\t'))
+            line++;
+          if (!*line)
+            rc = gpg_error (GPG_ERR_MISSING_VALUE);
+          else
+            {
+              *line++ = 0;
+              while (*line == ' ' || *line == '\t')
+                line++;
+              if (!*line)
+                rc = gpg_error (GPG_ERR_MISSING_VALUE);
+              else
+                {
+                  cmdopt = line;
+                  if (!command_has_option (cmd, cmdopt))
+                    rc = gpg_error (GPG_ERR_GENERAL);
+                }
+            }
+        }
+    }
   else
     rc = set_error (GPG_ERR_ASS_PARAMETER, "unknown value for WHAT");
+
   return rc;
 }
 
 
 \f
+/* Return true if the command CMD implements the option OPT.  */
+static int
+command_has_option (const char *cmd, const char *cmdopt)
+{
+  if (!strcmp (cmd, "IMPORT"))
+    {
+      if (!strcmp (cmdopt, "re-import"))
+        return 1;
+    }
+      
+  return 0;
+}
+
+
 /* Tell the assuan library about our commands */
 static int
 register_commands (assuan_context_t ctx)