[gnome-keyring] daemon: Stop exporting the $GNOME_KEYRING_CONTROL env variable



commit 2ca51a0aef5b1bc41f2e71d2b65edc8478dab69d
Author: Stef Walter <stefw gnome org>
Date:   Thu Mar 6 08:49:33 2014 +0100

    daemon: Stop exporting the $GNOME_KEYRING_CONTROL env variable
    
    In cases where we're using $XDG_RUNTIME_DIR to create a predictable
    control socket directory, stop setting the $GNOME_KEYRING_CONTROL
    environment variable.
    
    Note that we don't use the $XDG_RUNTIME_DIR fallback. This is because
    two of our clients don't link in GLib, both the pam and pkcs11
    modules. Getting involved in the whole tree of fallback possibilities
    for how to resolve $XDG_RUNTIME_DIR is not something I'm interested
    in duplicating.
    
    So instead what we do is if $XDG_RUNTIME_DIR is not set, we fall back
    to using the old $GNOME_KEYRING_CONTROL environment variable.
    
    We use the GLib logic when looking for XDG_RUNTIME_DIR. The variable
    is considered present even when empty.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=725801

 daemon/control/gkd-control-codes.h |    3 +-
 daemon/gkd-main.c                  |   10 ++
 daemon/gkd-util.c                  |    8 ++-
 daemon/test-shutdown.c             |   14 +--
 daemon/test-startup.c              |   41 ++++++++-
 pam/gkr-pam-client.c               |   95 +++++++++++++-------
 pam/gkr-pam-module.c               |  173 +++++++++++++-----------------------
 pam/test-pam.c                     |   32 +++----
 pkcs11/rpc-layer/gkm-rpc-module.c  |   11 +++
 pkcs11/rpc-layer/test-initialize.c |   42 +++++++++-
 10 files changed, 252 insertions(+), 177 deletions(-)
---
diff --git a/daemon/control/gkd-control-codes.h b/daemon/control/gkd-control-codes.h
index 69d9206..e4ff7ff 100644
--- a/daemon/control/gkd-control-codes.h
+++ b/daemon/control/gkd-control-codes.h
@@ -31,7 +31,8 @@ enum {
 enum {
        GKD_CONTROL_RESULT_OK,
        GKD_CONTROL_RESULT_DENIED,
-       GKD_CONTROL_RESULT_FAILED
+       GKD_CONTROL_RESULT_FAILED,
+       GKD_CONTROL_RESULT_NO_DAEMON
 };
 
 #endif /* __GKD_CONTROL_CODES_H__ */
diff --git a/daemon/gkd-main.c b/daemon/gkd-main.c
index 8066c9d..7cf99a9 100644
--- a/daemon/gkd-main.c
+++ b/daemon/gkd-main.c
@@ -577,6 +577,16 @@ discover_other_daemon (DiscoverFunc callback, gboolean acquire)
                        return TRUE;
        }
 
+       /* Or the default location when no evironment variable */
+       control_env = g_getenv ("XDG_RUNTIME_DIR");
+       if (control_env) {
+               control = g_build_filename (control_env, "keyring", NULL);
+               ret = (callback) (control);
+               g_free (control);
+               if (ret == TRUE)
+                       return TRUE;
+       }
+
        /* See if we can contact a daemon running, that didn't set an env variable */
        if (acquire && !gkd_dbus_singleton_acquire (&acquired))
                return FALSE;
diff --git a/daemon/gkd-util.c b/daemon/gkd-util.c
index 35d1b04..431633b 100644
--- a/daemon/gkd-util.c
+++ b/daemon/gkd-util.c
@@ -116,6 +116,7 @@ void
 gkd_util_init_master_directory (const gchar *replace)
 {
        gboolean exists = FALSE;
+       gboolean is_default = FALSE;
 
        g_free (master_directory);
        master_directory = NULL;
@@ -126,7 +127,9 @@ gkd_util_init_master_directory (const gchar *replace)
        /* Only use default directory if it has an predictable explicit path */
        } else if (g_getenv ("XDG_RUNTIME_DIR")) {
                master_directory = g_build_filename (g_get_user_runtime_dir (), "keyring", NULL);
-               if (!validate_master_directory (master_directory, &exists)) {
+               if (validate_master_directory (master_directory, &exists)) {
+                       is_default = TRUE;
+               } else {
                        g_free (master_directory);
                        master_directory = NULL;
                }
@@ -150,7 +153,8 @@ gkd_util_init_master_directory (const gchar *replace)
                }
        }
 
