[svn] GnuPG - r5324 - in branches/STABLE-BRANCH-2-0: agent common scd

svn author wk cvs at cvs.gnupg.org
Mon May 3 13:10:50 CEST 2010


Author: wk
Date: 2010-05-03 13:10:49 +0200 (Mon, 03 May 2010)
New Revision: 5324

Modified:
   branches/STABLE-BRANCH-2-0/agent/ChangeLog
   branches/STABLE-BRANCH-2-0/agent/call-scd.c
   branches/STABLE-BRANCH-2-0/agent/gpg-agent.c
   branches/STABLE-BRANCH-2-0/common/ChangeLog
   branches/STABLE-BRANCH-2-0/common/asshelp.c
   branches/STABLE-BRANCH-2-0/scd/ChangeLog
   branches/STABLE-BRANCH-2-0/scd/apdu.c
   branches/STABLE-BRANCH-2-0/scd/apdu.h
   branches/STABLE-BRANCH-2-0/scd/command.c
   branches/STABLE-BRANCH-2-0/scd/sc-copykeys.c
Log:
Collected changes


Modified: branches/STABLE-BRANCH-2-0/agent/ChangeLog
===================================================================
--- branches/STABLE-BRANCH-2-0/agent/ChangeLog	2010-04-27 14:11:41 UTC (rev 5323)
+++ branches/STABLE-BRANCH-2-0/agent/ChangeLog	2010-05-03 11:10:49 UTC (rev 5324)
@@ -1,3 +1,12 @@
+2010-05-03  Werner Koch  <wk at g10code.com>
+
+	* gpg-agent.c (check_own_socket_thread): Do not release SOCKNAME
+	too early.
+
+2010-03-17  Werner Koch  <wk at g10code.com>
+
+	* call-scd.c (unlock_scd): Send a BYE under certain conditions.
+
 2010-02-19  Werner Koch  <wk at g10code.com>
 
 	* call-pinentry.c (start_pinentry): Remove a translation prefix.

Modified: branches/STABLE-BRANCH-2-0/common/ChangeLog
===================================================================
--- branches/STABLE-BRANCH-2-0/common/ChangeLog	2010-04-27 14:11:41 UTC (rev 5323)
+++ branches/STABLE-BRANCH-2-0/common/ChangeLog	2010-05-03 11:10:49 UTC (rev 5324)
@@ -1,3 +1,8 @@
+2010-03-17  Werner Koch  <wk at g10code.com>
+
+	* asshelp.c (start_new_gpg_agent) [W32]: Use a named mutex to
+	avoid starting two agents.
+
 2010-03-12  Werner Koch  <wk at g10code.com>
 
 	* status.h (STATUS_ENTER): New.

Modified: branches/STABLE-BRANCH-2-0/scd/ChangeLog
===================================================================
--- branches/STABLE-BRANCH-2-0/scd/ChangeLog	2010-04-27 14:11:41 UTC (rev 5323)
+++ branches/STABLE-BRANCH-2-0/scd/ChangeLog	2010-05-03 11:10:49 UTC (rev 5324)
@@ -1,3 +1,14 @@
+2010-03-17  Werner Koch  <wk at g10code.com>
+
+	* command.c (open_card): Return GPG_ERR_NOT_OPERATIONAL if no
+	card services are available.
+	(get_reader_slot): Detect no services status.
+	(cmd_serialno): No reset if there are no services.
+	(scd_command_handler): Stop scdaemon in that case.
+	* apdu.c (pcsc_no_service): New.
+	(open_pcsc_reader_direct): Set it.
+	(apdu_open_reader): Add arg R_NO_SERVICE.
+
 2010-02-11  Marcus Brinkmann  <marcus at g10code.de>
 
 	From trunk 2009-09-23, 2009-10-16, 2009-11-02, 2009-11-04, 2009-11-05,

