summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTimothy Pearson <kb9vqf@pearsoncomputing.net>2015-09-17 17:30:17 -0500
committerTimothy Pearson <kb9vqf@pearsoncomputing.net>2015-09-17 17:30:17 -0500
commitce477303019c7f3ba18dcab48e4205d59614ce5a (patch)
tree19e49c43c92ba12de306af4f92f3fda64d9e92b8
parent5d20ad97bffa56b2e366989e71ac9429116c017d (diff)
downloadtdebase-ce477303019c7f3ba18dcab48e4205d59614ce5a.tar.gz
tdebase-ce477303019c7f3ba18dcab48e4205d59614ce5a.zip
Add initial cryptographic card login support
Tested with themed greeter and SAK disabled
-rw-r--r--kcheckpass/checkpass_pam.c16
-rw-r--r--kcontrol/hwmanager/devicepropsdlg.cpp16
-rw-r--r--kdesktop/lock/lockdlg.cc22
-rw-r--r--kdesktop/lock/lockdlg.h3
-rw-r--r--kdesktop/lock/lockprocess.cc154
-rw-r--r--kdesktop/lock/lockprocess.h10
-rw-r--r--kdesktop/lock/main.cc12
-rw-r--r--kdesktop/lockeng.cc82
-rw-r--r--kdesktop/lockeng.h5
-rw-r--r--tdm/CMakeLists.txt1
-rw-r--r--tdm/backend/client.c19
-rw-r--r--tdm/cryptocardwatcher/CMakeLists.txt32
-rw-r--r--tdm/cryptocardwatcher/main.cpp139
-rw-r--r--tdm/cryptocardwatcher/watcher.cc86
-rw-r--r--tdm/cryptocardwatcher/watcher.h40
-rw-r--r--tdm/kfrontend/CMakeLists.txt2
-rw-r--r--tdm/kfrontend/kgapp.cpp12
-rw-r--r--tdm/kfrontend/kgreeter.cpp72
-rw-r--r--tdm/kfrontend/kgreeter.h4
-rw-r--r--tdm/kfrontend/kgverify.cpp200
-rw-r--r--tdm/kfrontend/kgverify.h4
-rw-r--r--tdm/kfrontend/themer/tdmitem.cpp21
-rw-r--r--tdm/kfrontend/themer/tdmitem.h1
-rw-r--r--tdm/kfrontend/themer/tdmlabel.h6
-rw-r--r--tdm/kfrontend/themer/tdmthemer.cpp6
-rw-r--r--tdm/kfrontend/themer/tdmthemer.h1
-rw-r--r--tdm/kfrontend/themes/circles/circles.xml4
-rw-r--r--tdm/kfrontend/themes/minimalist/minimalist.xml4
-rw-r--r--tdm/kfrontend/themes/o2_enterprise/enterprise.xml4
-rw-r--r--tdmlib/dmctl.cpp88
-rw-r--r--tdmlib/kgreet_classic.cpp69
-rw-r--r--tdmlib/kgreet_classic.h3
-rw-r--r--tdmlib/kgreet_pam.cpp4
-rw-r--r--tdmlib/kgreet_pam.h1
-rw-r--r--tdmlib/kgreet_winbind.cpp4
-rw-r--r--tdmlib/kgreet_winbind.h1
-rw-r--r--tdmlib/kgreeterplugin.h8
37 files changed, 1006 insertions, 150 deletions
diff --git a/kcheckpass/checkpass_pam.c b/kcheckpass/checkpass_pam.c
index 7a35eedd..b11148ce 100644
--- a/kcheckpass/checkpass_pam.c
+++ b/kcheckpass/checkpass_pam.c
@@ -72,8 +72,20 @@ PAM_conv (int num_msg, pam_message_type **msg,
repl[count].resp = pd->conv(ConvGetNormal, msg[count]->msg);
break;
case PAM_PROMPT_ECHO_OFF:
- repl[count].resp =
- pd->conv(ConvGetHidden, pd->classic ? 0 : msg[count]->msg);
+ if (pd->classic) {
+ // WARNING
+ // This is far from foolproof, but it's the best we can do at this time...
+ // Try to detect PIN entry requests
+ if (strstr(msg[count]->msg, "PIN")) {
+ repl[count].resp = pd->conv(ConvGetHidden, msg[count]->msg);
+ }
+ else {
+ repl[count].resp = pd->conv(ConvGetHidden, 0);
+ }
+ }
+ else {
+ repl[count].resp = pd->conv(ConvGetHidden, msg[count]->msg);
+ }
break;
#ifdef PAM_BINARY_PROMPT
case PAM_BINARY_PROMPT:
diff --git a/kcontrol/hwmanager/devicepropsdlg.cpp b/kcontrol/hwmanager/devicepropsdlg.cpp
index a1ef81c2..9946ede6 100644
--- a/kcontrol/hwmanager/devicepropsdlg.cpp
+++ b/kcontrol/hwmanager/devicepropsdlg.cpp
@@ -779,8 +779,8 @@ void DevicePropertiesDialog::populateDeviceInformation() {
if (m_device->type() == TDEGenericDeviceType::CryptographicCard) {
TDECryptographicCardDevice* cdevice = static_cast<TDECryptographicCardDevice*>(m_device);
- connect(cdevice, TQT_SIGNAL(cardInserted()), this, TQT_SLOT(cryptographicCardInserted()));
- connect(cdevice, TQT_SIGNAL(cardRemoved()), this, TQT_SLOT(cryptographicCardRemoved()));
+ connect(cdevice, TQT_SIGNAL(cardInserted(TDECryptographicCardDevice*)), this, TQT_SLOT(cryptographicCardInserted()));
+ connect(cdevice, TQT_SIGNAL(cardRemoved(TDECryptographicCardDevice*)), this, TQT_SLOT(cryptographicCardRemoved()));
updateCryptographicCardStatusDisplay();
}
@@ -926,6 +926,7 @@ void DevicePropertiesDialog::cryptLUKSAddKey() {
unsigned int key_slot = lvi->text(0).toUInt();
bool allow_card = false;
bool use_card = false;
+ bool luks_card_key_modified = false;
KSSLCertificate* card_cert = NULL;
X509* card_cert_x509;
TQString disk_uuid = sdevice->diskUUID();
@@ -988,6 +989,7 @@ void DevicePropertiesDialog::cryptLUKSAddKey() {
// Use the secret key as the LUKS passcode
new_password = randomKey;
+ luks_card_key_modified = true;
}
else {
KMessageBox::error(this, i18n("<qt><b>Key creation failed</b><br>Please check that you have write access to /etc/trinity/luks/card and try again</qt>"), i18n("Key creation failure"));
@@ -1081,6 +1083,16 @@ void DevicePropertiesDialog::cryptLUKSAddKey() {
sdevice->cryptClearOperationsUnlockPassword();
KMessageBox::error(this, i18n("<qt><b>Key write failed</b><br>Please check the LUKS password and try again</qt>"), i18n("Key write failure"));
}
+ else {
+ if (luks_card_key_modified) {
+ if (KMessageBox::warningYesNo(this, i18n("<qt><b>You have created a new card-dependent key</b><br>Card-dependent keys work in conjunction with an encrypted key file stored on the host system.<br>When a card is used to boot, card-dependent keys must be updated in the initramfs image to become usable.<p>Would you like to update the initramfs image now?</qt>"), i18n("Update Required")) == KMessageBox::Yes) {
+ // Update the initramfs
+ if (system("update-initramfs -u -k all") != 0) {
+ KMessageBox::error(this, i18n("<qt><b>Initramfs update failed</b><br>Card-dependent keys may not be available for use until the root storage device is available / unlocked</qt>"), i18n("Initramfs update failure"));
+ }
+ }
+ }
+ }
}
}
}
diff --git a/kdesktop/lock/lockdlg.cc b/kdesktop/lock/lockdlg.cc
index e75ac2b1..827495c3 100644
--- a/kdesktop/lock/lockdlg.cc
+++ b/kdesktop/lock/lockdlg.cc
@@ -513,7 +513,17 @@ void PasswordDlg::handleVerify()
case ConvGetHidden:
if (!GRecvArr( &arr ))
break;
- greet->textPrompt( arr, false, false );
+ if (arr && (arr[0] != 0)) {
+ // Reset password entry and change text
+ greet->start();
+ greet->textPrompt( arr, false, false );
+ // Force relayout
+ setFixedSize( sizeHint().width(), sizeHint().height() + 1 );
+ setFixedSize( sizeHint() );
+ }
+ else {
+ greet->textPrompt( arr, false, false );
+ }
if (arr)
::free( arr );
return;
@@ -915,4 +925,14 @@ void PasswordDlg::capsLocked()
updateLabel();
}
+void PasswordDlg::attemptCardLogin() {
+ greet->start();
+ greet->next();
+}
+
+void PasswordDlg::resetCardLogin() {
+ greet->abort();
+ greet->start();
+}
+
#include "lockdlg.moc"
diff --git a/kdesktop/lock/lockdlg.h b/kdesktop/lock/lockdlg.h
index eea0931a..1bcb7567 100644
--- a/kdesktop/lock/lockdlg.h
+++ b/kdesktop/lock/lockdlg.h
@@ -49,6 +49,9 @@ class PasswordDlg : public TQDialog, public KGreeterPluginHandler
virtual void gplugStart();
virtual void gplugActivity();
virtual void gplugMsgBox( TQMessageBox::Icon type, const TQString &text );
+
+ virtual void attemptCardLogin();
+ virtual void resetCardLogin();
protected:
virtual void timerEvent(TQTimerEvent *);
diff --git a/kdesktop/lock/lockprocess.cc b/kdesktop/lock/lockprocess.cc
index aa951431..494852e3 100644
--- a/kdesktop/lock/lockprocess.cc
+++ b/kdesktop/lock/lockprocess.cc
@@ -34,6 +34,7 @@
#include <tdeapplication.h>
#include <kservicegroup.h>
#include <kdebug.h>
+#include <kuser.h>
#include <tdemessagebox.h>
#include <tdeglobalsettings.h>
#include <tdelocale.h>
@@ -112,6 +113,8 @@ Status DPMSInfo ( Display *, CARD16 *, BOOL * );
#include <GL/glx.h>
#endif
+#define KDESKTOP_DEBUG_ID 1204
+
#define LOCK_GRACE_DEFAULT 5000
#define AUTOLOGOUT_DEFAULT 600
@@ -146,7 +149,7 @@ Atom kde_wm_transparent_to_black = 0;
static void segv_handler(int)
{
- kdError(1204) << "A fatal exception was encountered."
+ kdError(KDESKTOP_DEBUG_ID) << "A fatal exception was encountered."
<< " Trapping and ignoring it so as not to compromise desktop security..."
<< kdBacktrace() << endl;
sleep(1);
@@ -272,7 +275,7 @@ LockProcess::LockProcess()
KServiceGroup::Ptr servGroup = KServiceGroup::baseGroup( "screensavers");
if (servGroup) {
relPath=servGroup->relPath();
- kdDebug(1204) << "relPath=" << relPath << endl;
+ kdDebug(KDESKTOP_DEBUG_ID) << "relPath=" << relPath << endl;
}
TDEGlobal::dirs()->addResourceType("scrsav",
TDEGlobal::dirs()->kde_default("apps") +
@@ -290,6 +293,19 @@ LockProcess::LockProcess()
}
}
+ // Initialize SmartCard readers
+ TDEGenericDevice *hwdevice;
+ TDEHardwareDevices *hwdevices = TDEGlobal::hardwareDevices();
+ TDEGenericHardwareList cardReaderList = hwdevices->listByDeviceClass(TDEGenericDeviceType::CryptographicCard);
+ for (hwdevice = cardReaderList.first(); hwdevice; hwdevice = cardReaderList.next()) {
+ TDECryptographicCardDevice* cdevice = static_cast<TDECryptographicCardDevice*>(hwdevice);
+ // connect(cdevice, SIGNAL(pinRequested(TQString,TDECryptographicCardDevice*)), this, SLOT(cryptographicCardPinRequested(TQString,TDECryptographicCardDevice*)));
+ connect(cdevice, TQT_SIGNAL(cardInserted(TDECryptographicCardDevice*)), this, TQT_SLOT(cryptographicCardInserted(TDECryptographicCardDevice*)));
+ connect(cdevice, TQT_SIGNAL(cardRemoved(TDECryptographicCardDevice*)), this, TQT_SLOT(cryptographicCardRemoved(TDECryptographicCardDevice*)));
+ cdevice->enableCardMonitoring(true);
+ // cdevice->enablePINEntryCallbacks(true);
+ }
+
#ifdef KEEP_MOUSE_UNGRABBED
setEnabled(false);
#endif
@@ -781,11 +797,11 @@ void LockProcess::readSaver()
TQStringList saverTypes = TQStringList::split(";", saverType);
for (uint i = 0; i < saverTypes.count(); i++) {
if ((saverTypes[i] == "ManipulateScreen") && !manipulatescreen) {
- kdDebug(1204) << "Screensaver is type ManipulateScreen and ManipulateScreen is forbidden" << endl;
+ kdDebug(KDESKTOP_DEBUG_ID) << "Screensaver is type ManipulateScreen and ManipulateScreen is forbidden" << endl;
mForbidden = true;
}
if ((saverTypes[i] == "OpenGL") && !opengl) {
- kdDebug(1204) << "Screensaver is type OpenGL and OpenGL is forbidden" << endl;
+ kdDebug(KDESKTOP_DEBUG_ID) << "Screensaver is type OpenGL and OpenGL is forbidden" << endl;
mForbidden = true;
}
if (saverTypes[i] == "OpenGL") {
@@ -794,7 +810,7 @@ void LockProcess::readSaver()
}
}
- kdDebug(1204) << "mForbidden: " << (mForbidden ? "true" : "false") << endl;
+ kdDebug(KDESKTOP_DEBUG_ID) << "mForbidden: " << (mForbidden ? "true" : "false") << endl;
if (trinity_desktop_lock_use_system_modal_dialogs) {
if (config.hasActionGroup("InWindow")) {
@@ -968,7 +984,7 @@ void LockProcess::createSaverWindow()
}
}
- kdDebug(1204) << "Saver window Id: " << winId() << endl;
+ kdDebug(KDESKTOP_DEBUG_ID) << "Saver window Id: " << winId() << endl;
}
void LockProcess::desktopResized()
@@ -1307,7 +1323,7 @@ bool LockProcess::startSaver(bool notify_ready)
{
if (!child_saver && !grabInput())
{
- kdWarning(1204) << "LockProcess::startSaver() grabInput() failed!!!!" << endl;
+ kdWarning(KDESKTOP_DEBUG_ID) << "LockProcess::startSaver() grabInput() failed!!!!" << endl;
return false;
}
mBusy = false;
@@ -1393,7 +1409,7 @@ bool LockProcess::startSaver(bool notify_ready)
//
void LockProcess::stopSaver()
{
- kdDebug(1204) << "LockProcess: stopping saver" << endl;
+ kdDebug(KDESKTOP_DEBUG_ID) << "LockProcess: stopping saver" << endl;
mHackProc.kill(SIGCONT);
stopHack();
mSuspended = false;
@@ -1446,30 +1462,30 @@ bool LockProcess::startLock()
GreeterPluginHandle plugin;
TQString path = KLibLoader::self()->findLibrary( ((*it)[0] == '/' ? *it : "kgreet_" + *it ).latin1() );
if (path.isEmpty()) {
- kdWarning(1204) << "GreeterPlugin " << *it << " does not exist" << endl;
+ kdWarning(KDESKTOP_DEBUG_ID) << "GreeterPlugin " << *it << " does not exist" << endl;
continue;
}
if (!(plugin.library = KLibLoader::self()->library( path.latin1() ))) {
- kdWarning(1204) << "Cannot load GreeterPlugin " << *it << " (" << path << ")" << endl;
+ kdWarning(KDESKTOP_DEBUG_ID) << "Cannot load GreeterPlugin " << *it << " (" << path << ")" << endl;
continue;
}
if (!plugin.library->hasSymbol( "kgreeterplugin_info" )) {
- kdWarning(1204) << "GreeterPlugin " << *it << " (" << path << ") is no valid greet widget plugin" << endl;
+ kdWarning(KDESKTOP_DEBUG_ID) << "GreeterPlugin " << *it << " (" << path << ") is no valid greet widget plugin" << endl;
plugin.library->unload();
continue;
}
plugin.info = (kgreeterplugin_info*)plugin.library->symbol( "kgreeterplugin_info" );
if (plugin.info->method && !mMethod.isEmpty() && mMethod != plugin.info->method) {
- kdDebug(1204) << "GreeterPlugin " << *it << " (" << path << ") serves " << plugin.info->method << ", not " << mMethod << endl;
+ kdDebug(KDESKTOP_DEBUG_ID) << "GreeterPlugin " << *it << " (" << path << ") serves " << plugin.info->method << ", not " << mMethod << endl;
plugin.library->unload();
continue;
}
if (!plugin.info->init( mMethod, getConf, this )) {
- kdDebug(1204) << "GreeterPlugin " << *it << " (" << path << ") refuses to serve " << mMethod << endl;
+ kdDebug(KDESKTOP_DEBUG_ID) << "GreeterPlugin " << *it << " (" << path << ") refuses to serve " << mMethod << endl;
plugin.library->unload();
continue;
}
- kdDebug(1204) << "GreeterPlugin " << *it << " (" << plugin.info->method << ", " << plugin.info->name << ") loaded" << endl;
+ kdDebug(KDESKTOP_DEBUG_ID) << "GreeterPlugin " << *it << " (" << plugin.info->method << ", " << plugin.info->name << ") loaded" << endl;
greetPlugin = plugin;
mLocked = true;
DM().setLock( true );
@@ -1588,7 +1604,7 @@ bool LockProcess::startHack()
if (!path.isEmpty()) {
mHackProc << path;
- kdDebug(1204) << "Starting hack: " << path << endl;
+ kdDebug(KDESKTOP_DEBUG_ID) << "Starting hack: " << path << endl;
while (!ts.atEnd()) {
ts >> word;
@@ -2297,10 +2313,10 @@ void LockProcess::stayOnTop()
// and stack others below it
Window* stack = new Window[ mDialogs.count() + mVkbdWindows.count() + 1 ];
int count = 0;
- for( TQValueList< VkbdWindow >::ConstIterator it = mVkbdWindows.begin(); it != mVkbdWindows.end(); ++it )
+ for( TQValueList< VkbdWindow >::ConstIterator it = mVkbdWindows.begin(); it != mVkbdWindows.end(); ++it ) {
stack[ count++ ] = (*it).id;
}
- for( TQValueList< TQWidget* >::ConstIterator it = mDialogs.begin(); it != mDialogs.end(); ++it )
+ for( TQValueList< TQWidget* >::ConstIterator it = mDialogs.begin(); it != mDialogs.end(); ++it ) {
stack[ count++ ] = (*it)->winId();
}
stack[ count++ ] = winId();
@@ -2795,6 +2811,110 @@ void LockProcess::processInputPipeCommand(TQString inputcommand) {
}
}
+void LockProcess::cryptographicCardInserted(TDECryptographicCardDevice* cdevice) {
+ TQString login_name = TQString::null;
+ X509CertificatePtrList certList = cdevice->cardX509Certificates();
+ if (certList.count() > 0) {
+ KSSLCertificate* card_cert = NULL;
+ card_cert = KSSLCertificate::fromX509(certList[0]);
+ TQStringList cert_subject_parts = TQStringList::split("/", card_cert->getSubject(), false);
+ for (TQStringList::Iterator it = cert_subject_parts.begin(); it != cert_subject_parts.end(); ++it ) {
+ TQString lcpart = (*it).lower();
+ if (lcpart.startsWith("cn=")) {
+ login_name = lcpart.right(lcpart.length() - strlen("cn="));
+ }
+ }
+ delete card_cert;
+ }
+
+ if (login_name != "") {
+ KUser user;
+ if (login_name == user.loginName()) {
+ // Activate appropriate VT
+ DM dm;
+ SessList sess;
+ if (dm.localSessions(sess)) {
+ TQString user, loc;
+ for (SessList::ConstIterator it = sess.begin(); it != sess.end(); ++it) {
+ DM::sess2Str2(*it, user, loc);
+ if ((*it).self) {
+ // Switch VTs
+ DM().switchVT((*it).vt);
+ break;
+ }
+ }
+ }
+
+ // Pass login to the PAM stack...
+ if (dynamic_cast<SAKDlg*>(currentDialog)) {
+ dynamic_cast<SAKDlg*>(currentDialog)->closeDialogForced();
+ TQTimer::singleShot(0, this, SLOT(signalPassDlgToAttemptCardLogin()));
+ }
+ else if (dynamic_cast<SecureDlg*>(currentDialog)) {
+ dynamic_cast<SecureDlg*>(currentDialog)->closeDialogForced();
+ TQTimer::singleShot(0, this, SLOT(signalPassDlgToAttemptCardLogin()));
+ }
+ else if (dynamic_cast<PasswordDlg*>(currentDialog)) {
+ signalPassDlgToAttemptCardLogin();
+ }
+ }
+ }
+}
+
+void LockProcess::cryptographicCardRemoved(TDECryptographicCardDevice* cdevice) {
+ PasswordDlg* passDlg = dynamic_cast<PasswordDlg*>(currentDialog);
+ if (passDlg) {
+ passDlg->resetCardLogin();
+ }
+ else {
+ TQTimer::singleShot(0, this, SLOT(signalPassDlgToAttemptCardAbort()));
+ }
+}
+
+void LockProcess::signalPassDlgToAttemptCardLogin() {
+ PasswordDlg* passDlg = dynamic_cast<PasswordDlg*>(currentDialog);
+ if (passDlg) {
+ passDlg->attemptCardLogin();
+ }
+ else {
+ if (currentDialog) {
+ // Try again later
+ TQTimer::singleShot(0, this, SLOT(signalPassDlgToAttemptCardLogin()));
+ }
+ }
+}
+
+void LockProcess::signalPassDlgToAttemptCardAbort() {
+ PasswordDlg* passDlg = dynamic_cast<PasswordDlg*>(currentDialog);
+ if (passDlg) {
+ passDlg->resetCardLogin();
+ }
+ else {
+ if (currentDialog) {
+ // Try again later
+ TQTimer::singleShot(0, this, SLOT(signalPassDlgToAttemptCardAbort()));
+ }
+ }
+}
+
+void LockProcess::cryptographicCardPinRequested(TQString prompt, TDECryptographicCardDevice* cdevice) {
+ TQCString password;
+ const char * pin_entry;
+
+ QueryDlg qryDlg(this);
+ qryDlg.updateLabel(prompt);
+ qryDlg.setUnlockIcon();
+ mForceReject = false;
+ execDialog(&qryDlg);
+ if (mForceReject == false) {
+ pin_entry = qryDlg.getEntry();
+ cdevice->setProvidedPin(pin_entry);
+ }
+ else {
+ cdevice->setProvidedPin(TQString::null);
+ }
+}
+
void LockProcess::fullyOnline() {
if (!mFullyOnlineSent) {
if (kdesktop_pid > 0) {
diff --git a/kdesktop/lock/lockprocess.h b/kdesktop/lock/lockprocess.h
index ae2a71c1..dafd2ae1 100644
--- a/kdesktop/lock/lockprocess.h
+++ b/kdesktop/lock/lockprocess.h
@@ -10,6 +10,11 @@
#ifndef __LOCKENG_H__
#define __LOCKENG_H__
+#include <ksslcertificate.h>
+
+#include <tdehardwaredevices.h>
+#include <tdecryptographiccarddevice.h>
+
#include <kgreeterplugin.h>
#include <kprocess.h>
@@ -134,6 +139,11 @@ class LockProcess : public TQWidget
void startSecureDialog();
void slotMouseActivity(XEvent *event);
void processInputPipeCommand(TQString command);
+ void cryptographicCardInserted(TDECryptographicCardDevice*);
+ void cryptographicCardRemoved(TDECryptographicCardDevice*);
+ void cryptographicCardPinRequested(TQString prompt, TDECryptographicCardDevice* cdevice);
+ void signalPassDlgToAttemptCardLogin();
+ void signalPassDlgToAttemptCardAbort();
private:
void configure();
diff --git a/kdesktop/lock/main.cc b/kdesktop/lock/main.cc
index e8265092..6937cbe6 100644
--- a/kdesktop/lock/main.cc
+++ b/kdesktop/lock/main.cc
@@ -372,15 +372,23 @@ int main( int argc, char **argv )
KSimpleConfig* tdmconfig;
OPEN_TDMCONFIG_AND_SET_GROUP
+ sigset_t new_mask;
+ sigset_t orig_mask;
+
+ // Block reception of all signals in this thread
+ sigprocmask(SIG_BLOCK, &new_mask, NULL);
+
+ // Create new LockProcess, which also spawns threads inheriting the blocked signal mask
trinity_desktop_lock_process = new LockProcess;
+ // Unblock reception of all signals in this thread
+ sigprocmask(SIG_UNBLOCK, &new_mask, NULL);
+
// Start loading core functions, such as the desktop wallpaper interface
app->processEvents();
if (args->isSet( "internal" )) {
kdesktop_pid = atoi(args->getOption( "internal" ));
- sigset_t new_mask;
- sigset_t orig_mask;
struct sigaction act;
in_internal_mode = TRUE;
diff --git a/kdesktop/lockeng.cc b/kdesktop/lockeng.cc
index 600573f2..ceffd73f 100644
--- a/kdesktop/lockeng.cc
+++ b/kdesktop/lockeng.cc
@@ -11,10 +11,16 @@
#include <stdlib.h>
+#include <ksslcertificate.h>
+
+#include <tdehardwaredevices.h>
+#include <tdecryptographiccarddevice.h>
+
#include <kstandarddirs.h>
#include <tdeapplication.h>
#include <kservicegroup.h>
#include <kdebug.h>
+#include <kuser.h>
#include <tdelocale.h>
#include <tqfile.h>
#include <tqtimer.h>
@@ -82,6 +88,7 @@ SaverEngine::SaverEngine()
mTerminationRequested(false),
mSaverProcessReady(false),
mNewVTAfterLockEngage(false),
+ mValidCryptoCardInserted(false),
mSwitchVTAfterLockEngage(-1),
dBusLocal(0),
dBusWatch(0),
@@ -158,6 +165,17 @@ SaverEngine::SaverEngine()
sigaddset(&mThreadBlockSet, SIGTTIN);
pthread_sigmask(SIG_BLOCK, &mThreadBlockSet, NULL);
+ // Initialize SmartCard readers
+ TDEGenericDevice *hwdevice;
+ TDEHardwareDevices *hwdevices = TDEGlobal::hardwareDevices();
+ TDEGenericHardwareList cardReaderList = hwdevices->listByDeviceClass(TDEGenericDeviceType::CryptographicCard);
+ for (hwdevice = cardReaderList.first(); hwdevice; hwdevice = cardReaderList.next()) {
+ TDECryptographicCardDevice* cdevice = static_cast<TDECryptographicCardDevice*>(hwdevice);
+ connect(cdevice, TQT_SIGNAL(certificateListAvailable(TDECryptographicCardDevice*)), this, TQT_SLOT(cryptographicCardInserted(TDECryptographicCardDevice*)));
+ connect(cdevice, TQT_SIGNAL(cardRemoved(TDECryptographicCardDevice*)), this, TQT_SLOT(cryptographicCardRemoved(TDECryptographicCardDevice*)));
+ cdevice->enableCardMonitoring(true);
+ }
+
dBusConnect();
}
@@ -186,6 +204,43 @@ SaverEngine::~SaverEngine()
delete m_helperThread;
}
+void SaverEngine::cryptographicCardInserted(TDECryptographicCardDevice* cdevice) {
+ TQString login_name = TQString::null;
+ X509CertificatePtrList certList = cdevice->cardX509Certificates();
+ if (certList.count() > 0) {
+ KSSLCertificate* card_cert = NULL;
+ card_cert = KSSLCertificate::fromX509(certList[0]);
+ TQStringList cert_subject_parts = TQStringList::split("/", card_cert->getSubject(), false);
+ for (TQStringList::Iterator it = cert_subject_parts.begin(); it != cert_subject_parts.end(); ++it ) {
+ TQString lcpart = (*it).lower();
+ if (lcpart.startsWith("cn=")) {
+ login_name = lcpart.right(lcpart.length() - strlen("cn="));
+ }
+ }
+ delete card_cert;
+ }
+
+ if (login_name != "") {
+ KUser user;
+ if (login_name == user.loginName()) {
+ mValidCryptoCardInserted = true;
+ // Disable saver
+ enable(false);
+ }
+ }
+}
+
+void SaverEngine::cryptographicCardRemoved(TDECryptographicCardDevice* cdevice) {
+ if (mValidCryptoCardInserted) {
+ // Restore saver timeout
+ configure();
+
+ // Force lock
+ lockScreen();
+ }
+ mValidCryptoCardInserted = false;
+}
+
//---------------------------------------------------------------------------
//
// This should be called only using DCOP.
@@ -283,28 +338,25 @@ bool SaverEngine::enable( bool e )
mEnabled = e;
- if (mEnabled)
- {
+ if (mEnabled) {
if ( !mXAutoLock ) {
mXAutoLock = new XAutoLock();
connect(mXAutoLock, TQT_SIGNAL(timeout()), TQT_SLOT(idleTimeout()));
}
- mXAutoLock->setTimeout(mTimeout);
- mXAutoLock->setDPMS(true);
+ mXAutoLock->setTimeout(mTimeout);
+ mXAutoLock->setDPMS(true);
//mXAutoLock->changeCornerLockStatus( mLockCornerTopLeft, mLockCornerTopRight, mLockCornerBottomLeft, mLockCornerBottomRight);
- // We'll handle blanking
- XSetScreenSaver(tqt_xdisplay(), mTimeout + 10, mXInterval, PreferBlanking, mXExposures);
- kdDebug() << "XSetScreenSaver " << mTimeout + 10 << endl;
-
- mXAutoLock->start();
-
- kdDebug(1204) << "Saver Engine started, timeout: " << mTimeout << endl;
+ // We'll handle blanking
+ XSetScreenSaver(tqt_xdisplay(), mTimeout + 10, mXInterval, PreferBlanking, mXExposures);
+ kdDebug() << "XSetScreenSaver " << mTimeout + 10 << endl;
+
+ mXAutoLock->start();
+
+ kdDebug(1204) << "Saver Engine started, timeout: " << mTimeout << endl;
}
- else
- {
- if (mXAutoLock)
- {
+ else {
+ if (mXAutoLock) {
delete mXAutoLock;
mXAutoLock = 0;
}
diff --git a/kdesktop/lockeng.h b/kdesktop/lockeng.h
index 166d6b40..5eebaa47 100644
--- a/kdesktop/lockeng.h
+++ b/kdesktop/lockeng.h
@@ -18,6 +18,7 @@
#include <tqdbusconnection.h>
+class TDECryptographicCardDevice;
class DCOPClientTransaction;
class TQT_DBusMessage;
class TQT_DBusProxy;
@@ -134,6 +135,9 @@ private slots:
void handleSecureDialog();
void slotSAKProcessExited();
+ void cryptographicCardInserted(TDECryptographicCardDevice*);
+ void cryptographicCardRemoved(TDECryptographicCardDevice*);
+
/**
* Enable wallpaper exports
*/
@@ -186,6 +190,7 @@ private:
bool mTerminationRequested;
bool mSaverProcessReady;
bool mNewVTAfterLockEngage;
+ bool mValidCryptoCardInserted;
int mSwitchVTAfterLockEngage;
struct sigaction mSignalAction;
TQT_DBusConnection dBusConn;
diff --git a/tdm/CMakeLists.txt b/tdm/CMakeLists.txt
index 08096f84..ce8a1f4e 100644
--- a/tdm/CMakeLists.txt
+++ b/tdm/CMakeLists.txt
@@ -21,3 +21,4 @@ include( ConfigureChecks.cmake )
add_subdirectory( backend )
add_subdirectory( kfrontend )
+add_subdirectory( cryptocardwatcher )
diff --git a/tdm/backend/client.c b/tdm/backend/client.c
index cb185bca..2676a5d2 100644
--- a/tdm/backend/client.c
+++ b/tdm/backend/client.c
@@ -180,7 +180,7 @@ PAM_conv( int num_msg,
ReInitErrorLog();
Debug( "PAM_conv\n" );
- for (count = 0; count < num_msg; count++)
+ 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 );
@@ -201,9 +201,18 @@ PAM_conv( int num_msg,
/* 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 );
+ // WARNING
+ // This is far from foolproof, but it's the best we can do at this time...
+ // Try to detect PIN entry requests
+ if (strstr(msg[count]->msg, "PIN")) {
+ reply[count].resp = pd->gconv(GCONV_HIDDEN, msg[count]->msg);
+ }
+ else {
+ 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 );
@@ -237,6 +246,7 @@ PAM_conv( int num_msg,
}
reply[count].resp_retcode = PAM_SUCCESS; /* unused in linux-pam */
}
+ }
Debug( " PAM_conv success\n" );
*resp = reply;
return PAM_SUCCESS;
@@ -769,7 +779,6 @@ Verify( GConvFunc gconv, int rootok )
}
#ifdef USE_PAM
-
Debug( " pam_acct_mgmt() ...\n" );
pretc = pam_acct_mgmt( pamh, 0 );
ReInitErrorLog();
diff --git a/tdm/cryptocardwatcher/CMakeLists.txt b/tdm/cryptocardwatcher/CMakeLists.txt
new file mode 100644
index 00000000..7564ac2c
--- /dev/null
+++ b/tdm/cryptocardwatcher/CMakeLists.txt
@@ -0,0 +1,32 @@
+#################################################
+#
+# (C) 2015 Timothy Pearson
+# kb9vqf (AT) pearsoncomputing.net
+#
+# Improvements and feedback are welcome
+#
+# This file is released under GPL >= 2
+#
+#################################################
+
+include_directories(
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${CMAKE_SOURCE_DIR}/tdmlib
+ ${TDE_INCLUDE_DIR}
+ ${TQT_INCLUDE_DIRS}
+)
+
+link_directories(
+ ${TQT_LIBRARY_DIRS}
+)
+
+
+##### tdecryptocardwatcher (executable) #########
+
+tde_add_executable( tdecryptocardwatcher AUTOMOC
+ SOURCES main.cpp watcher.cc
+ LINK tdecore-shared tdeio-shared dmctl-static
+ DESTINATION ${BIN_INSTALL_DIR}
+ SETUID
+)
+
diff --git a/tdm/cryptocardwatcher/main.cpp b/tdm/cryptocardwatcher/main.cpp
new file mode 100644
index 00000000..5d27ff19
--- /dev/null
+++ b/tdm/cryptocardwatcher/main.cpp
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2015 Timothy Pearson <kb9vqf@pearsoncomputing.net>
+ *
+ * This file is part of cryptocardwatcher, the TDE Cryptographic Card Session Monitor
+ *
+ * cryptocardwatcher is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * cryptocardwatcher is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with cryptocardwatcher. If not, see http://www.gnu.org/licenses/.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <exception>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <sys/file.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/select.h>
+#include <sys/time.h>
+#include <termios.h>
+#include <signal.h>
+#include <stdint.h>
+
+#include <tqobject.h>
+
+#include <tdeapplication.h>
+#include <tdecmdlineargs.h>
+
+#include <ksslcertificate.h>
+
+#include <tdehardwaredevices.h>
+#include <tdecryptographiccarddevice.h>
+
+#include "watcher.h"
+
+int lockfd = -1;
+char lockFileName[256];
+
+// --------------------------------------------------------------------------------------
+// Useful function from Stack Overflow
+// http://stackoverflow.com/questions/1599459/optimal-lock-file-method
+// --------------------------------------------------------------------------------------
+int tryGetLock(char const *lockName) {
+ mode_t m = umask( 0 );
+ int fd = open( lockName, O_RDWR|O_CREAT, 0666 );
+ umask( m );
+ if( fd >= 0 && flock( fd, LOCK_EX | LOCK_NB ) < 0 ) {
+ close( fd );
+ fd = -1;
+ }
+ return fd;
+}
+// --------------------------------------------------------------------------------------
+
+// --------------------------------------------------------------------------------------
+// Useful function from Stack Overflow
+// http://stackoverflow.com/questions/1599459/optimal-lock-file-method
+// --------------------------------------------------------------------------------------
+void releaseLock(int fd, char const *lockName) {
+ if( fd < 0 ) {
+ return;
+ }
+ remove( lockName );
+ close( fd );
+}
+// --------------------------------------------------------------------------------------
+
+void handle_sigterm(int signum) {
+ if (lockfd >= 0) {
+ releaseLock(lockfd, lockFileName);
+ }
+ exit(0);
+}
+
+static TDECmdLineOptions options[] =
+{
+ TDECmdLineLastOption
+};
+
+int main(int argc, char *argv[]) {
+ int ret = -1;
+
+ // Register cleanup handlers
+ struct sigaction action;
+ memset(&action, 0, sizeof(struct sigaction));
+ action.sa_handler = handle_sigterm;
+ sigaction(SIGTERM, &action, NULL);
+
+ // Ensure only one process is running
+ sprintf(lockFileName, "/var/lock/cryptocardwatcher.lock");
+ lockfd = tryGetLock(lockFileName);
+ if (lockfd < 0) {
+ printf ("[cryptocardwatcher] Another instance of this program is already running!\n[cryptocardwatcher] Lockfile detected at '%s'\n", lockFileName);
+ return -2;
+ }
+
+ // Parse command line arguments
+ TDECmdLineArgs::init(argc, argv, "cryptocardwatcher", "cryptocardwatcher", "TDE Cryptographic Card Session Monitor", "0.1");
+ TDECmdLineArgs::addCmdLineOptions(options);
+ TDEApplication::addCmdLineOptions();
+
+ // Initialize TDE application
+ TDEApplication tdeapp(false, false);
+ tdeapp.disableAutoDcopRegistration();
+ CardWatcher* watcher = new CardWatcher();
+
+ // Initialize SmartCard readers
+ TDEGenericDevice *hwdevice;
+ TDEHardwareDevices *hwdevices = TDEGlobal::hardwareDevices();
+ TDEGenericHardwareList cardReaderList = hwdevices->listByDeviceClass(TDEGenericDeviceType::CryptographicCard);
+ for (hwdevice = cardReaderList.first(); hwdevice; hwdevice = cardReaderList.next()) {
+ TDECryptographicCardDevice* cdevice = static_cast<TDECryptographicCardDevice*>(hwdevice);
+ TQObject::connect(cdevice, TQT_SIGNAL(cardInserted(TDECryptographicCardDevice*)), watcher, TQT_SLOT(cryptographicCardInserted(TDECryptographicCardDevice*)));
+ TQObject::connect(cdevice, TQT_SIGNAL(cardRemoved(TDECryptographicCardDevice*)), watcher, TQT_SLOT(cryptographicCardRemoved(TDECryptographicCardDevice*)));
+ cdevice->enableCardMonitoring(true);
+ }
+
+ // Start TDE application
+ ret = tdeapp.exec();
+
+ // Clean up
+ delete watcher;
+
+ releaseLock(lockfd, lockFileName);
+ return ret;
+}
diff --git a/tdm/cryptocardwatcher/watcher.cc b/tdm/cryptocardwatcher/watcher.cc
new file mode 100644
index 00000000..e2582118
--- /dev/null
+++ b/tdm/cryptocardwatcher/watcher.cc
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2015 Timothy Pearson <kb9vqf@pearsoncomputing.net>
+ *
+ * This file is part of cryptocardwatcher, the TDE Cryptographic Card Session Monitor
+ *
+ * cryptocardwatcher is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * cryptocardwatcher is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with cryptocardwatcher. If not, see http://www.gnu.org/licenses/.
+ */
+
+#include "watcher.h"
+
+#include <ksslcertificate.h>
+
+#include <tdehardwaredevices.h>
+#include <tdecryptographiccarddevice.h>
+
+#include <dmctl.h>
+#include <kuser.h>
+
+CardWatcher::CardWatcher() : TQObject() {
+ //
+}
+
+CardWatcher::~CardWatcher() {
+ //
+}
+
+void CardWatcher::cryptographicCardInserted(TDECryptographicCardDevice* cdevice) {
+ TQString login_name = TQString::null;
+ X509CertificatePtrList certList = cdevice->cardX509Certificates();
+ if (certList.count() > 0) {
+ KSSLCertificate* card_cert = NULL;
+ card_cert = KSSLCertificate::fromX509(certList[0]);
+ TQStringList cert_subject_parts = TQStringList::split("/", card_cert->getSubject(), false);
+ for (TQStringList::Iterator it = cert_subject_parts.begin(); it != cert_subject_parts.end(); ++it ) {
+ TQString lcpart = (*it).lower();
+ if (lcpart.startsWith("cn=")) {
+ login_name = lcpart.right(lcpart.length() - strlen("cn="));
+ }
+ }
+ delete card_cert;
+ }
+
+ if (login_name != "") {
+ // Determine if user already has an active session
+ DM dm;
+ SessList sess;
+ bool user_active = false;
+ if (dm.localSessions(sess)) {
+ TQString user, loc;
+ for (SessList::ConstIterator it = sess.begin(); it != sess.end(); ++it) {
+ DM::sess2Str2(*it, user, loc);
+ if (user.startsWith(login_name + ": ")) {
+ // Found active session
+ user_active = true;
+ }
+ if (user == "Unused") {
+ if ((*it).vt == dm.activeVT()) {
+ // Found active unused session
+ user_active = true;
+ }
+ }
+ }
+ }
+ if (!user_active) {
+ // Activate new VT
+ DM().startReserve();
+ }
+ }
+}
+
+void CardWatcher::cryptographicCardRemoved(TDECryptographicCardDevice* cdevice) {
+ //
+}
+
+#include "watcher.moc" \ No newline at end of file
diff --git a/tdm/cryptocardwatcher/watcher.h b/tdm/cryptocardwatcher/watcher.h
new file mode 100644
index 00000000..bfbb010a
--- /dev/null
+++ b/tdm/cryptocardwatcher/watcher.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2015 Timothy Pearson <kb9vqf@pearsoncomputing.net>
+ *
+ * This file is part of cryptocardwatcher, the TDE Cryptographic Card Session Monitor
+ *
+ * cryptocardwatcher is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * cryptocardwatcher is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with cryptocardwatcher. If not, see http://www.gnu.org/licenses/.
+ */
+
+#ifndef __TDECRYPTOCARDWATCHER_H__
+#define __TDECRYPTOCARDWATCHER_H__
+
+#include <tqobject.h>
+
+class TDECryptographicCardDevice;
+
+class CardWatcher : public TQObject
+{
+ Q_OBJECT
+
+ public:
+ CardWatcher();
+ ~CardWatcher();
+
+ public slots:
+ void cryptographicCardInserted(TDECryptographicCardDevice*);
+ void cryptographicCardRemoved(TDECryptographicCardDevice*);
+};
+
+#endif // __TDECRYPTOCARDWATCHER_H__ \ No newline at end of file
diff --git a/tdm/kfrontend/CMakeLists.txt b/tdm/kfrontend/CMakeLists.txt
index 8c0fffd5..ab2ddc69 100644
--- a/tdm/kfrontend/CMakeLists.txt
+++ b/tdm/kfrontend/CMakeLists.txt
@@ -68,7 +68,7 @@ tde_add_executable( tdm_greet AUTOMOC
kfdialog.cpp kgdialog.cpp kchooser.cpp kgverify.cpp
tdmshutdown.cpp tdmadmindialog.cpp kgreeter.cpp
kgapp.cpp sakdlg.cc
- LINK tdmthemer-static tdeui-shared Xtst ${TDMGREET_OPTIONAL_LINK}
+ LINK tdmthemer-static tdeui-shared tdeio-shared dmctl-static Xtst ${TDMGREET_OPTIONAL_LINK}
DESTINATION ${BIN_INSTALL_DIR}
)
diff --git a/tdm/kfrontend/kgapp.cpp b/tdm/kfrontend/kgapp.cpp
index 2d630485..65e6cf0d 100644
--- a/tdm/kfrontend/kgapp.cpp
+++ b/tdm/kfrontend/kgapp.cpp
@@ -72,6 +72,7 @@ bool has_twin = false;
bool is_themed = false;
bool trinity_desktop_lock_use_sak = TRUE;
bool trinity_desktop_synchronize_keyboard_lights = TRUE;
+bool trinity_desktop_watch_cryptographic_cards = TRUE;
TQPoint primaryScreenPosition;
static int
@@ -216,6 +217,7 @@ kg_main( const char *argv0 )
TDEProcess *tsak = 0;
TDEProcess *kbdl = 0;
+ TDEProcess *ccsm = 0;
TDEProcess *proc = 0;
TDEProcess *comp = 0;
TDEProcess *dcop = 0;
@@ -252,6 +254,12 @@ kg_main( const char *argv0 )
kbdl->start();
}
+ if (trinity_desktop_watch_cryptographic_cards) {
+ ccsm = new TDEProcess;
+ *ccsm << TQCString( argv0, strrchr( argv0, '/' ) - argv0 + 2 ) + "tdecryptocardwatcher";
+ ccsm->start();
+ }
+
XSetErrorHandler( ignoreXError );
argb_visual_available = false;
char *display = 0;
@@ -518,6 +526,10 @@ kg_main( const char *argv0 )
kbdl->closeStdin();
kbdl->detach();
}
+ if (ccsm) {
+ ccsm->closeStdin();
+ ccsm->detach();
+ }
if (comp) {
if (comp->isRunning()) {
if (_compositor == TDE_COMPOSITOR_BINARY) {
diff --git a/tdm/kfrontend/kgreeter.cpp b/tdm/kfrontend/kgreeter.cpp
index aa89fd78..d3ee07de 100644
--- a/tdm/kfrontend/kgreeter.cpp
+++ b/tdm/kfrontend/kgreeter.cpp
@@ -33,6 +33,13 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "themer/tdmitem.h"
#include "themer/tdmlabel.h"
+#include <dmctl.h>
+
+#include <ksslcertificate.h>
+
+#include <tdehardwaredevices.h>
+#include <tdecryptographiccarddevice.h>
+
#include <tdeapplication.h>
#include <tdelocale.h>
#include <kstandarddirs.h>
@@ -212,6 +219,17 @@ KGreeter::KGreeter( bool framed )
pluginList = KGVerify::init( _pluginsLogin );
}
+ // Initialize SmartCard readers
+ TDEGenericDevice *hwdevice;
+ TDEHardwareDevices *hwdevices = TDEGlobal::hardwareDevices();
+ TDEGenericHardwareList cardReaderList = hwdevices->listByDeviceClass(TDEGenericDeviceType::CryptographicCard);
+ for (hwdevice = cardReaderList.first(); hwdevice; hwdevice = cardReaderList.next()) {
+ TDECryptographicCardDevice* cdevice = static_cast<TDECryptographicCardDevice*>(hwdevice);
+ connect(cdevice, TQT_SIGNAL(certificateListAvailable(TDECryptographicCardDevice*)), this, TQT_SLOT(cryptographicCardInserted(TDECryptographicCardDevice*)));
+ connect(cdevice, TQT_SIGNAL(cardRemoved(TDECryptographicCardDevice*)), this, TQT_SLOT(cryptographicCardRemoved(TDECryptographicCardDevice*)));
+ cdevice->enableCardMonitoring(true);
+ }
+
mControlPipeHandlerThread = new TQEventLoopThread();
mControlPipeHandler = new ControlPipeHandlerObject();
mControlPipeHandler->mKGreeterParent = this;
@@ -829,6 +847,60 @@ KGreeter::verifySetUser( const TQString &user )
slotUserEntered();
}
+void KGreeter::cryptographicCardInserted(TDECryptographicCardDevice* cdevice) {
+ TQString login_name = TQString::null;
+ X509CertificatePtrList certList = cdevice->cardX509Certificates();
+ if (certList.count() > 0) {
+ KSSLCertificate* card_cert = NULL;
+ card_cert = KSSLCertificate::fromX509(certList[0]);
+ TQStringList cert_subject_parts = TQStringList::split("/", card_cert->getSubject(), false);
+ for (TQStringList::Iterator it = cert_subject_parts.begin(); it != cert_subject_parts.end(); ++it ) {
+ TQString lcpart = (*it).lower();
+ if (lcpart.startsWith("cn=")) {
+ login_name = lcpart.right(lcpart.length() - strlen("cn="));
+ }
+ }
+ delete card_cert;
+ }
+
+ if (login_name != "") {
+ DM dm;
+ SessList sess;
+ bool vt_active = false;
+ bool user_active = false;
+ if (dm.localSessions(sess)) {
+ TQString user, loc;
+ for (SessList::ConstIterator it = sess.begin(); it != sess.end(); ++it) {
+ DM::sess2Str2(*it, user, loc);
+ if (user.startsWith(login_name + ": ")) {
+ // Found active session
+ user_active = true;
+ }
+ if ((*it).self) {
+ if ((*it).vt == dm.activeVT()) {
+ vt_active = true;
+ }
+ }
+ }
+ }
+
+ if (!user_active && vt_active) {
+ // Select the correct user
+ verify->setUser(login_name);
+ verifySetUser(login_name);
+ verify->lockUserEntry(true);
+
+ // Initiate login
+ verify->accept();
+ }
+ }
+}
+
+void KGreeter::cryptographicCardRemoved(TDECryptographicCardDevice* cdevice) {
+ verify->lockUserEntry(false);
+ verify->requestAbort();
+}
+
KStdGreeter::KStdGreeter()
: KGreeter()
, clock( 0 )
diff --git a/tdm/kfrontend/kgreeter.h b/tdm/kfrontend/kgreeter.h
index 7d1c1bc6..fa24622d 100644
--- a/tdm/kfrontend/kgreeter.h
+++ b/tdm/kfrontend/kgreeter.h
@@ -46,6 +46,8 @@ class TQListViewItem;
class KGreeter;
class SAKDlg;
+class TDECryptographicCardDevice;
+
struct SessType {
TQString name, type;
bool hid;
@@ -138,6 +140,8 @@ class KGreeter : public KGDialog, public KGVerifyHandler {
private slots:
void slotLoadPrevWM();
+ void cryptographicCardInserted(TDECryptographicCardDevice*);
+ void cryptographicCardRemoved(TDECryptographicCardDevice*);
private:
ControlPipeHandlerObject* mControlPipeHandler;
diff --git a/tdm/kfrontend/kgverify.cpp b/tdm/kfrontend/kgverify.cpp
index 46b89e9c..a02cc1c3 100644
--- a/tdm/kfrontend/kgverify.cpp
+++ b/tdm/kfrontend/kgverify.cpp
@@ -30,6 +30,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "themer/tdmthemer.h"
#include "themer/tdmitem.h"
+#include "themer/tdmlabel.h"
#include <tdeapplication.h>
#include <tdelocale.h>
@@ -66,30 +67,31 @@ void KGVerifyHandler::updateStatus( bool, bool, int )
{
}
-KGVerify::KGVerify( KGVerifyHandler *_handler, KdmThemer *_themer,
- TQWidget *_parent, TQWidget *_predecessor,
- const TQString &_fixedUser,
- const PluginList &_pluginList,
- KGreeterPlugin::Function _func,
- KGreeterPlugin::Context _ctx )
+KGVerify::KGVerify(KGVerifyHandler *_handler, KdmThemer *_themer,
+ TQWidget *_parent, TQWidget *_predecessor,
+ const TQString &_fixedUser,
+ const PluginList &_pluginList,
+ KGreeterPlugin::Function _func,
+ KGreeterPlugin::Context _ctx)
: inherited()
- , coreLock( 0 )
- , fixedEntity( _fixedUser )
- , pluginList( _pluginList )
- , handler( _handler )
- , themer( _themer )
- , parent( _parent )
- , predecessor( _predecessor )
- , plugMenu( 0 )
- , curPlugin( -1 )
- , timedLeft( 0 )
- , func( _func )
- , ctx( _ctx )
- , enabled( true )
- , running( false )
- , suspended( false )
- , failed( false )
- , isClear( true )
+ , coreLock(0)
+ , fixedEntity(_fixedUser)
+ , pluginList(_pluginList)
+ , handler(_handler)
+ , themer(_themer)
+ , parent(_parent)
+ , predecessor(_predecessor)
+ , plugMenu(0)
+ , curPlugin(-1)
+ , timedLeft(0)
+ , func(_func)
+ , ctx(_ctx)
+ , enabled(true)
+ , running(false)
+ , suspended(false)
+ , failed(false)
+ , isClear(true)
+ , abortRequested(false)
{
connect( &timer, TQT_SIGNAL(timeout()), TQT_SLOT(slotTimeout()) );
connect( kapp, TQT_SIGNAL(activity()), TQT_SLOT(slotActivity()) );
@@ -269,6 +271,14 @@ KGVerify::setUser( const TQString &user )
}
void
+KGVerify::lockUserEntry(const bool lock)
+{
+ // assert( fixedEntity.isEmpty() );
+ Debug( "%s->lockUserEntry(%\"s)\n", pName.data(), lock );
+ greet->lockUserEntry(lock);
+}
+
+void
KGVerify::setPassword( const TQString &pass )
{
greet->setPassword( pass );
@@ -374,6 +384,12 @@ KGVerify::reject()
doReject( true );
}
+void // not a slot - called manually by greeter
+KGVerify::requestAbort()
+{
+ abortRequested = true;
+}
+
void
KGVerify::setEnabled( bool on )
{
@@ -478,27 +494,28 @@ KGVerify::VErrBox( TQWidget *parent, const TQString &user, const char *msg )
}
void // private static
-KGVerify::VInfoBox( TQWidget *parent, const TQString &user, const char *msg )
+KGVerify::VInfoBox(TQWidget *parent, const TQString &user, const char *msg)
{
TQString mesg = TQString::fromLocal8Bit( msg );
TQRegExp rx( "^Warning: your account will expire in (\\d+) day" );
- if (rx.search( mesg ) >= 0) {
- int expire = rx.cap( 1 ).toInt();
+ if (rx.search(mesg) >= 0) {
+ int expire = rx.cap(1).toInt();
mesg = expire ?
i18n("Your account expires tomorrow.",
"Your account expires in %n days.", expire) :
i18n("Your account expires today.");
- } else {
+ }
+ else {
rx.setPattern( "^Warning: your password will expire in (\\d+) day" );
- if (rx.search( mesg ) >= 0) {
- int expire = rx.cap( 1 ).toInt();
+ if (rx.search(mesg) >= 0) {
+ int expire = rx.cap(1).toInt();
mesg = expire ?
i18n("Your password expires tomorrow.",
"Your password expires in %n days.", expire) :
i18n("Your password expires today.");
}
}
- VMsgBox( parent, user, infobox, mesg );
+ VMsgBox(parent, user, infobox, mesg);
}
bool // public static
@@ -597,9 +614,24 @@ KGVerify::handleVerify()
Debug( " echo = %d\n", echo );
ndelay = GRecvInt();
Debug( " ndelay = %d\n%s->textPrompt(...)\n", ndelay, pName.data() );
- greet->textPrompt( msg, echo, ndelay );
- if (msg)
- free( msg );
+ if (abortRequested) {
+ greet->textPrompt("", echo, ndelay);
+ abortRequested = false;
+ }
+ else {
+ if (msg && (msg[0] != 0)) {
+ // Reset password entry and change text
+ setPassPromptText(msg);
+ greet->start();
+ greet->textPrompt(msg, echo, ndelay);
+ }
+ else {
+ greet->textPrompt(msg, echo, ndelay);
+ }
+ }
+ if (msg) {
+ free(msg);
+ }
return;
case V_GET_BINARY:
Debug( " V_GET_BINARY\n" );
@@ -607,9 +639,16 @@ KGVerify::handleVerify()
Debug( " %d bytes prompt\n", ret );
ndelay = GRecvInt();
Debug( " ndelay = %d\n%s->binaryPrompt(...)\n", ndelay, pName.data() );
- greet->binaryPrompt( msg, ndelay );
- if (msg)
- free( msg );
+ if (abortRequested) {
+ gplugReturnBinary(NULL);
+ abortRequested = false;
+ }
+ else {
+ greet->binaryPrompt( msg, ndelay );
+ }
+ if (msg) {
+ free(msg);
+ }
return;
}
@@ -622,11 +661,12 @@ KGVerify::handleVerify()
curUser = user = TQString::fromLocal8Bit( msg );
// greet needs this to be able to return something useful from
// getEntity(). but the backend is still unable to tell a domain ...
- Debug( " %s->setUser(%\"s)\n", pName.data(), user.latin1() );
+ Debug(" %s->setUser(%\"s)\n", pName.data(), user.latin1());
greet->setUser( curUser );
- handler->verifySetUser( curUser );
- if (msg)
- free( msg );
+ handler->verifySetUser(curUser);
+ if (msg) {
+ free(msg);
+ }
continue;
case V_PRE_OK: // this is only for func == AuthChAuthTok
Debug( " V_PRE_OK\n" );
@@ -636,8 +676,9 @@ KGVerify::handleVerify()
// is not implemented yet.
authTok = true;
cont = true;
- Debug( "%s->succeeded()\n", pName.data() );
+ Debug("%s->succeeded()\n", pName.data());
greet->succeeded();
+ abortRequested = false;
continue;
case V_CHTOK_AUTH:
Debug( " V_CHTOK_AUTH\n" );
@@ -648,14 +689,16 @@ KGVerify::handleVerify()
Debug( " V_CHTOK\n" );
nfunc = KGreeterPlugin::ChAuthTok;
user = TQString::null;
- dchtok:
+ dchtok:
{
timer.stop();
Debug( "%s->succeeded()\n", pName.data() );
greet->succeeded();
+ abortRequested = false;
KGChTok chtok( parent, user, pluginList, curPlugin, nfunc, KGreeterPlugin::Login );
- if (!chtok.exec())
+ if (!chtok.exec()) {
goto retry;
+ }
handler->verifyOk();
return;
}
@@ -665,11 +708,16 @@ KGVerify::handleVerify()
Debug( " %s->textMessage(%\"s, true)\n", pName.data(), msg );
if (!greet->textMessage( msg, true )) {
Debug( " message passed\n" );
- VErrBox( parent, user, msg );
- } else
+ if (!abortRequested) {
+ VErrBox( parent, user, msg );
+ }
+ }
+ else {
Debug( " message swallowed\n" );
- if (msg)
- free( msg );
+ }
+ if (msg) {
+ free(msg);
+ }
continue;
case V_MSG_INFO:
Debug( " V_MSG_INFO\n" );
@@ -677,10 +725,14 @@ KGVerify::handleVerify()
Debug( " %s->textMessage(%\"s, false)\n", pName.data(), msg );
if (!greet->textMessage( msg, false )) {
Debug( " message passed\n" );
- VInfoBox( parent, user, msg );
- } else
- Debug( " message swallowed\n" );
- free( msg );
+ if (!abortRequested) {
+ VInfoBox(parent, user, msg);
+ }
+ }
+ else {
+ Debug(" message swallowed\n");
+ }
+ free(msg);
continue;
}
@@ -698,6 +750,7 @@ KGVerify::handleVerify()
if (ent != fixedEntity) {
Debug( "%s->failed()\n", pName.data() );
greet->failed();
+ abortRequested = false;
MsgBox( sorrybox,
i18n("Authenticated user (%1) does not match requested user (%2).\n")
.arg( ent ).arg( fixedEntity ) );
@@ -706,12 +759,17 @@ KGVerify::handleVerify()
}
Debug( "%s->succeeded()\n", pName.data() );
greet->succeeded();
+ abortRequested = false;
handler->verifyOk();
return;
}
Debug( "%s->failed()\n", pName.data() );
greet->failed();
+ abortRequested = false;
+
+ // Reset password prompt text
+ setPassPromptText(TQString::null, true);
if (ret == V_AUTH) {
Debug( " V_AUTH\n" );
@@ -736,17 +794,36 @@ KGVerify::handleVerify()
}
}
+void KGVerify::setPassPromptText(TQString text, bool use_default_text) {
+ if (themer) {
+ KdmItem* password_label = themer->findNode("password-label");
+ if (password_label) {
+ KdmLabel* pass_label = static_cast<KdmLabel*>(password_label);
+ if (use_default_text) {
+ pass_label->setText(pass_label->lookupStock("password-label"));
+ }
+ else {
+ pass_label->setText(text);
+ }
+ pass_label->update();
+ themer->updateGeometry(true);
+ static_cast<TQWidget *>(themer->parent())->repaint(true);
+ }
+ }
+}
+
void
KGVerify::gplugReturnText( const char *text, int tag )
{
- Debug( "%s: gplugReturnText(%\"s, %d)\n", pName.data(),
- tag & V_IS_SECRET ? "<masked>" : text, tag );
- GSendStr( text );
+ Debug("%s: gplugReturnText(%\"s, %d)\n", pName.data(), tag & V_IS_SECRET ? "<masked>" : text, tag);
+ GSendStr(text);
if (text) {
- GSendInt( tag );
+ GSendInt(tag);
handleVerify();
- } else
+ }
+ else {
coreLock = 0;
+ }
}
void
@@ -755,12 +832,13 @@ KGVerify::gplugReturnBinary( const char *data )
if (data) {
unsigned const char *up = (unsigned const char *)data;
int len = up[3] | (up[2] << 8) | (up[1] << 16) | (up[0] << 24);
- Debug( "%s: gplugReturnBinary(%d bytes)\n", pName.data(), len );
- GSendArr( len, data );
+ Debug("%s: gplugReturnBinary(%d bytes)\n", pName.data(), len);
+ GSendArr(len, data);
handleVerify();
- } else {
- Debug( "%s: gplugReturnBinary(NULL)\n", pName.data() );
- GSendArr( 0, 0 );
+ }
+ else {
+ Debug("%s: gplugReturnBinary(NULL)\n", pName.data());
+ GSendArr(0, 0);
coreLock = 0;
}
}
diff --git a/tdm/kfrontend/kgverify.h b/tdm/kfrontend/kgverify.h
index 44fab973..7db52f2a 100644
--- a/tdm/kfrontend/kgverify.h
+++ b/tdm/kfrontend/kgverify.h
@@ -100,6 +100,7 @@ class KGVerify : public TQObject, public KGreeterPluginHandler {
void presetEntity( const TQString &entity, int field );
TQString getEntity() const;
void setUser( const TQString &user );
+ void lockUserEntry( const bool lock );
void setPassword( const TQString &pass );
/* virtual */ void selectPlugin( int id );
bool entitiesLocal() const;
@@ -113,6 +114,7 @@ class KGVerify : public TQObject, public KGreeterPluginHandler {
void resume();
void accept();
void reject();
+ void requestAbort();
int coreLock;
@@ -146,6 +148,7 @@ class KGVerify : public TQObject, public KGreeterPluginHandler {
bool capsLocked;
bool enabled, running, suspended, failed, delayed, cont;
bool authTok, isClear, timeable;
+ bool abortRequested;
static void VMsgBox( TQWidget *parent, const TQString &user, TQMessageBox::Icon type, const TQString &mesg );
static void VErrBox( TQWidget *parent, const TQString &user, const char *msg );
@@ -158,6 +161,7 @@ class KGVerify : public TQObject, public KGreeterPluginHandler {
void performAutoLogin();
bool scheduleAutoLogin( bool initial );
void doReject( bool initial );
+ void setPassPromptText(TQString text, bool use_default_text=false);
private slots:
//virtual void slotPluginSelected( int id ) = 0;
diff --git a/tdm/kfrontend/themer/tdmitem.cpp b/tdm/kfrontend/themer/tdmitem.cpp
index f5eabdb5..26a4887c 100644
--- a/tdm/kfrontend/themer/tdmitem.cpp
+++ b/tdm/kfrontend/themer/tdmitem.cpp
@@ -204,6 +204,22 @@ KdmItem::findNode( const TQString &_id ) const
return 0;
}
+KdmItem *
+KdmItem::findNodeByType( const TQString &_type ) const
+{
+ if (itemType == _type)
+ return const_cast<KdmItem *>( this );
+
+ TQValueList<KdmItem *>::ConstIterator it;
+ for (it = m_children.begin(); it != m_children.end(); ++it) {
+ KdmItem *t = (*it)->findNodeByType( _type );
+ if (t)
+ return t;
+ }
+
+ return 0;
+}
+
void
KdmItem::setWidget( TQWidget *widget )
{
@@ -336,11 +352,6 @@ KdmItem::paint( TQPainter *p, const TQRect &rect )
else {
// We have compositing support!
TQRgb blend_color = tqRgba(m_backgroundModifier, m_backgroundModifier, m_backgroundModifier, 0); // RGBA overlay
- float alpha = tqAlpha(blend_color) / 255.;
- int pixel = tqAlpha(blend_color) << 24 |
- int(tqRed(blend_color) * alpha) << 16 |
- int(tqGreen(blend_color) * alpha) << 8 |
- int(tqBlue(blend_color) * alpha);
TQImage img( myWidget->size(), 32 );
img = img.convertDepth(32);
diff --git a/tdm/kfrontend/themer/tdmitem.h b/tdm/kfrontend/themer/tdmitem.h
index be7fa65d..d2aeed69 100644
--- a/tdm/kfrontend/themer/tdmitem.h
+++ b/tdm/kfrontend/themer/tdmitem.h
@@ -152,6 +152,7 @@ public:
}
KdmItem *findNode( const TQString &id ) const;
+ KdmItem *findNodeByType( const TQString &type ) const;
virtual void setWidget( TQWidget *widget );
TQWidget *widget() const { return myWidget; }
virtual void setLayoutItem( TQLayoutItem *item );
diff --git a/tdm/kfrontend/themer/tdmlabel.h b/tdm/kfrontend/themer/tdmlabel.h
index 8b955fca..e45d6809 100644
--- a/tdm/kfrontend/themer/tdmlabel.h
+++ b/tdm/kfrontend/themer/tdmlabel.h
@@ -40,6 +40,9 @@ public:
KdmLabel( KdmItem *parent, const TQDomNode &node, const char *name = 0 );
void setText( const TQString &txt );
+ /* Method to lookup the caption associated with an item */
+ TQString lookupStock( const TQString &stock );
+
protected:
// reimplemented; returns the minimum size of rendered text
virtual TQSize sizeHint();
@@ -71,9 +74,6 @@ public slots:
void slotAccel();
private:
- /* Method to lookup the caption associated with an item */
- TQString lookupStock( const TQString &stock );
-
/* Lookup variables in the text */
TQString lookupText( const TQString &t );
diff --git a/tdm/kfrontend/themer/tdmthemer.cpp b/tdm/kfrontend/themer/tdmthemer.cpp
index d6d051cf..6c27b762 100644
--- a/tdm/kfrontend/themer/tdmthemer.cpp
+++ b/tdm/kfrontend/themer/tdmthemer.cpp
@@ -117,6 +117,12 @@ KdmThemer::findNode( const TQString &item ) const
return rootItem->findNode( item );
}
+KdmItem *
+KdmThemer::findNodeByType( const TQString &item ) const
+{
+ return rootItem->findNodeByType( item );
+}
+
void
KdmThemer::updateGeometry( bool force )
{
diff --git a/tdm/kfrontend/themer/tdmthemer.h b/tdm/kfrontend/themer/tdmthemer.h
index 2b8865b4..785a116d 100644
--- a/tdm/kfrontend/themer/tdmthemer.h
+++ b/tdm/kfrontend/themer/tdmthemer.h
@@ -72,6 +72,7 @@ public:
virtual // just to put the reference in the vmt
KdmItem *findNode( const TQString & ) const;
+ KdmItem *findNodeByType( const TQString & ) const;
void updateGeometry( bool force ); // force = true for external calls
diff --git a/tdm/kfrontend/themes/circles/circles.xml b/tdm/kfrontend/themes/circles/circles.xml
index 0596e0ee..102cae7b 100644
--- a/tdm/kfrontend/themes/circles/circles.xml
+++ b/tdm/kfrontend/themes/circles/circles.xml
@@ -165,13 +165,13 @@
<normal color="#FF8080" alpha="0.0"/>
<pos anchor="w" y="50%" width="box" height="box"/>
<box orientation="vertical" xpadding="0" ypadding="0" spacing="14">
- <item type="label">
+ <item type="label" id="username-label">
<pos anchor="ne" x="100%"/>
<normal color="#000000" font="Sans 12"/>
<!-- Stock label for: Username: -->
<stock type="username-label"/>
</item>
- <item type="label">
+ <item type="label" id="password-label">
<pos anchor="ne" x="100%"/>
<normal color="#000000" font="Sans 12"/>
<!-- Stock label for: Password: -->
diff --git a/tdm/kfrontend/themes/minimalist/minimalist.xml b/tdm/kfrontend/themes/minimalist/minimalist.xml
index f1dfada8..dd903679 100644
--- a/tdm/kfrontend/themes/minimalist/minimalist.xml
+++ b/tdm/kfrontend/themes/minimalist/minimalist.xml
@@ -37,7 +37,7 @@
</item>
<!-- user field -->
- <item type="label">
+ <item type="label" id="username-label">
<pos anchor="nw" x="145" y="225"/>
<normal font="Sans 11" color="#dfdbd2"/>
<stock type="username-label"/>
@@ -58,7 +58,7 @@
<!-- password field -->
- <item type="label">
+ <item type="label" id="password-label">
<pos anchor="nw" x="145" y="285"/>
<normal font="Sans 11" color="#dfdbd2"/>
<stock type="password-label"/>
diff --git a/tdm/kfrontend/themes/o2_enterprise/enterprise.xml b/tdm/kfrontend/themes/o2_enterprise/enterprise.xml
index 39f159b0..11b87ae0 100644
--- a/tdm/kfrontend/themes/o2_enterprise/enterprise.xml
+++ b/tdm/kfrontend/themes/o2_enterprise/enterprise.xml
@@ -54,12 +54,12 @@
<normal alpha="0.0" color="#000000" />
<pos width="box" y="50%" anchor="w" height="box" />
<box xpadding="10" spacing="10" ypadding="0" orientation="vertical" >
- <item type="label" >
+ <item type="label" id="username-label">
<pos x="100%" anchor="ne" />
<normal color="#000000" font="Sans Condensed 10" />
<stock type="username-label" />
</item>
- <item type="label" >
+ <item type="label" id="password-label">
<pos x="100%" anchor="ne" />
<normal color="#000000" font="Sans Condensed 10" />
<stock type="password-label" />
diff --git a/tdmlib/dmctl.cpp b/tdmlib/dmctl.cpp
index 75e88fc6..00c3cb48 100644
--- a/tdmlib/dmctl.cpp
+++ b/tdmlib/dmctl.cpp
@@ -25,6 +25,7 @@
#include <dcopclient.h>
#include <tqregexp.h>
+#include <tqfile.h>
#include <X11/Xauth.h>
#include <X11/Xlib.h>
@@ -37,8 +38,34 @@
#include <fcntl.h>
#include <errno.h>
+#include <config.h>
+
+static TQString readcfg(const char *cfg_file) {
+ TQString ctl = "/var/run/xdmctl";
+
+ TQStringList lines;
+ TQFile file(cfg_file);
+ if ( file.open( IO_ReadOnly ) ) {
+ TQTextStream stream(&file);
+ TQString line;
+ while ( !stream.atEnd() ) {
+ line = stream.readLine();
+ TQStringList keyvaluepair = TQStringList::split("=", line, false);
+ if (keyvaluepair.count() > 1) {
+ if (keyvaluepair[0].lower() == "FifoDir") {
+ ctl = keyvaluepair[1];
+ }
+ }
+ }
+ file.close();
+ }
+
+ return ctl;
+}
+
static int DMType = DM::Unknown;
-static const char *ctl, *dpy;
+static const char *dpy;
+static TQString ctl;
DM::DM() : fd( -1 )
{
@@ -46,16 +73,27 @@ DM::DM() : fd( -1 )
struct sockaddr_un sa;
if (DMType == Unknown) {
- if (!(dpy = ::getenv( "DISPLAY" )))
- DMType = NoDM;
- else if ((ctl = ::getenv( "DM_CONTROL" )))
+ if (!(dpy = ::getenv( "DISPLAY" ))) {
+ // Try to read TDM control file
+ if ((ctl = readcfg(KDE_CONFDIR "/tdm/tdmrc")) != TQString::null) {
+ DMType = NewTDM;
+ }
+ else {
+ DMType = NoDM;
+ }
+ }
+ else if ((ctl = ::getenv( "DM_CONTROL" )) != TQString::null) {
DMType = NewTDM;
- else if ((ctl = ::getenv( "XDM_MANAGED" )) && ctl[0] == '/')
+ }
+ else if (((ctl = ::getenv( "XDM_MANAGED" )) != TQString::null) && ctl[0] == '/') {
DMType = OldTDM;
- else if (::getenv( "GDMSESSION" ))
+ }
+ else if (::getenv( "GDMSESSION" )) {
DMType = GDM;
- else
+ }
+ else {
DMType = NoDM;
+ }
}
switch (DMType) {
default:
@@ -76,12 +114,17 @@ DM::DM() : fd( -1 )
}
}
GDMAuthenticate();
- } else {
- if ((ptr = const_cast<char*>(strchr( dpy, ':' ))))
- ptr = strchr( ptr, '.' );
- snprintf( sa.sun_path, sizeof(sa.sun_path),
- "%s/dmctl-%.*s/socket",
- ctl, ptr ? int(ptr - dpy) : 512, dpy );
+ }
+ else {
+ if (!dpy) {
+ snprintf( sa.sun_path, sizeof(sa.sun_path), "%s/dmctl/socket", ctl.ascii() );
+ }
+ else {
+ if ((ptr = const_cast<char*>(strchr( dpy, ':' )))) {
+ ptr = strchr( ptr, '.' );
+ }
+ snprintf( sa.sun_path, sizeof(sa.sun_path), "%s/dmctl-%.*s/socket", ctl.ascii(), ptr ? int(ptr - dpy) : 512, dpy );
+ }
if (::connect( fd, (struct sockaddr *)&sa, sizeof(sa) )) {
::close( fd );
fd = -1;
@@ -100,8 +143,9 @@ DM::DM() : fd( -1 )
DM::~DM()
{
- if (fd >= 0)
+ if (fd >= 0) {
close( fd );
+ }
}
bool
@@ -172,13 +216,15 @@ DM::exec( const char *cmd, TQCString &buf )
bool
DM::canShutdown()
{
- if (DMType == OldTDM)
- return strstr( ctl, ",maysd" ) != 0;
+ if (DMType == OldTDM) {
+ return strstr( ctl.ascii(), ",maysd" ) != 0;
+ }
TQCString re;
- if (DMType == GDM)
+ if (DMType == GDM) {
return exec( "QUERY_LOGOUT_ACTION\n", re ) && re.find("HALT") >= 0;
+ }
return exec( "caps\n", re ) && re.find( "\tshutdown" ) >= 0;
}
@@ -282,7 +328,7 @@ DM::numReserve()
return 1; /* Bleh */
if (DMType == OldTDM)
- return strstr( ctl, ",rsvd" ) ? 1 : -1;
+ return strstr( ctl.ascii(), ",rsvd" ) ? 1 : -1;
TQCString re;
int p;
@@ -304,8 +350,9 @@ DM::startReserve()
bool
DM::localSessions( SessList &list )
{
- if (DMType == OldTDM)
+ if (DMType == OldTDM) {
return false;
+ }
TQCString re;
@@ -325,8 +372,9 @@ DM::localSessions( SessList &list )
list.append( se );
}
} else {
- if (!exec( "list\talllocal\n", re ))
+ if (!exec( "list\talllocal\n", re )) {
return false;
+ }
TQStringList sess = TQStringList::split( TQChar('\t'), re.data() + 3 );
for (TQStringList::ConstIterator it = sess.begin(); it != sess.end(); ++it) {
TQStringList ts = TQStringList::split( TQChar(','), *it, true );
diff --git a/tdmlib/kgreet_classic.cpp b/tdmlib/kgreet_classic.cpp
index 3d1cedc1..6aac4d96 100644
--- a/tdmlib/kgreet_classic.cpp
+++ b/tdmlib/kgreet_classic.cpp
@@ -45,6 +45,15 @@ protected:
static int echoMode;
+TQString KClassicGreeter::passwordPrompt() {
+ if (func == Authenticate) {
+ return i18n("&Password:");
+ }
+ else {
+ return i18n("Current &password:");
+ }
+}
+
KClassicGreeter::KClassicGreeter( KGreeterPluginHandler *_handler,
KdmThemer *themer,
TQWidget *parent, TQWidget *pred,
@@ -60,7 +69,7 @@ KClassicGreeter::KClassicGreeter( KGreeterPluginHandler *_handler,
running( false )
{
KdmItem *user_entry = 0, *pw_entry = 0;
- TQGridLayout *grid = 0;
+ grid = 0;
int line = 0;
layoutItem = 0;
@@ -120,11 +129,7 @@ KClassicGreeter::KClassicGreeter( KGreeterPluginHandler *_handler,
passwdEdit->adjustSize();
pw_entry->setWidget( passwdEdit );
} else {
- passwdLabel = new TQLabel( passwdEdit,
- func == Authenticate ?
- i18n("&Password:") :
- i18n("Current &password:"),
- parent );
+ passwdLabel = new TQLabel( passwdEdit, passwordPrompt(), parent );
grid->addWidget( passwdLabel, line, 0 );
grid->addWidget( passwdEdit, line++, 1 );
}
@@ -217,6 +222,10 @@ KClassicGreeter::setUser( const TQString &user )
passwdEdit->selectAll();
}
+void KClassicGreeter::lockUserEntry( const bool lock ) {
+ loginEdit->setEnabled(!lock);
+}
+
void // virtual
KClassicGreeter::setPassword( const TQString &pass )
{
@@ -276,10 +285,24 @@ void // virtual
KClassicGreeter::textPrompt( const char *prompt, bool echo, bool nonBlocking )
{
pExp = exp;
- if (echo)
+ if (echo) {
exp = 0;
- else if (!authTok)
+ }
+ else if (!authTok) {
exp = 1;
+ if (passwdLabel) {
+ if (prompt && (prompt[0] != 0)) {
+ passwdLabel->setText(prompt);
+ }
+ else {
+ passwdLabel->setText(passwordPrompt());
+ }
+ if (grid) {
+ grid->invalidate();
+ grid->activate();
+ }
+ }
+ }
else {
TQString pr( prompt );
if (pr.find( TQRegExp( "\\bpassword\\b", false ) ) >= 0) {
@@ -294,7 +317,8 @@ KClassicGreeter::textPrompt( const char *prompt, bool echo, bool nonBlocking )
KGreeterPluginHandler::IsSecret );
return;
}
- } else {
+ }
+ else {
handler->gplugMsgBox( TQMessageBox::Critical,
i18n("Unrecognized prompt \"%1\"")
.arg( prompt ) );
@@ -392,6 +416,15 @@ KClassicGreeter::succeeded()
void // virtual
KClassicGreeter::failed()
{
+ if (passwdLabel) {
+ // reset password prompt
+ passwdLabel->setText(passwordPrompt());
+ if (grid) {
+ grid->invalidate();
+ grid->activate();
+ }
+ }
+
// assert( running || timed_login );
setActive( false );
setActive2( false );
@@ -402,6 +435,15 @@ KClassicGreeter::failed()
void // virtual
KClassicGreeter::revive()
{
+ if (passwdLabel) {
+ // reset password prompt
+ passwdLabel->setText(passwordPrompt());
+ if (grid) {
+ grid->invalidate();
+ grid->activate();
+ }
+ }
+
// assert( !running );
setActive2( true );
if (authTok) {
@@ -425,6 +467,15 @@ KClassicGreeter::revive()
void // virtual
KClassicGreeter::clear()
{
+ if (passwdLabel) {
+ // reset password prompt
+ passwdLabel->setText(passwordPrompt());
+ if (grid) {
+ grid->invalidate();
+ grid->activate();
+ }
+ }
+
// assert( !running && !passwd1Edit );
passwdEdit->erase();
if (loginEdit) {
diff --git a/tdmlib/kgreet_classic.h b/tdmlib/kgreet_classic.h
index 1f467a52..78bacf50 100644
--- a/tdmlib/kgreet_classic.h
+++ b/tdmlib/kgreet_classic.h
@@ -50,6 +50,7 @@ class KClassicGreeter : public TQObject, public KGreeterPlugin {
virtual void presetEntity( const TQString &entity, int field );
virtual TQString getEntity() const;
virtual void setUser( const TQString &user );
+ virtual void lockUserEntry( const bool lock );
virtual void setPassword( const TQString &pass );
virtual void setEnabled( bool on );
virtual bool textMessage( const char *message, bool error );
@@ -70,6 +71,7 @@ class KClassicGreeter : public TQObject, public KGreeterPlugin {
void slotActivity();
private:
+ TQString passwordPrompt();
void setActive( bool enable );
void setActive2( bool enable );
void returnData();
@@ -81,6 +83,7 @@ class KClassicGreeter : public TQObject, public KGreeterPlugin {
TQString fixedUser, curUser;
Function func;
Context ctx;
+ TQGridLayout* grid;
int exp, pExp, has;
bool running, authTok;
};
diff --git a/tdmlib/kgreet_pam.cpp b/tdmlib/kgreet_pam.cpp
index b16dfb44..97d19afd 100644
--- a/tdmlib/kgreet_pam.cpp
+++ b/tdmlib/kgreet_pam.cpp
@@ -263,6 +263,10 @@ KPamGreeter::setUser( const TQString &user )
}
}
+void KPamGreeter::lockUserEntry( const bool lock ) {
+ loginEdit->setEnabled(!lock);
+}
+
void // virtual
KPamGreeter::setPassword( const TQString &pass )
{
diff --git a/tdmlib/kgreet_pam.h b/tdmlib/kgreet_pam.h
index 03c404c1..7772880a 100644
--- a/tdmlib/kgreet_pam.h
+++ b/tdmlib/kgreet_pam.h
@@ -50,6 +50,7 @@ class KPamGreeter : public TQObject, public KGreeterPlugin {
virtual void presetEntity( const TQString &entity, int field );
virtual TQString getEntity() const;
virtual void setUser( const TQString &user );
+ virtual void lockUserEntry( const bool lock );
virtual void setPassword( const TQString &pass );
virtual void setEnabled( bool on );
virtual bool textMessage( const char *message, bool error );
diff --git a/tdmlib/kgreet_winbind.cpp b/tdmlib/kgreet_winbind.cpp
index aa7e39b1..53b992fa 100644
--- a/tdmlib/kgreet_winbind.cpp
+++ b/tdmlib/kgreet_winbind.cpp
@@ -297,6 +297,10 @@ KWinbindGreeter::setUser( const TQString &user )
passwdEdit->selectAll();
}
+void KWinbindGreeter::lockUserEntry( const bool lock ) {
+ loginEdit->setEnabled(!lock);
+}
+
void // virtual
KWinbindGreeter::setPassword( const TQString &pass )
{
diff --git a/tdmlib/kgreet_winbind.h b/tdmlib/kgreet_winbind.h
index 54f2653f..8c41ca5d 100644
--- a/tdmlib/kgreet_winbind.h
+++ b/tdmlib/kgreet_winbind.h
@@ -54,6 +54,7 @@ class KWinbindGreeter : public TQObject, public KGreeterPlugin {
virtual void presetEntity( const TQString &entity, int field );
virtual TQString getEntity() const;
virtual void setUser( const TQString &user );
+ virtual void lockUserEntry( const bool lock );
virtual void setPassword( const TQString &pass );
virtual void setEnabled( bool on );
virtual bool textMessage( const char *message, bool error );
diff --git a/tdmlib/kgreeterplugin.h b/tdmlib/kgreeterplugin.h
index 92582845..4604a6aa 100644
--- a/tdmlib/kgreeterplugin.h
+++ b/tdmlib/kgreeterplugin.h
@@ -152,6 +152,12 @@ public:
virtual void setUser( const TQString &user ) = 0;
/**
+ * Lock or unlock editing of the username entry field
+ * @param lock true to lock, false to unlock
+ */
+ virtual void lockUserEntry( const bool lock ) = 0;
+
+ /**
* "Push" a password into the talker.
* @param pass the password to set.
*/
@@ -183,7 +189,7 @@ public:
/**
* Prompt the user for data. Reply by calling handler->gplugReturnText().
- * @param propmt the prompt to display. It may be null, in which case
+ * @param prompt the prompt to display. It may be null, in which case
* "Username"/"Password" should be shown and the replies should be tagged
* with the respective Is* flag.
* @param echo if true, a normal input widget can be used, otherwise one that