[gnome-keyring] [daemon] Use new control protocol for daemon.



commit 8919b91a25d29bd74b079ab169d0fb174786a16d
Author: Stef Walter <stef memberwebs com>
Date:   Wed Dec 16 00:40:27 2009 +0000

    [daemon] Use new control protocol for daemon.
    
    Test new control protocol, and use in pam and startup. Refactor
    the names of some of the daemon files.

 daemon/Makefile.am                  |    4 +-
 daemon/control/Makefile.am          |    1 +
 daemon/control/gkd-control.c        |  267 +++++++++++++++++++--
 daemon/control/gkd-control.h        |    4 +-
 daemon/dbus/gkd-dbus-environment.c  |    5 +-
 daemon/dbus/gkd-dbus-service.c      |    5 +-
 daemon/dbus/gkd-dbus-session.c      |    7 +-
 daemon/{gkr-daemon.c => gkd-main.c} |  457 +++++++++++++++--------------------
 daemon/gkd-main.h                   |   31 +++
 daemon/gkd-util.c                   |  209 ++++++++++++++++
 daemon/gkd-util.h                   |   46 ++++
 daemon/gkr-daemon-io.c              |   14 +-
 daemon/gkr-daemon-ops.c             |    7 +-
 daemon/gkr-daemon.h                 |    4 -
 daemon/pkcs11/gkr-pkcs11-daemon.c   |    8 +-
 daemon/util/gkr-daemon-util.c       |  105 --------
 daemon/util/gkr-daemon-util.h       |    8 -
 pam/gkr-pam-client.c                |   51 ++--
 pam/gkr-pam-module.c                |   58 +++---
 pam/tests/unit-test-pam.c           |    6 +-
 pkcs11/rpc-layer/gck-rpc-dispatch.c |    2 +-
 pkcs11/rpc-layer/gck-rpc-module.c   |    6 +-
 pkcs11/ssh-agent/gck-ssh-agent.c    |    2 +-
 23 files changed, 814 insertions(+), 493 deletions(-)
---
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index 73d81ee..cc818f0 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -26,7 +26,8 @@ INCLUDES=	\
 	$(GLIB_CFLAGS)
 
 gnome_keyring_daemon_SOURCES = \
-	gkr-daemon.c gkr-daemon.h \
+	gkd-main.c gkd-main.h \
+	gkd-util.c gkd-util.h \
 	gkr-daemon-io.c \
 	gkr-daemon-ops.c
 
@@ -35,6 +36,7 @@ gnome_keyring_daemon_LDADD = \
 	$(top_builddir)/daemon/dbus/libgkr-dbus.la \
 	$(top_builddir)/daemon/keyrings/libgkr-keyrings.la \
 	$(top_builddir)/daemon/ui/libgkr-ui.la \
+	$(top_builddir)/daemon/control/libgkd-control.la \
 	$(top_builddir)/daemon/prompt/libgkd-prompt.la \
 	$(top_builddir)/daemon/util/libgkr-daemon-util.la \
 	$(top_builddir)/library/libgnome-keyring-common.la \
diff --git a/daemon/control/Makefile.am b/daemon/control/Makefile.am
index 166505b..e189c5a 100644
--- a/daemon/control/Makefile.am
+++ b/daemon/control/Makefile.am
@@ -5,6 +5,7 @@ INCLUDES= \
 	-DLIBEXECDIR=\""$(libexecdir)"\" \
 	-DGNOMELOCALEDIR=\""$(datadir)/locale"\" \
 	-I$(top_srcdir) \
+	-I$(top_srcdir)/daemon \
 	-I$(top_builddir) \
 	$(GLIB_CFLAGS)
 
diff --git a/daemon/control/gkd-control.c b/daemon/control/gkd-control.c
index db22625..f01c483 100644
--- a/daemon/control/gkd-control.c
+++ b/daemon/control/gkd-control.c
@@ -22,6 +22,8 @@
 #include "config.h"
 
 #include "gkd-control.h"
+#include "gkd-main.h"
+#include "gkd-util.h"
 
 #include "egg/egg-buffer.h"
 #include "egg/egg-cleanup.h"
@@ -86,6 +88,10 @@ enum {
 	GNOME_KEYRING_RESULT_NO_MATCH
 };
 
+/* -----------------------------------------------------------------------------------
+ * CONTROL SERVER
+ */
+
 static ControlData*
 control_data_new (void)
 {
@@ -172,18 +178,37 @@ control_change_keyring_password (EggBuffer *buffer)
 static guint32
 control_prepare_environment (EggBuffer *buffer)
 {
-	gchar **environment;
-	guint32 res;
+	gchar **environment, **e;
 	gsize offset = 8;
+	gchar *x;
+	int i;
 
 	if (!egg_buffer_get_stringv (buffer, offset, &offset, &environment, g_realloc))
 		return GNOME_KEYRING_RESULT_BAD_ARGUMENTS;
 
-	/* TODO: Prepare the environment */
-	res = GNOME_KEYRING_RESULT_DENIED;
+	/* Accept environment from outside */
+	for (e = environment; *e; ++e) {
+		x = strchr (*e, '=');
+		if (x) {
+			*(x++) = 0;
+			/* We're only interested in these environment variables */
+			for (i = 0; GKD_UTIL_IN_ENVIRONMENT[i] != NULL; ++i) {
+				if (g_str_equal (*e, GKD_UTIL_IN_ENVIRONMENT[i])) {
+					g_setenv (*e, x, FALSE);
+					break;
+				}
+			}
+		}
+	}
 
 	g_strfreev (environment);
-	return res;
+
+	/*
+	 * We've now definitely received everything we need to run. Ask
+	 * the daemon to complete the initialization.
+	 */
+	gkd_main_complete_initialization ();
+	return GNOME_KEYRING_RESULT_OK;
 }
 
 static gboolean
@@ -230,21 +255,21 @@ control_process (EggBuffer *req, GIOChannel *channel)
 	case GNOME_KEYRING_OP_UNLOCK_KEYRING:
 		res = control_unlock_keyring (req);
 		cdata = control_data_new ();
-		egg_buffer_add_uint32 (&cdata->buffer, 4);
+		egg_buffer_add_uint32 (&cdata->buffer, 0);
 		egg_buffer_add_uint32 (&cdata->buffer, res);
 		break;
 	case GNOME_KEYRING_OP_CHANGE_KEYRING_PASSWORD:
 		res = control_change_keyring_password (req);
 		cdata = control_data_new ();
-		egg_buffer_add_uint32 (&cdata->buffer, 4);
+		egg_buffer_add_uint32 (&cdata->buffer, 0);
 		egg_buffer_add_uint32 (&cdata->buffer, res);
 		break;
 	case GNOME_KEYRING_OP_PREPARE_ENVIRONMENT:
 		res = control_prepare_environment (req);
 		cdata = control_data_new ();
-		egg_buffer_add_uint32 (&cdata->buffer, 8);
-		egg_buffer_add_uint32 (&cdata->buffer, res);
 		egg_buffer_add_uint32 (&cdata->buffer, 0);
+		egg_buffer_add_uint32 (&cdata->buffer, res);
+		egg_buffer_add_stringv (&cdata->buffer, gkd_util_get_environment ());
 		break;
 	default:
 		g_message ("received unsupported request operation on control socket: %d", (int)op);
@@ -252,6 +277,8 @@ control_process (EggBuffer *req, GIOChannel *channel)
 	}
 
 	if (cdata) {
+		g_return_if_fail (!egg_buffer_has_error (&cdata->buffer));
+		egg_buffer_set_uint32 (&cdata->buffer, 0, cdata->buffer.len);
 		g_io_add_watch_full (channel, G_PRIORITY_DEFAULT, G_IO_OUT | G_IO_HUP,
 		                     control_output, cdata, control_data_free);
 	}
