diff options
Diffstat (limited to 'kdm/backend/client.c')
-rw-r--r-- | kdm/backend/client.c | 1865 |
1 files changed, 0 insertions, 1865 deletions
diff --git a/kdm/backend/client.c b/kdm/backend/client.c deleted file mode 100644 index 0cf4e216b..000000000 --- a/kdm/backend/client.c +++ /dev/null @@ -1,1865 +0,0 @@ -/* - -Copyright 1988, 1998 The Open Group -Copyright 2000-2004 Oswald Buddenhagen <ossi@kde.org> - -Permission to use, copy, modify, distribute, and sell this software and its -documentation for any purpose is hereby granted without fee, provided that -the above copyright notice appear in all copies and that both that -copyright notice and this permission notice appear in supporting -documentation. - -The above copyright notice and this permission notice shall be included -in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of a copyright holder shall -not be used in advertising or otherwise to promote the sale, use or -other dealings in this Software without prior written authorization -from the copyright holder. - -*/ - -/* - * xdm - display manager daemon - * Author: Keith Packard, MIT X Consortium - * - * user verification and session initiation. - */ - -#include "dm.h" -#include "dm_auth.h" -#include "dm_error.h" - -#include <sys/stat.h> -#include <pwd.h> -#include <grp.h> -#ifdef SECURE_RPC -# include <rpc/rpc.h> -# include <rpc/key_prot.h> -extern int key_setnet( struct key_netstarg *arg ); -#endif -#ifdef K5AUTH -# include <krb5/krb5.h> -#endif -#ifdef HAVE_SETUSERCONTEXT -# include <login_cap.h> -#endif -#ifdef USE_PAM -# ifdef HAVE_PAM_PAM_APPL_H -# include <pam/pam_appl.h> -# else -# include <security/pam_appl.h> -# endif -#elif defined(_AIX) /* USE_PAM */ -# include <login.h> -# include <usersec.h> -extern int loginrestrictions( const char *Name, const int Mode, const char *Tty, char **Msg ); -extern int loginfailed( const char *User, const char *Host, const char *Tty ); -extern int loginsuccess( const char *User, const char *Host, const char *Tty, char **Msg ); -#else /* USE_PAM || _AIX */ -# ifdef KERBEROS -# include <sys/param.h> -# include <krb.h> -# ifndef NO_AFS -# include <kafs.h> -# endif -# endif -/* for nologin */ -# include <sys/types.h> -# include <unistd.h> -/* for expiration */ -# include <time.h> -#endif /* USE_PAM || _AIX */ -#ifdef HAVE_SHADOW -# include <shadow.h> -#endif -#include <signal.h> - -#ifdef WITH_CONSOLE_KIT -#include "consolekit.h" -#endif - -#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 - -#ifdef WITH_CONSOLE_KIT -#include "consolekit.h" -#endif - -/* - * Session data, mostly what struct verify_info was for - */ -char *curuser; -char *curpass; -char *curtype; -char *newpass; -char **userEnviron; -char **systemEnviron; -static int curuid; -static int curgid; -int cursource; - -char *dmrcuser; -char *curdmrc; -char *newdmrc; - -static struct passwd *p; -#ifdef HAVE_SETUSERCONTEXT -# ifdef HAVE_LOGIN_GETCLASS -login_cap_t *lc; -# else -struct login_cap *lc; -# endif -#endif -#ifdef USE_PAM -static pam_handle_t *pamh; -#elif defined(_AIX) -static char tty[16], hostname[100]; -#else -# ifdef USESHADOW -static struct spwd *sp; -# endif -# ifdef KERBEROS -static char krbtkfile[MAXPATHLEN]; -# endif -#endif - -#define V_RET_AUTH \ - do { \ - PrepErrorGreet (); \ - GSendInt (V_AUTH); \ - return 0; \ - } while(0) - -#define V_RET_FAIL(m) \ - do { \ - PrepErrorGreet (); \ - GSendInt (V_MSG_ERR); \ - GSendStr (m); \ - GSendInt (V_FAIL); \ - return 0; \ - } while(0) - -#ifdef USE_PAM - -# ifdef PAM_MESSAGE_NONCONST -typedef struct pam_message pam_message_type; -typedef void *pam_gi_type; -# else -typedef const struct pam_message pam_message_type; -typedef const void *pam_gi_type; -# endif - -struct pam_data { - GConvFunc gconv; - int usecur; - int abort; -}; - -static int -PAM_conv( int num_msg, - pam_message_type **msg, - struct pam_response **resp, - void *appdata_ptr ) -{ - int count; - struct pam_response *reply; - struct pam_data *pd = (struct pam_data *)appdata_ptr; - - if (!(reply = Calloc( num_msg, sizeof(*reply) ))) - return PAM_CONV_ERR; - - ReInitErrorLog(); - Debug( "PAM_conv\n" ); - for (count = 0; count < num_msg; count++) - switch (msg[count]->msg_style) { - case PAM_TEXT_INFO: - Debug( " PAM_TEXT_INFO: %s\n", msg[count]->msg ); - PrepErrorGreet(); - GSendInt( V_MSG_INFO ); - GSendStr( msg[count]->msg ); - continue; - case PAM_ERROR_MSG: - Debug( " PAM_ERROR_MSG: %s\n", msg[count]->msg ); - PrepErrorGreet(); - GSendInt( V_MSG_ERR ); - GSendStr( msg[count]->msg ); - continue; - default: - /* could do better error handling here, but see below ... */ - if (pd->usecur) { - switch (msg[count]->msg_style) { - /* case PAM_PROMPT_ECHO_ON: cannot happen */ - case PAM_PROMPT_ECHO_OFF: - Debug( " PAM_PROMPT_ECHO_OFF (usecur): %s\n", msg[count]->msg ); - if (!curpass) - pd->gconv( GCONV_PASS, 0 ); - StrDup( &reply[count].resp, curpass ); - break; - default: - LogError( "Unknown PAM message style <%d>\n", msg[count]->msg_style ); - goto conv_err; - } - } else { - switch (msg[count]->msg_style) { - case PAM_PROMPT_ECHO_ON: - Debug( " PAM_PROMPT_ECHO_ON: %s\n", msg[count]->msg ); - reply[count].resp = pd->gconv( GCONV_NORMAL, msg[count]->msg ); - break; - case PAM_PROMPT_ECHO_OFF: - Debug( " PAM_PROMPT_ECHO_OFF: %s\n", msg[count]->msg ); - reply[count].resp = pd->gconv( GCONV_HIDDEN, msg[count]->msg ); - break; -#ifdef PAM_BINARY_PROMPT - case PAM_BINARY_PROMPT: - Debug( " PAM_BINARY_PROMPT\n" ); - reply[count].resp = pd->gconv( GCONV_BINARY, msg[count]->msg ); - break; -#endif - default: - LogError( "Unknown PAM message style <%d>\n", msg[count]->msg_style ); - goto conv_err; - } - } - if (!reply[count].resp) { - Debug( " PAM_conv aborted\n" ); - pd->abort = TRUE; - goto conv_err; - } - reply[count].resp_retcode = PAM_SUCCESS; /* unused in linux-pam */ - } - Debug( " PAM_conv success\n" ); - *resp = reply; - return PAM_SUCCESS; - - conv_err: - for (; count >= 0; count--) - if (reply[count].resp) - switch (msg[count]->msg_style) { - case PAM_PROMPT_ECHO_ON: - case PAM_PROMPT_ECHO_OFF: /* could wipe ... */ -#ifdef PAM_BINARY_PROMPT - case PAM_BINARY_PROMPT: /* ... that too ... */ -#endif - free( reply[count].resp ); - break; - } - free( reply ); - return PAM_CONV_ERR; -} - -static int -PAM_conv_null( int num_msg, - pam_message_type **msg, - struct pam_response **resp, - void *appdata_ptr ATTR_UNUSED ) -{ - int count; - struct pam_response *reply; - - if (!(reply = Calloc( num_msg, sizeof(*reply) ))) - return PAM_CONV_ERR; - - ReInitErrorLog(); - Debug( "PAM_conv_null\n" ); - for (count = 0; count < num_msg; count++) { - switch (msg[count]->msg_style) { - case PAM_TEXT_INFO: - Debug( " PAM_TEXT_INFO: %s\n", msg[count]->msg ); - continue; - case PAM_ERROR_MSG: - LogError( "PAM error message: %s\n", msg[count]->msg ); - continue; - default: - /* unknown */ - Debug( " PAM_<%d>\n", msg[count]->msg_style ); - free( reply ); - return PAM_CONV_ERR; - } - reply[count].resp_retcode = PAM_SUCCESS; /* unused in linux-pam */ - } - Debug( " PAM_conv_null success\n" ); - *resp = reply; - return PAM_SUCCESS; -} - -# ifdef PAM_FAIL_DELAY -static void -fail_delay( int retval ATTR_UNUSED, unsigned usec_delay ATTR_UNUSED, - void *appdata_ptr ATTR_UNUSED ) -{} -# endif - - /** - * 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 *loginname, - const char *hostname, - const char *tty, - int success) -{ - struct passwd *pw; - char buf[64]; - int audit_fd; - - audit_fd = audit_open(); - if (loginname) - pw = getpwnam(loginname); - else { - loginname = "unknown"; - pw = NULL; - } - Debug("log_to_audit %p %s\n", pw, loginname); - - 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", loginname); - audit_log_user_message(audit_fd, AUDIT_USER_LOGIN, - buf, hostname, NULL, tty, (int)success); - } - close(audit_fd); -} -#endif - -static int -doPAMAuth( const char *psrv, struct pam_data *pdata ) -{ - pam_gi_type pitem; - struct pam_conv pconv; - int pretc; - - pdata->abort = FALSE; - pconv.conv = PAM_conv; - pconv.appdata_ptr = (void *)pdata; - Debug( " PAM service %s\n", psrv ); - if ((pretc = pam_start( psrv, curuser, &pconv, &pamh )) != PAM_SUCCESS) - goto pam_bail2; - if ((pretc = pam_set_item( pamh, PAM_TTY, td->name )) != PAM_SUCCESS) { - pam_bail: - pam_end( pamh, pretc ); - pamh = 0; - pam_bail2: - ReInitErrorLog(); - LogError( "PAM error: %s\n", pam_strerror( 0, pretc ) ); - V_RET_FAIL( 0 ); - } - if ((td->displayType & d_location) == dForeign) { - char *cp = strchr( td->name, ':' ); - *cp = 0; - pretc = pam_set_item( pamh, PAM_RHOST, td->name ); - *cp = ':'; - if (pretc != PAM_SUCCESS) - goto pam_bail; - } -# ifdef __sun__ /* Only Solaris <= 9, but checking it does not seem worth it. */ - else if (pam_set_item( pamh, PAM_RHOST, 0 ) != PAM_SUCCESS) - goto pam_bail; -# endif -# ifdef PAM_FAIL_DELAY - pam_set_item( pamh, PAM_FAIL_DELAY, (void *)fail_delay ); -# endif - ReInitErrorLog(); - - Debug( " pam_authenticate() ...\n" ); - pretc = pam_authenticate( pamh, - td->allowNullPasswd ? 0 : PAM_DISALLOW_NULL_AUTHTOK ); - ReInitErrorLog(); - Debug( " pam_authenticate() returned: %s\n", pam_strerror( pamh, pretc ) ); - if (pdata->abort) { - pam_end( pamh, PAM_SUCCESS ); - pamh = 0; - return 0; - } - if (!curuser) { - Debug( " asking PAM for user ...\n" ); - pam_get_item( pamh, PAM_USER, &pitem ); - ReInitErrorLog(); - StrDup( &curuser, (const char *)pitem ); - GSendInt( V_PUT_USER ); - GSendStr( curuser ); - } - if (pretc != PAM_SUCCESS) { - /* Log the failed login attempt */ - log_to_audit_system (curuser, td->remoteHost, td->name, AU_FAILED); - switch (pretc) { - case PAM_USER_UNKNOWN: - case PAM_AUTH_ERR: - case PAM_MAXTRIES: /* should handle this better ... */ - case PAM_AUTHINFO_UNAVAIL: /* returned for unknown users ... bogus */ - pam_end( pamh, pretc ); - pamh = 0; - V_RET_AUTH; - default: - pam_end( pamh, pretc ); - pamh = 0; - V_RET_FAIL( 0 ); - } - } - return 1; -} - -#endif /* USE_PAM */ - -static int -#if defined(USE_PAM) || defined(_AIX) -AccNoPass( const char *un ) -{ - struct passwd *pw = 0; -# ifdef HAVE_SHADOW /* (sic!) - not USESHADOW */ - struct spwd *spw; -# endif -#else -AccNoPass( const char *un, struct passwd *pw ) -{ -#endif - struct group *gr; - char **fp; - int hg; - - if (!*un) - return 0; - - if (cursource != PWSRC_MANUAL) - return 1; - - for (hg = 0, fp = td->noPassUsers; *fp; fp++) - if (**fp == '@') - hg = 1; - else if (!strcmp( un, *fp )) - return 1; - else if (!strcmp( "*", *fp )) { -#if defined(USE_PAM) || defined(_AIX) - if (!(pw = getpwnam( un ))) - return 0; - if (pw->pw_passwd[0] == '!' || pw->pw_passwd[0] == '*') - continue; -# ifdef HAVE_SHADOW /* (sic!) - not USESHADOW */ - if ((spw = getspnam( un )) && - (spw->sp_pwdp[0] == '!' || spw->sp_pwdp[0] == '*')) - continue; -# endif -#endif - if (pw->pw_uid) - return 1; - } - -#if defined(USE_PAM) || defined(_AIX) - if (hg && (pw || (pw = getpwnam( un )))) { -#else - if (hg) { -#endif - for (setgrent(); (gr = getgrent()); ) - for (fp = td->noPassUsers; *fp; fp++) - if (**fp == '@' && !strcmp( gr->gr_name, *fp + 1 )) { - if (pw->pw_gid == gr->gr_gid) { - endgrent(); - return 1; - } - for (; *gr->gr_mem; gr->gr_mem++) - if (!strcmp( un, *gr->gr_mem )) { - endgrent(); - return 1; - } - } - endgrent(); - } - - return 0; -} - -#if !defined(USE_PAM) && !defined(_AIX) && defined(HAVE_SETUSERCONTEXT) -# define LC_RET0 do { login_close(lc); return 0; } while(0) -#else -# define LC_RET0 return 0 -#endif - -int -Verify( GConvFunc gconv, int rootok ) -{ -#ifdef USE_PAM - const char *psrv; - struct pam_data pdata; - int pretc, pnopass; - char psrvb[64]; -#elif defined(_AIX) - char *msg, *curret; - int i, reenter; -#else - struct stat st; - const char *nolg; - char *buf; - int fd; -# ifdef HAVE_GETUSERSHELL - char *s; -# endif -# if defined(HAVE_STRUCT_PASSWD_PW_EXPIRE) || defined(USESHADOW) - int tim, expir, warntime, quietlog; -# endif -#endif - - Debug( "Verify ...\n" ); - -#ifdef USE_PAM - - pnopass = FALSE; - if (!strcmp( curtype, "classic" )) { - if (!gconv( GCONV_USER, 0 )) - return 0; - if (AccNoPass( curuser )) { - gconv( GCONV_PASS_ND, 0 ); - if (!*curpass) { - pnopass = TRUE; - sprintf( psrvb, "%.31s-np", PAMService ); - psrv = psrvb; - } else - psrv = PAMService; - } else - psrv = PAMService; - pdata.usecur = TRUE; - } else if (!strcmp( curtype, "pam" )) { - psrv = PAMService; - pdata.usecur = FALSE; - } else { - sprintf( psrvb, "%.31s-%.31s", PAMService, curtype ); - psrv = psrvb; - pdata.usecur = FALSE; - } - pdata.gconv = gconv; - if (!doPAMAuth( psrv, &pdata )) - return 0; - -#elif defined(_AIX) - - if ((td->displayType & d_location) == dForeign) { - char *tmpch; - strncpy( hostname, td->name, sizeof(hostname) - 1 ); - hostname[sizeof(hostname)-1] = '\0'; - if ((tmpch = strchr( hostname, ':' ))) - *tmpch = '\0'; - } else - hostname[0] = '\0'; - - /* tty names should only be 15 characters long */ -# if 0 - for (i = 0; i < 15 && td->name[i]; i++) { - if (td->name[i] == ':' || td->name[i] == '.') - tty[i] = '_'; - else - tty[i] = td->name[i]; - } - tty[i] = '\0'; -# else - memcpy( tty, "/dev/xdm/", 9 ); - for (i = 0; i < 6 && td->name[i]; i++) { - if (td->name[i] == ':' || td->name[i] == '.') - tty[9 + i] = '_'; - else - tty[9 + i] = td->name[i]; - } - tty[9 + i] = '\0'; -# endif - - if (!strcmp( curtype, "classic" )) { - if (!gconv( GCONV_USER, 0 )) - return 0; - if (AccNoPass( curuser )) { - gconv( GCONV_PASS_ND, 0 ); - if (!*curpass) { - Debug( "accepting despite empty password\n" ); - goto done; - } - } else - if (!gconv( GCONV_PASS, 0 )) - return 0; - enduserdb(); - msg = NULL; - if ((i = authenticate( curuser, curpass, &reenter, &msg ))) { - Debug( "authenticate() failed: %s\n", msg ); - if (msg) - free( msg ); - loginfailed( curuser, hostname, tty ); - if (i == ENOENT || i == ESAD) - V_RET_AUTH; - else - V_RET_FAIL( 0 ); - } - if (reenter) { - LogError( "authenticate() requests more data: %s\n", msg ); - free( msg ); - V_RET_FAIL( 0 ); - } - } else if (!strcmp( curtype, "generic" ) || !strcmp(curtype, "pam")) { - if (!gconv( GCONV_USER, 0 )) - return 0; - for (curret = 0;;) { - msg = NULL; - if ((i = authenticate( curuser, curret, &reenter, &msg ))) { - Debug( "authenticate() failed: %s\n", msg ); - if (msg) - free( msg ); - loginfailed( curuser, hostname, tty ); - if (i == ENOENT || i == ESAD) - V_RET_AUTH; - else - V_RET_FAIL( 0 ); - } - if (curret) - free( curret ); - if (!reenter) - break; - if (!(curret = gconv( GCONV_HIDDEN, msg ))) - return 0; - free( msg ); - } - } else { - LogError( "Unsupported authentication type %\"s requested\n", curtype ); - V_RET_FAIL( 0 ); - } - if (msg) { - PrepErrorGreet(); - GSendInt( V_MSG_INFO ); - GSendStr( msg ); - free( msg ); - } - - done: - -#else - - if (strcmp( curtype, "classic" )) { - LogError( "Unsupported authentication type %\"s requested\n", curtype ); - V_RET_FAIL( 0 ); - } - - if (!gconv( GCONV_USER, 0 )) - return 0; - - if (!(p = getpwnam( curuser ))) { - Debug( "getpwnam() failed.\n" ); - gconv( GCONV_PASS, 0 ); - V_RET_AUTH; - } - if (p->pw_passwd[0] == '!' || p->pw_passwd[0] == '*') { - Debug( "account is locked\n" ); - gconv( GCONV_PASS, 0 ); - V_RET_AUTH; - } - -# ifdef USESHADOW - if ((sp = getspnam( curuser ))) { - p->pw_passwd = sp->sp_pwdp; - if (p->pw_passwd[0] == '!' || p->pw_passwd[0] == '*') { - Debug( "account is locked\n" ); - gconv( GCONV_PASS, 0 ); - V_RET_AUTH; - } - } else - Debug( "getspnam() failed: %m. Are you root?\n" ); -# endif - - if (!*p->pw_passwd) { - if (!td->allowNullPasswd) { - Debug( "denying user with empty password\n" ); - gconv( GCONV_PASS, 0 ); - V_RET_AUTH; - } - goto nplogin; - } - - if (AccNoPass( curuser, p )) { - nplogin: - gconv( GCONV_PASS_ND, 0 ); - if (!*curpass) { - Debug( "accepting password-less login\n" ); - goto done; - } - } else - if (!gconv( GCONV_PASS, 0 )) - return 0; - -# ifdef KERBEROS - if (p->pw_uid) { - int ret; - char realm[REALM_SZ]; - - if (krb_get_lrealm( realm, 1 )) { - LogError( "Can't get KerberosIV realm.\n" ); - V_RET_FAIL( 0 ); - } - - sprintf( krbtkfile, "%s.%.*s", TKT_ROOT, MAXPATHLEN - strlen( TKT_ROOT ) - 2, td->name ); - krb_set_tkt_string( krbtkfile ); - unlink( krbtkfile ); - - ret = krb_verify_user( curuser, "", realm, curpass, 1, "rcmd" ); - if (ret == KSUCCESS) { - chown( krbtkfile, p->pw_uid, p->pw_gid ); - Debug( "KerberosIV verify succeeded\n" ); - goto done; - } else if (ret != KDC_PR_UNKNOWN && ret != SKDC_CANT) { - LogError( "KerberosIV verification failure %\"s for %s\n", - krb_get_err_text( ret ), curuser ); - krbtkfile[0] = '\0'; - V_RET_FAIL( 0 ); - } - Debug( "KerberosIV verify failed: %s\n", krb_get_err_text( ret ) ); - } - krbtkfile[0] = '\0'; -# endif /* KERBEROS */ - -# if defined(ultrix) || defined(__ultrix__) - if (authenticate_user( p, curpass, NULL ) < 0) -# elif defined(HAVE_CRYPT) - if (strcmp( crypt( curpass, p->pw_passwd ), p->pw_passwd )) -# else - if (strcmp( curpass, p->pw_passwd )) -# endif - { - Debug( "password verify failed\n" ); - V_RET_AUTH; - } - - done: - -#endif /* !defined(USE_PAM) && !defined(_AIX) */ - - Debug( "restrict %s ...\n", curuser ); - -#if defined(USE_PAM) || defined(_AIX) - if (!(p = getpwnam( curuser ))) { - LogError( "getpwnam(%s) failed.\n", curuser ); - V_RET_FAIL( 0 ); - } -#endif - if (!p->pw_uid) { - if (!rootok && !td->allowRootLogin) - V_RET_FAIL( "Root logins are not allowed" ); - /* Log the failed login attempt */ - log_to_audit_system (curuser, td->remoteHost, td->name, AU_FAILED); - return 1; /* don't deny root to log in */ - } - -#ifdef USE_PAM - - Debug( " pam_acct_mgmt() ...\n" ); - pretc = pam_acct_mgmt( pamh, 0 ); - ReInitErrorLog(); - Debug( " pam_acct_mgmt() returned: %s\n", pam_strerror( pamh, pretc ) ); - if (pretc == PAM_NEW_AUTHTOK_REQD) { - pdata.usecur = FALSE; - pdata.gconv = conv_interact; - /* pam will have output a message already, so no PrepErrorGreet () */ - if (gconv != conv_interact || pnopass) { - pam_end( pamh, PAM_SUCCESS ); - pamh = 0; - GSendInt( V_CHTOK_AUTH ); - /* this cannot auth the wrong user, as only classic auths get here */ - while (!doPAMAuth( PAMService, &pdata )) - if (pdata.abort) - return 0; - GSendInt( V_PRE_OK ); - } else - GSendInt( V_CHTOK ); - for (;;) { - Debug( " pam_chauthtok() ...\n" ); - pretc = pam_chauthtok( pamh, PAM_CHANGE_EXPIRED_AUTHTOK ); - ReInitErrorLog(); - Debug( " pam_chauthtok() returned: %s\n", pam_strerror( pamh, pretc ) ); - if (pdata.abort) { - pam_end( pamh, PAM_SUCCESS ); - pamh = 0; - return 0; - } - if (pretc == PAM_SUCCESS) - break; - /* Log the failed login attempt */ - log_to_audit_system (curuser, td->remoteHost, td->name, AU_FAILED); - /* effectively there is only PAM_AUTHTOK_ERR */ - GSendInt( V_FAIL ); - } - if (curpass) - free( curpass ); - curpass = newpass; - newpass = 0; - } else if (pretc != PAM_SUCCESS) { - pam_end( pamh, pretc ); - pamh = 0; - V_RET_AUTH; - } - -#elif defined(_AIX) /* USE_PAM */ - - msg = NULL; - if (loginrestrictions( curuser, - ((td->displayType & d_location) == dForeign) ? S_RLOGIN : S_LOGIN, - tty, &msg ) == -1) - { - Debug( "loginrestrictions() - %s\n", msg ? msg : "error" ); - loginfailed( curuser, hostname, tty ); - PrepErrorGreet(); - if (msg) { - GSendInt( V_MSG_ERR ); - GSendStr( msg ); - } - GSendInt( V_AUTH ); - return 0; - } - if (msg) - free( (void *)msg ); - -#endif /* USE_PAM || _AIX */ - -#ifndef _AIX - -# ifdef HAVE_SETUSERCONTEXT -# ifdef HAVE_LOGIN_GETCLASS - lc = login_getclass( p->pw_class ); -# else - lc = login_getpwclass( p ); -# endif - if (!lc) - V_RET_FAIL( 0 ); - - p->pw_shell = login_getcapstr( lc, "shell", p->pw_shell, p->pw_shell ); -# endif - -# ifndef USE_PAM - -/* restrict_expired */ -# if defined(HAVE_STRUCT_PASSWD_PW_EXPIRE) || defined(USESHADOW) - -# if !defined(HAVE_STRUCT_PASSWD_PW_EXPIRE) || (!defined(HAVE_SETUSERCONTEXT) && defined(USESHADOW)) - if (sp) -# endif - { - -# define DEFAULT_WARN (2L * 7L) /* Two weeks */ - - tim = time( NULL ) / 86400L; - -# ifdef HAVE_SETUSERCONTEXT - quietlog = login_getcapbool( lc, "hushlogin", 0 ); - warntime = login_getcaptime( lc, "warnexpire", - DEFAULT_WARN * 86400L, - DEFAULT_WARN * 86400L ) / 86400L; -# else - quietlog = 0; -# ifdef USESHADOW - warntime = sp->sp_warn != -1 ? sp->sp_warn : DEFAULT_WARN; -# else - warntime = DEFAULT_WARN; -# endif -# endif - -# ifdef HAVE_STRUCT_PASSWD_PW_EXPIRE - if (p->pw_expire) { - expir = p->pw_expire / 86400L; -# else - if (sp->sp_expire != -1) { - expir = sp->sp_expire; -# endif - if (tim > expir) { - PrepErrorGreet(); - GSendInt( V_MSG_ERR ); - GSendStr( "Your account has expired;" - " please contact your system administrator" ); - /* Log the failed login attempt */ - log_to_audit_system (curuser, td->remoteHost, td->name, AU_FAILED); - GSendInt( V_FAIL ); - LC_RET0; - } else if (tim > (expir - warntime) && !quietlog) { - ASPrintf( &buf, - "Warning: your account will expire in %d day(s)", - expir - tim ); - if (buf) { - PrepErrorGreet(); - GSendInt( V_MSG_INFO ); - GSendStr( buf ); - free( buf ); - } - } - } - -# ifdef HAVE_STRUCT_PASSWD_PW_EXPIRE - if (p->pw_change) { - expir = p->pw_change / 86400L; -# else - if (!sp->sp_lstchg) { - PrepErrorGreet(); - GSendInt( V_MSG_ERR ); - GSendStr( "You are required to change your password immediately" - " (root enforced)" ); - /* XXX todo password change */ - GSendInt( V_FAIL ); - LC_RET0; - } else if (sp->sp_max != -1) { - expir = sp->sp_lstchg + sp->sp_max; - if (sp->sp_inact != -1 && tim > expir + sp->sp_inact) { - PrepErrorGreet(); - GSendInt( V_MSG_ERR ); - GSendStr( "Your account has expired;" - " please contact your system administrator" ); - /* Log the failed login attempt */ - log_to_audit_system (curuser, td->remoteHost, td->name, AU_FAILED); - GSendInt( V_FAIL ); - LC_RET0; - } -# endif - if (tim > expir) { - PrepErrorGreet(); - GSendInt( V_MSG_ERR ); - GSendStr( "You are required to change your password immediately" - " (password aged)" ); - /* XXX todo password change */ - GSendInt( V_FAIL ); - LC_RET0; - } else if (tim > (expir - warntime) && !quietlog) { - ASPrintf( &buf, - "Warning: your password will expire in %d day(s)", - expir - tim ); - if (buf) { - PrepErrorGreet(); - GSendInt( V_MSG_INFO ); - GSendStr( buf ); - free( buf ); - } - } - } - - } - -# endif /* HAVE_STRUCT_PASSWD_PW_EXPIRE || USESHADOW */ - -/* restrict_nologin */ -# ifndef _PATH_NOLOGIN -# define _PATH_NOLOGIN "/etc/nologin" -# endif - - if (( -# ifdef HAVE_SETUSERCONTEXT - /* Do we ignore a nologin file? */ - !login_getcapbool( lc, "ignorenologin", 0 )) && - (!stat( (nolg = login_getcapstr( lc, "nologin", "", NULL )), &st ) || -# endif - !stat( (nolg = _PATH_NOLOGIN), &st ))) - { - PrepErrorGreet(); - GSendInt( V_MSG_ERR ); - if (st.st_size && (fd = open( nolg, O_RDONLY )) >= 0) { - if ((buf = Malloc( st.st_size + 1 ))) { - if (read( fd, buf, st.st_size ) == st.st_size) { - buf[st.st_size] = 0; - GSendStr( buf ); - free( buf ); - close( fd ); - GSendInt( V_FAIL ); - LC_RET0; - } - free( buf ); - } - close( fd ); - } - GSendStr( "Logins are not allowed at the moment.\nTry again later" ); - /* Log the failed login attempt */ - log_to_audit_system (curuser, td->remoteHost, td->name, AU_FAILED); - GSendInt( V_FAIL ); - LC_RET0; - } - -/* restrict_time */ -# if defined(HAVE_SETUSERCONTEXT) && defined(HAVE_AUTH_TIMEOK) - if (!auth_timeok( lc, time( NULL ) )) { - PrepErrorGreet(); - GSendInt( V_MSG_ERR ); - GSendStr( "You are not allowed to login at the moment" ); - /* Log the failed login attempt */ - log_to_audit_system (curuser, td->remoteHost, td->name, AU_FAILED); - GSendInt( V_FAIL ); - LC_RET0; - } -# endif - -# ifdef HAVE_GETUSERSHELL - for (;;) { - if (!(s = getusershell())) { - Debug( "shell not in /etc/shells\n" ); - endusershell(); - V_RET_FAIL( "Your login shell is not listed in /etc/shells" ); - /* Log the failed login attempt */ - log_to_audit_system (curuser, td->remoteHost, td->name, AU_FAILED); - } - if (!strcmp( s, p->pw_shell )) { - endusershell(); - break; - } - } -# endif - -# endif /* !USE_PAM */ - -/* restrict_nohome */ -# ifdef HAVE_SETUSERCONTEXT - if (login_getcapbool( lc, "requirehome", 0 )) { - struct stat st; - if (!*p->pw_dir || stat( p->pw_dir, &st ) || st.st_uid != p->pw_uid) { - PrepErrorGreet(); - GSendInt( V_MSG_ERR ); - GSendStr( "Home folder not available" ); - GSendInt( V_FAIL ); - LC_RET0; - } - } -# endif - -#endif /* !_AIX */ - - return 1; - -} - - -static const char *envvars[] = { - "TZ", /* SYSV and SVR4, but never hurts */ -#ifdef _AIX - "AUTHSTATE", /* for kerberos */ -#endif - NULL -}; - - -#if defined(USE_PAM) && defined(HAVE_INITGROUPS) -static int num_saved_gids; -static gid_t *saved_gids; - -static int -saveGids( void ) -{ - num_saved_gids = getgroups( 0, 0 ); - if (!(saved_gids = Malloc( sizeof(gid_t) * num_saved_gids ))) - return 0; - if (getgroups( num_saved_gids, saved_gids ) < 0) { - LogError( "saving groups failed: %m\n" ); - return 0; - } - return 1; -} - -static int -restoreGids( void ) -{ - if (setgroups( num_saved_gids, saved_gids ) < 0) { - LogError( "restoring groups failed: %m\n" ); - return 0; - } - if (setgid( p->pw_gid ) < 0) { - LogError( "restoring gid failed: %m\n" ); - return 0; - } - return 1; -} -#endif /* USE_PAM && HAVE_INITGROUPS */ - -static int -resetGids( void ) -{ -#ifdef HAVE_INITGROUPS - if (setgroups( 0, &p->pw_gid /* anything */ ) < 0) { - LogError( "restoring groups failed: %m\n" ); - return 0; - } -#endif - if (setgid( 0 ) < 0) { - LogError( "restoring gid failed: %m\n" ); - return 0; - } - return 1; -} - -static int -SetGid( const char *name, int gid ) -{ - if (setgid( gid ) < 0) { - LogError( "setgid(%d) (user %s) failed: %m\n", gid, name ); - return 0; - } -#ifdef HAVE_INITGROUPS - if (initgroups( name, gid ) < 0) { - LogError( "initgroups for %s failed: %m\n", name ); - setgid( 0 ); - return 0; - } -#endif /* QNX4 doesn't support multi-groups, no initgroups() */ - return 1; -} - -static int -SetUid( const char *name, int uid ) -{ - if (setuid( uid ) < 0) { - LogError( "setuid(%d) (user %s) failed: %m\n", uid, name ); - return 0; - } - return 1; -} - -static int -SetUser( const char *name, int uid, int gid ) -{ - if (SetGid( name, gid )) { - if (SetUid( name, uid )) - return 1; - resetGids(); - } - return 0; -} - -#if defined(SECURE_RPC) || defined(K5AUTH) -static void -NukeAuth( int len, const char *name ) -{ - int i; - - for (i = 0; i < td->authNum; i++) - if (td->authorizations[i]->name_length == len && - !memcmp( td->authorizations[i]->name, name, len )) - { - memcpy( &td->authorizations[i], &td->authorizations[i+1], - sizeof(td->authorizations[i]) * (--td->authNum - i) ); - break; - } -} -#endif - -static void -mergeSessionArgs( int cansave ) -{ - char *mfname; - const char *fname; - int i, needsave; - - mfname = 0; - fname = ".dmrc"; - if ((!curdmrc || newdmrc) && *dmrcDir) - if (StrApp( &mfname, dmrcDir, "/", curuser, fname, (char *)0 )) - fname = mfname; - needsave = 0; - if (!curdmrc) { - curdmrc = iniLoad( fname ); - if (!curdmrc) { - StrDup( &curdmrc, "[Desktop]\nSession=default\n" ); - needsave = 1; - } - } - if (newdmrc) { - curdmrc = iniMerge( curdmrc, newdmrc ); - needsave = 1; - } - if (needsave && cansave) - if (!iniSave( curdmrc, fname ) && errno == ENOENT && mfname) { - for (i = 0; mfname[i]; i++) - if (mfname[i] == '/') { - mfname[i] = 0; - mkdir( mfname, 0755 ); - mfname[i] = '/'; - } - iniSave( curdmrc, mfname ); - } - if (mfname) - free( mfname ); -} - -static int removeAuth; -#ifdef USE_PAM -static int removeSession; -static int removeCreds; -#endif - -#ifdef WITH_CONSOLE_KIT -int -StartClient( const char *ck_session_cookie ) -#else -int -StartClient() -#endif -{ - const char *home, *sessargs, *desksess; - char **env, *xma; - char **argv, *fname, *str; -#ifdef USE_PAM - char **pam_env; -# ifdef _AIX - char **saved_env; -# endif - struct pam_conv pconv; - int pretc; -#else -# ifdef _AIX - char *msg; - char **theenv; - extern char **newenv; /* from libs.a, this is set up by setpenv */ -# endif -#endif -#ifdef HAVE_SETUSERCONTEXT - extern char **environ; -#endif - char *failsafeArgv[2], *lname; - int i, pid, lfd; - - if (StrCmp( dmrcuser, curuser )) { - if (curdmrc) { free( curdmrc ); curdmrc = 0; } - if (dmrcuser) { free( dmrcuser ); dmrcuser = 0; } - } - -#if defined(USE_PAM) || defined(_AIX) - if (!(p = getpwnam( curuser ))) { - LogError( "getpwnam(%s) failed.\n", curuser ); - return 0; - } -#endif - -#ifndef USE_PAM -# ifdef _AIX - msg = NULL; - loginsuccess( curuser, hostname, tty, &msg ); - if (msg) { - Debug( "loginsuccess() - %s\n", msg ); - free( (void *)msg ); - } -# else /* _AIX */ -# if defined(KERBEROS) && !defined(NO_AFS) - if (krbtkfile[0] != '\0') { - if (k_hasafs()) { - if (k_setpag() == -1) - LogError( "setpag() for %s failed\n", curuser ); - if ((ret = k_afsklog( NULL, NULL )) != KSUCCESS) - LogError( "AFS Warning: %s\n", krb_get_err_text( ret ) ); - } - } -# endif /* KERBEROS && AFS */ -# endif /* _AIX */ -#endif /* !PAM */ - - curuid = p->pw_uid; - curgid = p->pw_gid; - - env = baseEnv( curuser ); - xma = 0; - if (td->ctrl.fpath && StrDup( &xma, td->ctrl.fpath )) { - if ((td->allowShutdown == SHUT_ALL || - (td->allowShutdown == SHUT_ROOT && !curuser)) && - StrApp( &xma, ",maysd", (char *)0 )) - { - if (td->allowNuke == SHUT_ALL || - (td->allowNuke == SHUT_ROOT && !curuser)) - StrApp( &xma, ",mayfn", (char *)0 ); - StrApp( &xma, td->defSdMode == SHUT_FORCENOW ? ",fn" : - td->defSdMode == SHUT_TRYNOW ? ",tn" : ",sched", - (char *)0 ); - } - if ((td->displayType & d_location) == dLocal && AnyReserveDisplays()) - StrApp( &xma, ",rsvd", (char *)0 ); - } else - StrDup( &xma, "true" ); - StrApp( &xma, ",method=", curtype, (char *)0 ); - if (td_setup) - StrApp( &xma, ",auto", (char *)0 ); - if (xma) { - env = setEnv( env, "XDM_MANAGED", xma ); - free( xma ); - } - if (td->autoLock && cursource == PWSRC_AUTOLOGIN) - env = setEnv( env, "DESKTOP_LOCKED", "true" ); - env = setEnv( env, "PATH", curuid ? td->userPath : td->systemPath ); - env = setEnv( env, "SHELL", p->pw_shell ); - env = setEnv( env, "HOME", p->pw_dir ); - if (cursource == PWSRC_AUTOLOGIN) - env = setEnv (env, "TDM_AUTOLOGIN", curuser); -#if !defined(USE_PAM) && !defined(_AIX) && defined(KERBEROS) - if (krbtkfile[0] != '\0') - env = setEnv( env, "KRBTKFILE", krbtkfile ); -#endif -#ifdef WITH_CONSOLE_KIT - if (ck_session_cookie != NULL) { - env = setEnv ( env, "XDG_SESSION_COOKIE", ck_session_cookie ); - } -#endif -#ifdef WITH_CONSOLE_KIT - if (ck_session_cookie != NULL) { - env = setEnv ( env, "XDG_SESSION_COOKIE", ck_session_cookie ); - } -#endif - userEnviron = inheritEnv( env, envvars ); - env = systemEnv( p->pw_name ); - systemEnviron = setEnv( env, "HOME", p->pw_dir ); - Debug( "user environment:\n%[|''>'\n's" - "system environment:\n%[|''>'\n's" - "end of environments\n", - userEnviron, - systemEnviron ); - - /* - * for user-based authorization schemes, - * add the user to the server's allowed "hosts" list. - */ - for (i = 0; i < td->authNum; i++) { -#ifdef SECURE_RPC - if (td->authorizations[i]->name_length == 9 && - !memcmp( td->authorizations[i]->name, "SUN-DES-1", 9 )) - { - XHostAddress addr; - char netname[MAXNETNAMELEN+1]; - char domainname[MAXNETNAMELEN+1]; - - getdomainname( domainname, sizeof(domainname) ); - user2netname( netname, curuid, domainname ); - addr.family = FamilyNetname; - addr.length = strlen( netname ); - addr.address = netname; - XAddHost( dpy, &addr ); - } -#endif -#ifdef K5AUTH - if (td->authorizations[i]->name_length == 14 && - !memcmp( td->authorizations[i]->name, "MIT-KERBEROS-5", 14 )) - { - /* Update server's auth file with user-specific info. - * Don't need to AddHost because X server will do that - * automatically when it reads the cache we are about - * to point it at. - */ - XauDisposeAuth( td->authorizations[i] ); - td->authorizations[i] = - Krb5GetAuthFor( 14, "MIT-KERBEROS-5", td->name ); - SaveServerAuthorizations( td, td->authorizations, td->authNum ); - } -#endif - } - - if (*dmrcDir) - mergeSessionArgs( TRUE ); - - Debug( "now starting the session\n" ); - -#ifdef USE_PAM - /* the greeter is gone by now ... */ - pconv.conv = PAM_conv_null; - pconv.appdata_ptr = 0; - if ((pretc = pam_set_item( pamh, PAM_CONV, &pconv )) != PAM_SUCCESS) { - ReInitErrorLog(); - LogError( "pam_set_item() for %s failed: %s\n", - curuser, pam_strerror( pamh, pretc ) ); - return 0; - } - ReInitErrorLog(); -#endif - -#ifdef USE_PAM - -# ifdef HAVE_SETUSERCONTEXT - if (setusercontext( lc, p, p->pw_uid, LOGIN_SETGROUP )) { - LogError( "setusercontext(groups) for %s failed: %m\n", - curuser ); - return 0; - } -# else - if (!SetGid( curuser, curgid )) - return 0; -# endif - -# ifdef _AIX - if (!(pam_env = initStrArr( 0 ))) { - resetGids(); - return 0; - } - saved_env = environ; - environ = pam_env; -# endif - removeCreds = 1; /* set it first - i don't trust PAM's rollback */ - pretc = pam_setcred( pamh, 0 ); - ReInitErrorLog(); -# ifdef _AIX - pam_env = environ; - environ = saved_env; -# endif -# ifdef HAVE_INITGROUPS - /* This seems to be a strange place for it, but do it: - - after the initial groups are set - - after pam_setcred might have set something, even in the error case - - before pam_setcred(DELETE_CRED) might need it - */ - if (!saveGids()) - return 0; -# endif - if (pretc != PAM_SUCCESS) { - LogError( "pam_setcred() for %s failed: %s\n", - curuser, pam_strerror( pamh, pretc ) ); - resetGids(); - return 0; - } - - removeSession = 1; /* set it first - same as above */ - pretc = pam_open_session( pamh, 0 ); - ReInitErrorLog(); - if (pretc != PAM_SUCCESS) { - LogError( "pam_open_session() for %s failed: %s\n", - curuser, pam_strerror( pamh, pretc ) ); - resetGids(); - return 0; - } - - /* we don't want sessreg and the startup/reset scripts run with user - credentials. unfortunately, we can reset only the gids. */ - resetGids(); - -# define D_LOGIN_SETGROUP LOGIN_SETGROUP -#else /* USE_PAM */ -# define D_LOGIN_SETGROUP 0 -#endif /* USE_PAM */ - - /* Login succeeded */ - log_to_audit_system (curuser, td->remoteHost, td->name, AU_SUCCESS); - - removeAuth = 1; - chownCtrl( &td->ctrl, curuid ); - endpwent(); -#if !defined(USE_PAM) && defined(USESHADOW) && !defined(_AIX) - endspent(); -#endif - ClearCloseOnFork( mstrtalk.pipe->wfd ); - switch (pid = Fork()) { - case 0: - - sessreg( td, getpid(), curuser, curuid ); - - if (source( systemEnviron, td->startup, td_setup )) { - LogError( "Cannot execute startup script %\"s\n", td->startup ); - exit( 1 ); - } - - if (Setjmp( mstrtalk.errjmp )) - exit( 1 ); - GSet( &mstrtalk ); - - setsid(); - Signal( SIGINT, SIG_DFL ); - - /* Memory leaks are ok here as we exec() soon. */ - -#if defined(USE_PAM) || !defined(_AIX) - -# ifdef USE_PAM - /* pass in environment variables set by libpam and modules it called */ -# ifndef _AIX - pam_env = pam_getenvlist( pamh ); - ReInitErrorLog(); -# endif - if (pam_env) - for (; *pam_env; pam_env++) - userEnviron = putEnv( *pam_env, userEnviron ); -# endif - -# ifdef HAVE_SETLOGIN - if (setlogin( curuser ) < 0) { - LogError( "setlogin for %s failed: %m\n", curuser ); - exit( 1 ); - } -# define D_LOGIN_SETLOGIN LOGIN_SETLOGIN -# else -# define D_LOGIN_SETLOGIN 0 -# endif - -# if defined(USE_PAM) && defined(HAVE_INITGROUPS) - if (!restoreGids()) - exit( 1 ); -# endif - -# ifndef HAVE_SETUSERCONTEXT - -# ifdef USE_PAM - if (!SetUid( curuser, curuid )) - exit( 1 ); -# else - if (!SetUser( curuser, curuid, curgid )) - exit( 1 ); -# endif - -# else /* !HAVE_SETUSERCONTEXT */ - - /* - * Destroy environment. - * We need to do this before setusercontext() because that may - * set or reset some environment variables. - */ - if (!(environ = initStrArr( 0 ))) - exit( 1 ); - - /* - * Set the user's credentials: uid, gid, groups, - * environment variables, resource limits, and umask. - */ - if (setusercontext( lc, p, p->pw_uid, - LOGIN_SETALL & ~(D_LOGIN_SETGROUP|D_LOGIN_SETLOGIN) ) < 0) - { - LogError( "setusercontext for %s failed: %m\n", curuser ); - exit( 1 ); - } - - for (i = 0; environ[i]; i++) - userEnviron = putEnv( environ[i], userEnviron ); - -# endif /* !HAVE_SETUSERCONTEXT */ - -#else /* PAM || !_AIX */ - /* - * Set the user's credentials: uid, gid, groups, - * audit classes, user limits, and umask. - */ - if (setpcred( curuser, NULL ) == -1) { - LogError( "setpcred for %s failed: %m\n", curuser ); - exit( 1 ); - } - - /* - * Set the users process environment. Store protected variables and - * obtain updated user environment list. This call will initialize - * global 'newenv'. - */ - if (setpenv( curuser, PENV_INIT | PENV_ARGV | PENV_NOEXEC, - userEnviron, NULL ) != 0) - { - LogError( "Can't set %s's process environment\n", curuser ); - exit( 1 ); - } - userEnviron = newenv; - -#endif /* _AIX */ - - /* - * for user-based authorization schemes, - * use the password to get the user's credentials. - */ -#ifdef SECURE_RPC - /* do like "keylogin" program */ - if (!curpass[0]) - LogInfo( "No password for NIS provided.\n" ); - else { - char netname[MAXNETNAMELEN+1], secretkey[HEXKEYBYTES+1]; - int nameret, keyret; - int len; - int key_set_ok = 0; - struct key_netstarg netst; - - nameret = getnetname( netname ); - Debug( "user netname: %s\n", netname ); - len = strlen( curpass ); - if (len > 8) - bzero( curpass + 8, len - 8 ); - keyret = getsecretkey( netname, secretkey, curpass ); - Debug( "getsecretkey returns %d, key length %d\n", - keyret, strlen( secretkey ) ); - netst.st_netname = netname; - memcpy( netst.st_priv_key, secretkey, HEXKEYBYTES ); - memset( netst.st_pub_key, 0, HEXKEYBYTES ); - if (key_setnet( &netst ) < 0) - Debug( "Could not set secret key.\n" ); - /* is there a key, and do we have the right password? */ - if (keyret == 1) { - if (*secretkey) { - keyret = key_setsecret( secretkey ); - Debug( "key_setsecret returns %d\n", keyret ); - if (keyret == -1) - LogError( "Failed to set NIS secret key\n" ); - else - key_set_ok = 1; - } else { - /* found a key, but couldn't interpret it */ - LogError( "Password incorrect for NIS principal %s\n", - nameret ? netname : curuser ); - } - } - if (!key_set_ok) - NukeAuth( 9, "SUN-DES-1" ); - bzero( secretkey, strlen( secretkey ) ); - } -#endif -#ifdef K5AUTH - /* do like "kinit" program */ - if (!curpass[0]) - LogInfo( "No password for Kerberos5 provided.\n" ); - else - if ((str = Krb5Init( curuser, curpass, td->name ))) - userEnviron = setEnv( userEnviron, "KRB5CCNAME", str ); - else - NukeAuth( 14, "MIT-KERBEROS-5" ); -#endif /* K5AUTH */ - if (td->autoReLogin) { - GSendInt( D_ReLogin ); - GSendStr( curuser ); - GSendStr( curpass ); - GSendStr( newdmrc ); - } - if (curpass) - bzero( curpass, strlen( curpass ) ); - SetUserAuthorization( td ); - home = getEnv( userEnviron, "HOME" ); - if (home) { - if (chdir( home ) < 0) { - LogError( "Cannot chdir to %s's home %s: %m, using /\n", - curuser, home ); - home = 0; - userEnviron = setEnv( userEnviron, "HOME", "/" ); - goto cdroot; - } - ASPrintf( &lname, td->clientLogFile, td->name ); - if ((lfd = creat( lname, 0600 )) < 0) { - LogWarn( "Cannot create session log file %s: %m\n", lname ); - free( lname ); - goto tmperr; - } - } else { - cdroot: - chdir( "/" ); - tmperr: - ASPrintf( &lname, "/tmp/xerr-%s-%s", curuser, td->name ); - unlink( lname ); - if ((lfd = open( lname, O_WRONLY|O_CREAT|O_EXCL, 0600 )) < 0) { - LogError( "Cannot create fallback session log file %s: %m\n", - lname ); - goto logerr; - } - } - dup2( lfd, 1 ); - dup2( lfd, 2 ); - close( lfd ); - logerr: - free( lname ); - if (!*dmrcDir) - mergeSessionArgs( home != 0 ); - if (!(desksess = iniEntry( curdmrc, "Desktop", "Session", 0 ))) - desksess = "failsafe"; /* only due to OOM */ - GSendInt( D_User ); - GSendInt( curuid ); - GSendStr( curuser ); - GSendStr( desksess ); - close( mstrtalk.pipe->wfd ); - userEnviron = setEnv( userEnviron, "DESKTOP_SESSION", desksess ); - for (i = 0; td->sessionsDirs[i]; i++) { - fname = 0; - if (StrApp( &fname, td->sessionsDirs[i], "/", desksess, ".desktop", (char *)0 )) { - if ((str = iniLoad( fname ))) { - if (!StrCmp( iniEntry( str, "Desktop Entry", "Hidden", 0 ), "true" ) || - !(sessargs = iniEntry( str, "Desktop Entry", "Exec", 0 ))) - sessargs = ""; - free( str ); - free( fname ); - goto gotit; - } - free( fname ); - } - } - if (!strcmp( desksess, "failsafe" ) || - !strcmp( desksess, "default" ) || - !strcmp( desksess, "custom" )) - sessargs = desksess; - else - sessargs = ""; - gotit: - if (!(argv = parseArgs( (char **)0, td->session )) || - !(argv = addStrArr( argv, sessargs, -1 ))) - exit( 1 ); - if (argv[0] && *argv[0]) { - Debug( "executing session %\"[s\n", argv ); - execute( argv, userEnviron ); - LogError( "Session %\"s execution failed: %m\n", argv[0] ); - } else - LogError( "Session has no command/arguments\n" ); - failsafeArgv[0] = td->failsafeClient; - failsafeArgv[1] = 0; - execute( failsafeArgv, userEnviron ); - LogError( "Failsafe client %\"s execution failed: %m\n", - failsafeArgv[0] ); - exit( 1 ); - case -1: - RegisterCloseOnFork( mstrtalk.pipe->wfd ); - LogError( "Forking session on %s failed: %m\n", td->name ); - return 0; - default: - RegisterCloseOnFork( mstrtalk.pipe->wfd ); - Debug( "StartSession, fork succeeded %d\n", pid ); - return pid; - } -} - -void -SessionExit( int status ) -{ - int pid; -#ifdef USE_PAM - int pretc; -#endif - - Signal( SIGTERM, SIG_IGN ); - - if (removeAuth) { - if (source( systemEnviron, td->reset, td_setup )) - LogError( "Cannot execute reset script %\"s\n", td->reset ); - sessreg( td, 0, 0, 0 ); - - switch ((pid = Fork())) { - case 0: -#if defined(USE_PAM) && defined(HAVE_INITGROUPS) - if (restoreGids() && SetUid( curuser, curuid )) -#else - if (SetUser( curuser, curuid, curgid )) -#endif - - { - RemoveUserAuthorization( td ); -#ifdef K5AUTH - Krb5Destroy( td->name ); -#endif /* K5AUTH */ -#if !defined(USE_PAM) && !defined(_AIX) -# ifdef KERBEROS - if (krbtkfile[0]) { - (void)dest_tkt(); -# ifndef NO_AFS - if (k_hasafs()) - (void)k_unlog(); -# endif - } -# endif -#endif /* !USE_PAM && !_AIX*/ - } - exit( 0 ); - case -1: - LogError( "Cannot clean up session: fork() failed: %m" ); - break; - default: - Wait4( pid ); - break; - } - } - -#ifdef USE_PAM - if (removeCreds) { -# ifdef HAVE_INITGROUPS - restoreGids(); -# endif - if (removeSession) - if ((pretc = pam_close_session( pamh, 0 )) != PAM_SUCCESS) - LogError( "pam_close_session() failed: %s\n", - pam_strerror( pamh, pretc ) ); - if ((pretc = pam_setcred( pamh, PAM_DELETE_CRED )) != PAM_SUCCESS) - LogError( "pam_setcred(DELETE_CRED) failed: %s\n", - pam_strerror( pamh, pretc ) ); - resetGids(); - } - if (pamh) { - pam_end( pamh, PAM_SUCCESS ); - ReInitErrorLog(); - } -#endif - - /* make sure the server gets reset after the session is over */ - if (td->serverPid >= 2) { - if (!td->terminateServer && td->resetSignal) - TerminateProcess( td->serverPid, td->resetSignal ); - } else - ResetServer( td ); - Debug( "display %s exiting with status %d\n", td->name, status ); - exit( status ); -} - -int -ReadDmrc() -{ - char *data, *fname = 0; - int len, pid, pfd[2], err; - - if (!dmrcuser || !dmrcuser[0] || !(p = getpwnam( dmrcuser ))) - return GE_NoUser; - - if (*dmrcDir) { - if (!StrApp( &fname, dmrcDir, "/", dmrcuser, ".dmrc", (char *)0 )) - return GE_Error; - if (!(curdmrc = iniLoad( fname ))) { - free( fname ); - return GE_Ok; - } - free( fname ); - return GE_NoFile; - } - - if (!StrApp( &fname, p->pw_dir, "/.dmrc", (char *)0 )) - return GE_Error; - if (pipe( pfd )) - return GE_Error; - if ((pid = Fork()) < 0) { - close( pfd[0] ); - close( pfd[1] ); - return GE_Error; - } - if (!pid) { - if (!SetUser( p->pw_name, p->pw_uid, p->pw_gid )) - exit( 0 ); - if (!(data = iniLoad( fname ))) { - static const int m1 = -1; - write( pfd[1], &m1, sizeof(int) ); - exit( 0 ); - } - len = strlen( data ); - write( pfd[1], &len, sizeof(int) ); - write( pfd[1], data, len + 1 ); - exit( 0 ); - } - close( pfd[1] ); - free( fname ); - err = GE_Error; - if (Reader( pfd[0], &len, sizeof(int) ) == sizeof(int)) { - if (len == -1) - err = GE_Denied; - else if ((curdmrc = Malloc( len + 1 ))) { - if (Reader( pfd[0], curdmrc, len + 1 ) == len + 1) - err = GE_Ok; - else { - free( curdmrc ); - curdmrc = 0; - } - } - } - close( pfd[0] ); - (void)Wait4( pid ); - return err; -} |