[gnome-keyring] [daemon] Rework signal handling, startup procedure.



commit 7d19e6eb281a60b6f39af32b1242b808f0f7edd0
Author: Stef Walter <stef memberwebs com>
Date:   Sun Aug 30 02:00:07 2009 +0000

    [daemon] Rework signal handling, startup procedure.
    
    Reworking the signal handling, so we have a specific thread for
    handling signals. All other threads ignore signals. This is the
    recommended way to 'mix' signals and threads.
    
    In addition we move the part of startup that we can perform
    after forking into separate procedures. In particular we try
    to prevent starting threads until after we've forked. Besides
    the obvious sanity, this helps the signal handling to work
    for all threads.

 daemon/gkr-daemon-dbus.c                     |    2 +-
 daemon/gkr-daemon.c                          |  164 +++++++++++++++++++------
 daemon/gkr-daemon.h                          |    4 +-
 daemon/pkcs11/gkr-pkcs11-daemon.c            |   43 ++++---
 daemon/pkcs11/gkr-pkcs11-daemon.h            |    4 +-
 pkcs11/rpc-layer/gck-rpc-daemon-standalone.c |    6 +-
 pkcs11/rpc-layer/gck-rpc-dispatch.c          |   68 ++++++++---
 pkcs11/rpc-layer/gck-rpc-layer.h             |   11 ++-
 pkcs11/ssh-agent/gck-ssh-agent-private.h     |    2 +-
 pkcs11/ssh-agent/gck-ssh-agent-standalone.c  |   16 ++-
 pkcs11/ssh-agent/gck-ssh-agent.c             |  165 ++++++++++++--------------
 pkcs11/ssh-agent/gck-ssh-agent.h             |    6 +-
 12 files changed, 313 insertions(+), 178 deletions(-)
---
diff --git a/daemon/gkr-daemon-dbus.c b/daemon/gkr-daemon-dbus.c
index fb6eb1b..10d1c15 100644
--- a/daemon/gkr-daemon-dbus.c
+++ b/daemon/gkr-daemon-dbus.c
@@ -387,7 +387,7 @@ daemon_dbus_cleanup (gpointer unused)
 }
 
 void 
-gkr_daemon_dbus_setup (void)
+gkr_daemon_dbus_initialize (void)
 {
 	dbus_uint32_t res = 0;
 	DBusError derr = { 0 };
diff --git a/daemon/gkr-daemon.c b/daemon/gkr-daemon.c
index 39a8c61..c63081e 100644
--- a/daemon/gkr-daemon.c
+++ b/daemon/gkr-daemon.c
@@ -28,7 +28,6 @@
 #include "egg/egg-libgcrypt.h"
 #include "egg/egg-secure-memory.h"
 #include "egg/egg-unix-credentials.h"
-#include "egg/egg-unix-signal.h"
 
 #include "keyrings/gkr-keyring-login.h"
 
@@ -69,8 +68,6 @@
 #define  STDOUT  1
 #define  STDERR  2
 
-static GMainLoop *loop = NULL;
-
 #ifndef HAVE_SOCKLEN_T
 #define socklen_t int
 #endif
@@ -330,19 +327,98 @@ prepare_logging ()
     g_log_set_default_handler (log_handler, NULL);
 }
 
