2008-08-08 Marcus Brinkmann <marcus@g10code.de>
authorMarcus Brinkmann <mb@g10code.com>
Fri, 8 Aug 2008 01:06:48 +0000 (01:06 +0000)
committerMarcus Brinkmann <mb@g10code.com>
Fri, 8 Aug 2008 01:06:48 +0000 (01:06 +0000)
* gpgsm.h (struct server_control_s): Remove member dirmngr_seen.
* call-dirmngr.c (dirmngr2_ctx, dirmngr_ctx_locked)
(dirmngr2_ctx_locked): New global variables.
(prepare_dirmngr): Don't check dirmngr_seen anymore.
(start_dirmngr): Move bunch of code to ...
(start_dirmngr_ext): ... this new function.
(release_dirmngr, start_dirmngr2, release_dirmngr2): New
functions.
(gpgsm_dirmngr_isvalid): Call release_dirmngr.
(gpgsm_dirmngr_lookup): Call release_dirmngr.  If dirmngr_ctx is
locked, use dirmngr2_locked.
(gpgsm_dirmngr_run_command): Call release_dirmngr.

sm/ChangeLog
sm/call-dirmngr.c
sm/gpgsm.h

index a6a584b..e96970c 100644 (file)
@@ -1,3 +1,18 @@
+2008-08-08  Marcus Brinkmann  <marcus@g10code.de>
+
+       * gpgsm.h (struct server_control_s): Remove member dirmngr_seen.
+       * call-dirmngr.c (dirmngr2_ctx, dirmngr_ctx_locked)
+       (dirmngr2_ctx_locked): New global variables.
+       (prepare_dirmngr): Don't check dirmngr_seen anymore.
+       (start_dirmngr): Move bunch of code to ...
+       (start_dirmngr_ext): ... this new function.
+       (release_dirmngr, start_dirmngr2, release_dirmngr2): New
+       functions.
+       (gpgsm_dirmngr_isvalid): Call release_dirmngr.
+       (gpgsm_dirmngr_lookup): Call release_dirmngr.  If dirmngr_ctx is
+       locked, use dirmngr2_locked.
+       (gpgsm_dirmngr_run_command): Call release_dirmngr.
+
 2008-06-25  Werner Koch  <wk@g10code.com>
 
        * sign.c (gpgsm_sign): Revamp the hash algorithm selection.
