From 8fde13d07c0059040ed531ca3ac365f5780ff240 Mon Sep 17 00:00:00 2001 From: Shea Levy Date: Tue, 18 Nov 2014 14:34:53 -0500 Subject: [PATCH] gpg-agent: Enable socket activation This allows gpg-agent to be managed by tools such as systemd or launchd --- agent/gpg-agent.c | 62 ++++++++++++++++++++++++++++++++++++------------------ doc/gpg-agent.texi | 21 +++++++++++++++++- 2 files changed, 61 insertions(+), 22 deletions(-) diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index 5960fe3..2f06982 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -124,7 +124,9 @@ enum cmd_and_opt_values oPuttySupport, oDisableScdaemon, oDisableCheckOwnSocket, - oWriteEnvFile + oWriteEnvFile, + oAgentFD, + oSSHAgentFD }; @@ -138,6 +140,8 @@ static ARGPARSE_OPTS opts[] = { { 301, NULL, 0, N_("@Options:\n ") }, { oDaemon, "daemon", 0, N_("run in daemon mode (background)") }, + { oAgentFD, "agent-fd", 1, "@" }, + { oSSHAgentFD, "ssh-agent-fd", 1, "@" }, { oServer, "server", 0, N_("run in server mode (foreground)") }, { oVerbose, "verbose", 0, N_("verbose") }, { oQuiet, "quiet", 0, N_("be somewhat more quiet") }, @@ -596,6 +600,31 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread) return 1; /* handled */ } +/* Handle agent socket(s) */ +static void +handle_agent_socks(int fd, int fd_ssh) +{ +#ifndef HAVE_W32_SYSTEM + if (chdir("/")) + { + log_error ("chdir to / failed: %s\n", strerror (errno)); + exit (1); + } + + { + struct sigaction sa; + + sa.sa_handler = SIG_IGN; + sigemptyset (&sa.sa_mask); + sa.sa_flags = 0; + sigaction (SIGPIPE, &sa, NULL); + } +#endif /*!HAVE_W32_SYSTEM*/ + + log_info ("%s %s started\n", strusage(11), strusage(13) ); + handle_connections (fd, fd_ssh); + assuan_sock_close (fd); +} /* The main entry point. */ int @@ -612,6 +641,8 @@ main (int argc, char **argv ) int default_config =1; int pipe_server = 0; int is_daemon = 0; + int fd_agent = GNUPG_INVALID_FD; + int fd_ssh_agent = GNUPG_INVALID_FD; int nodetach = 0; int csh_style = 0; char *logfile = NULL; @@ -819,6 +850,8 @@ main (int argc, char **argv ) case oSh: csh_style = 0; break; case oServer: pipe_server = 1; break; case oDaemon: is_daemon = 1; break; + case oAgentFD: fd_agent = pargs.r.ret_int; break; + case oSSHAgentFD: fd_ssh_agent = pargs.r.ret_int; break; case oDisplay: default_display = xstrdup (pargs.r.ret_str); break; case oTTYname: default_ttyname = xstrdup (pargs.r.ret_str); break; @@ -904,7 +937,8 @@ main (int argc, char **argv ) bind_textdomain_codeset (PACKAGE_GT, "UTF-8"); #endif - if (!pipe_server && !is_daemon && !gpgconf_list) + if (!pipe_server && !is_daemon && !gpgconf_list && + fd_agent == GNUPG_INVALID_FD) { /* We have been called without any options and thus we merely check whether an agent is already running. We do this right @@ -1054,6 +1088,10 @@ main (int argc, char **argv ) agent_deinit_default_ctrl (ctrl); xfree (ctrl); } + else if (fd_agent != GNUPG_INVALID_FD) + { + handle_agent_socks(fd_agent, fd_ssh_agent); + } else if (!is_daemon) ; /* NOTREACHED */ else @@ -1238,26 +1276,8 @@ main (int argc, char **argv ) log_set_prefix (NULL, oldflags | JNLIB_LOG_RUN_DETACHED); opt.running_detached = 1; } - - if (chdir("/")) - { - log_error ("chdir to / failed: %s\n", strerror (errno)); - exit (1); - } - - { - struct sigaction sa; - - sa.sa_handler = SIG_IGN; - sigemptyset (&sa.sa_mask); - sa.sa_flags = 0; - sigaction (SIGPIPE, &sa, NULL); - } #endif /*!HAVE_W32_SYSTEM*/ - - log_info ("%s %s started\n", strusage(11), strusage(13) ); - handle_connections (fd, opt.ssh_support ? fd_ssh : GNUPG_INVALID_FD); - assuan_sock_close (fd); + handle_agent_socks(fd, opt.ssh_support ? fd_ssh : GNUPG_INVALID_FD); } return 0; diff --git a/doc/gpg-agent.texi b/doc/gpg-agent.texi index a4079d7..1556e54 100644 --- a/doc/gpg-agent.texi +++ b/doc/gpg-agent.texi @@ -43,7 +43,15 @@ .IR file ] .RI [ options ] .B \-\-daemon -.RI [ command_line ] +.br +.B gpg-agent +.RB [ \-\-homedir +.IR dir ] +.RB [ \-\-options +.IR file ] +.RI [ options ] +.B \-\-agent-fd +.IR fd @end ifset @mansect description @@ -186,6 +194,11 @@ Yet another way is creating a new process as a child of gpg-agent: @code{gpg-agent --daemon /bin/sh}. This way you get a new shell with the environment setup properly; if you exit from this shell, gpg-agent terminates as well. + +@item --agent-fd @var{fd} +@opindex agent-fd +Start the gpg-agent using @var{fd} as the listening socket. This is useful for +socket activation a la systemd and launchd. @end table @mansect options @@ -532,6 +545,12 @@ Ignore requests to change the current @code{tty} or X window system's @code{DISPLAY} variable respectively. This is useful to lock the pinentry to pop up at the @code{tty} or display you started the agent. +@item --ssh-agent-fd @var{fd} +@opindex ssh-agent-fd + +When starting the agent with @option{--agent-fd}, use this to pass in a socket +to be used for the OpenSSH agent protocol. + @anchor{option --enable-ssh-support} @item --enable-ssh-support @opindex enable-ssh-support