Bläddra i källkod

2008-10-01 Marcus Brinkmann <marcus@g10code.com>

	* src/agent.c (agent_connect): Set assuan log stream.
	* src/p11-initialize.c: Include "debug.h".
	(C_Initialize): Call _scute_debug_init.
	* src/Makefile.am (sources): Add debug.c.
	* src/debug.c: New file.
	* src/debug.h: Rewritten.
	* src/agent.c, src/cert-gpgsm.c, src/cert-object.c,
          src/slots.c, src/error-mapping.c: More or improved or
          adjusted debug output.
Marcus Brinkmann 17 år sedan
förälder
incheckning
37d267f741
10 ändrade filer med 331 tillägg och 61 borttagningar
  1. 12 0
      ChangeLog
  2. 1 1
      src/Makefile.am
  3. 35 20
      src/agent.c
  4. 4 4
      src/cert-gpgsm.c
  5. 111 28
      src/cert-object.c
  6. 143 0
      src/debug.c
  7. 19 5
      src/debug.h
  8. 1 1
      src/error-mapping.c
  9. 4 1
      src/p11-initialize.c
  10. 1 1
      src/slots.c

+ 12 - 0
ChangeLog

@@ -1,3 +1,15 @@
+2008-10-01  Marcus Brinkmann  <marcus@g10code.com>
+
+	* src/agent.c (agent_connect): Set assuan log stream.
+	* src/p11-initialize.c: Include "debug.h".
+	(C_Initialize): Call _scute_debug_init.
+	* src/Makefile.am (sources): Add debug.c.
+	* src/debug.c: New file.
+	* src/debug.h: Rewritten.
+	* src/agent.c, src/cert-gpgsm.c, src/cert-object.c,
+          src/slots.c, src/error-mapping.c: More or improved or
+          adjusted debug output.
+
 2008-09-30  Marcus Brinkmann  <marcus@g10code.com>
 2008-09-30  Marcus Brinkmann  <marcus@g10code.com>
 
 
 	* src/cert-object.c [!CERT_PARSING]: Disable some certificate
 	* src/cert-object.c [!CERT_PARSING]: Disable some certificate

+ 1 - 1
src/Makefile.am

@@ -31,7 +31,7 @@
 
 
 EXTRA_DIST = libscute.vers scute.def versioninfo.rc.in stpcpy.h
 EXTRA_DIST = libscute.vers scute.def versioninfo.rc.in stpcpy.h
 
 
-sources = cryptoki.h pkcs11.h debug.h settings.h support.h		\
+sources = cryptoki.h pkcs11.h debug.c debug.h settings.h support.h	\
 	locking.h locking.c error-mapping.h error-mapping.c		\
 	locking.h locking.c error-mapping.h error-mapping.c		\
 	get-path.c agent.h agent.c					\
 	get-path.c agent.h agent.c					\
 	slots.h slots.c table.h table.c					\
 	slots.h slots.c table.h table.c					\

+ 35 - 20
src/agent.c

@@ -67,7 +67,7 @@ gnupg_allow_set_foregound_window (pid_t pid)
     return;
     return;
 #ifdef HAVE_W32_SYSTEM
 #ifdef HAVE_W32_SYSTEM
   else if (!AllowSetForegroundWindow (pid))
   else if (!AllowSetForegroundWindow (pid))
-    DEBUG ("AllowSetForegroundWindow(%lu) failed: %i\n",
+    DEBUG (DBG_CRIT, "AllowSetForegroundWindow(%lu) failed: %i\n",
 	   (unsigned long)pid, GetLastError ());
 	   (unsigned long)pid, GetLastError ());
 #endif
 #endif
 }
 }
@@ -190,7 +190,7 @@ spawn_process_detached (const char *pgmname, const char *argv[])
               | GetPriorityClass (GetCurrentProcess ())
               | GetPriorityClass (GetCurrentProcess ())
               | CREATE_NEW_PROCESS_GROUP
               | CREATE_NEW_PROCESS_GROUP
               | DETACHED_PROCESS); 
               | DETACHED_PROCESS); 
