Browse Source

2008-08-23 Marcus Brinkmann <marcus@g10code.com>

	* src/Makefile.am [HAVE_W32_SYSTEM]: Build autonomous DLL.
	* src/dllmain.c (DllMain): New file.
	* src/cert-gpgsm.c: Include "debug.h".  Use
	 assuan_pipe_connect_ext instead of assuan_pipe_connect everywhere.
	* src/agent.c (WINVER) [HAVE_W32_SYSTEM]: Define symbol.
	[HAVE_W32_SYSTEM]: Include <windows.h>.  Do this before including
	<assuan.h>.
	(gnupg_allow_set_foregound_window): New function.
	(agent_connect): Use Sleep() instead of _sleep().
	(default_inq_cb): New function, and use it in all transactions.
	(agent_configure): Don't bail out if ttytname is not defined.  Set
	allow-pinentry-notify.
	* tests/t-support.h [_WIN32]: Include <windows.h>.
	(init_cryptoki) [_WIN32]: Call WSAStartup.
Marcus Brinkmann 17 years ago
parent
commit
34897e607b
5 changed files with 169 additions and 29 deletions
  1. 21 0
      ChangeLog
  2. 68 22
      src/agent.c
  3. 22 7
      src/cert-gpgsm.c
  4. 49 0
      src/dllmain.c
  5. 9 0
      tests/t-support.h

+ 21 - 0
ChangeLog

@@ -1,3 +1,24 @@
+2008-08-23  Marcus Brinkmann  <marcus@g10code.com>
+
+	* src/Makefile.am [HAVE_W32_SYSTEM]: Build autonomous DLL.
+	* src/dllmain.c (DllMain): New file.
+	* src/cert-gpgsm.c: Include "debug.h".  Use
+	 assuan_pipe_connect_ext instead of assuan_pipe_connect everywhere.
+	* src/agent.c (WINVER) [HAVE_W32_SYSTEM]: Define symbol.
+	[HAVE_W32_SYSTEM]: Include <windows.h>.  Do this before including
+	<assuan.h>.
+	(gnupg_allow_set_foregound_window): New function.
+	(agent_connect): Use Sleep() instead of _sleep().
+	(default_inq_cb): New function, and use it in all transactions.
+	(agent_configure): Don't bail out if ttytname is not defined.  Set
+	allow-pinentry-notify.
+	* tests/t-support.h [_WIN32]: Include <windows.h>.
+	(init_cryptoki) [_WIN32]: Call WSAStartup.
+
+2008-08-21  Marcus Brinkmann  <marcus@g10code.com>
+
+	* src/scute.def: Start at @1 instead of @0.
+
 2008-08-21  Marcus Brinkmann  <marcus@g10code.com>
 2008-08-21  Marcus Brinkmann  <marcus@g10code.com>
 
 
 	* src/agent.c (agent_configure): Fix cut and paste error.
 	* src/agent.c (agent_configure): Fix cut and paste error.

+ 68 - 22
src/agent.c

@@ -38,6 +38,14 @@
 #include <string.h>
 #include <string.h>
 #include <stdarg.h>
 #include <stdarg.h>
 
 
+#ifdef HAVE_W32_SYSTEM
+#define PATHSEP_C ';'
+#define WINVER 0x0500  /* Required for AllowSetForegroundWindow.  */
+#include <windows.h>
+#else
+#define PATHSEP_C ':'
+#endif
+
 #include <assuan.h>
 #include <assuan.h>
 #include <gpg-error.h>
 #include <gpg-error.h>
 
 
@@ -45,18 +53,24 @@
 #include "support.h"
 #include "support.h"
 #include "agent.h"
 #include "agent.h"
 
 
-#ifdef HAVE_W32_SYSTEM
-#define PATHSEP_C ';'
-#else
-#define PATHSEP_C ':'
-#endif
-
 
 
 /* The global agent context.  */
 /* The global agent context.  */
 static assuan_context_t agent_ctx = NULL;
 static assuan_context_t agent_ctx = NULL;
 
 
 
 
 #ifdef HAVE_W32_SYSTEM
 #ifdef HAVE_W32_SYSTEM
+/* Hack required for Windows.  */
+void 
+gnupg_allow_set_foregound_window (pid_t pid)
+{
+  if (!pid || pid == (pid_t)(-1))
+    return;
+  if (!AllowSetForegroundWindow (pid))
+    DEBUG ("AllowSetForegroundWindow(%lu) failed: %i\n",
+	   (unsigned long)pid, GetLastError ());
+}
+
+
 /* Helper function to build_w32_commandline. */
 /* Helper function to build_w32_commandline. */
 static char *
 static char *
 build_w32_commandline_copy (char *buffer, const char *string)
 build_w32_commandline_copy (char *buffer, const char *string)
