summaryrefslogtreecommitdiff
path: root/pam
diff options
context:
space:
mode:
authorStef Walter <stefw@gnome.org>2014-03-06 12:00:06 +0100
committerStef Walter <stefw@gnome.org>2014-03-06 18:45:20 +0100
commit02d7fd262a5bff089925029cae85c3586a850986 (patch)
tree318c8bd473f9b4ac2f13c81e1e9a76edb3190c29 /pam
parent86bd8c5a8eb9b0bd299645b5d2eaa6dd043b355f (diff)
downloadgnome-keyring-02d7fd262a5bff089925029cae85c3586a850986.tar.gz
pam: Add some tests for the PAM module
These require you to install some pam configs into /etc/pam.d. You can do it with the following commands: $ make enable-pam-tests $ make disable-pam-tests
Diffstat (limited to 'pam')
-rw-r--r--pam/Makefile.am54
-rw-r--r--pam/fixtures/gnome-keyring-test-auth-start8
-rw-r--r--pam/fixtures/gnome-keyring-test-no-start8
-rw-r--r--pam/fixtures/gnome-keyring-test-session-start8
-rw-r--r--pam/fixtures/login.keyringbin0 -> 180 bytes
-rw-r--r--pam/mock-pam.c125
-rw-r--r--pam/test-pam.c518
7 files changed, 721 insertions, 0 deletions
diff --git a/pam/Makefile.am b/pam/Makefile.am
index 8707ab6c..5c83c00e 100644
--- a/pam/Makefile.am
+++ b/pam/Makefile.am
@@ -18,3 +18,57 @@ pam_gnome_keyring_la_LIBADD = \
pam_gnome_keyring_la_LDFLAGS = \
-module -avoid-version \
-export-symbols-regex 'pam_sm_'
+
+# -----------------------------------------------------------------------------
+# PAM tests
+
+pam_CONFIGS = \
+ pam/fixtures/gnome-keyring-test-auth-start \
+ pam/fixtures/gnome-keyring-test-no-start \
+ pam/fixtures/gnome-keyring-test-session-start \
+ $(NULL)
+
+EXTRA_DIST += pam/fixtures
+
+enable-pam-tests:
+ for t in $(notdir $(pam_CONFIGS)); do \
+ $(SED_SUBST) $(srcdir)/pam/fixtures/$$t > $(sysconfdir)/pam.d/$$t; \
+ done
+
+disable-pam-tests:
+ for t in $(notdir $(pam_CONFIGS)); do \
+ $(RM) -f $(sysconfdir)/pam.d/$$t; \
+ done
+
+noinst_LTLIBRARIES += pam_mock.la
+
+pam_mock_la_SOURCES = pam/mock-pam.c
+pam_mock_la_LIBADD = \
+ -lpam
+pam_mock_la_LDFLAGS = \
+ -module -avoid-version \
+ -export-symbols-regex 'pam_sm_' \
+ -rpath /force/shared
+
+pam_CFLAGS = \
+ -DSYSCONFDIR=\"$(sysconfdir)\" \
+ $(NULL)
+
+pam_LIBS = \
+ libgkd-control-client.la \
+ libgkd-test.la \
+ libegg.la \
+ libegg-test.la \
+ $(GIO_LIBS) \
+ $(GLIB_LIBS) \
+ -lpam
+
+pam_TESTS = \
+ test-pam
+
+test_pam_SOURCES = pam/test-pam.c
+test_pam_LDADD = $(pam_LIBS)
+test_pam_CFLAGS = $(pam_CFLAGS)
+
+check_PROGRAMS += $(pam_TESTS)
+TESTS += $(pam_TESTS)
diff --git a/pam/fixtures/gnome-keyring-test-auth-start b/pam/fixtures/gnome-keyring-test-auth-start
new file mode 100644
index 00000000..57d93440
--- /dev/null
+++ b/pam/fixtures/gnome-keyring-test-auth-start
@@ -0,0 +1,8 @@
+auth required @abs_builddir@/.libs/pam_mock.so
+auth required @abs_builddir@/.libs/pam_gnome_keyring.so auto_start
+
+password required @abs_builddir@/.libs/pam_mock.so
+password required @abs_builddir@/.libs/pam_gnome_keyring.so use_authtok
+
+session required @abs_builddir@/.libs/pam_mock.so
+session required @abs_builddir@/.libs/pam_gnome_keyring.so
diff --git a/pam/fixtures/gnome-keyring-test-no-start b/pam/fixtures/gnome-keyring-test-no-start
new file mode 100644
index 00000000..dee22ca7
--- /dev/null
+++ b/pam/fixtures/gnome-keyring-test-no-start
@@ -0,0 +1,8 @@
+auth required @abs_builddir@/.libs/pam_mock.so
+auth required @abs_builddir@/.libs/pam_gnome_keyring.so
+
+password required @abs_builddir@/.libs/pam_mock.so
+password required @abs_builddir@/.libs/pam_gnome_keyring.so use_authtok
+
+session required @abs_builddir@/.libs/pam_mock.so
+session required @abs_builddir@/.libs/pam_gnome_keyring.so
diff --git a/pam/fixtures/gnome-keyring-test-session-start b/pam/fixtures/gnome-keyring-test-session-start
new file mode 100644
index 00000000..38a39462
--- /dev/null
+++ b/pam/fixtures/gnome-keyring-test-session-start
@@ -0,0 +1,8 @@
+auth required @abs_builddir@/.libs/pam_mock.so
+auth required @abs_builddir@/.libs/pam_gnome_keyring.so
+
+password required @abs_builddir@/.libs/pam_mock.so
+password required @abs_builddir@/.libs/pam_gnome_keyring.so use_authtok
+
+session required @abs_builddir@/.libs/pam_mock.so
+session required @abs_builddir@/.libs/pam_gnome_keyring.so auto_start
diff --git a/pam/fixtures/login.keyring b/pam/fixtures/login.keyring
new file mode 100644
index 00000000..f53ed5d9
--- /dev/null
+++ b/pam/fixtures/login.keyring
Binary files differ
diff --git a/pam/mock-pam.c b/pam/mock-pam.c
new file mode 100644
index 00000000..59f2da2f
--- /dev/null
+++ b/pam/mock-pam.c
@@ -0,0 +1,125 @@
+/*
+ Copyright (C) 2014 Red Hat Inc.
+
+ 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,
+ <http://www.gnu.org/licenses/>.
+
+ Author: Stef Walter <stefw@gnome.org>
+*/
+
+#include "config.h"
+
+#include <security/pam_appl.h>
+#include <security/pam_modules.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+static int
+prompt_password (pam_handle_t *ph,
+ const char *prompt,
+ int password_type)
+{
+ const struct pam_conv *conv;
+ struct pam_message msg;
+ struct pam_response *resp;
+ const struct pam_message *msgs[1];
+ const void *item;
+ char *password;
+ int ret;
+
+ /* Get the conversation function */
+ ret = pam_get_item (ph, PAM_CONV, &item);
+ if (ret != PAM_SUCCESS)
+ return ret;
+
+ /* Setup a message */
+ memset (&msg, 0, sizeof (msg));
+ memset (&resp, 0, sizeof (resp));
+ msg.msg_style = PAM_PROMPT_ECHO_OFF;
+ msg.msg = prompt;
+ msgs[0] = &msg;
+
+ /* Call away */
+ conv = (const struct pam_conv*)item;
+ ret = (conv->conv) (1, msgs, &resp, conv->appdata_ptr);
+ if (ret != PAM_SUCCESS)
+ return ret;
+
+ password = resp[0].resp;
+ free (resp);
+
+ if (password == NULL)
+ return PAM_CONV_ERR;
+
+ /* Store it away for later use */
+ ret = pam_set_item (ph, password_type, password);
+ free (password);
+
+ if (ret == PAM_SUCCESS)
+ ret = pam_get_item (ph, password_type, &item);
+
+ return ret;
+}
+
+PAM_EXTERN int
+pam_sm_authenticate (pam_handle_t *ph,
+ int unused,
+ int argc,
+ const char **argv)
+{
+ /* Just prompt for the password, accept any result */
+ return prompt_password (ph, "Password: ", PAM_AUTHTOK);
+}
+
+PAM_EXTERN int
+pam_sm_open_session (pam_handle_t *ph,
+ int flags,
+ int argc,
+ const char **argv)
+{
+ return PAM_IGNORE;
+}
+
+PAM_EXTERN int
+pam_sm_close_session (pam_handle_t *ph,
+ int flags,
+ int argc,
+ const char **argv)
+{
+ return PAM_IGNORE;
+}
+
+PAM_EXTERN int
+pam_sm_setcred (pam_handle_t *ph,
+ int flags,
+ int argc,
+ const char **argv)
+{
+ return PAM_SUCCESS;
+}
+
+PAM_EXTERN int
+pam_sm_chauthtok (pam_handle_t *ph,
+ int flags,
+ int argc,
+ const char **argv)
+{
+ if (flags & PAM_PRELIM_CHECK)
+ return prompt_password (ph, "Old Password: ", PAM_OLDAUTHTOK);
+ else if (flags & PAM_UPDATE_AUTHTOK)
+ return prompt_password (ph, "New Password: ", PAM_AUTHTOK);
+ else
+ return PAM_IGNORE;
+}
diff --git a/pam/test-pam.c b/pam/test-pam.c
new file mode 100644
index 00000000..3fe6946b
--- /dev/null
+++ b/pam/test-pam.c
@@ -0,0 +1,518 @@
+/*
+ Copyright (C) 2014 Red Hat Inc
+
+ 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,
+ <http://www.gnu.org/licenses/>.
+
+ Author: Stef Walter <stefw@gnome.org>
+*/
+
+#include "config.h"
+
+#include "daemon/control/gkd-control.h"
+#include "daemon/gkd-test.h"
+
+#include "egg/egg-testing.h"
+#include "egg/egg-secure-memory.h"
+
+#include <security/pam_appl.h>
+
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <gio/gio.h>
+
+#include <sys/wait.h>
+#include <errno.h>
+#include <fcntl.h>
+
+EGG_SECURE_DEFINE_GLIB_GLOBALS ();
+
+typedef struct {
+ GTestDBus *dbus;
+ GDBusConnection *connection;
+ gchar *directory;
+ GPid pid;
+ gboolean skipping;
+ pam_handle_t *ph;
+ struct pam_conv conv;
+ const gchar *password;
+ const gchar *new_password;
+} Test;
+
+const gchar *PASS_ENVIRON[] = {
+ "DBUS_SESSION_ADDRESS",
+ "XDG_RUNTIME_DIR",
+ "XDG_DATA_HOME",
+ NULL
+};
+
+static void
+skip_test (Test *test,
+ const gchar *reason)
+{
+ test->skipping = TRUE;
+#if GLIB_CHECK_VERSION(2, 40, 0)
+ g_test_skip (reason);
+#else
+ if (g_test_verbose ())
+ g_print ("GTest: skipping: %s\n", reason);
+ else
+ g_print ("SKIP: %s ", reason);
+#endif
+}
+
+static int
+conv_func (int n,
+ const struct pam_message **msg,
+ struct pam_response **resp,
+ void *arg)
+{
+ struct pam_response *aresp;
+ Test *test = arg;
+ int i;
+
+ g_assert (n > 0 && n < PAM_MAX_NUM_MSG);
+ aresp = g_new0(struct pam_response, n);
+
+ for (i = 0; i < n; ++i) {
+ aresp[i].resp_retcode = 0;
+ aresp[i].resp = NULL;
+ switch (msg[i]->msg_style) {
+ case PAM_PROMPT_ECHO_OFF:
+ if (test->password) {
+ aresp[i].resp = strdup (test->password);
+ test->password = NULL;
+ } else if (test->new_password) {
+ aresp[i].resp = strdup (test->new_password);
+ test->new_password = NULL;
+ }
+ g_assert (aresp[i].resp != NULL);
+ break;
+ case PAM_PROMPT_ECHO_ON:
+ aresp[i].resp = strdup (test->password);
+ g_assert (aresp[i].resp != NULL);
+ break;
+ case PAM_ERROR_MSG:
+ fputs(msg[i]->msg, stderr);
+ if (strlen(msg[i]->msg) > 0 &&
+ msg[i]->msg[strlen(msg[i]->msg) - 1] != '\n')
+ fputc('\n', stderr);
+ break;
+ case PAM_TEXT_INFO:
+ fprintf(stdout, "# %s", msg[i]->msg);
+ if (strlen(msg[i]->msg) > 0 &&
+ msg[i]->msg[strlen(msg[i]->msg) - 1] != '\n')
+ fputc('\n', stdout);
+ break;
+ default:
+ return PAM_CONV_ERR;
+ }
+ }
+ *resp = aresp;
+ return PAM_SUCCESS;
+}
+
+static void
+setup (Test *test,
+ gconstpointer user_data)
+{
+ const gchar *pam_conf = user_data;
+ GError *error = NULL;
+ gchar *contents;
+ gboolean found;
+ gchar *filename;
+ gchar *env;
+ int ret;
+
+ /* First check if we have the right pam config */
+ filename = g_build_filename (SYSCONFDIR, "pam.d", pam_conf, NULL);
+ g_file_get_contents (filename, &contents, NULL, &error);
+ g_free (filename);
+
+ if (error == NULL) {
+ found = (strstr (contents, BUILDDIR) &&
+ strstr (contents, "pam_gnome_keyring.so"));
+ g_free (contents);
+ if (!found) {
+ skip_test (test, "test pam config contents invalid");
+ return;
+ }
+ } else if (g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT)) {
+ skip_test (test, "missing test pam config");
+ return;
+ }
+
+ 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->conv.conv = conv_func;
+ test->conv.appdata_ptr = test;
+ ret = pam_start (pam_conf, g_get_user_name (), &test->conv, &test->ph);
+ g_assert_cmpint (ret, ==, PAM_SUCCESS);
+
+ g_unsetenv ("GNOME_KEYRING_CONTROL");
+
+ g_assert_cmpint (pam_putenv (test->ph, "GSETTINGS_SCHEMA_DIR=" BUILDDIR "/schema"), ==, PAM_SUCCESS);
+ g_assert_cmpint (pam_putenv (test->ph, "G_DEBUG=fatal-warnings,fatal-criticals"), ==, PAM_SUCCESS);
+
+ env = g_strdup_printf ("GNOME_KEYRING_TEST_PATH=%s", test->directory);
+ g_assert_cmpint (pam_putenv (test->ph, env), ==, PAM_SUCCESS);
+ g_free (env);
+
+ env = g_strdup_printf ("DBUS_SESSION_BUS_ADDRESS=%s", g_test_dbus_get_bus_address (test->dbus));
+ g_assert_cmpint (pam_putenv (test->ph, env), ==, PAM_SUCCESS);
+ g_free (env);
+
+ test->connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
+ g_assert_no_error (error);
+}
+
+static void
+teardown (Test *test,
+ gconstpointer unused)
+{
+ if (test->skipping)
+ return;
+
+ g_object_unref (test->connection);
+
+ pam_end (test->ph, PAM_SUCCESS);
+
+ if (test->pid) {
+ if (waitpid (test->pid, NULL, WNOHANG) != test->pid) {
+ kill (test->pid, SIGTERM);
+ g_assert_cmpint (waitpid (test->pid, NULL, 0), ==, test->pid);
+ }
+ g_spawn_close_pid (test->pid);
+ }
+
+ egg_tests_remove_scratch_directory (test->directory);
+ g_free (test->directory);
+
+ g_test_dbus_down (test->dbus);
+ g_object_unref (test->dbus);
+}
+
+static gboolean
+check_if_login_keyring_locked (Test *test)
+{
+ GVariant *retval;
+ GError *error = NULL;
+ GVariant *prop;
+ gboolean ret;
+
+ retval = g_dbus_connection_call_sync (test->connection,
+ "org.gnome.keyring",
+ "/org/freedesktop/secrets/collection/login",
+ "org.freedesktop.DBus.Properties",
+ "Get",
+ g_variant_new ("(ss)",
+ "org.freedesktop.Secret.Collection", "Locked"),
+ G_VARIANT_TYPE ("(v)"),
+ G_DBUS_CALL_FLAGS_NO_AUTO_START, -1,
+ NULL, &error);
+ g_assert_no_error (error);
+ g_variant_get (retval, "(@v)", &prop);
+ ret = g_variant_get_boolean (g_variant_get_variant (prop));
+ g_variant_unref (retval);
+
+ return ret;
+}
+
+static gboolean
+check_if_login_item_1_exists (Test *test)
+{
+ GVariant *retval;
+ GError *error = NULL;
+ gchar *remote;
+
+ retval = g_dbus_connection_call_sync (test->connection,
+ "org.gnome.keyring",
+ "/org/freedesktop/secrets/collection/login/1",
+ "org.freedesktop.DBus.Properties",
+ "Get",
+ g_variant_new ("(ss)",
+ "org.freedesktop.Secret.Item", "Locked"),
+ G_VARIANT_TYPE ("(v)"),
+ G_DBUS_CALL_FLAGS_NO_AUTO_START, -1,
+ NULL, &error);
+
+ if (error) {
+ remote = g_dbus_error_get_remote_error (error);
+ if (!remote || !g_str_equal (remote, "org.freedesktop.Secret.Error.NoSuchObject"))
+ g_assert_no_error (error);
+ g_error_free (error);
+ return FALSE;
+ }
+
+ g_variant_unref (retval);
+ return TRUE;
+}
+
+static void
+test_starts_creates (Test *test,
+ gconstpointer user_data)
+{
+ const char *pam_conf = user_data;
+ gboolean start_in_session;
+ const gchar *control;
+ gchar *login_keyring;
+
+ if (test->skipping)
+ return;
+
+ start_in_session = (strstr (pam_conf, "session") != NULL);
+
+ login_keyring = g_build_filename (test->directory, "login.keyring", NULL);
+ g_assert (!g_file_test (login_keyring, G_FILE_TEST_EXISTS));
+
+ test->password = "booo";
+ g_assert_cmpint (pam_authenticate (test->ph, 0), ==, PAM_SUCCESS);
+
+ if (start_in_session)
+ g_assert_cmpint (pam_open_session (test->ph, 0), ==, PAM_SUCCESS);
+
+ g_assert (pam_getenv (test->ph, "GNOME_KEYRING_CONTROL") != NULL);
+ control = pam_getenv (test->ph, "GNOME_KEYRING_CONTROL");
+
+ /* Initialize the daemon for real */
+ g_assert (gkd_control_initialize (control, "secrets", PASS_ENVIRON));
+
+ /* The keyring was created */
+ g_assert (g_file_test (login_keyring, G_FILE_TEST_IS_REGULAR));
+ g_free (login_keyring);
+
+ g_assert (check_if_login_keyring_locked (test) == FALSE);
+ g_assert (check_if_login_item_1_exists (test) == FALSE);
+
+ if (!start_in_session)
+ g_assert_cmpint (pam_open_session (test->ph, 0), ==, PAM_SUCCESS);
+
+ g_assert (gkd_control_quit (control, 0));
+}
+
+static void
+test_starts_exists (Test *test,
+ gconstpointer user_data)
+{
+ const gchar *pam_conf = user_data;
+ const gchar *control;
+ gboolean start_in_session;
+
+ if (test->skipping)
+ return;
+
+ start_in_session = (strstr (pam_conf, "session") != NULL);
+
+ egg_tests_copy_scratch_file (test->directory, SRCDIR "/pam/fixtures/login.keyring");
+
+ test->password = "booo";
+ g_assert_cmpint (pam_authenticate (test->ph, 0), ==, PAM_SUCCESS);
+
+ if (start_in_session)
+ g_assert_cmpint (pam_open_session (test->ph, 0), ==, PAM_SUCCESS);
+
+ g_assert (pam_getenv (test->ph, "GNOME_KEYRING_CONTROL") != NULL);
+ control = pam_getenv (test->ph, "GNOME_KEYRING_CONTROL");
+
+ /* Initialize the daemon for real */
+ g_assert (gkd_control_initialize (control, "secrets", PASS_ENVIRON));
+
+ /* Lookup the item */
+ g_assert (check_if_login_keyring_locked (test) == FALSE);
+ g_assert (check_if_login_item_1_exists (test) == TRUE);
+
+ if (!start_in_session)
+ g_assert_cmpint (pam_open_session (test->ph, 0), ==, PAM_SUCCESS);
+
+ g_assert (gkd_control_quit (control, 0));
+}
+
+static void
+test_auth_nostart (Test *test,
+ gconstpointer user_data)
+{
+ gchar *login_keyring;
+
+ if (test->skipping)
+ return;
+
+ test->password = "booo";
+ g_assert_cmpint (pam_authenticate (test->ph, 0), ==, PAM_SUCCESS);
+
+ g_assert (pam_getenv (test->ph, "GNOME_KEYRING_CONTROL") == NULL);
+
+ login_keyring = g_build_filename (test->directory, "login.keyring", NULL);
+ g_assert (!g_file_test (login_keyring, G_FILE_TEST_EXISTS));
+ g_free (login_keyring);
+}
+
+static void
+test_auth_running_unlocks (Test *test,
+ gconstpointer user_data)
+{
+ const gchar *control;
+ gchar **env;
+ GPid pid;
+
+ const gchar *argv[] = {
+ BUILDDIR "/gnome-keyring-daemon", "--foreground", NULL,
+ };
+
+ if (test->skipping)
+ return;
+
+ 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);
+
+ test->password = "booo";
+ g_assert_cmpint (pam_authenticate (test->ph, 0), ==, PAM_SUCCESS);
+
+ /* Lookup the item */
+ g_assert (check_if_login_keyring_locked (test) == FALSE);
+ g_assert (check_if_login_item_1_exists (test) == TRUE);
+
+ g_assert (gkd_control_quit (control, 0));
+ g_assert_cmpint (waitpid (pid, NULL, 0), ==, pid);
+
+ g_strfreev (env);
+}
+
+static void
+test_password_changes_running (Test *test,
+ gconstpointer user_data)
+{
+ const gchar *control;
+ gchar **env;
+ GPid pid;
+
+ const gchar *argv[] = {
+ BUILDDIR "/gnome-keyring-daemon", "--foreground", NULL
+ };
+
+ if (test->skipping)
+ return;
+
+ 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);
+
+ test->password = "booo";
+ test->new_password = "changed";
+ g_assert_cmpint (pam_chauthtok (test->ph, 0), ==, PAM_SUCCESS);
+
+ /* 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_assert (gkd_control_unlock (control, "changed"));
+ g_assert (gkd_control_quit (control, 0));
+ g_assert_cmpint (waitpid (pid, NULL, 0), ==, pid);
+
+ g_strfreev (env);
+}
+
+static void
+test_password_changes_starts (Test *test,
+ gconstpointer user_data)
+{
+ const gchar *control;
+ gchar **env;
+ GPid pid;
+
+ const gchar *argv[] = {
+ BUILDDIR "/gnome-keyring-daemon", "--foreground", NULL,
+ };
+
+ if (test->skipping)
+ return;
+
+ egg_tests_copy_scratch_file (test->directory, SRCDIR "/pam/fixtures/login.keyring");
+
+ test->password = "booo";
+ test->new_password = "changed";
+ g_assert_cmpint (pam_chauthtok (test->ph, 0), ==, PAM_SUCCESS);
+
+ /* Start it again */
+ 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);
+}
+
+int
+main (int argc, char **argv)
+{
+ g_test_init (&argc, &argv, NULL);
+
+ g_test_add ("/pam/auth-no-start", Test,
+ "gnome-keyring-test-no-start",
+ setup, test_auth_nostart, teardown);
+
+ g_test_add ("/pam/auth-starts-creates-keyring", Test,
+ "gnome-keyring-test-auth-start",
+ setup, test_starts_creates, teardown);
+ g_test_add ("/pam/session-starts-creates-keyring", Test,
+ "gnome-keyring-test-session-start",
+ setup, test_starts_creates, teardown);
+
+ g_test_add ("/pam/auth-starts-unlocks-existing", Test,
+ "gnome-keyring-test-auth-start",
+ setup, test_starts_exists, teardown);
+ g_test_add ("/pam/session-starts-unlocks-existing", Test,
+ "gnome-keyring-test-session-start",
+ setup, test_starts_exists, teardown);
+
+ g_test_add ("/pam/auth-running-unlocks-existing", Test,
+ "gnome-keyring-test-no-start",
+ setup, test_auth_running_unlocks, teardown);
+
+ g_test_add ("/pam/password-changes-running", Test,
+ "gnome-keyring-test-no-start",
+ setup, test_password_changes_running, teardown);
+ g_test_add ("/pam/password-changes-starts", Test,
+ "gnome-keyring-test-no-start",
+ setup, test_password_changes_starts, teardown);
+
+ return g_test_run ();
+}