-       gkd_util_push_environment (GKD_UTIL_ENV_CONTROL, master_directory);
+       if (!is_default)
+               gkd_util_push_environment (GKD_UTIL_ENV_CONTROL, master_directory);
        egg_cleanup_register (uninit_master_directory, NULL);
 }
 
diff --git a/daemon/test-shutdown.c b/daemon/test-shutdown.c
index 28f6a9e..819be48 100644
--- a/daemon/test-shutdown.c
+++ b/daemon/test-shutdown.c
@@ -77,20 +77,17 @@ test_sigterm (Test *test,
 {
        const gchar *argv[] = {
                BUILDDIR "/gnome-keyring-daemon", "--foreground",
+               "--control-directory", test->directory,
                "--components=secrets,pkcs11", NULL
        };
 
-       const gchar *control;
        gchar **output;
        gint status;
        GPid pid;
 
        output = gkd_test_launch_daemon (test->directory, argv, &pid, NULL);
 
-       control = g_environ_getenv (output, "GNOME_KEYRING_CONTROL");
-       g_assert_cmpstr (control, !=, NULL);
-
-       g_assert (gkd_control_unlock (control, "booo"));
+       g_assert (gkd_control_unlock (test->directory, "booo"));
        g_strfreev (output);
 
        /* Terminate the daemon */
@@ -107,20 +104,17 @@ test_close_connection (Test *test,
 {
        const gchar *argv[] = {
                BUILDDIR "/gnome-keyring-daemon", "--foreground",
+               "--control-directory", test->directory,
                "--components=secrets,pkcs11", NULL
        };
 
-       const gchar *control;
        gchar **output;
        gint status;
        GPid pid;
 
        output = gkd_test_launch_daemon (test->directory, argv, &pid, NULL);
 
-       control = g_environ_getenv (output, "GNOME_KEYRING_CONTROL");
-       g_assert_cmpstr (control, !=, NULL);
-
-       g_assert (gkd_control_unlock (control, "booo"));
+       g_assert (gkd_control_unlock (test->directory, "booo"));
        g_strfreev (output);
 
        /* Now close the dbus connection */
diff --git a/daemon/test-startup.c b/daemon/test-startup.c
index 3391cd2..af63ad6 100644
--- a/daemon/test-startup.c
+++ b/daemon/test-startup.c
@@ -192,13 +192,14 @@ test_control_xdghome (Test *test,
        gchar **output;
        gint status;
 
+       /* Control directory not printed when default */
        directory = g_build_filename (test->directory, "different", NULL);
        output = gkd_test_launch_daemon (test->directory, argv, &pid,
                                         "XDG_RUNTIME_DIR", directory,
                                         NULL);
 
        expected = g_build_filename (directory, "/keyring", NULL);
-       g_assert_cmpstr (g_environ_getenv (output, "GNOME_KEYRING_CONTROL"), ==, expected);
+       g_assert_cmpstr (g_environ_getenv (output, "GNOME_KEYRING_CONTROL"), ==, NULL);
        g_strfreev (output);
 
        g_assert (gkd_control_quit (expected, 0));
@@ -209,6 +210,41 @@ test_control_xdghome (Test *test,
        g_free (expected);
 }
 
+static void
+test_daemon_replace (Test *test,
+                     gconstpointer unused)
+{
+       const gchar *argv[] = {
+               BUILDDIR "/gnome-keyring-daemon", "--foreground",
+               "--components=", NULL
+       };
+
+       const gchar *replace[] = {
+               BUILDDIR "/gnome-keyring-daemon", "--foreground",
+               "--replace", "--components=", NULL
+       };
+
+       gchar **output;
+       gint status;
+       GPid pid;
+
+       /* Start the first daemon */
+       output = gkd_test_launch_daemon (test->directory, argv, &pid,
+                                        "XDG_RUNTIME_DIR", "/tmp/keyring-test-two",
+                                        NULL);
+       g_free (output);
+
+       /* Replace with the second daemon */
+       output = gkd_test_launch_daemon (test->directory, replace, &test->pid,
+                                        "XDG_RUNTIME_DIR", "/tmp/keyring-test-two",
+                                        NULL);
+       g_free (output);
+
+       /* The first daemon should have exited cleanly here */
+       g_assert_cmpint (waitpid (pid, &status, 0), ==, pid);
+       g_assert_cmpint (status, ==, 0);
+}
+
 int
 main (int argc, char **argv)
 {
@@ -225,5 +261,8 @@ main (int argc, char **argv)
        g_test_add ("/daemon/startup/control/xdghome", Test, NULL,
                    setup, test_control_xdghome, teardown);
 
+       g_test_add ("/daemon/startup/replace", Test, NULL,
+                   setup, test_daemon_replace, teardown);
+
        return g_test_run ();
 }
diff --git a/pam/gkr-pam-client.c b/pam/gkr-pam-client.c
index 9b6c70a..d2ce8b5 100644
--- a/pam/gkr-pam-client.c
+++ b/pam/gkr-pam-client.c
@@ -142,73 +142,100 @@ write_credentials_byte (int sock)
 }
 
 static int
-connect_to_daemon (const char *control)
+lookup_daemon (const char *control,
+               struct sockaddr_un *addr)
 {
-       struct sockaddr_un addr;
        struct stat st;
-       int sock;
+       const char *suffix;
 
-       addr.sun_family = AF_UNIX;
-       if (strlen (control) + strlen ("/control") + 1 > sizeof (addr.sun_path)) {
-               syslog (GKR_LOG_ERR, "gkr-pam: address is too long for unix socket path: %s/control",
-                       control);
-               return -1;
+       if (control == NULL) {
+               control = getenv ("XDG_RUNTIME_DIR");
+               if (control == NULL)
+                       return GKD_CONTROL_RESULT_NO_DAEMON;
+               suffix = "/keyring/control";
+       } else {
+               suffix = "/control";
        }
 
-       strcpy (addr.sun_path, control);
-       strcat (addr.sun_path, "/control");
+       if (strlen (control) + strlen (suffix) + 1 > sizeof (addr->sun_path)) {
+               syslog (GKR_LOG_ERR, "gkr-pam: address is too long for unix socket path: %s/%s",
+                       control, suffix);
+               return GKD_CONTROL_RESULT_FAILED;
+       }
+
+       memset (addr, 0, sizeof (*addr));
+       addr->sun_family = AF_UNIX;
+       strcpy (addr->sun_path, control);
+       strcat (addr->sun_path, suffix);
 
        /* A bunch of checks to make sure nothing funny is going on */
-       if (lstat (addr.sun_path, &st) < 0) {
+       if (lstat (addr->sun_path, &st) < 0) {
+               if (errno == ENOENT)
+                       return GKD_CONTROL_RESULT_NO_DAEMON;
+
                syslog (GKR_LOG_ERR, "Couldn't access gnome keyring socket: %s: %s",
-                       addr.sun_path, strerror (errno));
-               return -1;
+                       addr->sun_path, strerror (errno));
+               return GKD_CONTROL_RESULT_FAILED;
        }
        
        if (st.st_uid != geteuid ()) {
                syslog (GKR_LOG_ERR, "The gnome keyring socket is not owned with the same "
-                       "credentials as the user login: %s", addr.sun_path);
-               return -1;
+                       "credentials as the user login: %s", addr->sun_path);
+               return GKD_CONTROL_RESULT_FAILED;
        }
        
        if (S_ISLNK(st.st_mode) || !S_ISSOCK(st.st_mode)) {
                syslog (GKR_LOG_ERR, "The gnome keyring socket is not a valid simple "
                        "non-linked socket");
-               return -1;
+               return GKD_CONTROL_RESULT_FAILED;
        }
 
+       return GKD_CONTROL_RESULT_OK;
+}
+
+static int
+connect_daemon (struct sockaddr_un *addr,
+                int *out_sock)
+{
+       int sock;
+
        /* Now we connect */
        sock = socket (AF_UNIX, SOCK_STREAM, 0);
        if (sock < 0) {
                syslog (GKR_LOG_ERR, "couldn't create control socket: %s", strerror (errno));
-               return -1;
+               return GKD_CONTROL_RESULT_FAILED;
        }
 
        /* close on exec */
        fcntl (sock, F_SETFD, 1);
 
-       if (connect (sock, (struct sockaddr*) &addr, sizeof (addr)) < 0) {
+       if (connect (sock, (struct sockaddr *)addr, sizeof (*addr)) < 0) {
+               if (errno == ECONNREFUSED) {
+                       close (sock);
+                       return GKD_CONTROL_RESULT_NO_DAEMON;
+               }
                syslog (GKR_LOG_ERR, "couldn't connect to gnome-keyring-daemon socket at: %s: %s",
-                       addr.sun_path, strerror (errno));
+                       addr->sun_path, strerror (errno));
                close (sock);
-               return -1;
+               return GKD_CONTROL_RESULT_FAILED;
        }
 
        /* Verify the server is running as the right user */
        
        if (check_peer_same_uid (sock) <= 0) {
                close (sock);
-               return -1;
+               return GKD_CONTROL_RESULT_FAILED;
        }
        
        /* This lets the server verify us */
        
        if (write_credentials_byte (sock) < 0) {
                close (sock);
-               return -1;
+               return GKD_CONTROL_RESULT_FAILED;
        }
        
-       return sock;
+       *out_sock = sock;
+       return GKD_CONTROL_RESULT_OK;
 }
 
 static void
@@ -266,14 +293,17 @@ read_part (int fd, unsigned char *data, int len)
 }
 
 static int
-keyring_daemon_op (const char *control, int op, int argc, const char* argv[])
+keyring_daemon_op (struct sockaddr_un *addr,
+                   int op,
+                   int argc,
+                   const char *argv[])
 {
        int ret = GKD_CONTROL_RESULT_OK;
        unsigned char buf[4];
        int i, sock = -1;
        uint oplen, l;
 
-       assert (control);
+       assert (addr);
 
        /* 
         * We only support operations with zero or more strings
@@ -282,11 +312,9 @@ keyring_daemon_op (const char *control, int op, int argc, const char* argv[])
         
        assert (op == GKD_CONTROL_OP_CHANGE || op == GKD_CONTROL_OP_UNLOCK);
 
-       sock = connect_to_daemon (control);
-       if (sock < 0) {
-               ret = -1;
+       ret = connect_daemon (addr, &sock);
+       if (ret != GKD_CONTROL_RESULT_OK)
                goto done;
-       }
 
        /* Calculate the packet length */
        oplen = 8; /* The packet size, and op code */
@@ -346,6 +374,7 @@ gkr_pam_client_run_operation (struct passwd *pwd, const char *control,
                               int op, int argc, const char* argv[])
 {
        struct sigaction ignpipe, oldpipe, defchld, oldchld;
+       struct sockaddr_un addr;
        int res;
        pid_t pid;
        int status;
@@ -361,11 +390,15 @@ gkr_pam_client_run_operation (struct passwd *pwd, const char *control,
        defchld.sa_handler = SIG_DFL;
        sigaction (SIGCHLD, &defchld, &oldchld);
 
+       res = lookup_daemon (control, &addr);
+       if (res != GKD_CONTROL_RESULT_OK)
+               return res;
+
        if (pwd->pw_uid == getuid () && pwd->pw_gid == getgid () && 
            pwd->pw_uid == geteuid () && pwd->pw_gid == getegid ()) {
 
                /* Already running as the right user, simple */
-               res = keyring_daemon_op (control, op, argc, argv);
+               res = keyring_daemon_op (&addr, op, argc, argv);
                
        } else {
                
@@ -386,7 +419,7 @@ gkr_pam_client_run_operation (struct passwd *pwd, const char *control,
                                exit (GKD_CONTROL_RESULT_FAILED);
                        }
        
-                       res = keyring_daemon_op (control, op, argc, argv);
+                       res = keyring_daemon_op (&addr, op, argc, argv);
                        exit (res);
                        return 0; /* Never reached */
                        
diff --git a/pam/gkr-pam-module.c b/pam/gkr-pam-module.c
index ad30f19..e82e30d 100644
--- a/pam/gkr-pam-module.c
+++ b/pam/gkr-pam-module.c
@@ -605,35 +605,6 @@ done:
 }
 
 static int
-start_daemon_if_necessary (pam_handle_t *ph, struct passwd *pwd, 
-                           const char *password, int* started)
-{
-       const char *control;
-       int ret;
-
-       *started = 0;
-
-       /* See if it's already running, and transfer env variables */
-       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));
-                       return ret;
-               }
-               
-               /* Daemon is already running */
-               return PAM_SUCCESS;
-       }
-
-       /* Not running, start process */
-       ret = start_daemon (ph, pwd, password);
-       *started = (ret == PAM_SUCCESS);
-       return ret;
-}
-
-static int
 stop_daemon (pam_handle_t *ph, struct passwd *pwd)
 {
        const char *spid = NULL;
@@ -675,7 +646,10 @@ done:
 }
 
 static int
-unlock_keyring (pam_handle_t *ph, struct passwd *pwd, const char *password)
+unlock_keyring (pam_handle_t *ph,
+                struct passwd *pwd,
+                const char *password,
+                int *need_daemon)
 {
        const char *control;
        int res;
@@ -685,18 +659,15 @@ unlock_keyring (pam_handle_t *ph, struct passwd *pwd, const char *password)
        assert (password);
 
        control = get_any_env (ph, ENV_CONTROL);
-       if (!control) {
-               syslog (GKR_LOG_WARN, "gkr-pam: couldn't unlock login keyring: %s",
-                       "gnome-keyring-daemon is not running");
-               return PAM_SERVICE_ERR;
-       }
-       
        argv[0] = password;
 
        res = gkr_pam_client_run_operation (pwd, control, GKD_CONTROL_OP_UNLOCK, 1, argv);
-
        /* An error unlocking */
-       if (res == GKD_CONTROL_RESULT_DENIED) {
+       if (res == GKD_CONTROL_RESULT_NO_DAEMON) {
+               if (need_daemon)
+                       *need_daemon = 1;
+               return PAM_SERVICE_ERR;
+       } else if (res == GKD_CONTROL_RESULT_DENIED) {
                syslog (GKR_LOG_ERR, "gkr-pam: the password for the login keyring was invalid.");
                return PAM_SERVICE_ERR;
        } else if (res != GKD_CONTROL_RESULT_OK) {
@@ -709,8 +680,11 @@ unlock_keyring (pam_handle_t *ph, struct passwd *pwd, const char *password)
 }
 
 static int
-change_keyring_password (pam_handle_t *ph, struct passwd *pwd, 
-                         const char *password, const char *original)
+change_keyring_password (pam_handle_t *ph,
+                         struct passwd *pwd,
+                         const char *password,
+                         const char *original,
+                         int *need_daemon)
 {
        const char *control;
        const char *argv[3];
@@ -721,19 +695,17 @@ change_keyring_password (pam_handle_t *ph, struct passwd *pwd,
        assert (original);
 
        control = get_any_env (ph, ENV_CONTROL);
-       if (!control) {
-               syslog (GKR_LOG_WARN, "gkr-pam: couldn't change password on login keyring: %s",
-                       "gnome-keyring-daemon is not running");
-               return PAM_SERVICE_ERR;
-       }
-       
        argv[0] = original;
        argv[1] = password;
        
        res = gkr_pam_client_run_operation (pwd, control, GKD_CONTROL_OP_CHANGE, 2, argv);
 
+       if (res == GKD_CONTROL_RESULT_NO_DAEMON) {
+               if (need_daemon)
+                       *need_daemon = 1;
+               return PAM_SERVICE_ERR;
        /* No keyring, not an error. Will be created at initial authenticate. */
-       if (res == GKD_CONTROL_RESULT_DENIED) {
+       } else if (res == GKD_CONTROL_RESULT_DENIED) {
                syslog (GKR_LOG_ERR, "gkr-pam: couldn't change password for the login keyring: the passwords 
didn't match.");
                return PAM_SERVICE_ERR;
        } else if (res != GKD_CONTROL_RESULT_OK) {
@@ -835,8 +807,7 @@ pam_sm_authenticate (pam_handle_t *ph, int unused, int argc, const char **argv)
 {
        struct passwd *pwd;
        const char *user, *password;
-       const char *control;
-       int started_daemon;
+       int need_daemon = 0;
        uint args;
        int ret;
        
@@ -870,36 +841,24 @@ pam_sm_authenticate (pam_handle_t *ph, int unused, int argc, const char **argv)
                return PAM_SUCCESS;
        }
 
-       started_daemon = 0;
-
-       /* Should we start the daemon? */
-       if (args & ARG_AUTO_START) {
-               ret = start_daemon_if_necessary (ph, pwd, password, &started_daemon);
-               if (ret != PAM_SUCCESS)
-                       return ret;
-       }
-
-       control = get_any_env (ph, ENV_CONTROL);
+       ret = unlock_keyring (ph, pwd, password, &need_daemon);
+       if (ret != PAM_SUCCESS && need_daemon) {
+               if (args & ARG_AUTO_START) {
+                       /* If we started the daemon, its already unlocked, since we passed the password */
+                       ret = start_daemon (ph, pwd, password);
 
-       /* If gnome keyring is running, then unlock now */
-       if (control) {
-               /* If we started the daemon, its already unlocked, since we passed the password */
-               if (!started_daemon) {
-                       ret = unlock_keyring (ph, pwd, password);
-                       if (ret != PAM_SUCCESS)
-                               return ret;
-               }
-               
-       /* Otherwise start later in open session, store password */
-       } else {
-               if (pam_set_data (ph, "gkr_system_authtok", strdup (password),
-                                 cleanup_free_password) != PAM_SUCCESS) {
+               /* Otherwise start later in open session, store password */
+               } else if (pam_set_data (ph, "gkr_system_authtok", strdup (password),
+                                        cleanup_free_password) != PAM_SUCCESS) {
                        syslog (GKR_LOG_ERR, "gkr-pam: error storing authtok");
                        return PAM_AUTHTOK_RECOVER_ERR;
+
+               } else {
+                       ret = PAM_SUCCESS;
                }
-       }
+       }
 
-       return PAM_SUCCESS;
+       return ret;
 }
 
 PAM_EXTERN int
@@ -909,7 +868,7 @@ pam_sm_open_session (pam_handle_t *ph, int flags, int argc, const char **argv)
        struct passwd *pwd;
        int ret;
        uint args;
-       int started_daemon;
+       int need_daemon = 0;
 
        args = parse_args (ph, argc, argv);
 
@@ -942,23 +901,12 @@ pam_sm_open_session (pam_handle_t *ph, int flags, int argc, const char **argv)
                password = NULL;
        }
        
-       started_daemon = 0;
-       
-       /* Should we start the daemon? */
-       if (args & ARG_AUTO_START) {
-               ret = start_daemon_if_necessary (ph, pwd, password, &started_daemon);
-               if (ret != PAM_SUCCESS)
-                       return ret;
+       if (args & ARG_AUTO_START || password) {
+               ret = unlock_keyring (ph, pwd, password, &need_daemon);
+               if (ret != PAM_SUCCESS && need_daemon && (args & ARG_AUTO_START))
+                       ret = start_daemon (ph, pwd, password);
        }
 
-       /* If gnome keyring is running, but we didn't start it here, then unlock now */
-       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;
-               }
-       }
-       
        return PAM_SUCCESS;
 }
 
@@ -1022,7 +970,8 @@ static int
 pam_chauthtok_update (pam_handle_t *ph, struct passwd *pwd, uint args)
 {
        const char *password, *original;
-       int ret, started_daemon = 0;
+       int need_daemon = 0;
+       int ret;
        
        ret = pam_get_item (ph, PAM_OLDAUTHTOK, (const void**)&original);
        if (ret != PAM_SUCCESS || original == NULL) {
@@ -1056,29 +1005,29 @@ pam_chauthtok_update (pam_handle_t *ph, struct passwd *pwd, uint args)
                        return PAM_AUTHTOK_RECOVER_ERR;
                }
        }
-       
-       /* 
-        * We always start the daemon here, and don't respect the auto_start
-        * argument. Because if the password is being changed, then making 
-        * the 'login' keyring match it is a priority.
-        *
-        * Note that we don't pass in an unlock password, that happens below.
-        */
-       ret = start_daemon_if_necessary (ph, pwd, NULL, &started_daemon);
-       if (ret != PAM_SUCCESS)
-               return ret;
-       
-       ret = change_keyring_password (ph, pwd, password, original);
 
-       /* if not auto_start, kill the daemon if we started it: we don't want
-        * it to stay */
-       if (started_daemon && !(args & ARG_AUTO_START))
-               stop_daemon (ph, pwd);
+       ret = change_keyring_password (ph, pwd, password, original, &need_daemon);
+       if (ret != PAM_SUCCESS && need_daemon) {
 
-       if (ret != PAM_SUCCESS)
-               return ret;
-               
-       return PAM_SUCCESS;
+               /*
+                * We always start the daemon here, and don't respect the auto_start
+                * argument. Because if the password is being changed, then making
+                * the 'login' keyring match it is a priority.
+                *
+                * Note that we don't pass in an unlock password, that happens below.
+                */
+               ret = start_daemon (ph, pwd, NULL);
+               if (ret == PAM_SUCCESS) {
+                       ret = change_keyring_password (ph, pwd, password, original, NULL);
+
+                       /* if not auto_start, kill the daemon if we started it: we don't want
+                        * it to stay */
+                       if (!(args & ARG_AUTO_START))
+                               stop_daemon (ph, pwd);
+               }
+       }
+
+       return ret;
 }
 
 PAM_EXTERN int
diff --git a/pam/test-pam.c b/pam/test-pam.c
index 3fe6946..4000901 100644
--- a/pam/test-pam.c
+++ b/pam/test-pam.c
@@ -155,13 +155,13 @@ setup (Test *test,
 
        g_assert_no_error (error);
 
-       test->dbus = g_test_dbus_new (G_TEST_DBUS_NONE);
-       g_test_dbus_up (test->dbus);
-
        test->directory = egg_tests_create_scratch_directory (NULL, NULL);
 
        g_setenv ("XDG_RUNTIME_DIR", test->directory, TRUE);
 
+       test->dbus = g_test_dbus_new (G_TEST_DBUS_NONE);
+       g_test_dbus_up (test->dbus);
+
        test->conv.conv = conv_func;
        test->conv.appdata_ptr = test;
        ret = pam_start (pam_conf, g_get_user_name (), &test->conv, &test->ph);
@@ -368,7 +368,7 @@ static void
 test_auth_running_unlocks (Test *test,
                            gconstpointer user_data)
 {
-       const gchar *control;
+       gchar *control;
        gchar **env;
        GPid pid;
 
@@ -382,10 +382,6 @@ test_auth_running_unlocks (Test *test,
        egg_tests_copy_scratch_file (test->directory, SRCDIR "/pam/fixtures/login.keyring");
 
        env = gkd_test_launch_daemon (test->directory, argv, &pid, NULL);
-       g_assert_cmpstr (g_environ_getenv (env, "GNOME_KEYRING_CONTROL"), !=, NULL);
-
-       control = g_environ_getenv (env, "GNOME_KEYRING_CONTROL");
-       g_setenv ("GNOME_KEYRING_CONTROL", control, TRUE);
 
        g_assert (check_if_login_keyring_locked (test) == TRUE);
 
@@ -396,6 +392,7 @@ test_auth_running_unlocks (Test *test,
        g_assert (check_if_login_keyring_locked (test) == FALSE);
        g_assert (check_if_login_item_1_exists (test) == TRUE);
 
+       control = g_strdup_printf ("%s/keyring", test->directory);
        g_assert (gkd_control_quit (control, 0));
        g_assert_cmpint (waitpid (pid, NULL, 0), ==, pid);
 
@@ -406,7 +403,7 @@ static void
 test_password_changes_running (Test *test,
                                gconstpointer user_data)
 {
-       const gchar *control;
+       gchar *control;
        gchar **env;
        GPid pid;
 
@@ -418,11 +415,10 @@ test_password_changes_running (Test *test,
                return;
 
        egg_tests_copy_scratch_file (test->directory, SRCDIR "/pam/fixtures/login.keyring");
+       control = g_strdup_printf ("%s/keyring", test->directory);
 
        env = gkd_test_launch_daemon (test->directory, argv, &pid, NULL);
-       g_assert_cmpstr (g_environ_getenv (env, "GNOME_KEYRING_CONTROL"), !=, NULL);
-       control = g_environ_getenv (env, "GNOME_KEYRING_CONTROL");
-       g_setenv ("GNOME_KEYRING_CONTROL", control, TRUE);
+       g_strfreev (env);
 
        test->password = "booo";
        test->new_password = "changed";
@@ -431,25 +427,23 @@ test_password_changes_running (Test *test,
        /* Quit the daemon */
        g_assert (gkd_control_quit (control, 0));
        g_assert_cmpint (waitpid (pid, NULL, 0), ==, pid);
-       g_strfreev (env);
 
        /* Start it again */
        env = gkd_test_launch_daemon (test->directory, argv, &pid, NULL);
-       control = g_environ_getenv (env, "GNOME_KEYRING_CONTROL");
-       g_setenv ("GNOME_KEYRING_CONTROL", control, TRUE);
+       g_strfreev (env);
 
        g_assert (gkd_control_unlock (control, "changed"));
        g_assert (gkd_control_quit (control, 0));
        g_assert_cmpint (waitpid (pid, NULL, 0), ==, pid);
 
-       g_strfreev (env);
+       g_free (control);
 }
 
 static void
 test_password_changes_starts (Test *test,
                               gconstpointer user_data)
 {
-       const gchar *control;
+       gchar *control;
        gchar **env;
        GPid pid;
 
@@ -461,6 +455,7 @@ test_password_changes_starts (Test *test,
                return;
 
        egg_tests_copy_scratch_file (test->directory, SRCDIR "/pam/fixtures/login.keyring");
+       control = g_strdup_printf ("%s/keyring", test->directory);
 
        test->password = "booo";
        test->new_password = "changed";
@@ -470,14 +465,13 @@ test_password_changes_starts (Test *test,
        env = gkd_test_launch_daemon (test->directory, argv, &pid,
                                      "GNOME_KEYRING_TEST_SERVICE", "another.Bus.Name",
                                      NULL);
-       control = g_environ_getenv (env, "GNOME_KEYRING_CONTROL");
-       g_setenv ("GNOME_KEYRING_CONTROL", control, TRUE);
 
        g_assert (gkd_control_unlock (control, "changed"));
        g_assert (gkd_control_quit (control, 0));
        g_assert_cmpint (waitpid (pid, NULL, 0), ==, pid);
 
        g_strfreev (env);
+       g_free (control);
 }
 
 int
diff --git a/pkcs11/rpc-layer/gkm-rpc-module.c b/pkcs11/rpc-layer/gkm-rpc-module.c
index 01e0798..24457ce 100644
--- a/pkcs11/rpc-layer/gkm-rpc-module.c
+++ b/pkcs11/rpc-layer/gkm-rpc-module.c
@@ -1198,6 +1198,17 @@ rpc_C_Initialize (CK_VOID_PTR init_args)
                                        goto done;
                                }
                                sprintf (pkcs11_socket_path, "%s/pkcs11", path);
+                       } else {
+                               path = getenv ("XDG_RUNTIME_DIR");
+                               if (path) {
+                                       pkcs11_socket_path = malloc (strlen (path) + strlen 
("/keyring/pkcs11") + 1);
+                                       if (pkcs11_socket_path == NULL) {
+                                               warning (("can't malloc memory"));
+                                               ret = CKR_HOST_MEMORY;
+                                               goto done;
+                                       }
+                                       sprintf (pkcs11_socket_path, "%s/keyring/pkcs11", path);
+                               }
                        }
                }
 
diff --git a/pkcs11/rpc-layer/test-initialize.c b/pkcs11/rpc-layer/test-initialize.c
index 205666c..a5bc7c9 100644
--- a/pkcs11/rpc-layer/test-initialize.c
+++ b/pkcs11/rpc-layer/test-initialize.c
@@ -48,6 +48,9 @@ setup (Test *test,
        g_test_dbus_up (test->dbus);
 
        test->directory = egg_tests_create_scratch_directory (NULL, NULL);
+
+       g_unsetenv ("GNOME_KEYRING_CONTROL");
+       g_setenv ("XDG_RUNTIME_DIR", test->directory, TRUE);
 }
 
 static void
@@ -87,7 +90,41 @@ test_initialize_normal (Test *test,
        /* Start the first daemon */
        output = gkd_test_launch_daemon (test->directory, argv, &test->pid, NULL);
        control = g_environ_getenv (output, "GNOME_KEYRING_CONTROL");
-       g_assert_cmpstr (control, !=, NULL);
+       g_assert_cmpstr (control, ==, NULL);
+       g_strfreev (output);
+
+       module = gck_module_initialize (BUILDDIR "/.libs/gnome-keyring-pkcs11.so",
+                                       NULL, &error);
+       g_assert_no_error (error);
+
+       info = gck_module_get_info (module);
+       g_assert (info != NULL);
+       g_assert_cmpstr (info->library_description, ==, "GNOME Keyring Daemon Core");
+       gck_module_info_free (info);
+
+       g_object_unref (module);
+}
+
+static void
+test_initialize_control (Test *test,
+                         gconstpointer unused)
+{
+       const gchar *argv[] = {
+               BUILDDIR "/gnome-keyring-daemon", "--foreground",
+               "--control-directory", test->directory,
+               "--components=pkcs11", NULL
+       };
+
+       const gchar *control;
+       gchar **output;
+       GckModule *module;
+       GckModuleInfo *info;
+       GError *error = NULL;
+
+       /* Start the first daemon */
+       output = gkd_test_launch_daemon (test->directory, argv, &test->pid, NULL);
+       control = g_environ_getenv (output, "GNOME_KEYRING_CONTROL");
+       g_assert_cmpstr (control, ==, test->directory);
        g_setenv ("GNOME_KEYRING_CONTROL", control, TRUE);
        g_strfreev (output);
 
@@ -113,6 +150,7 @@ test_initialize_no_daemon (Test *test,
 
        /* No daemon to connect to */
        g_unsetenv ("GNOME_KEYRING_CONTROL");
+       g_unsetenv ("XDG_RUNTIME_DIR");
 
        module = gck_module_initialize (BUILDDIR "/.libs/gnome-keyring-pkcs11.so",
                                        NULL, &error);
@@ -133,6 +171,8 @@ main (int argc, char **argv)
 
        g_test_add ("/pkcs11/rpc-layer/initialize/normal", Test, NULL,
                    setup, test_initialize_normal, teardown);
+       g_test_add ("/pkcs11/rpc-layer/initialize/control", Test, NULL,
+                   setup, test_initialize_control, teardown);
        g_test_add ("/pkcs11/rpc-layer/initialize/no-daemon", Test, NULL,
                    setup, test_initialize_no_daemon, teardown);
 


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