Browse Source

Add initial cryptographic card login support

Tested with themed greeter and SAK disabled
pull/2/head
Timothy Pearson 4 years ago
parent
commit
ce47730301

+ 14
- 2
kcheckpass/checkpass_pam.c View File

@@ -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:

+ 14
- 2
kcontrol/hwmanager/devicepropsdlg.cpp View File

@@ -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"));
}
}
}
}
}
}
}

+ 21
- 1
kdesktop/lock/lockdlg.cc View File

@@ -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"

+ 3
- 0
kdesktop/lock/lockdlg.h View File

@@ -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 *);

+ 137
- 17
kdesktop/lock/lockprocess.cc View File

@@ -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) {

+ 10
- 0
kdesktop/lock/lockprocess.h View File

@@ -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();

+ 10
- 2
kdesktop/lock/main.cc View File

@@ -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;

+ 67
- 15
kdesktop/lockeng.cc View File

@@ -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;
}

+ 5
- 0
kdesktop/lockeng.h View File

@@ -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;

+ 1
- 0
tdm/CMakeLists.txt View File

@@ -21,3 +21,4 @@ include( ConfigureChecks.cmake )

add_subdirectory( backend )
add_subdirectory( kfrontend )
add_subdirectory( cryptocardwatcher )

+ 14
- 5
tdm/backend/client.c View File

@@ -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();

+ 32
- 0
tdm/cryptocardwatcher/CMakeLists.txt View File

@@ -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
)


+ 139
- 0
tdm/cryptocardwatcher/main.cpp View File

@@ -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;
}

+ 86
- 0
tdm/cryptocardwatcher/watcher.cc View File

@@ -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"

+ 40
- 0
tdm/cryptocardwatcher/watcher.h View File

@@ -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__

+ 1
- 1
tdm/kfrontend/CMakeLists.txt View File

@@ -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}
)


+ 12
- 0
tdm/kfrontend/kgapp.cpp View File

@@ -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) {

+ 72
- 0
tdm/kfrontend/kgreeter.cpp View File

@@ -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 )

+ 4
- 0
tdm/kfrontend/kgreeter.h View File

@@ -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;

+ 139
- 61
tdm/kfrontend/kgverify.cpp View File

@@ -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;
}
}

+ 4
- 0
tdm/kfrontend/kgverify.h View File

@@ -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;

+ 16
- 5
tdm/kfrontend/themer/tdmitem.cpp View File

@@ -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);

+ 1
- 0
tdm/kfrontend/themer/tdmitem.h View File

@@ -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 );

+ 3
- 3
tdm/kfrontend/themer/tdmlabel.h View File

@@ -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 );


+ 6
- 0
tdm/kfrontend/themer/tdmthemer.cpp View File

@@ -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 )
{

+ 1
- 0
tdm/kfrontend/themer/tdmthemer.h View File

@@ -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


+ 2
- 2
tdm/kfrontend/themes/circles/circles.xml View File

@@ -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: -->

+ 2
- 2
tdm/kfrontend/themes/minimalist/minimalist.xml View File

@@ -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"/>

+ 2
- 2
tdm/kfrontend/themes/o2_enterprise/enterprise.xml View File

@@ -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" />

+ 68
- 20
tdmlib/dmctl.cpp View File

@@ -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 );

+ 60
- 9
tdmlib/kgreet_classic.cpp View File

@@ -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) {

+ 3
- 0
tdmlib/kgreet_classic.h View File

@@ -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;
};

+ 4
- 0
tdmlib/kgreet_pam.cpp View File

@@ -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 )
{

+ 1
- 0
tdmlib/kgreet_pam.h View File

@@ -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 );

+ 4
- 0
tdmlib/kgreet_winbind.cpp View File

@@ -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 )
{

+ 1
- 0
tdmlib/kgreet_winbind.h View File

@@ -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 );

+ 7
- 1
tdmlib/kgreeterplugin.h View File

@@ -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

Loading…
Cancel
Save