aboutsummaryrefslogtreecommitdiffstats
path: root/agent/gpg-agent.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--agent/gpg-agent.c181
1 files changed, 112 insertions, 69 deletions
diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c
index 65d5fd5a6..911afb881 100644
--- a/agent/gpg-agent.c
+++ b/agent/gpg-agent.c
@@ -84,13 +84,14 @@ enum cmd_and_opt_values
oDisablePth,
oDefCacheTTL,
oMaxCacheTTL,
+ oUseStandardSocket,
+ oNoUseStandardSocket,
oIgnoreCacheForSigning,
oAllowMarkTrusted,
oKeepTTY,
- oKeepDISPLAY,
-
-aTest };
+ oKeepDISPLAY
+};
@@ -115,6 +116,9 @@ static ARGPARSE_OPTS opts[] = {
{ oNoGrab, "no-grab" ,0, N_("do not grab keyboard and mouse")},
{ oLogFile, "log-file" ,2, N_("use a log file for the server")},
{ oDisablePth, "disable-pth", 0, N_("do not allow multiple connections")},
+ { oUseStandardSocket, "use-standard-socket", 0,
+ N_("use a standard location for the socket")},
+ { oNoUseStandardSocket, "no-use-standard-socket", 0, "@"},
{ oPinentryProgram, "pinentry-program", 2 ,
N_("|PGM|use PGM as the PIN-Entry program") },
@@ -154,7 +158,7 @@ static int shutdown_pending;
static int maybe_setuid = 1;
/* Name of the communication socket */
-static char socket_name[128];
+static char *socket_name;
/* Default values for options passed to the pinentry. */
static char *default_display;
@@ -177,12 +181,11 @@ static char *current_logfile;
static void create_directories (void);
#ifdef USE_GNU_PTH
static void handle_connections (int listen_fd);
-
/* Pth wrapper function definitions. */
GCRY_THREAD_OPTION_PTH_IMPL;
-
#endif /*USE_GNU_PTH*/
-static void check_for_running_agent (void);
+
+static int check_for_running_agent (int);
@@ -293,7 +296,7 @@ set_debug (void)
static void
cleanup (void)
{
- if (*socket_name)
+ if (socket_name && *socket_name)
{
char *p;
@@ -419,6 +422,7 @@ main (int argc, char **argv )
int debug_wait = 0;
int disable_pth = 0;
int gpgconf_list = 0;
+ int standard_socket = 0;
gpg_error_t err;
@@ -437,17 +441,12 @@ main (int argc, char **argv )
/* Libgcrypt requires us to register the threading model first.
Note that this will also do the pth_init. */
#ifdef USE_GNU_PTH
-#ifdef HAVE_W32_SYSTEM
- /* For W32 we need pth. */
- pth_init ();
-#else
err = gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pth);
if (err)
{
log_fatal ("can't register GNU Pth with Libgcrypt: %s\n",
gpg_strerror (err));
}
-#endif
#endif /*USE_GNU_PTH*/
@@ -468,18 +467,28 @@ main (int argc, char **argv )
may_coredump = disable_core_dumps ();
+ /* Set default options. */
parse_rereadable_options (NULL, 0); /* Reset them to default values. */
-
+#ifdef HAVE_W32_SYSTEM
+ standard_socket = 1; /* Under Windows we always use a standard
+ socket. */
+#endif
+
shell = getenv ("SHELL");
if (shell && strlen (shell) >= 3 && !strcmp (shell+strlen (shell)-3, "csh") )
csh_style = 1;
-
+
+
opt.homedir = getenv("GNUPGHOME");
+#ifdef HAVE_W32_SYSTEM
+ if (!opt.homedir || !*opt.homedir)
+ opt.homedir = read_w32_registry_string (NULL,
+ "Software\\GNU\\GnuPG", "HomeDir");
+#endif /*HAVE_W32_SYSTEM*/
if (!opt.homedir || !*opt.homedir)
opt.homedir = GNUPG_DEFAULT_HOMEDIR;
-
- /* check whether we have a config file on the commandline */
+ /* Check whether we have a config file on the commandline */
orig_argc = argc;
orig_argv = argv;
pargs.argc = &argc;
@@ -509,7 +518,6 @@ main (int argc, char **argv )
Now we are now working under our real uid
*/
-
if (default_config)
configname = make_filename (opt.homedir, "gpg-agent.conf", NULL );
@@ -584,6 +592,9 @@ main (int argc, char **argv )
case oLCmessages: default_lc_messages = xstrdup (pargs.r.ret_str);
break;
+ case oUseStandardSocket: standard_socket = 1; break;
+ case oNoUseStandardSocket: standard_socket = 0; break;
+
case oKeepTTY: opt.keep_tty = 1; break;
case oKeepDISPLAY: opt.keep_display = 1; break;
@@ -695,7 +706,7 @@ main (int argc, char **argv )
if (!pipe_server && !is_daemon)
{
log_set_prefix (NULL, JNLIB_LOG_WITH_PREFIX);
- check_for_running_agent ();
+ check_for_running_agent (0);
agent_exit (0);
}
@@ -736,6 +747,7 @@ main (int argc, char **argv )
else
{ /* Regular server mode */
int fd;
+ int rc;
pid_t pid;
int len;
struct sockaddr_un serv_addr;
@@ -750,28 +762,28 @@ main (int argc, char **argv )
unsetenv ("DISPLAY");
#endif
- *socket_name = 0;
- snprintf (socket_name, DIM(socket_name)-1,
- "/tmp/gpg-XXXXXX/S.gpg-agent");
- socket_name[DIM(socket_name)-1] = 0;
- p = strrchr (socket_name, '/');
- if (!p)
- BUG ();
- *p = 0;;
-
-#ifndef HAVE_W32_SYSTEM
- if (!mkdtemp(socket_name))
+ /* Create the socket name . */
+ if (standard_socket)
+ socket_name = make_filename (opt.homedir, "S.gpg-agent", NULL);
+ else
{
- log_error ("can't create directory `%s': %s\n",
- socket_name, strerror(errno) );
- exit (1);
+ socket_name = xstrdup ("/tmp/gpg-XXXXXX/S.gpg-agent");
+ p = strrchr (socket_name, '/');
+ if (!p)
+ BUG ();
+ *p = 0;;
+ if (!mkdtemp(socket_name))
+ {
+ log_error (_("can't create directory `%s': %s\n"),
+ socket_name, strerror(errno) );
+ exit (1);
+ }
+ *p = '/';
}
-#endif
- *p = '/';
- if (strchr (socket_name, ':') )
+ if (strchr (socket_name, PATHSEP_C) )
{
- log_error ("colons are not allowed in the socket name\n");
+ log_error ("`%s' are not allowed in the socket name\n", PATHSEP_S);
exit (1);
}
if (strlen (socket_name)+1 >= sizeof serv_addr.sun_path )
@@ -797,13 +809,22 @@ main (int argc, char **argv )
len = (offsetof (struct sockaddr_un, sun_path)
+ strlen(serv_addr.sun_path) + 1);
- if (
#ifdef HAVE_W32_SYSTEM
- _w32_sock_bind
+ rc = _w32_sock_bind (fd, (struct sockaddr*)&serv_addr, len);
+ if (rc == -1 && standard_socket)
+ {
+ remove (socket_name);
+ rc = bind (fd, (struct sockaddr*)&serv_addr, len);
+ }
#else
- bind
+ rc = bind (fd, (struct sockaddr*)&serv_addr, len);
+ if (rc == -1 && standard_socket && errno == EADDRINUSE)
+ {
+ remove (socket_name);
+ rc = bind (fd, (struct sockaddr*)&serv_addr, len);
+ }
#endif
- (fd, (struct sockaddr*)&serv_addr, len) == -1)
+ if (rc == -1)
{
log_error ("error binding socket to `%s': %s\n",
serv_addr.sun_path, strerror (errno) );
@@ -823,7 +844,10 @@ main (int argc, char **argv )
fflush (NULL);
-#ifndef HAVE_W32_SYSTEM
+#ifdef HAVE_W32_SYSTEM
+ pid = getpid ();
+ printf ("set GPG_AGENT_INFO=%s;%lu;1\n", socket_name, (ulong)pid);
+#else /*!HAVE_W32_SYSTEM*/
pid = fork ();
if (pid == (pid_t)-1)
{
@@ -1286,53 +1310,72 @@ handle_connections (int listen_fd)
/* Figure out whether an agent is available and running. Prints an
- error if not. */
-static void
-check_for_running_agent ()
+ error if not. Usually started with MODE 0. */
+static int
+check_for_running_agent (int mode)
{
int rc;
char *infostr, *p;
assuan_context_t ctx;
int prot, pid;
- infostr = getenv ("GPG_AGENT_INFO");
- if (!infostr || !*infostr)
+ if (!mode)
{
- log_error (_("no gpg-agent running in this session\n"));
- return;
- }
+ infostr = getenv ("GPG_AGENT_INFO");
+ if (!infostr || !*infostr)
+ {
+ if (!check_for_running_agent (1))
+ return 0; /* Okay, its running on the standard socket. */
+ log_error (_("no gpg-agent running in this session\n"));
+ return -1;
+ }
- infostr = xstrdup (infostr);
- if ( !(p = strchr (infostr, ':')) || p == infostr)
- {
- log_error (_("malformed GPG_AGENT_INFO environment variable\n"));
- xfree (infostr);
- return;
- }
+ infostr = xstrdup (infostr);
+ if ( !(p = strchr (infostr, PATHSEP_C)) || p == infostr)
+ {
+ xfree (infostr);
+ if (!check_for_running_agent (1))
+ return 0; /* Okay, its running on the standard socket. */
+ log_error (_("malformed GPG_AGENT_INFO environment variable\n"));
+ return -1;
+ }
- *p++ = 0;
- pid = atoi (p);
- while (*p && *p != ':')
- p++;
- prot = *p? atoi (p+1) : 0;
- if (prot != 1)
+ *p++ = 0;
+ pid = atoi (p);
+ while (*p && *p != PATHSEP_C)
+ p++;
+ prot = *p? atoi (p+1) : 0;
+ if (prot != 1)
+ {
+ xfree (infostr);
+ log_error (_("gpg-agent protocol version %d is not supported\n"),
+ prot);
+ if (!check_for_running_agent (1))
+ return 0; /* Okay, its running on the standard socket. */
+ return -1;
+ }
+ }
+ else /* MODE != 0 */
{
- log_error (_("gpg-agent protocol version %d is not supported\n"),
- prot);
- xfree (infostr);
- return;
+ infostr = make_filename (opt.homedir, "S.gpg-agent", NULL);
}
+
rc = assuan_socket_connect (&ctx, infostr, pid);
xfree (infostr);
if (rc)
{
- log_error ("can't connect to the agent: %s\n", assuan_strerror (rc));
- return;
+ if (!mode && !check_for_running_agent (1))
+ return 0; /* Okay, its running on the standard socket. */
+
+ if (!mode)
+ log_error ("can't connect to the agent: %s\n", assuan_strerror (rc));
+ return -1;
}
if (!opt.quiet)
log_info ("gpg-agent running and available\n");
assuan_disconnect (ctx);
+ return 0;
}