index 4cbc019..3777092 100644 (file)
@@ -44,7 +44,14 @@ struct membuf {
 
 
 
+/* fixme: We need a context for each thread or serialize the access to
+   the dirmngr.  */
 static assuan_context_t dirmngr_ctx = NULL;
+static assuan_context_t dirmngr2_ctx = NULL;
+
+static int dirmngr_ctx_locked;
+static int dirmngr2_ctx_locked;
+
 static int force_pipe_server = 0;
 
 struct inq_certificate_parm_s {
@@ -142,18 +149,14 @@ prepare_dirmngr (ctrl_t ctrl, assuan_context_t ctx, gpg_error_t err)
 {
   struct keyserver_spec *server;
 
-  if (!ctrl->dirmngr_seen)
+  if (!err)
     {
-      ctrl->dirmngr_seen = 1;
-      if (!err)
-        {
-          err = assuan_transact (ctx, "OPTION audit-events=1",
-                                 NULL, NULL, NULL, NULL, NULL, NULL);
-          if (gpg_err_code (err) == GPG_ERR_UNKNOWN_OPTION)
-            err = 0;  /* Allow the use of old dirmngr versions.  */
-        }
-      audit_log_ok (ctrl->audit, AUDIT_DIRMNGR_READY, err);
+      err = assuan_transact (ctx, "OPTION audit-events=1",
+                            NULL, NULL, NULL, NULL, NULL, NULL);
+      if (gpg_err_code (err) == GPG_ERR_UNKNOWN_OPTION)
+       err = 0;  /* Allow the use of old dirmngr versions.  */
     }
+  audit_log_ok (ctrl->audit, AUDIT_DIRMNGR_READY, err);
 
   server = opt.keyserver;
   while (server)
@@ -162,7 +165,7 @@ prepare_dirmngr (ctrl_t ctrl, assuan_context_t ctx, gpg_error_t err)
       char *user = server->user ? server->user : "";
       char *pass = server->pass ? server->pass : "";
       char *base = server->base ? server->base : "";
-
+      
       snprintf (line, DIM (line) - 1, "LDAPSERVER %s:%i:%s:%s:%s",
                server->host, server->port, user, pass, base);
       line[DIM (line) - 1] = 0;
@@ -180,7 +183,7 @@ prepare_dirmngr (ctrl_t ctrl, assuan_context_t ctx, gpg_error_t err)
 /* Try to connect to the agent via socket or fork it off and work by
    pipes.  Handle the server's initial greeting */
 static int
-start_dirmngr (ctrl_t ctrl)
+start_dirmngr_ext (ctrl_t ctrl, assuan_context_t *ctx_r)
 {
   int rc;
   char *infostr, *p;
@@ -190,12 +193,9 @@ start_dirmngr (ctrl_t ctrl)
   if (opt.disable_dirmngr)
     return gpg_error (GPG_ERR_NO_DIRMNGR);
 
-  if (dirmngr_ctx)
-    {
-      prepare_dirmngr (ctrl, dirmngr_ctx, 0);
-      return 0; /* fixme: We need a context for each thread or serialize
-                   the access to the dirmngr */
-    }
+  if (*ctx_r)
+    return 0;
+
   /* Note: if you change this to multiple connections, you also need
      to take care of the implicit option sending caching. */
 
@@ -266,7 +266,7 @@ start_dirmngr (ctrl_t ctrl)
               log_error (_("malformed DIRMNGR_INFO environment variable\n"));
               xfree (infostr);
               force_pipe_server = 1;
-              return start_dirmngr (ctrl);
+              return start_dirmngr_ext (ctrl, ctx_r);
             }
           *p++ = 0;
           pid = atoi (p);
@@ -279,7 +279,7 @@ start_dirmngr (ctrl_t ctrl)
                          prot);
               xfree (infostr);
               force_pipe_server = 1;
-              return start_dirmngr (ctrl);
+              return start_dirmngr_ext (ctrl, ctx_r);
             }
         }
       else
@@ -297,7 +297,7 @@ start_dirmngr (ctrl_t ctrl)
         {
           log_info (_("can't connect to the dirmngr - trying fall back\n"));
           force_pipe_server = 1;
-          return start_dirmngr (ctrl);
+          return start_dirmngr_ext (ctrl, ctx_r);
         }
 #endif /*!HAVE_W32_SYSTEM*/
     }
@@ -309,7 +309,7 @@ start_dirmngr (ctrl_t ctrl)
       log_error ("can't connect to the dirmngr: %s\n", gpg_strerror (rc));
       return gpg_error (GPG_ERR_NO_DIRMNGR);
     }
-  dirmngr_ctx = ctx;
+  *ctx_r = ctx;
 
   if (DBG_ASSUAN)
     log_debug ("connection to dirmngr established\n");
@@ -317,6 +317,42 @@ start_dirmngr (ctrl_t ctrl)
 }
 
 
+static int
+start_dirmngr (ctrl_t ctrl)
+{
+  assert (! dirmngr_ctx_locked);
+  dirmngr_ctx_locked = 1;
+
+  return start_dirmngr_ext (ctrl, &dirmngr_ctx);
+}
+
+
+static void
+release_dirmngr (ctrl_t ctrl)
+{
+  assert (dirmngr_ctx_locked);
+  dirmngr_ctx_locked = 0;
+}
+
+
+static int
+start_dirmngr2 (ctrl_t ctrl)
+{
+  assert (! dirmngr2_ctx_locked);
+  dirmngr2_ctx_locked = 1;
+
+  return start_dirmngr_ext (ctrl, &dirmngr2_ctx);
+}
+
+
+static void
+release_dirmngr2 (ctrl_t ctrl)
+{
+  assert (dirmngr2_ctx_locked);
+  dirmngr2_ctx_locked = 0;
+}
+
+
 \f
 /* Handle a SENDCERT inquiry. */
 static int