+/* -----------------------------------------------------------------------------
+ * SIGNALS
+ */
+
+static sigset_t signal_set;
+static gint signal_quitting = 0;
+
+static gpointer
+signal_thread (gpointer user_data)
+{
+	GMainLoop *loop = user_data;
+	int sig, err;
+
+	for (;;) {
+		err = sigwait (&signal_set, &sig);
+		if (err != EINTR && err != 0) {
+			g_warning ("couldn't wait for signals: %s", g_strerror (err));
+			return NULL;
+		}
+
+		switch (sig) {
+		case SIGPIPE:
+			/* Ignore */
+			break;
+		case SIGINT:
+		case SIGHUP:
+		case SIGTERM:
+			g_atomic_int_set (&signal_quitting, 1);
+			g_main_loop_quit (loop);
+			return NULL;
+		default:
+			g_warning ("received unexpected signal when waiting for signals: %d", sig);
+			break;
+		}
+	}
+
+	g_assert_not_reached ();
+	return NULL;
+}
+
+static void
+setup_signal_handling (GMainLoop *loop)
+{
+	GError *error = NULL;
+
+	/*
+	 * Block these signals for this thread, and any threads
+	 * started up after this point (so essentially all threads).
+	 *
+	 * We also start a signal handling thread which uses signal_set
+	 * to catch the various signals we're interested in.
+	 */
+
+	sigemptyset (&signal_set);
+	sigaddset (&signal_set, SIGPIPE);
+	sigaddset (&signal_set, SIGINT);
+	sigaddset (&signal_set, SIGHUP);
+	sigaddset (&signal_set, SIGTERM);
+	pthread_sigmask (SIG_BLOCK, &signal_set, NULL);
+
+	g_thread_create (signal_thread, loop, FALSE, &error);
+	if (error != NULL) {
+		g_warning ("couldn't startup thread for signal handling: %s",
+		           error && error->message ? error->message : "");
+		g_clear_error (&error);
+	}
+}
+
 void
 gkr_daemon_quit (void)
 {
-	g_main_loop_quit (loop);
+	/*
+	 * Send a signal to terminate our signal thread,
+	 * which in turn runs stops the main loop and that
+	 * starts the shutdown process.
+	 */
+
+	raise (SIGTERM);
 }
 
-static gboolean
-signal_handler (guint sig, gpointer unused)
+static void
+cleanup_signal_handling (void)
 {
-	gkr_daemon_quit ();
-	return TRUE;
+	/* The thread is not joinable, so cleans itself up */
+	if (!g_atomic_int_get (&signal_quitting))
+		g_warning ("gkr_daemon_quit() was not used to shutdown the daemon");
 }
 
+/* -----------------------------------------------------------------------------
+ * STARTUP
+ */
+
 static int
 sane_dup2 (int fd1, int fd2)
 {
@@ -614,59 +690,60 @@ fork_and_print_environment (void)
 }
 
 static gboolean
-gkr_daemon_complete_initialization_steps (void)
+gkr_daemon_startup_steps (void)
 {
-	/* Initialize new style PKCS#11 components */
-	if (!gkr_pkcs11_daemon_initialize ())
-		return FALSE;
-	
-	/* Initialize the appropriate components */
-	
+	/* Startup the appropriate components, creates sockets etc.. */
 #ifdef WITH_SSH	
 	if (check_run_component ("ssh")) {
-		if (!gkr_pkcs11_daemon_setup_ssh ())
+		if (!gkr_pkcs11_daemon_startup_ssh ())
 			return FALSE;
 	}
 #endif
-	
+
 	if (check_run_component ("pkcs11")) {
-		if (!gkr_pkcs11_daemon_setup_pkcs11 ())
+		if (!gkr_pkcs11_daemon_startup_pkcs11 ())
 			return FALSE;
 	}
-	
-	gkr_daemon_dbus_setup ();
-	
-	initialization_completed = TRUE;
+
+	return TRUE;
+}
+
+static gboolean
+gkr_daemon_initialize_steps (void)
+{
+	/* Initialize new style PKCS#11 components */
+	if (!gkr_pkcs11_daemon_initialize ())
+		return FALSE;
+
+	gkr_daemon_dbus_initialize ();
 	return TRUE;
 }
 
-gboolean
+void
 gkr_daemon_complete_initialization (void)
 {
 	/*
 	 * Sometimes we don't initialize the full daemon right on 
 	 * startup. When run with --login is one such case.
 	 */
-	
+
 	if (initialization_completed) {
 		g_message ("The daemon was already initialized.");
-		return TRUE;
+		return;
 	}
 
 	/* Set this early so that two initializations don't overlap */
 	initialization_completed = TRUE;
-
-	/* But then set it back if initializing fails */
-	initialization_completed = gkr_daemon_complete_initialization_steps ();
-
-	return initialization_completed;
+	gkr_daemon_startup_steps ();
+	gkr_daemon_initialize_steps ();
 }
 
 int
 main (int argc, char *argv[])
 {
 	GMainContext *ctx;
-	
+	GMainLoop *loop;
+
 	/* 
 	 * The gnome-keyring startup is not as simple as I wish it could be. 
 	 * 
@@ -731,24 +808,28 @@ main (int argc, char *argv[])
 	if (run_for_login) {
 		login_password = read_login_password (STDIN);
 		atexit (clear_login_password);
-	
-	/* Not a login daemon. Initialize now. */
+
+	/* Not a login daemon. Startup stuff now.*/
 	} else {
-		if (!gkr_daemon_complete_initialization ())
+		/* These are things that can run before forking */
+		if (!gkr_daemon_startup_steps ())
 			cleanup_and_exit (1);
 	}
