[Xfce4-commits] <xfce4-session:master> Restore ssh and gpg agent starting (bug #7018).

Nick Schermer noreply at xfce.org
Thu Apr 19 21:02:01 CEST 2012


Updating branch refs/heads/master
         to 79ab94111bf4a5508f0f9c47544075402b9f1890 (commit)
       from f955321a3996c69c65118fbe1964eda13af3f5f5 (commit)

commit 79ab94111bf4a5508f0f9c47544075402b9f1890
Author: Nick Schermer <nick at xfce.org>
Date:   Thu Apr 19 20:56:31 2012 +0200

    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.

 configure.in.in              |    2 +-
 xfce4-session/main.c         |    2 +
 xfce4-session/xfsm-startup.c |  223 +++++++++++++++++++++++++++++++++++++++++-
 xfce4-session/xfsm-startup.h |    1 +
 4 files changed, 222 insertions(+), 6 deletions(-)

diff --git a/configure.in.in b/configure.in.in
index 003efd1..2c7dd89 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 0ae376a..82dc1d4 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 0fdbcf5..b4fa780 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 38c0eae..03762e0 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);


More information about the Xfce4-commits mailing list