@@ -485,6 +521,7 @@ gpgsm_dirmngr_isvalid (ctrl_t ctrl,
       if (!certid)
         {
           log_error ("error getting the certificate ID\n");
+         release_dirmngr (ctrl);
           return gpg_error (GPG_ERR_GENERAL);
         }
     }
@@ -584,6 +621,7 @@ gpgsm_dirmngr_isvalid (ctrl_t ctrl,
           ksba_cert_release (rspcert);
         }
     }
+  release_dirmngr (ctrl);
   return rc;
 }
 
@@ -738,31 +776,59 @@ gpgsm_dirmngr_lookup (ctrl_t ctrl, strlist_t names, int cache_only,
   char line[ASSUAN_LINELENGTH];
   struct lookup_parm_s parm;
   size_t len;
+  assuan_context_t ctx;
 
-  rc = start_dirmngr (ctrl);
-  if (rc)
-    return rc;
+  /* The lookup function can be invoked from the callback of a lookup
+     function, for example to walk the chain.  */
+  assert (!dirmngr_ctx_locked || !dirmngr2_ctx_locked);
+  if (! dirmngr_ctx_locked)
+    {
+      rc = start_dirmngr (ctrl);
+      if (rc)
+       return rc;
+      ctx = dirmngr_ctx;
+    }
+  else
+    {
+      rc = start_dirmngr2 (ctrl);
+      if (rc)
+       return rc;
+      ctx = dirmngr2_ctx;
+    }
 
   pattern = pattern_from_strlist (names);
   if (!pattern)
-    return out_of_core ();
+    {
+      if (ctx == dirmngr_ctx)
+       release_dirmngr (ctrl);
+      else
+       release_dirmngr2 (ctrl);
+
+      return out_of_core ();
+    }
   snprintf (line, DIM(line)-1, "LOOKUP%s %s", 
             cache_only? " --cache-only":"", pattern);
   line[DIM(line)-1] = 0;
   xfree (pattern);
 
   parm.ctrl = ctrl;
-  parm.ctx = dirmngr_ctx;
+  parm.ctx = ctx;
   parm.cb = cb;
   parm.cb_value = cb_value;
   parm.error = 0;
   init_membuf (&parm.data, 4096);
 
-  rc = assuan_transact (dirmngr_ctx, line, lookup_cb, &parm,
+  rc = assuan_transact (ctx, line, lookup_cb, &parm,
                         NULL, NULL, lookup_status_cb, &parm);
   xfree (get_membuf (&parm.data, &len));
+
+  if (ctx == dirmngr_ctx)
+    release_dirmngr (ctrl);
+  else
+    release_dirmngr2 (ctrl);
+
   if (rc)
-    return rc;
+      return rc;
   return parm.error;
 }
 
@@ -881,7 +947,10 @@ gpgsm_dirmngr_run_command (ctrl_t ctrl, const char *command,
     len += 1 + 3*strlen (argv[i]); /* enough space for percent escaping */
   line = xtrymalloc (len);
   if (!line)
-    return out_of_core ();
+    {
+      release_dirmngr (ctrl);
+      return out_of_core ();
+    }
 
   p = stpcpy (line, command);
   for (i=0; i < argc; i++)
@@ -910,5 +979,6 @@ gpgsm_dirmngr_run_command (ctrl_t ctrl, const char *command,
                         run_command_status_cb, ctrl);
   xfree (line);
   log_info ("response of dirmngr: %s\n", rc? gpg_strerror (rc): "okay");
+  release_dirmngr (ctrl);
   return rc;
 }
index 2cd1775..add1928 100644 (file)
@@ -172,8 +172,6 @@ struct server_control_s
   audit_ctx_t audit;  /* NULL or a context for the audit subsystem.  */
   int agent_seen;     /* Flag indicating that the gpg-agent has been
                          accessed.  */
-  int dirmngr_seen;   /* Flag indicating that the dirmngr has been
-                         accessed.  */
   
   int with_colons;    /* Use column delimited output format */
   int with_chain;     /* Include the certifying certs in a listing */