Fix usage of ARGPARSE_OPTS.
[gnupg.git] / dirmngr / dirmngr-client.c
index 770e941..53b405e 100644 (file)
@@ -15,7 +15,7 @@
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
  */
 
 #include <config.h>
 #include <gpg-error.h>
 #include <assuan.h>
 
-#define JNLIB_NEED_LOG_LOGV
 #include "../common/logging.h"
 #include "../common/argparse.h"
 #include "../common/stringhelp.h"
 #include "../common/mischelp.h"
 #include "../common/strlist.h"
+#include "../common/asshelp.h"
 
-#include "i18n.h"
-#include "util.h"
-#include "init.h"
+#include "../common/i18n.h"
+#include "../common/util.h"
+#include "../common/init.h"
 
 
 /* Constants for the options.  */
@@ -80,7 +80,7 @@ static ARGPARSE_OPTS opts[] = {
   { oPEM,      "pem",       0, N_("expect certificates in PEM format")},
   { oForceDefaultResponder, "force-default-responder", 0,
     N_("force the use of the default OCSP responder")},
-  { 0, NULL, 0, NULL }
+  ARGPARSE_end ()
 };
 
 
@@ -90,7 +90,6 @@ static struct
   int quiet;
   int verbose;
   const char *dirmngr_program;
-  int force_pipe_server;
   int force_default_responder;
   int pem;
   int escaped_pem; /* PEM is additional percent encoded.  */
@@ -117,8 +116,26 @@ static unsigned char bintoasc[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
 static unsigned char asctobin[256]; /* runtime initialized */
 
 
+/* Build the helptable for radix64 to bin conversion. */
+static void
+init_asctobin (void)
+{
+  static int initialized;
+  int i;
+  unsigned char *s;
+
+  if (initialized)
+    return;
+  initialized = 1;
+
+  for (i=0; i < 256; i++ )
+    asctobin[i] = 255; /* Used to detect invalid characters. */
+  for (s=bintoasc, i=0; *s; s++, i++)
+    asctobin[*s] = i;
+}
+
+
 /* Prototypes.  */
-static assuan_context_t start_dirmngr (int only_daemon);
 static gpg_error_t read_certificate (const char *fname,
                                      unsigned char **rbuf, size_t *rbuflen);
 static gpg_error_t do_check (assuan_context_t ctx,
@@ -184,9 +201,9 @@ main (int argc, char **argv )
   early_system_init ();
   set_strusage (my_strusage);
   log_set_prefix ("dirmngr-client",
-                  JNLIB_LOG_WITH_PREFIX);
+                  GPGRT_LOG_WITH_PREFIX);
 
-  /* For W32 we need to initialize the socket subsystem.  Becuase we
+  /* For W32 we need to initialize the socket subsystem.  Because we
      don't use Pth we need to do this explicit. */
 #ifdef HAVE_W32_SYSTEM
  {
@@ -236,19 +253,6 @@ main (int argc, char **argv )
   if (log_get_errorcount (0))
     exit (2);
 
-  /* Build the helptable for radix64 to bin conversion. */
-  if (opt.pem)
-    {
-      int i;
-      unsigned char *s;
-
-      for (i=0; i < 256; i++ )
-        asctobin[i] = 255; /* Used to detect invalid characters. */
-      for (s=bintoasc, i=0; *s; s++, i++)
-        asctobin[*s] = i;
-    }
-
-
   if (cmd_ping)
     err = 0;
   else if (cmd_lookup || cmd_loadcrl)
@@ -292,9 +296,20 @@ main (int argc, char **argv )
       exit (2);
     }
 
-  ctx = start_dirmngr (1);
-  if (!ctx)
-    exit (2);
+  err = start_new_dirmngr (&ctx,
+                           GPG_ERR_SOURCE_DEFAULT,
+                           opt.dirmngr_program
+                             ? opt.dirmngr_program
+                             : gnupg_module_name (GNUPG_MODULE_NAME_DIRMNGR),
+                           ! cmd_ping,
+                           opt.verbose,
+                           0,
+                           NULL, NULL);
+  if (err)
+    {
+      log_error (_("can't connect to the dirmngr: %s\n"), gpg_strerror (err));
+      exit (2);
+    }
 
   if (cmd_ping)
     ;
@@ -432,131 +447,6 @@ data_cb (void *opaque, const void *buffer, size_t length)
 }
 
 
