Init cache encryption on the fly.
authorWerner Koch <wk@gnupg.org>
Mon, 29 Nov 2010 06:49:44 +0000 (06:49 +0000)
committerWerner Koch <wk@gnupg.org>
Mon, 29 Nov 2010 06:49:44 +0000 (06:49 +0000)
add some debug code

agent/ChangeLog
agent/cache.c
agent/gpg-agent.c

index 3a0464e..eb80654 100644 (file)
@@ -1,6 +1,13 @@
+2010-11-29  Werner Koch  <wk@g10code.com>
+
+       * cache.c (initialize_module_cache): Factor code out to ...
+       (init_encryption): new.
+       (new_data, agent_get_cache): Init encryption on on the fly.
+
 2010-11-26  Werner Koch  <wk@g10code.com>
 
        * gpg-agent.c (CHECK_OWN_SOCKET_INTERVAL): New.
+       (handle_tick) [W32CE]: Don't check own socket.
 
 2010-11-23  Werner Koch  <wk@g10code.com>
 
index f19e97d..67c834b 100644 (file)
@@ -71,15 +71,42 @@ static ITEM thecache;
 void
 initialize_module_cache (void)
 {
-  static int initialized;
+  if (!pth_mutex_init (&encryption_lock))
+    {
+      gpg_error_t err = gpg_error_from_syserror ();
+      log_fatal ("error initializing cache module: %s\n", gpg_strerror (err));
+    }
+}
+
+
+void
+deinitialize_module_cache (void)
+{
+  gcry_cipher_close (encryption_handle);
+  encryption_handle = NULL;
+}
+
+
+/* We do the encryption init on the fly.  We can't do it in the module
+   init code because that is run before we listen for connections and
+   in case we are started on demand by gpg etc. it will only wait for
+   a few seconds to decide whether the agent may now accept
+   connections.  Thus we should get into listen state as soon as
+   possible.  */
+static gpg_error_t
+init_encryption (void)
+{
   gpg_error_t err;
   void *key;
 
-  if (!pth_mutex_init (&encryption_lock))
-    err = gpg_error_from_syserror ();
-  else
-    err = gcry_cipher_open (&encryption_handle, GCRY_CIPHER_AES128,
-                            GCRY_CIPHER_MODE_AESWRAP, GCRY_CIPHER_SECURE);
+  if (encryption_handle)
+    return 0; /* Shortcut - Already initialized.  */
+
+  if (!pth_mutex_acquire (&encryption_lock, 0, NULL))
+    log_fatal ("failed to acquire cache encryption mutex\n");
+
+  err = gcry_cipher_open (&encryption_handle, GCRY_CIPHER_AES128,
+                          GCRY_CIPHER_MODE_AESWRAP, GCRY_CIPHER_SECURE);
   if (!err)
     {
       key = gcry_random_bytes (ENCRYPTION_KEYSIZE, GCRY_STRONG_RANDOM);
@@ -90,22 +117,24 @@ initialize_module_cache (void)
           err = gcry_cipher_setkey (encryption_handle, key, ENCRYPTION_KEYSIZE);
           xfree (key);
         }
+      if (err)
+        {
+          gcry_cipher_close (encryption_handle);
+          encryption_handle = NULL;
+        }
     }
   if (err)
-    log_fatal ("error initializing cache encryption context: %s\n",
-             gpg_strerror (err));
-  initialized = 1;
-}
-
+    log_error ("error initializing cache encryption context: %s\n",
+               gpg_strerror (err));
+  
+  if (!pth_mutex_release (&encryption_lock))
+    log_fatal ("failed to release cache encryption mutex\n");
 
-void
-deinitialize_module_cache (void)
-{
-  gcry_cipher_close (encryption_handle);
-  encryption_handle = NULL;
+  return err? gpg_error (GPG_ERR_NOT_INITIALIZED) : 0;
 }
 
 
