.
authorWerner Koch <wk@gnupg.org>
Wed, 20 Apr 2005 19:19:24 +0000 (19:19 +0000)
committerWerner Koch <wk@gnupg.org>
Wed, 20 Apr 2005 19:19:24 +0000 (19:19 +0000)
agent/ChangeLog
agent/agent.h
agent/call-scd.c
agent/gpg-agent.c
agent/minip12.c

index e30b2cb..5f26fc6 100644 (file)
@@ -3,6 +3,18 @@
        * command-ssh.c (ssh_handler_request_identities): Removed
        debugging code (sleep call), which was commited unintenionally.
 
+2005-04-20  Werner Koch  <wk@g10code.com>
+
+       * minip12.c (parse_bag_encrypted_data): Fix the unpadding hack.
+
+       * gpg-agent.c: New option --disable-scdaemon.
+       (handle_connections): Add time event to drive ...
+       (handle_tick): New function.
+       (main): Record the parent PID. Fixed segv when using ssh and a
+       command.
+
+       * call-scd.c (start_scd): Take care of this option.
+
 2005-04-03  Moritz Schulte  <moritz@g10code.com>
 
        * command-ssh.c (ssh_request_spec): New member: secret_input.
index e12a02b..298b5b1 100644 (file)
@@ -66,6 +66,7 @@ struct {
                                    pinentry.  */
   const char *scdaemon_program; /* Filename of the program to handle
                                    smartcard tasks.  */
+  int disable_scdaemon;         /* Never use the SCdaemon. */
   int no_grab;         /* Don't let the pinentry grab the keyboard */
   unsigned long def_cache_ttl;
   unsigned long max_cache_ttl;
index 4d1498b..8373fd4 100644 (file)
@@ -137,6 +137,9 @@ start_scd (ctrl_t ctrl)
   int no_close_list[3];
   int i;
 
+  if (opt.disable_scdaemon)
+    return gpg_error (GPG_ERR_NOT_SUPPORTED);
+
 #ifdef USE_GNU_PTH
   if (!pth_mutex_acquire (&scd_lock, 0, NULL))
     {
index 1134893..7c682ad 100644 (file)
@@ -94,7 +94,8 @@ enum cmd_and_opt_values
   oAllowPresetPassphrase,
   oKeepTTY,
   oKeepDISPLAY,
-  oSSHSupport
+  oSSHSupport,
+  oDisableScdaemon
 };
 
 
@@ -128,6 +129,7 @@ static ARGPARSE_OPTS opts[] = {
                                N_("|PGM|use PGM as the PIN-Entry program") },
   { oScdaemonProgram, "scdaemon-program", 2 ,
                                N_("|PGM|use PGM as the SCdaemon program") },
+  { oDisableScdaemon, "disable-scdaemon", 0, N_("do not use the SCdaemon") },
 
   { oDisplay,    "display",     2, "@" },
   { oTTYname,    "ttyname",     2, "@" },
@@ -187,6 +189,11 @@ static const char *debug_level;
    the log file after a SIGHUP if it didn't changed. Malloced. */
 static char *current_logfile;
 
+/* The handle_tick() function may test whether a parent is still
+   runing.  We record the PID of the parent here or -1 if it should be
+   watched. */
+static pid_t parent_pid = (pid_t)(-1);
+
 /*
    Local prototypes. 
  */
@@ -387,6 +394,7 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread)
       opt.max_cache_ttl = MAX_CACHE_TTL;
       opt.ignore_cache_for_signing = 0;
       opt.allow_mark_trusted = 0;
+      opt.disable_scdaemon = 0;
       return 1;
     }
 
@@ -415,6 +423,7 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread)
       
     case oPinentryProgram: opt.pinentry_program = pargs->r.ret_str; break;
     case oScdaemonProgram: opt.scdaemon_program = pargs->r.ret_str; break;
+    case oDisableScdaemon: opt.disable_scdaemon = 1; break;
 
     case oDefCacheTTL: opt.def_cache_ttl = pargs->r.ret_ulong; break;
     case oMaxCacheTTL: opt.max_cache_ttl = pargs->r.ret_ulong; break;
@@ -740,6 +749,8 @@ main (int argc, char **argv )
               GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME);
       printf ("allow-mark-trusted:%lu:\n",
               GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME);
+      printf ("disable-scdaemon:%lu:\n",
+              GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME);
 
       agent_exit (0);
     }
@@ -819,6 +830,11 @@ main (int argc, char **argv )
       else
        fd_ssh = -1;
 
+      /* If we are going to exec a program in the parent, we record
+         the PID, so that the child may check whether the program is
+         still alive. */
+      if (argc)
+        parent_pid = getpid ();
 
       fflush (NULL);
 #ifdef HAVE_W32_SYSTEM
@@ -878,14 +894,14 @@ main (int argc, char **argv )
                   kill (pid, SIGTERM );
                   exit (1);
                 }
-              if (putenv (infostr_ssh_sock))
+              if (opt.ssh_support && putenv (infostr_ssh_sock))
                 {
                   log_error ("failed to set environment: %s\n",
                              strerror (errno) );
                   kill (pid, SIGTERM );
                   exit (1);
                 }
