Updated from latest NewPG project
[gnupg.git] / sm / call-dirmngr.c
index 30b3476..6c1156a 100644 (file)
@@ -26,6 +26,7 @@
 #include <unistd.h> 
 #include <time.h>
 #include <assert.h>
+#include <ctype.h>
 
 #include <gcrypt.h>
 
@@ -59,7 +60,9 @@ struct lookup_parm_s {
   int error;
 };
 
-
+struct run_command_parm_s {
+  ASSUAN_CONTEXT ctx;
+};
 
 
 /* A simple implementation of a dynamic buffer.  Use init_membuf() to
@@ -304,6 +307,13 @@ gpgsm_dirmngr_isvalid (KsbaCert cert)
       return seterr (General_Error);
     }
 
+  if (opt.verbose > 1)
+    {
+      char *fpr = gpgsm_get_fingerprint_string (cert, GCRY_MD_SHA1);
+      log_info ("asking dirmngr about %s\n", fpr);
+      xfree (fpr);
+    }
+
   parm.ctx = dirmngr_ctx;
   parm.cert = cert;
 
@@ -313,6 +323,8 @@ gpgsm_dirmngr_isvalid (KsbaCert cert)
 
   rc = assuan_transact (dirmngr_ctx, line, NULL, NULL,
                         inq_certificate, &parm, NULL, NULL);
+  if (opt.verbose > 1)
+    log_info ("response of dirmngr: %s\n", rc? assuan_strerror (rc): "okay");
   return map_assuan_err (rc);
 }
 
@@ -443,7 +455,7 @@ lookup_status_cb (void *opaque, const char *line)
 }
 
 
-/* Run the Directroy Managers lookup command using the apptern
+/* Run the Directroy Managers lookup command using the pattern
    compiled from the strings given in NAMES.  The caller must provide
    the callback CB which will be passed cert by cert.  Note that CTRL
    is optional. */
@@ -484,3 +496,136 @@ gpgsm_dirmngr_lookup (CTRL ctrl, STRLIST names,
 }
 
 
+\f
+/* Run Command helpers*/
+
+/* Fairly simple callback to write all output of dirmngr to stdout. */
+static AssuanError
+run_command_cb (void *opaque, const void *buffer, size_t length)
+{
+  if (buffer)
+    {
+      if ( fwrite (buffer, length, 1, stdout) != 1 )
+        log_error ("error writing to stdout: %s\n", strerror (errno));
+    }
+  return 0;
+}
+
+/* Handle inquiries from the dirmngr COMMAND. */
+static AssuanError
+run_command_inq_cb (void *opaque, const char *line)
+{
+  struct run_command_parm_s *parm = opaque;
+  AssuanError rc = 0;
+
+  if ( !strncmp (line, "SENDCERT", 8) && (line[8] == ' ' || !line[8]) )
+    { /* send the given certificate */
+      int err;
+      KsbaCert cert;
+      const unsigned char *der;
+      size_t derlen;
+
+      line += 8;
+      if (!*line)
+        return ASSUAN_Inquire_Error;
+
+      err = gpgsm_find_cert (line, &cert);
+      if (err)
+        {
+          log_error ("certificate not found: %s\n", gnupg_strerror (err));
+          rc = ASSUAN_Inquire_Error;
+        }
+      else
+        {
+          der = ksba_cert_get_image (cert, &derlen);
+          if (!der)
+            rc = ASSUAN_Inquire_Error;
+          else
+            rc = assuan_send_data (parm->ctx, der, derlen);
+          ksba_cert_release (cert);
+        }
+    }
+  else if ( !strncmp (line, "PRINTINFO", 9) && (line[9] == ' ' || !line[9]) )
+    { /* Simply show the message given in the argument. */
+      line += 9;
+      log_info ("dirmngr: %s\n", line);
+    }
+  else
+    {
+      log_error ("unsupported inquiry `%s'\n", line);
+      rc = ASSUAN_Inquire_Unknown;
+    }
+
+  return rc; 
+}
+
+static AssuanError
+run_command_status_cb (void *opaque, const char *line)
+{
+  if (opt.verbose)
+    {
+      log_info ("dirmngr status: %s\n", line);
+    }
+  return 0;
+}
+
+
+
+/* Pass COMMAND to dirmngr and print all output generated by Dirmngr
+   to stdout.  A couple of inquiries are defined (see above).  ARGC
+   arguments in ARGV are given to the Dirmngr.  Spaces, plus and
+   percent characters within the argument strings are percent escaped
+   so that blanks can act as delimiters. */
+int
+gpgsm_dirmngr_run_command (CTRL ctrl, const char *command,
+                           int argc, char **argv)
+{ 
+  int rc;
+  int i;
+  const char *s;
+  char *line, *p;
+  size_t len;
+  struct run_command_parm_s parm;
+
+  rc = start_dirmngr ();
+  if (rc)
+    return rc;
+
+  parm.ctx = dirmngr_ctx;
+
+  len = strlen (command) + 1;
+  for (i=0; i < argc; i++)
+    len += 1 + 3*strlen (argv[i]); /* enough space for percent escaping */
+  line = xtrymalloc (len);
+  if (!line)
+    return GNUPG_Out_Of_Core;
+
+  p = stpcpy (line, command);
+  for (i=0; i < argc; i++)
+    {
+      *p++ = ' ';
+      for (s=argv[i]; *s; s++)
+        {
+          if (!isascii (*s))
+            *p++ = *s;
+          else if (*s == ' ')
+            *p++ = '+';
+          else if (!isprint (*s) || *s == '+')
+            {
+              sprintf (p, "%%%02X", *s);
+              p += 3;
+            }
+          else
+            *p++ = *s;
+        }
+    }
+  *p = 0;
+
+  rc = assuan_transact (dirmngr_ctx, line,
+                        run_command_cb, NULL,
+                        run_command_inq_cb, &parm,
+                        run_command_status_cb, NULL);
+  xfree (line);
+  log_info ("response of dirmngr: %s\n", rc? assuan_strerror (rc): "okay");
+  return map_assuan_err (rc);
+}