Modified: branches/STABLE-BRANCH-2-0/agent/call-scd.c
===================================================================
--- branches/STABLE-BRANCH-2-0/agent/call-scd.c	2010-04-27 14:11:41 UTC (rev 5323)
+++ branches/STABLE-BRANCH-2-0/agent/call-scd.c	2010-05-03 11:10:49 UTC (rev 5324)
@@ -176,6 +176,17 @@
 static int 
 unlock_scd (ctrl_t ctrl, int rc)
 {
+  if (gpg_err_code (rc) == GPG_ERR_NOT_OPERATIONAL
+      && gpg_err_source (rc) == GPG_ERR_SOURCE_SCD)
+    {
+      /* If the SCdaemon returned this error, it detected a major
+         problem, like no reader connected.  To finish this we need to
+         stop the connection.  This simulates an explicit killing of
+         the SCdaemon.  */
+      assuan_transact (primary_scd_ctx, "BYE",
+                       NULL, NULL, NULL, NULL, NULL, NULL);
+    }
+      
   if (ctrl->scd_local->locked != 1)
     {
       log_error ("unlock_scd: invalid lock count (%d)\n",

Modified: branches/STABLE-BRANCH-2-0/agent/gpg-agent.c
===================================================================
--- branches/STABLE-BRANCH-2-0/agent/gpg-agent.c	2010-04-27 14:11:41 UTC (rev 5323)
+++ branches/STABLE-BRANCH-2-0/agent/gpg-agent.c	2010-05-03 11:10:49 UTC (rev 5324)
@@ -2101,7 +2101,6 @@
   check_own_socket_running++;
 
   rc = assuan_new (&ctx);
-  xfree (sockname);
   if (rc)
     {
       log_error ("can't allocate assuan context: %s\n", gpg_strerror (rc));
@@ -2137,6 +2136,7 @@
   xfree (buffer);
 
  leave:
+  xfree (sockname);
   if (ctx)
     assuan_release (ctx);
   if (rc)

Modified: branches/STABLE-BRANCH-2-0/common/asshelp.c
===================================================================
--- branches/STABLE-BRANCH-2-0/common/asshelp.c	2010-04-27 14:11:41 UTC (rev 5323)
+++ branches/STABLE-BRANCH-2-0/common/asshelp.c	2010-05-03 11:10:49 UTC (rev 5324)
@@ -231,25 +231,68 @@
                and thus there is no need for the GPG_AGENT_INFO
                envvar.  This is possible as we don't have a real unix
                domain socket but use a plain file and thus there is no
-               need to care about non-local file systems. */
+               need to care about non-local file systems.  We use a
+               named mutex to interlock the spawning.  There is just
+               one problem with that: If gpg-agent needs more than 3
+               seconds to come up and listen on the socket we might
+               still spawn another agent.  However this is no serious
+               problem because an agent detects this and handles it.
+               Thus the mutex merely helps to save resources in the
+               most common cases.  */
             const char *argv[3];
+            HANDLE mutex;
+            int waitrc;
 
             argv[0] = "--daemon";
             argv[1] = "--use-standard-socket"; 
             argv[2] = NULL;  
 
-            rc = gnupg_spawn_process_detached (agent_program, argv, NULL);
-            if (rc)
-              log_debug ("failed to start agent `%s': %s\n",
-                         agent_program, gpg_strerror (rc));
+            mutex = CreateMutex (NULL, FALSE, "GnuPG_spawn_agent_sentinel");
+            if (!mutex)
+              {
+                log_error ("failed to create the spawn_agent mutex: %s\n",
+                           w32_strerror (-1));
+                rc = gpg_error (GPG_ERR_GENERAL);
+              }
+            else if ((waitrc = WaitForSingleObject (mutex, 5000))
+                     == WAIT_OBJECT_0)
+              {
+                rc = assuan_socket_connect (&ctx, sockname, 0);
+                if (rc)
+                  {
+                    /* Still not available.  */
+                    rc = gnupg_spawn_process_detached (agent_program,
+                                                       argv, NULL);
+                    if (rc)
+                      log_debug ("failed to start agent `%s': %s\n",
+                                 agent_program, gpg_strerror (rc));
+                    else
+                      {
+                        /* Give the agent some time to prepare itself. */
+                        gnupg_sleep (3);
+                        /* Now try again to connect the agent.  */
+                        rc = assuan_socket_connect (&ctx, sockname, 0);
+                      }
+                  }
+                if (!ReleaseMutex (mutex))
+                  log_error ("failed to release the spawn_agent mutex: %s\n",
+                             w32_strerror (-1));
+              }
+            else if (waitrc == WAIT_TIMEOUT)
+              {
+                log_info ("error waiting for the spawn_agent mutex: timeout\n");
+                rc = gpg_error (GPG_ERR_GENERAL);
+              }
             else
               {
-                /* Give the agent some time to prepare itself. */
-                gnupg_sleep (3);
-                /* Now try again to connect the agent.  */
-                rc = assuan_socket_connect (ctx, sockname, 0, 0);
+                log_debug ("error waiting for the spawn_agent mutex: "
+                           "(code=%d) %s\n", waitrc, w32_strerror (-1));
+                rc = gpg_error (GPG_ERR_GENERAL);
               }
-          }
+            
+            if (mutex)
+              CloseHandle (mutex);
+        }
 #else /*!HAVE_W32_SYSTEM*/
           {
             const char *pgmname;

Modified: branches/STABLE-BRANCH-2-0/scd/apdu.c
===================================================================
--- branches/STABLE-BRANCH-2-0/scd/apdu.c	2010-04-27 14:11:41 UTC (rev 5323)
+++ branches/STABLE-BRANCH-2-0/scd/apdu.c	2010-05-03 11:10:49 UTC (rev 5324)
@@ -287,7 +287,10 @@
 long (* DLSTDCALL pcsc_set_timeout) (unsigned long context,
                                      unsigned long timeout);
 
+/* Flag set if PC/SC returned the no-service error.  */
+static int pcsc_no_service;
 
+
 /*  Prototypes.  */
 static int pcsc_get_status (int slot, unsigned int *status);
 static int reset_pcsc_reader (int slot);
@@ -1487,8 +1490,11 @@
       log_error ("pcsc_establish_context failed: %s (0x%lx)\n",
                  pcsc_error_string (err), err);
       reader_table[slot].used = 0;
+      if (err == 0x8010001d)
+        pcsc_no_service = 1;
       return -1;
     }
+  pcsc_no_service = 0;
 
   err = pcsc_list_readers (reader_table[slot].pcsc.context,
                            NULL, NULL, &nreader);
@@ -2321,14 +2327,18 @@
    error. If PORTSTR is NULL we default to a suitable port (for ctAPI:
    the first USB reader.  For PC/SC the first listed reader). */
 int
-apdu_open_reader (const char *portstr)
+apdu_open_reader (const char *portstr, int *r_no_service)
 {
   static int pcsc_api_loaded, ct_api_loaded;
+  int slot;
 
+  if (r_no_service)
+    *r_no_service = 0;
+
 #ifdef HAVE_LIBUSB
   if (!opt.disable_ccid)
     {
-      int slot, i;
+      int i;
       const char *s;
 
       slot = open_ccid_reader (portstr);
@@ -2458,7 +2468,11 @@
       pcsc_api_loaded = 1;
     }
 
-  return open_pcsc_reader (portstr);
+  slot = open_pcsc_reader (portstr);
+  if (slot == -1 && r_no_service && pcsc_no_service)
+    *r_no_service = 1;
+
+  return slot;
 }
 
 

Modified: branches/STABLE-BRANCH-2-0/scd/apdu.h
===================================================================
--- branches/STABLE-BRANCH-2-0/scd/apdu.h	2010-04-27 14:11:41 UTC (rev 5323)
+++ branches/STABLE-BRANCH-2-0/scd/apdu.h	2010-05-03 11:10:49 UTC (rev 5324)
@@ -80,8 +80,8 @@
 #define APDU_CARD_ACTIVE   (4)    /* Card is active.  */
 
 
-/* Note , that apdu_open_reader returns no status word but -1 on error. */
-int apdu_open_reader (const char *portstr);
+/* Note, that apdu_open_reader returns no status word but -1 on error. */
+int apdu_open_reader (const char *portstr, int *r_no_service);
 int apdu_open_remote_reader (const char *portstr,
                              const unsigned char *cookie, size_t length,
                              int (*readfnc) (void *opaque,

Modified: branches/STABLE-BRANCH-2-0/scd/command.c
===================================================================
--- branches/STABLE-BRANCH-2-0/scd/command.c	2010-04-27 14:11:41 UTC (rev 5323)
+++ branches/STABLE-BRANCH-2-0/scd/command.c	2010-05-03 11:10:49 UTC (rev 5324)
@@ -70,6 +70,10 @@
       && (c)->reader_slot == locked_session->ctrl_backlink->reader_slot)
 
 
+/* Flag indicating that the reader has been disabled.  */
+static int reader_disabled;
+
+
 /* This structure is used to keep track of open readers (slots). */
 struct slot_status_s 
 {
@@ -394,7 +398,15 @@
 
   /* Try to open the reader. */
   if (ss->slot == -1)
-    ss->slot = apdu_open_reader (opt.reader_port);
+    {
+      int no_service_flag;
+      ss->slot = apdu_open_reader (opt.reader_port, &no_service_flag);
+      if (no_service_flag)
+        {
+          log_info ("no card services - disabling scdaemon\n");
+          reader_disabled = 1;
+        }
+    }
 
   /* Return the slot_table index.  */
   return 0;
@@ -409,6 +421,9 @@
   gpg_error_t err;
   int slot;
 
+  if (reader_disabled)
+    return gpg_error (GPG_ERR_NOT_OPERATIONAL);
+
   /* If we ever got a card not present error code, return that.  Only
      the SERIALNO command and a reset are able to clear from that
      state. */
@@ -441,7 +456,7 @@
     slot = get_reader_slot ();
   ctrl->reader_slot = slot;
   if (slot == -1)
-    err = gpg_error (GPG_ERR_CARD);
+    err = gpg_error (reader_disabled? GPG_ERR_NOT_OPERATIONAL: GPG_ERR_CARD);
   else
     {
       /* Fixme: We should move the apdu_connect call to
@@ -495,7 +510,7 @@
   time_t stamp;
 
   /* Clear the remove flag so that the open_card is able to reread it.  */
-  if (ctrl->server_local->card_removed)
+  if (!reader_disabled && ctrl->server_local->card_removed)
     {
       if ( IS_LOCKED (ctrl) )
         return gpg_error (GPG_ERR_LOCKED);
@@ -1995,7 +2010,7 @@
           BUG ();
       sl->next_session = ctrl->server_local->next_session;
     }
-  stopme = ctrl->server_local->stopme;
+  stopme = ctrl->server_local->stopme || reader_disabled;
   xfree (ctrl->server_local);
   ctrl->server_local = NULL;
 

Modified: branches/STABLE-BRANCH-2-0/scd/sc-copykeys.c
===================================================================
--- branches/STABLE-BRANCH-2-0/scd/sc-copykeys.c	2010-04-27 14:11:41 UTC (rev 5323)
+++ branches/STABLE-BRANCH-2-0/scd/sc-copykeys.c	2010-05-03 11:10:49 UTC (rev 5324)
@@ -139,7 +139,7 @@
   if (argc != 1)
     usage (1);
 
-  slot = apdu_open_reader (reader_port);
+  slot = apdu_open_reader (reader_port, NULL);
   if (slot == -1)
     exit (1);
   if (apdu_connect (slot))




More information about the Gnupg-commits mailing list