gnome-keyring r1381 - in trunk: . common daemon library pam
- From: nnielsen svn gnome org
- To: svn-commits-list gnome org
- Subject: gnome-keyring r1381 - in trunk: . common daemon library pam
- Date: Thu, 11 Dec 2008 23:33:20 +0000 (UTC)
Author: nnielsen
Date: Thu Dec 11 23:33:20 2008
New Revision: 1381
URL: http://svn.gnome.org/viewvc/gnome-keyring?rev=1381&view=rev
Log:
* common/gkr-crypto.c:
* common/gkr-secure-memory.c:
* common/gkr-secure-memory.h:
* daemon/gkr-daemon.c:
* daemon/gkr-daemon.h:
* daemon/gkr-daemon-dbus.c:
* daemon/gkr-daemon-ops.c:
* pam/gkr-pam-module.c: Rework initialization of the daemon
so that most initialization can happen after starting via PAM.
Fixes bug #558181
Modified:
trunk/ChangeLog
trunk/common/gkr-crypto.c
trunk/common/gkr-secure-memory.c
trunk/common/gkr-secure-memory.h
trunk/daemon/gkr-daemon-dbus.c
trunk/daemon/gkr-daemon-ops.c
trunk/daemon/gkr-daemon.c
trunk/daemon/gkr-daemon.h
trunk/library/gnome-keyring-private.h
trunk/library/gnome-keyring-socket.c
trunk/library/gnome-keyring.c
trunk/pam/gkr-pam-module.c
Modified: trunk/common/gkr-crypto.c
==============================================================================
--- trunk/common/gkr-crypto.c (original)
+++ trunk/common/gkr-crypto.c Thu Dec 11 23:33:20 2008
@@ -66,6 +66,8 @@
void
gkr_crypto_setup (void)
{
+ unsigned seed;
+
if (gcrypt_initialized)
return;
@@ -80,6 +82,9 @@
gkr_secure_free);
gcrypt_initialized = TRUE;
+
+ gcry_create_nonce (&seed, sizeof (seed));
+ srand (seed);
}
static const char HEXC[] = "0123456789ABCDEF";
Modified: trunk/common/gkr-secure-memory.c
==============================================================================
--- trunk/common/gkr-secure-memory.c (original)
+++ trunk/common/gkr-secure-memory.c Thu Dec 11 23:33:20 2008
@@ -774,7 +774,7 @@
}
void
-gkr_secure_strfree (char *str)
+gkr_secure_strclear (char *str)
{
volatile char *vp;
size_t len;
@@ -782,12 +782,6 @@
if (!str)
return;
- /*
- * If we're using unpageable 'secure' memory, then the free call
- * should zero out the memory, but because on certain platforms
- * we may be using normal memory, zero it out here just in case.
- */
-
vp = (volatile char*)str;
len = strlen (str);
while (len) {
@@ -795,6 +789,17 @@
vp++;
len--;
}
+}
+
+void
+gkr_secure_strfree (char *str)
+{
+ /*
+ * If we're using unpageable 'secure' memory, then the free call
+ * should zero out the memory, but because on certain platforms
+ * we may be using normal memory, zero it out here just in case.
+ */
+ gkr_secure_strclear (str);
gkr_secure_free_full (str, GKR_SECURE_USE_FALLBACK);
}
Modified: trunk/common/gkr-secure-memory.h
==============================================================================
--- trunk/common/gkr-secure-memory.h (original)
+++ trunk/common/gkr-secure-memory.h Thu Dec 11 23:33:20 2008
@@ -80,6 +80,8 @@
char* gkr_secure_strdup (const char *str);
+void gkr_secure_strclear (char *str);
+
void gkr_secure_strfree (char *str);
#endif /* GKR_SECURE_MEMORY_H */
Modified: trunk/daemon/gkr-daemon-dbus.c
==============================================================================
--- trunk/daemon/gkr-daemon-dbus.c (original)
+++ trunk/daemon/gkr-daemon-dbus.c Thu Dec 11 23:33:20 2008
@@ -202,7 +202,7 @@
dbus_message_unref (msg);
if (!reply) {
- g_warning ("couldn't set environment variable in session: %s", derr.message);
+ g_message ("couldn't set environment variable in session: %s", derr.message);
return;
}
@@ -357,15 +357,6 @@
DBusError derr = { 0 };
const gchar *env;
- /*
- * We may be launched before the DBUS session, (ie: via PAM)
- * and DBus tries to launch itself somehow, so double check
- * that it has really started.
- */
- env = getenv ("DBUS_SESSION_BUS_ADDRESS");
- if (!env || !env[0])
- return;
-
if (dbus_initialized)
return;
@@ -414,7 +405,7 @@
case DBUS_REQUEST_NAME_REPLY_IN_QUEUE:
case DBUS_REQUEST_NAME_REPLY_EXISTS:
g_message ("another gnome-keyring-daemon is running");
- return;
+ break;
default:
g_return_if_reached ();
break;
Modified: trunk/daemon/gkr-daemon-ops.c
==============================================================================
--- trunk/daemon/gkr-daemon-ops.c (original)
+++ trunk/daemon/gkr-daemon-ops.c Thu Dec 11 23:33:20 2008
@@ -1713,8 +1713,11 @@
g_strfreev (environment);
- /* We may have received DBUS environment variable so try and setup DBUS */
- gkr_daemon_dbus_setup ();
+ /*
+ * We've now definitely received everything we need to run. Ask
+ * the daemon to complete the initialization.
+ */
+ gkr_daemon_complete_initialization();
gkr_buffer_add_uint32 (result, GNOME_KEYRING_RESULT_OK);
Modified: trunk/daemon/gkr-daemon.c
==============================================================================
--- trunk/daemon/gkr-daemon.c (original)
+++ trunk/daemon/gkr-daemon.c Thu Dec 11 23:33:20 2008
@@ -90,28 +90,30 @@
/* All the components to run on startup if not set in gconf */
#ifdef WITH_SSH
-#define DEFAULT_COMPONENTS "ssh,keyring,pkcs11"
+#define DEFAULT_COMPONENTS "ssh,pkcs11"
#else
-#define DEFAULT_COMPONENTS "keyring,pkcs11"
+#define DEFAULT_COMPONENTS "pkcs11"
#endif
static gboolean run_foreground = FALSE;
static gboolean run_daemonized = FALSE;
-static gboolean unlock_with_login = FALSE;
-static gboolean start_any_daemon = FALSE;
+static gboolean run_for_login = FALSE;
+static gboolean run_for_start = FALSE;
static gchar* run_components = NULL;
+static gchar* login_password = NULL;
+static gboolean initialization_completed = FALSE;
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, &unlock_with_login,
- "Use login password from stdin", NULL },
- { "start", 's', 0, G_OPTION_ARG_NONE, &start_any_daemon,
- "Start or initialize an already running daemon" },
+ { "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 components to run", DEFAULT_COMPONENTS },
+ "The optional components to run", DEFAULT_COMPONENTS },
{ NULL }
};
@@ -136,9 +138,9 @@
}
/* Check the arguments */
- if (unlock_with_login && start_any_daemon) {
+ if (run_for_login && run_for_start) {
g_printerr ("gnome-keyring-daemon: The --start option is incompatible with --login");
- start_any_daemon = FALSE;
+ run_for_login = FALSE;
}
@@ -369,6 +371,12 @@
/* We only accept a max of 8K as the login password */
#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
+ * password.
+ */
gchar *buf = gkr_secure_alloc (MAX_BLOCK);
gchar *ret = NULL;
@@ -401,28 +409,18 @@
}
static void
-close_stdinout (void)
+cleanup_and_exit (int code)
{
- int fd;
-
- fd = open ("/dev/null", O_RDONLY);
- sane_dup2 (fd, 0);
- close (fd);
-
- fd = open ("/dev/null", O_WRONLY);
- sane_dup2 (fd, 1);
- close (fd);
-
- fd = open ("/dev/null", O_WRONLY);
- sane_dup2 (fd, 2);
- close (fd);
+ gkr_cleanup_perform ();
+ exit (code);
}
static void
-cleanup_and_exit (int code)
+clear_login_password (void)
{
- gkr_cleanup_perform ();
- _exit (code);
+ if(login_password)
+ gkr_secure_strfree (login_password);
+ login_password = NULL;
}
static gboolean
@@ -430,11 +428,32 @@
GIOCondition cond,
gpointer callback_data)
{
- cleanup_and_exit (2);
+ gkr_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;
@@ -445,7 +464,7 @@
}
static gboolean
-initialize_running_daemon (int sock)
+initialize_other_running_daemon (int sock)
{
GnomeKeyringResult res;
gchar **envp, **e;
@@ -506,11 +525,11 @@
* a daemon process, just return and let things go
* their normal way.
*/
- sock = gnome_keyring_socket_connect_daemon (FALSE);
+ sock = gnome_keyring_socket_connect_daemon (FALSE, TRUE);
if (sock == -1)
return FALSE;
- ret = initialize_running_daemon (sock);
+ ret = initialize_other_running_daemon (sock);
close (sock);
/* Initialization failed, start this process up as a daemon */
@@ -532,147 +551,194 @@
return TRUE;
}
-int
-main (int argc, char *argv[])
+static void
+fork_and_print_environment (void)
{
- const char *env;
- int fd;
+ int status;
pid_t pid;
- GIOChannel *channel;
- GMainContext *ctx;
- gchar *login_password;
- unsigned seed;
+ int fd, i;
+
+ if (run_foreground) {
+ print_environment (getpid ());
+ return;
+ }
- g_type_init ();
- g_thread_init (NULL);
+ 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);
+
+ waitpid (pid, &status, 0);
+ if (WEXITSTATUS (status) != 0)
+ exit (WEXITSTATUS (status));
+
+ } else {
+ /* Not double forking, we know the PID */
+ print_environment (pid);
+ }
+
+ /* The initial process exits successfully */
+ exit (0);
+ }
- parse_arguments (&argc, &argv);
+ if (!run_daemonized)
+ return;
-#ifdef HAVE_LOCALE_H
- /* internationalisation */
- setlocale (LC_ALL, "");
-#endif
+ /* Double fork if need to daemonize properly */
+ pid = fork ();
+
+ if (pid != 0) {
-#ifdef HAVE_GETTEXT
- bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
- textdomain (GETTEXT_PACKAGE);
- bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
-#endif
+ /* Here we are in the intermediate child process */
+
+ /*
+ * This process exits, so that the final child will inherit
+ * init as parent to avoid zombies
+ */
+ if (pid == -1)
+ exit (1);
- /*
- * If asked to start a daemon, see if one is already running
- * and initialize it if so.
+ /* 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 process. */
+
+ for (i = 0; i < 3; ++i) {
+ fd = open ("/dev/null", O_RDONLY);
+ sane_dup2 (fd, i);
+ close (fd);
+ }
+}
+
+gboolean
+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 (start_any_daemon) {
- if (start_or_initialize_daemon ())
- return 0;
+
+ if (initialization_completed) {
+ g_message ("The daemon was already initialized.");
+ return TRUE;
}
- gkr_crypto_setup ();
-
- gcry_create_nonce (&seed, sizeof (seed));
- srand (seed);
+ gkr_daemon_dbus_setup ();
/* Initialize object storage */
if (!gkr_pk_object_storage_initialize ())
- cleanup_and_exit (1);
+ return FALSE;
#ifdef ROOT_CERTIFICATES
if (!gkr_pk_root_storage_initialize ())
- cleanup_and_exit (1);
+ return FALSE;
#endif
/* Initialize the appropriate components */
- if (check_run_component ("keyring")) {
- if (!gkr_daemon_io_create_master_socket ())
- cleanup_and_exit (1);
- }
-
+
#ifdef WITH_SSH
if (check_run_component ("ssh")) {
if (!gkr_daemon_ssh_io_initialize () ||
!gkr_ssh_storage_initialize ())
- cleanup_and_exit (1);
+ return FALSE;
}
#endif
if (check_run_component ("pkcs11")) {
if (!gkr_pkcs11_daemon_setup ())
- cleanup_and_exit (1);
- }
-
+ return FALSE;
+ }
+
+ initialization_completed = TRUE;
+ return TRUE;
+}
+
+int
+main (int argc, char *argv[])
+{
+ GMainContext *ctx;
+
/*
- * When --login is specified then the login password is passed
- * in on stdin. All data (including newlines) are part of the
- * password.
+ * 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
+ * --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.
*/
- login_password = unlock_with_login ? read_login_password (STDIN) : NULL;
+
+ g_type_init ();
+ g_thread_init (NULL);
+
+#ifdef HAVE_LOCALE_H
+ /* internationalisation */
+ setlocale (LC_ALL, "");
+#endif
+
+#ifdef HAVE_GETTEXT
+ bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
+ textdomain (GETTEXT_PACKAGE);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+#endif
+
+ gkr_crypto_setup ();
+
+ /* 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 ())
+ cleanup_and_exit (0);
+ }
/*
- * The whole forking and daemonizing dance starts here.
+ * Always initialize the keyring subsystem. This is a necessary
+ * component that everything else depends on in one way or
+ * another.
*/
- if (!run_foreground) {
- pid = fork ();
-
- /* An intermediate child */
- if (pid == 0) {
- if (run_daemonized) {
- pid = fork ();
-
- /* Still in the intermedate child */
- if (pid != 0) {
- gkr_secure_free (login_password);
-
- /* This process exits, so that the
- * final child will inherit init as parent
- * to avoid zombies
- */
- if (pid == -1) {
- exit (1);
- } else {
- /* This is where we know the pid of the daemon.
- * The initial process will waitpid until we exit,
- * so there is no race */
- print_environment (pid);
- exit (0);
- }
- }
- }
-
- /* final child continues here */
-
- /* The initial process */
- } else {
- gkr_secure_free (login_password);
-
- if (run_daemonized) {
- int status;
-
- /* Initial process, waits for intermediate child */
- if (pid == -1)
- exit (1);
-
- waitpid (pid, &status, 0);
- if (WEXITSTATUS (status) != 0)
- exit (WEXITSTATUS (status));
-
- } else {
- print_environment (pid);
- }
-
- exit (0);
- }
-
- /* The final child ... */
- close_stdinout ();
+ if (!gkr_daemon_io_create_master_socket ())
+ cleanup_and_exit (1);
+ /* The --login option. Delayed initialization */
+ if (run_for_login) {
+ login_password = read_login_password (STDIN);
+ atexit (clear_login_password);
+
+ /* Not a login daemon. Initialize now. */
} else {
- print_environment (getpid ());
+ if (!gkr_daemon_complete_initialization ())
+ cleanup_and_exit (1);
}
+
+ /* The whole forking and daemonizing dance starts here. */
+ fork_and_print_environment();
- /* Daemon process continues here */
-
- /* Send all warning or error messages to syslog */
+ /* Prepare logging a second time, since we may be in a different process */
prepare_logging();
loop = g_main_loop_new (NULL, FALSE);
@@ -683,29 +749,19 @@
gkr_unix_signal_connect (ctx, SIGHUP, signal_handler, NULL);
gkr_unix_signal_connect (ctx, SIGTERM, signal_handler, NULL);
- 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);
- }
- }
+ /* TODO: Do we still need this? XFCE still seems to use it. */
+ slave_lifetime_to_fd ();
gkr_async_workers_init (loop);
- gkr_daemon_dbus_setup ();
/*
* Unlock the login keyring if we were given a password on STDIN.
* If it does not exist. We create it.
*/
- if (unlock_with_login && login_password) {
+ if (login_password) {
if (!gkr_keyring_login_unlock (login_password))
g_warning ("Failed to unlock login on startup");
- gkr_secure_free (login_password);
+ gkr_secure_strclear (login_password);
}
g_main_loop_run (loop);
Modified: trunk/daemon/gkr-daemon.h
==============================================================================
--- trunk/daemon/gkr-daemon.h (original)
+++ trunk/daemon/gkr-daemon.h Thu Dec 11 23:33:20 2008
@@ -47,10 +47,12 @@
void gkr_daemon_quit (void);
+gboolean gkr_daemon_complete_initialization (void);
+
gboolean gkr_daemon_io_create_master_socket (void);
+
const gchar* gkr_daemon_io_get_socket_path (void);
-/* Dbus Initialization/Cleanup */
-void gkr_daemon_dbus_setup (void);
+void gkr_daemon_dbus_setup (void);
#endif /* GNOME_KEYRING_DAEMON_H */
Modified: trunk/library/gnome-keyring-private.h
==============================================================================
--- trunk/library/gnome-keyring-private.h (original)
+++ trunk/library/gnome-keyring-private.h Thu Dec 11 23:33:20 2008
@@ -57,7 +57,7 @@
#define GNOME_KEYRING_DAEMON_PATH "/org/gnome/keyring/daemon"
#define GNOME_KEYRING_DAEMON_INTERFACE "org.gnome.keyring.Daemon"
-int gnome_keyring_socket_connect_daemon (gboolean non_blocking);
+int gnome_keyring_socket_connect_daemon (gboolean non_blocking, gboolean only_running);
int gnome_keyring_socket_read_all (int fd, guchar *buf, size_t len);
int gnome_keyring_socket_write_all (int fd, const guchar *buf, size_t len);
gboolean gnome_keyring_socket_read_buffer (int fd, GkrBuffer *buffer);
Modified: trunk/library/gnome-keyring-socket.c
==============================================================================
--- trunk/library/gnome-keyring-socket.c (original)
+++ trunk/library/gnome-keyring-socket.c Thu Dec 11 23:33:20 2008
@@ -123,7 +123,7 @@
}
int
-gnome_keyring_socket_connect_daemon (gboolean non_blocking)
+gnome_keyring_socket_connect_daemon (gboolean non_blocking, gboolean only_running)
{
const gchar *epath = NULL;
int sock = -1;
@@ -140,7 +140,7 @@
}
/* Try using DBus to find daemon */
- if (sock < 0) {
+ if (sock < 0 && !only_running) {
gchar *dpath = find_daemon_via_dbus ();
if (dpath) {
sock = connect_to_daemon_at (dpath);
Modified: trunk/library/gnome-keyring.c
==============================================================================
--- trunk/library/gnome-keyring.c (original)
+++ trunk/library/gnome-keyring.c Thu Dec 11 23:33:20 2008
@@ -339,7 +339,7 @@
close (op->socket);
}
- op->socket = gnome_keyring_socket_connect_daemon (TRUE);
+ op->socket = gnome_keyring_socket_connect_daemon (TRUE, FALSE);
if (op->socket < 0) {
schedule_op_failed (op, GNOME_KEYRING_RESULT_NO_KEYRING_DAEMON);
} else {
@@ -366,7 +366,7 @@
g_assert (buffer != NULL);
g_assert (receive_buffer != NULL);
- socket = gnome_keyring_socket_connect_daemon (FALSE);
+ socket = gnome_keyring_socket_connect_daemon (FALSE, FALSE);
if (socket < 0)
return GNOME_KEYRING_RESULT_NO_KEYRING_DAEMON;
@@ -399,7 +399,7 @@
{
int socket;
- socket = gnome_keyring_socket_connect_daemon (FALSE);
+ socket = gnome_keyring_socket_connect_daemon (FALSE, FALSE);
if (socket < 0) {
return FALSE;
}
Modified: trunk/pam/gkr-pam-module.c
==============================================================================
--- trunk/pam/gkr-pam-module.c (original)
+++ trunk/pam/gkr-pam-module.c Thu Dec 11 23:33:20 2008
@@ -271,7 +271,7 @@
setup_child (int inp[2], int outp[2], int errp[2],
pam_handle_t *ph, struct passwd *pwd, const char *password)
{
- char *args[] = { GNOME_KEYRING_DAEMON, "-d", "--login", NULL};
+ char *args[] = { GNOME_KEYRING_DAEMON, "--daemonize", "--login", NULL};
const char* display;
int i, ret;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]