-	 
+
 	/* The whole forking and daemonizing dance starts here. */
 	fork_and_print_environment();
 
+	setup_signal_handling (loop);
+
 	/* Prepare logging a second time, since we may be in a different process */
 	prepare_logging();
 
-	signal (SIGPIPE, SIG_IGN);
-	egg_unix_signal_connect (ctx, SIGINT, signal_handler, NULL);
-	egg_unix_signal_connect (ctx, SIGHUP, signal_handler, NULL);
-	egg_unix_signal_connect (ctx, SIGTERM, signal_handler, NULL);
-             
+	/* Remainder initialization after forking, if initialization not delayed */
+	if (!run_for_login) {
+		initialization_completed = TRUE;
+		gkr_daemon_initialize_steps ();
+	}
+
 	/* TODO: Do we still need this? XFCE still seems to use it. */
 	slave_lifetime_to_fd ();
 
@@ -773,5 +854,8 @@ main (int argc, char *argv[])
 	/* Final shutdown of anything workers running about */
 	gkr_daemon_async_workers_uninit ();
 
+	/* Wrap up signal handling here */
+	cleanup_signal_handling ();
+
 	return 0;
 }
diff --git a/daemon/gkr-daemon.h b/daemon/gkr-daemon.h
index f37fd7e..e2d9c2a 100644
--- a/daemon/gkr-daemon.h
+++ b/daemon/gkr-daemon.h
@@ -47,12 +47,12 @@ extern GkrDaemonOperation keyring_ops[];
 
 void           gkr_daemon_quit (void);
 
-gboolean       gkr_daemon_complete_initialization (void);
+void           gkr_daemon_complete_initialization (void);
 
 gboolean       gkr_daemon_io_create_master_socket (void);
 
 const gchar*   gkr_daemon_io_get_socket_path      (void);
 
-void           gkr_daemon_dbus_setup              (void);
+void           gkr_daemon_dbus_initialize         (void);
 
 #endif /* GNOME_KEYRING_DAEMON_H */
diff --git a/daemon/pkcs11/gkr-pkcs11-daemon.c b/daemon/pkcs11/gkr-pkcs11-daemon.c
index 8a213b7..4f36d5e 100644
--- a/daemon/pkcs11/gkr-pkcs11-daemon.c
+++ b/daemon/pkcs11/gkr-pkcs11-daemon.c
@@ -57,9 +57,11 @@ pkcs11_daemon_cleanup (gpointer unused)
 	CK_RV rv;
 	
 	g_assert (pkcs11_roof);
-	
+
 	gkr_daemon_async_begin_concurrent ();
-	
+
+		gck_ssh_agent_uninitialize ();
+		gck_rpc_layer_uninitialize ();
 		rv = (pkcs11_roof->C_Finalize) (NULL);
 	
 	gkr_daemon_async_end_concurrent ();
@@ -77,6 +79,7 @@ gkr_pkcs11_daemon_initialize (void)
 	CK_FUNCTION_LIST_PTR roots_store; 
 	CK_FUNCTION_LIST_PTR ssh_store;
 	CK_FUNCTION_LIST_PTR user_store;
+	gboolean ret;
 	CK_RV rv;
 
 	/* Now initialize them all */
@@ -115,7 +118,15 @@ gkr_pkcs11_daemon_initialize (void)
 	}		
 	
 	egg_cleanup_register (pkcs11_daemon_cleanup, NULL);
-	return TRUE;
+
+	gkr_daemon_async_begin_concurrent ();
+
+		ret = gck_ssh_agent_initialize (pkcs11_roof) &&
+		      gck_rpc_layer_initialize (pkcs11_roof);
+
+	gkr_daemon_async_end_concurrent ();
+
+	return ret;
 }
 
 static void
