summaryrefslogtreecommitdiff
path: root/core/opie-login/loginwindowimpl.cpp
authorsandman <sandman>2002-07-27 22:43:37 (UTC)
committer sandman <sandman>2002-07-27 22:43:37 (UTC)
commitdac5c073c3e04ceb6900aeb72e53cf6d7350c3c9 (patch) (side-by-side diff)
treed8c522214a94a437ccd5339957ca64ac4779755c /core/opie-login/loginwindowimpl.cpp
parent9e728b734630d08ec5ee3ff695d1b66995a6d7c7 (diff)
downloadopie-dac5c073c3e04ceb6900aeb72e53cf6d7350c3c9.zip
opie-dac5c073c3e04ceb6900aeb72e53cf6d7350c3c9.tar.gz
opie-dac5c073c3e04ceb6900aeb72e53cf6d7350c3c9.tar.bz2
Initial checkin of the new opie-login
Just replace $OPIEDIR/bin/qpe with $OPIEDIR/bin/opie-login in /etc/init.d/opie
Diffstat (limited to 'core/opie-login/loginwindowimpl.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--core/opie-login/loginwindowimpl.cpp323
1 files changed, 323 insertions, 0 deletions
diff --git a/core/opie-login/loginwindowimpl.cpp b/core/opie-login/loginwindowimpl.cpp
new file mode 100644
index 0000000..3265b46
--- a/dev/null
+++ b/core/opie-login/loginwindowimpl.cpp
@@ -0,0 +1,323 @@
+#include <qapplication.h>
+#include <qpushbutton.h>
+#include <qlayout.h>
+#include <qframe.h>
+#include <qlineedit.h>
+#include <qtimer.h>
+#include <qcombobox.h>
+#include <qpixmap.h>
+#include <qlabel.h>
+#include <qpopupmenu.h>
+#include <qmessagebox.h>
+
+#include <qpe/qcopenvelope_qws.h>
+
+#include <opie/odevice.h>
+
+#include <stdio.h>
+
+#include <pwd.h>
+#include <grp.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#ifdef USEPAM
+extern "C" {
+#include <security/pam_appl.h>
+}
+#else
+#include <crypt.h>
+#include <shadow.h>
+#endif
+
+#include "loginwindowimpl.h"
+#include "inputmethods.h"
+
+LoginWindowImpl::LoginWindowImpl ( ) : LoginWindow ( 0, "LOGIN-WINDOW", WStyle_Customize | WStyle_NoBorder | WDestructiveClose )
+{
+ QPopupMenu *pop = new QPopupMenu ( this );
+ pop-> insertItem ( tr( "Restart" ), this, SLOT( restart ( )));
+ m_menu-> setPopup ( pop );
+
+ QHBoxLayout *lay = new QHBoxLayout ( m_taskbar, 4, 4 );
+ m_input = new InputMethods ( m_taskbar );
+ lay-> addWidget ( m_input );
+ lay-> addStretch ( 10 );
+
+ setActiveWindow ( );
+ m_password-> setFocus ( );
+
+ m_user-> insertStringList ( getAllUsers ( ));
+
+ QTimer::singleShot ( 0, this, SLOT( showIM ( )));
+
+ QString opiedir = ::getenv ( "OPIEDIR" );
+ QPixmap bgpix ( opiedir + "/pics/launcher/opie-background.jpg" );
+
+ if ( !bgpix. isNull ( ))
+ setBackgroundPixmap ( bgpix );
+
+ m_caption-> setText ( m_caption-> text ( ) + tr( "<center><h1><u>%1 %2</u></h1></center>" ). arg ( ODevice::inst ( )-> systemString ( )). arg ( ODevice::inst ( )-> systemVersionString ( )));
+}
+
+LoginWindowImpl::~LoginWindowImpl ( )
+{
+}
+
+void LoginWindowImpl::keyPressEvent ( QKeyEvent *e )
+{
+ switch ( e-> key ( )) {
+ case Key_F34: suspend ( );
+ break;
+ case Key_F35: backlight ( );
+ break;
+ default : e-> ignore ( );
+ break;
+ }
+ LoginWindow::keyPressEvent ( e );
+}
+
+
+void LoginWindowImpl::toggleEchoMode ( bool t )
+{
+ m_password-> setEchoMode ( t ? QLineEdit::Normal : QLineEdit::Password );
+}
+
+QStringList LoginWindowImpl::getAllUsers ( )
+{
+ 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 LoginWindowImpl::showIM ( )
+{
+ m_input-> showInputMethod ( );
+}
+
+void LoginWindowImpl::restart ( )
+{
+ qApp-> quit ( );
+}
+
+void LoginWindowImpl::suspend ( )
+{
+ system ( "apm -s" );
+ usleep ( 1 * 1000 * 1000 );
+ {
+ QCopEnvelope e("QPE/System", "setBacklight(int)");
+ e << -3; // Force on
+ }
+}
+
+void LoginWindowImpl::backlight ( )
+{
+ {
+ QCopEnvelope e("QPE/System", "setBacklight(int)");
+ e << -2; // toggle
+ }
+}
+
+#ifdef USEPAM
+
+static const char *_PAM_SERVICE = "xdm";
+static const char *PAM_password;
+
+typedef const struct pam_message pam_message_type;
+
+static int PAM_conv( int, pam_message_type **, struct pam_response **, void * );
+
+static struct pam_conv PAM_conversation = {
+ &PAM_conv,
+ NULL
+};
+
+//----------------------------------------------------------------------------
+
+static char *COPY_STRING( const char * s ) {
+ return (s) ? strdup(s) : (char *)NULL;
+}
+
+#define GET_MEM if (reply) realloc(reply, size);\
+ else reply = (struct pam_response *)malloc(size); \
+ if (!reply) return PAM_CONV_ERR; \
+ size += sizeof(struct pam_response)
+
+
+static int PAM_conv( int num_msg, pam_message_type **msg,
+ struct pam_response **resp, void *)
+{
+ int count = 0, replies = 0;
+ struct pam_response *reply = NULL;
+ int size = sizeof(struct pam_response);
+
+ for( count = 0; count < num_msg; count++ ) {
+ switch (msg[count]->msg_style) {
+ case PAM_PROMPT_ECHO_ON:
+ /* user name given to PAM already */
+ return PAM_CONV_ERR;
+
+ case PAM_PROMPT_ECHO_OFF:
+ /* wants password */
+ GET_MEM;
+ reply[replies].resp_retcode = PAM_SUCCESS;
+ reply[replies].resp = COPY_STRING(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;
+}
+
+
+static bool pwcheck_PAM( const char *user, const char *password )
+{
+ bool pw_correct = false;
+ int pam_error;
+ int pam_return = 0;
+ pam_handle_t *pamh = 0;
+ PAM_password = password;
+
+ pam_error = pam_start( _PAM_SERVICE, user, &PAM_conversation, &pamh );
+ if( pam_error == PAM_SUCCESS ) {
+ pam_error = pam_authenticate( pamh, 0 );
+ if( pam_error == PAM_SUCCESS ) {
+ //-- password correct
+ pw_correct = true;
+ pam_return = PAM_SUCCESS;
+ } else {
+ pam_return = pam_error;
+ }
+ } else {
+ // cerr << "PAM error: " << pam_strerror( pamh, pam_error ) << endl;
+ }
+ pam_end( pamh, pam_return );
+ return pw_correct;
+}
+
+#else
+
+//----------------------------------------------------------------------------
+
+static bool pwcheck_Unix( 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 LoginWindowImpl::changeIdentity ( const char *user )
+{
+ const char *DEFAULT_LOGIN_PATH = "/bin:/usr/bin";
+ const char *DEFAULT_ROOT_LOGIN_PATH = "/usr/sbin:/bin:/usr/bin:/sbin";
+
+ bool fail = false;
+ struct passwd *pw = getpwnam ( user );
+
+ fail |= ( pw == 0 );
+ printf ( "1 %d\n", fail );
+ fail |= ( initgroups ( pw-> pw_name, pw-> pw_gid ));
+ endgrent ( );
+ printf ( "2 %d\n", fail );
+ fail |= ( setgid ( pw-> pw_gid ));
+ printf ( "3 %d\n", fail );
+ fail |= ( setuid ( pw-> pw_uid ));
+
+ printf ( "4 %d\n", fail );
+ fail |= ( chdir ( pw-> pw_dir ) && chdir ( "/" ));
+
+ printf ( "5 %d\n", fail );
+ fail |= ( setenv ( "HOME", pw-> pw_dir, 1 ));
+ printf ( "6 %d\n", fail );
+ fail |= ( setenv ( "SHELL", pw-> pw_shell, 1 ));
+ printf ( "7 %d\n", fail );
+ fail |= ( setenv ( "USER", pw-> pw_name, 1 ));
+ printf ( "8 %d\n", fail );
+ fail |= ( setenv ( "LOGNAME", pw-> pw_name, 1 ));
+ printf ( "9 %d\n", fail );
+ fail |= ( setenv ( "PATH", ( pw-> pw_uid ? DEFAULT_LOGIN_PATH : DEFAULT_ROOT_LOGIN_PATH ), 1 ));
+ printf ( "10 %d\n", fail );
+
+ return !fail;
+}
+
+void LoginWindowImpl::login ( )
+{
+ const char *user = strdup ( m_user-> currentText ( ). local8Bit ( ));
+ const char *pass = strdup ( m_password-> text ( ). local8Bit ( ));
+ bool ok;
+
+ if ( !user || !user [0] )
+ return;
+ if ( !pass )
+ pass = "";
+
+#if defined( USEPAM )
+ ok = pwcheck_PAM ( user, pass );
+#else
+ ok = pwcheck_Unix ( user, pass );
+#endif
+
+ if ( ok ) {
+ if ( changeIdentity ( user )) {
+ QString opie = getenv ( "OPIEDIR" );
+ opie += "/bin/qpe";
+
+ execl ( opie. latin1 ( ), "qpe", 0 );
+
+ QMessageBox::critical ( this, tr( "Failure" ), tr( "Could not start OPIE." ));
+ restart ( );
+ }
+ else {
+ QMessageBox::critical ( this, tr( "Failure" ), tr( "Could not switch to new user identity" ));
+ restart ( );
+ }
+ }
+ else {
+ QMessageBox::warning ( this, tr( "Wrong password" ), tr( "The given password is incorrect." ));
+ m_password-> clear ( );
+ }
+}