From ff7322912780843dfb3bce1d720452aeed89592e Mon Sep 17 00:00:00 2001 From: tpearson Date: Thu, 15 Sep 2011 19:17:28 +0000 Subject: [PATCH] Add secure desktop area dialog to kdebase git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdebase@1253853 283d02a7-25f6-0310-bc7c-ecb5cbfe19da --- kdesktop/lock/CMakeLists.txt | 2 +- kdesktop/lock/lockprocess.cc | 100 ++++++++++++++---- kdesktop/lock/lockprocess.h | 4 + kdesktop/lock/main.cc | 21 +++- kdesktop/lock/securedlg.cc | 194 +++++++++++++++++++++++++++++++++++ kdesktop/lock/securedlg.h | 66 ++++++++++++ kdesktop/lockeng.cc | 44 +++++++- kdesktop/lockeng.h | 9 +- 8 files changed, 416 insertions(+), 24 deletions(-) create mode 100644 kdesktop/lock/securedlg.cc create mode 100644 kdesktop/lock/securedlg.h diff --git a/kdesktop/lock/CMakeLists.txt b/kdesktop/lock/CMakeLists.txt index 216c9ae9f..ee5580cdb 100644 --- a/kdesktop/lock/CMakeLists.txt +++ b/kdesktop/lock/CMakeLists.txt @@ -30,7 +30,7 @@ set( target kdesktop_lock ) set( ${target}_SRCS lockprocess.cc lockdlg.cc infodlg.cc querydlg.cc sakdlg.cc - autologout.cc main.cc + securedlg.cc autologout.cc main.cc ) tde_add_executable( ${target} AUTOMOC diff --git a/kdesktop/lock/lockprocess.cc b/kdesktop/lock/lockprocess.cc index 17de269bf..6b708801b 100644 --- a/kdesktop/lock/lockprocess.cc +++ b/kdesktop/lock/lockprocess.cc @@ -23,6 +23,7 @@ #include "infodlg.h" #include "querydlg.h" #include "sakdlg.h" +#include "securedlg.h" #include "autologout.h" #include "kdesktopsettings.h" @@ -135,6 +136,7 @@ extern bool trinity_desktop_lock_forced; bool trinity_desktop_lock_autohide_lockdlg = TRUE; bool trinity_desktop_lock_closing_windows = FALSE; +bool trinity_desktop_lock_in_sec_dlg = FALSE; #define ENABLE_CONTINUOUS_LOCKDLG_DISPLAY \ if (!mForceContinualLockDisplayTimer->isActive()) mForceContinualLockDisplayTimer->start(100, FALSE); \ @@ -174,6 +176,7 @@ LockProcess::LockProcess(bool child, bool useBlankOnly) mEnsureVRootWindowSecurityTimer(NULL), mHackDelayStartupTimer(NULL), mHackDelayStartupTimeout(0), + mHackStartupEnabled(true), m_startupStatusDialog(NULL) { setupSignals(); @@ -191,6 +194,7 @@ LockProcess::LockProcess(bool child, bool useBlankOnly) connect( mEnsureVRootWindowSecurityTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(repaintRootWindowIfNeeded()) ); mHackDelayStartupTimeout = trinity_desktop_lock_delay_screensaver_start?KDesktopSettings::timeout()*1000:10*1000; + mHackStartupEnabled = trinity_desktop_lock_delay_screensaver_start?KDesktopSettings::screenSaverEnabled():true; // Get root window size XWindowAttributes rootAttr; @@ -323,6 +327,9 @@ bool LockProcess::closeCurrentWindow() if (dynamic_cast(currentDialog)) { dynamic_cast(currentDialog)->closeDialogForced(); } + else if (dynamic_cast(currentDialog)) { + dynamic_cast(currentDialog)->closeDialogForced(); + } else { currentDialog->close(); } @@ -390,7 +397,7 @@ void LockProcess::checkPipe() mDialogControlLock = true; if (currentDialog != NULL) { mForceReject = true; - currentDialog->close(); + closeCurrentWindow(); } mDialogControlLock = false; } @@ -403,7 +410,7 @@ void LockProcess::checkPipe() mDialogControlLock = true; if (currentDialog != NULL) { mForceReject = true; - currentDialog->close(); + closeCurrentWindow(); } mDialogControlLock = false; // Display info message dialog @@ -424,7 +431,7 @@ void LockProcess::checkPipe() mDialogControlLock = true; if (currentDialog != NULL) { mForceReject = true; - currentDialog->close(); + closeCurrentWindow(); } mDialogControlLock = false; // Display info message dialog @@ -448,7 +455,7 @@ void LockProcess::checkPipe() mDialogControlLock = true; if (currentDialog != NULL) { mForceReject = true; - currentDialog->close(); + closeCurrentWindow(); } mDialogControlLock = false; // Display query dialog @@ -579,6 +586,62 @@ void LockProcess::quitSaver() kapp->quit(); } +//--------------------------------------------------------------------------- +void LockProcess::startSecureDialog() +{ + int ret; + SecureDlg inDlg( this ); + inDlg.setRetInt(&ret); + mBusy = true; + execDialog( &inDlg ); + mBusy = false; + trinity_desktop_lock_in_sec_dlg = false; + if (ret == 0) { + kapp->quit(); + } + if (ret == 1) { + // In case of a forced lock we don't react to events during + // the dead-time to give the screensaver some time to activate. + // That way we don't accidentally show the password dialog before + // the screensaver kicks in because the user moved the mouse after + // selecting "lock screen", that looks really untidy. + mBusy = true; + if (startLock()) + { + if (trinity_desktop_lock_delay_screensaver_start) { + mBusy = false; + } + else { + TQTimer::singleShot(1000, this, TQT_SLOT(slotDeadTimePassed())); + } + return; + } + stopSaver(); + mBusy = false; + } + // FIXME + // Handle remaining two cases (task manager and logoff menu) + stopSaver(); +} + +bool LockProcess::runSecureDialog() +{ + m_startupStatusDialog = new KSMModalDialog(this); + m_startupStatusDialog->setStatusMessage(i18n("Securing desktop session").append("...")); + m_startupStatusDialog->show(); + m_startupStatusDialog->setActiveWindow(); + tqApp->processEvents(); + + trinity_desktop_lock_in_sec_dlg = true; + if (startSaver()) { + TQTimer::singleShot(0, this, TQT_SLOT(startSecureDialog())); + return true; + } + else { + return false; + } +} + //--------------------------------------------------------------------------- // // Read and apply configuration. @@ -1029,7 +1092,7 @@ bool LockProcess::startSaver() raise(); XSync(qt_xdisplay(), False); setVRoot( winId(), winId() ); - if (!(trinity_desktop_lock_delay_screensaver_start && trinity_desktop_lock_forced)) { + if (!(trinity_desktop_lock_delay_screensaver_start && (trinity_desktop_lock_forced || trinity_desktop_lock_in_sec_dlg))) { if (backingPixmap.isNull()) setBackgroundColor(black); else @@ -1046,12 +1109,14 @@ bool LockProcess::startSaver() TQTimer::singleShot( 0, this, SLOT(slotPaintBackground()) ); } - if (trinity_desktop_lock_delay_screensaver_start && trinity_desktop_lock_forced && trinity_desktop_lock_use_system_modal_dialogs) { - ENABLE_CONTINUOUS_LOCKDLG_DISPLAY - mHackDelayStartupTimer->start(mHackDelayStartupTimeout, TRUE); - } - else { - startHack(); + if (trinity_desktop_lock_in_sec_dlg == FALSE) { + if (trinity_desktop_lock_delay_screensaver_start && trinity_desktop_lock_forced && trinity_desktop_lock_use_system_modal_dialogs) { + ENABLE_CONTINUOUS_LOCKDLG_DISPLAY + if (mHackStartupEnabled) mHackDelayStartupTimer->start(mHackDelayStartupTimeout, TRUE); + } + else { + startHack(); + } } return true; } @@ -1309,7 +1374,7 @@ void LockProcess::hackExited(KProcess *) if (!mSuspended) { if (trinity_desktop_lock_use_system_modal_dialogs) { ENABLE_CONTINUOUS_LOCKDLG_DISPLAY - mHackDelayStartupTimer->start(mHackDelayStartupTimeout, TRUE); + if (mHackStartupEnabled) mHackDelayStartupTimer->start(mHackDelayStartupTimeout, TRUE); } } } @@ -1339,7 +1404,7 @@ void LockProcess::suspend() mSuspended = true; stopHack(); ENABLE_CONTINUOUS_LOCKDLG_DISPLAY - mHackDelayStartupTimer->start(mHackDelayStartupTimeout, TRUE); + if (mHackStartupEnabled) mHackDelayStartupTimer->start(mHackDelayStartupTimeout, TRUE); } else { TQString hackStatus; @@ -1350,8 +1415,7 @@ void LockProcess::suspend() char hackstat[8192]; FILE *fp = fopen(TQString("/proc/%1/stat").arg(mHackProc.pid()).ascii(),"r"); if (fp != NULL) { - if (fgets (hackstat, 8192, fp) != NULL) - puts(hackstat); + fgets (hackstat, 8192, fp); fclose (fp); } hackstat[8191] = 0; @@ -1372,7 +1436,7 @@ void LockProcess::suspend() void LockProcess::resume( bool force ) { - if (trinity_desktop_lock_use_sak && mHackDelayStartupTimer->isActive()) { + if (trinity_desktop_lock_use_sak && (mHackDelayStartupTimer->isActive() || !mHackStartupEnabled)) { return; } if( !force && (!mDialogs.isEmpty() || !mVisibility )) { @@ -1617,7 +1681,7 @@ bool LockProcess::x11Event(XEvent *event) // fall through case KeyPress: if ((mHackDelayStartupTimer) && (mHackDelayStartupTimer->isActive())) { - mHackDelayStartupTimer->start(mHackDelayStartupTimeout, TRUE); + if (mHackStartupEnabled) mHackDelayStartupTimer->start(mHackDelayStartupTimeout, TRUE); } if (mBusy || !mDialogs.isEmpty()) break; @@ -1625,7 +1689,7 @@ bool LockProcess::x11Event(XEvent *event) if (trinity_desktop_lock_delay_screensaver_start) { if (mLocked) { ENABLE_CONTINUOUS_LOCKDLG_DISPLAY - mHackDelayStartupTimer->start(mHackDelayStartupTimeout, TRUE); + if (mHackStartupEnabled) mHackDelayStartupTimer->start(mHackDelayStartupTimeout, TRUE); } if (!mLocked) { diff --git a/kdesktop/lock/lockprocess.h b/kdesktop/lock/lockprocess.h index 88d84dde2..1b5fa9fbf 100644 --- a/kdesktop/lock/lockprocess.h +++ b/kdesktop/lock/lockprocess.h @@ -55,6 +55,8 @@ public: bool dontLock(); + bool runSecureDialog(); + void setChildren(TQValueList children) { child_sockets = children; } void setParent(int fd) { mParent = fd; } @@ -88,6 +90,7 @@ private slots: void closeDialogAndStartHack(); bool closeCurrentWindow(); void repaintRootWindowIfNeeded(); + void startSecureDialog(); private: void configure(); @@ -180,6 +183,7 @@ private: TQTimer* mHackDelayStartupTimer; int mHackDelayStartupTimeout; + bool mHackStartupEnabled; TQPixmap backingPixmap; diff --git a/kdesktop/lock/main.cc b/kdesktop/lock/main.cc index 587ad49db..1d459a0d3 100644 --- a/kdesktop/lock/main.cc +++ b/kdesktop/lock/main.cc @@ -29,6 +29,8 @@ #include #include +#include + #include #include @@ -60,6 +62,7 @@ static KCmdLineOptions options[] = { { "forcelock", I18N_NOOP("Force session locking"), 0 }, { "dontlock", I18N_NOOP("Only start screensaver"), 0 }, + { "securedialog", I18N_NOOP("Launch the secure dialog"), 0 }, { "blank", I18N_NOOP("Only use the blank screensaver"), 0 }, KCmdLineLastOption }; @@ -169,12 +172,24 @@ int main( int argc, char **argv ) rt = process.lock(); sig = true; } - else if( child || args->isSet( "dontlock" )) + else if( child || args->isSet( "dontlock" )) { rt = process.dontLock(); - else + } + else if( child || args->isSet( "securedialog" )) { + int retcode = tde_sak_verify_calling_process(); + if (retcode == 0) { + rt = process.runSecureDialog(); + } + else { + return 1; + } + } + else { rt = process.defaultSave(); - if (!rt) + } + if (!rt) { return 1; + } if( sig ) { diff --git a/kdesktop/lock/securedlg.cc b/kdesktop/lock/securedlg.cc new file mode 100644 index 000000000..2f6ecc7a4 --- /dev/null +++ b/kdesktop/lock/securedlg.cc @@ -0,0 +1,194 @@ +//=========================================================================== +// +// This file is part of the KDE project +// +// Copyright (c) 2010-2011 Timothy Pearson + +#include + +#include "securedlg.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#ifndef AF_LOCAL +# define AF_LOCAL AF_UNIX +#endif + +extern bool trinity_desktop_lock_use_system_modal_dialogs; +extern bool trinity_desktop_lock_use_sak; + +//=========================================================================== +// +// Simple dialog for displaying an unlock status or recurring error message +// +SecureDlg::SecureDlg(LockProcess *parent) + : TQDialog(parent, "information dialog", true, (trinity_desktop_lock_use_system_modal_dialogs?((WFlags)WStyle_StaysOnTop):((WFlags)WX11BypassWM))), + mUnlockingFailed(false), retInt(NULL) +{ + if (trinity_desktop_lock_use_system_modal_dialogs) { + // Signal that we do not want any window controls to be shown at all + Atom kde_wm_system_modal_notification; + kde_wm_system_modal_notification = XInternAtom(qt_xdisplay(), "_KDE_WM_MODAL_SYS_NOTIFICATION", False); + XChangeProperty(qt_xdisplay(), winId(), kde_wm_system_modal_notification, XA_INTEGER, 32, PropModeReplace, (unsigned char *) "TRUE", 1L); + } + setCaption(i18n("Secure Desktop Area")); + + frame = new TQFrame( this ); + if (trinity_desktop_lock_use_system_modal_dialogs) + frame->setFrameStyle( TQFrame::NoFrame ); + else + frame->setFrameStyle( TQFrame::Panel | TQFrame::Raised ); + frame->setLineWidth( 2 ); + + KSMModalDialogHeader* theader = new KSMModalDialogHeader( frame ); + + KUser user; + + mLogonStatus = new TQLabel( frame ); + mLogonStatus->setText(i18n("'%1' is currently logged on").arg( user.fullName() )); + + KSeparator *sep = new KSeparator( KSeparator::HLine, frame ); + + mLockButton = new TQPushButton( frame ); + mLockButton->setText(i18n("Lock Session")); + + mTaskButton = new TQPushButton( frame ); + mTaskButton->setText(i18n("Task Manager")); + mTaskButton->setEnabled(false); // FIXME + + mCancelButton = new TQPushButton( frame ); + mCancelButton->setText(i18n("Cancel")); + + mShutdownButton = new TQPushButton( frame ); + mShutdownButton->setText(i18n("Logoff Menu")); + mShutdownButton->setEnabled(false); // FIXME + + TQVBoxLayout *unlockDialogLayout = new TQVBoxLayout( this ); + unlockDialogLayout->addWidget( frame ); + + TQHBoxLayout *layStatus = new TQHBoxLayout( 0, 0, KDialog::spacingHint()); + layStatus->addWidget( mLogonStatus ); + + TQHBoxLayout *layPBRow1 = new TQHBoxLayout( 0, 0, KDialog::spacingHint()); + layPBRow1->addWidget( mLockButton ); + layPBRow1->addWidget( mTaskButton ); + layPBRow1->addWidget( mShutdownButton ); + layPBRow1->addWidget( mCancelButton ); + + frameLayout = new TQGridLayout( frame, 1, 1, KDialog::marginHint(), KDialog::spacingHint() ); + frameLayout->addMultiCellWidget( theader, 0, 0, 0, 1, Qt::AlignTop | AlignLeft ); + frameLayout->addMultiCellLayout( layStatus, 1, 1, 0, 1, AlignLeft | AlignVCenter); + frameLayout->addMultiCellWidget( sep, 2, 2, 0, 1 ); + frameLayout->addMultiCellLayout( layPBRow1, 3, 3, 0, 1, AlignLeft | AlignVCenter); + + connect(mCancelButton, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotBtnCancel())); + connect(mLockButton, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotBtnLock())); + connect(mTaskButton, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotBtnTask())); + connect(mShutdownButton, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotBtnShutdown())); + + TQSize dlgSz = sizeHint(); + int btnSize = dlgSz.width(); + btnSize = btnSize / 4; + btnSize = btnSize - (KDialog::spacingHint() / 2); + mLockButton->setFixedWidth(btnSize); + mTaskButton->setFixedWidth(btnSize); + mCancelButton->setFixedWidth(btnSize); + mShutdownButton->setFixedWidth(btnSize); + + installEventFilter(this); +} + +SecureDlg::~SecureDlg() +{ + hide(); +} + +void SecureDlg::slotBtnCancel() +{ + if (retInt) *retInt = 0; + hide(); +} + +void SecureDlg::slotBtnLock() +{ + if (retInt) *retInt = 1; + hide(); +} + +void SecureDlg::slotBtnTask() +{ + if (retInt) *retInt = 2; + hide(); +} + +void SecureDlg::slotBtnShutdown() +{ + if (retInt) *retInt = 3; + hide(); +} + +void SecureDlg::setRetInt(int *i) +{ + retInt = i; +} + +void SecureDlg::closeDialogForced() +{ + if (retInt) *retInt = 0; + TQDialog::reject(); +} + +void SecureDlg::reject() +{ + +} + +void SecureDlg::show() +{ + TQDialog::show(); + TQApplication::flushX(); +} + +#include "securedlg.moc" diff --git a/kdesktop/lock/securedlg.h b/kdesktop/lock/securedlg.h new file mode 100644 index 000000000..b9278d8d7 --- /dev/null +++ b/kdesktop/lock/securedlg.h @@ -0,0 +1,66 @@ +//=========================================================================== +// +// This file is part of the KDE project +// +// Copyright (c) 2010 Timothy Pearson +// + +#ifndef __SECUREDLG_H__ +#define __SECUREDLG_H__ + +#include +#include +#include + +#include "lockprocess.h" + +class TQFrame; +class TQGridLayout; +class TQLabel; +class KPushButton; +class TQListView; + +//=========================================================================== +// +// Simple dialog for displaying an info message. +// It does not handle password validation. +// +class SecureDlg : public TQDialog +{ + Q_OBJECT + +public: + SecureDlg(LockProcess *parent); + ~SecureDlg(); + virtual void show(); + + void closeDialogForced(); + void setRetInt(int *); + +private slots: + void slotBtnCancel(); + void slotBtnLock(); + void slotBtnTask(); + void slotBtnShutdown(); + +protected slots: + virtual void reject(); + +private: + TQFrame *frame; + TQGridLayout *frameLayout; + TQLabel *mLogonStatus; + TQButton *mCancelButton; + TQButton *mLockButton; + TQButton *mTaskButton; + TQButton *mShutdownButton; + int mCapsLocked; + bool mUnlockingFailed; + TQStringList layoutsList; + TQStringList::iterator currLayout; + int sPid, sFd; + int* retInt; +}; + +#endif + diff --git a/kdesktop/lockeng.cc b/kdesktop/lockeng.cc index af1207755..49be555f3 100644 --- a/kdesktop/lockeng.cc +++ b/kdesktop/lockeng.cc @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -26,6 +27,7 @@ #include "xautolock_c.h" extern xautolock_corner_t xautolock_corners[ 4 ]; +bool trinity_lockeng_sak_available = TRUE; //=========================================================================== // @@ -36,7 +38,8 @@ extern xautolock_corner_t xautolock_corners[ 4 ]; SaverEngine::SaverEngine() : KScreensaverIface(), TQWidget(), - mBlankOnly(false) + mBlankOnly(false), + mSAKProcess(NULL) { // Save X screensaver parameters XGetScreenSaver(qt_xdisplay(), &mXTimeout, &mXInterval, @@ -49,6 +52,12 @@ SaverEngine::SaverEngine() connect(&mLockProcess, TQT_SIGNAL(processExited(KProcess *)), TQT_SLOT(lockProcessExited())); + mSAKProcess = new KProcess; + *mSAKProcess << "kdmtsak"; + connect(mSAKProcess, TQT_SIGNAL(processExited(KProcess*)), this, TQT_SLOT(slotSAKProcessExited())); + + TQTimer::singleShot( 0, this, TQT_SLOT(handleSecureDialog()) ); + configure(); } @@ -189,6 +198,36 @@ bool SaverEngine::isBlanked() return (mState != Waiting); } +//--------------------------------------------------------------------------- +void SaverEngine::handleSecureDialog() +{ + // Wait for SAK press + mSAKProcess->start(); +} + +void SaverEngine::slotSAKProcessExited() +{ + int retcode = mSAKProcess->exitStatus(); + if (retcode != 0) trinity_lockeng_sak_available = FALSE; + + if (trinity_lockeng_sak_available == TRUE) { + bool ok = true; + if (mState == Waiting) + { + ok = startLockProcess( SecureDialog ); + if( ok && mState != Saving ) + { + } + } + else + { + mLockProcess.kill( SIGHUP ); + } + + TQTimer::singleShot( 0, this, TQT_SLOT(handleSecureDialog()) ); + } +} + //--------------------------------------------------------------------------- // // Read and apply configuration. @@ -263,6 +302,9 @@ bool SaverEngine::startLockProcess( LockType lock_type ) case DontLock: mLockProcess << TQString( "--dontlock" ); break; + case SecureDialog: + mLockProcess << TQString( "--securedialog" ); + break; default: break; } diff --git a/kdesktop/lockeng.h b/kdesktop/lockeng.h index 9b125985f..b1e31bda4 100644 --- a/kdesktop/lockeng.h +++ b/kdesktop/lockeng.h @@ -82,8 +82,12 @@ protected slots: void idleTimeout(); void lockProcessExited(); +private slots: + void handleSecureDialog(); + void slotSAKProcessExited(); + protected: - enum LockType { DontLock, DefaultLock, ForceLock }; + enum LockType { DontLock, DefaultLock, ForceLock, SecureDialog }; bool startLockProcess( LockType lock_type ); void stopLockProcess(); bool handleKeyPress(XKeyEvent *xke); @@ -107,6 +111,9 @@ protected: bool mBlankOnly; // only use the blanker, not the defined saver TQValueVector< DCOPClientTransaction* > mLockTransactions; + +private: + KProcess* mSAKProcess; }; #endif