-/* Try to connect to the dirmngr via socket or fork it off and work by
-   pipes.  Handle the server's initial greeting */
-static assuan_context_t
-start_dirmngr (int only_daemon)
-{
-  int rc;
-  char *infostr, *p;
-  assuan_context_t ctx;
-  int try_default = 0;
-
-  infostr = opt.force_pipe_server? NULL : getenv (DIRMNGR_INFO_NAME);
-  if (only_daemon && (!infostr || !*infostr))
-    {
-      if (dirmngr_user_socket_name ())
-        infostr = xstrdup (dirmngr_user_socket_name ());
-      else
-        infostr = xstrdup (dirmngr_sys_socket_name ());
-      try_default = 1;
-    }
-
-  rc = assuan_new (&ctx);
-  if (rc)
-    {
-      log_error (_("failed to allocate assuan context: %s\n"),
-                 gpg_strerror (rc));
-      return NULL;
-    }
-
-  if (!infostr || !*infostr)
-    {
-      const char *pgmname;
-      const char *argv[3];
-      assuan_fd_t no_close_list[3];
-      int i;
-
-      if (only_daemon)
-        {
-          log_error (_("apparently no running dirmngr\n"));
-          return NULL;
-        }
-
-      if (opt.verbose)
-        log_info (_("no running dirmngr - starting one\n"));
-
-      if (!opt.dirmngr_program || !*opt.dirmngr_program)
-        opt.dirmngr_program = "./dirmngr";
-      if ( !(pgmname = strrchr (opt.dirmngr_program, '/')))
-        pgmname = opt.dirmngr_program;
-      else
-        pgmname++;
-
-      argv[0] = pgmname;
-      argv[1] = "--server";
-      argv[2] = NULL;
-
-      i=0;
-      if (log_get_fd () != -1)
-        no_close_list[i++] = assuan_fd_from_posix_fd (log_get_fd ());
-      no_close_list[i++] = assuan_fd_from_posix_fd (es_fileno (es_stderr));
-      no_close_list[i] = ASSUAN_INVALID_FD;
-
-      /* Connect to the agent and perform initial handshaking.  */
-      rc = assuan_pipe_connect (ctx, opt.dirmngr_program, argv,
-                                no_close_list, NULL, NULL, 0);
-    }
-  else /* Connect to a daemon.  */
-    {
-      int prot;
-      int pid;
-
-      infostr = xstrdup (infostr);
-      if (!try_default && *infostr)
-        {
-          if ( !(p = strchr (infostr, ':')) || p == infostr)
-            {
-              log_error (_("malformed %s environment variable\n"),
-                         DIRMNGR_INFO_NAME);
-              xfree (infostr);
-              if (only_daemon)
-                return NULL;
-              /* Try again by starting a new instance.  */
-              opt.force_pipe_server = 1;
-              return start_dirmngr (0);
-            }
-          *p++ = 0;
-          pid = atoi (p);
-          while (*p && *p != ':')
-            p++;
-          prot = *p? atoi (p+1) : 0;
-          if (prot != 1)
-            {
-              log_error (_("dirmngr protocol version %d is not supported\n"),
-                         prot);
-              xfree (infostr);
-              if (only_daemon)
-                return NULL;
-              opt.force_pipe_server = 1;
-              return start_dirmngr (0);
-            }
-        }
-      else
-        pid = -1;
-
-      rc = assuan_socket_connect (ctx, infostr, pid, 0);
-      xfree (infostr);
-      if (gpg_err_code(rc) == GPG_ERR_ASS_CONNECT_FAILED && !only_daemon)
-        {
-          log_error (_("can't connect to the dirmngr - trying fall back\n"));
-          opt.force_pipe_server = 1;
-          return start_dirmngr (0);
-        }
-    }
-
-  if (rc)
-    {
-      assuan_release (ctx);
-      log_error (_("can't connect to the dirmngr: %s\n"),
-                 gpg_strerror (rc));
-      return NULL;
-    }
-
-  return ctx;
-}
-
-
 /* Read the first PEM certificate from the file FNAME.  If fname is
    NULL the next certificate is read from stdin.  The certificate is
    returned in an alloced buffer whose address will be returned in
@@ -576,6 +466,8 @@ read_pem_certificate (const char *fname, unsigned char **rbuf, size_t *rbuflen)
     s_waitend
   } state = s_init;
 
+  init_asctobin ();
+
   fp = fname? fopen (fname, "r") : stdin;
   if (!fp)
     return gpg_error_from_errno (errno);
@@ -625,7 +517,7 @@ read_pem_certificate (const char *fname, unsigned char **rbuf, size_t *rbuflen)
             }
           break;
         case s_init:
-          state = s_lfseen;
+          state = s_lfseen; /* fall through */
         case s_lfseen:
           if (c != "-----BEGIN "[pos])
             state = s_idle;
@@ -727,6 +619,15 @@ read_certificate (const char *fname, unsigned char **rbuf, size_t *rbuflen)
 
   if (opt.pem)
     return read_pem_certificate (fname, rbuf, rbuflen);
+  else if (fname)
+    {
+      /* A filename has been given.  Let's just assume it is in PEM
+         format and decode it, and fall back to interpreting it as
+         binary certificate if that fails.  */
+      err = read_pem_certificate (fname, rbuf, rbuflen);
+      if (! err)
+        return 0;
+    }
 
   fp = fname? fopen (fname, "rb") : stdin;
   if (!fp)