-  DEBUG ("CreateProcess(detached), path=`%s' cmdline=`%s'\n",
+  DEBUG (DBG_INFO, "CreateProcess(detached), path=`%s' cmdline=`%s'\n",
 	 pgmname, cmdline);
 	 pgmname, cmdline);
   if (!CreateProcess (pgmname,       /* Program to start.  */
   if (!CreateProcess (pgmname,       /* Program to start.  */
                       cmdline,       /* Command line arguments.  */
                       cmdline,       /* Command line arguments.  */
@@ -204,16 +204,16 @@ spawn_process_detached (const char *pgmname, const char *argv[])
                       &pi            /* Returns process information.  */
                       &pi            /* Returns process information.  */
                       ))
                       ))
     {
     {
-      DEBUG ("CreateProcess(detached) failed: %i\n", GetLastError ());
+      DEBUG (DBG_CRIT, "CreateProcess(detached) failed: %i\n",
+	     GetLastError ());
       free (cmdline);
       free (cmdline);
       return gpg_error (GPG_ERR_GENERAL);
       return gpg_error (GPG_ERR_GENERAL);
     }
     }
   free (cmdline);
   free (cmdline);
   cmdline = NULL;
   cmdline = NULL;
 
 
-  DEBUG ("CreateProcess(detached) ready: hProcess=%p hThread=%p"
-	 " dwProcessID=%d dwThreadId=%d\n",
-	 pi.hProcess, pi.hThread,
+  DEBUG (DBG_INFO, "CreateProcess(detached) ready: hProcess=%p hThread=%p"
+	 " dwProcessID=%d dwThreadId=%d\n", pi.hProcess, pi.hThread,
 	 (int) pi.dwProcessId, (int) pi.dwThreadId);
 	 (int) pi.dwProcessId, (int) pi.dwThreadId);
 
 
   CloseHandle (pi.hThread); 
   CloseHandle (pi.hThread); 
@@ -255,8 +255,9 @@ agent_connect (assuan_context_t *ctx_r)
 	  const char *agent_program;
 	  const char *agent_program;
 
 
           /* With no success start a new server.  */
           /* With no success start a new server.  */
-	  DEBUG ("no running GPG agent at %s, starting one\n", sockname);
-          
+	  DEBUG (DBG_INFO, "no running GPG agent at %s, starting one\n",
+		 sockname);
+
           agent_program = get_gpg_agent_path ();
           agent_program = get_gpg_agent_path ();
 
 
 #ifdef HAVE_W32_SYSTEM
 #ifdef HAVE_W32_SYSTEM
@@ -275,7 +276,7 @@ agent_connect (assuan_context_t *ctx_r)
 
 
             err = spawn_process_detached (agent_program, argv);
             err = spawn_process_detached (agent_program, argv);
             if (err)
             if (err)
-              DEBUG ("failed to start agent `%s': %s\n",
+              DEBUG (DBG_CRIT, "failed to start agent `%s': %s\n",
 		     agent_program, gpg_strerror (err));
 		     agent_program, gpg_strerror (err));
             else
             else
               {
               {
@@ -324,7 +325,7 @@ agent_connect (assuan_context_t *ctx_r)
 
 
       if (!(ptr = strchr (infostr, PATHSEP_C)) || ptr == infostr)
       if (!(ptr = strchr (infostr, PATHSEP_C)) || ptr == infostr)
 	{
 	{
-	  DEBUG ("malformed GPG_AGENT_INFO environment variable");
+	  DEBUG (DBG_CRIT, "malformed GPG_AGENT_INFO environment variable");
 	  free (infostr);
 	  free (infostr);
 	  force_pipe_server = 1;
 	  force_pipe_server = 1;
 	  goto restart;
 	  goto restart;
@@ -337,7 +338,7 @@ agent_connect (assuan_context_t *ctx_r)
       protocol_version = *ptr ? atoi (ptr + 1) : 0;
       protocol_version = *ptr ? atoi (ptr + 1) : 0;
       if (protocol_version != 1)
       if (protocol_version != 1)
 	{
 	{
-	  DEBUG ("GPG agent protocol version '%d' not supported",
+	  DEBUG (DBG_CRIT, "GPG agent protocol version '%d' not supported",
 		 protocol_version);
 		 protocol_version);
 	  free (infostr);
 	  free (infostr);
 	  force_pipe_server = 1;
 	  force_pipe_server = 1;
@@ -348,7 +349,7 @@ agent_connect (assuan_context_t *ctx_r)
       free (infostr);
       free (infostr);
       if (err)
       if (err)
 	{
 	{
-	  DEBUG ("cannot connect to GPG agent: %s", gpg_strerror (err));
+	  DEBUG (DBG_CRIT, "cannot connect to GPG agent: %s", gpg_strerror (err));
 	  force_pipe_server = 1;
 	  force_pipe_server = 1;
 	  goto restart;
 	  goto restart;
 	}
 	}
@@ -356,10 +357,13 @@ agent_connect (assuan_context_t *ctx_r)
 
 
   if (err)
   if (err)
     {
     {
-      DEBUG ("cannot connect to GPG agent: %s", gpg_strerror (err));
+      DEBUG (DBG_CRIT, "cannot connect to GPG agent: %s", gpg_strerror (err));
       return gpg_error (GPG_ERR_NO_AGENT);
       return gpg_error (GPG_ERR_NO_AGENT);
     }
     }
 
 
+  if (_scute_debug_flags & DBG_ASSUAN)
+    assuan_set_log_stream (*ctx_r, _scute_debug_stream);
+
   return 0;
   return 0;
 }
 }
 
 
@@ -377,13 +381,12 @@ default_inq_cb (void *opaque, const char *line)
       /* We do not pass errors to avoid breaking other code.  */
       /* We do not pass errors to avoid breaking other code.  */
     }
     }
   else
   else
-    DEBUG ("ignoring gpg-agent inquiry `%s'\n", line);
+    DEBUG (DBG_CRIT, "ignoring gpg-agent inquiry `%s'\n", line);
 
 
   return 0;
   return 0;
 }
 }
 
 
 
 