@@ -230,7 +244,7 @@ agent_connect (assuan_context_t *ctx_r)
       sockname = make_filename (default_homedir (), "S.gpg-agent", NULL);
       sockname = make_filename (default_homedir (), "S.gpg-agent", NULL);
       if (! sockname)
       if (! sockname)
 	return gpg_error_from_errno (errno);
 	return gpg_error_from_errno (errno);
-	
+
       err = assuan_socket_connect (ctx_r, sockname, 0);
       err = assuan_socket_connect (ctx_r, sockname, 0);
 
 
       if (err)
       if (err)
@@ -238,7 +252,7 @@ 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, starting one");
+	  DEBUG ("no running GPG agent at %s, starting one\n", sockname);
           
           
           agent_program = get_gpg_agent_path ();
           agent_program = get_gpg_agent_path ();
 
 
@@ -263,7 +277,7 @@ agent_connect (assuan_context_t *ctx_r)
             else
             else
               {
               {
                 /* Give the agent some time to prepare itself. */
                 /* Give the agent some time to prepare itself. */
-                _sleep (3);
+                Sleep (3 * 1000);
                 /* Now try again to connect the agent.  */
                 /* Now try again to connect the agent.  */
                 err = assuan_socket_connect (ctx_r, sockname, 0);
                 err = assuan_socket_connect (ctx_r, sockname, 0);
               }
               }
@@ -347,6 +361,26 @@ agent_connect (assuan_context_t *ctx_r)
 }
 }
 
 
 
 
+/* This is the default inquiry callback.  It mainly handles the
+   Pinentry notifications.  */
+static int
+default_inq_cb (void *opaque, const char *line)
+{
+  (void)opaque;
+
+  if (!strncmp (line, "PINENTRY_LAUNCHED", 17) && (line[17]==' '||!line[17]))
+    {
+      gnupg_allow_set_foregound_window ((pid_t)strtoul (line+17, NULL, 10));
+      /* We do not pass errors to avoid breaking other code.  */
+    }
+  else
+    DEBUG ("ignoring gpg-agent inquiry `%s'\n", line);
+
+  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, ...)
@@ -363,7 +397,8 @@ agent_simple_cmd (assuan_context_t ctx, const char *fmt, ...)
   if (res < 0)
   if (res < 0)
     return gpg_error_from_errno (errno);
     return gpg_error_from_errno (errno);
 
 
-  err = assuan_transact (ctx, optstr, NULL, NULL, NULL, NULL, NULL, NULL);
+  err = assuan_transact (ctx, optstr, NULL, NULL, default_inq_cb,
+			 NULL, NULL, NULL);
   if (err)
   if (err)
     DEBUG ("gpg-agent command '%s' failed: %s", optstr, gpg_strerror (err));
     DEBUG ("gpg-agent command '%s' failed: %s", optstr, gpg_strerror (err));
   free (optstr);
   free (optstr);
@@ -401,12 +436,12 @@ agent_configure (assuan_context_t ctx)
   dft_ttyname = getenv ("GPG_TTY");
   dft_ttyname = getenv ("GPG_TTY");
   if ((!dft_ttyname || !*dft_ttyname) && ttyname (0))
   if ((!dft_ttyname || !*dft_ttyname) && ttyname (0))
     dft_ttyname = ttyname (0);
     dft_ttyname = ttyname (0);
-  if (!dft_ttyname)
-    return 0;
-
-  err = agent_simple_cmd (ctx, "OPTION ttyname=%s", dft_ttyname);
-  if (err)
-    return err;
+  if (dft_ttyname)
+    {
+      err = agent_simple_cmd (ctx, "OPTION ttyname=%s", dft_ttyname);
+      if (err)
+	return err;
+    }
 
 
   dft_ttytype = getenv ("TERM");
   dft_ttytype = getenv ("TERM");
   if (dft_ttytype)
   if (dft_ttytype)
@@ -469,6 +504,12 @@ agent_configure (assuan_context_t ctx)
   else if (err)
   else if (err)
     return err;
     return err;
 
 
+  err = agent_simple_cmd (ctx, "OPTION allow-pinentry-notify");
+  if (gpg_err_code (err) == GPG_ERR_UNKNOWN_OPTION)
+    err = 0;
+  else if (err)
+    return err;
+
   return err;
   return err;
 }
 }
 
 
