summaryrefslogtreecommitdiffstats
path: root/agent
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2007-06-19 11:11:11 +0200
committerWerner Koch <wk@gnupg.org>2007-06-19 11:11:11 +0200
commit540f9164c01dbbd1f8fc9abcd2ee67dbf6e1ee10 (patch)
tree298058ec8adf7c7c059ce7db127334a9ddb49bec /agent
parentjnlib/ (diff)
downloadgnupg2-540f9164c01dbbd1f8fc9abcd2ee67dbf6e1ee10.tar.xz
gnupg2-540f9164c01dbbd1f8fc9abcd2ee67dbf6e1ee10.zip
Made percent_escape more general.
Added regression tests support to jnlib. W32 changes.
Diffstat (limited to 'agent')
-rw-r--r--agent/ChangeLog6
-rw-r--r--agent/gpg-agent.c31
-rw-r--r--agent/w32main.c154
3 files changed, 170 insertions, 21 deletions
diff --git a/agent/ChangeLog b/agent/ChangeLog
index e23cd99a9..19564556e 100644
--- a/agent/ChangeLog
+++ b/agent/ChangeLog
@@ -5,10 +5,14 @@
2007-06-18 Werner Koch <wk@g10code.com>
+ * w32main.c (build_argv): New.
+ (WinMain): Use it.
+
* command.c (cmd_killagent) [W32]: New.
(cmd_getinfo): New.
* gpg-agent.c (get_agent_ssh_socket_name): New.
-
+ (no_force_standard_socket) New.
+ (create_server_socket): Use it.
* Makefile.am (gpg_agent_res_ldflags): Pass windows option to ld.
2007-06-14 Werner Koch <wk@g10code.com>
diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c
index 419f3769a..8907e9234 100644
--- a/agent/gpg-agent.c
+++ b/agent/gpg-agent.c
@@ -93,6 +93,7 @@ enum cmd_and_opt_values
oMinPassphraseLen,
oUseStandardSocket,
oNoUseStandardSocket,
+ oNoReuseStandardSocket,
oIgnoreCacheForSigning,
oAllowMarkTrusted,
@@ -130,6 +131,7 @@ static ARGPARSE_OPTS opts[] = {
{ oUseStandardSocket, "use-standard-socket", 0,
N_("use a standard location for the socket")},
{ oNoUseStandardSocket, "no-use-standard-socket", 0, "@"},
+ { oNoReuseStandardSocket, "no-reuse-standard-socket", 0, "@"},
{ oPinentryProgram, "pinentry-program", 2 ,
N_("|PGM|use PGM as the PIN-Entry program") },
@@ -186,6 +188,10 @@ static char *socket_name;
/* Name of the communication socket used for ssh-agent-emulation. */
static char *socket_name_ssh;
+/* If set to true and a standard socket is requested, we won't try to
+ bind to a socket which is already in use. */
+static int no_reuse_standard_socket;
+
/* Default values for options passed to the pinentry. */
static char *default_display;
static char *default_ttyname;
@@ -215,7 +221,7 @@ static pid_t parent_pid = (pid_t)(-1);
static char *create_socket_name (int use_standard_socket,
char *standard_name, char *template);
-static int create_server_socket (int is_standard_name, const char *name);
+static int create_server_socket (int is_standard_name, char *name);
static void create_directories (void);
static void agent_init_default_ctrl (ctrl_t ctrl);
@@ -621,6 +627,7 @@ main (int argc, char **argv )
case oUseStandardSocket: standard_socket = 1; break;
case oNoUseStandardSocket: standard_socket = 0; break;
+ case oNoReuseStandardSocket: no_reuse_standard_socket = 1; break;
case oKeepTTY: opt.keep_tty = 1; break;
case oKeepDISPLAY: opt.keep_display = 1; break;
@@ -715,7 +722,7 @@ main (int argc, char **argv )
#define GC_OPT_FLAG_NO_ARG_DESC (1UL << 6)
filename = make_filename (opt.homedir, "gpg-agent.conf", NULL );
- filename_esc = percent_escape (filename);
+ filename_esc = percent_escape (filename, NULL);
printf ("gpgconf-gpg-agent.conf:%lu:\"%s\n",
GC_OPT_FLAG_DEFAULT, filename_esc);
@@ -1226,10 +1233,10 @@ create_socket_name (int use_standard_socket,
/* Create a Unix domain socket with NAME. IS_STANDARD_NAME indicates
- whether a non-random socket is used. Returns the filedescriptor or
+ whether a non-random socket is used. Returns the file descriptor or
terminates the process in case of an error. */
static int
-create_server_socket (int is_standard_name, const char *name)
+create_server_socket (int is_standard_name, char *name)
{
struct sockaddr_un *serv_addr;
socklen_t len;
@@ -1257,14 +1264,16 @@ create_server_socket (int is_standard_name, const char *name)
#ifdef HAVE_W32_SYSTEM
rc = _w32_sock_bind (fd, (struct sockaddr*) serv_addr, len);
- if (is_standard_name && rc == -1 )
+ if (is_standard_name && rc == -1 && errno == WSAEADDRINUSE
+ && !no_reuse_standard_socket)
{
remove (name);
- rc = bind (fd, (struct sockaddr*) serv_addr, len);
+ rc = _w32_sock_bind (fd, (struct sockaddr*) serv_addr, len);
}
#else
rc = bind (fd, (struct sockaddr*) serv_addr, len);
- if (is_standard_name && rc == -1 && errno == EADDRINUSE)
+ if (is_standard_name && rc == -1 && errno == EADDRINUSE
+ && !no_reuse_standard_socket)
{
remove (name);
rc = bind (fd, (struct sockaddr*) serv_addr, len);
@@ -1272,9 +1281,15 @@ create_server_socket (int is_standard_name, const char *name)
#endif
if (rc == -1)
{
+ /* We use gpg_strerror here because it allows us to get strings
+ for some W32 socket error codes. */
log_error (_("error binding socket to `%s': %s\n"),
- serv_addr->sun_path, strerror (errno));
+ serv_addr->sun_path,
+ gpg_strerror (gpg_error_from_errno (errno)));
+
close (fd);
+ if (is_standard_name && no_reuse_standard_socket)
+ *name = 0; /* Inhibit removal of the socket by cleanup(). */
agent_exit (2);
}
diff --git a/agent/w32main.c b/agent/w32main.c
index 5fccb7ea2..176050220 100644
--- a/agent/w32main.c
+++ b/agent/w32main.c
@@ -1,5 +1,6 @@
/* w32main.c - W32 main entry pint and taskbar support for the GnuPG Agent
* Copyright (C) 2007 Free Software Foundation, Inc.
+ * Copyright 1996, 1998 Alexandre Julliard
*
* This file is part of GnuPG.
*
@@ -37,6 +38,136 @@ static HINSTANCE glob_hinst;
static HWND glob_hwnd;
+/* Build an argv array from the command in CMDLINE. RESERVED is the
+ number of args to reserve before the first one. This code is based
+ on Alexandre Julliard's LGPLed wine-0.9.34/dlls/kernel32/process.c
+ and modified to fit into our framework. The function returns NULL
+ on error; on success an arry with the argiments is returned. This
+ array has been allocaqted using a plain malloc (and not the usual
+ xtrymalloc). */
+static char **
+build_argv (char *cmdline_arg, int reserved)
+{
+ int argc;
+ char **argv;
+ char *cmdline, *s, *arg, *d;
+ int in_quotes, bs_count;
+
+ cmdline = malloc (strlen (cmdline_arg) + 1);
+ if (!cmdline)
+ return NULL;
+ strcpy (cmdline, cmdline_arg);
+
+ /* First determine the required size of the array. */
+ argc = reserved + 1;
+ bs_count = 0;
+ in_quotes = 0;
+ s = cmdline;
+ for (;;)
+ {
+ if ( !*s || ((*s==' ' || *s=='\t') && !in_quotes)) /* A space. */
+ {
+ argc++;
+ /* Skip the remaining spaces. */
+ while (*s==' ' || *s=='\t')
+ s++;
+ if (!*s)
+ break;
+ bs_count = 0;
+ }
+ else if (*s=='\\')
+ {
+ bs_count++;
+ s++;
+ }
+ else if ( (*s == '\"') && !(bs_count & 1))
+ {
+ /* Unescaped '\"' */
+ in_quotes = !in_quotes;
+ bs_count=0;
+ s++;
+ }
+ else /* A regular character. */
+ {
+ bs_count = 0;
+ s++;
+ }
+ }
+
+ argv = malloc (argc * sizeof *argv);
+ if (!argv)
+ {
+ free (cmdline);
+ return NULL;
+ }
+
+ /* Now actually parse the command line. */
+ argc = reserved;
+ bs_count = 0;
+ in_quotes=0;
+ arg = d = s = cmdline;
+ while (*s)
+ {
+ if ((*s==' ' || *s=='\t') && !in_quotes)
+ {
+ /* Close the argument and copy it. */
+ *d = 0;
+ argv[argc++] = arg;
+
+ /* Skip the remaining spaces. */
+ do
+ s++;
+ while (*s==' ' || *s=='\t');
+
+ /* Start with a new argument */
+ arg = d = s;
+ bs_count = 0;
+ }
+ else if (*s=='\\')
+ {
+ *d++ = *s++;
+ bs_count++;
+ }
+ else if (*s=='\"')
+ {
+ if ( !(bs_count & 1) )
+ {
+ /* Preceded by an even number of backslashes, this is
+ half that number of backslashes, plus a '\"' which we
+ discard. */
+ d -= bs_count/2;
+ s++;
+ in_quotes = !in_quotes;
+ }
+ else
+ {
+ /* Preceded by an odd number of backslashes, this is
+ half that number of backslashes followed by a '\"'. */
+ d = d - bs_count/2 - 1;
+ *d++ ='\"';
+ s++;
+ }
+ bs_count=0;
+ }
+ else /* A regular character. */
+ {
+ *d++ = *s++;
+ bs_count = 0;
+ }
+ }
+
+ if (*arg)
+ {
+ *d = 0;
+ argv[argc++] = arg;
+ }
+ argv[argc] = NULL;
+
+ return argv;
+}
+
+
+
/* Our window message processing function. */
static LRESULT CALLBACK
wndw_proc (HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
@@ -155,24 +286,23 @@ w32_setup_taskbar (void)
/* The main entry point for the Windows version. We save away all GUI
- related stuff, parse the commandline and finally call the real
+ related stuff, parse the command line and finally call the real
main. */
int WINAPI
WinMain (HINSTANCE hinst, HINSTANCE hprev, LPSTR cmdline, int showcmd)
{
- /* Fixme: We need a parser for the command line. Should be
- available in some CRT code - need to see whether we can find a
- GNU version. For nopw we call gpg-agent with a couple of fixed arguments
- */
- char *argv[] = { "gpg-agent.exe", "--daemon", "-v", "--debug-all", NULL };
+ char **argv;
+ int argc;
+ /* We use the GetCommandLine function because that also includes the
+ program name in contrast to the CMDLINE arg. */
+ argv = build_argv (GetCommandLineA (), 0);
+ if (!argv)
+ return 2; /* Can't do much about a malloc failure. */
+ for (argc=0; argv[argc]; argc++)
+ ;
glob_hinst = hinst;
- return w32_main (DIM(argv)-1, argv);
+ return w32_main (argc, argv);
}
-
-
-
-
-