diff options
Diffstat (limited to 'daemon/verify-pam.c')
-rw-r--r-- | daemon/verify-pam.c | 1673 |
1 files changed, 0 insertions, 1673 deletions
diff --git a/daemon/verify-pam.c b/daemon/verify-pam.c deleted file mode 100644 index 4331e751..00000000 --- a/daemon/verify-pam.c +++ /dev/null @@ -1,1673 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * GDM - The GNOME Display Manager - * Copyright (C) 1999, 2000 Martin K. Petersen <mkp@mkp.net> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "config.h" - -#include <unistd.h> -#include <stdlib.h> -#include <string.h> -#include <grp.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <syslog.h> -#include <security/pam_appl.h> -#include <pwd.h> -#ifdef __sun -#include <fcntl.h> -#endif - -#include <glib/gi18n.h> - -#include "gdm.h" -#include "misc.h" -#include "slave.h" -#include "verify.h" -#include "errorgui.h" - -#include "gdm-common.h" -#include "gdm-log.h" -#include "gdm-daemon-config.h" - -#include "gdm-socket-protocol.h" - -#ifdef HAVE_LOGINDEVPERM -#include <libdevinfo.h> -#endif /* HAVE_LOGINDEVPERM */ -#ifdef HAVE_ADT -#include <bsm/adt.h> -#include <bsm/adt_event.h> -#endif /* HAVE_ADT */ - -#define AU_FAILED 0 -#define AU_SUCCESS 1 -#ifdef HAVE_LIBAUDIT -#include <libaudit.h> -#else -#define log_to_audit_system(l,h,d,s) do { ; } while (0) -#endif - -/* Evil, but this way these things are passed to the child session */ -static pam_handle_t *pamh = NULL; - -static GdmDisplay *cur_gdm_disp = NULL; - -/* Hack. Used so user does not need to select username in face - * browser again if pw was wrong. Not used if username was typed - * manually */ -static char* prev_user; -static unsigned auth_retries; - -/* this is another hack */ -static gboolean did_we_ask_for_password = FALSE; - -static char *selected_user = NULL; - -static gboolean opened_session = FALSE; -static gboolean did_setcred = FALSE; - -extern char *gdm_ack_question_response; - -#ifdef HAVE_ADT -#define PW_FALSE 1 /* no password change */ -#define PW_TRUE 2 /* successful password change */ -#define PW_FAILED 3 /* failed password change */ - -static adt_session_data_t *adt_ah = NULL; /* audit session handle */ - -/* - * audit_success_login - audit successful login - * - * Entry process audit context established -- i.e., pam_setcred () - * called. - * pw_change == PW_TRUE, if successful password change audit - * required. - * pwent = authenticated user's passwd entry. - * - * Exit ADT_login (ADT_SUCCESS) audit record written - * pw_change == PW_TRUE, ADT_passwd (ADT_SUCCESS) audit - * record written. - * adt_ah = audit session established for audit_logout (); - * - */ -static void -audit_success_login (int pw_change, struct passwd *pwent) -{ - adt_event_data_t *event; /* event to generate */ - - if (adt_start_session (&adt_ah, NULL, ADT_USE_PROC_DATA) != 0) { - - syslog (LOG_AUTH | LOG_ALERT, - "adt_start_session (ADT_login): %m"); - return; - } - - if (adt_set_user (adt_ah, pwent->pw_uid, pwent->pw_gid, - pwent->pw_uid, pwent->pw_gid, NULL, ADT_USER) != 0) { - - syslog (LOG_AUTH | LOG_ALERT, - "adt_set_user (ADT_login, %s): %m", pwent->pw_name); - } - if ((event = adt_alloc_event (adt_ah, ADT_login)) == NULL) { - - syslog (LOG_AUTH | LOG_ALERT, "adt_alloc_event (ADT_login): %m"); - } else if (adt_put_event (event, ADT_SUCCESS, ADT_SUCCESS) != 0) { - - syslog (LOG_AUTH | LOG_ALERT, - "adt_put_event (ADT_login, ADT_SUCCESS): %m"); - } - - if (pw_change == PW_TRUE) { - - /* Also audit password change */ - adt_free_event (event); - if ((event = adt_alloc_event (adt_ah, ADT_passwd)) == NULL) { - - syslog (LOG_AUTH | LOG_ALERT, - "adt_alloc_event (ADT_passwd): %m"); - } else if (adt_put_event (event, ADT_SUCCESS, - ADT_SUCCESS) != 0) { - - syslog (LOG_AUTH | LOG_ALERT, - "adt_put_event (ADT_passwd, ADT_SUCCESS): %m"); - } - } - adt_free_event (event); -} - -/* - * audit_fail_login - audit failed login - * - * Entry did_setcred == FALSE, process audit context is not established. - * TRUE, process audit context established. - * d = display structure, d->attached non 0 if local, - * d->hostname used if remote. - * pw_change == PW_FALSE, if no password change requested. - * PW_TRUE, if successful password change audit - * required. - * PW_FAILED, if failed password change audit - * required. - * pwent = NULL, or password entry to use. - * pamerr = PAM error code; reason for failure. - * - * Exit ADT_login (ADT_FAILURE) audit record written - * pw_change == PW_TRUE, ADT_passwd (ADT_FAILURE) audit - * record written. - * - */ -static void -audit_fail_login (GdmDisplay *d, int pw_change, struct passwd *pwent, - int pamerr) -{ - adt_session_data_t *ah; /* audit session handle */ - adt_event_data_t *event; /* event to generate */ - adt_termid_t *tid; /* terminal ID for failures */ - - if (did_setcred == TRUE) { - if (adt_start_session (&ah, NULL, ADT_USE_PROC_DATA) != 0) { - - syslog (LOG_AUTH | LOG_ALERT, - "adt_start_session (ADT_login, ADT_FAILURE): %m"); - return; - } - } else { - if (adt_start_session (&ah, NULL, 0) != 0) { - - syslog (LOG_AUTH | LOG_ALERT, - "adt_start_session (ADT_login, ADT_FAILURE): %m"); - return; - } - if (d->attached) { - /* login from the local host */ - if (adt_load_ttyname ("/dev/console", &tid) != 0) { - - syslog (LOG_AUTH | LOG_ALERT, - "adt_loadhostname (localhost): %m"); - } - } else { - /* login from a remote host */ - if (adt_load_hostname (d->hostname, &tid) != 0) { - - syslog (LOG_AUTH | LOG_ALERT, - "adt_loadhostname (%s): %m", d->hostname); - } - } - if (adt_set_user (ah, - pwent ? pwent->pw_uid : ADT_NO_ATTRIB, - pwent ? pwent->pw_gid : ADT_NO_ATTRIB, - pwent ? pwent->pw_uid : ADT_NO_ATTRIB, - pwent ? pwent->pw_gid : ADT_NO_ATTRIB, - tid, ADT_NEW) != 0) { - - syslog (LOG_AUTH | LOG_ALERT, - "adt_set_user (%s): %m", - pwent ? pwent->pw_name : "ADT_NO_ATTRIB"); - } - } - if ((event = adt_alloc_event (ah, ADT_login)) == NULL) { - - syslog (LOG_AUTH | LOG_ALERT, - "adt_alloc_event (ADT_login, ADT_FAILURE): %m"); - goto done; - } else if (adt_put_event (event, ADT_FAILURE, - ADT_FAIL_PAM + pamerr) != 0) { - - syslog (LOG_AUTH | LOG_ALERT, - "adt_put_event (ADT_login (ADT_FAIL, %s): %m", - pam_strerror (pamh, pamerr)); - } - if (pw_change != PW_FALSE) { - - /* Also audit password change */ - adt_free_event (event); - if ((event = adt_alloc_event (ah, ADT_passwd)) == NULL) { - - syslog (LOG_AUTH | LOG_ALERT, - "adt_alloc_event (ADT_passwd): %m"); - goto done; - } - if (pw_change == PW_TRUE) { - if (adt_put_event (event, ADT_SUCCESS, - ADT_SUCCESS) != 0) { - - syslog (LOG_AUTH | LOG_ALERT, - "adt_put_event (ADT_passwd, ADT_SUCCESS): " - "%m"); - } - } else if (pw_change == PW_FAILED) { - if (adt_put_event (event, ADT_FAILURE, - ADT_FAIL_PAM + pamerr) != 0) { - - syslog (LOG_AUTH | LOG_ALERT, - "adt_put_event (ADT_passwd, ADT_FAILURE): " - "%m"); - } - } - } - adt_free_event (event); - - done: - /* reset process audit state. this process is being reused.*/ - - if ((adt_set_user (ah, ADT_NO_AUDIT, ADT_NO_AUDIT, ADT_NO_AUDIT, - ADT_NO_AUDIT, NULL, ADT_NEW) != 0) || - (adt_set_proc (ah) != 0)) { - - syslog (LOG_AUTH | LOG_ALERT, - "adt_put_event (ADT_login (ADT_FAILURE reset, %m)"); - } - (void) adt_end_session (ah); -} - -/* - * audit_logout - audit user logout - * - * Entry adt_ah = audit session handle established by - * audit_success_login (). - * - * Exit ADT_logout (ADT_SUCCESS) audit record written - * process audit state reset. (this process is reused for - * the next login.) - * audit session adt_ah ended. - */ -static void -audit_logout (void) -{ - adt_event_data_t *event; /* event to generate */ - - if ((event = adt_alloc_event (adt_ah, ADT_logout)) == NULL) { - - syslog (LOG_AUTH | LOG_ALERT, - "adt_alloc_event (ADT_logout): %m"); - } else if (adt_put_event (event, ADT_SUCCESS, ADT_SUCCESS) != 0) { - - syslog (LOG_AUTH | LOG_ALERT, - "adt_put_event (ADT_logout, ADT_SUCCESS): %m"); - } - adt_free_event (event); - - /* reset process audit state. this process is being reused.*/ - - if ((adt_set_user (adt_ah, ADT_NO_AUDIT, ADT_NO_AUDIT, ADT_NO_AUDIT, - ADT_NO_AUDIT, NULL, ADT_NEW) != 0) || - (adt_set_proc (adt_ah) != 0)) { - - syslog (LOG_AUTH | LOG_ALERT, - "adt_set_proc (ADT_logout reset): %m"); - } - (void) adt_end_session (adt_ah); -} -#endif /* HAVE_ADT */ - -#ifdef __sun -void -solaris_xserver_cred (char *login, GdmDisplay *d, struct passwd *pwent) -{ - struct stat statbuf; - struct group *gr; - gid_t groups[NGROUPS_UMAX]; - char *home, *disp, *tmp, pipe[MAXPATHLEN], info[MAXPATHLEN]; - int displayNumber = 0; - int retval, fd, i, nb; - int ngroups; - - if (!d->attached) - return; - - if (g_access (pwent->pw_dir, F_OK) != 0) { - gdm_debug ("solaris_xserver_cred: no HOME dir access\n"); - return; - } - - /* - * Handshake with server. Make sure it created a pipe. - * Open and write. - */ - if ((tmp = strstr (d->name, ":")) != NULL) { - tmp++; - displayNumber = atoi (tmp); - } - - sprintf (pipe, "%s/%d", SDTLOGIN_DIR, displayNumber); - - if (g_stat (SDTLOGIN_DIR, &statbuf) == 0) { - if (! statbuf.st_mode & S_IFDIR) { - gdm_debug ("solaris_xserver_cred: %s is not a directory\n", - SDTLOGIN_DIR); - return; - } - } - else { - gdm_debug ("solaris_xserver_cred: %s does not exist\n", SDTLOGIN_DIR); - return; - } - - fd = open (pipe, O_RDWR); - g_unlink (pipe); - - if (fd < 0) { - gdm_debug ("solaris_xserver_cred: could not open %s\n", pipe); - return; - } - if (fstat (fd, &statbuf) == 0 ) { - if ( ! statbuf.st_mode & S_IFIFO) { - close (fd); - gdm_debug ("solaris_xserver_cred: %s is not a pipe\n", pipe); - return; - } - } else { - close (fd); - gdm_debug ("solaris_xserver_cred: %s does not exist\n", pipe); - return; - } - - sprintf (info, "GID=\"%d\"; ", pwent->pw_gid); - nb = write (fd, info, strlen (info)); - gdm_debug ("solaris_xserver_cred: %s\n", info); - - if (initgroups (login, pwent->pw_gid) == -1) { - ngroups = 0; - } else { - ngroups = getgroups (NGROUPS_UMAX, groups); - } - - for (i=0; i < ngroups; i++) { - sprintf (info, "G_LIST_ID=\"%u\" ", groups[i]); - nb = write (fd, info, strlen (info)); - gdm_debug ("solaris_xserver_cred: %s\n", info); - } - - if (ngroups > 0) { - sprintf (info, ";"); - write (fd, info, strlen (info)); - } - - sprintf (info, " HOME=\"%s\" ", pwent->pw_dir); - nb = write (fd, info, strlen (info)); - gdm_debug ("solaris_xserver_cred: %s\n", info); - - sprintf (info, " UID=\"%d\" EOF=\"\";", pwent->pw_uid); - nb = write (fd, info, strlen (info)); - gdm_debug ("solaris_xserver_cred: %s\n", info); - - /* - * Handshake with server. Make sure it read the pipe. - * - * Close file descriptor. - */ - close (fd); - - return; -} -#endif - -void -gdm_verify_select_user (const char *user) -{ - g_free (selected_user); - if (ve_string_empty (user)) - selected_user = NULL; - else - selected_user = g_strdup (user); -} - -static const char * -perhaps_translate_message (const char *msg) -{ - char *s; - const char *ret; - static GHashTable *hash = NULL; - static char *locale = NULL; - - /* if locale changes out from under us then rebuild hash table - */ - if ((locale != NULL) && - (strcmp (locale, setlocale (LC_ALL, NULL)) != 0)) { - g_assert (hash != NULL); - g_hash_table_destroy (hash); - hash = NULL; - } - - if (hash == NULL) { - g_free (locale); - locale = g_strdup (setlocale (LC_ALL, NULL)); - - /* Here we come with some fairly standard messages so that - we have as much as possible translated. Should really be - translated in pam I suppose. This way we can "change" - some of these messages to be more sane. */ - hash = g_hash_table_new (g_str_hash, g_str_equal); - /* login: is whacked always translate to Username: */ - g_hash_table_insert (hash, "login:", _("Username:")); - g_hash_table_insert (hash, "Username:", _("Username:")); - g_hash_table_insert (hash, "username:", _("Username:")); - g_hash_table_insert (hash, "Password:", _("Password:")); - g_hash_table_insert (hash, "password:", _("Password:")); - g_hash_table_insert (hash, "You are required to change your password immediately (password aged)", _("You are required to change your password immediately (password aged)")); - g_hash_table_insert (hash, "You are required to change your password immediately (root enforced)", _("You are required to change your password immediately (root enforced)")); - g_hash_table_insert (hash, "Your account has expired; please contact your system administrator", _("Your account has expired; please contact your system administrator")); - g_hash_table_insert (hash, "No password supplied", _("No password supplied")); - g_hash_table_insert (hash, "Password unchanged", _("Password unchanged")); - g_hash_table_insert (hash, "Can not get username", _("Can not get username")); - g_hash_table_insert (hash, "Retype new UNIX password:", _("Retype new UNIX password:")); - g_hash_table_insert (hash, "Enter new UNIX password:", _("Enter new UNIX password:")); - g_hash_table_insert (hash, "(current) UNIX password:", _("(current) UNIX password:")); - g_hash_table_insert (hash, "Error while changing NIS password.", _("Error while changing NIS password.")); - g_hash_table_insert (hash, "You must choose a longer password", _("You must choose a longer password")); - g_hash_table_insert (hash, "Password has been already used. Choose another.", _("Password has been already used. Choose another.")); - g_hash_table_insert (hash, "You must wait longer to change your password", _("You must wait longer to change your password")); - g_hash_table_insert (hash, "Sorry, passwords do not match", _("Sorry, passwords do not match")); - /* FIXME: what about messages which have some variables in them, perhaps try to do those as well */ - } - s = g_strstrip (g_strdup (msg)); - ret = g_hash_table_lookup (hash, s); - g_free (s); - if (ret != NULL) - return ret; - else - return msg; -} - -/* Internal PAM conversation function. Interfaces between the PAM - * authentication system and the actual greeter program */ - -static int -gdm_verify_pam_conv (int num_msg, struct pam_message **msg, - struct pam_response **resp, - void *appdata_ptr) -{ - int replies = 0; - int i; - char *s = NULL; - struct pam_response *reply = NULL; - const void *p; - const char *login; - - if (pamh == NULL) - return PAM_CONV_ERR; - - /* Should never happen unless PAM is on crack and keeps asking questions - after we told it to go away. So tell it to go away again and - maybe it will listen */ - /* well, it actually happens if there are multiple pam modules - * with conversations */ - if ( ! gdm_slave_action_pending () || selected_user) - return PAM_CONV_ERR; - - reply = malloc (sizeof (struct pam_response) * num_msg); - - if (reply == NULL) - return PAM_CONV_ERR; - - memset (reply, 0, sizeof (struct pam_response) * num_msg); - - /* Here we set the login if it wasn't already set, - * this is kind of anal, but this way we guarantee that - * the greeter always is up to date on the login */ - if (pam_get_item (pamh, PAM_USER, (void **)&p) == PAM_SUCCESS) { - login = (const char *)p; - gdm_slave_greeter_ctl_no_ret (GDM_SETLOGIN, login); - } - - /* Workaround to avoid gdm messages being logged as PAM_pwdb */ - gdm_log_shutdown (); - gdm_log_init (); - - for (replies = 0; replies < num_msg; replies++) { - const char *m = (*msg)[replies].msg; - m = perhaps_translate_message (m); - - switch ((*msg)[replies].msg_style) { - - /* PAM requested textual input with echo on */ - case PAM_PROMPT_ECHO_ON: - if (strcmp (m, _("Username:")) == 0) { - if ( ve_string_empty (selected_user)) { - /* this is an evil hack, but really there is no way we'll - know this is a username prompt. However we SHOULD NOT - rely on this working. The pam modules can set their - prompt to whatever they wish to */ - gdm_slave_greeter_ctl_no_ret - (GDM_MSG, _("Please enter your username")); - s = gdm_slave_greeter_ctl (GDM_PROMPT, m); - /* this will clear the message */ - gdm_slave_greeter_ctl_no_ret (GDM_MSG, ""); - } - } else { - s = gdm_slave_greeter_ctl (GDM_PROMPT, m); - } - - if (gdm_slave_greeter_check_interruption ()) { - g_free (s); - for (i = 0; i < replies; i++) - if (reply[replies].resp != NULL) - free (reply[replies].resp); - free (reply); - return PAM_CONV_ERR; - } - - reply[replies].resp_retcode = PAM_SUCCESS; - reply[replies].resp = strdup (ve_sure_string (s)); - g_free (s); - break; - - case PAM_PROMPT_ECHO_OFF: - if (strcmp (m, _("Password:")) == 0) - did_we_ask_for_password = TRUE; - /* PAM requested textual input with echo off */ - s = gdm_slave_greeter_ctl (GDM_NOECHO, m); - if (gdm_slave_greeter_check_interruption ()) { - g_free (s); - for (i = 0; i < replies; i++) - if (reply[replies].resp != NULL) - free (reply[replies].resp); - free (reply); - return PAM_CONV_ERR; - } - 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_slave_greeter_ctl_no_ret (GDM_ERRDLG, m); - 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_slave_greeter_ctl_no_ret (GDM_MSG, m); - reply[replies].resp_retcode = PAM_SUCCESS; - reply[replies].resp = NULL; - break; - - default: - /* PAM has been smoking serious crack */ - for (i = 0; i < replies; i++) - if (reply[replies].resp != NULL) - free (reply[replies].resp); - free (reply); - return PAM_CONV_ERR; - } - - } - - *resp = reply; - return PAM_SUCCESS; -} - -static struct pam_conv pamc = { - &gdm_verify_pam_conv, - NULL -}; - -/* Extra message to give on queries */ -static char *extra_standalone_message = NULL; - -static int -gdm_verify_standalone_pam_conv (int num_msg, struct pam_message **msg, - struct pam_response **resp, - void *appdata_ptr) -{ - int replies = 0; - int i; - char *text; - char *question_msg; - struct pam_response *reply = NULL; - - if (pamh == NULL) - return PAM_CONV_ERR; - - reply = malloc (sizeof (struct pam_response) * num_msg); - - if (reply == NULL) - return PAM_CONV_ERR; - - memset (reply, 0, sizeof (struct pam_response) * num_msg); - - for (replies = 0; replies < num_msg; replies++) { - const char *m = (*msg)[replies].msg; - m = perhaps_translate_message (m); - switch ((*msg)[replies].msg_style) { - - case PAM_PROMPT_ECHO_ON: - if (extra_standalone_message != NULL) - text = g_strdup_printf - ("%s%s", extra_standalone_message, - m); - else - text = g_strdup (m); - - /* PAM requested textual input with echo on */ - question_msg = g_strdup_printf ("question_msg=%s$$echo=%d", text, TRUE); - - gdm_slave_send_string (GDM_SOP_SHOW_QUESTION_DIALOG, question_msg); - - g_free (question_msg); - g_free (text); - - reply[replies].resp_retcode = PAM_SUCCESS; - if (gdm_ack_question_response) { - reply[replies].resp = strdup (ve_sure_string (gdm_ack_question_response)); - g_free (gdm_ack_question_response); - gdm_ack_question_response = NULL; - } else - reply[replies].resp = NULL; - - break; - - case PAM_PROMPT_ECHO_OFF: - if (extra_standalone_message != NULL) - text = g_strdup_printf - ("%s%s", extra_standalone_message, - m); - else - text = g_strdup (m); - - /* PAM requested textual input with echo off */ - question_msg = g_strdup_printf ("question_msg=%s$$echo=%d", text, TRUE); - - gdm_slave_send_string (GDM_SOP_SHOW_QUESTION_DIALOG, question_msg); - - g_free (question_msg); - g_free (text); - - reply[replies].resp_retcode = PAM_SUCCESS; - if (gdm_ack_question_response) { - reply[replies].resp = strdup (ve_sure_string (gdm_ack_question_response)); - g_free (gdm_ack_question_response); - gdm_ack_question_response = NULL; - } else - reply[replies].resp = NULL; - - break; - - case PAM_ERROR_MSG: - /* PAM sent a message that should displayed to the user */ - gdm_errorgui_error_box (cur_gdm_disp, - GTK_MESSAGE_ERROR, - m); - 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_errorgui_error_box (cur_gdm_disp, - GTK_MESSAGE_INFO, - m); - reply[replies].resp_retcode = PAM_SUCCESS; - reply[replies].resp = NULL; - break; - - default: - /* PAM has been smoking serious crack */ - for (i = 0; i < replies; i++) - if (reply[replies].resp != NULL) - free (reply[replies].resp); - free (reply); - return PAM_CONV_ERR; - } - - } - - *resp = reply; - return PAM_SUCCESS; -} - -static struct pam_conv standalone_pamc = { - &gdm_verify_standalone_pam_conv, - NULL -}; - -/* Creates a pam handle for the auto login */ -static gboolean -create_pamh (GdmDisplay *d, - const char *service, - const char *login, - struct pam_conv *conv, - const char *display, - int *pamerr) -{ - if (display == NULL) { - gdm_error (_("Cannot setup pam handle with null display")); - return FALSE; - } - - if (pamh != NULL) { - gdm_error ("create_pamh: Stale pamh around, cleaning up"); - pam_end (pamh, PAM_SUCCESS); - } - /* init things */ - pamh = NULL; - opened_session = FALSE; - did_setcred = FALSE; - - /* Initialize a PAM session for the user */ - if ((*pamerr = pam_start (service, login, conv, &pamh)) != PAM_SUCCESS) { - pamh = NULL; /* be anal */ - if (gdm_slave_action_pending ()) - gdm_error (_("Unable to establish service %s: %s\n"), - service, pam_strerror (NULL, *pamerr)); - return FALSE; - } - - /* Inform PAM of the user's tty */ -#ifdef __sun - if (d->attached) - (void) pam_set_item (pamh, PAM_TTY, "/dev/console"); - else -#endif /* sun */ - if ((*pamerr = pam_set_item (pamh, PAM_TTY, display)) != PAM_SUCCESS) { - if (gdm_slave_action_pending ()) - gdm_error (_("Can't set PAM_TTY=%s"), display); - return FALSE; - } - - if ( ! d->attached) { - /* Only set RHOST if host is remote */ - /* From the host of the display */ - if ((*pamerr = pam_set_item (pamh, PAM_RHOST, - d->hostname)) != PAM_SUCCESS) { - if (gdm_slave_action_pending ()) - gdm_error (_("Can't set PAM_RHOST=%s"), - d->hostname); - return FALSE; - } - } - - return TRUE; -} - -/** - * log_to_audit_system: - * @login: Name of user - * @hostname: Name of host machine - * @tty: Name of display - * @success: 1 for success, 0 for failure - * - * Logs the success or failure of the login attempt with the linux kernel - * audit system. The intent is to capture failed events where the user - * fails authentication or otherwise is not permitted to login. There are - * many other places where pam could potentially fail and cause login to - * fail, but these are system failures rather than the signs of an account - * being hacked. - * - * Returns nothing. - */ - -#ifdef HAVE_LIBAUDIT -static void -log_to_audit_system(const char *login, - const char *hostname, - const char *tty, - gboolean success) -{ - struct passwd *pw; - char buf[64]; - int audit_fd; - - audit_fd = audit_open(); - if (login) - pw = getpwnam(login); - else { - login = "unknown"; - pw = NULL; - } - if (pw) { - snprintf(buf, sizeof(buf), "uid=%d", pw->pw_uid); - audit_log_user_message(audit_fd, AUDIT_USER_LOGIN, - buf, hostname, NULL, tty, (int)success); - } else { - snprintf(buf, sizeof(buf), "acct=%s", login); - audit_log_user_message(audit_fd, AUDIT_USER_LOGIN, - buf, hostname, NULL, tty, (int)success); - } - close(audit_fd); -} -#endif - -/** - * gdm_verify_user: - * @username: Name of user or NULL if we should ask - * @display: Name of display to register with the authentication system - * @local: boolean if local - * @allow_retry: boolean if we should allow retry logic to be enabled. - * We only want this to work for normal login, not for - * asking for the root password to cal the configurator. - * - * Provides a communication layer between the operating system's - * authentication functions and the gdmgreeter. - * - * Returns the user's login on success and NULL on failure. - */ - -gchar * -gdm_verify_user (GdmDisplay *d, - const char *username, - const gchar *display, - gboolean local, - gboolean allow_retry) -{ - gint pamerr = 0; - struct passwd *pwent = NULL; - const void *p; - char *login, *passreq, *consoleonly; - char *pam_stack = NULL; - int null_tok = 0; - gboolean credentials_set = FALSE; - gboolean error_msg_given = FALSE; - gboolean started_timer = FALSE; - -#ifdef HAVE_ADT - int pw_change = PW_FALSE; /* if got to trying to change password */ -#endif /* HAVE_ADT */ - - verify_user_again: - - pamerr = 0; - login = NULL; - error_msg_given = FALSE; - credentials_set = FALSE; - started_timer = FALSE; - null_tok = 0; - - /* Don't start a timed login if we've already entered a username */ - if (username != NULL) { - login = g_strdup (username); - gdm_slave_greeter_ctl_no_ret (GDM_SETLOGIN, login); - } else { - /* start the timer for timed logins */ - if ( ! ve_string_empty (gdm_daemon_config_get_value_string (GDM_KEY_TIMED_LOGIN)) && - d->timed_login_ok && - (local || gdm_daemon_config_get_value_bool (GDM_KEY_ALLOW_REMOTE_AUTOLOGIN))) { - gdm_slave_greeter_ctl_no_ret (GDM_STARTTIMER, ""); - started_timer = TRUE; - } - } - - cur_gdm_disp = d; - - authenticate_again: - - if (prev_user && !login) { - login = g_strdup(prev_user); - } else if (login && !prev_user) { - prev_user = g_strdup(login); - auth_retries = 0; - } else if (login && prev_user && strcmp (login, prev_user)) { - g_free (prev_user); - prev_user = g_strdup (login); - auth_retries = 0; - } - - /* - * Initialize a PAM session for the user... - * Get value per-display so different displays can use different - * PAM Stacks, in case one display should use a different - * authentication mechanism than another display. - */ - pam_stack = gdm_daemon_config_get_value_string_per_display (GDM_KEY_PAM_STACK, (char *)display); - - if ( ! create_pamh (d, pam_stack, login, &pamc, display, &pamerr)) { - if (started_timer) - gdm_slave_greeter_ctl_no_ret (GDM_STOPTIMER, ""); - g_free (pam_stack); - goto pamerr; - } - - g_free (pam_stack); - - /* - * have to unset login otherwise there is no chance to ever enter - * a different user - */ - g_free (login); - login = NULL; - - pam_set_item (pamh, PAM_USER_PROMPT, _("Username:")); - -#if 0 - /* FIXME: this makes things wait at the wrong places! such as - when running the configurator. We wish to ourselves cancel logins - without a delay, so ... evil */ -#ifdef PAM_FAIL_DELAY - pam_fail_delay (pamh, gdm_daemon_config_get_value_int (GDM_KEY_RETRY_DELAY) * 1000000); -#endif /* PAM_FAIL_DELAY */ -#endif - - passreq = gdm_read_default ("PASSREQ="); - if ((passreq != NULL) && - g_ascii_strcasecmp (passreq, "YES") == 0) - gdm_daemon_config_set_value_bool (GDM_KEY_PASSWORD_REQUIRED, TRUE); - - if (gdm_daemon_config_get_value_bool (GDM_KEY_PASSWORD_REQUIRED)) - null_tok |= PAM_DISALLOW_NULL_AUTHTOK; - - gdm_verify_select_user (NULL); - - /* Start authentication session */ - did_we_ask_for_password = FALSE; - if ((pamerr = pam_authenticate (pamh, null_tok)) != PAM_SUCCESS) { - /* Log the failed login attempt */ - log_to_audit_system(login, d->hostname, display, AU_FAILED); - if ( ! ve_string_empty (selected_user)) { - pam_handle_t *tmp_pamh; - - /* Face browser was used to select a user, - just completely rewhack everything since it - seems various PAM implementations are - having goats with just setting PAM_USER - and trying to pam_authenticate again */ - - g_free (login); - login = selected_user; - selected_user = NULL; - - gdm_sigterm_block_push (); - gdm_sigchld_block_push (); - tmp_pamh = pamh; - pamh = NULL; - gdm_sigchld_block_pop (); - gdm_sigterm_block_pop (); - - /* FIXME: what about errors */ - /* really this has been a sucess, not a failure */ - pam_end (tmp_pamh, pamerr); - - g_free (prev_user); - prev_user = NULL; - auth_retries = 0; - - gdm_slave_greeter_ctl_no_ret (GDM_SETLOGIN, login); - - goto authenticate_again; - } - - if (started_timer) - gdm_slave_greeter_ctl_no_ret (GDM_STOPTIMER, ""); - - if (gdm_slave_action_pending ()) { - /* FIXME: see note above about PAM_FAIL_DELAY */ - /* #ifndef PAM_FAIL_DELAY */ - gdm_sleep_no_signal (gdm_daemon_config_get_value_int (GDM_KEY_RETRY_DELAY)); - /* wait up to 100ms randomly */ - usleep (g_random_int_range (0, 100000)); - /* #endif */ /* PAM_FAIL_DELAY */ - gdm_error (_("Couldn't authenticate user")); - - if (prev_user) { - - unsigned max_auth_retries = 3; - char *val = gdm_read_default ("LOGIN_RETRIES="); - - if (val) { - max_auth_retries = atoi (val); - g_free (val); - } - - if (allow_retry == FALSE || pamerr == PAM_MAXTRIES || - ++auth_retries >= max_auth_retries) { - - g_free (prev_user); - prev_user = NULL; - auth_retries = 0; - } - } - } else { - /* cancel, configurator etc pressed */ - g_free (prev_user); - prev_user = NULL; - auth_retries = 0; - } - - goto pamerr; - } - - /* stop the timer for timed logins */ - if (started_timer) - gdm_slave_greeter_ctl_no_ret (GDM_STOPTIMER, ""); - - g_free (login); - login = NULL; - g_free (prev_user); - prev_user = NULL; - - if ((pamerr = pam_get_item (pamh, PAM_USER, (void **)&p)) != PAM_SUCCESS) { - login = NULL; - /* is not really an auth problem, but it will - pretty much look as such, it shouldn't really - happen */ - if (gdm_slave_action_pending ()) - gdm_error (_("Couldn't authenticate user")); - goto pamerr; - } - - login = g_strdup ((const char *)p); - /* kind of anal, the greeter likely already knows, but it could have - been changed */ - gdm_slave_greeter_ctl_no_ret (GDM_SETLOGIN, login); - - if ( ! gdm_slave_check_user_wants_to_log_in (login)) { - /* cleanup stuff */ - gdm_slave_greeter_ctl_no_ret (GDM_SETLOGIN, ""); - g_free (login); - login = NULL; - gdm_slave_greeter_ctl_no_ret (GDM_RESETOK, ""); - - gdm_verify_cleanup (d); - - goto verify_user_again; - } - - /* Check if user is root and is allowed to log in */ - consoleonly = gdm_read_default ("CONSOLE="); - if ((consoleonly != NULL) && - g_ascii_strcasecmp (consoleonly, "/dev/console") == 0) - gdm_daemon_config_set_value_bool (GDM_KEY_ALLOW_REMOTE_ROOT, FALSE); - - pwent = getpwnam (login); - if ( ( ! gdm_daemon_config_get_value_bool (GDM_KEY_ALLOW_ROOT) || - ( ! gdm_daemon_config_get_value_bool (GDM_KEY_ALLOW_REMOTE_ROOT) && ! local) ) && - pwent != NULL && - pwent->pw_uid == 0) { - /* Log the failed login attempt */ - log_to_audit_system(login, d->hostname, display, AU_FAILED); - gdm_error (_("Root login disallowed on display '%s'"), - display); - gdm_slave_greeter_ctl_no_ret (GDM_ERRBOX, - _("\nThe system administrator " - "is not allowed to login " - "from this screen")); - /*gdm_slave_greeter_ctl_no_ret (GDM_ERRDLG, - _("Root login disallowed"));*/ - error_msg_given = TRUE; - -#ifdef HAVE_ADT - /* - * map console login not allowed as a pam_acct_mgmt () failure - * indeed that's where these checks should be made. - */ - pamerr = PAM_PERM_DENIED; -#endif /* HAVE_ADT */ - goto pamerr; - } - - if (gdm_daemon_config_get_value_bool (GDM_KEY_DISPLAY_LAST_LOGIN)) { - char *info = gdm_get_last_info (login); - gdm_slave_greeter_ctl_no_ret (GDM_MSG, info); - g_free (info); - } - - /* Check if the user's account is healthy. */ - pamerr = pam_acct_mgmt (pamh, null_tok); - switch (pamerr) { - case PAM_SUCCESS : - break; - case PAM_NEW_AUTHTOK_REQD : - if ((pamerr = pam_chauthtok (pamh, PAM_CHANGE_EXPIRED_AUTHTOK)) != PAM_SUCCESS) { - /* Log the failed login attempt */ - log_to_audit_system(login, d->hostname, display, AU_FAILED); - gdm_error (_("Authentication token change failed for user %s"), login); - gdm_slave_greeter_ctl_no_ret (GDM_ERRBOX, - _("\nThe change of the authentication token failed. " - "Please try again later or contact the system administrator.")); - error_msg_given = TRUE; -#ifdef HAVE_ADT - /* Password change failed */ - pw_change = PW_FAILED; -#endif /* HAVE_ADT */ - goto pamerr; - } -#ifdef HAVE_ADT - /* Password changed */ - pw_change = PW_TRUE; -#endif /* HAVE_ADT */ - break; - case PAM_ACCT_EXPIRED : - /* Log the failed login attempt */ - log_to_audit_system(login, d->hostname, display, AU_FAILED); - gdm_error (_("User %s no longer permitted to access the system"), login); - gdm_slave_greeter_ctl_no_ret (GDM_ERRBOX, - _("\nThe system administrator has disabled your account.")); - error_msg_given = TRUE; - goto pamerr; - case PAM_PERM_DENIED : - /* Log the failed login attempt */ - log_to_audit_system(login, d->hostname, display, AU_FAILED); - gdm_error (_("User %s not permitted to gain access at this time"), login); - gdm_slave_greeter_ctl_no_ret (GDM_ERRBOX, - _("\nThe system administrator has disabled access to the system temporarily.")); - error_msg_given = TRUE; - goto pamerr; - default : - /* Log the failed login attempt */ - log_to_audit_system(login, d->hostname, display, AU_FAILED); - if (gdm_slave_action_pending ()) - gdm_error (_("Couldn't set acct. mgmt for %s"), login); - goto pamerr; - } - - pwent = getpwnam (login); - if (/* paranoia */ pwent == NULL || - ! gdm_setup_gids (login, pwent->pw_gid)) { - gdm_error (_("Cannot set user group for %s"), login); - gdm_slave_greeter_ctl_no_ret (GDM_ERRBOX, - _("\nCannot set your user group; " - "you will not be able to log in. " - "Please contact your system administrator.")); -#ifdef HAVE_ADT - /* - * map group setup error as a pam_setcred () failure - * indeed that's where this should be done. - */ - pamerr = PAM_SYSTEM_ERR; -#endif /* HAVE_ADT */ - goto pamerr; - } - - did_setcred = TRUE; - -#ifdef __sun - solaris_xserver_cred (login, d, pwent); -#endif - - /* Set credentials */ - pamerr = pam_setcred (pamh, PAM_ESTABLISH_CRED); - if (pamerr != PAM_SUCCESS) { - did_setcred = FALSE; - if (gdm_slave_action_pending ()) - gdm_error (_("Couldn't set credentials for %s"), login); - goto pamerr; - } - - credentials_set = TRUE; - opened_session = TRUE; - - /* Register the session */ - pamerr = pam_open_session (pamh, 0); - if (pamerr != PAM_SUCCESS) { - opened_session = FALSE; - /* we handle this above */ - did_setcred = FALSE; - if (gdm_slave_action_pending ()) - gdm_error (_("Couldn't open session for %s"), login); - goto pamerr; - } - /* Login succeeded */ - log_to_audit_system(login, d->hostname, display, AU_SUCCESS); - - /* Workaround to avoid gdm messages being logged as PAM_pwdb */ - gdm_log_shutdown (); - gdm_log_init (); - - cur_gdm_disp = NULL; - -#ifdef HAVE_LOGINDEVPERM - if (d->attached) - (void) di_devperm_login ("/dev/console", pwent->pw_uid, - pwent->pw_gid, NULL); -#endif /* HAVE_LOGINDEVPERM */ -#ifdef HAVE_ADT - audit_success_login (pw_change, pwent); -#endif /* HAVE_ADT */ - - return login; - - pamerr: -#ifdef HAVE_ADT - audit_fail_login (d, pw_change, pwent, pamerr); -#endif /* HAVE_ADT */ - - /* The verbose authentication is turned on, output the error - * message from the PAM subsystem */ - if ( ! error_msg_given && - gdm_slave_action_pending ()) { - /* - * I'm not sure yet if I should display this message for any - * other issues - heeten - * Adding AUTHINFO_UNAVAIL to the list - its what an unknown - * user is. - */ - if (pamerr == PAM_AUTH_ERR || - pamerr == PAM_USER_UNKNOWN || - pamerr == PAM_AUTHINFO_UNAVAIL) { - gboolean is_capslock = FALSE; - const char *basemsg; - char *msg; - char *ret; - - ret = gdm_slave_greeter_ctl (GDM_QUERY_CAPSLOCK, ""); - if ( ! ve_string_empty (ret)) - is_capslock = TRUE; - g_free (ret); - - /* Only give this message if we actually asked for - password, otherwise it would be silly to say that - the password may have been wrong */ - if (did_we_ask_for_password) { - basemsg = _("\nIncorrect username or password. " - "Letters must be typed in the correct " - "case."); - } else { - basemsg = _("\nAuthentication failed. " - "Letters must be typed in the correct " - "case."); - } - if (is_capslock) { - msg = g_strconcat (basemsg, " ", - _("Caps Lock is on."), - NULL); - } else { - msg = g_strdup (basemsg); - } - gdm_slave_greeter_ctl_no_ret (GDM_ERRBOX, msg); - g_free (msg); - } else { - gdm_slave_greeter_ctl_no_ret (GDM_ERRDLG, _("Authentication failed")); - } - } - - did_setcred = FALSE; - opened_session = FALSE; - - if (pamh != NULL) { - pam_handle_t *tmp_pamh; - gdm_sigterm_block_push (); - gdm_sigchld_block_push (); - tmp_pamh = pamh; - pamh = NULL; - gdm_sigchld_block_pop (); - gdm_sigterm_block_pop (); - - /* Throw away the credentials */ - if (credentials_set) - pam_setcred (tmp_pamh, PAM_DELETE_CRED); - pam_end (tmp_pamh, pamerr); - } - pamh = NULL; - - /* Workaround to avoid gdm messages being logged as PAM_pwdb */ - gdm_log_shutdown (); - gdm_log_init (); - - g_free (login); - - cur_gdm_disp = NULL; - - return NULL; -} - -/** - * gdm_verify_setup_user: - * @login: The name of the user - * @display: The name of the display - * - * This is used for auto loging in. This just sets up the login - * session for this user - */ - -gboolean -gdm_verify_setup_user (GdmDisplay *d, const gchar *login, const gchar *display, - char **new_login) -{ - gint pamerr = 0; - struct passwd *pwent = NULL; - const void *p; - char *passreq; - char *pam_stack = NULL; - char *pam_service_name = NULL; - int null_tok = 0; - gboolean credentials_set; - const char *after_login; - - credentials_set = FALSE; - -#ifdef HAVE_ADT - int pw_change = PW_FALSE; /* if got to trying to change password */ -#endif /* HAVE_ADT */ - - *new_login = NULL; - - if (login == NULL) - return FALSE; - - cur_gdm_disp = d; - - g_free (extra_standalone_message); - extra_standalone_message = g_strdup_printf ("%s (%s)", - _("Automatic login"), - login); - - /* - * Initialize a PAM session for the user... - * Get value per-display so different displays can use different - * PAM Stacks, in case one display should use a different - * authentication mechanism than another display. - */ - pam_stack = gdm_daemon_config_get_value_string_per_display (GDM_KEY_PAM_STACK, (char *)display); - pam_service_name = g_strdup_printf ("%s-autologin", pam_stack); - - if ( ! create_pamh (d, pam_service_name, login, &standalone_pamc, - display, &pamerr)) { - g_free (pam_stack); - g_free (pam_service_name); - goto setup_pamerr; - } - g_free (pam_stack); - g_free (pam_service_name); - - passreq = gdm_read_default ("PASSREQ="); - if ((passreq != NULL) && - g_ascii_strcasecmp (passreq, "YES") == 0) - gdm_daemon_config_set_value_bool (GDM_KEY_PASSWORD_REQUIRED, TRUE); - - if (gdm_daemon_config_get_value_bool (GDM_KEY_PASSWORD_REQUIRED)) - null_tok |= PAM_DISALLOW_NULL_AUTHTOK; - - /* Start authentication session */ - did_we_ask_for_password = FALSE; - if ((pamerr = pam_authenticate (pamh, null_tok)) != PAM_SUCCESS) { - if (gdm_slave_action_pending ()) { - gdm_error (_("Couldn't authenticate user")); - gdm_errorgui_error_box (cur_gdm_disp, - GTK_MESSAGE_ERROR, - _("Authentication failed")); - } - goto setup_pamerr; - } - - if ((pamerr = pam_get_item (pamh, PAM_USER, (void **)&p)) != PAM_SUCCESS) { - /* is not really an auth problem, but it will - pretty much look as such, it shouldn't really - happen */ - gdm_error (_("Couldn't authenticate user")); - gdm_errorgui_error_box (cur_gdm_disp, - GTK_MESSAGE_ERROR, - _("Authentication failed")); - goto setup_pamerr; - } - after_login = (const char *)p; - - if (after_login != NULL /* should never be */ && - strcmp (after_login, login) != 0) { - *new_login = g_strdup (after_login); - } - -#ifdef HAVE_ADT - /* to set up for same auditing calls as in gdm_verify_user */ - pwent = getpwnam (login); -#endif /* HAVE_ADT */ - - /* Check if the user's account is healthy. */ - pamerr = pam_acct_mgmt (pamh, null_tok); - switch (pamerr) { - case PAM_SUCCESS : - break; - case PAM_NEW_AUTHTOK_REQD : - /* XXX: this is for automatic and timed logins, - * we shouldn't be asking for new pw since we never - * authenticated the user. I suppose just ignoring - * this would be OK */ -#if 0 /* don't change password */ - if ((pamerr = pam_chauthtok (pamh, PAM_CHANGE_EXPIRED_AUTHTOK)) != PAM_SUCCESS) { - gdm_error (_("Authentication token change failed for user %s"), login); - gdm_errorgui_error_box (cur_gdm_disp, - GTK_MESSAGE_ERROR, - _("\nThe change of the authentication token failed. " - "Please try again later or contact the system administrator.")); -#ifdef HAVE_ADT - pw_change = PW_FAILED; -#endif /* HAVE_ADT */ - goto setup_pamerr; - } -#ifdef HAVE_ADT - pw_change = PW_TRUE; -#endif /* HAVE_ADT */ -#endif /* 0 */ - break; - case PAM_ACCT_EXPIRED : - gdm_error (_("User %s no longer permitted to access the system"), login); - gdm_errorgui_error_box (cur_gdm_disp, - GTK_MESSAGE_ERROR, - _("The system administrator has disabled your account.")); - goto setup_pamerr; - case PAM_PERM_DENIED : - gdm_error (_("User %s not permitted to gain access at this time"), login); - gdm_errorgui_error_box (cur_gdm_disp, - GTK_MESSAGE_ERROR, - _("The system administrator has disabled your access to the system temporarily.")); - goto setup_pamerr; - default : - if (gdm_slave_action_pending ()) - gdm_error (_("Couldn't set acct. mgmt for %s"), login); - goto setup_pamerr; - } - - pwent = getpwnam (login); - if (/* paranoia */ pwent == NULL || - ! gdm_setup_gids (login, pwent->pw_gid)) { - gdm_error (_("Cannot set user group for %s"), login); - gdm_errorgui_error_box (cur_gdm_disp, - GTK_MESSAGE_ERROR, - _("Cannot set your user group; " - "you will not be able to log in. " - "Please contact your system administrator.")); -#ifdef HAVE_ADT - /* - * map group setup error as a pam_setcred () failure - * indeed that's where this should be done. - */ - pamerr = PAM_SYSTEM_ERR; -#endif /* HAVE_ADT */ - goto setup_pamerr; - } - - did_setcred = TRUE; - -#ifdef __sun - solaris_xserver_cred ((char *)login, d, pwent); -#endif - - /* Set credentials */ - pamerr = pam_setcred (pamh, PAM_ESTABLISH_CRED); - if (pamerr != PAM_SUCCESS) { - did_setcred = FALSE; - if (gdm_slave_action_pending ()) - gdm_error (_("Couldn't set credentials for %s"), login); - goto setup_pamerr; - } - - credentials_set = TRUE; - opened_session = TRUE; - - /* Register the session */ - pamerr = pam_open_session (pamh, 0); - if (pamerr != PAM_SUCCESS) { - did_setcred = FALSE; - opened_session = FALSE; - /* Throw away the credentials */ - pam_setcred (pamh, PAM_DELETE_CRED); - - if (gdm_slave_action_pending ()) - gdm_error (_("Couldn't open session for %s"), login); - goto setup_pamerr; - } - - /* Workaround to avoid gdm messages being logged as PAM_pwdb */ - gdm_log_shutdown (); - gdm_log_init (); - - cur_gdm_disp = NULL; - - g_free (extra_standalone_message); - extra_standalone_message = NULL; - -#ifdef HAVE_LOGINDEVPERM - if (d->attached) - (void) di_devperm_login ("/dev/console", pwent->pw_uid, - pwent->pw_gid, NULL); -#endif /* HAVE_LOGINDEVPERM */ -#ifdef HAVE_ADT - audit_success_login (pw_change, pwent); -#endif /* HAVE_ADT */ - - return TRUE; - - setup_pamerr: - -#ifdef HAVE_ADT - audit_fail_login (d, pw_change, pwent, pamerr); -#endif /* HAVE_ADT */ - - did_setcred = FALSE; - opened_session = FALSE; - if (pamh != NULL) { - pam_handle_t *tmp_pamh; - - gdm_sigterm_block_push (); - gdm_sigchld_block_push (); - tmp_pamh = pamh; - pamh = NULL; - gdm_sigchld_block_pop (); - gdm_sigterm_block_pop (); - - /* Throw away the credentials */ - if (credentials_set) - pam_setcred (tmp_pamh, PAM_DELETE_CRED); - pam_end (tmp_pamh, pamerr); - } - pamh = NULL; - - /* Workaround to avoid gdm messages being logged as PAM_pwdb */ - gdm_log_shutdown (); - gdm_log_init (); - - cur_gdm_disp = NULL; - - g_free (extra_standalone_message); - extra_standalone_message = NULL; - - return FALSE; -} - -/** - * gdm_verify_cleanup: - * - * Unregister the user's session - */ - -void -gdm_verify_cleanup (GdmDisplay *d) -{ - gid_t groups[1] = { 0 }; - cur_gdm_disp = d; - - if (pamh != NULL) { - gint pamerr; - pam_handle_t *tmp_pamh; - gboolean old_opened_session; - gboolean old_did_setcred; - - gdm_debug ("Running gdm_verify_cleanup and pamh != NULL"); - - gdm_sigterm_block_push (); - gdm_sigchld_block_push (); - tmp_pamh = pamh; - pamh = NULL; - old_opened_session = opened_session; - opened_session = FALSE; - old_did_setcred = did_setcred; - did_setcred = FALSE; - gdm_sigchld_block_pop (); - gdm_sigterm_block_pop (); - - pamerr = PAM_SUCCESS; - -#ifdef HAVE_ADT - /* - * User exiting. - * If logged in, audit logout before cleaning up - */ - if (old_opened_session && old_did_setcred) { - audit_logout (); - } -#endif /* HAVE_ADT */ - /* Close the users session */ - if (old_opened_session) { - gdm_debug ("Running pam_close_session"); - pamerr = pam_close_session (tmp_pamh, 0); - } - - /* Throw away the credentials */ - if (old_did_setcred) { - gdm_debug ("Running pam_setcred with PAM_DELETE_CRED"); - pamerr = pam_setcred (tmp_pamh, PAM_DELETE_CRED); - } - - pam_end (tmp_pamh, pamerr); - -#ifdef HAVE_LOGINDEVPERM - if (old_opened_session && old_did_setcred && d->attached) { - (void) di_devperm_logout ("/dev/console"); - /* give it back to gdm user */ - (void) di_devperm_login ("/dev/console", - gdm_daemon_config_get_gdmuid (), - gdm_daemon_config_get_gdmgid (), NULL); - } -#endif /* HAVE_LOGINDEVPERM */ - - /* Workaround to avoid gdm messages being logged as PAM_pwdb */ - gdm_log_shutdown (); - gdm_log_init (); - } - - /* Clear the group setup */ - setgid (0); - /* this will get rid of any suplementary groups etc... */ - setgroups (1, groups); - - cur_gdm_disp = NULL; - - /* reset limits */ - gdm_reset_limits (); -} - -/* used in pam */ -gboolean -gdm_verify_setup_env (GdmDisplay *d) -{ - gchar **pamenv; - - if (pamh == NULL) - return FALSE; - - /* Migrate any PAM env. variables to the user's environment */ - /* This leaks, oh well */ - if ((pamenv = pam_getenvlist (pamh))) { - gint i; - - for (i = 0 ; pamenv[i] ; i++) { - putenv (g_strdup (pamenv[i])); - } - } - - return TRUE; -} |