-
 /* Send a simple command to the agent.  */
 /* Send a simple command to the agent.  */
 static gpg_error_t 
 static gpg_error_t 
 agent_simple_cmd (assuan_context_t ctx, const char *fmt, ...)
 agent_simple_cmd (assuan_context_t ctx, const char *fmt, ...)
@@ -403,7 +406,8 @@ agent_simple_cmd (assuan_context_t ctx, const char *fmt, ...)
   err = assuan_transact (ctx, optstr, NULL, NULL, default_inq_cb,
   err = assuan_transact (ctx, optstr, NULL, NULL, default_inq_cb,
 			 NULL, NULL, NULL);
 			 NULL, NULL, NULL);
   if (err)
   if (err)
-    DEBUG ("gpg-agent command '%s' failed: %s", optstr, gpg_strerror (err));
+    DEBUG (DBG_CRIT, "gpg-agent command '%s' failed: %s", optstr,
+	   gpg_strerror (err));
   free (optstr);
   free (optstr);
       
       
   return err;
   return err;
@@ -526,10 +530,11 @@ scute_agent_initialize (void)
 
 
   if (agent_ctx)
   if (agent_ctx)
     {
     {
-      DEBUG ("GPG Agent connection already established");
+      DEBUG (DBG_CRIT, "GPG Agent connection already established");
       return 0;
       return 0;
     }
     }
 
 
+  DEBUG (DBG_INFO, "Establishing connection to gpg-agent");
   err = agent_connect (&agent_ctx);
   err = agent_connect (&agent_ctx);
   if (err)
   if (err)
     return err;
     return err;
@@ -863,7 +868,10 @@ pksign_cb (void *opaque, const void *buffer, size_t length)
   struct signature *sig = opaque;
   struct signature *sig = opaque;
 
 
   if (sig->len + length > MAX_SIGNATURE_LEN)
   if (sig->len + length > MAX_SIGNATURE_LEN)
-    return gpg_error (GPG_ERR_BAD_DATA);
+    {
+      DEBUG (DBG_INFO, "maximum signature length exceeded");
+      return gpg_error (GPG_ERR_BAD_DATA);
+    }
 
 
   memcpy (&sig->data[sig->len], buffer, length);
   memcpy (&sig->data[sig->len], buffer, length);
   sig->len += length;
   sig->len += length;
@@ -1028,7 +1036,10 @@ scute_agent_get_cert (int no, struct cert *cert)
 			 NULL, NULL, NULL, NULL);
 			 NULL, NULL, NULL, NULL);
   /* Just to be safe... */
   /* Just to be safe... */
   if (!err && cert_s.cert_der_len <= 16)
   if (!err && cert_s.cert_der_len <= 16)
-    err = gpg_error (GPG_ERR_BAD_CERT);
+    {
+      DEBUG (DBG_INFO, "bad card certificate rejected");
+      err = gpg_error (GPG_ERR_BAD_CERT);
+    }
   if (err)
   if (err)
     {
     {
       if (cert_s.cert_der)
       if (cert_s.cert_der)
@@ -1036,6 +1047,9 @@ scute_agent_get_cert (int no, struct cert *cert)
       return err;
       return err;
     }
     }
 
 
+  DEBUG (DBG_INFO, "got certificate from card with length %i",
+	 cert_s.cert_der_len);
+
   cert->cert_der = cert_s.cert_der;
   cert->cert_der = cert_s.cert_der;
   cert->cert_der_len = cert_s.cert_der_len;
   cert->cert_der_len = cert_s.cert_der_len;
 
 
