From 62c946c5a92ab11b5ad9495ff0bab158d38bce48 Mon Sep 17 00:00:00 2001 From: sandman Date: Mon, 14 Oct 2002 00:59:28 +0000 Subject: - last login name is saved - wait image should be displayed right now - the qApp object is destroyed before the launcher is started -- this should prevent some semaphore permission problems - added a (very basic) crash handler - added a simple "respawned too fast" detection in case of qt/e fb problems - if opie-login is started with -a or --autologin it doesn't prompt for a username/password - instead it loads qpe directly using the specified user account So even if you are not running multiuser, you should now start qpe with: opie-login --autologin=root --- (limited to 'core/opie-login/loginapplication.cpp') diff --git a/core/opie-login/loginapplication.cpp b/core/opie-login/loginapplication.cpp new file mode 100644 index 0000000..cd58c47 --- a/dev/null +++ b/core/opie-login/loginapplication.cpp @@ -0,0 +1,193 @@ +#include +#include +#include +#include +#include + +#ifdef USEPAM +extern "C" { +#include +} +#else +#include +#include +#endif + +#include "loginapplication.h" + +LoginApplication *lApp; + +LoginApplication::LoginApplication ( int &argc, char **argv ) + : QPEApplication ( argc, argv, GuiServer ) +{ + lApp = this; +} + +const char *LoginApplication::s_username = 0; + +#ifdef USEPAM + +const char *LoginApplication::s_pam_password = 0; + +int LoginApplication::pam_helper ( int num_msg, const struct pam_message **msg, struct pam_response **resp, void * ) +{ + int replies = 0; + struct pam_response *reply = 0; + int size = sizeof( struct pam_response ); + + for ( int i = 0; i < num_msg; i++ ) { + switch ( msg [i]-> msg_style ) { + case PAM_PROMPT_ECHO_ON: // user name given to PAM already + return PAM_CONV_ERR; + + case PAM_PROMPT_ECHO_OFF: // wants password + reply = (struct pam_response *) ::realloc ( reply, size ); + if ( !reply ) + return PAM_CONV_ERR; + size += sizeof( struct pam_response ); + + reply [replies]. resp_retcode = PAM_SUCCESS; + reply [replies]. resp = ::strdup ( s_pam_password ); + replies++; // PAM frees resp + break; + + case PAM_TEXT_INFO: + break; + + default: + /* unknown or PAM_ERROR_MSG */ + if ( reply ) + ::free ( reply ); + return PAM_CONV_ERR; + } + } + if ( reply ) + *resp = reply; + return PAM_SUCCESS; +} + + +bool LoginApplication::checkPassword ( const char *user, const char *pass ) +{ + static struct pam_conv conv = { &LoginApplication::pam_helper, 0 }; + + int pam_error; + pam_handle_t *pamh = 0; + + pam_error = ::pam_start( "xdm", user, &conv, &pamh ); + if ( pam_error == PAM_SUCCESS ) { + s_pam_password = pass; + pam_error = ::pam_authenticate ( pamh, 0 ); + s_pam_password = 0; + } + ::pam_end ( pamh, pam_error ); + return ( pam_error == PAM_SUCCESS ); +} + +#else + +bool LoginApplication::checkPassword ( const char *user, const char *pass ) +{ + char *encrypted, *correct; + struct passwd *pw; + + if ( !user || !pass ) + return false; + + pw = ::getpwnam ( user ); + + if ( !pw ) + return false; + + if (( ::strcmp ( pw-> pw_passwd, "x" ) == 0 ) || ( ::strcmp ( pw-> pw_passwd, "*" ) == 0 )) { + struct spwd *sp = ::getspnam ( pw-> pw_name ); + + if ( !sp ) + return false; + + correct = sp-> sp_pwdp; + } + else + correct = pw-> pw_passwd; + + if ( correct == 0 || correct[0] == '\0' ) + return true; + + encrypted = ::crypt ( pass, correct ); + return ( ::strcmp ( encrypted, correct ) == 0 ); +} + +#endif + +bool LoginApplication::changeIdentity ( ) +{ + const char *DEFAULT_LOGIN_PATH = "/bin:/usr/bin"; + const char *DEFAULT_ROOT_LOGIN_PATH = "/usr/sbin:/bin:/usr/bin:/sbin"; + + if ( !s_username ) + return false; + struct passwd *pw = ::getpwnam ( s_username ); + if ( !pw ) + return false; + + bool fail = false; + fail |= ( ::initgroups ( pw-> pw_name, pw-> pw_gid )); + ::endgrent ( ); + fail |= ( ::setgid ( pw-> pw_gid )); + fail |= ( ::setuid ( pw-> pw_uid )); + + fail |= ( ::chdir ( pw-> pw_dir ) && ::chdir ( "/" )); + + fail |= ( ::setenv ( "HOME", pw-> pw_dir, 1 )); + fail |= ( ::setenv ( "SHELL", pw-> pw_shell, 1 )); + fail |= ( ::setenv ( "USER", pw-> pw_name, 1 )); + fail |= ( ::setenv ( "LOGNAME", pw-> pw_name, 1 )); + fail |= ( ::setenv ( "PATH", ( pw-> pw_uid ? DEFAULT_LOGIN_PATH : DEFAULT_ROOT_LOGIN_PATH ), 1 )); + + return !fail; +} + +bool LoginApplication::login ( ) +{ + char *opie = ::getenv ( "OPIEDIR" ); + char *arg = new char [::strlen ( opie ) + 8 + 1]; + + ::strcpy ( arg, opie ); + ::strcat ( arg, "/bin/qpe" ); + + // start qpe via a login shell + ::execl ( "/bin/sh", "-sh", "-c", arg, 0 ); + + return false; +} + +const char *LoginApplication::loginAs ( ) +{ + return s_username; +} + +void LoginApplication::setLoginAs ( const char *name ) +{ + s_username = name; +} + +QStringList LoginApplication::allUsers ( ) +{ + struct passwd *pwd; + QStringList sl; + + while (( pwd = ::getpwent ( ))) { + if (( pwd-> pw_uid == 0 ) || ( pwd-> pw_uid >= 500 && pwd-> pw_uid < 65534 )) + sl << QString ( pwd-> pw_name ); + } + + ::endpwent ( ); + + return sl; +} + +void LoginApplication::quitToConsole ( ) +{ + QPEApplication::quit ( ); + ::kill ( ::getppid ( ), SIGTERM ); +} -- cgit v0.9.0.2