@@ -123,8 +134,8 @@ pkcs11_rpc_cleanup (gpointer unused)
 {
 	gkr_daemon_async_begin_concurrent ();
 
-		gck_rpc_layer_uninitialize ();
-		
+		gck_rpc_layer_shutdown ();
+
 	gkr_daemon_async_end_concurrent ();
 }
 
@@ -142,21 +153,19 @@ accept_rpc_client (GIOChannel *channel, GIOCondition cond, gpointer unused)
 }
 
 gboolean
-gkr_pkcs11_daemon_setup_pkcs11 (void)
+gkr_pkcs11_daemon_startup_pkcs11 (void)
 {
 	GIOChannel *channel;
 	const gchar *base_dir;
 	int sock;
-	
-	g_assert (pkcs11_roof);
 
 	base_dir = gkr_daemon_util_get_master_directory ();
 	g_return_val_if_fail (base_dir, FALSE);
 
 	gkr_daemon_async_begin_concurrent ();
 
-		sock = gck_rpc_layer_initialize (base_dir, pkcs11_roof);
-		
+		sock = gck_rpc_layer_startup (base_dir);
+
 	gkr_daemon_async_end_concurrent ();
 	
 	if (sock == -1)
@@ -176,8 +185,8 @@ pkcs11_ssh_cleanup (gpointer unused)
 {
 	gkr_daemon_async_begin_concurrent ();
 
-		gck_ssh_agent_uninitialize ();
-		
+		gck_ssh_agent_shutdown ();
+
 	gkr_daemon_async_end_concurrent ();
 }
 
@@ -195,21 +204,19 @@ accept_ssh_client (GIOChannel *channel, GIOCondition cond, gpointer unused)
 }
 
 gboolean
-gkr_pkcs11_daemon_setup_ssh (void)
+gkr_pkcs11_daemon_startup_ssh (void)
 {
 	GIOChannel *channel;
 	const gchar *base_dir;
 	int sock;
-	
-	g_assert (pkcs11_roof);
 
 	base_dir = gkr_daemon_util_get_master_directory ();
 	g_return_val_if_fail (base_dir, FALSE);
 
 	gkr_daemon_async_begin_concurrent ();
-	
-		sock = gck_ssh_agent_initialize (base_dir, pkcs11_roof);
-		
+
+		sock = gck_ssh_agent_startup (base_dir);
+
 	gkr_daemon_async_end_concurrent ();
 	
 	if (sock == -1)
diff --git a/daemon/pkcs11/gkr-pkcs11-daemon.h b/daemon/pkcs11/gkr-pkcs11-daemon.h
index 2d4ef63..d41bc78 100644
--- a/daemon/pkcs11/gkr-pkcs11-daemon.h
+++ b/daemon/pkcs11/gkr-pkcs11-daemon.h
@@ -26,8 +26,8 @@
 
 gboolean      gkr_pkcs11_daemon_initialize       (void);
 
-gboolean      gkr_pkcs11_daemon_setup_pkcs11     (void);
+gboolean      gkr_pkcs11_daemon_startup_pkcs11   (void);
 
-gboolean      gkr_pkcs11_daemon_setup_ssh        (void);
+gboolean      gkr_pkcs11_daemon_startup_ssh      (void);
 
 #endif /* GKRPKCS11DAEMON_H_ */
diff --git a/pkcs11/rpc-layer/gck-rpc-daemon-standalone.c b/pkcs11/rpc-layer/gck-rpc-daemon-standalone.c
index 2134a4e..c806d53 100644
--- a/pkcs11/rpc-layer/gck-rpc-daemon-standalone.c
+++ b/pkcs11/rpc-layer/gck-rpc-daemon-standalone.c
@@ -100,7 +100,8 @@ main (int argc, char *argv[])
 		exit (1);
 	}
 	
-	sock = gck_rpc_layer_initialize (SOCKET_PATH, funcs);
+	gck_rpc_layer_initialize (funcs);
+	sock = gck_rpc_layer_startup (SOCKET_PATH);
 	if (sock == -1)
 		exit (1);
 	
@@ -120,6 +121,7 @@ main (int argc, char *argv[])
 			gck_rpc_layer_accept ();
 	}
 	