@@ -1048,10 +1062,11 @@ scute_agent_finalize (void)
 {
 {
   if (!agent_ctx)
   if (!agent_ctx)
     {
     {
-      DEBUG ("no GPG Agent connection established");
+      DEBUG (DBG_CRIT, "no GPG Agent connection established");
       return;
       return;
     }
     }
 
 
+  DEBUG (DBG_INFO, "releasing agent context");
   assuan_disconnect (agent_ctx);
   assuan_disconnect (agent_ctx);
   agent_ctx = NULL;
   agent_ctx = NULL;
 }
 }

+ 4 - 4
src/cert-gpgsm.c

@@ -564,7 +564,7 @@ export_cert_compat (char *fpr, struct cert *cert)
   if (err)
   if (err)
     {
     {
       close (output_fds[0]);
       close (output_fds[0]);
-      DEBUG ("failed to spawn %s\n", get_gpgsm_path ());
+      DEBUG (DBG_CRIT, "failed to spawn %s\n", get_gpgsm_path ());
       return err;
       return err;
     }
     }
 
 
@@ -653,7 +653,7 @@ export_cert (char *fpr, struct cert *cert)
 				 NULL, NULL, 128);
 				 NULL, NULL, 128);
   if (err)
   if (err)
     {
     {
-      DEBUG ("spawning %s\n", get_gpgsm_path ());
+      DEBUG (DBG_CRIT, "spawning %s\n", get_gpgsm_path ());
       return err;
       return err;
     }
     }
 
 
@@ -731,7 +731,7 @@ scute_gpgsm_search_certs_by_grip (const char *grip,
 				 NULL, NULL, 128);
 				 NULL, NULL, 128);
   if (err)
   if (err)
     {
     {
-      DEBUG ("spawning %s\n", get_gpgsm_path ());
+      DEBUG (DBG_CRIT, "spawning %s\n", get_gpgsm_path ());
       return err;
       return err;
     }
     }
 
 
@@ -762,7 +762,7 @@ scute_gpgsm_search_certs_by_fpr (const char *fpr,
 				 NULL, NULL, 128);
 				 NULL, NULL, 128);
   if (err)
   if (err)
     {
     {
-      DEBUG ("failed to spawn %s\n", get_gpgsm_path ());
+      DEBUG (DBG_CRIT, "failed to spawn %s\n", get_gpgsm_path ());
       return err;
       return err;
     }
     }
 
 

+ 111 - 28
src/cert-object.c

@@ -42,6 +42,7 @@
 #include "cryptoki.h"
 #include "cryptoki.h"
 #include "support.h"
 #include "support.h"
 #include "cert.h"
 #include "cert.h"
+#include "debug.h"
 
 
 
 
 /* Parsing certificates is problematic, as there is no reliable
 /* Parsing certificates is problematic, as there is no reliable
@@ -85,7 +86,11 @@ time_to_ck_date (time_t *atime, CK_DATE *ckdate)
   if (!(broken_time.tm_year >= 0 && broken_time.tm_year <= 8099
   if (!(broken_time.tm_year >= 0 && broken_time.tm_year <= 8099
 	&& broken_time.tm_mon >= 0 && broken_time.tm_mon <= 11
 	&& broken_time.tm_mon >= 0 && broken_time.tm_mon <= 11
 	&& broken_time.tm_mday >= 1 && broken_time.tm_mday <= 31))
 	&& broken_time.tm_mday >= 1 && broken_time.tm_mday <= 31))
-    return false;
+    { 
+      DEBUG (DBG_INFO, "unrepresentable time %i-%i-%i",
+	     broken_time.tm_year, broken_time.tm_mon, broken_time.tm_mday);
+      return false;
+    }
 
 
 #define LAST_DIGIT(d) (((d) % 10) + '0')
 #define LAST_DIGIT(d) (((d) % 10) + '0')
   nr = broken_time.tm_year + 1900;
   nr = broken_time.tm_year + 1900;
@@ -120,7 +125,10 @@ asn1_get_len (unsigned char **asn1, int *asn1_len, int *rlen)
   int result = 0;
   int result = 0;
 
 
   if (len < 1)
   if (len < 1)
-    return gpg_error (GPG_ERR_GENERAL);
+    {
+      DEBUG (DBG_INFO, "unexpected end of certificate");
+      return gpg_error (GPG_ERR_GENERAL);
+    }
 
 
   if (*ptr & 0x80)
   if (*ptr & 0x80)
     {
     {
@@ -132,8 +140,16 @@ asn1_get_len (unsigned char **asn1, int *asn1_len, int *rlen)
     cnt = 1;
     cnt = 1;
 
 
   /* We only support a limited number of length bytes.  */
   /* We only support a limited number of length bytes.  */
