summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2007-06-20 13:16:42 +0200
committerWerner Koch <wk@gnupg.org>2007-06-20 13:16:42 +0200
commit09cc0ee7bebcdde9f5a40e827a9e29f9ae7fdf11 (patch)
tree7b5d692846eeed89f8c419814b791188488290fe
parentMade percent_escape more general. (diff)
downloadgnupg2-09cc0ee7bebcdde9f5a40e827a9e29f9ae7fdf11.tar.xz
gnupg2-09cc0ee7bebcdde9f5a40e827a9e29f9ae7fdf11.zip
[w32] gpg-agent is now started automagically by gpgsm.
-rw-r--r--agent/gpg-agent.c2
-rw-r--r--common/ChangeLog11
-rw-r--r--common/exechelp.c135
-rw-r--r--common/sysutils.c55
-rw-r--r--common/sysutils.h4
-rw-r--r--doc/ChangeLog4
-rw-r--r--doc/glossary.texi5
-rw-r--r--doc/gpg-agent.texi2
-rw-r--r--g10/ChangeLog8
-rw-r--r--g10/misc.c73
-rw-r--r--g10/sign.c5
-rw-r--r--scd/scdaemon.c2
-rw-r--r--sm/ChangeLog4
-rw-r--r--sm/call-agent.c89
-rw-r--r--sm/gpgsm.c2
15 files changed, 261 insertions, 140 deletions
diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c
index 8907e9234..a0646925c 100644
--- a/agent/gpg-agent.c
+++ b/agent/gpg-agent.c
@@ -691,7 +691,7 @@ main (int argc, char **argv )
{
log_debug ("waiting for debugger - my pid is %u .....\n",
(unsigned int)getpid());
- sleep (debug_wait);
+ gnupg_sleep (debug_wait);
log_debug ("... okay\n");
}
diff --git a/common/ChangeLog b/common/ChangeLog
index f0381229e..3f8fa41c4 100644
--- a/common/ChangeLog
+++ b/common/ChangeLog
@@ -1,3 +1,14 @@
+2007-06-20 Werner Koch <wk@g10code.com>
+
+ * sysutils.c (gnupg_sleep): New.
+ * sysutils.h [W32]: Remove _sleep wrapper. Changed all callers to
+ use gnupg_sleep.
+
+ * exechelp.c (build_w32_commandline_copy): New.
+ (build_w32_commandline): Factored some code out to new function
+ and correctly process a PGMNAME with spaces.
+ (gnupg_spawn_process_detached) [W32]: Implement.
+
2007-06-14 Werner Koch <wk@g10code.com>
* simple-pwquery.h (MAP_SPWQ_ERROR_IMPL): New.
diff --git a/common/exechelp.c b/common/exechelp.c
index b4700c5cd..d0be84047 100644
--- a/common/exechelp.c
+++ b/common/exechelp.c
@@ -80,17 +80,51 @@
#ifdef HAVE_W32_SYSTEM
+/* Helper function to build_w32_commandline. */
+static char *
+build_w32_commandline_copy (char *buffer, const char *string)
+{
+ char *p = buffer;
+ const char *s;
+
+ if (!*string) /* Empty string. */
+ p = stpcpy (p, "\"\"");
+ else if (strpbrk (string, " \t\n\v\f\""))
+ {
+ /* Need top do some kind of quoting. */
+ p = stpcpy (p, "\"");
+ for (s=string; *s; s++)
+ {
+ *p++ = *s;
+ if (*s == '\"')
+ *p++ = *s;
+ }
+ *p++ = '\"';
+ *p = 0;
+ }
+ else
+ p = stpcpy (p, string);
+
+ return p;
+}
+
/* Build a command line for use with W32's CreateProcess. On success
CMDLINE gets the address of a newly allocated string. */
static gpg_error_t
-build_w32_commandline (const char *pgmname, const char **argv, char **cmdline)
+build_w32_commandline (const char *pgmname, const char * const *argv,
+ char **cmdline)
{
int i, n;
const char *s;
char *buf, *p;
*cmdline = NULL;
- n = strlen (pgmname);
+ n = 0;
+ s = pgmname;
+ n += strlen (s) + 1 + 2; /* (1 space, 2 quoting */
+ for (; *s; s++)
+ if (*s == '\"')
+ n++; /* Need to double inner quotes. */
for (i=0; (s=argv[i]); i++)
{
n += strlen (s) + 1 + 2; /* (1 space, 2 quoting */
@@ -104,26 +138,11 @@ build_w32_commandline (const char *pgmname, const char **argv, char **cmdline)
if (!buf)
return gpg_error_from_syserror ();
- /* fixme: PGMNAME may not contain spaces etc. */
- p = stpcpy (p, pgmname);
+ p = build_w32_commandline_copy (p, pgmname);
for (i=0; argv[i]; i++)
{
- if (!*argv[i]) /* Empty string. */
- p = stpcpy (p, " \"\"");
- else if (strpbrk (argv[i], " \t\n\v\f\""))
- {
- p = stpcpy (p, " \"");
- for (s=argv[i]; *s; s++)
- {
- *p++ = *s;
- if (*s == '\"')
- *p++ = *s;
- }
- *p++ = '\"';
- *p = 0;
- }
- else
- p = stpcpy (stpcpy (p, " "), argv[i]);
+ *p++ = ' ';
+ p = build_w32_commandline_copy (p, argv[i]);
}
*cmdline= buf;
@@ -330,7 +349,7 @@ gnupg_spawn_process (const char *pgmname, const char *argv[],
pi.hProcess, pi.hThread,
(int) pi.dwProcessId, (int) pi.dwThreadId);
- /* Process ha been created suspended; resume it now. */
+ /* Process has been created suspended; resume it now. */
ResumeThread (pi.hThread);
CloseHandle (pi.hThread);
@@ -525,7 +544,79 @@ gnupg_spawn_process_detached (const char *pgmname, const char *argv[],
const char *envp[] )
{
#ifdef HAVE_W32_SYSTEM
- return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+ gpg_error_t err;
+ SECURITY_ATTRIBUTES sec_attr;
+ PROCESS_INFORMATION pi =
+ {
+ NULL, /* Returns process handle. */
+ 0, /* Returns primary thread handle. */
+ 0, /* Returns pid. */
+ 0 /* Returns tid. */
+ };
+ STARTUPINFO si;
+ int cr_flags;
+ char *cmdline;
+
+
+ /* FIXME: We don't make use of ENVP yet. It is currently only used
+ to pass the GPG_AGENT_INFO variable to gpg-agent. As the default
+ on windows is to use a standard socket, this does not really
+ matter. */
+
+
+ if (access (pgmname, X_OK))
+ return gpg_error_from_syserror ();
+
+ /* Prepare security attributes. */
+ memset (&sec_attr, 0, sizeof sec_attr );
+ sec_attr.nLength = sizeof sec_attr;
+ sec_attr.bInheritHandle = FALSE;
+
+ /* Build the command line. */
+ err = build_w32_commandline (pgmname, argv, &cmdline);
+ if (err)
+ return err;
+
+ /* Start the process. */
+ memset (&si, 0, sizeof si);
+ si.cb = sizeof (si);
+ si.dwFlags = STARTF_USESHOWWINDOW;
+ si.wShowWindow = DEBUG_W32_SPAWN? SW_SHOW : SW_MINIMIZE;
+
+ cr_flags = (CREATE_DEFAULT_ERROR_MODE
+ | GetPriorityClass (GetCurrentProcess ())
+ | CREATE_NEW_PROCESS_GROUP
+ | DETACHED_PROCESS);
+ log_debug ("CreateProcess(detached), path=`%s' cmdline=`%s'\n",
+ pgmname, cmdline);
+ if (!CreateProcess (pgmname, /* Program to start. */
+ cmdline, /* Command line arguments. */
+ &sec_attr, /* Process security attributes. */
+ &sec_attr, /* Thread security attributes. */
+ FALSE, /* Inherit handles. */
+ cr_flags, /* Creation flags. */
+ NULL, /* Environment. */
+ NULL, /* Use current drive/directory. */
+ &si, /* Startup information. */
+ &pi /* Returns process information. */
+ ))
+ {
+ log_error ("CreateProcess(detached) failed: %s\n", w32_strerror (-1));
+ xfree (cmdline);
+ return gpg_error (GPG_ERR_GENERAL);
+ }
+ xfree (cmdline);
+ cmdline = NULL;
+
+ log_debug ("CreateProcess(detached) ready: hProcess=%p hThread=%p"
+ " dwProcessID=%d dwThreadId=%d\n",
+ pi.hProcess, pi.hThread,
+ (int) pi.dwProcessId, (int) pi.dwThreadId);
+
+ CloseHandle (pi.hThread);
+
+ return 0;
+
#else
pid_t pid;
int i;
diff --git a/common/sysutils.c b/common/sysutils.c
index d044f222b..ff1fe1ba4 100644
--- a/common/sysutils.c
+++ b/common/sysutils.c
@@ -20,23 +20,36 @@
*/
#include <config.h>
+
+#ifdef WITHOUT_GNU_PTH /* Give the Makefile a chance to build without Pth. */
+# undef HAVE_PTH
+# undef USE_GNU_PTH
+#endif
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#ifdef HAVE_STAT
-#include <sys/stat.h>
+# include <sys/stat.h>
#endif
#if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2
- #include <asm/sysinfo.h>
- #include <asm/unistd.h>
+# include <asm/sysinfo.h>
+# include <asm/unistd.h>
#endif
#ifdef HAVE_SETRLIMIT
- #include <time.h>
- #include <sys/time.h>
- #include <sys/resource.h>
+# include <time.h>
+# include <sys/time.h>
+# include <sys/resource.h>
+#endif
+#ifdef HAVE_W32_SYSTEM
+# include <windows.h>
+#endif
+#ifdef HAVE_PTH
+# include <pth.h>
#endif
+
#include "util.h"
#include "i18n.h"
@@ -229,3 +242,33 @@ check_permissions(const char *path,int extension,int checkonly)
return 0;
}
#endif
+
+
+/* Wrapper around the usual sleep fucntion. This one won't wake up
+ before the sleep time has really elapsed. When build with Pth it
+ merely calls pth_sleep and thus suspends only the current
+ thread. */
+void
+gnupg_sleep (unsigned int seconds)
+{
+#ifdef HAVE_PTH
+ /* With Pth we force a regular sleep for seconds == 0 so that also
+ the process will give up its timeslot. */
+ if (!seconds)
+ {
+# ifdef HAVE_W32_SYSTEM
+ Sleep (0);
+# else
+ sleep (0);
+# endif
+ }
+ pth_sleep (seconds);
+#else
+ /* Fixme: make sure that a sleep won't wake up to early. */
+# ifdef HAVE_W32_SYSTEM
+ Sleep (seconds*1000);
+# else
+ sleep (seconds);
+# endif
+#endif
+}
diff --git a/common/sysutils.h b/common/sysutils.h
index 712991599..0e295f5d1 100644
--- a/common/sysutils.h
+++ b/common/sysutils.h
@@ -27,11 +27,9 @@ int disable_core_dumps (void);
int enable_core_dumps (void);
const unsigned char *get_session_marker (size_t *rlen);
int check_permissions (const char *path,int extension,int checkonly);
+void gnupg_sleep (unsigned int seconds);
#ifdef HAVE_W32_SYSTEM
-/* Windows declares sleep as obsolete, but provides a definition for
- _sleep but non for the still existing sleep. */
-#define sleep(a) _sleep ((a))
#include "../jnlib/w32help.h"
diff --git a/doc/ChangeLog b/doc/ChangeLog
index df1b7d82f..a87680b2b 100644
--- a/doc/ChangeLog
+++ b/doc/ChangeLog
@@ -1,3 +1,7 @@
+2007-06-19 Werner Koch <wk@g10code.com>
+
+ * glossary.texi (Glossary): Describe PSE.
+
2007-06-18 Werner Koch <wk@g10code.com>
* gpg-agent.texi (Agent GETINFO): New.
diff --git a/doc/glossary.texi b/doc/glossary.texi
index 5ea4a95f2..6eede19d2 100644
--- a/doc/glossary.texi
+++ b/doc/glossary.texi
@@ -26,5 +26,10 @@ entered as a 40 character hexadecimal formatted string.
The @emph{Online Certificate Status Protocol} is used as an
alternative to a @acronym{CRL}. It is described in @code{RFC 2560}.
+@item PSE
+ The @emph{Personal Security Environment} describes a database to
+store private keys. This is either a smartcard or a collection of files
+on a disk; the latter is often called a Soft-PSE.
+
@end table
diff --git a/doc/gpg-agent.texi b/doc/gpg-agent.texi
index a079b3095..85ce1acd4 100644
--- a/doc/gpg-agent.texi
+++ b/doc/gpg-agent.texi
@@ -832,7 +832,7 @@ Here is an example session:
@subsection Generating a Key
This is used to create a new keypair and store the secret key inside the
-active PSE -w which is in most cases a Soft-PSE. An not yet defined
+active PSE --- which is in most cases a Soft-PSE. An not yet defined
option allows to choose the storage location. To get the secret key out
of the PSE, a special export tool has to be used.
diff --git a/g10/ChangeLog b/g10/ChangeLog
index 5e0a29062..b49d8868b 100644
--- a/g10/ChangeLog
+++ b/g10/ChangeLog
@@ -1,3 +1,11 @@
+2007-06-20 Werner Koch <wk@g10code.com>
+
+ * misc.c (setsysinfo, trap_unaligned): Remove. It is also in
+ common/sysutils.c.
+ (disable_core_dumps, get_session_marker):
+
+ * sign.c (sleep): Remove sleep wrapper.
+
2007-06-18 Marcus Brinkmann <marcus@g10code.de>
* gpg.c (gpgconf_list): Percent escape output of --gpgconf-list.
diff --git a/g10/misc.c b/g10/misc.c
index c743da614..4cb7191e5 100644
--- a/g10/misc.c
+++ b/g10/misc.c
@@ -94,51 +94,6 @@ static struct secured_file_item *secured_files;
-#if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2
-static int
-setsysinfo(unsigned long op, void *buffer, unsigned long size,
- int *start, void *arg, unsigned long flag)
-{
- return syscall(__NR_osf_setsysinfo, op, buffer, size, start, arg, flag);
-}
-
-void
-trap_unaligned(void)
-{
- unsigned int buf[2];
-
- buf[0] = SSIN_UACPROC;
- buf[1] = UAC_SIGBUS | UAC_NOPRINT;
- setsysinfo(SSI_NVPAIRS, buf, 1, 0, 0, 0);
-}
-#else
-void
-trap_unaligned(void)
-{ /* dummy */
-}
-#endif
-
-
-int
-disable_core_dumps()
-{
-#ifdef HAVE_DOSISH_SYSTEM
- return 0;
-#else
-#ifdef HAVE_SETRLIMIT
- struct rlimit limit;
-
- limit.rlim_cur = 0;
- limit.rlim_max = 0;
- if( !setrlimit( RLIMIT_CORE, &limit ) )
- return 0;
- if( errno != EINVAL && errno != ENOSYS )
- log_fatal(_("can't disable core dumps: %s\n"), strerror(errno) );
-#endif
- return 1;
-#endif
-}
-
/* For the sake of SELinux we want to restrict access through gpg to
certain files we keep under our own control. This function
@@ -371,34 +326,6 @@ print_digest_algo_note( int algo )
gcry_md_algo_name (algo));
}
-/* Return a string which is used as a kind of process ID */
-const byte *
-get_session_marker( size_t *rlen )
-{
- static byte marker[SIZEOF_UNSIGNED_LONG*2];
- static int initialized;
-
- if ( !initialized )
- {
- volatile ulong aa, bb; /* We really want the uninitialized value. */
- ulong a, b;
-
- initialized = 1;
- /* Although this marker is guessable it is not easy to use this
- * for a faked control packet because an attacker does not have
- * enough control about the time the verification takes place.
- * Of course, we could add just more random but than we need the
- * random generator even for verification tasks - which does not
- * make sense. */
- a = aa ^ (ulong)getpid();
- b = bb ^ (ulong)time(NULL);
- memcpy ( marker, &a, SIZEOF_UNSIGNED_LONG );
- memcpy ( marker+SIZEOF_UNSIGNED_LONG, &b, SIZEOF_UNSIGNED_LONG );
- }
- *rlen = sizeof(marker);
- return marker;
-}
-
/****************
* Wrapper around the libgcrypt function with additonal checks on
* the OpenPGP contraints for the algo ID.
diff --git a/g10/sign.c b/g10/sign.c
index 062fa9f48..1a1a80bc6 100644
--- a/g10/sign.c
+++ b/g10/sign.c
@@ -26,7 +26,6 @@
#include <string.h>
#include <errno.h>
#include <assert.h>
-#include <unistd.h> /* need sleep() */
#include "gpg.h"
#include "options.h"
@@ -47,8 +46,6 @@
#ifdef HAVE_DOSISH_SYSTEM
#define LF "\r\n"
-void __stdcall Sleep(ulong);
-#define sleep(a) Sleep((a)*1000)
#else
#define LF "\n"
#endif
@@ -1563,7 +1560,7 @@ update_keysig_packet( PKT_signature **ret_sig,
one. */
while(sig->timestamp<=orig_sig->timestamp)
{
- sleep(1);
+ gnupg_sleep (1);
sig->timestamp=make_timestamp();
}
diff --git a/scd/scdaemon.c b/scd/scdaemon.c
index f9a99922f..b2508943d 100644
--- a/scd/scdaemon.c
+++ b/scd/scdaemon.c
@@ -519,7 +519,7 @@ main (int argc, char **argv )
{
log_debug ("waiting for debugger - my pid is %u .....\n",
(unsigned int)getpid());
- sleep (debug_wait);
+ gnupg_sleep (debug_wait);
log_debug ("... okay\n");
}
diff --git a/sm/ChangeLog b/sm/ChangeLog
index c5d342bd2..896b5c368 100644
--- a/sm/ChangeLog
+++ b/sm/ChangeLog
@@ -1,3 +1,7 @@
+2007-06-20 Werner Koch <wk@g10code.com>
+
+ * call-agent.c (start_agent) [W32]: Start the agent on the fly.
+
2007-06-18 Marcus Brinkmann <marcus@g10code.de>
* gpgsm.c (main): Percent escape output of --gpgconf-list.
diff --git a/sm/call-agent.c b/sm/call-agent.c
index 1ac5412be..b30fe60df 100644
--- a/sm/call-agent.c
+++ b/sm/call-agent.c
@@ -37,7 +37,8 @@
#include "i18n.h"
#include "asshelp.h"
#include "keydb.h" /* fixme: Move this to import.c */
-#include "../common/membuf.h"
+#include "membuf.h"
+#include "exechelp.h"
static assuan_context_t agent_ctx = NULL;
@@ -83,21 +84,12 @@ start_agent (ctrl_t ctrl)
infostr = force_pipe_server? NULL : getenv ("GPG_AGENT_INFO");
if (!infostr || !*infostr)
{
- const char *pgmname;
- const char *argv[3];
char *sockname;
- int no_close_list[3];
- int i;
/* First check whether we can connect at the standard
socket. */
sockname = make_filename (opt.homedir, "S.gpg-agent", NULL);
rc = assuan_socket_connect (&ctx, sockname, 0);
- xfree (sockname);
-#ifdef HAVE_W32_SYSTEM
-# warning Print a warning if connecting is not possible
- /* and offer to fire up the agent. */
-#endif
if (rc)
{
@@ -112,30 +104,71 @@ start_agent (ctrl_t ctrl)
gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
log_error ("error flushing pending output: %s\n",
strerror (errno));
+ xfree (sockname);
return tmperr;
}
if (!opt.agent_program || !*opt.agent_program)
opt.agent_program = gnupg_module_name (GNUPG_MODULE_NAME_AGENT);
- if ( !(pgmname = strrchr (opt.agent_program, '/')))
- pgmname = opt.agent_program;
- else
- pgmname++;
-
- argv[0] = pgmname;
- argv[1] = "--server";
- argv[2] = NULL;
-
- i=0;
- if (log_get_fd () != -1)
- no_close_list[i++] = log_get_fd ();
- no_close_list[i++] = fileno (stderr);
- no_close_list[i] = -1;
-
- /* Connect to the agent and perform initial handshaking. */
- rc = assuan_pipe_connect (&ctx, opt.agent_program, argv,
- no_close_list);
+
+#ifdef HAVE_W32_SYSTEM
+ {
+ /* Under Windows we start the server in daemon mode. This
+ is because the default is to use the standard socket
+ 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. */
+ const char *argv[3];
+
+ /* The --no-reuse-standard option makes sure that we don't
+ start a second instance of a agent in case another
+ process has started one in the meantime. */
+ argv[0] = "--daemon";
+ argv[1] = "--no-reuse-standard-socket";
+ argv[2] = NULL;
+
+ rc = gnupg_spawn_process_detached (opt.agent_program, argv, NULL);
+ if (rc)
+ log_debug ("failed to start agent `%s': %s\n",
+ opt.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);
+ }
+ }
+#else /*!HAVE_W32_SYSTEM*/
+ {
+ const char *pgmname;
+ const char *argv[3];
+ int no_close_list[3];
+ int i;
+
+ if ( !(pgmname = strrchr (opt.agent_program, '/')))
+ pgmname = opt.agent_program;
+ else
+ pgmname++;
+
+ argv[0] = pgmname;
+ argv[1] = "--server";
+ argv[2] = NULL;
+
+ i=0;
+ if (log_get_fd () != -1)
+ no_close_list[i++] = log_get_fd ();
+ no_close_list[i++] = fileno (stderr);
+ no_close_list[i] = -1;
+
+ /* Connect to the agent and perform initial handshaking. */
+ rc = assuan_pipe_connect (&ctx, opt.agent_program, argv,
+ no_close_list);
+ }
+#endif /*!HAVE_W32_SYSTEM*/
}
+ xfree (sockname);
}
else
{
diff --git a/sm/gpgsm.c b/sm/gpgsm.c
index f6d2b8444..b6a3e69c2 100644
--- a/sm/gpgsm.c
+++ b/sm/gpgsm.c
@@ -1438,7 +1438,7 @@ main ( int argc, char **argv)
{
log_debug ("waiting for debugger - my pid is %u .....\n",
(unsigned int)getpid());
- sleep (debug_wait);
+ gnupg_sleep (debug_wait);
log_debug ("... okay\n");
}
gpgsm_server (recplist);