diff -upr gnome-keyring-2.20.3.orig/daemon/gkr-daemon.c gnome-keyring-2.20.3/daemon/gkr-daemon.c --- gnome-keyring-2.20.3.orig/daemon/gkr-daemon.c 2007-11-24 17:33:44.000000000 +0000 +++ gnome-keyring-2.20.3/daemon/gkr-daemon.c 2008-01-08 16:59:46.000000000 +0000 @@ -27,6 +27,7 @@ #include "common/gkr-async.h" #include "common/gkr-cleanup.h" #include "common/gkr-unix-signal.h" +#include "common/gkr-location.h" #include "keyrings/gkr-keyrings.h" @@ -183,6 +184,10 @@ main (int argc, char *argv[]) GIOChannel *channel; GMainContext *ctx; int i; + gboolean login; + char *login_password; + int len; + GkrKeyring *login_keyring; g_type_init (); g_thread_init (NULL); @@ -214,6 +219,7 @@ main (int argc, char *argv[]) foreground = FALSE; daemon = FALSE; + login = FALSE; if (argc > 1) { for (i = 1; i < argc; i++) { @@ -221,8 +227,19 @@ main (int argc, char *argv[]) foreground = TRUE; if (strcmp (argv[i], "-d") == 0) daemon = TRUE; + if (strcmp (argv[i], "--login") == 0) + login = TRUE; } } + + login_password = NULL; + if (login) { + login_password = gnome_keyring_memory_alloc (256); + fgets (login_password, 256, stdin); + len = strlen (login_password); + if (login_password[len-1] == '\n') + login_password[len-1] = 0; + } if (!foreground) { pid = fork (); @@ -318,6 +335,27 @@ main (int argc, char *argv[]) gkr_daemon_dbus_setup (loop, path); #endif + + if (login_password) { + login_keyring = gkr_keyrings_get_login (); + if (login_keyring) { + if (!gkr_keyring_unlock (login_keyring, + login_password)) { + g_warning ("Failed to unlock login keyring"); + } + } else { + login_keyring = + gkr_keyring_create (GKR_LOCATION_BASE_LOCAL, + "login", + login_password); + if (login_keyring) { + gkr_keyrings_add (login_keyring); + g_object_unref (login_keyring); + } + } + gnome_keyring_memory_free (login_password); + } + g_main_loop_run (loop); /* Make sure no other threads are running */ diff -upr gnome-keyring-2.20.3.orig/pam/gkr-pam-module.c gnome-keyring-2.20.3/pam/gkr-pam-module.c --- gnome-keyring-2.20.3.orig/pam/gkr-pam-module.c 2007-11-30 18:50:29.000000000 +0000 +++ gnome-keyring-2.20.3/pam/gkr-pam-module.c 2008-01-08 17:00:50.000000000 +0000 @@ -249,17 +249,22 @@ cleanup_free_password (pam_handle_t *ph, } static void -setup_child (int outp[2], int errp[2], pam_handle_t *ph, struct passwd *pwd) +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", NULL}; + char *args[] = { GNOME_KEYRING_DAEMON, "-d", "--login", NULL}; const char* display; int ret; assert (pwd); assert (pwd->pw_dir); - + + /* If no password, don't pas in --login */ + if (password == NULL) + args[2] = NULL; + /* Fix up our end of the pipes */ - if (dup2 (outp[WRITE_END], STDOUT) < 0 || + if (dup2 (inp[READ_END], STDIN) < 0 || + dup2 (outp[WRITE_END], STDOUT) < 0 || dup2 (errp[WRITE_END], STDERR) < 0) { syslog (GKR_LOG_ERR, "gkr-pam: couldn't setup pipes: %s", strerror (errno)); @@ -267,6 +272,8 @@ setup_child (int outp[2], int errp[2], p } /* Close unnecessary file descriptors */ + close (inp[READ_END]); + close (inp[WRITE_END]); close (outp[READ_END]); close (outp[WRITE_END]); close (errp[READ_END]); @@ -358,9 +365,10 @@ setup_environment (char *line, void *arg } static int -start_daemon (pam_handle_t *ph, struct passwd *pwd) +start_daemon (pam_handle_t *ph, struct passwd *pwd, const char *password) { struct sigaction defsact, oldsact; + int inp[2] = { -1, -1 }; int outp[2] = { -1, -1 }; int errp[2] = { -1, -1 }; int ret = PAM_SERVICE_ERR; @@ -382,7 +390,7 @@ start_daemon (pam_handle_t *ph, struct p sigaction (SIGCHLD, &defsact, &oldsact); /* Create the necessary pipes */ - if (pipe (outp) < 0 || pipe (errp) < 0) { + if (pipe (inp) < 0 || pipe (outp) < 0 || pipe (errp) < 0) { syslog (GKR_LOG_ERR, "gkr-pam: couldn't create pipes: %s", strerror (errno)); goto done; @@ -397,7 +405,7 @@ start_daemon (pam_handle_t *ph, struct p /* This is the child */ case 0: - setup_child (outp, errp, ph, pwd); + setup_child (inp, outp, errp, ph, pwd, password); /* Should never be reached */ break; @@ -407,9 +415,16 @@ start_daemon (pam_handle_t *ph, struct p }; /* Close our unneeded ends of the pipes */ + close (inp[READ_END]); close (outp[WRITE_END]); close (errp[WRITE_END]); - outp[WRITE_END] = errp[WRITE_END] = -1; + inp[READ_END] = outp[WRITE_END] = errp[WRITE_END] = -1; + + if (password) { + /* Write the login keyring password */ + write (inp[WRITE_END], password, strlen (password)); + write (inp[WRITE_END], "\n", 1); + } /* * Note that we're not using select() or any such. We know how the @@ -448,6 +463,8 @@ done: /* Restore old handler */ sigaction (SIGCHLD, &oldsact, NULL); + close_safe (inp[0]); + close_safe (inp[1]); close_safe (outp[0]); close_safe (outp[1]); close_safe (errp[0]); @@ -460,7 +477,7 @@ done: } static int -start_daemon_if_necessary (pam_handle_t *ph, struct passwd *pwd) +start_daemon_if_necessary (pam_handle_t *ph, struct passwd *pwd, const char *password) { const char *socket; int ret; @@ -480,7 +497,7 @@ start_daemon_if_necessary (pam_handle_t } /* Not running, start process */ - return start_daemon (ph, pwd); + return start_daemon (ph, pwd, password); } static int @@ -701,6 +718,7 @@ pam_sm_authenticate (pam_handle_t *ph, i struct passwd *pwd; const char *user, *password; const char *socket; + int started_daemon; uint args; int ret; @@ -738,9 +756,11 @@ pam_sm_authenticate (pam_handle_t *ph, i } + started_daemon = 0; /* Should we start the daemon? */ if (args & ARG_AUTO_START) { - ret = start_daemon_if_necessary (ph, pwd); + started_daemon = 1; + ret = start_daemon_if_necessary (ph, pwd, password); if (ret != PAM_SUCCESS) return ret; } @@ -749,10 +769,12 @@ pam_sm_authenticate (pam_handle_t *ph, i /* If gnome keyring is running, then unlock now */ if (socket) { - ret = unlock_keyring (ph, pwd, password); - if (ret != PAM_SUCCESS) - return ret; - + /* 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 in open session, store password */ } else { if (pam_set_data (ph, "gkr_system_authtok", strdup (password), @@ -772,6 +794,7 @@ pam_sm_open_session (pam_handle_t *ph, i struct passwd *pwd; int ret; uint args = parse_args (argc, argv); + int started_daemon; /* Figure out the user name */ ret = pam_get_user (ph, &user, NULL); @@ -787,29 +810,32 @@ pam_sm_open_session (pam_handle_t *ph, i return PAM_SERVICE_ERR; } - /* Should we start the daemon? */ - if (args & ARG_AUTO_START) { - ret = start_daemon_if_necessary (ph, pwd); - if (ret != PAM_SUCCESS) - return ret; - } - /* Get the stored authtok here */ if (pam_get_data (ph, "gkr_system_authtok", (const void**)&password) != PAM_SUCCESS) { - /* * No password, no worries, maybe this (PAM using) application * didn't do authentication, or is hopeless and wants to call * different PAM callbacks from different processes. * * No use complaining - */ - return PAM_SUCCESS; + */ + password = NULL; } - if (unlock_keyring (ph, pwd, password) != PAM_SUCCESS) - return PAM_SERVICE_ERR; + started_daemon = 0; + /* Should we start the daemon? */ + if (args & ARG_AUTO_START) { + started_daemon = 1; + ret = start_daemon_if_necessary (ph, pwd, password); + if (ret != PAM_SUCCESS) + return ret; + } + if (!started_daemon && password != NULL) { + if (unlock_keyring (ph, pwd, password) != PAM_SUCCESS) + return PAM_SERVICE_ERR; + } + return PAM_SUCCESS; } @@ -907,7 +933,7 @@ pam_chauthtok_update (pam_handle_t *ph, * argument. Because if the password is being changed, then making * the 'login' keyring match it is a priority. */ - ret = start_daemon_if_necessary (ph, pwd); + ret = start_daemon_if_necessary (ph, pwd, original); if (ret != PAM_SUCCESS) return ret;