@@ -761,7 +802,8 @@ scute_agent_learn (struct agent_card_info_s *info)
 
 
   memset (info, 0, sizeof (*info));
   memset (info, 0, sizeof (*info));
   err = assuan_transact (agent_ctx, "LEARN --send",
   err = assuan_transact (agent_ctx, "LEARN --send",
-			 NULL, NULL, NULL, NULL, learn_status_cb, info);
+			 NULL, NULL, default_inq_cb,
+			 NULL, learn_status_cb, info);
 
 
   return err;
   return err;
 }
 }
@@ -791,7 +833,8 @@ scute_agent_check_status (void)
   char flag = '-';
   char flag = '-';
 
 
   err = assuan_transact (agent_ctx, "SCD GETINFO status",
   err = assuan_transact (agent_ctx, "SCD GETINFO status",
-			 read_status_cb, &flag, NULL, NULL, NULL, NULL);
+			 read_status_cb, &flag, default_inq_cb,
+			 NULL, NULL, NULL);
 
 
   if (err)
   if (err)
     return err;
     return err;
@@ -862,7 +905,8 @@ scute_agent_sign (char *grip, unsigned char *data, int len,
     return gpg_error (GPG_ERR_INV_ARG);
     return gpg_error (GPG_ERR_INV_ARG);
 
 
   snprintf (cmd, sizeof (cmd), "SIGKEY %s", grip);
   snprintf (cmd, sizeof (cmd), "SIGKEY %s", grip);
-  err = assuan_transact (agent_ctx, cmd, NULL, NULL, NULL, NULL, NULL, NULL);
+  err = assuan_transact (agent_ctx, cmd, NULL, NULL, default_inq_cb,
+			 NULL, NULL, NULL);
   if (err)
   if (err)
     return err;
     return err;
 
 
@@ -871,12 +915,13 @@ scute_agent_sign (char *grip, unsigned char *data, int len,
   pretty_data[2 * len] = '\0';
   pretty_data[2 * len] = '\0';
 
 
   snprintf (cmd, sizeof (cmd), "sethash --hash=tls-md5sha1 %s", pretty_data);
   snprintf (cmd, sizeof (cmd), "sethash --hash=tls-md5sha1 %s", pretty_data);
-  err = assuan_transact (agent_ctx, cmd, NULL, NULL, NULL, NULL, NULL, NULL);
+  err = assuan_transact (agent_ctx, cmd, NULL, NULL, default_inq_cb,
+			 NULL, NULL, NULL);
   if (err)
   if (err)
     return err;
     return err;
 
 
   err = assuan_transact (agent_ctx, "PKSIGN",
   err = assuan_transact (agent_ctx, "PKSIGN",
-			 pksign_cb, &sig, NULL, NULL, NULL, NULL);
+			 pksign_cb, &sig, default_inq_cb, NULL, NULL, NULL);
   if (err)
   if (err)
     return err;
     return err;
 
 
@@ -903,7 +948,8 @@ gpg_error_t scute_agent_is_trusted (char *fpr, bool *is_trusted)
   char cmd[150];
   char cmd[150];
 
 
   snprintf (cmd, sizeof (cmd), "ISTRUSTED %s", fpr);
   snprintf (cmd, sizeof (cmd), "ISTRUSTED %s", fpr);
-  err = assuan_transact (agent_ctx, cmd, NULL, NULL, NULL, NULL, NULL, NULL);
+  err = assuan_transact (agent_ctx, cmd, NULL, NULL, default_inq_cb,
+			 NULL, NULL, NULL);
   if (err && gpg_err_code (err) != GPG_ERR_NOT_TRUSTED)
   if (err && gpg_err_code (err) != GPG_ERR_NOT_TRUSTED)
     return err;
     return err;
   else if (!err)
   else if (!err)

+ 22 - 7
src/cert-gpgsm.c

@@ -42,6 +42,7 @@
 
 
 #include "cert.h"
 #include "cert.h"
 #include "support.h"
 #include "support.h"
+#include "debug.h"
 
 
 
 
 #ifndef HAVE_W32_SYSTEM
 #ifndef HAVE_W32_SYSTEM
@@ -557,11 +558,13 @@ export_cert_compat (char *fpr, struct cert *cert)
   child_fds[0] = output_fds[1];
   child_fds[0] = output_fds[1];
   child_fds[1] = -1;
   child_fds[1] = -1;
 
 
-  err = assuan_pipe_connect (&ctx, GPGSM_PATH, argv, child_fds);
+  err = assuan_pipe_connect_ext (&ctx, get_gpgsm_path (), argv, child_fds,
+				 NULL, NULL, 128);
   close (output_fds[1]);
   close (output_fds[1]);
   if (err)
   if (err)
     {
     {
       close (output_fds[0]);
       close (output_fds[0]);
+      DEBUG ("failed to spawn %s\n", get_gpgsm_path ());
       return err;
       return err;
     }
     }
 
 
@@ -646,9 +649,13 @@ export_cert (char *fpr, struct cert *cert)
   char cmd[COMMANDLINELEN];
   char cmd[COMMANDLINELEN];
   struct export_hook exp;
   struct export_hook exp;
 
 
-  err = assuan_pipe_connect (&ctx, GPGSM_PATH, argv, NULL);
+  err = assuan_pipe_connect_ext (&ctx, get_gpgsm_path (), argv, NULL,
+				 NULL, NULL, 128);
   if (err)
   if (err)
-    return err;
+    {
+      DEBUG ("spawning %s\n", get_gpgsm_path ());
+      return err;
+    }
 
 
   exp.buffer = NULL;
   exp.buffer = NULL;
   exp.buffer_len = 0;
   exp.buffer_len = 0;
@@ -720,9 +727,13 @@ scute_gpgsm_search_certs_by_grip (const char *grip,
   const char *argv[] = { "gpgsm", "--server", NULL };
   const char *argv[] = { "gpgsm", "--server", NULL };
   struct search_ctx_by_field search;
   struct search_ctx_by_field search;
 
 
-  err = assuan_pipe_connect (&ctx, GPGSM_PATH, argv, NULL);
+  err = assuan_pipe_connect_ext (&ctx, get_gpgsm_path (), argv, NULL,
+				 NULL, NULL, 128);
   if (err)
   if (err)
-    return err;
+    {
+      DEBUG ("spawning %s\n", get_gpgsm_path ());
+      return err;
+    }
 
 
   search.field = SEARCH_BY_GRIP;
   search.field = SEARCH_BY_GRIP;
   search.pattern = grip;
   search.pattern = grip;
@@ -747,9 +758,13 @@ scute_gpgsm_search_certs_by_fpr (const char *fpr,
   const char *argv[] = { "gpgsm", "--server", NULL };
   const char *argv[] = { "gpgsm", "--server", NULL };
   struct search_ctx_by_field search;
   struct search_ctx_by_field search;
 
 
-  err = assuan_pipe_connect (&ctx, GPGSM_PATH, argv, NULL);
+  err = assuan_pipe_connect_ext (&ctx, get_gpgsm_path (), argv, NULL,
+				 NULL, NULL, 128);
   if (err)
   if (err)
-    return err;
+    {
+      DEBUG ("failed to spawn %s\n", get_gpgsm_path ());
+      return err;
+    }
 
 
   search.field = SEARCH_BY_FPR;
   search.field = SEARCH_BY_FPR;
   search.pattern = fpr;
   search.pattern = fpr;

+ 49 - 0
src/dllmain.c

@@ -0,0 +1,49 @@
+/* main.cc - DLL entry point
+   Copyright (C) 2007 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 Lesser General Public License
+   as published by the Free Software Foundation; either version 2.1 
+   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 Lesser General Public License
+   along with Scute; if not, write to the Free Software Foundation, 
+   Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA  */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <windows.h>
+#include <shlobj.h>
+
+#include <gpg-error.h>
+#include <assuan.h>
+
+
+/* Entry point called by DLL loader.  */
+STDAPI
+DllMain (HINSTANCE hinst, DWORD reason, LPVOID reserved)
+{
+  if (reason == DLL_PROCESS_ATTACH)
+    {
+      WSADATA wsadat;
+	
+      WSAStartup (0x202, &wsadat);
+    }
+  else if (reason == DLL_PROCESS_DETACH)
+    {
+      WSACleanup ();
+    }
+  
+  return TRUE;
+}

+ 9 - 0
tests/t-support.h

@@ -262,11 +262,20 @@ session_state_str (CK_STATE state)
     }								\
     }								\
   while (0)
   while (0)
 
 
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
 void
 void
 init_cryptoki (void)
 init_cryptoki (void)
 {
 {
   CK_RV err;
   CK_RV err;
 
 
+#ifdef _WIN32
+  WSADATA wsadat;
+  WSAStartup (0x202, &wsadat);
+#endif
+
   err = C_Initialize (NULL);
   err = C_Initialize (NULL);
   fail_if_err (err);
   fail_if_err (err);
 }
 }