@@ -278,7 +305,7 @@ control_input (GIOChannel *channel, GIOCondition cond, gpointer user_data)
 				if (errno != EAGAIN || errno != EINTR)
 					finished = TRUE;
 			} else if (getuid () != uid) {
-				g_warning ("uid mismatch: %u, should be %u\n", uid, getuid ());
+				g_message ("control request from bad uid: %u, should be %u\n", uid, getuid ());
 				finished = TRUE;
 			} else {
 				cdata->position = 1;
@@ -298,7 +325,7 @@ control_input (GIOChannel *channel, GIOCondition cond, gpointer user_data)
 		/* Time for reading the packet */
 		} else {
 			if (!egg_buffer_get_uint32 (buffer, 0, NULL, &packet_size) || packet_size < 4) {
-				g_warning ("invalid packet size from client");
+				g_message ("invalid packet size in control request");
 				finished = TRUE;
 			} else {
 				g_assert (buffer->len < packet_size);
@@ -342,19 +369,19 @@ control_accept (GIOChannel *channel, GIOCondition cond, gpointer callback_data)
 	addrlen = sizeof (addr);
 	new_fd = accept (fd, (struct sockaddr *) &addr, &addrlen);
 	if (new_fd < 0) {
-		g_warning ("couldn't accept new connection: %s", g_strerror (errno));
+		g_warning ("couldn't accept new control request: %s", g_strerror (errno));
 		return TRUE;
 	}
 
 	val = fcntl (new_fd, F_GETFL, 0);
 	if (val < 0) {
-		g_warning ("can't get client fd flags: %s", g_strerror (errno));
+		g_warning ("can't get control request fd flags: %s", g_strerror (errno));
 		close (new_fd);
 		return TRUE;
 	}
 
 	if (fcntl (new_fd, F_SETFL, val | O_NONBLOCK) < 0) {
-		g_warning ("can't set client to non-blocking io: %s", g_strerror (errno));
+		g_warning ("can't set control request to non-blocking io: %s", g_strerror (errno));
 		close (new_fd);
 		return TRUE;
 	}
@@ -378,20 +405,17 @@ control_cleanup_channel (gpointer user_data)
 }
 
 gboolean
-gkd_control_initialize (const gchar *directory)
+gkd_control_listen (void)
 {
 	struct sockaddr_un addr;
 	GIOChannel *channel;
 	gchar *path;
 	int sock;
 
-	path = g_strdup_printf ("%s/socket", directory);
+	path = g_strdup_printf ("%s/control", gkd_util_get_master_directory ());
 	egg_cleanup_register (control_cleanup_channel, path);
 
-#ifdef WITH_TESTS
-	if (g_getenv ("GNOME_KEYRING_TEST_PATH"))
-		unlink (path);
-#endif
+	unlink (path);
 
 	sock = socket (AF_UNIX, SOCK_STREAM, 0);
 	if (sock < 0) {
@@ -403,18 +427,18 @@ gkd_control_initialize (const gchar *directory)
 	addr.sun_family = AF_UNIX;
 	g_strlcpy (addr.sun_path, path, sizeof (addr.sun_path));
 	if (bind (sock, (struct sockaddr*) &addr, sizeof (addr)) < 0) {
-		g_warning ("couldn't bind to socket: %s: %s", path, g_strerror (errno));
+		g_warning ("couldn't bind to control socket: %s: %s", path, g_strerror (errno));
 		close (sock);
 		return FALSE;
 	}
 
 	if (listen (sock, 128) < 0) {
-		g_warning ("couldn't listen on socket: %s: %s", path, g_strerror (errno));
+		g_warning ("couldn't listen on control socket: %s: %s", path, g_strerror (errno));
 		close (sock);
 		return FALSE;
 	}
 
-	if (!egg_unix_credentials_setup (sock)) {
+	if (!egg_unix_credentials_setup (sock) < 0) {
 		close (sock);
 		return FALSE;
 	}
@@ -426,3 +450,200 @@ gkd_control_initialize (const gchar *directory)
 
 	return TRUE;
 }
+
+/* -----------------------------------------------------------------------------------
+ * CONTROL CLIENT
+ */
+
+static int
+control_connect (const gchar *path)
+{
+	struct sockaddr_un addr;
+	struct stat st;
+	int sock;
+
+	/* First a bunch of checks to make sure nothing funny is going on */
+	if (lstat (path, &st) < 0) {
+		g_message ("couldn't access conrol socket: %s: %s", path, g_strerror (errno));
+		return -1;
+
+	} else if (st.st_uid != geteuid ()) {
+		g_message("The control socket is not owned with the same "
+		          "credentials as the user login: %s", path);
+		return -1;
+
+	} else if (S_ISLNK (st.st_mode) || !S_ISSOCK (st.st_mode)) {
+		g_message ("The control socket is not a valid simple non-linked socket");
+		return -1;
+	}
+
+	addr.sun_family = AF_UNIX;
+	g_strlcpy (addr.sun_path, path, sizeof (addr.sun_path));
+
+	/* Now we connect */
+	sock = socket (AF_UNIX, SOCK_STREAM, 0);
+	if (sock < 0) {
+		g_warning ("couldn't create control socket: %s", g_strerror (errno));
+		return -1;
+	}
+
+	/* Close on exec */
+	fcntl (sock, F_SETFD, 1);
+
+	if (connect (sock, (struct sockaddr*) &addr, sizeof (addr)) < 0) {
+		g_message ("couldn't connect to control socket at: %s: %s",
+		           addr.sun_path, g_strerror (errno));
+		close (sock);
+		return -1;
+	}
+
+	/* This lets the server verify us */
+	for (;;) {
+		if (egg_unix_credentials_write (sock) < 0) {
+			if (errno == EINTR || errno == EAGAIN)
+				continue;
+			g_message ("couldn't send credentials to control socket: %s",
+			           g_strerror (errno));
+			close (sock);
+			return -1;
+		}
+
+		return sock;
+	}
+}
+
+static gboolean
+control_write (int fd, EggBuffer *buf)
+{
+	gsize bytes = 0;
+	gssize res;
+
+	while (bytes < buf->len) {
+		res = write (fd, buf->buf + bytes, buf->len - bytes);
+		if (res < 0) {
+			if (errno != EINTR && errno != EAGAIN) {
+				g_warning ("couldn't write all bytes to control socket: %s",
+				           g_strerror (errno));
+				return FALSE;
+			}
+		} else {
+			bytes += res;
+		}
+	}
+
+	return TRUE;
+}
+
+static gsize
+control_read_raw (int fd, guchar *buf, size_t len)
+{
+	gsize bytes;
+	gssize res;
+
+	bytes = 0;
+	while (bytes < len) {
+		res = read (fd, buf + bytes, len - bytes);
+		if (res <= 0) {
+			if (res == 0)
+				res = -1;
+			else if (errno == EAGAIN)
+				continue;
+			else
+				g_warning ("couldn't read %u bytes from control socket: %s",
+					   (unsigned int)len, g_strerror (errno));
+			return res;
+		}
+		bytes += res;
+	}
+	return bytes;
+}
+
+
+static gboolean
+control_read (int fd, EggBuffer *buffer)
+{
+	guint32 packet_size;
+
+	egg_buffer_resize (buffer, 4);
+	if (control_read_raw (fd, buffer->buf, 4) != 4)
+		return FALSE;
+
+	if (!egg_buffer_get_uint32 (buffer, 0, NULL, &packet_size) ||
+	    packet_size < 4)
+		return FALSE;
+
+	egg_buffer_resize (buffer, packet_size);
+	if (control_read_raw (fd, buffer->buf + 4, packet_size - 4) != packet_size - 4)
+		return FALSE;
+
+	return TRUE;
+}
+
+static gboolean
+control_chat (int sock)
+{
+	gchar **envp, **e;
+	EggBuffer buffer;
+	gsize offset;
+	gboolean ret;
+	guint32 res;
+
+	envp = gkd_util_build_environment (GKD_UTIL_IN_ENVIRONMENT);
+
+	egg_buffer_init_full (&buffer, 128, g_realloc);
+	egg_buffer_add_uint32 (&buffer, 0);
+	egg_buffer_add_uint32 (&buffer, GNOME_KEYRING_OP_PREPARE_ENVIRONMENT);
+	egg_buffer_add_stringv (&buffer, (const char**)envp);
+	egg_buffer_set_uint32 (&buffer, 0, buffer.len);
+
+	g_strfreev (envp);
+
+	g_return_val_if_fail (!egg_buffer_has_error (&buffer), FALSE);
+
+	envp = NULL;
+
+	ret = control_write (sock, &buffer) &&
+	      control_read (sock, &buffer);
+
+	offset = 4;
+	if (ret)
+		ret = egg_buffer_get_uint32 (&buffer, offset, &offset, &res);
+	if (ret && res == GNOME_KEYRING_RESULT_OK)
+	      egg_buffer_get_stringv (&buffer, offset, &offset, &envp, g_realloc);
+
+	egg_buffer_uninit (&buffer);
+
+	if (!ret || res != GNOME_KEYRING_RESULT_OK) {
+		g_message ("couldn't initialize running daemon");
+		return FALSE;
+	}
+
+	g_return_val_if_fail (envp, FALSE);
+	for (e = envp; *e; ++e)
+		gkd_util_push_environment_full (*e);
+	g_strfreev (envp);
+
+	return TRUE;
+}
+
+gboolean
+gkd_control_initialize (const gchar *directory)
+{
+	gboolean ret;
+	gchar *path;
+	int sock;
+
+	g_return_val_if_fail (directory, FALSE);
+
+	path = g_strdup_printf ("%s/control", directory);
+	sock = control_connect (path);
+	g_free (path);
+
+	if (sock < 0)
+		return FALSE;
+
+	ret = control_chat (sock);
+
+	close (sock);
+	return ret;
+}
diff --git a/daemon/control/gkd-control.h b/daemon/control/gkd-control.h
index 09c1aa4..84249db 100644
--- a/daemon/control/gkd-control.h
+++ b/daemon/control/gkd-control.h
@@ -24,6 +24,8 @@
 
 #include <glib.h>
 
-gboolean gkd_control_initialize (const gchar *directory);
+gboolean          gkd_control_listen        (void);
+
+gboolean          gkd_control_initialize    (const gchar *directory);
 
 #endif /* __GKD_CONTROL_H__ */
diff --git a/daemon/dbus/gkd-dbus-environment.c b/daemon/dbus/gkd-dbus-environment.c
index bac3d37..3513e31 100644
--- a/daemon/dbus/gkd-dbus-environment.c
+++ b/daemon/dbus/gkd-dbus-environment.c
@@ -24,8 +24,7 @@
 #include "config.h"
 
 #include "gkd-dbus-private.h"
-
-#include "util/gkr-daemon-util.h"
+#include "gkd-util.h"
 
 #include <dbus/dbus.h>
 
@@ -73,7 +72,7 @@ gkd_dbus_environment_init (DBusConnection *conn)
 	 * The list of all environment variables registered by
 	 * various components in the daemon.
 	 */
-	envp = gkr_daemon_util_get_environment ();
+	envp = gkd_util_get_environment ();
 
 	for (; *envp; ++envp) {
 
diff --git a/daemon/dbus/gkd-dbus-service.c b/daemon/dbus/gkd-dbus-service.c
index 601dfda..c076152 100644
--- a/daemon/dbus/gkd-dbus-service.c
+++ b/daemon/dbus/gkd-dbus-service.c
@@ -24,9 +24,8 @@
 #include "config.h"
 
 #include "gkd-dbus-private.h"
-
+#include "gkd-util.h"
 #include "gkr-daemon.h"
-#include "util/gkr-daemon-util.h"
 
 #include <dbus/dbus.h>
 
@@ -71,7 +70,7 @@ message_handler_cb (DBusConnection *conn, DBusMessage *message, void *user_data)
 		DBusMessageIter items, entry;
 		gchar **parts;
 
-		env = gkr_daemon_util_get_environment ();
+		env = gkd_util_get_environment ();
 		g_return_val_if_fail (env, DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
 
 		/* Setup the result */
diff --git a/daemon/dbus/gkd-dbus-session.c b/daemon/dbus/gkd-dbus-session.c
index 2370999..b904486 100644
--- a/daemon/dbus/gkd-dbus-session.c
+++ b/daemon/dbus/gkd-dbus-session.c
@@ -24,8 +24,7 @@
 #include "config.h"
 
 #include "gkd-dbus-private.h"
-
-#include "gkr-daemon.h"
+#include "gkd-main.h"
 
 #include <dbus/dbus.h>
 
@@ -121,7 +120,7 @@ signal_filter (DBusConnection *conn, DBusMessage *msg, void *user_data)
 	/* Quit the daemon when the session is over */
 	if (dbus_message_is_signal (msg, IFACE_SESSION_PRIVATE, "Stop")) {
 		unregister_daemon_in_session (conn);
-		gkr_daemon_quit ();
+		gkd_main_quit ();
 		return DBUS_HANDLER_RESULT_HANDLED;
 	} else if (dbus_message_is_signal (msg, IFACE_SESSION_PRIVATE, "QueryEndSession")) {
 		send_end_session_response (conn);
@@ -129,7 +128,7 @@ signal_filter (DBusConnection *conn, DBusMessage *msg, void *user_data)
 	} else if (dbus_message_is_signal (msg, IFACE_SESSION_PRIVATE, "EndSession")) {
 		send_end_session_response (conn);
 		unregister_daemon_in_session (conn);
-		gkr_daemon_quit ();
+		gkd_main_quit ();
 		return DBUS_HANDLER_RESULT_HANDLED;
 	}
 
diff --git a/daemon/gkr-daemon.c b/daemon/gkd-main.c
similarity index 73%
rename from daemon/gkr-daemon.c
rename to daemon/gkd-main.c
index affac8a..1d17458 100644
--- a/daemon/gkr-daemon.c
+++ b/daemon/gkd-main.c
@@ -7,23 +7,28 @@
    modify it under the terms of the GNU General Public License as
    published by the Free Software Foundation; either version 2 of the
    License, or (at your option) any later version.
-  
+
    Gnome keyring is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    General Public License for more details.
-  
+
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
    Author: Alexander Larsson <alexl redhat com>
+   Author: Stef Walter <stef memberwebs com>
 */
 
 #include "config.h"
 
+#include "gkd-main.h"
+#include "gkd-util.h"
 #include "gkr-daemon.h"
 
+#include "control/gkd-control.h"
+
 #include "dbus/gkd-dbus.h"
 
 #include "egg/egg-cleanup.h"
@@ -40,11 +45,9 @@
 #include "ui/gkr-ask-daemon.h"
 
 #include "util/gkr-daemon-async.h"
-#include "util/gkr-daemon-util.h"
 
-#include <unistd.h>
-#include <fcntl.h>
 #include <errno.h>
+#include <fcntl.h>
 #include <pthread.h>
 #include <stdlib.h>
 #include <stdio.h>
@@ -52,6 +55,8 @@
 #include <signal.h>
 #include <locale.h>
 #include <syslog.h>
+#include <unistd.h>
+
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/un.h>
@@ -92,21 +97,24 @@ static gboolean run_for_login = FALSE;
 static gboolean run_for_start = FALSE;
 static gchar* run_components = NULL;
 static gchar* login_password = NULL;
+static const gchar* control_directory = NULL;
 static gboolean initialization_completed = FALSE;
 static gboolean sig_thread_valid = FALSE;
 static pthread_t sig_thread;
 
 static GOptionEntry option_entries[] = {
-	{ "foreground", 'f', 0, G_OPTION_ARG_NONE, &run_foreground, 
-	  "Run in the foreground", NULL }, 
-	{ "daemonize", 'd', 0, G_OPTION_ARG_NONE, &run_daemonized, 
-	  "Run as a daemon", NULL }, 
-	{ "login", 'l', 0, G_OPTION_ARG_NONE, &run_for_login, 
+	{ "foreground", 'f', 0, G_OPTION_ARG_NONE, &run_foreground,
+	  "Run in the foreground", NULL },
+	{ "daemonize", 'd', 0, G_OPTION_ARG_NONE, &run_daemonized,
+	  "Run as a daemon", NULL },
+	{ "login", 'l', 0, G_OPTION_ARG_NONE, &run_for_login,
 	  "Run for a user login. Read login password from stdin", NULL },
 	{ "start", 's', 0, G_OPTION_ARG_NONE, &run_for_start,
 	  "Start a dameon or initialize an already running daemon." },
 	{ "components", 'c', 0, G_OPTION_ARG_STRING, &run_components,
 	  "The optional components to run", DEFAULT_COMPONENTS },
+	{ "control-directory", 'l', 0, G_OPTION_ARG_FILENAME, &control_directory,
+	  "The directory for sockets and control data", NULL },
 	{ NULL }
 };
 
@@ -115,28 +123,27 @@ parse_arguments (int *argc, char** argv[])
 {
 	GError *err = NULL;
 	GOptionContext *context;
-	
+
 	context = g_option_context_new ("- The Gnome Keyring Daemon");
 	g_option_context_add_main_entries (context, option_entries, GETTEXT_PACKAGE);
-	
+
 	if (!g_option_context_parse (context, argc, argv, &err)) {
 		g_printerr ("gnome-keyring-daemon: %s", err && err->message ? err->message : "");
 		g_clear_error (&err);
 	}
-	
+
 	/* Take ownership of the string */
 	if (run_components) {
 		run_components = g_strdup (run_components);
 		egg_cleanup_register (g_free, run_components);
 	}
-	
+
 	/* Check the arguments */
 	if (run_for_login && run_for_start) {
 		g_printerr ("gnome-keyring-daemon: The --start option is incompatible with --login");
 		run_for_login = FALSE;
 	}
-		
-	
+
 	g_option_context_free (context);
 }
 
@@ -146,37 +153,37 @@ check_conf_component (const gchar* component, gboolean *enabled)
 	GConfClient *client;
 	GConfValue *value;
 	GError *err = NULL;
-	gchar *key; 
+	gchar *key;
 
 	*enabled = FALSE;
 
 	client = gconf_client_get_default ();
 	g_return_val_if_fail (client, FALSE);
-	
+
 	key = g_strdup_printf ("/apps/gnome-keyring/daemon-components/%s", component);
 	value = gconf_client_get (client, key, &err);
 	g_free (key);
 	g_object_unref (client);
-	
+
 	if (err) {
-		g_printerr ("gnome-keyring-daemon: couldn't lookup %s component setting: %s", 
+		g_printerr ("gnome-keyring-daemon: couldn't lookup %s component setting: %s",
 		            component, err->message ? err->message : "");
 		g_clear_error (&err);
 		return FALSE;
 	}
-	
+
 	/* Value is unset */
 	if (!value)
-		return FALSE;		
-	
+		return FALSE;
+
 	/* Should be a list of type string */
 	if (value->type != GCONF_VALUE_BOOL) {
-	    	g_printerr ("gnome-keyring-daemon: bad gconf value type for daemon-components");
-	    	g_clear_error (&err);
-	    	gconf_value_free (value);
-	    	return FALSE;
+		g_printerr ("gnome-keyring-daemon: bad gconf value type for daemon-components");
+		g_clear_error (&err);
+		gconf_value_free (value);
+		return FALSE;
 	}
-	
+
 	*enabled = gconf_value_get_bool (value);
 	gconf_value_free (value);
 	return TRUE;
@@ -190,16 +197,16 @@ check_run_component (const char* component)
 
 	if (run == NULL) {
 
-		/* Use gconf to determine whether the component should be enabled */	
+		/* Use gconf to determine whether the component should be enabled */
 		if (check_conf_component (component, &enabled))
 			return enabled;
-			
+
 		/* No gconf, error or unset, use built in defaults */
 		run = DEFAULT_COMPONENTS;
 	}
-	
-	/* 
-	 * Note that this assumes that no components are substrings of 
+
+	/*
+	 * Note that this assumes that no components are substrings of
 	 * one another. Which makes things quick, and simple.
 	 */
 	return strstr (run, component) ? TRUE : FALSE;
@@ -211,16 +218,16 @@ check_run_component (const char* component)
 
 static gboolean do_warning = TRUE;
 #define WARNING  "couldn't allocate secure memory to keep passwords " \
-		 "and or keys from being written to the disk"
-		 
+                 "and or keys from being written to the disk"
+
 #define ABORTMSG "The GNOME_KEYRING_PARANOID environment variable was set. " \
                  "Exiting..."
 
 
-/* 
+/*
  * These are called from gkr-secure-memory.c to provide appropriate
  * locking for memory between threads
- */ 
+ */
 
 void
 egg_memory_lock (void)
@@ -228,7 +235,7 @@ egg_memory_lock (void)
 	/* The daemon uses cooperative threading, and doesn't need locking */
 }
 
-void 
+void
 egg_memory_unlock (void)
 {
 	/* The daemon uses cooperative threading, and doesn't need locking */
@@ -238,35 +245,35 @@ void*
 egg_memory_fallback (void *p, size_t sz)
 {
 	const gchar *env;
-	
+
 	/* We were asked to free memory */
 	if (!sz) {
 		g_free (p);
 		return NULL;
 	}
-	
+
 	/* We were asked to allocate */
 	if (!p) {
 		if (do_warning) {
 			g_message (WARNING);
 			do_warning = FALSE;
 		}
-		
+
 		env = g_getenv ("GNOME_KEYRING_PARANOID");
-		if (env && *env) 
+		if (env && *env)
 			g_error (ABORTMSG);
-			
+
 		return g_malloc0 (sz);
 	}
-	
-	/* 
-	 * Reallocation is a bit of a gray area, as we can be asked 
-	 * by external libraries (like libgcrypt) to reallocate a 
-	 * non-secure block into secure memory. We cannot satisfy 
-	 * this request (as we don't know the size of the original 
+
+	/*
+	 * Reallocation is a bit of a gray area, as we can be asked
+	 * by external libraries (like libgcrypt) to reallocate a
+	 * non-secure block into secure memory. We cannot satisfy
+	 * this request (as we don't know the size of the original
 	 * block) so we just try our best here.
 	 */
-			 
+
 	return g_realloc (p, sz);
 }
 
@@ -275,45 +282,45 @@ egg_memory_fallback (void *p, size_t sz)
  */
 
 static void
-log_handler (const gchar *log_domain, GLogLevelFlags log_level, 
+log_handler (const gchar *log_domain, GLogLevelFlags log_level,
              const gchar *message, gpointer user_data)
 {
-    int level;
-
-    /* Note that crit and err are the other way around in syslog */
-        
-    switch (G_LOG_LEVEL_MASK & log_level) {
-    case G_LOG_LEVEL_ERROR:
-        level = LOG_CRIT;
-        break;
-    case G_LOG_LEVEL_CRITICAL:
-        level = LOG_ERR;
-        break;
-    case G_LOG_LEVEL_WARNING:
-        level = LOG_WARNING;
-        break;
-    case G_LOG_LEVEL_MESSAGE:
-        level = LOG_NOTICE;
-        break;
-    case G_LOG_LEVEL_INFO:
-        level = LOG_INFO;
-        break;
-    case G_LOG_LEVEL_DEBUG:
-        level = LOG_DEBUG;
-        break;
-    default:
-        level = LOG_ERR;
-        break;
-    }
-    
-    /* Log to syslog first */
-    if (log_domain)
-        syslog (level, "%s: %s", log_domain, message);
-    else
-        syslog (level, "%s", message);
- 
-    /* And then to default handler for aborting and stuff like that */
-    g_log_default_handler (log_domain, log_level, message, user_data); 
+	int level;
+
+	/* Note that crit and err are the other way around in syslog */
+
+	switch (G_LOG_LEVEL_MASK & log_level) {
+	case G_LOG_LEVEL_ERROR:
+		level = LOG_CRIT;
+		break;
+	case G_LOG_LEVEL_CRITICAL:
+		level = LOG_ERR;
+		break;
+	case G_LOG_LEVEL_WARNING:
+		level = LOG_WARNING;
+		break;
+	case G_LOG_LEVEL_MESSAGE:
+		level = LOG_NOTICE;
+		break;
+	case G_LOG_LEVEL_INFO:
+		level = LOG_INFO;
+		break;
+	case G_LOG_LEVEL_DEBUG:
+		level = LOG_DEBUG;
+		break;
+	default:
+		level = LOG_ERR;
+		break;
+	}
+
+	/* Log to syslog first */
+	if (log_domain)
+		syslog (level, "%s: %s", log_domain, message);
+	else
+		syslog (level, "%s", message);
+
+	/* And then to default handler for aborting and stuff like that */
+	g_log_default_handler (log_domain, log_level, message, user_data);
 }
 
 static void
@@ -327,18 +334,18 @@ printerr_handler (const gchar *string)
 static void
 prepare_logging ()
 {
-    GLogLevelFlags flags = G_LOG_FLAG_FATAL | G_LOG_LEVEL_ERROR | 
-                G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING | 
-                G_LOG_LEVEL_MESSAGE | G_LOG_LEVEL_INFO;
-                
-    openlog ("gnome-keyring-daemon", LOG_PID, LOG_AUTH);
-    
-    g_log_set_handler (NULL, flags, log_handler, NULL);
-    g_log_set_handler ("Glib", flags, log_handler, NULL);
-    g_log_set_handler ("Gtk", flags, log_handler, NULL);
-    g_log_set_handler ("Gnome", flags, log_handler, NULL);
-    g_log_set_default_handler (log_handler, NULL);
-    g_set_printerr_handler (printerr_handler);
+	GLogLevelFlags flags = G_LOG_FLAG_FATAL | G_LOG_LEVEL_ERROR |
+	                       G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING |
+	                       G_LOG_LEVEL_MESSAGE | G_LOG_LEVEL_INFO;
+
+	openlog ("gnome-keyring-daemon", LOG_PID, LOG_AUTH);
+
+	g_log_set_handler (NULL, flags, log_handler, NULL);
+	g_log_set_handler ("Glib", flags, log_handler, NULL);
+	g_log_set_handler ("Gtk", flags, log_handler, NULL);
+	g_log_set_handler ("Gnome", flags, log_handler, NULL);
+	g_log_set_default_handler (log_handler, NULL);
+	g_set_printerr_handler (printerr_handler);
 }
 
 /* -----------------------------------------------------------------------------
@@ -409,7 +416,7 @@ setup_signal_handling (GMainLoop *loop)
 }
 
 void
-gkr_daemon_quit (void)
+gkd_main_quit (void)
 {
 	/*
 	 * Send a signal to terminate our signal thread,
@@ -444,7 +451,7 @@ sane_dup2 (int fd1, int fd2)
 	ret = dup2 (fd1, fd2);
 	if (ret < 0 && errno == EINTR)
 		goto retry;
-	
+
 	return ret;
 }
 
@@ -455,16 +462,16 @@ read_login_password (int fd)
 	#define MAX_LENGTH 8192
 	#define MAX_BLOCK 256
 
-	/* 
-	 * When --login is specified then the login password is passed 
-	 * in on stdin. All data (including newlines) are part of the 
+	/*
+	 * When --login is specified then the login password is passed
+	 * in on stdin. All data (including newlines) are part of the
 	 * password.
 	 */
-	
+
 	gchar *buf = egg_secure_alloc (MAX_BLOCK);
 	gchar *ret = NULL;
 	int r, len = 0;
-	
+
 	for (;;) {
 		r = read (fd, buf, sizeof (buf));
 		if (r < 0) {
@@ -473,20 +480,20 @@ read_login_password (int fd)
 			egg_secure_free (ret);
 			egg_secure_free (buf);
 			return NULL;
-			
-		} else  { 
+
+		} else  {
 			char *n = egg_secure_realloc (ret, len + r + 1);
-			memset(n + len, 0, r + 1); 
+			memset(n + len, 0, r + 1);
 			ret = n;
 			len = len + r;
-			
+
 			strncat (ret, buf, r);
 		}
-		
+
 		if (r == 0 || len > MAX_LENGTH)
 			break;
 	}
-	
+
 	egg_secure_free (buf);
 	return ret;
 }
@@ -506,131 +513,39 @@ clear_login_password (void)
 	login_password = NULL;
 }
 
-static gboolean
-lifetime_slave_pipe_io (GIOChannel  *channel,
-			GIOCondition cond,
-			gpointer     callback_data)
-{
-	egg_cleanup_perform ();
-	_exit (2);
-	return FALSE;
-}
-
-static void
-slave_lifetime_to_fd (void)
-{
-	const char *env;
-	GIOChannel *channel;
-	int fd;
-	
-	env = getenv ("GNOME_KEYRING_LIFETIME_FD");
-	if (env && env[0]) {
-		fd = atoi (env);
-		if (fd != 0) {
-			channel = g_io_channel_unix_new (fd);
-			g_io_add_watch (channel,
-					G_IO_IN | G_IO_HUP,
-					lifetime_slave_pipe_io, NULL);
-			g_io_channel_unref (channel);
-		}
-	}
-}
-
 static void
 print_environment (pid_t pid)
 {
 	const gchar **env;
-	for (env = gkr_daemon_util_get_environment (); *env; ++env)
+	for (env = gkd_util_get_environment (); *env; ++env)
 		printf ("%s\n", *env);
 	if (pid)
 		printf ("GNOME_KEYRING_PID=%d\n", (gint)pid);
 }
 
-static gboolean
-initialize_other_running_daemon (int sock)
-{
-	GnomeKeyringResult res;
-	gchar **envp, **e;
-	EggBuffer buf;
-	gboolean ret;
-	
-	if (egg_unix_credentials_write (sock) < 0)
-		return FALSE;
-
-	egg_buffer_init_full (&buf, 128, g_realloc);
-	
-	envp = gnome_keyring_build_environment (GNOME_KEYRING_IN_ENVIRONMENT);
-	ret = gkr_proto_encode_prepare_environment (&buf, (const gchar**)envp);
-	g_strfreev (envp);
-	
-	if (!ret) {
-		egg_buffer_uninit (&buf);
-		g_return_val_if_reached (FALSE);
-	}
-
-	envp = NULL;
-
-	ret = gnome_keyring_socket_write_buffer (sock, &buf) && 
-	      gnome_keyring_socket_read_buffer (sock, &buf) && 
-	      gkr_proto_decode_prepare_environment_reply (&buf, &res, &envp);
-	
-	
-	egg_buffer_uninit (&buf);
-	
-	if(!ret) {
-		g_warning ("couldn't initialize running daemon");
-		return FALSE;
-	}
-
-	if (res == GNOME_KEYRING_RESULT_OK) {
-		g_return_val_if_fail (envp, FALSE);
-		for (e = envp; *e; ++e)
-			gkr_daemon_util_push_environment_full (*e);
-		ret = TRUE;
-	} else {
-		g_warning ("couldn't initialize running daemon: %s", gnome_keyring_result_to_message (res));
-		ret = FALSE;
-	}
-	
-	g_strfreev (envp);
-
-	return ret;
-}
 
 static gboolean
-start_or_initialize_daemon (void)
+start_or_initialize_daemon (const gchar *directory)
 {
-	gboolean ret;
-	int sock;
-	
-	/* 
-	 * Is a daemon already running? If not we need to run
-	 * a daemon process, just return and let things go 
-	 * their normal way. 
-	 */
-	sock = gnome_keyring_socket_connect_daemon (FALSE, TRUE);
-	if (sock == -1)
+	if (!directory)
 		return FALSE;
-	
-	ret = initialize_other_running_daemon (sock);
-	close (sock);
-	
+
 	/* Initialization failed, start this process up as a daemon */
-	if (!ret)
+	if (!gkd_control_initialize (directory))
 		return FALSE;
-	
-	/* 
-	 * Now we've initialized the daemon, we need to print out 
+
+	/*
+	 * Now we've initialized the daemon, we need to print out
 	 * the daemon's environment for any callers, and possibly
 	 * block if we've been asked to remain in the foreground.
 	 */
 	print_environment (0);
-	
+
 	/* TODO: Better way to sleep forever? */
 	if (run_foreground) {
 		while (sleep(0x08000000) == 0);
 	}
-	
+
 	return TRUE;
 }
 
@@ -645,15 +560,15 @@ fork_and_print_environment (void)
 		print_environment (getpid ());
 		return;
 	}
-	
+
 	pid = fork ();
-		
+
 	if (pid != 0) {
 
 		/* Here we are in the initial process */
 
 		if (run_daemonized) {
-			
+
 			/* Initial process, waits for intermediate child */
 			if (pid == -1)
 				exit (1);
@@ -661,7 +576,7 @@ fork_and_print_environment (void)
 			waitpid (pid, &status, 0);
 			if (WEXITSTATUS (status) != 0)
 				exit (WEXITSTATUS (status));
-			
+
 		} else {
 			/* Not double forking, we know the PID */
 			print_environment (pid);
@@ -670,30 +585,30 @@ fork_and_print_environment (void)
 		/* The initial process exits successfully */
 		exit (0);
 	}
-	
-	if (run_daemonized) { 
-		
+
+	if (run_daemonized) {
+
 		/* Double fork if need to daemonize properly */
 		pid = fork ();
-	
+
 		if (pid != 0) {
 
 			/* Here we are in the intermediate child process */
-				
-			/* 
-			 * This process exits, so that the final child will inherit 
+
+			/*
+			 * This process exits, so that the final child will inherit
 			 * init as parent to avoid zombies
 			 */
 			if (pid == -1)
 				exit (1);
-	
+
 			/* We've done two forks. Now we know the PID */
 			print_environment (pid);
-				
+
 			/* The intermediate child exits */
 			exit (0);
 		}
-		
+
 	}
 
 	/* Here we are in the resulting daemon or background process. */
@@ -708,8 +623,16 @@ fork_and_print_environment (void)
 static gboolean
 gkr_daemon_startup_steps (void)
 {
+	/*
+	 * Always initialize the keyring subsystem. This is a necessary
+	 * component that everything else depends on in one way or
+	 * another.
+	 */
+	if (!gkr_daemon_io_create_master_socket ())
+		return FALSE;
+
 	/* Startup the appropriate components, creates sockets etc.. */
-#ifdef WITH_SSH	
+#ifdef WITH_SSH
 	if (check_run_component ("ssh")) {
 		if (!gkr_pkcs11_daemon_startup_ssh ())
 			return FALSE;
@@ -732,15 +655,25 @@ gkr_daemon_initialize_steps (void)
 	if (!gkr_pkcs11_daemon_initialize ())
 		return FALSE;
 
+	/*
+	 * Unlock the login keyring if we were given a password on STDIN.
+	 * If it does not exist. We create it.
+	 */
+	if (login_password) {
+		if (!gkr_keyring_login_unlock (login_password))
+			g_message ("Failed to unlock login on startup");
+		egg_secure_strclear (login_password);
+	}
+
 	gkd_dbus_setup ();
 	return TRUE;
 }
 
 void
-gkr_daemon_complete_initialization (void)
+gkd_main_complete_initialization (void)
 {
 	/*
-	 * Sometimes we don't initialize the full daemon right on 
+	 * Sometimes we don't initialize the full daemon right on
 	 * startup. When run with --login is one such case.
 	 */
 
@@ -761,24 +694,24 @@ main (int argc, char *argv[])
 	GMainContext *ctx;
 	GMainLoop *loop;
 
-	/* 
-	 * The gnome-keyring startup is not as simple as I wish it could be. 
-	 * 
-	 * It's often started in the primidoral stages of a session, where 
-	 * there's no DBus, no GConf, and no proper X display. This is the 
+	/*
+	 * The gnome-keyring startup is not as simple as I wish it could be.
+	 *
+	 * It's often started in the primidoral stages of a session, where
+	 * there's no DBus, no GConf, and no proper X display. This is the
 	 * strange world of PAM.
-	 * 
+	 *
 	 * When started with the --login option, we do as little initialization
 	 * as possible. We expect a login password on the stdin, and unlock
 	 * or create the login keyring.
-	 * 
-	 * Then later we expect gnome-keyring-dameon to be run again with the 
+	 *
+	 * Then later we expect gnome-keyring-dameon to be run again with the
 	 * --start option. This second gnome-keyring-daemon will hook the
 	 * original daemon up with environment variables necessary to initialize
 	 * itself and bring it into the session. This second daemon usually exits.
-	 * 
-	 * Without either of these options, we follow a more boring and 
-	 * predictable startup.  
+	 *
+	 * Without either of these options, we follow a more boring and
+	 * predictable startup.
 	 */
 
 #ifdef WITH_TESTS
@@ -789,7 +722,7 @@ main (int argc, char *argv[])
 
 	g_type_init ();
 	g_thread_init (NULL);
-	
+
 #ifdef HAVE_LOCALE_H
 	/* internationalisation */
 	setlocale (LC_ALL, "");
@@ -802,30 +735,31 @@ main (int argc, char *argv[])
 #endif
 
 	egg_libgcrypt_initialize ();
-	
+
 	/* Send all warning or error messages to syslog */
 	prepare_logging ();
-	
+
 	parse_arguments (&argc, &argv);
-	
+
 	/* The --start option */
 	if (run_for_start) {
-		if (start_or_initialize_daemon ())
+		if (!control_directory)
+			control_directory = g_getenv (GKD_UTIL_ENV_CONTROL);
+		if (start_or_initialize_daemon (control_directory))
 			cleanup_and_exit (0);
-	} 
+	}
+
+	/* Initialize the main directory */
+	gkd_util_init_master_directory (control_directory);
 
 	/* Initialize our daemon main loop and threading */
 	loop = g_main_loop_new (NULL, FALSE);
 	ctx = g_main_loop_get_context (loop);
 	gkr_daemon_async_workers_init (loop);
-	
-	/* 
-	 * Always initialize the keyring subsystem. This is a necessary
-	 * component that everything else depends on in one way or 
-	 * another. 
-	 */
-	if (!gkr_daemon_io_create_master_socket ())
-		cleanup_and_exit (1);
+
+	/* Initialize our control socket */
+	if (!gkd_control_listen ())
+		return FALSE;
 
 	/* The --login option. Delayed initialization */
 	if (run_for_login) {
@@ -853,27 +787,24 @@ main (int argc, char *argv[])
 		gkr_daemon_initialize_steps ();
 	}
 
-	/* TODO: Do we still need this? XFCE still seems to use it. */
-	slave_lifetime_to_fd ();
-
 	/*
 	 * Unlock the login keyring if we were given a password on STDIN.
-	 * If it does not exist. We create it. 
+	 * If it does not exist. We create it.
 	 */
 	if (login_password) {
 		if (!gkr_keyring_login_unlock (login_password))
 			g_message ("Failed to unlock login on startup");
 		egg_secure_strclear (login_password);
 	}
-	
+
 	g_main_loop_run (loop);
 
 	/* Make sure no other threads are running */
 	gkr_daemon_async_workers_stop_all ();
-	
+
 	/* This wraps everything up in order */
 	egg_cleanup_perform ();
-	
+
 	/* Final shutdown of anything workers running about */
 	gkr_daemon_async_workers_uninit ();
 
diff --git a/daemon/gkd-main.h b/daemon/gkd-main.h
new file mode 100644
index 0000000..4b14f4d
--- /dev/null
+++ b/daemon/gkd-main.h
@@ -0,0 +1,31 @@
+/*
+ * gnome-keyring
+ *
+ * Copyright (C) 2009 Stefan Walter
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef GKD_MAIN_H_
+#define GKD_MAIN_H_
+
+#include <glib.h>
+
+void           gkd_main_quit (void);
+
+void           gkd_main_complete_initialization (void);
+
+#endif /* GKD_MAIN_H_ */
diff --git a/daemon/gkd-util.c b/daemon/gkd-util.c
new file mode 100644
index 0000000..06e4dbf
--- /dev/null
+++ b/daemon/gkd-util.c
@@ -0,0 +1,209 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* gkr-daemon-util.c - Helper utilities for the daemon
+
+   Copyright (C) 2007, Stefan Walter
+
+   The Gnome Keyring Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The Gnome Keyring Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the Gnome Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.
+
+   Author: Stef Walter <stef memberwebs com>
+*/
+
+#include "config.h"
+
+#include "gkd-util.h"
+
+#include "egg/egg-cleanup.h"
+#include "egg/egg-mkdtemp.h"
+#include "egg/egg-unix-credentials.h"
+
+#include <glib.h>
+
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+/*
+ * A list of all the environment variables the daemon can
+ * possibly send out when it starts.
+ */
+const gchar *GKD_UTIL_OUT_ENVIRONMENT[] = {
+	"SSH_AUTH_SOCK",
+	"GNOME_KEYRING_SOCKET",
+	"GNOME_KEYRING_CONTROL",
+	"GNOME_KEYRING_PID",
+	"SSH_AGENT_PID",
+	NULL
+};
+
+/*
+ * A list of all the environment variables the daemon
+ * is interested in from clients if it was started
+ * early before these environment variables were set.
+ */
+const gchar *GKD_UTIL_IN_ENVIRONMENT[] = {
+	"DISPLAY",
+	"DBUS_SESSION_BUS_ADDRESS",
+	"DESKTOP_AUTOSTART_ID",
+	"ICEAUTHORITY",
+	"LANG",
+	"XAUTHORITY",
+	"XAUTHLOCALHOSTNAME",
+	"XDG_SESSION_COOKIE",
+	"LOGNAME",
+	"USERNAME",
+	NULL
+};
+
+static gchar* master_directory = NULL;
+static GArray* published_environ = NULL;
+
+static void
+uninit_master_directory (gpointer data)
+{
+	g_assert (master_directory);
+	rmdir (master_directory);
+	g_free (master_directory);
+	master_directory = NULL;
+}
+
+void
+gkd_util_init_master_directory (const gchar *replace)
+{
+	gboolean exists = FALSE;
+	gboolean valid = FALSE;
+	struct stat st;
+
+	if (replace) {
+		exists = TRUE;
+		if (lstat (replace, &st) < 0) {
+			if (errno != ENOTDIR && errno != ENOENT)
+				exists = FALSE;
+		} else if (st.st_uid != geteuid ()) {
+			g_message ("The gnome-keyring control directory is not owned with the same "
+			           "credentials as the user login: %s", replace);
+		} else if (st.st_mode != (S_IRUSR | S_IWUSR | S_IXUSR)) {
+			g_message ("The gnome-keyring control directory has invalid permissions. It "
+			           "must be only be accessible by its owner (ie: 0600): %s", replace);
+		} else {
+			valid = TRUE;
+		}
+	}
+
+	/* Generate a new directory */
+	if (!valid) {
+		master_directory = g_build_filename (g_get_tmp_dir (), "keyring-XXXXXX", NULL);
+		if (egg_mkdtemp (master_directory) == NULL)
+			g_warning ("couldn't create socket directory: %s", g_strerror (errno));
+
+	/* A directory was supplied, but doesn't exist yet */
+	} else if (!exists) {
+		g_assert (replace);
+		master_directory = g_strdup (replace);
+		if (g_mkdir_with_parents (master_directory, S_IRUSR | S_IWUSR | S_IXUSR) < 0)
+			g_warning ("couldn't create socket directory: %s", g_strerror (errno));
+
+	/* A valid existing directory was supplied */
+	} else {
+		g_assert (replace);
+		master_directory = g_strdup (replace);
+	}
+
+	gkd_util_push_environment (GKD_UTIL_ENV_CONTROL, master_directory);
+	egg_cleanup_register (uninit_master_directory, NULL);
+}
+
+const gchar*
+gkd_util_get_master_directory (void)
+{
+	g_return_val_if_fail (master_directory, NULL);
+	return master_directory;
+}
+
+static void
+uninit_environment (gpointer data)
+{
+	guint i;
+
+	if (published_environ) {
+		for (i = 0; i < published_environ->len; ++i)
+			g_free (g_array_index (published_environ, gchar*, i));
+		g_array_free (published_environ, TRUE);
+	}
+
+	published_environ = NULL;
+}
+
+static void
+init_environment ()
+{
+	if (published_environ)
+		return;
+	published_environ = g_array_new (TRUE, TRUE, sizeof (gchar*));
+	egg_cleanup_register (uninit_environment, NULL);
+}
+
+void
+gkd_util_push_environment (const gchar *name, const gchar *value)
+{
+	gchar *env;
+
+	init_environment ();
+
+	env = g_strdup_printf ("%s=%s", name, value);
+	g_array_append_val (published_environ, env);
+}
+
+void
+gkd_util_push_environment_full (const gchar *var)
+{
+	gchar *env;
+
+	g_return_if_fail (strchr (var, '=') != NULL);
+	init_environment ();
+
+	env = g_strdup (var);
+	g_array_append_val (published_environ, env);
+}
+
+const gchar**
+gkd_util_get_environment (void)
+{
+	init_environment ();
+	return (const gchar**)published_environ->data;
+}
+
+gchar**
+gkd_util_build_environment (const gchar **names)
+{
+	GArray *array = g_array_sized_new (TRUE, TRUE, sizeof (gchar*), 8);
+	const gchar *value;
+	const gchar **name;
+	gchar *env;
+
+	/* Transform them into NAME=VALUE pairs */
+	for (name = names; *name; ++name) {
+		value = g_getenv (*name);
+		if (value) {
+			env = g_strdup_printf ("%s=%s", *name, value);
+			g_array_append_val (array, env);
+		}
+	}
+
+	return (gchar**)g_array_free (array, FALSE);
+}
diff --git a/daemon/gkd-util.h b/daemon/gkd-util.h
new file mode 100644
index 0000000..d17bd2b
--- /dev/null
+++ b/daemon/gkd-util.h
@@ -0,0 +1,46 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* gkd-util.h - Helper utilities for the daemon
+
+   Copyright (C) 2008, Stefan Walter
+
+   The Gnome Keyring Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The Gnome Keyring Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the Gnome Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.
+
+   Author: Stef Walter <stef memberwebs com>
+*/
+
+#ifndef GKD_UTIL_H_
+#define GKD_UTIL_H_
+
+#include <glib.h>
+
+#define         GKD_UTIL_ENV_CONTROL             "GNOME_KEYRING_CONTROL"
+
+extern const gchar *GKD_UTIL_OUT_ENVIRONMENT[];
+extern const gchar *GKD_UTIL_IN_ENVIRONMENT[];
+
+void            gkd_util_init_master_directory   (const gchar *replace);
+
+const gchar*    gkd_util_get_master_directory    (void);
+
+void            gkd_util_push_environment        (const gchar *name, const gchar *value);
+
+void            gkd_util_push_environment_full   (const gchar *env);
+
+const gchar**   gkd_util_get_environment         (void);
+
+gchar**         gkd_util_build_environment       (const gchar **names);
+
+#endif /*GKD_UTIL_H_*/
diff --git a/daemon/gkr-daemon-io.c b/daemon/gkr-daemon-io.c
index e499c65..af12634 100644
--- a/daemon/gkr-daemon-io.c
+++ b/daemon/gkr-daemon-io.c
@@ -32,6 +32,7 @@
 #include <sys/socket.h>
 #include <sys/un.h>
 
+#include "gkd-util.h"
 #include "gkr-daemon.h"
 
 #include "egg/egg-buffer.h"
@@ -399,15 +400,12 @@ gkr_daemon_io_create_master_socket (void)
 	struct sockaddr_un addr;
 	GIOChannel *channel;
 
-	tmp_dir = gkr_daemon_util_get_master_directory ();
+	tmp_dir = gkd_util_get_master_directory ();
 	g_return_val_if_fail (tmp_dir, FALSE);
 		
 	snprintf (socket_path, sizeof (socket_path), "%s/socket", tmp_dir);
-	
-#ifdef WITH_TESTS
-	if (g_getenv ("GNOME_KEYRING_TEST_PATH"))
-		unlink (socket_path);
-#endif
+
+	unlink (socket_path);
 
 	egg_cleanup_register (cleanup_socket_dir, NULL);
 	
@@ -437,7 +435,7 @@ gkr_daemon_io_create_master_socket (void)
 	channel = g_io_channel_unix_new (sock);
 	g_io_add_watch (channel, G_IO_IN | G_IO_HUP, accept_client, NULL);
 	g_io_channel_unref (channel);
-	
-	gkr_daemon_util_push_environment ("GNOME_KEYRING_SOCKET", socket_path);
+
+	gkd_util_push_environment ("GNOME_KEYRING_SOCKET", socket_path);
 	return TRUE;
 }
diff --git a/daemon/gkr-daemon-ops.c b/daemon/gkr-daemon-ops.c
index 04c004a..b12967f 100644
--- a/daemon/gkr-daemon-ops.c
+++ b/daemon/gkr-daemon-ops.c
@@ -22,6 +22,8 @@
 
 #include "config.h"
 
+#include "gkd-main.h"
+#include "gkd-util.h"
 #include "gkr-daemon.h"
 
 #include "egg/egg-buffer.h"
@@ -39,7 +41,6 @@
 #include "ui/gkr-ask-request.h"
 #include "ui/gkr-ask-daemon.h"
 
-#include "util/gkr-daemon-util.h"
 #include "util/gkr-location.h"
 
 #include <unistd.h>
@@ -1738,12 +1739,12 @@ op_prepare_daemon_environment (EggBuffer *packet, EggBuffer *result, GkrKeyringR
 	 * We've now definitely received everything we need to run. Ask
 	 * the daemon to complete the initialization. 
 	 */
-	gkr_daemon_complete_initialization();
+	gkd_main_complete_initialization();
 
 	egg_buffer_add_uint32 (result, GNOME_KEYRING_RESULT_OK);
 
 	/* These are the environment variables that the daemon setup */
-	daemonenv = gkr_daemon_util_get_environment ();
+	daemonenv = gkd_util_get_environment ();
 	g_return_val_if_fail (daemonenv, FALSE);
 	
 	egg_buffer_add_stringv (result, daemonenv);
diff --git a/daemon/gkr-daemon.h b/daemon/gkr-daemon.h
index 80e3491..b843f24 100644
--- a/daemon/gkr-daemon.h
+++ b/daemon/gkr-daemon.h
@@ -45,10 +45,6 @@ typedef gboolean (*GkrDaemonOperation) (EggBuffer *packet, EggBuffer *result,
 
 extern GkrDaemonOperation keyring_ops[];
 
-void           gkr_daemon_quit (void);
-
-void           gkr_daemon_complete_initialization (void);
-
 gboolean       gkr_daemon_io_create_master_socket (void);
 
 const gchar*   gkr_daemon_io_get_socket_path      (void);
diff --git a/daemon/pkcs11/gkr-pkcs11-daemon.c b/daemon/pkcs11/gkr-pkcs11-daemon.c
index e05d76d..9fcaefc 100644
--- a/daemon/pkcs11/gkr-pkcs11-daemon.c
+++ b/daemon/pkcs11/gkr-pkcs11-daemon.c
@@ -21,6 +21,7 @@
 
 #include "config.h"
 
+#include "gkd-util.h"
 #include "gkr-pkcs11-auth.h"
 #include "gkr-pkcs11-daemon.h"
 
@@ -33,7 +34,6 @@
 #include "pkcs11/user-store/gck-user-store.h"
 
 #include "daemon/util/gkr-daemon-async.h"
-#include "daemon/util/gkr-daemon-util.h"
 
 #include "egg/egg-cleanup.h"
 
@@ -165,7 +165,7 @@ gkr_pkcs11_daemon_startup_pkcs11 (void)
 	const gchar *base_dir;
 	int sock;
 
-	base_dir = gkr_daemon_util_get_master_directory ();
+	base_dir = gkd_util_get_master_directory ();
 	g_return_val_if_fail (base_dir, FALSE);
 
 	gkr_daemon_async_begin_concurrent ();
@@ -216,7 +216,7 @@ gkr_pkcs11_daemon_startup_ssh (void)
 	const gchar *base_dir;
 	int sock;
 
-	base_dir = gkr_daemon_util_get_master_directory ();
+	base_dir = gkd_util_get_master_directory ();
 	g_return_val_if_fail (base_dir, FALSE);
 
 	gkr_daemon_async_begin_concurrent ();
@@ -233,7 +233,7 @@ gkr_pkcs11_daemon_startup_ssh (void)
 	g_io_channel_unref (channel);
 	
 	/* gck-ssh-agent sets the environment variable */
-	gkr_daemon_util_push_environment ("SSH_AUTH_SOCK", g_getenv ("SSH_AUTH_SOCK"));
+	gkd_util_push_environment ("SSH_AUTH_SOCK", g_getenv ("SSH_AUTH_SOCK"));
 
 	egg_cleanup_register (pkcs11_ssh_cleanup, NULL);
 
diff --git a/daemon/util/gkr-daemon-util.c b/daemon/util/gkr-daemon-util.c
index 8391902..fd3490a 100644
--- a/daemon/util/gkr-daemon-util.c
+++ b/daemon/util/gkr-daemon-util.c
@@ -228,108 +228,3 @@ gkr_daemon_client_get_app_path (GkrDaemonClient* client)
 	return client->app_path;
 }
 
-/* -------------------------------------------------------------------------------------- */
-
-static gchar* master_directory = NULL;
-static GArray* published_environ = NULL;
-
-static void
-uninit_master_directory (gpointer data)
-{
-	g_assert (master_directory);
-	rmdir (master_directory);
-	g_free (master_directory);
-	master_directory = NULL;
-}
-
-static void
-init_master_directory (void)
-{
-	gboolean have_path = FALSE;
-
-	/* 
-	 * When run under control of unit tests, we let the parent process
-	 * pass in the socket path that we're going to create our main socket on.
- 	 */
-	
-#ifdef WITH_TESTS
-	const gchar* env = g_getenv ("GNOME_KEYRING_TEST_PATH");
-	if (env && *env) {
-		master_directory = g_strdup (env);
-		if (g_mkdir_with_parents (master_directory, S_IRUSR | S_IWUSR | S_IXUSR) < 0)
-			g_warning ("couldn't create socket directory: %s", g_strerror (errno));
-		have_path = TRUE;
-	} 
-#endif /* WITH_TESTS */	
-	
-	/* Create private directory for agent socket */
-	if (!have_path) {
-		master_directory = g_build_filename (g_get_tmp_dir (), "keyring-XXXXXX", NULL);
-		if (egg_mkdtemp (master_directory) == NULL)
-			g_warning ("couldn't create socket directory: %s", g_strerror (errno));
-	}
-	
-	egg_cleanup_register (uninit_master_directory, NULL);
-}
-		
-const gchar*
-gkr_daemon_util_get_master_directory (void)
-{
-	if (!master_directory) 
-		init_master_directory ();
-	
-	return master_directory;
-}
-
-static void
-uninit_environment (gpointer data)
-{
-	guint i;
-	
-	if (published_environ) {
-		for (i = 0; i < published_environ->len; ++i)
-			g_free (g_array_index (published_environ, gchar*, i));
-		g_array_free (published_environ, TRUE);
-	}
-	
-	published_environ = NULL;
-}
-
-static void 
-init_environment ()
-{
-	if (published_environ)
-		return;
-	published_environ = g_array_new (TRUE, TRUE, sizeof (gchar*)); 
-	egg_cleanup_register (uninit_environment, NULL);
-}
-
-void
-gkr_daemon_util_push_environment (const gchar *name, const gchar *value)
-{
-	gchar *env;
-
-	init_environment ();
-		
-	env = g_strdup_printf ("%s=%s", name, value);
-	g_array_append_val (published_environ, env);
-}
-
-void 
-gkr_daemon_util_push_environment_full (const gchar *var)
-{
-	gchar *env;
-	
-	g_return_if_fail (strchr (var, '=') != NULL);
-	init_environment ();
-	
-	env = g_strdup (var);
-	g_array_append_val (published_environ, env);
-}
-
-const gchar**
-gkr_daemon_util_get_environment (void)
-{
-	init_environment ();
-	return (const gchar**)published_environ->data;
-}
diff --git a/daemon/util/gkr-daemon-util.h b/daemon/util/gkr-daemon-util.h
index 0a6f06e..69ce6b2 100644
--- a/daemon/util/gkr-daemon-util.h
+++ b/daemon/util/gkr-daemon-util.h
@@ -31,14 +31,6 @@ G_BEGIN_DECLS
 
 #include <sys/types.h>
 
-const gchar*    gkr_daemon_util_get_master_directory    (void);
-
-void            gkr_daemon_util_push_environment        (const gchar *name, const gchar *value);
-
-void            gkr_daemon_util_push_environment_full   (const gchar *env);
-
-const gchar**   gkr_daemon_util_get_environment         (void);
-
 #define GKR_TYPE_DAEMON_CLIENT             (gkr_daemon_client_get_type ())
 #define GKR_DAEMON_CLIENT(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), GKR_TYPE_DAEMON_CLIENT, GkrDaemonClient))
 #define GKR_DAEMON_CLIENT_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), GKR_TYPE_DAEMON_CLIENT, GkrDaemonClientClass))
diff --git a/pam/gkr-pam-client.c b/pam/gkr-pam-client.c
index 8ff890b..88a2382 100644
--- a/pam/gkr-pam-client.c
+++ b/pam/gkr-pam-client.c
@@ -29,6 +29,7 @@
 #include "egg/egg-unix-credentials.h"
 
 #include <sys/types.h>
+#include <sys/param.h>
 #include <sys/socket.h>
 #include <sys/stat.h>
 #include <sys/un.h>
@@ -54,9 +55,6 @@
 #include <sys/ucred.h>
 #endif
 
-#define PAM_APP_NAME      "Auto Login (PAM)"
-#define PAM_APP_NAME_LEN  (sizeof (PAM_APP_NAME) - 1)
-
 static int
 check_peer_same_uid (int sock)
 {
@@ -143,16 +141,24 @@ write_credentials_byte (int sock)
 }
 
 static int
-connect_to_daemon (const char *path)
+connect_to_daemon (const char *control)
 {
+	char path[MAXPATHLEN];
 	struct sockaddr_un addr;
 	struct stat st;
 	int sock;
-	
-	/* First a bunch of checks to make sure nothing funny is going on */
-	
+
+	/* Build up the directory name */
+	if (strlen (control) + strlen ("/control") + 1 >= MAXPATHLEN) {
+		syslog (GKR_LOG_ERR, "The gnome keyring socket directory is too long");
+		return -1;
+	}
+	strcpy (path, control);
+	strcat (path, "/control");
+
+	/* A bunch of checks to make sure nothing funny is going on */
 	if (lstat (path, &st) < 0) {
-		syslog (GKR_LOG_ERR, "Couldn't access gnome keyring socket: %s: %s", 
+		syslog (GKR_LOG_ERR, "Couldn't access gnome keyring socket: %s: %s",
 		        path, strerror (errno));
 		return -1;
 	}
@@ -176,7 +182,7 @@ connect_to_daemon (const char *path)
 	
 	sock = socket (AF_UNIX, SOCK_STREAM, 0);
 	if (sock < 0) {
-		syslog (GKR_LOG_ERR, "couldn't create socket: %s", strerror (errno));
+		syslog (GKR_LOG_ERR, "couldn't create control socket: %s", strerror (errno));
 		return -1;
 	}
 
@@ -184,7 +190,7 @@ connect_to_daemon (const char *path)
 	fcntl (sock, F_SETFD, 1);
 
 	if (connect (sock, (struct sockaddr*) &addr, sizeof (addr)) < 0) {
-		syslog (GKR_LOG_ERR, "couldn't connect to daemon at: %s: %s", 
+		syslog (GKR_LOG_ERR, "couldn't connect to gnome-keyring-daemon socket at: %s: %s",
 		        path, strerror (errno));
 		close (sock);
 		return -1;
@@ -262,16 +268,16 @@ read_part (int fd, unsigned char *data, int len)
 }
 
 static GnomeKeyringResult 
-keyring_daemon_op (const char *socket, GnomeKeyringOpCode op, int argc, 
+keyring_daemon_op (const char *control, GnomeKeyringOpCode op, int argc,
                    const char* argv[])
 {
 	GnomeKeyringResult ret = GNOME_KEYRING_RESULT_OK;
 	unsigned char buf[4];
 	int i, sock = -1;
 	uint oplen, l;
-	
-	assert (socket);
-	
+
+	assert (control);
+
 	/* 
 	 * We only support operations with zero or more strings
 	 * and an empty (only result code) return. 
@@ -281,19 +287,12 @@ keyring_daemon_op (const char *socket, GnomeKeyringOpCode op, int argc,
 	        op == GNOME_KEYRING_OP_CREATE_KEYRING || 
 	        op == GNOME_KEYRING_OP_CHANGE_KEYRING_PASSWORD);
 
-	sock = connect_to_daemon (socket);
+	sock = connect_to_daemon (control);
 	if (sock < 0) {
 		ret = -1;
 		goto done;
 	}
-	
-	/* Send the application packet / name */
-	egg_buffer_encode_uint32 (buf, PAM_APP_NAME_LEN + 8);
-	write_part (sock, buf, 4, &ret);
-	egg_buffer_encode_uint32 (buf, PAM_APP_NAME_LEN);
-	write_part (sock, buf, 4, &ret);
-	write_part (sock, (unsigned char*)PAM_APP_NAME, PAM_APP_NAME_LEN, &ret);
-	    
+
 	/* Calculate the packet length */
 	oplen = 8; /* The packet size, and op code */
 	for (i = 0; i < argc; ++i)  
@@ -348,7 +347,7 @@ done:
 }
 
 GnomeKeyringResult
-gkr_pam_client_run_operation (struct passwd *pwd, const char *socket, 
+gkr_pam_client_run_operation (struct passwd *pwd, const char *control,
                               GnomeKeyringOpCode op, int argc, const char* argv[])
 {
 	struct sigaction ignpipe, oldpipe, defchld, oldchld;
@@ -371,7 +370,7 @@ gkr_pam_client_run_operation (struct passwd *pwd, const char *socket,
 	    pwd->pw_uid == geteuid () && pwd->pw_gid == getegid ()) {
 
 		/* Already running as the right user, simple */
-		res = keyring_daemon_op (socket, op, argc, argv);
+		res = keyring_daemon_op (control, op, argc, argv);
 		
 	} else {
 		
@@ -392,7 +391,7 @@ gkr_pam_client_run_operation (struct passwd *pwd, const char *socket,
 				exit (GNOME_KEYRING_RESULT_IO_ERROR);
 			}
 	
-			res = keyring_daemon_op (socket, op, argc, argv);
+			res = keyring_daemon_op (control, op, argc, argv);
 			exit (res);
 			return 0; /* Never reached */
 			
diff --git a/pam/gkr-pam-module.c b/pam/gkr-pam-module.c
index 530bf42..98e4ea7 100644
--- a/pam/gkr-pam-module.c
+++ b/pam/gkr-pam-module.c
@@ -67,10 +67,10 @@ enum {
 	ARG_USE_AUTHTOK	        = 1 << 2
 };
 
-#define LOGIN_KEYRING		"login"
+#define LOGIN_KEYRING           "login"
 
-#define ENV_SOCKET 		"GNOME_KEYRING_SOCKET"
-#define ENV_PID    		"GNOME_KEYRING_PID"
+#define ENV_CONTROL             "GNOME_KEYRING_CONTROL"
+#define ENV_PID                 "GNOME_KEYRING_PID"
 
 /* read & write ends of a pipe */
 #define  READ_END   0
@@ -578,15 +578,15 @@ static int
 start_daemon_if_necessary (pam_handle_t *ph, struct passwd *pwd, 
                            const char *password, int* started)
 {
-	const char *socket;
+	const char *control;
 	int ret;
-	
+
 	*started = 0;
-	
+
 	/* See if it's already running, and transfer env variables */
-	socket = get_any_env (ph, ENV_SOCKET);
-	if (socket) {
-		ret = setup_pam_env (ph, ENV_SOCKET, socket);
+	control = get_any_env (ph, ENV_CONTROL);
+	if (control) {
+		ret = setup_pam_env (ph, ENV_CONTROL, control);
 		if (ret != PAM_SUCCESS) {
 			syslog (GKR_LOG_ERR, "gkr-pam: couldn't set environment variables: %s",
 			        pam_strerror (ph, ret));
@@ -647,15 +647,15 @@ done:
 static int
 create_keyring (pam_handle_t *ph, struct passwd *pwd, const char *password)
 {
-	const char *socket;
+	const char *control;
 	GnomeKeyringResult res;
 	const char *argv[2];
 	
 	assert (pwd);
 	assert (password);
-	
-	socket = get_any_env (ph, ENV_SOCKET);
-	if (!socket) {
+
+	control = get_any_env (ph, ENV_CONTROL);
+	if (!control) {
 		syslog (GKR_LOG_WARN, "gkr-pam: couldn't create '%s' keyring: %s", 
 		        LOGIN_KEYRING, "gnome-keyring-daemon is not running");
 		return PAM_SERVICE_ERR;
@@ -664,7 +664,7 @@ create_keyring (pam_handle_t *ph, struct passwd *pwd, const char *password)
 	argv[0] = LOGIN_KEYRING;
 	argv[1] = password;
 	
-	res = gkr_pam_client_run_operation (pwd, socket, GNOME_KEYRING_OP_CREATE_KEYRING, 2, argv);
+	res = gkr_pam_client_run_operation (pwd, control, GNOME_KEYRING_OP_CREATE_KEYRING, 2, argv);
 	if (res != GNOME_KEYRING_RESULT_OK) {
 		syslog (GKR_LOG_ERR, "gkr-pam: couldn't create '%s' keyring: %d", LOGIN_KEYRING, res);
 		return PAM_SERVICE_ERR;
@@ -678,15 +678,15 @@ create_keyring (pam_handle_t *ph, struct passwd *pwd, const char *password)
 static int
 unlock_keyring (pam_handle_t *ph, struct passwd *pwd, const char *password)
 {
-	const char *socket;
+	const char *control;
 	GnomeKeyringResult res;
 	const char *argv[2];
 	
 	assert (pwd);
 	assert (password);
-	
-	socket = get_any_env (ph, ENV_SOCKET);
-	if (!socket) {
+
+	control = get_any_env (ph, ENV_CONTROL);
+	if (!control) {
 		syslog (GKR_LOG_WARN, "gkr-pam: couldn't unlock '%s' keyring: %s", 
 		        LOGIN_KEYRING, "gnome-keyring-daemon is not running");
 		return PAM_SERVICE_ERR;
@@ -695,7 +695,7 @@ unlock_keyring (pam_handle_t *ph, struct passwd *pwd, const char *password)
 	argv[0] = LOGIN_KEYRING;
 	argv[1] = password;
 	
-	res = gkr_pam_client_run_operation (pwd, socket, GNOME_KEYRING_OP_UNLOCK_KEYRING, 2, argv);
+	res = gkr_pam_client_run_operation (pwd, control, GNOME_KEYRING_OP_UNLOCK_KEYRING, 2, argv);
 
 	/* 'login' keyring doesn't exist, create it */
 	if (res == GNOME_KEYRING_RESULT_NO_SUCH_KEYRING) {
@@ -715,16 +715,16 @@ static int
 change_keyring_password (pam_handle_t *ph, struct passwd *pwd, 
                          const char *password, const char *original)
 {
-	const char *socket;
+	const char *control;
 	GnomeKeyringResult res;
 	const char *argv[3];
 	
 	assert (pwd);
 	assert (password);
 	assert (original);
-	
-	socket = get_any_env (ph, ENV_SOCKET);
-	if (!socket) {
+
+	control = get_any_env (ph, ENV_CONTROL);
+	if (!control) {
 		syslog (GKR_LOG_WARN, "gkr-pam: couldn't change password on '%s' keyring: %s", 
 		        LOGIN_KEYRING, "gnome-keyring-daemon is not running");
 		return PAM_SERVICE_ERR;
@@ -734,7 +734,7 @@ change_keyring_password (pam_handle_t *ph, struct passwd *pwd,
 	argv[1] = original;
 	argv[2] = password;	
 	
-	res = gkr_pam_client_run_operation (pwd, socket, GNOME_KEYRING_OP_CHANGE_KEYRING_PASSWORD, 3, argv);
+	res = gkr_pam_client_run_operation (pwd, control, GNOME_KEYRING_OP_CHANGE_KEYRING_PASSWORD, 3, argv);
 
 	/* No keyring, not an error. Will be created at initial authenticate. */
 	if (res == GNOME_KEYRING_RESULT_NO_SUCH_KEYRING) {
@@ -841,7 +841,7 @@ pam_sm_authenticate (pam_handle_t *ph, int unused, int argc, const char **argv)
 {
 	struct passwd *pwd;
 	const char *user, *password;
-	const char *socket;
+	const char *control;
 	int started_daemon;
 	uint args;
 	int ret;
@@ -884,11 +884,11 @@ pam_sm_authenticate (pam_handle_t *ph, int unused, int argc, const char **argv)
 		if (ret != PAM_SUCCESS)
 			return ret;
 	}
-	
-	socket = get_any_env (ph, ENV_SOCKET);
+
+	control = get_any_env (ph, ENV_CONTROL);
 
 	/* If gnome keyring is running, then unlock now */
-	if (socket) {
+	if (control) {
 		/* If we started the daemon, its already unlocked, since we passed the password */
 		if (!started_daemon) {
 			ret = unlock_keyring (ph, pwd, password);
@@ -958,7 +958,7 @@ pam_sm_open_session (pam_handle_t *ph, int flags, int argc, const char **argv)
 	}
 
 	/* If gnome keyring is running, but we didn't start it here, then unlock now */
-	if (get_any_env (ph, ENV_SOCKET) != NULL) {
+	if (get_any_env (ph, ENV_CONTROL) != NULL) {
 		if (!started_daemon && password != NULL) {
 			if (unlock_keyring (ph, pwd, password) != PAM_SUCCESS)
 				return PAM_SERVICE_ERR;
diff --git a/pam/tests/unit-test-pam.c b/pam/tests/unit-test-pam.c
index 3e2679d..2881661 100644
--- a/pam/tests/unit-test-pam.c
+++ b/pam/tests/unit-test-pam.c
@@ -37,7 +37,7 @@ DEFINE_TEST(pam_open)
 	char** pam_env;
 
 	/* Clear out this environment variable so we force a new daemon */
-	putenv("GNOME_KEYRING_SOCKET=");
+	putenv("GNOME_KEYRING_CONTROL=");
 
 	int ret = pam_authenticate (test_pamh, 0);
 	if (ret != PAM_SUCCESS)
@@ -56,13 +56,13 @@ DEFINE_TEST(pam_env)
 {
 	const char *socket;
 
-	socket = g_getenv ("GNOME_KEYRING_SOCKET");
+	socket = g_getenv ("GNOME_KEYRING_CONTROL");
 	/* "socket should have been setup" */
 	g_assert (socket && socket[0]);
 	/* "socket should have been created" */
 	g_assert (g_file_test (socket, G_FILE_TEST_EXISTS));
 
-	g_printerr ("GNOME_KEYRING_SOCKET is: %s\n", g_getenv ("GNOME_KEYRING_SOCKET"));
+	g_printerr ("GNOME_KEYRING_CONTROL is: %s\n", g_getenv ("GNOME_KEYRING_CONTROL"));
 	sleep (3);
 }
 
diff --git a/pkcs11/rpc-layer/gck-rpc-dispatch.c b/pkcs11/rpc-layer/gck-rpc-dispatch.c
index 58e0533..13e1909 100644
--- a/pkcs11/rpc-layer/gck-rpc-dispatch.c
+++ b/pkcs11/rpc-layer/gck-rpc-dispatch.c
@@ -2296,7 +2296,7 @@ gck_rpc_layer_startup (const char *prefix)
 	assert (pkcs11_dispatchers == NULL);
 
 	snprintf (pkcs11_socket_path, sizeof (pkcs11_socket_path), 
-	          "%s/socket.pkcs11", prefix);
+	          "%s/pkcs11", prefix);
 
 	sock = socket(AF_UNIX, SOCK_STREAM, 0);
 	if (sock < 0) {
diff --git a/pkcs11/rpc-layer/gck-rpc-module.c b/pkcs11/rpc-layer/gck-rpc-module.c
index 8094d57..837abe3 100644
--- a/pkcs11/rpc-layer/gck-rpc-module.c
+++ b/pkcs11/rpc-layer/gck-rpc-module.c
@@ -1176,12 +1176,12 @@ rpc_C_Initialize (CK_VOID_PTR init_args)
 			}
 		}
 		
-		/* Lookup the socket path, append '.pkcs11' */
+		/* Lookup the socket path, append '/pkcs11' */
 		if (pkcs11_socket_path[0] == 0) {
 			pkcs11_socket_path[0] = 0;
-			path = getenv ("GNOME_KEYRING_SOCKET");
+			path = getenv ("GNOME_KEYRING_CONTROL");
 			if (path && path[0]) {
-				snprintf (pkcs11_socket_path, sizeof (pkcs11_socket_path), "%s.pkcs11", path);
+				snprintf (pkcs11_socket_path, sizeof (pkcs11_socket_path), "%s/pkcs11", path);
 				pkcs11_socket_path[sizeof (pkcs11_socket_path) - 1] = 0;
 			}
 		}
diff --git a/pkcs11/ssh-agent/gck-ssh-agent.c b/pkcs11/ssh-agent/gck-ssh-agent.c
index 7b4d0ac..322f5c8 100644
--- a/pkcs11/ssh-agent/gck-ssh-agent.c
+++ b/pkcs11/ssh-agent/gck-ssh-agent.c
@@ -411,7 +411,7 @@ gck_ssh_agent_startup (const gchar *prefix)
 	
 	g_return_val_if_fail (prefix, -1);
 	
-	snprintf (socket_path, sizeof (socket_path), "%s/socket.ssh", prefix);
+	snprintf (socket_path, sizeof (socket_path), "%s/ssh", prefix);
 	unlink (socket_path);
 
 	sock = socket (AF_UNIX, SOCK_STREAM, 0);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]