From 8b95f0279ddf0d35141ed5bf7aa348b2b761aebc Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Wed, 4 Nov 2015 15:17:55 -0500 Subject: Get the new lockscreen all setup and (somewhat) functional in the screensaver. Also setup the screensaver so that the "--test-ss" option makes it fully-functional even if the WM event handler is not installed for valid testing). The *only* thing which is still broken is that PAM is allowing all passwords for the user to unlock the system (probably some kind of password cache for the current credentials?). Still need to find some way to register a "lock" with PAM so that it forces the validation of the user's login credentials again. --- lumina-wm-INCOMPLETE/LLockScreen.cpp | 157 +++++++++++++++++++++++++++++++++++ 1 file changed, 157 insertions(+) create mode 100644 lumina-wm-INCOMPLETE/LLockScreen.cpp (limited to 'lumina-wm-INCOMPLETE/LLockScreen.cpp') diff --git a/lumina-wm-INCOMPLETE/LLockScreen.cpp b/lumina-wm-INCOMPLETE/LLockScreen.cpp new file mode 100644 index 00000000..3778042f --- /dev/null +++ b/lumina-wm-INCOMPLETE/LLockScreen.cpp @@ -0,0 +1,157 @@ +//=========================================== +// Lumina-DE source code +// Copyright (c) 2015, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +#include "LLockScreen.h" +#include "ui_LLockScreen.h" + +//Standard C libary for username/system fetch +#include +//#include + +//PAM libraries +#include +#include +#include +//#include +//#include +//#include + +#define DEBUG 1 + +LLockScreen::LLockScreen(QWidget *parent) : QWidget(parent), ui(new Ui::LLockScreen()){ + ui->setupUi(this); + waittime = new QTimer(this); + waittime->setInterval(300000); //5 minutes (too many attempts in short time) + waittime->setSingleShot(true); + connect(ui->tool_unlock, SIGNAL(clicked()), this, SLOT(TryUnlock()) ); + connect(ui->line_password, SIGNAL(returnPressed()), this, SLOT(TryUnlock()) ); + connect(ui->line_password, SIGNAL(textEdited(QString)), this, SIGNAL(InputDetected()) ); + connect(ui->line_password, SIGNAL(cursorPositionChanged(int,int)), this, SIGNAL(InputDetected()) ); + connect(waittime, SIGNAL(timeout()), this, SLOT(aboutToShow()) ); +} + +LLockScreen::~LLockScreen(){ + +} + +void LLockScreen::LoadSystemDetails(){ + //Run every time the screen is initially locked + QString user = QString(getlogin()); + ui->label_username->setText( QString(tr("Locked by: %1")).arg(user) ); + ui->label_hostname->setText( QHostInfo::localHostName() ); + ui->tool_unlock->setIcon( LXDG::findIcon("document-decrypt","") ); + attempts = 0; + bool ok = PAM_lockSession(user); + qDebug() << "Closed PAM session:" << ok; +} + +void LLockScreen::aboutToHide(){ + //auto-hide timeout - clear display + ui->line_password->clear(); + ui->line_password->clearFocus(); + if(!waittime->isActive()){ ui->label_info->clear(); } //could be obsolete the next time the lock screen is shown + +} + +void LLockScreen::aboutToShow(){ + if(!waittime->isActive()){ + ui->label_info->setText( PAM_checkLockInfo( QString(getlogin()) ) ); + this->setEnabled(true); + triesleft = 4; //back to initial number of tries + } + ui->line_password->clear(); + ui->line_password->setFocus(); +} + +// ================= +// PRIVATE +// ================= +// PAM structures for the functions below +static struct pam_conv pamc = { openpam_nullconv, NULL }; +pam_handle_t *pamh; + +bool LLockScreen::PAM_checkpass(QString user, QString pass, QString &info){ + //Convert the inputs to C character arrays for use in PAM + if(DEBUG){qDebug() << "Check Password w/PAM:" << user << pass;} + QByteArray tmp2 = pass.toUtf8(); + char* cPassword = tmp2.data(); + //initialize variables + bool result = false; + //Place the user-supplied password into the structure + int ret = pam_set_item(pamh, PAM_AUTHTOK, cPassword); + //Set the TTY + //Authenticate with PAM + ret = pam_authenticate(pamh,0); + if( ret == PAM_SUCCESS ){ + //Check for valid, unexpired account and verify access restrictions + ret = pam_acct_mgmt(pamh,0); + if( ret == PAM_SUCCESS ){ + result = true; + ret = pam_setcred(pamh,PAM_REINITIALIZE_CRED); + ret = pam_end(pamh,ret); + }else{ info = PAM_getError(ret); } + }else{ + info = PAM_getError(ret); + } + if(DEBUG){ qDebug() << " - Result:" << result << ret; } + //return verification result + return result; +} + +QString LLockScreen::PAM_checkLockInfo(QString user){ + //Return info string with any account lock/reset info + return ""; //not implemented yet +} + +QString LLockScreen::PAM_getError(int ret){ + QString err; + //Interpret a PAM error message and log it + //qWarning() << "PAM Error: " << ret; + switch( ret ){ + case PAM_MAXTRIES: + err = tr("Too Many Failures: Try again later."); + break; + case PAM_NEW_AUTHTOK_REQD: + err = tr("Password Expired: Contact System Admin"); + break; + default: + triesleft--; + if(triesleft>0){ err = QString(tr("Failure: %1 Attempts Remaining")).arg( QString::number(triesleft) ); } + else{err = tr("Too Many Failures: Try again in 5 minutes"); } + if(DEBUG){ err.append("\n"+QString(pam_strerror(pamh, ret)) ); } + } + return err; +} + +bool LLockScreen::PAM_lockSession(QString user){ + QByteArray tmp = user.toUtf8(); + char* cUser = tmp.data(); + int ret = pam_start( user=="root" ? "system": "login", cUser, &pamc, &pamh); + //if(ret == PAM_SUCCESS){ ret = pam_setcred(pamh,PAM_DELETE_CRED); } + return (ret== PAM_SUCCESS); +} +// ================= +// PRIVATE SLOTS +// ================= +void LLockScreen::TryUnlock(){ + attempts++; + this->setEnabled(false); + QString pass = ui->line_password->text(); + ui->line_password->clear(); + QString user = QString(getlogin()); + QString info; + bool ok = PAM_checkpass(user, pass, info); + if(ok){ + emit ScreenUnlocked(); + this->setEnabled(true); + }else if(triesleft>1){ + this->setEnabled(true); + ui->label_info->setText(info); + }else{ + ui->label_info->setText(info); + waittime->start(); + } +} -- cgit