+	gck_rpc_layer_shutdown ();
 	gck_rpc_layer_uninitialize ();
 	
 	rv = (funcs->C_Finalize) (NULL);
@@ -129,4 +131,4 @@ main (int argc, char *argv[])
 	dlclose(module);
 
 	return 0;
-}
\ No newline at end of file
+}
diff --git a/pkcs11/rpc-layer/gck-rpc-dispatch.c b/pkcs11/rpc-layer/gck-rpc-dispatch.c
index ae722d3..58e0533 100644
--- a/pkcs11/rpc-layer/gck-rpc-dispatch.c
+++ b/pkcs11/rpc-layer/gck-rpc-dispatch.c
@@ -2234,7 +2234,53 @@ gck_rpc_layer_accept (void)
 }
 
 int
-gck_rpc_layer_initialize (const char *prefix, CK_FUNCTION_LIST_PTR module)
+gck_rpc_layer_initialize (CK_FUNCTION_LIST_PTR module)
+{
+	assert (module);
+
+	/* cannot be called more than once */
+	assert (!pkcs11_module);
+	pkcs11_module = module;
+	return 1;
+}
+
+void
+gck_rpc_layer_uninitialize (void)
+{
+	DispatchState *ds, *next;
+
+	if (!pkcs11_module)
+		return;
+
+	/* Close our main listening socket */
+	if (pkcs11_socket != -1)
+		close (pkcs11_socket);
+	pkcs11_socket = -1;
+
+	/* Delete our unix socket */
+	if(pkcs11_socket_path[0])
+		unlink (pkcs11_socket_path);
+	pkcs11_socket_path[0] = 0;
+
+	/* Stop all of the dispatch threads */
+	for (ds = pkcs11_dispatchers; ds; ds = next) {
+		next = ds->next;
+
+		/* Forcibly shutdown the connection */
+		if (ds->socket)
+			shutdown (ds->socket, SHUT_RDWR);
+		g_thread_join (ds->thread);
+
+		/* This is always closed by dispatch thread */
+		assert (ds->socket == -1);
+		free (ds);
+	}
+
+	pkcs11_module = NULL;
+}
+
+int
+gck_rpc_layer_startup (const char *prefix)
 {
 	struct sockaddr_un addr;
 	int sock;
@@ -2243,14 +2289,12 @@ gck_rpc_layer_initialize (const char *prefix, CK_FUNCTION_LIST_PTR module)
 	GCK_RPC_CHECK_CALLS ();
 #endif
 
-	assert (module);
 	assert (prefix);
 
 	/* cannot be called more than once */
-	assert (!pkcs11_module);
 	assert (pkcs11_socket == -1);
 	assert (pkcs11_dispatchers == NULL);
-	
+
 	snprintf (pkcs11_socket_path, sizeof (pkcs11_socket_path), 
 	          "%s/socket.pkcs11", prefix);
 
@@ -2259,7 +2303,7 @@ gck_rpc_layer_initialize (const char *prefix, CK_FUNCTION_LIST_PTR module)
 		gck_rpc_warn ("couldn't create pkcs11 socket: %s", strerror (errno));
 		return -1;
 	}
-	
+
 	memset(&addr, 0, sizeof(addr));
 	addr.sun_family = AF_UNIX;
 	unlink (pkcs11_socket_path);
@@ -2269,27 +2313,23 @@ gck_rpc_layer_initialize (const char *prefix, CK_FUNCTION_LIST_PTR module)
 		                  pkcs11_socket_path, strerror (errno));
 		return -1;
 	}
-	
+
 	if (listen (sock, 128) < 0) {
 		gck_rpc_warn ("couldn't listen on pkcs11 socket: %s: %s", 
 		                  pkcs11_socket_path, strerror (errno));
 		return -1;
 	}
-	
-	pkcs11_module = module;
+
 	pkcs11_socket = sock;
 	pkcs11_dispatchers = NULL;
-	
+
 	return sock;
 }
 
 void
-gck_rpc_layer_uninitialize (void)
+gck_rpc_layer_shutdown (void)
 {
 	DispatchState *ds, *next;
-	
-	if (!pkcs11_module)
-		return;
 
 	/* Close our main listening socket */
 	if (pkcs11_socket != -1) 
@@ -2314,6 +2354,4 @@ gck_rpc_layer_uninitialize (void)
 		assert (ds->socket == -1);
 		free (ds);
 	}