-  if (cnt > 2 || len < cnt)
-    return gpg_error (GPG_ERR_GENERAL);
+  if (cnt > 2)
+    {
+      DEBUG (DBG_INFO, "unsupported length field");
+      return gpg_error (GPG_ERR_GENERAL);
+    }
+  if (len < cnt)
+    {
+      DEBUG (DBG_INFO, "unexpected end of certificate");
+      return gpg_error (GPG_ERR_GENERAL);
+    }
 
 
   while (cnt--)
   while (cnt--)
     {
     {
@@ -175,8 +191,16 @@ asn1_get_element (unsigned char *cert, int cert_len,
   for (i = 0; i < path_size; i++)
   for (i = 0; i < path_size; i++)
     {
     {
       prev_certp = certp;
       prev_certp = certp;
-      if (cert_left < 1 || *certp != path[i].tag)
-	return gpg_error (GPG_ERR_GENERAL);
+      if (cert_left < 1)
+	{
+	  DEBUG (DBG_INFO, "unexpected end of certificate");
+	  return gpg_error (GPG_ERR_GENERAL);
+	}
+      if (*certp != path[i].tag)
+	{
+	  DEBUG (DBG_INFO, "wrong element in lookup path");
+	  return gpg_error (GPG_ERR_GENERAL);
+	}
       certp++;
       certp++;
       cert_left--;
       cert_left--;
       err = asn1_get_len (&certp, &cert_left, &len);
       err = asn1_get_len (&certp, &cert_left, &len);
@@ -185,7 +209,10 @@ asn1_get_element (unsigned char *cert, int cert_len,
       if (!path[i].enter)
       if (!path[i].enter)
 	{
 	{
 	  if (cert_left < len)
 	  if (cert_left < len)
-	    return gpg_error (GPG_ERR_GENERAL);
+	    {
+	      DEBUG (DBG_INFO, "unexpected end of certificate");
+	      return gpg_error (GPG_ERR_GENERAL);
+	    }
 	  certp += len;
 	  certp += len;
 	  cert_left -= len;
 	  cert_left -= len;
 	}
 	}
@@ -195,8 +222,16 @@ asn1_get_element (unsigned char *cert, int cert_len,
 	     bit string.  */
 	     bit string.  */
 	  if (path[i].tag == '\x03')
 	  if (path[i].tag == '\x03')
 	    {
 	    {
-	      if (cert_left < 1 || *certp != '\x00')
-		return gpg_error (GPG_ERR_GENERAL);
+	      if (cert_left < 1)
+		{
+		  DEBUG (DBG_INFO, "unexpected end of certificate");
+		  return gpg_error (GPG_ERR_GENERAL);
+		}
+	      if (*certp != '\x00')
+		{
+		  DEBUG (DBG_INFO, "expected binary encapsulation missing");
+		  return gpg_error (GPG_ERR_GENERAL);
+		}
 	      certp++;
 	      certp++;
 	      cert_left--;
 	      cert_left--;
 	    }
 	    }
@@ -280,7 +315,10 @@ asn1_get_modulus (unsigned char *cert, int cert_len,
     return err;
     return err;
 
 
   if (*sub_len < 1)
   if (*sub_len < 1)
-    return gpg_error (GPG_ERR_GENERAL);
+    {
+      DEBUG (DBG_INFO, "modulus too short");
+      return gpg_error (GPG_ERR_GENERAL);
+    }
 
 
   (*sub_start)++;
   (*sub_start)++;
   (*sub_len)--;
   (*sub_len)--;
@@ -322,7 +360,10 @@ asn1_get_public_exp (unsigned char *cert, int cert_len,
     return err;
     return err;
 
 
   if (*sub_len < 1)
   if (*sub_len < 1)
-    return gpg_error (GPG_ERR_GENERAL);
+    {
+      DEBUG (DBG_INFO, "public exponent too short");
+      return gpg_error (GPG_ERR_GENERAL);
+    }
 
 
   (*sub_start)++;
   (*sub_start)++;
   (*sub_len)--;
   (*sub_len)--;
@@ -351,7 +392,10 @@ attr_one (CK_ATTRIBUTE_PTR attr, CK_ULONG *attr_count,
   attr[i].ulValueLen = size;
   attr[i].ulValueLen = size;
   attr[i].pValue = malloc (size);
   attr[i].pValue = malloc (size);
   if (attr[i].pValue == NULL)
   if (attr[i].pValue == NULL)
-    return gpg_error (GPG_ERR_ENOMEM);
+    {
+      DEBUG (DBG_CRIT, "out of memory");
+      return gpg_error (GPG_ERR_ENOMEM);
+    }
   memcpy (attr[i].pValue, val, size);
   memcpy (attr[i].pValue, val, size);
   (*attr_count)++;
   (*attr_count)++;
   return 0;
   return 0;
@@ -413,16 +457,31 @@ scute_attr_cert (struct cert *cert,
   /* See below.  */
   /* See below.  */
   err = asn1_get_subject (cert->cert_der, cert->cert_der_len,
   err = asn1_get_subject (cert->cert_der, cert->cert_der_len,
 			  &subject_start, &subject_len);
 			  &subject_start, &subject_len);
+  if (err)
+    {
+      DEBUG (DBG_INFO, "rejecting certificate: could not get subject: %s",
+	     gpg_strerror (err));
+      return err;
+    }
 #endif
 #endif
 #if CERT_PARSING
 #if CERT_PARSING
-  if (!err)
-    err = asn1_get_issuer (cert->cert_der, cert->cert_der_len,
-			   &issuer_start, &issuer_len);
-  if (!err)
-    err = asn1_get_serial (cert->cert_der, cert->cert_der_len,
-			   &serial_start, &serial_len);
+  err = asn1_get_issuer (cert->cert_der, cert->cert_der_len,
+			 &issuer_start, &issuer_len);
   if (err)
   if (err)
-    return err;
+    {
+      DEBUG (DBG_INFO, "rejecting certificate: could not get issuer: %s",
+	     gpg_strerror (err));
+      return err;
+    }
+
+  err = asn1_get_serial (cert->cert_der, cert->cert_der_len,
+			 &serial_start, &serial_len);
+  if (err)
+    {
+      DEBUG (DBG_INFO, "rejecting certificate: could not get serial: %s",
+	     gpg_strerror (err));
+      return err;
+    }
 #endif
 #endif
 
 
 
 
@@ -430,7 +489,10 @@ scute_attr_cert (struct cert *cert,
   attr = malloc (sizeof (CK_ATTRIBUTE) * NR_ATTR_CERT);
   attr = malloc (sizeof (CK_ATTRIBUTE) * NR_ATTR_CERT);
   attr_count = 0;
   attr_count = 0;
   if (!attr)
   if (!attr)
-    return gpg_error (GPG_ERR_ENOMEM);
+    {
+      DEBUG (DBG_INFO, "out of memory");
+      return gpg_error (GPG_ERR_ENOMEM);
+    }
 
 
 #define one_attr_ext(type, val, size)					\
 #define one_attr_ext(type, val, size)					\
   if (!err)								\
   if (!err)								\
@@ -506,6 +568,8 @@ scute_attr_cert (struct cert *cert,
 
 
   if (err)
   if (err)
     {
     {
+      DEBUG (DBG_INFO, "could not build certificate object: %s",
+	     gpg_strerror (err));
       scute_attr_free (attr, attr_count);
       scute_attr_free (attr, attr_count);
       return err;
       return err;
     }
     }
@@ -563,21 +627,38 @@ scute_attr_prv (struct cert *cert, CK_ATTRIBUTE_PTR *attrp,
 #if CERT_PARSING
 #if CERT_PARSING
   err = asn1_get_subject (cert->cert_der, cert->cert_der_len,
   err = asn1_get_subject (cert->cert_der, cert->cert_der_len,
 			  &subject_start, &subject_len);
 			  &subject_start, &subject_len);
-  if (!err)
-    err = asn1_get_modulus (cert->cert_der, cert->cert_der_len,
-			    &modulus_start, &modulus_len);
-  if (!err)
-    err = asn1_get_public_exp (cert->cert_der, cert->cert_der_len,
-			       &public_exp_start, &public_exp_len);
   if (err)
   if (err)
-    return err;
+    {
+      DEBUG (DBG_INFO, "rejecting certificate: could not get subject: %s",
+	     gpg_strerror (err));
+      return err;
+    }
+  err = asn1_get_modulus (cert->cert_der, cert->cert_der_len,
+			  &modulus_start, &modulus_len);
+  if (err)
+    {
+      DEBUG (DBG_INFO, "rejecting certificate: could not get modulus: %s",
+	     gpg_strerror (err));
+      return err;
+    }
+  err = asn1_get_public_exp (cert->cert_der, cert->cert_der_len,
+			     &public_exp_start, &public_exp_len);
+  if (err)
+    {
+      DEBUG (DBG_INFO, "rejecting certificate: could not get public exp: %s",
+	     gpg_strerror (err));
+      return err;
+    }
 #endif
 #endif
 
 
 #define NR_ATTR_PRV 27
 #define NR_ATTR_PRV 27
   attr = malloc (sizeof (CK_ATTRIBUTE) * NR_ATTR_PRV);
   attr = malloc (sizeof (CK_ATTRIBUTE) * NR_ATTR_PRV);
   attr_count = 0;
   attr_count = 0;
   if (!attr)
   if (!attr)
-    return gpg_error (GPG_ERR_ENOMEM);
+    {
+      DEBUG (DBG_INFO, "out of core");
+      return gpg_error (GPG_ERR_ENOMEM);
+    }
 
 
 #undef one_attr_ext
 #undef one_attr_ext
 #define one_attr_ext(type, val, size)					\
 #define one_attr_ext(type, val, size)					\
@@ -659,6 +740,8 @@ scute_attr_prv (struct cert *cert, CK_ATTRIBUTE_PTR *attrp,
 
 
   if (err)
   if (err)
     {
     {
+      DEBUG (DBG_INFO, "could not build private certificate object: %s",
+	     gpg_strerror (err));
       scute_attr_free (attr, attr_count);
       scute_attr_free (attr, attr_count);
       return err;
       return err;
     }
     }

+ 143 - 0
src/debug.c

@@ -0,0 +1,143 @@
+/* debug.c - Cryptoki implementation.
+   Copyright (C) 2008 g10 Code GmbH
+
+   This file is part of Scute.
+ 
+   Scute is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   Scute is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with Scute; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+   In addition, as a special exception, g10 Code GmbH gives permission
+   to link this library: with the Mozilla Foundation's code for
+   Mozilla (or with modified versions of it that use the same license
+   as the "Mozilla" code), and distribute the linked executables.  You
+   must obey the GNU General Public License in all respects for all of
+   the code used other than "Mozilla".  If you modify this file, you
+   may extend this exception to your version of the file, but you are
+   not obligated to do so.  If you do not wish to do so, delete this
+   exception statement from your version.  */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <assuan.h>
+#include <gpg-error.h>
+#include <string.h>
+
+#include "debug.h"
+
+
+FILE *_scute_debug_stream;
+
+unsigned int _scute_debug_flags;
+
+
+#ifdef HAVE_W32_SYSTEM
+#define PATHSEP_C ';'
+#else
+#define PATHSEP_C ':'
+#endif
+
+
+/* Remove leading and trailing white spaces.  */
+static char *
+trim_spaces (char *str)
+{
+  char *string, *p, *mark;
+
+  string = str;
+  /* Find first non space character.  */
+  for (p = string; *p && isspace (*(unsigned char *) p); p++)
+    ;
+  /* Move characters.  */
+  for (mark = NULL; (*string = *p); string++, p++)
+    if (isspace (*(unsigned char *) p))
+      {
+	if (!mark)
+	  mark = string;
+      }
+    else
+      mark = NULL;
+  if (mark)
+    *mark = '\0';	/* Remove trailing spaces.  */
+
+  return str;
+}
+
+#include <errno.h>
+
+void
+_scute_debug_init (void)
+{
+  static int initialized;
+
+  if (!initialized)
+    {
+      char *e;
+      const char *s1, *s2;;
+      FILE *stream;
+
+      e = getenv ("SCUTE_DEBUG");
+
+      initialized = 1;
+     
+      stream = stderr;
+      if (e)
+	{
+	  _scute_debug_flags = atoi (e);
+	  s1 = strchr (e, PATHSEP_C);
+	  if (s1)
+	    {
+#ifndef HAVE_W32_SYSTEM
+	      if (getuid () == geteuid ())
+		{
+#endif
+		  char *p;
+		  FILE *fp;
+
+		  s1++;
+		  if (!(s2 = strchr (s1, PATHSEP_C)))
+		    s2 = s1 + strlen (s1);
+		  p = malloc (s2 - s1 + 1);
+		  if (p)
+		    {
+		      memcpy (p, s1, s2 - s1);
+		      p[s2-s1] = 0;
+		      trim_spaces (p);
+		      fp = fopen (p,"a");
+		      if (fp)
+			{
+			  setvbuf (fp, NULL, _IOLBF, 0);
+			  stream = fp;
+			}
+		      free (p);
+		    }
+#ifndef HAVE_W32_SYSTEM
+		}
+#endif
+	    }
+        }
+
+      if (_scute_debug_flags > 0)
+        fprintf (stream, "scute debug init: flags=0x%x\n", _scute_debug_flags);
+
+      assuan_set_assuan_log_prefix ("scute-assuan");
+      _scute_debug_stream = stream;
+      if (_scute_debug_flags & DBG_ASSUAN)
+	assuan_set_assuan_log_stream (stream);
+    }
+}

+ 19 - 5
src/debug.h

@@ -1,5 +1,5 @@
 /* debug.c - Debug interface.
 /* debug.c - Debug interface.
-   Copyright (C) 2006 g10 Code GmbH
+   Copyright (C) 2006, 2008 g10 Code GmbH
 
 
    This file is part of Scute.
    This file is part of Scute.
  
  
@@ -34,9 +34,23 @@
 
 
 #define DEBUG_PREFIX "scute: "
 #define DEBUG_PREFIX "scute: "
 
 
-/* FIXME: Eventually, we should control output with an environment
-   variable.  */
-#define DEBUG(format, ...) \
-  fprintf (stderr, DEBUG_PREFIX "%s: " format "\n", __func__, ##__VA_ARGS__)
+#define DBG_CRIT 0
+#define DBG_INFO (1 << 0)
+#define DBG_ASSUAN (1 << 1)
+
+extern FILE *_scute_debug_stream;
+extern unsigned int _scute_debug_flags;
+
+#define DEBUG(flag, format, ...)  \
+  do \
+    { \
+      if (_scute_debug_flags & (flag)) \
+        fprintf (_scute_debug_stream, \
+                 DEBUG_PREFIX "%s: " format "\n", __func__, ##__VA_ARGS__); \
+    } \
+  while (0)
+
+void _scute_debug_init (void);
+
 
 
 #endif /* !DEBUG_H */
 #endif /* !DEBUG_H */

+ 1 - 1
src/error-mapping.c

@@ -65,7 +65,7 @@ CK_RV
 scute_gpg_err_to_ck (gpg_error_t err)
 scute_gpg_err_to_ck (gpg_error_t err)
 {
 {
   if (err)
   if (err)
-    DEBUG ("Error occured: %s (%s)\n", gpg_strerror (err),
+    DEBUG (DBG_CRIT, "Error occured: %s (%s)\n", gpg_strerror (err),
 	   gpg_strsource (err));
 	   gpg_strsource (err));
 
 
   switch (gpg_err_code (err))
   switch (gpg_err_code (err))

+ 4 - 1
src/p11-initialize.c

@@ -43,8 +43,9 @@
 #include "agent.h"
 #include "agent.h"
 #include "error-mapping.h"
 #include "error-mapping.h"
 #include "slots.h"
 #include "slots.h"
+#include "debug.h"
+
 
 
-
 CK_DEFINE_FUNCTION(CK_RV, C_Initialize) (CK_VOID_PTR pInitArgs)
 CK_DEFINE_FUNCTION(CK_RV, C_Initialize) (CK_VOID_PTR pInitArgs)
 {
 {
   CK_RV err;
   CK_RV err;
@@ -56,6 +57,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_Initialize) (CK_VOID_PTR pInitArgs)
      substitute for assuan_error_t.  */
      substitute for assuan_error_t.  */
   assuan_set_assuan_err_source (GPG_ERR_SOURCE_ANY);
   assuan_set_assuan_err_source (GPG_ERR_SOURCE_ANY);
 
 
+  _scute_debug_init ();
+
   /* Check the threading configuration.  */
   /* Check the threading configuration.  */
   if (pInitArgs != NULL_PTR)
   if (pInitArgs != NULL_PTR)
     {
     {

+ 1 - 1
src/slots.c

@@ -423,7 +423,7 @@ slots_update_slot (slot_iterator_t id)
 	       || strncmp (slot->info.serialno, "D27600012401", 12)
 	       || strncmp (slot->info.serialno, "D27600012401", 12)
 	       || strlen (slot->info.serialno) != 32))
 	       || strlen (slot->info.serialno) != 32))
     {
     {
-      DEBUG ("token not an OpenPGP card: %s", slot->info.serialno);
+      DEBUG (DBG_INFO, "token not an OpenPGP card: %s", slot->info.serialno);
       err = gpg_error (GPG_ERR_CARD_NOT_PRESENT);
       err = gpg_error (GPG_ERR_CARD_NOT_PRESENT);
       scute_agent_release_card_info (&slot->info);
       scute_agent_release_card_info (&slot->info);
     }
     }