Add initial cryptographic card login support

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

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

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

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

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

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

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

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

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

@ -21,3 +21,4 @@ include( ConfigureChecks.cmake )
add_subdirectory( backend )
add_subdirectory( kfrontend )
add_subdirectory( cryptocardwatcher )

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

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

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

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

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

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

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

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

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

@ -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()) );
@ -268,6 +270,14 @@ KGVerify::setUser( const TQString &user )
gplugActivity();
}
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 )
{
@ -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.");
}
}