-	
-	pkcs11_module = NULL;
 }
diff --git a/pkcs11/rpc-layer/gck-rpc-layer.h b/pkcs11/rpc-layer/gck-rpc-layer.h
index 7486193..913b54b 100644
--- a/pkcs11/rpc-layer/gck-rpc-layer.h
+++ b/pkcs11/rpc-layer/gck-rpc-layer.h
@@ -7,14 +7,19 @@
  * DISPATCHER 
  */
 
-/* Call to initialize the module and start listening, returns socket or -1 */
-int                gck_rpc_layer_initialize             (const char *prefix, 
-                                                         CK_FUNCTION_LIST_PTR funcs);
+/* Call to initialize the module */
+int                gck_rpc_layer_initialize             (CK_FUNCTION_LIST_PTR funcs);
 
 /* Should be called to cleanup dispatcher */
 void               gck_rpc_layer_uninitialize           (void);
 
+/* Call to start listening, returns socket or -1 */
+int                gck_rpc_layer_startup                (const char *prefix);
+
 /* Accept a new connection. Should be called when above fd has read */
 void               gck_rpc_layer_accept                 (void);
 
+/* Call to shutdown socket */
+void               gck_rpc_layer_shutdown               (void);
+
 #endif /* GCKRPC_LAYER_H_ */
diff --git a/pkcs11/ssh-agent/gck-ssh-agent-private.h b/pkcs11/ssh-agent/gck-ssh-agent-private.h
index 47ce045..08af331 100644
--- a/pkcs11/ssh-agent/gck-ssh-agent-private.h
+++ b/pkcs11/ssh-agent/gck-ssh-agent-private.h
@@ -91,7 +91,7 @@ extern const GckSshAgentOperation gck_ssh_agent_operations[GCK_SSH_OP_MAX];
  * gck-ssh-agent.c
  */
 
-int                   gck_ssh_agent_initialize_with_module          (const gchar *prefix, GP11Module *module);
+gboolean              gck_ssh_agent_initialize_with_module          (GP11Module *module);
 
 GP11Session*          gck_ssh_agent_checkout_main_session           (void);
 
diff --git a/pkcs11/ssh-agent/gck-ssh-agent-standalone.c b/pkcs11/ssh-agent/gck-ssh-agent-standalone.c
index 0a2782f..16e03d5 100644
--- a/pkcs11/ssh-agent/gck-ssh-agent-standalone.c
+++ b/pkcs11/ssh-agent/gck-ssh-agent-standalone.c
@@ -83,6 +83,7 @@ main(int argc, char *argv[])
 	GError *error = NULL;
 	GIOChannel *channel;
 	GMainLoop *loop;
+	gboolean ret;
 	int sock;
 	
 	g_type_init ();
@@ -107,12 +108,16 @@ main(int argc, char *argv[])
 	g_signal_connect (module, "authenticate-object", G_CALLBACK (authenticate_object), NULL);
 	gp11_module_set_auto_authenticate (module, GP11_AUTHENTICATE_OBJECTS);
 
-	sock = gck_ssh_agent_initialize_with_module ("/tmp", module);
+	ret = gck_ssh_agent_initialize_with_module (module);
 	g_object_unref (module);
-	
+
+	if (ret == FALSE)
+		return 1;
+
+	sock = gck_ssh_agent_startup ("/tmp");
 	if (sock == -1)
 		return 1;
-	
+
 	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);
@@ -123,8 +128,9 @@ main(int argc, char *argv[])
 	loop = g_main_loop_new (NULL, FALSE);
 	g_main_loop_run (loop);
 	g_main_loop_unref (loop);
-	
+
+	gck_ssh_agent_shutdown ();
 	gck_ssh_agent_uninitialize ();
-	
+
 	return 0;
 }
diff --git a/pkcs11/ssh-agent/gck-ssh-agent.c b/pkcs11/ssh-agent/gck-ssh-agent.c
index c235726..7b4d0ac 100644
--- a/pkcs11/ssh-agent/gck-ssh-agent.c
+++ b/pkcs11/ssh-agent/gck-ssh-agent.c
@@ -191,52 +191,6 @@ static gboolean pkcs11_main_checked = FALSE;
 static GMutex *pkcs11_main_mutex = NULL;
 static GCond *pkcs11_main_cond = NULL;
 