-              if (putenv (infostr_ssh_pid))
+              if (opt.ssh_support && putenv (infostr_ssh_pid))
                 {
                   log_error ("failed to set environment: %s\n",
                              strerror (errno) );
@@ -922,8 +938,7 @@ main (int argc, char **argv )
                      printf ("%s; export SSH_AGENT_PID;\n", infostr_ssh_pid);
                    }
                 }
-              /* Note: teh standard free is here correct.  */
-              free (infostr);
+              free (infostr); /* (Note that a vanilla free is here correct.) */
              if (opt.ssh_support)
                {
                  free (infostr_ssh_sock);
@@ -1311,6 +1326,27 @@ create_directories (void)
 
 
 #ifdef USE_GNU_PTH
+/* This is the worker for the ticker.  It is called every few seconds
+   and may only do fast operations. */
+static void
+handle_tick (void)
+{
+#ifndef HAVE_W32_SYSTEM
+  if (parent_pid != (pid_t)(-1))
+    {
+      if (kill (parent_pid, 0))
+        {
+          shutdown_pending = 2;
+          log_info ("parent process died - shutting down\n");
+          log_info ("%s %s stopped\n", strusage(11), strusage(13) );
+          cleanup ();
+          agent_exit (0);
+        }
+    }
+#endif /*HAVE_W32_SYSTEM*/
+}
+
+
 static void
 handle_signal (int signo)
 {
@@ -1409,7 +1445,7 @@ static void
 handle_connections (int listen_fd, int listen_fd_ssh)
 {
   pth_attr_t tattr;
-  pth_event_t ev;
+  pth_event_t ev, time_ev;
   sigset_t sigs;
   int signo;
   struct sockaddr_un paddr;
@@ -1434,6 +1470,7 @@ handle_connections (int listen_fd, int listen_fd_ssh)
 #else
   ev = NULL;
 #endif
+  time_ev = NULL;
 
   FD_ZERO (&fdset);
   FD_SET (listen_fd, &fdset);
@@ -1456,16 +1493,33 @@ handle_connections (int listen_fd, int listen_fd_ssh)
           continue;
        }
 
+      /* Create a timeout event if needed. */
+      if (!time_ev)
+        time_ev = pth_event (PTH_EVENT_TIME, pth_timeout (2, 0));
+
       /* POSIX says that fd_set should be implemented as a structure,
          thus a simple assignment is fine to copy the entire set.  */
       read_fdset = fdset;
 
+      if (time_ev)
+        pth_event_concat (ev, time_ev, NULL);
       ret = pth_select_ev (FD_SETSIZE, &read_fdset, NULL, NULL, NULL, ev);
+      if (time_ev)
+        pth_event_isolate (time_ev);
+
       if (ret == -1)
        {
-          if (pth_event_occurred (ev))
+          if (pth_event_occurred (ev)
+              || (time_ev && pth_event_occurred (time_ev)))
             {
-              handle_signal (signo);
+              if (pth_event_occurred (ev))
+                handle_signal (signo);
+              if (time_ev && pth_event_occurred (time_ev))
+                {
+                  pth_event_free (time_ev, PTH_FREE_ALL);
+                  time_ev = NULL;
+                  handle_tick ();
+                }
               continue;
             }
           log_error (_("pth_select failed: %s - waiting 1s\n"),
@@ -1479,6 +1533,13 @@ handle_connections (int listen_fd, int listen_fd_ssh)
           handle_signal (signo);
         }
 
+      if (time_ev && pth_event_occurred (time_ev))
+        {
+          pth_event_free (time_ev, PTH_FREE_ALL);
+          time_ev = NULL;
+          handle_tick ();
+        }
+
       if (FD_ISSET (listen_fd, &read_fdset))
        {
           plen = sizeof paddr;
@@ -1515,6 +1576,8 @@ handle_connections (int listen_fd, int listen_fd_ssh)
     }
 
   pth_event_free (ev, PTH_FREE_ALL);
+  if (time_ev)
+    pth_event_free (time_ev, PTH_FREE_ALL);
   cleanup ();
   log_info (_("%s %s stopped\n"), strusage(11), strusage(13));
 }
index fc9b26d..5ca8503 100644 (file)
@@ -486,6 +486,7 @@ parse_bag_encrypted_data (const unsigned char *buffer, size_t length,
   buffer = p = plain;
 
 /*   { */
+/* #  warning debug code is enabled */
 /*     FILE *fp = fopen ("tmp-rc2-plain.der", "wb"); */
 /*     if (!fp || fwrite (p, n, 1, fp) != 1) */
 /*       exit (2); */
@@ -586,8 +587,10 @@ parse_bag_encrypted_data (const unsigned char *buffer, size_t length,
         }
 
       /* Ugly hack to cope with the padding: Forget about the rest if
-         that it is less than the cipher's block length. */
-      if (n < 8)
+         that is less or equal to the cipher's block length.  We can
+         reasonable assume that all valid data will be longer than
+         just one block. */
+      if (n <= 8)
         n = 0;  
 
       /* Skip the optional SET with the pkcs12 cert attributes. */
@@ -602,7 +605,7 @@ parse_bag_encrypted_data (const unsigned char *buffer, size_t length,
             { /* The optional SET. */
               p += ti.length;
               n -= ti.length;
-              if (n < 8)
+              if (n <= 8)
                 n = 0;
               if (n && parse_tag (&p, &n, &ti))
                 goto bailout;