+
 static void
 release_data (struct secret_data_s *data)
 {
@@ -122,8 +151,9 @@ new_data (const char *string, struct secret_data_s **r_data)
   
   *r_data = NULL;
 
-  if (!encryption_handle)
-    return gpg_error (GPG_ERR_NOT_INITIALIZED);
+  err = init_encryption ();
+  if (err)
+    return err;
 
   length = strlen (string) + 1;
 
@@ -369,8 +399,8 @@ agent_get_cache (const char *key, cache_mode_t cache_mode)
             log_debug ("... hit\n");
           if (r->pw->totallen < 32)
             err = gpg_error (GPG_ERR_INV_LENGTH);
-          else if (!encryption_handle)
-            err = gpg_error (GPG_ERR_NOT_INITIALIZED);
+          else if ((err = init_encryption ()))
+            ;
           else if (!(value = xtrymalloc_secure (r->pw->totallen - 8)))
             err = gpg_error_from_syserror ();
           else
index 4d7cbde..b897a9b 100644 (file)
@@ -203,10 +203,9 @@ static ARGPARSE_OPTS opts[] = {
 #endif
 
 /* How often shall we check our own socket in standard socket mode.
-   For WindowsCE be use a longer interval because we don't expect any
-   problems and resources are anyway scare.  */
+   If that value is 0 we don't check at all.  */
 #ifdef HAVE_W32_SYSTEM
-# define CHECK_OWN_SOCKET_INTERVAL  (300)
+# define CHECK_OWN_SOCKET_INTERVAL  (0)
 #else
 # define CHECK_OWN_SOCKET_INTERVAL  (60)  /* Seconds.  */
 #endif
@@ -1691,11 +1690,13 @@ handle_tick (void)
 #endif /*HAVE_W32_SYSTEM*/
   
   /* Code to be run from time to time.  */
+#if CHECK_OWN_SOCKET_INTERVAL > 0
   if (last_minute + CHECK_OWN_SOCKET_INTERVAL <= time (NULL))
     {
       check_own_socket ();
       last_minute = time (NULL);
     }
+#endif
 
 }
 
@@ -1799,8 +1800,13 @@ start_connection_thread (void *arg)
 {
   ctrl_t ctrl = arg;
 
+  if (opt.verbose)
+    log_debug ("handler 0x%lx checking nonce\n", pth_thread_id ());
   if (check_nonce (ctrl, &socket_nonce))
-    return NULL;
+    {
+      log_debug ("handler 0x%lx nonce check FAILED\n", pth_thread_id ());
+      return NULL;
+    }
 
   agent_init_default_ctrl (ctrl);
   if (opt.verbose)
@@ -1918,6 +1924,7 @@ handle_connections (gnupg_fd_t listen_fd, gnupg_fd_t listen_fd_ssh)
 
   for (;;)
     {
+      log_debug ("%s: Begin main loop\n", __func__);
       /* Make sure that our signals are not blocked.  */
       pth_sigmask (SIG_UNBLOCK, &sigs, NULL);
 
@@ -1927,6 +1934,7 @@ handle_connections (gnupg_fd_t listen_fd, gnupg_fd_t listen_fd_ssh)
           if (pth_ctrl (PTH_CTRL_GETTHREADS) == 1)
             break; /* ready */
 
+          log_debug ("%s: shutdown pending\n", __func__);
           /* Do not accept new connections but keep on running the
              loop to cope with the timer events.  */
           FD_ZERO (&fdset);
@@ -1945,6 +1953,7 @@ handle_connections (gnupg_fd_t listen_fd, gnupg_fd_t listen_fd_ssh)
               nexttick.tv_usec = 0;
             }
           time_ev = pth_event (PTH_EVENT_TIME, nexttick);
+          log_debug ("%s: time event created\n", __func__);
         }
 
       /* POSIX says that fd_set should be implemented as a structure,
@@ -1953,7 +1962,10 @@ handle_connections (gnupg_fd_t listen_fd, gnupg_fd_t listen_fd_ssh)
 
       if (time_ev)
         pth_event_concat (ev, time_ev, NULL);
+
+      log_debug ("%s: Pre-select\n", __func__);
       ret = pth_select_ev (nfd+1, &read_fdset, NULL, NULL, NULL, ev);
+      log_debug ("%s: Post-select res=%d\n", __func__, ret);
       if (time_ev)
         pth_event_isolate (time_ev);
 
@@ -1984,8 +1996,10 @@ handle_connections (gnupg_fd_t listen_fd, gnupg_fd_t listen_fd_ssh)
           continue;
        }
 
+      log_debug ("%s: Checking events\n", __func__);
       if (pth_event_occurred (ev))
         {
+          log_debug ("%s: Got event\n", __func__);
 #if defined(HAVE_W32_SYSTEM) && defined(PTH_EVENT_HANDLE)
           agent_sigusr2_action ();
 #else
@@ -1995,12 +2009,14 @@ handle_connections (gnupg_fd_t listen_fd, gnupg_fd_t listen_fd_ssh)
 
       if (time_ev && pth_event_occurred (time_ev))
         {
+          log_debug ("%s: Got tick event\n", __func__);
           pth_event_free (time_ev, PTH_FREE_ALL);
           time_ev = NULL;
           handle_tick ();
         }
 
 
+      log_debug ("%s: Restore mask\n", __func__);
       /* We now might create new threads and because we don't want any
          signals (as we are handling them here) to be delivered to a
          new thread.  Thus we need to block those signals. */
@@ -2010,9 +2026,11 @@ handle_connections (gnupg_fd_t listen_fd, gnupg_fd_t listen_fd_ssh)
        {
           ctrl_t ctrl;
 
+          log_debug ("%s: Pre-accept\n", __func__);
           plen = sizeof paddr;
          fd = INT2FD (pth_accept (FD2INT(listen_fd),
                                    (struct sockaddr *)&paddr, &plen));
+          log_debug ("%s: Post-accept fd=%d\n", __func__, fd);
          if (fd == GNUPG_INVALID_FD)
            {
              log_error ("accept failed: %s\n", strerror (errno));
@@ -2034,6 +2052,7 @@ handle_connections (gnupg_fd_t listen_fd, gnupg_fd_t listen_fd_ssh)
             {
               char threadname[50];
 
+              log_debug ("%s: Spawning handler\n", __func__);
               snprintf (threadname, sizeof threadname-1,
                         "conn fd=%d (gpg)", FD2INT(fd));
               threadname[sizeof threadname -1] = 0;
@@ -2046,6 +2065,7 @@ handle_connections (gnupg_fd_t listen_fd, gnupg_fd_t listen_fd_ssh)
                   assuan_sock_close (fd);
                   xfree (ctrl);
                 }
+              log_debug ("%s: handler spawned\n", __func__);
             }
           fd = GNUPG_INVALID_FD;
        }
@@ -2055,6 +2075,7 @@ handle_connections (gnupg_fd_t listen_fd, gnupg_fd_t listen_fd_ssh)
        {
           ctrl_t ctrl;
 
+          log_debug ("%s: SSH STUFF!\n", __func__);
           plen = sizeof paddr;
          fd = INT2FD(pth_accept (FD2INT(listen_fd_ssh),
                                   (struct sockaddr *)&paddr, &plen));
@@ -2095,8 +2116,10 @@ handle_connections (gnupg_fd_t listen_fd, gnupg_fd_t listen_fd_ssh)
             }
           fd = GNUPG_INVALID_FD;
        }
+      log_debug ("%s: End main loop\n", __func__);
     }
 
+  log_debug ("%s: main loop terminated\n", __func__);
   pth_event_free (ev, PTH_FREE_ALL);
   if (time_ev)
     pth_event_free (time_ev, PTH_FREE_ALL);