-static gboolean
-init_pkcs11 (GP11Module *module)
-{
-	GP11Session *session = NULL;
-	GList *slots, *l;
-	GP11Mechanisms *mechs;
-	GError *error = NULL;
-	
-	g_assert (GP11_IS_MODULE (module));
-	
-	/* Find a good slot for our session keys */
-	slots = gp11_module_get_slots (module, TRUE);
-	for (l = slots; session == NULL && l; l = g_list_next (l)) {
-		
-		/* Check that it has the mechanisms we need */
-		mechs = gp11_slot_get_mechanisms (l->data);
-		if (gp11_mechanisms_check (mechs, CKM_RSA_PKCS, CKM_DSA, GP11_INVALID)) {
-
-			/* Try and open a session */
-			session = gp11_slot_open_session (l->data, CKF_SERIAL_SESSION, &error);
-			if (!session) {
-				g_warning ("couldn't create pkcs#11 session: %s", error->message);
-				g_clear_error (&error);
-			}
-		}
-		
-		gp11_mechanisms_free (mechs);
-	}
-	
-	gp11_list_unref_free (slots);
-	
-	if (!session) {
-		g_warning ("couldn't select a usable pkcs#11 slot for the ssh agent to use");
-		return FALSE;
-	}
-
-	pkcs11_module = g_object_ref (module);
-	
-	pkcs11_main_mutex = g_mutex_new ();
-	pkcs11_main_cond = g_cond_new ();
-	pkcs11_main_checked = FALSE;
-	pkcs11_main_session = session;
-	
-	return TRUE;
-}
-
 GP11Session*
 gck_ssh_agent_checkout_main_session (void)
 {
@@ -272,28 +226,6 @@ gck_ssh_agent_checkin_main_session (GP11Session *session)
 	g_mutex_unlock (pkcs11_main_mutex);
 }
 
-static void
-uninit_pkcs11 (void)
-{
-	gboolean ret;
-	
-	g_assert (pkcs11_main_mutex);
-	ret = g_mutex_trylock (pkcs11_main_mutex);
-	g_assert (ret);
-
-		g_assert (GP11_IS_SESSION (pkcs11_main_session));
-		g_assert (!pkcs11_main_checked);
-		g_object_unref (pkcs11_main_session);
-		pkcs11_main_session = NULL;
-		
-	g_mutex_unlock (pkcs11_main_mutex);
-	g_mutex_free (pkcs11_main_mutex);
-	g_cond_free (pkcs11_main_cond);
-	
-	g_assert (pkcs11_module);
-	g_object_unref (pkcs11_module);
-}
-
 /* --------------------------------------------------------------------------------------
  * MAIN THREAD
  */
@@ -358,7 +290,7 @@ gck_ssh_agent_accept (void)
 }
 
 void 
-gck_ssh_agent_uninitialize (void)
+gck_ssh_agent_shutdown (void)
 {
 	Client *client;
 	GList *l;
@@ -385,36 +317,99 @@ gck_ssh_agent_uninitialize (void)
 	
 	g_list_free (socket_clients);
 	socket_clients = NULL;
-	
-	uninit_pkcs11 ();
+}
+
+void
+gck_ssh_agent_uninitialize (void)
+{
+	gboolean ret;
+
+	g_assert (pkcs11_main_mutex);
+	ret = g_mutex_trylock (pkcs11_main_mutex);
+	g_assert (ret);
+
+		g_assert (GP11_IS_SESSION (pkcs11_main_session));
+		g_assert (!pkcs11_main_checked);
+		g_object_unref (pkcs11_main_session);
+		pkcs11_main_session = NULL;
+
+	g_mutex_unlock (pkcs11_main_mutex);
+	g_mutex_free (pkcs11_main_mutex);
+	g_cond_free (pkcs11_main_cond);
+
+	g_assert (pkcs11_module);
+	g_object_unref (pkcs11_module);
 }
 
 int
