diff options
author | George Lebl <jirka@5z.com> | 2001-09-27 04:10:06 +0000 |
---|---|---|
committer | George Lebl <jirka@src.gnome.org> | 2001-09-27 04:10:06 +0000 |
commit | fed3c0d16a1bfd742e1ee455986aa7cbfe8f1d10 (patch) | |
tree | 87d951e9f98594fe34e7e8335309c1fe6ae38efa | |
parent | 7dba418955f0a06edaa1a1e4d48180d5ad610129 (diff) | |
download | gdm-fed3c0d16a1bfd742e1ee455986aa7cbfe8f1d10.tar.gz |
Add a failsafe question dialog similar in operation to the failsafe error
Wed Sep 26 21:01:38 2001 George Lebl <jirka@5z.com>
* daemon/verify.h, daemon/verify-*.c, daemon/slave.c,
daemon/errorgui.[ch], daemon/gdm.c: Add a failsafe question
dialog similar in operation to the failsafe error box, and use
it in the standalone pam conv function. Kill all instances of
PAM_SILENT since we can now always converse with the user.
* daemon/verify-pam.c: use a global pamh again but this time a bit
smarter. Make sure if we use a global one that it has all the
right things set. Also set PAM_RHOST to "localhost" or the remote
host if not a "console" login. Set PAM_RUSER to "gdm" (or whatever
the gdm user is). I'm sure I'm fucking something up again but
I can't find enough docs to verify that what I'm doing is 100%
correct. Not to mention that there seem to be some braindead
modules out there to begin with.
-rw-r--r-- | ChangeLog | 17 | ||||
-rw-r--r-- | daemon/errorgui.c | 153 | ||||
-rw-r--r-- | daemon/errorgui.h | 11 | ||||
-rw-r--r-- | daemon/gdm.c | 19 | ||||
-rw-r--r-- | daemon/slave.c | 22 | ||||
-rw-r--r-- | daemon/verify-crypt.c | 12 | ||||
-rw-r--r-- | daemon/verify-pam.c | 295 | ||||
-rw-r--r-- | daemon/verify-shadow.c | 10 | ||||
-rw-r--r-- | daemon/verify.h | 11 |
9 files changed, 467 insertions, 83 deletions
@@ -1,3 +1,20 @@ +Wed Sep 26 21:01:38 2001 George Lebl <jirka@5z.com> + + * daemon/verify.h, daemon/verify-*.c, daemon/slave.c, + daemon/errorgui.[ch], daemon/gdm.c: Add a failsafe question + dialog similar in operation to the failsafe error box, and use + it in the standalone pam conv function. Kill all instances of + PAM_SILENT since we can now always converse with the user. + + * daemon/verify-pam.c: use a global pamh again but this time a bit + smarter. Make sure if we use a global one that it has all the + right things set. Also set PAM_RHOST to "localhost" or the remote + host if not a "console" login. Set PAM_RUSER to "gdm" (or whatever + the gdm user is). I'm sure I'm fucking something up again but + I can't find enough docs to verify that what I'm doing is 100% + correct. Not to mention that there seem to be some braindead + modules out there to begin with. + Mon Sep 17 07:17:32 2001 George Lebl <jirka@5z.com> * gui/gdmlogin.c: fix crash when quiver would happen while diff --git a/daemon/errorgui.c b/daemon/errorgui.c index a4aeb03f..10ba0f9e 100644 --- a/daemon/errorgui.c +++ b/daemon/errorgui.c @@ -172,4 +172,157 @@ gdm_error_box (GdmDisplay *d, const char *dialog_type, const char *error) } } +char * +gdm_run_failsafe_question (const char *question, + gboolean echo, + int screenx, + int screeny, + int screenwidth, + int screenheight) +{ + GtkWidget *dialog; + GtkRequisition req; + guint sid; + GtkWidget *entry, *label; + char *ret; + char **argv = g_new0 (char *, 2); + argv[0] = "gdm-failsafe-question"; + + /* Avoid creating ~gdm/.gnome stuff */ + gnome_do_not_create_directories = TRUE; + + gnome_init ("gdm-failsafe-question", VERSION, 1, argv); + + sid = gtk_signal_lookup ("event", + GTK_TYPE_WIDGET); + gtk_signal_add_emission_hook (sid, + gdm_event, + NULL); + + dialog = gnome_dialog_new (question, + GNOME_STOCK_BUTTON_OK, + NULL); + gnome_dialog_close_hides (GNOME_DIALOG (dialog), + TRUE /* just_hide */); + + label = gtk_label_new (question); + gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (dialog)->vbox), + label, FALSE, FALSE, 0); + entry = gtk_entry_new (); + gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (dialog)->vbox), + entry, FALSE, FALSE, 0); + if ( ! echo) + gtk_entry_set_visibility (GTK_ENTRY (entry), + FALSE /* visible */); + gnome_dialog_editable_enters (GNOME_DIALOG (dialog), + GTK_EDITABLE (entry)); + + gtk_widget_show_all (dialog); + + gtk_widget_size_request (dialog, &req); + + if (screenwidth <= 0) + screenwidth = gdk_screen_width (); + if (screenheight <= 0) + screenheight = gdk_screen_height (); + + gtk_widget_set_uposition (dialog, + screenx + + (screenwidth / 2) - + (req.width / 2), + screeny + + (screenheight / 2) - + (req.height / 2)); + + gtk_widget_grab_focus (entry); + + gtk_widget_show_now (dialog); + + if (dialog->window != NULL) { + gdk_error_trap_push (); + XSetInputFocus (GDK_DISPLAY (), + GDK_WINDOW_XWINDOW (dialog->window), + RevertToPointerRoot, + CurrentTime); + gdk_flush (); + gdk_error_trap_pop (); + } + + gnome_dialog_run_and_close (GNOME_DIALOG (dialog)); + + ret = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry))); + gtk_widget_destroy (dialog); + return ret; +} + +char * +gdm_failsafe_question (GdmDisplay *d, + const char *question, + gboolean echo) +{ + pid_t pid; + int p[2]; + + if (pipe (p) < 0) + return NULL; + + gdm_safe_fork (&extra_process); + pid = extra_process; + if (pid == 0) { + char *geom; + int i; + + for (i = 0; i < sysconf (_SC_OPEN_MAX); i++) { + if (p[1] != i) + close(i); + } + + /* No error checking here - if it's messed the best response + * is to ignore & try to continue */ + open ("/dev/null", O_RDONLY); /* open stdin - fd 0 */ + open ("/dev/null", O_RDWR); /* open stdout - fd 1 */ + open ("/dev/null", O_RDWR); /* open stderr - fd 2 */ + + /* The pipe on stdout */ + dup2 (p[1], 1); + + if (d != NULL) + geom = g_strdup_printf ("%d:%d:%d:%d", + d->screenx, + d->screeny, + d->screenwidth, + d->screenheight); + else + geom = "0:0:0:0"; + + if (stored_path != NULL) + putenv (stored_path); + execlp (stored_argv[0], + stored_argv[0], + "--run-failsafe-question", + question, + echo ? "TRUE" : "FALSE", + geom, + NULL); + gdm_error (_("gdm_failsafe_question: Failed to execute self")); + _exit (1); + } else if (pid > 0) { + char buf[BUFSIZ]; + int bytes; + close (p[1]); + waitpid (pid, 0, 0); + extra_process = -1; + bytes = read (p[0], buf, BUFSIZ-1); + if (bytes > 0) { + close (p[0]); + buf[bytes] = '\0'; + return g_strdup (buf); + } + close (p[0]); + } else { + gdm_error (_("gdm_failsafe_question: Cannot fork to display error/info box")); + } + return NULL; +} + /* EOF */ diff --git a/daemon/errorgui.h b/daemon/errorgui.h index be9af821..fa4e6275 100644 --- a/daemon/errorgui.h +++ b/daemon/errorgui.h @@ -33,6 +33,17 @@ void gdm_error_box (GdmDisplay *d, const char *dialog_type, const char *error); +char * gdm_run_failsafe_question(const char *question, + gboolean echo, + int screenx, + int screeny, + int screenwidth, + int screenheight); +/* this spawns self with the argument to run the above */ +char * gdm_failsafe_question (GdmDisplay *d, + const char *question, + gboolean echo); + #endif /* GDM_ERRORGUI_H */ /* EOF */ diff --git a/daemon/gdm.c b/daemon/gdm.c index 677c9aa3..73ca9939 100644 --- a/daemon/gdm.c +++ b/daemon/gdm.c @@ -1231,6 +1231,25 @@ main (int argc, char *argv[]) gdm_run_errorgui (argv[2], argv[3], x, y, width, height); _exit (0); } + /* This is another utter hack. Same as above but for questions */ + if (argc == 5 && + strcmp (argv[1], "--run-failsafe-question") == 0) { + int x = 0, y = 0, width = 0, height = 0; + gboolean echo; + char *ret; + sscanf (argv[4], "%d:%d:%d:%d", &x, &y, &width, &height); + if (strcmp (argv[3], "FALSE") == 0) + echo = FALSE; + else + echo = TRUE; + ret = gdm_run_failsafe_question (argv[2], echo, x, y, width, height); + if (ret != NULL) { + g_print (ret); + fflush (stdout); + } + _exit (0); + } + /* XDM compliant error message */ if (getuid() != 0) { diff --git a/daemon/slave.c b/daemon/slave.c index 6bcee30b..be386390 100644 --- a/daemon/slave.c +++ b/daemon/slave.c @@ -268,7 +268,7 @@ setup_automatic_session (GdmDisplay *display, const char *name) greet = FALSE; gdm_debug ("setup_automatic_session: Automatic login: %s", login); - gdm_verify_setup_user (login, display->name); + gdm_verify_setup_user (display, login, display->name); /* Run the init script. gdmslave suspends until script * has terminated */ @@ -679,7 +679,8 @@ gdm_slave_wait_for_login (void) setegid (0); gdm_debug ("gdm_slave_wait_for_login: In loop"); - login = gdm_verify_user (NULL /* username*/, + login = gdm_verify_user (d, + NULL /* username*/, d->name, d->console); gdm_debug ("gdm_slave_wait_for_login: end verify for '%s'", @@ -705,7 +706,8 @@ gdm_slave_wait_for_login (void) oldAllowRoot = GdmAllowRoot; GdmAllowRoot = TRUE; gdm_slave_greeter_ctl_no_ret (GDM_SETLOGIN, "root"); - login = gdm_verify_user ("root", + login = gdm_verify_user (d, + "root", d->name, d->console); GdmAllowRoot = oldAllowRoot; @@ -762,7 +764,7 @@ gdm_slave_wait_for_login (void) * may have sighupped the main gdm server and with it * wiped us */ - gdm_verify_cleanup (); + gdm_verify_cleanup (d); gdm_slave_send_num (GDM_SOP_LOGGED_IN, FALSE); @@ -1953,7 +1955,7 @@ gdm_slave_session_start (void) /* setup the verify env vars, set credentials and such stuff * and open the session */ - if ( ! gdm_verify_open_session ()) + if ( ! gdm_verify_open_session (d)) gdm_child_exit (DISPLAY_REMANAGE, _("%s: Could not open session for %s. " "Aborting."), @@ -2177,7 +2179,7 @@ gdm_slave_session_stop (pid_t sesspid) if (sesspid > 0) kill (- (sesspid), SIGTERM); - gdm_verify_cleanup(); + gdm_verify_cleanup (d); pwent = getpwnam (local_login); /* PAM overwrites our pwent */ @@ -2259,7 +2261,7 @@ gdm_slave_term_handler (int sig) gdm_debug ("gdm_slave_term_handler: Whacking server"); gdm_server_stop (d); - gdm_verify_cleanup(); + gdm_verify_cleanup (d); _exit (DISPLAY_ABORT); } @@ -2327,7 +2329,7 @@ gdm_slave_child_handler (int sig) /* if greet is TRUE, then the greeter died outside of our * control really, so clean up and die, something is wrong */ gdm_server_stop (d); - gdm_verify_cleanup (); + gdm_verify_cleanup (d); if (WIFEXITED (status)) { _exit (WEXITSTATUS (status)); @@ -2395,7 +2397,7 @@ gdm_slave_xioerror_handler (Display *disp) gdm_error (_("gdm_slave_xioerror_handler: Fatal X error - Restarting %s"), d->name); gdm_server_stop (d); - gdm_verify_cleanup (); + gdm_verify_cleanup (d); if (do_xfailed_on_xio_error) _exit (DISPLAY_XFAILED); @@ -2463,7 +2465,7 @@ gdm_slave_exit (gint status, const gchar *format, ...) setegid (0); gdm_server_stop (d); - gdm_verify_cleanup (); + gdm_verify_cleanup (d); /* Kill children where applicable */ if (d->greetpid != 0) diff --git a/daemon/verify-crypt.c b/daemon/verify-crypt.c index 14cd8f23..450cef49 100644 --- a/daemon/verify-crypt.c +++ b/daemon/verify-crypt.c @@ -22,7 +22,7 @@ #include <pwd.h> #ifdef HAVE_CRYPT - #include <crypt.h> +# include <crypt.h> #endif /* HAVE_CRYPT */ #include <vicious.h> @@ -54,7 +54,8 @@ extern gboolean GdmAllowRemoteRoot; */ gchar * -gdm_verify_user (const char *username, +gdm_verify_user (GdmDisplay *d, + const char *username, const gchar *display, gboolean local) { @@ -203,7 +204,8 @@ gdm_verify_user (const char *username, */ void -gdm_verify_setup_user (const gchar *login, const gchar *display) +gdm_verify_setup_user (GdmDisplay *d, + const gchar *login, const gchar *display) { } @@ -215,7 +217,7 @@ gdm_verify_setup_user (const gchar *login, const gchar *display) */ void -gdm_verify_cleanup (void) +gdm_verify_cleanup (GdmDisplay *d) { } @@ -234,7 +236,7 @@ gdm_verify_check (void) /* used in pam */ gboolean -gdm_verify_open_session (void) +gdm_verify_open_session (GdmDisplay *d) { return TRUE; } diff --git a/daemon/verify-pam.c b/daemon/verify-pam.c index 331dae8c..2bfe1b1f 100644 --- a/daemon/verify-pam.c +++ b/daemon/verify-pam.c @@ -29,6 +29,7 @@ #include "misc.h" #include "slave.h" #include "verify.h" +#include "errorgui.h" static const gchar RCSid[]="$Id$"; @@ -38,11 +39,15 @@ extern gboolean GdmVerboseAuth; extern gboolean GdmAllowRoot; extern gboolean GdmAllowRemoteRoot; extern gchar *GdmTimedLogin; +extern gchar *GdmUser; extern gboolean GdmAllowRemoteAutoLogin; /* Evil, but this way these things are passed to the child session */ static char *current_login = NULL; static char *current_display = NULL; +static pam_handle_t *pamh = NULL; + +static GdmDisplay *cur_gdm_disp = NULL; /* Internal PAM conversation function. Interfaces between the PAM @@ -125,8 +130,69 @@ gdm_verify_standalone_pam_conv (int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr) { - /* FIXME: always error out for now! */ - return PAM_CONV_ERR; + int replies = 0; + char *s; + struct pam_response *reply = NULL; + + reply = malloc (sizeof (struct pam_response) * num_msg); + + if (!reply) + return PAM_CONV_ERR; + + memset (reply, 0, sizeof (struct pam_response) * num_msg); + + for (replies = 0; replies < num_msg; replies++) { + + switch (msg[replies]->msg_style) { + + case PAM_PROMPT_ECHO_ON: + /* PAM requested textual input with echo on */ + s = gdm_failsafe_question (cur_gdm_disp, + _((gchar *) msg[replies]->msg), + TRUE /* echo */); + reply[replies].resp_retcode = PAM_SUCCESS; + reply[replies].resp = strdup (ve_sure_string (s)); + g_free (s); + break; + + case PAM_PROMPT_ECHO_OFF: + /* PAM requested textual input with echo off */ + s = gdm_failsafe_question (cur_gdm_disp, + _((gchar *) msg[replies]->msg), + FALSE /* echo */); + reply[replies].resp_retcode = PAM_SUCCESS; + reply[replies].resp = strdup (ve_sure_string (s)); + g_free (s); + break; + + case PAM_ERROR_MSG: + /* PAM sent a message that should displayed to the user */ + gdm_error_box (cur_gdm_disp, + GNOME_MESSAGE_BOX_ERROR, + _((gchar *) msg[replies]->msg)); + reply[replies].resp_retcode = PAM_SUCCESS; + reply[replies].resp = NULL; + break; + + case PAM_TEXT_INFO: + /* PAM sent a message that should displayed to the user */ + gdm_error_box (cur_gdm_disp, + GNOME_MESSAGE_BOX_INFO, + _((gchar *) msg[replies]->msg)); + reply[replies].resp_retcode = PAM_SUCCESS; + reply[replies].resp = NULL; + break; + + default: + /* PAM has been smoking serious crack */ + free (reply); + return PAM_CONV_ERR; + } + + } + + *resp = reply; + return PAM_SUCCESS; } static struct pam_conv standalone_pamc = { @@ -148,7 +214,8 @@ static struct pam_conv standalone_pamc = { */ gchar * -gdm_verify_user (const char *username, +gdm_verify_user (GdmDisplay *d, + const char *username, const gchar *display, gboolean local) { @@ -158,7 +225,10 @@ gdm_verify_user (const char *username, gboolean error_msg_given = FALSE; gboolean started_timer = FALSE; gchar *auth_errmsg; - pam_handle_t *pamh; + + if (pamh != NULL) + pam_end (pamh, PAM_SUCCESS); + pamh = NULL; /* start the timer for timed logins */ if (local || @@ -180,6 +250,8 @@ gdm_verify_user (const char *username, } else { login = g_strdup (username); } + + cur_gdm_disp = d; /* Initialize a PAM session for the user */ if ((pamerr = pam_start ("gdm", login, &pamc, &pamh)) != PAM_SUCCESS) { @@ -199,6 +271,26 @@ gdm_verify_user (const char *username, goto pamerr; } + /* gdm is requesting the login */ + if ((pamerr = pam_set_item (pamh, PAM_RUSER, GdmUser)) != PAM_SUCCESS) { + if (started_timer) + gdm_slave_greeter_ctl_no_ret (GDM_STOPTIMER, ""); + if (gdm_slave_should_complain ()) + gdm_error (_("Can't set PAM_RUSER=%s"), GdmUser); + goto pamerr; + } + + /* From the host of the display */ + if ((pamerr = pam_set_item (pamh, PAM_RHOST, + d->console ? "localhost" : d->hostname)) != PAM_SUCCESS) { + if (started_timer) + gdm_slave_greeter_ctl_no_ret (GDM_STOPTIMER, ""); + if (gdm_slave_should_complain ()) + gdm_error (_("Can't set PAM_RHOST=%s"), + d->console ? "localhost" : d->hostname); + goto pamerr; + } + /* Start authentication session */ if ((pamerr = pam_authenticate (pamh, 0)) != PAM_SUCCESS) { if (started_timer) @@ -262,8 +354,6 @@ gdm_verify_user (const char *username, goto pamerr; } - pam_end (pamh, PAM_SUCCESS); - /* Workaround to avoid gdm messages being logged as PAM_pwdb */ closelog (); openlog ("gdm", LOG_PID, LOG_DAEMON); @@ -272,6 +362,8 @@ gdm_verify_user (const char *username, current_login = g_strdup (login); g_free (current_display); current_display = g_strdup (display); + + cur_gdm_disp = NULL; return login; @@ -298,7 +390,9 @@ gdm_verify_user (const char *username, gdm_slave_greeter_ctl_no_ret (GDM_MSGERR, _("Please enter your username"));*/ } - pam_end (pamh, pamerr); + if (pamh != NULL) + pam_end (pamh, pamerr); + pamh = NULL; /* Workaround to avoid gdm messages being logged as PAM_pwdb */ closelog (); @@ -311,9 +405,108 @@ gdm_verify_user (const char *username, g_free (login); + cur_gdm_disp = NULL; + return NULL; } +/* Ensures a pamh existance */ +static gboolean +ensure_pamh (GdmDisplay *d, + const char *login, + const char *display, + int *pamerr) +{ + if (login == NULL || + display == NULL) { + gdm_error (_("Cannot setup pam handle with null login " + "and/or display")); + return FALSE; + } + + g_assert (pamerr != NULL); + + if (pamh != NULL) { + const char *item; + + /* Make sure this is the right pamh */ + if (pam_get_item (pamh, PAM_USER, (const void **)&item) + != PAM_SUCCESS) + goto ensure_create; + + if (item == NULL || + strcmp (item, login) != 0) + goto ensure_create; + + if (pam_get_item (pamh, PAM_TTY, (const void **)&item) + != PAM_SUCCESS) + goto ensure_create; + + if (item == NULL || + strcmp (item, display) != 0) + goto ensure_create; + + /* ensure some parameters */ + if (pam_set_item (pamh, PAM_CONV, &standalone_pamc) + != PAM_SUCCESS) { + goto ensure_create; + } + if (pam_set_item (pamh, PAM_RUSER, GdmUser) + != PAM_SUCCESS) { + goto ensure_create; + } + if (d->console) { + if (pam_set_item (pamh, PAM_RHOST, "localhost") + != PAM_SUCCESS) { + goto ensure_create; + } + } else { + if (pam_set_item (pamh, PAM_RHOST, d->hostname) + != PAM_SUCCESS) { + goto ensure_create; + } + } + return TRUE; + } + +ensure_create: + if (pamh != NULL) + pam_end (pamh, PAM_SUCCESS); + pamh = NULL; + + /* Initialize a PAM session for the user */ + if ((*pamerr = pam_start ("gdm", login, &standalone_pamc, &pamh)) != PAM_SUCCESS) { + if (gdm_slave_should_complain ()) + gdm_error (_("Can't find /etc/pam.d/gdm!")); + return FALSE; + } + + /* Inform PAM of the user's tty */ + if ((*pamerr = pam_set_item (pamh, PAM_TTY, display)) != PAM_SUCCESS) { + if (gdm_slave_should_complain ()) + gdm_error (_("Can't set PAM_TTY=%s"), display); + return FALSE; + } + + /* gdm is requesting the login */ + if ((*pamerr = pam_set_item (pamh, PAM_RUSER, GdmUser)) != PAM_SUCCESS) { + if (gdm_slave_should_complain ()) + gdm_error (_("Can't set PAM_RUSER=%s"), GdmUser); + return FALSE; + } + + /* From the host of the display */ + if ((*pamerr = pam_set_item (pamh, PAM_RHOST, + d->console ? "localhost" : d->hostname)) != PAM_SUCCESS) { + if (gdm_slave_should_complain ()) + gdm_error (_("Can't set PAM_RHOST=%s"), + d->console ? "localhost" : d->hostname); + return FALSE; + } + + return TRUE; +} + /** * gdm_verify_setup_user: * @login: The name of the user @@ -324,30 +517,23 @@ gdm_verify_user (const char *username, */ void -gdm_verify_setup_user (const gchar *login, const gchar *display) +gdm_verify_setup_user (GdmDisplay *d, const gchar *login, const gchar *display) { - pam_handle_t *pamh; gint pamerr; if (!login) return; + cur_gdm_disp = d; + /* Initialize a PAM session for the user */ - if ((pamerr = pam_start ("gdm", login, &standalone_pamc, &pamh)) != PAM_SUCCESS) { - if (gdm_slave_should_complain ()) - gdm_error (_("Can't find /etc/pam.d/gdm!")); - goto setup_pamerr; - } - - /* Inform PAM of the user's tty */ - if ((pamerr = pam_set_item (pamh, PAM_TTY, display)) != PAM_SUCCESS) { - if (gdm_slave_should_complain ()) - gdm_error (_("Can't set PAM_TTY=%s"), display); + if ( ! ensure_pamh (d, login, display, &pamerr)) { goto setup_pamerr; } /* If the user's password has expired, ask for a new one */ - /* FIXME: This would require our conversation function to work */ + /* This is for automatic logins, we shouldn't bother the user + * though I'm unsure */ #if 0 pamerr = pam_acct_mgmt (pamh, 0); @@ -360,8 +546,6 @@ gdm_verify_setup_user (const gchar *login, const gchar *display) } #endif - pam_end (pamh, PAM_SUCCESS); - /* Workaround to avoid gdm messages being logged as PAM_pwdb */ closelog (); openlog ("gdm", LOG_PID, LOG_DAEMON); @@ -371,11 +555,15 @@ gdm_verify_setup_user (const gchar *login, const gchar *display) g_free (current_display); current_display = g_strdup (display); + cur_gdm_disp = NULL; + return; setup_pamerr: - pam_end (pamh, pamerr); + if (pamh != NULL) + pam_end (pamh, pamerr); + pamh = NULL; /* Workaround to avoid gdm messages being logged as PAM_pwdb */ closelog (); @@ -385,6 +573,8 @@ gdm_verify_setup_user (const gchar *login, const gchar *display) current_login = NULL; g_free (current_display); current_display = NULL; + + cur_gdm_disp = NULL; } @@ -395,38 +585,28 @@ gdm_verify_setup_user (const gchar *login, const gchar *display) */ void -gdm_verify_cleanup (void) +gdm_verify_cleanup (GdmDisplay *d) { - pam_handle_t *pamh; gint pamerr; if (current_login == NULL) return; + cur_gdm_disp = d; + /* Initialize a PAM session for the user */ - if ((pamerr = pam_start ("gdm", current_login, - &standalone_pamc, &pamh)) != PAM_SUCCESS) { - if (gdm_slave_should_complain ()) - gdm_error (_("Can't find /etc/pam.d/gdm!")); + if ( ! ensure_pamh (d, current_login, current_display, &pamerr)) { goto cleanup_pamerr; } - - /* Inform PAM of the user's tty */ - if (current_display != NULL && - (pamerr = pam_set_item - (pamh, PAM_TTY, current_display)) != PAM_SUCCESS) { - if (gdm_slave_should_complain ()) - gdm_error (_("Can't set PAM_TTY=%s"), current_display); - goto cleanup_pamerr; - } - /* FIXME: theoretically this closes even sessions that * don't exist, which I suppose is OK */ - pam_close_session (pamh, PAM_SILENT); + pam_close_session (pamh, 0); cleanup_pamerr: - pam_end (pamh, pamerr); + if (pamh != NULL) + pam_end (pamh, pamerr); + pamh = NULL; /* Workaround to avoid gdm messages being logged as PAM_pwdb */ closelog (); @@ -436,6 +616,8 @@ cleanup_pamerr: current_login = NULL; g_free (current_display); current_display = NULL; + + cur_gdm_disp = NULL; } @@ -458,34 +640,23 @@ gdm_verify_check (void) /* used in pam */ gboolean -gdm_verify_open_session (void) +gdm_verify_open_session (GdmDisplay *d) { gchar **pamenv; - pam_handle_t *pamh; gint pamerr; if (current_login == NULL) return FALSE; + cur_gdm_disp = d; + /* Initialize a PAM session for the user */ - if ((pamerr = pam_start ("gdm", current_login, - &standalone_pamc, &pamh)) != PAM_SUCCESS) { - if (gdm_slave_should_complain ()) - gdm_error (_("Can't find /etc/pam.d/gdm!")); - goto open_pamerr; - } - - /* Inform PAM of the user's tty */ - if (current_display != NULL && - (pamerr = pam_set_item - (pamh, PAM_TTY, current_display)) != PAM_SUCCESS) { - if (gdm_slave_should_complain ()) - gdm_error (_("Can't set PAM_TTY=%s"), current_display); + if ( ! ensure_pamh (d, current_login, current_display, &pamerr)) { goto open_pamerr; } /* Register the session */ - if ((pamerr = pam_open_session (pamh, PAM_SILENT)) != PAM_SUCCESS) { + if ((pamerr = pam_open_session (pamh, 0)) != PAM_SUCCESS) { if (gdm_slave_should_complain ()) gdm_error (_("Couldn't open session for %s"), current_login); @@ -493,7 +664,7 @@ gdm_verify_open_session (void) } /* Set credentials */ - if ((pamerr = pam_setcred (pamh, PAM_SILENT)) != PAM_SUCCESS) { + if ((pamerr = pam_setcred (pamh, 0)) != PAM_SUCCESS) { if (gdm_slave_should_complain ()) gdm_error (_("Couldn't set credentials for %s"), current_login); @@ -511,12 +682,18 @@ gdm_verify_open_session (void) } open_pamerr: - pam_end (pamh, pamerr); + if (pamerr != PAM_SUCCESS && + pamh != NULL) { + pam_end (pamh, pamerr); + pamh = NULL; + } /* Workaround to avoid gdm messages being logged as PAM_pwdb */ closelog (); openlog ("gdm", LOG_PID, LOG_DAEMON); + cur_gdm_disp = NULL; + return (pamerr == PAM_SUCCESS); } diff --git a/daemon/verify-shadow.c b/daemon/verify-shadow.c index 0bbe2547..74e468a0 100644 --- a/daemon/verify-shadow.c +++ b/daemon/verify-shadow.c @@ -23,7 +23,7 @@ #include <shadow.h> #ifdef HAVE_CRYPT - #include <crypt.h> +# include <crypt.h> #endif /* HAVE_CRYPT */ #include <vicious.h> @@ -54,7 +54,7 @@ extern gboolean GdmAllowRemoteRoot; */ gchar * -gdm_verify_user (const char *username, const gchar *display, gboolean local) +gdm_verify_user (GdmDisplay *d, const char *username, const gchar *display, gboolean local) { gchar *login, *passwd, *ppasswd, *auth_errmsg; struct passwd *pwent; @@ -211,7 +211,7 @@ gdm_verify_user (const char *username, const gchar *display, gboolean local) */ void -gdm_verify_setup_user (const gchar *login, const gchar *display) +gdm_verify_setup_user (GdmDisplay *d, const gchar *login, const gchar *display) { } @@ -222,7 +222,7 @@ gdm_verify_setup_user (const gchar *login, const gchar *display) * Unregister the user's session */ void -gdm_verify_cleanup (void) +gdm_verify_cleanup (GdmDisplay *d) { } @@ -242,7 +242,7 @@ gdm_verify_check (void) /* used in pam */ gboolean -gdm_verify_open_session (void) +gdm_verify_open_session (GdmDisplay *d) { return TRUE; } diff --git a/daemon/verify.h b/daemon/verify.h index 22b09c7e..236760e5 100644 --- a/daemon/verify.h +++ b/daemon/verify.h @@ -23,14 +23,17 @@ /* If username is NULL, we ask, if local is FALSE, don't start * the timed login timer */ -gchar *gdm_verify_user (const char *username, +gchar *gdm_verify_user (GdmDisplay *d, + const char *username, const gchar *display, gboolean local); -void gdm_verify_cleanup (void); +void gdm_verify_cleanup (GdmDisplay *d); void gdm_verify_check (void); /* used in pam */ -gboolean gdm_verify_open_session (void); -void gdm_verify_setup_user (const gchar *login, const gchar *display) ; +gboolean gdm_verify_open_session (GdmDisplay *d); +void gdm_verify_setup_user (GdmDisplay *d, + const gchar *login, + const gchar *display) ; #endif /* GDM_VERIFY_H */ |