summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Schermer <nick@xfce.org>2012-04-19 20:56:31 +0200
committerNick Schermer <nick@xfce.org>2012-04-19 20:56:31 +0200
commit79ab94111bf4a5508f0f9c47544075402b9f1890 (patch)
treedbe720445d907d1dfce5c9d8ca784626d62bc197
parentf955321a3996c69c65118fbe1964eda13af3f5f5 (diff)
downloadxfce4-session-79ab94111bf4a5508f0f9c47544075402b9f1890.tar.gz
Restore ssh and gpg agent starting (bug #7018).
Because we cannot start anything before dbus is initialized (which has been removed from xinit to make startup better with consolekit), add it in the startup code. The agent is started and the variables returned by the process are loaded in the environment before other applications are started. The daemons are also closed if xfce4-session is terminated.
-rw-r--r--configure.in.in2
-rw-r--r--xfce4-session/main.c2
-rw-r--r--xfce4-session/xfsm-startup.c223
-rw-r--r--xfce4-session/xfsm-startup.h1
4 files changed, 222 insertions, 6 deletions
diff --git a/configure.in.in b/configure.in.in
index 003efd17..2c7dd89a 100644
--- a/configure.in.in
+++ b/configure.in.in
@@ -63,7 +63,7 @@ AC_HEADER_STDC
AC_CHECK_HEADERS([asm/unistd.h errno.h fcntl.h limits.h \
netdb.h pwd.h signal.h stdarg.h sys/param.h sys/resource.h \
sys/socket.h sys/time.h sys/wait.h sys/utsname.h time.h \
- unistd.h sys/param.h sys/user.h sys/sysctl.h math.h])
+ unistd.h sys/param.h sys/user.h sys/sysctl.h math.h sys/types.h])
AC_CHECK_FUNCS([getaddrinfo gethostbyname gethostname getpwuid setsid \
sigaction strdup sync vfork])
diff --git a/xfce4-session/main.c b/xfce4-session/main.c
index 0ae376a4..82dc1d43 100644
--- a/xfce4-session/main.c
+++ b/xfce4-session/main.c
@@ -307,6 +307,8 @@ main (int argc, char **argv)
gtk_main ();
+ xfsm_startup_shutdown ();
+
shutdown_type = xfsm_manager_get_shutdown_type (manager);
/* take over the ref before we release the manager */
diff --git a/xfce4-session/xfsm-startup.c b/xfce4-session/xfsm-startup.c
index 0fdbcf58..b4fa780a 100644
--- a/xfce4-session/xfsm-startup.c
+++ b/xfce4-session/xfsm-startup.c
@@ -30,7 +30,9 @@
#ifdef HAVE_MEMORY_H
#include <memory.h>
#endif
+#ifdef HAVE_STDIO_H
#include <stdio.h>
+#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
@@ -43,6 +45,12 @@
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif
#include <glib/gstdio.h>
#include <gdk/gdkx.h>
@@ -65,10 +73,6 @@ typedef struct
XfsmProperties *properties;
} XfsmStartupData;
-
-/*
- Prototypes
- */
static void xfsm_startup_failsafe (XfsmManager *manager);
static gboolean xfsm_startup_session_next_prio_group (XfsmManager *manager);
@@ -82,10 +86,219 @@ static gboolean xfsm_startup_timeout (gpointer data);
static void xfsm_startup_handle_failed_startup (XfsmProperties *properties,
XfsmManager *manager);
+
+static gchar *running_sshagent = NULL;
+
+
+
+static void
+xfsm_startup_init_sshagent (const gchar *cmd,
+ const gchar *agent)
+{
+ gchar *stdout = NULL;
+ GError *error = NULL;
+ gchar **lines;
+ guint i;
+ gchar *p, *t;
+ gchar *variable, *value;
+
+ if (g_spawn_command_line_sync (cmd, &stdout, NULL, NULL, &error))
+ {
+ if (G_UNLIKELY (stdout == NULL))
+ {
+ g_message ("%s returned no variables to stdout", agent);
+ return;
+ }
+
+ lines = g_strsplit (stdout, "\n", -1);
+ g_assert (lines != NULL);
+ for (i = 0; lines[i] != NULL; i++)
+ {
+ p = strchr (lines[i], '=');
+ if (G_UNLIKELY (p == NULL))
+ continue;
+ t = strchr (p + 1, ';');
+ if (G_UNLIKELY (t == NULL))
+ continue;
+
+ variable = g_strndup (lines[i], p - lines[i]);
+ value = g_strndup (p + 1, t - p - 1);
+
+ g_setenv (variable, value, TRUE);
+
+ g_free (variable);
+ g_free (value);
+ }
+ g_strfreev (lines);
+
+ /* keep this around for shutdown */
+ running_sshagent = g_strdup (agent);
+ }
+ else
+ {
+ g_warning ("Failed to spawn %s: %s", agent, error->message);
+ g_error_free (error);
+ }
+
+ g_free (stdout);
+}
+
+
void
xfsm_startup_init (XfconfChannel *channel)
{
- /* nothing to be done here, currently */
+ gchar *agent;
+ gchar *path = NULL;
+ gchar *envfile;
+ gchar *cmd;
+ const gchar *ssh_agent_pid;
+ pid_t pid;
+
+ if (xfconf_channel_get_bool (channel, "/startup/ssh-agent/enabled", TRUE))
+ {
+ agent = xfconf_channel_get_string (channel, "/startup/ssh-agent/type", NULL);
+ if (g_strcmp0 (agent, "gpg-agent") == 0
+ || g_strcmp0 (agent, "ssh-agent") == 0)
+ {
+ path = g_find_program_in_path (agent);
+ }
+ else if (agent == NULL)
+ {
+ /* lookup gpg- or ssh-agent */
+ path = g_find_program_in_path ("gpg-agent");
+ if (G_UNLIKELY (path != NULL))
+ {
+ agent = g_strdup ("gpg-agent");
+ }
+ else
+ {
+ path = g_find_program_in_path ("ssh-agent");
+ if (path != NULL)
+ agent = g_strdup ("ssh-agent");
+ }
+ }
+ else
+ {
+ g_message ("Unknown authentication agent \"%s\" set", agent);
+
+ /* avoid more errors */
+ g_free (agent);
+ return;
+ }
+
+ if (G_LIKELY (path != NULL))
+ {
+ ssh_agent_pid = g_getenv ("SSH_AGENT_PID");
+ if (ssh_agent_pid != NULL && *ssh_agent_pid == '\0')
+ ssh_agent_pid = NULL;
+
+ if (ssh_agent_pid != NULL)
+ {
+ /* check if the pid is still responding (ie not stale) */
+ pid = atoi (ssh_agent_pid);
+ if (pid > 0 && kill (pid, 0) != 0)
+ {
+ g_unsetenv ("SSH_AGENT_PID");
+ g_unsetenv ("SSH_AUTH_SOCK");
+
+ ssh_agent_pid = NULL;
+ }
+ }
+
+ if (g_strcmp0 (agent, "gpg-agent") == 0)
+ {
+ envfile = xfce_resource_lookup (XFCE_RESOURCE_CACHE, "gpg-agent-info");
+
+ if (ssh_agent_pid == NULL)
+ {
+ cmd = g_strdup_printf ("%s --sh --daemon --enable-ssh-support "
+ "--write-env-file '%s'", path, envfile);
+ xfsm_startup_init_sshagent (cmd, agent);
+ g_free (cmd);
+ }
+ else if (g_getenv ("GPG_AGENT_INFO") == NULL)
+ {
+ g_message ("ssh-agent is already running; starting gpg-agent without ssh support");
+ cmd = g_strdup_printf ("%s --sh --daemon --write-env-file '%s'", path, envfile);
+ xfsm_startup_init_sshagent (cmd, agent);
+ g_free (cmd);
+ }
+ else
+ {
+ g_message ("%s is already running", agent);
+ }
+
+ g_free (envfile);
+ }
+ else if (g_strcmp0 (agent, "ssh-agent") == 0)
+ {
+ if (ssh_agent_pid == NULL)
+ {
+ cmd = g_strdup_printf ("%s -s", path);
+ xfsm_startup_init_sshagent (cmd, agent);
+ g_free (cmd);
+ }
+ else
+ {
+ g_message ("%s is already running", agent);
+ }
+ }
+ }
+ else
+ {
+ g_printerr ("xfce4-session: %s\n",
+ "No gpg or ssh authentication agent found");
+ }
+
+ g_free (agent);
+ g_free (path);
+ }
+}
+
+
+void
+xfsm_startup_shutdown (void)
+{
+ gchar *envfile;
+ const gchar *agentpid;
+ pid_t pid;
+ gboolean is_gpg_agent;
+
+ if (running_sshagent == NULL)
+ return;
+
+ agentpid = g_getenv ("SSH_AGENT_PID");
+ if (G_UNLIKELY (agentpid == NULL))
+ {
+ g_warning ("%s was started, but SSH_AGENT_PID is not set, nothing to kill", running_sshagent);
+ }
+ else
+ {
+ is_gpg_agent = g_strcmp0 (running_sshagent, "gpg-agent") == 0;
+
+ /* kill the process (gpg-agent uses SIGINT, ssh-agent SIGTERM) */
+ pid = atoi (agentpid);
+ if (pid < 1
+ || kill (pid, is_gpg_agent ? SIGINT : SIGTERM) != 0)
+ {
+ g_warning ("Failed to kill %s with pid %s", running_sshagent, agentpid);
+ }
+
+ /* drop the info file from gpg-agent */
+ if (is_gpg_agent)
+ {
+ envfile = xfce_resource_lookup (XFCE_RESOURCE_CACHE, "gpg-agent-info");
+ if (G_LIKELY (envfile != NULL))
+ g_unlink (envfile);
+ g_free (envfile);
+ }
+ }
+
+ /* make sure the env values are unset */
+ g_unsetenv ("SSH_AGENT_PID");
+ g_unsetenv ("SSH_AUTH_SOCK");
+
+ g_free (running_sshagent);
}
diff --git a/xfce4-session/xfsm-startup.h b/xfce4-session/xfsm-startup.h
index 38c0eae4..03762e06 100644
--- a/xfce4-session/xfsm-startup.h
+++ b/xfce4-session/xfsm-startup.h
@@ -27,6 +27,7 @@
#include <libxfce4util/libxfce4util.h>
void xfsm_startup_init (XfconfChannel *channel);
+void xfsm_startup_shutdown (void);
void xfsm_startup_foreign (XfsmManager *manager);
void xfsm_startup_begin (XfsmManager *manager);
void xfsm_startup_session_continue (XfsmManager *manager);