-gck_ssh_agent_initialize (const gchar *prefix, CK_FUNCTION_LIST_PTR funcs)
+gck_ssh_agent_initialize (CK_FUNCTION_LIST_PTR funcs)
 {
 	GP11Module *module;
-	int sock;
-	
+	gboolean ret;
+
 	g_return_val_if_fail (funcs, -1);
-	g_return_val_if_fail (prefix, -1);
-	
+
 	module = gp11_module_new (funcs);
 	gp11_module_set_auto_authenticate (module, GP11_AUTHENTICATE_OBJECTS);
 	gp11_module_set_pool_sessions (module, TRUE);
-	sock = gck_ssh_agent_initialize_with_module (prefix, module);
+	ret = gck_ssh_agent_initialize_with_module (module);
 	g_object_unref (module);
-		
-	return sock;
+	return ret;
+}
+
+gboolean
+gck_ssh_agent_initialize_with_module (GP11Module *module)
+{
+	GP11Session *session = NULL;
+	GList *slots, *l;
+	GP11Mechanisms *mechs;
+	GError *error = NULL;
+
+	g_assert (GP11_IS_MODULE (module));
+
+	/* Find a good slot for our session keys */
+	slots = gp11_module_get_slots (module, TRUE);
+	for (l = slots; session == NULL && l; l = g_list_next (l)) {
+
+		/* Check that it has the mechanisms we need */
+		mechs = gp11_slot_get_mechanisms (l->data);
+		if (gp11_mechanisms_check (mechs, CKM_RSA_PKCS, CKM_DSA, GP11_INVALID)) {
+
+			/* Try and open a session */
+			session = gp11_slot_open_session (l->data, CKF_SERIAL_SESSION, &error);
+			if (!session) {
+				g_warning ("couldn't create pkcs#11 session: %s", error->message);
+				g_clear_error (&error);
+			}
+		}
+
+		gp11_mechanisms_free (mechs);
+	}
+
+	gp11_list_unref_free (slots);
+
+	if (!session) {
+		g_warning ("couldn't select a usable pkcs#11 slot for the ssh agent to use");
+		return FALSE;
+	}
+
+	pkcs11_module = g_object_ref (module);
+
+	pkcs11_main_mutex = g_mutex_new ();
+	pkcs11_main_cond = g_cond_new ();
+	pkcs11_main_checked = FALSE;
+	pkcs11_main_session = session;
+
+	return TRUE;
 }
 
 int 
-gck_ssh_agent_initialize_with_module (const gchar *prefix, GP11Module *module)
+gck_ssh_agent_startup (const gchar *prefix)
 {
 	struct sockaddr_un addr;
 	int sock;
 	
 	g_return_val_if_fail (prefix, -1);
-	g_return_val_if_fail (GP11_IS_MODULE (module), -1);
 	
 	snprintf (socket_path, sizeof (socket_path), "%s/socket.ssh", prefix);
 	unlink (socket_path);
@@ -439,13 +434,7 @@ gck_ssh_agent_initialize_with_module (const gchar *prefix, GP11Module *module)
 		close (sock);
 		return -1;
 	}
-	
-	/* Load our main session */
-	if (!init_pkcs11 (module)) {
-		close (sock);
-		return -1;
-	}
-	
+
 	g_setenv ("SSH_AUTH_SOCK", socket_path, TRUE);
 	
 	socket_fd = sock;
diff --git a/pkcs11/ssh-agent/gck-ssh-agent.h b/pkcs11/ssh-agent/gck-ssh-agent.h
index f544b20..529a940 100644
--- a/pkcs11/ssh-agent/gck-ssh-agent.h
+++ b/pkcs11/ssh-agent/gck-ssh-agent.h
@@ -5,10 +5,14 @@
 
 #include "pkcs11/pkcs11.h"
 
-int               gck_ssh_agent_initialize              (const gchar *prefix, CK_FUNCTION_LIST_PTR funcs);
+int               gck_ssh_agent_startup                 (const gchar *prefix);
 
 void              gck_ssh_agent_accept                  (void);
 
+void              gck_ssh_agent_shutdown                (void);
+
+gboolean          gck_ssh_agent_initialize              (CK_FUNCTION_LIST_PTR funcs);
+
 void              gck_ssh_agent_uninitialize            (void);
 
 #endif /* GCKSSHAGENT_H_ */



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