Browse Source

Add initial cryptographic card login support

Tested with themed greeter and SAK disabled
Timothy Pearson 3 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,
72 72
         repl[count].resp = pd->conv(ConvGetNormal, msg[count]->msg);
73 73
         break;
74 74
       case PAM_PROMPT_ECHO_OFF:
75
-        repl[count].resp =
76
-            pd->conv(ConvGetHidden, pd->classic ? 0 : msg[count]->msg);
75
+        if (pd->classic) {
76
+          // WARNING
77
+          // This is far from foolproof, but it's the best we can do at this time...
78
+          // Try to detect PIN entry requests
79
+          if (strstr(msg[count]->msg, "PIN")) {
80
+            repl[count].resp = pd->conv(ConvGetHidden, msg[count]->msg);
81
+          }
82
+          else {
83
+            repl[count].resp = pd->conv(ConvGetHidden, 0);
84
+          }
85
+        }
86
+        else {
87
+          repl[count].resp = pd->conv(ConvGetHidden, msg[count]->msg);
88
+        }
77 89
         break;
78 90
 #ifdef PAM_BINARY_PROMPT
79 91
       case PAM_BINARY_PROMPT:

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

@@ -779,8 +779,8 @@ void DevicePropertiesDialog::populateDeviceInformation() {
779 779
 		if (m_device->type() == TDEGenericDeviceType::CryptographicCard) {
780 780
 			TDECryptographicCardDevice* cdevice = static_cast<TDECryptographicCardDevice*>(m_device);
781 781
 
782
-			connect(cdevice, TQT_SIGNAL(cardInserted()), this, TQT_SLOT(cryptographicCardInserted()));
783
-			connect(cdevice, TQT_SIGNAL(cardRemoved()), this, TQT_SLOT(cryptographicCardRemoved()));
782
+			connect(cdevice, TQT_SIGNAL(cardInserted(TDECryptographicCardDevice*)), this, TQT_SLOT(cryptographicCardInserted()));
783
+			connect(cdevice, TQT_SIGNAL(cardRemoved(TDECryptographicCardDevice*)), this, TQT_SLOT(cryptographicCardRemoved()));
784 784
 
785 785
 			updateCryptographicCardStatusDisplay();
786 786
 		}
@@ -926,6 +926,7 @@ void DevicePropertiesDialog::cryptLUKSAddKey() {
926 926
 			unsigned int key_slot = lvi->text(0).toUInt();
927 927
 			bool allow_card = false;
928 928
 			bool use_card = false;
929
+			bool luks_card_key_modified = false;
929 930
 			KSSLCertificate* card_cert = NULL;
930 931
 			X509* card_cert_x509;
931 932
 			TQString disk_uuid = sdevice->diskUUID();
@@ -988,6 +989,7 @@ void DevicePropertiesDialog::cryptLUKSAddKey() {
988 989
 
989 990
 						// Use the secret key as the LUKS passcode
990 991
 						new_password = randomKey;
992
+						luks_card_key_modified = true;
991 993
 					}
992 994
 					else {
993 995
 						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() {
1081 1083
 							sdevice->cryptClearOperationsUnlockPassword();
1082 1084
 							KMessageBox::error(this, i18n("<qt><b>Key write failed</b><br>Please check the LUKS password and try again</qt>"), i18n("Key write failure"));
1083 1085
 						}
1086
+						else {
1087
+							if (luks_card_key_modified) {
1088
+								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) {
1089
+									// Update the initramfs
1090
+									if (system("update-initramfs -u -k all") != 0) {
1091
+										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"));
1092
+									}
1093
+								}
1094
+							}
1095
+						}
1084 1096
 					}
1085 1097
 				}
1086 1098
 			}

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

@@ -513,7 +513,17 @@ void PasswordDlg::handleVerify()
513 513
 		case ConvGetHidden:
514 514
 			if (!GRecvArr( &arr ))
515 515
 				break;
516
-			greet->textPrompt( arr, false, false );
516
+			if (arr && (arr[0] != 0)) {
517
+				// Reset password entry and change text
518
+				greet->start();
519
+				greet->textPrompt( arr, false, false );
520
+				// Force relayout
521
+				setFixedSize( sizeHint().width(), sizeHint().height() + 1 );
522
+				setFixedSize( sizeHint() );
523
+			}
524
+			else {
525
+				greet->textPrompt( arr, false, false );
526
+			}
517 527
 			if (arr)
518 528
 				::free( arr );
519 529
 			return;
@@ -915,4 +925,14 @@ void PasswordDlg::capsLocked()
915 925
 	updateLabel();
916 926
 }
917 927
 
928
+void PasswordDlg::attemptCardLogin() {
929
+	greet->start();
930
+	greet->next();
931
+}
932
+
933
+void PasswordDlg::resetCardLogin() {
934
+	greet->abort();
935
+	greet->start();
936
+}
937
+
918 938
 #include "lockdlg.moc"

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

@@ -49,6 +49,9 @@ class PasswordDlg : public TQDialog, public KGreeterPluginHandler
49 49
 		virtual void gplugStart();
50 50
 		virtual void gplugActivity();
51 51
 		virtual void gplugMsgBox( TQMessageBox::Icon type, const TQString &text );
52
+
53
+		virtual void attemptCardLogin();
54
+		virtual void resetCardLogin();
52 55
 	
53 56
 	protected:
54 57
 		virtual void timerEvent(TQTimerEvent *);

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

@@ -34,6 +34,7 @@
34 34
 #include <tdeapplication.h>
35 35
 #include <kservicegroup.h>
36 36
 #include <kdebug.h>
37
+#include <kuser.h>
37 38
 #include <tdemessagebox.h>
38 39
 #include <tdeglobalsettings.h>
39 40
 #include <tdelocale.h>
@@ -112,6 +113,8 @@ Status DPMSInfo ( Display *, CARD16 *, BOOL * );
112 113
 #include <GL/glx.h>
113 114
 #endif
114 115
 
116
+#define KDESKTOP_DEBUG_ID 1204
117
+
115 118
 #define LOCK_GRACE_DEFAULT          5000
116 119
 #define AUTOLOGOUT_DEFAULT          600
117 120
 
@@ -146,7 +149,7 @@ Atom kde_wm_transparent_to_black = 0;
146 149
 
147 150
 static void segv_handler(int)
148 151
 {
149
-	kdError(1204) << "A fatal exception was encountered."
152
+	kdError(KDESKTOP_DEBUG_ID) << "A fatal exception was encountered."
150 153
 		<< " Trapping and ignoring it so as not to compromise desktop security..."
151 154
 		<< kdBacktrace() << endl;
152 155
 	sleep(1);
@@ -272,7 +275,7 @@ LockProcess::LockProcess()
272 275
 	KServiceGroup::Ptr servGroup = KServiceGroup::baseGroup( "screensavers");
273 276
 	if (servGroup) {
274 277
 		relPath=servGroup->relPath();
275
-		kdDebug(1204) << "relPath=" << relPath << endl;
278
+		kdDebug(KDESKTOP_DEBUG_ID) << "relPath=" << relPath << endl;
276 279
 	}
277 280
 	TDEGlobal::dirs()->addResourceType("scrsav",
278 281
 					TDEGlobal::dirs()->kde_default("apps") +
@@ -290,6 +293,19 @@ LockProcess::LockProcess()
290 293
 		}
291 294
 	}
292 295
 
296
+	// Initialize SmartCard readers
297
+	TDEGenericDevice *hwdevice;
298
+	TDEHardwareDevices *hwdevices = TDEGlobal::hardwareDevices();
299
+	TDEGenericHardwareList cardReaderList = hwdevices->listByDeviceClass(TDEGenericDeviceType::CryptographicCard);
300
+	for (hwdevice = cardReaderList.first(); hwdevice; hwdevice = cardReaderList.next()) {
301
+		TDECryptographicCardDevice* cdevice = static_cast<TDECryptographicCardDevice*>(hwdevice);
302
+		// connect(cdevice, SIGNAL(pinRequested(TQString,TDECryptographicCardDevice*)), this, SLOT(cryptographicCardPinRequested(TQString,TDECryptographicCardDevice*)));
303
+		connect(cdevice, TQT_SIGNAL(cardInserted(TDECryptographicCardDevice*)), this, TQT_SLOT(cryptographicCardInserted(TDECryptographicCardDevice*)));
304
+		connect(cdevice, TQT_SIGNAL(cardRemoved(TDECryptographicCardDevice*)), this, TQT_SLOT(cryptographicCardRemoved(TDECryptographicCardDevice*)));
305
+		cdevice->enableCardMonitoring(true);
306
+		// cdevice->enablePINEntryCallbacks(true);
307
+	}
308
+
293 309
 #ifdef KEEP_MOUSE_UNGRABBED
294 310
 	setEnabled(false);
295 311
 #endif
@@ -781,11 +797,11 @@ void LockProcess::readSaver()
781 797
 			TQStringList saverTypes = TQStringList::split(";", saverType);
782 798
 			for (uint i = 0; i < saverTypes.count(); i++) {
783 799
 				if ((saverTypes[i] == "ManipulateScreen") && !manipulatescreen) {
784
-					kdDebug(1204) << "Screensaver is type ManipulateScreen and ManipulateScreen is forbidden" << endl;
800
+					kdDebug(KDESKTOP_DEBUG_ID) << "Screensaver is type ManipulateScreen and ManipulateScreen is forbidden" << endl;
785 801
 					mForbidden = true;
786 802
 				}
787 803
 				if ((saverTypes[i] == "OpenGL") && !opengl) {
788
-					kdDebug(1204) << "Screensaver is type OpenGL and OpenGL is forbidden" << endl;
804
+					kdDebug(KDESKTOP_DEBUG_ID) << "Screensaver is type OpenGL and OpenGL is forbidden" << endl;
789 805
 					mForbidden = true;
790 806
 				}
791 807
 				if (saverTypes[i] == "OpenGL") {
@@ -794,7 +810,7 @@ void LockProcess::readSaver()
794 810
 			}
795 811
 		}
796 812
 
797
-		kdDebug(1204) << "mForbidden: " << (mForbidden ? "true" : "false") << endl;
813
+		kdDebug(KDESKTOP_DEBUG_ID) << "mForbidden: " << (mForbidden ? "true" : "false") << endl;
798 814
 
799 815
 		if (trinity_desktop_lock_use_system_modal_dialogs) {
800 816
 			if (config.hasActionGroup("InWindow")) {
@@ -968,7 +984,7 @@ void LockProcess::createSaverWindow()
968 984
 		}
969 985
 	}
970 986
 
971
-	kdDebug(1204) << "Saver window Id: " << winId() << endl;
987
+	kdDebug(KDESKTOP_DEBUG_ID) << "Saver window Id: " << winId() << endl;
972 988
 }
973 989
 
974 990
 void LockProcess::desktopResized()
@@ -1307,7 +1323,7 @@ bool LockProcess::startSaver(bool notify_ready)
1307 1323
 {
1308 1324
 	if (!child_saver && !grabInput())
1309 1325
 	{
1310
-		kdWarning(1204) << "LockProcess::startSaver() grabInput() failed!!!!" << endl;
1326
+		kdWarning(KDESKTOP_DEBUG_ID) << "LockProcess::startSaver() grabInput() failed!!!!" << endl;
1311 1327
 		return false;
1312 1328
 	}
1313 1329
 	mBusy = false;
@@ -1393,7 +1409,7 @@ bool LockProcess::startSaver(bool notify_ready)
1393 1409
 //
1394 1410
 void LockProcess::stopSaver()
1395 1411
 {
1396
-	kdDebug(1204) << "LockProcess: stopping saver" << endl;
1412
+	kdDebug(KDESKTOP_DEBUG_ID) << "LockProcess: stopping saver" << endl;
1397 1413
 	mHackProc.kill(SIGCONT);
1398 1414
 	stopHack();
1399 1415
 	mSuspended = false;
@@ -1446,30 +1462,30 @@ bool LockProcess::startLock()
1446 1462
 		GreeterPluginHandle plugin;
1447 1463
 		TQString path = KLibLoader::self()->findLibrary( ((*it)[0] == '/' ? *it : "kgreet_" + *it ).latin1() );
1448 1464
 		if (path.isEmpty()) {
1449
-			kdWarning(1204) << "GreeterPlugin " << *it << " does not exist" << endl;
1465
+			kdWarning(KDESKTOP_DEBUG_ID) << "GreeterPlugin " << *it << " does not exist" << endl;
1450 1466
 			continue;
1451 1467
 		}
1452 1468
 		if (!(plugin.library = KLibLoader::self()->library( path.latin1() ))) {
1453
-			kdWarning(1204) << "Cannot load GreeterPlugin " << *it << " (" << path << ")" << endl;
1469
+			kdWarning(KDESKTOP_DEBUG_ID) << "Cannot load GreeterPlugin " << *it << " (" << path << ")" << endl;
1454 1470
 			continue;
1455 1471
 		}
1456 1472
 		if (!plugin.library->hasSymbol( "kgreeterplugin_info" )) {
1457
-			kdWarning(1204) << "GreeterPlugin " << *it << " (" << path << ") is no valid greet widget plugin" << endl;
1473
+			kdWarning(KDESKTOP_DEBUG_ID) << "GreeterPlugin " << *it << " (" << path << ") is no valid greet widget plugin" << endl;
1458 1474
 			plugin.library->unload();
1459 1475
 			continue;
1460 1476
 		}
1461 1477
 		plugin.info = (kgreeterplugin_info*)plugin.library->symbol( "kgreeterplugin_info" );
1462 1478
 		if (plugin.info->method && !mMethod.isEmpty() && mMethod != plugin.info->method) {
1463
-			kdDebug(1204) << "GreeterPlugin " << *it << " (" << path << ") serves " << plugin.info->method << ", not " << mMethod << endl;
1479
+			kdDebug(KDESKTOP_DEBUG_ID) << "GreeterPlugin " << *it << " (" << path << ") serves " << plugin.info->method << ", not " << mMethod << endl;
1464 1480
 			plugin.library->unload();
1465 1481
 			continue;
1466 1482
 		}
1467 1483
 		if (!plugin.info->init( mMethod, getConf, this )) {
1468
-			kdDebug(1204) << "GreeterPlugin " << *it << " (" << path << ") refuses to serve " << mMethod << endl;
1484
+			kdDebug(KDESKTOP_DEBUG_ID) << "GreeterPlugin " << *it << " (" << path << ") refuses to serve " << mMethod << endl;
1469 1485
 			plugin.library->unload();
1470 1486
 			continue;
1471 1487
 		}
1472
-		kdDebug(1204) << "GreeterPlugin " << *it << " (" << plugin.info->method << ", " << plugin.info->name << ") loaded" << endl;
1488
+		kdDebug(KDESKTOP_DEBUG_ID) << "GreeterPlugin " << *it << " (" << plugin.info->method << ", " << plugin.info->name << ") loaded" << endl;
1473 1489
 		greetPlugin = plugin;
1474 1490
 		mLocked = true;
1475 1491
 		DM().setLock( true );
@@ -1588,7 +1604,7 @@ bool LockProcess::startHack()
1588 1604
 	if (!path.isEmpty()) {
1589 1605
 		mHackProc << path;
1590 1606
 
1591
-		kdDebug(1204) << "Starting hack: " << path << endl;
1607
+		kdDebug(KDESKTOP_DEBUG_ID) << "Starting hack: " << path << endl;
1592 1608
 
1593 1609
 		while (!ts.atEnd()) {
1594 1610
 			ts >> word;
@@ -2297,10 +2313,10 @@ void LockProcess::stayOnTop()
2297 2313
 		// and stack others below it
2298 2314
 		Window* stack = new Window[ mDialogs.count() + mVkbdWindows.count() + 1 ];
2299 2315
 		int count = 0;
2300
-		for( TQValueList< VkbdWindow >::ConstIterator it = mVkbdWindows.begin(); it != mVkbdWindows.end(); ++it )
2316
+		for( TQValueList< VkbdWindow >::ConstIterator it = mVkbdWindows.begin(); it != mVkbdWindows.end(); ++it ) {
2301 2317
 			stack[ count++ ] = (*it).id;
2302 2318
 		}
2303
-		for( TQValueList< TQWidget* >::ConstIterator it = mDialogs.begin(); it != mDialogs.end(); ++it )
2319
+		for( TQValueList< TQWidget* >::ConstIterator it = mDialogs.begin(); it != mDialogs.end(); ++it ) {
2304 2320
 			stack[ count++ ] = (*it)->winId();
2305 2321
 		}
2306 2322
 		stack[ count++ ] = winId();
@@ -2795,6 +2811,110 @@ void LockProcess::processInputPipeCommand(TQString inputcommand) {
2795 2811
 	}
2796 2812
 }
2797 2813
 
2814
+void LockProcess::cryptographicCardInserted(TDECryptographicCardDevice* cdevice) {
2815
+	TQString login_name = TQString::null;
2816
+	X509CertificatePtrList certList = cdevice->cardX509Certificates();
2817
+	if (certList.count() > 0) {
2818
+		KSSLCertificate* card_cert = NULL;
2819
+		card_cert = KSSLCertificate::fromX509(certList[0]);
2820
+		TQStringList cert_subject_parts = TQStringList::split("/", card_cert->getSubject(), false);
2821
+		for (TQStringList::Iterator it = cert_subject_parts.begin(); it != cert_subject_parts.end(); ++it ) {
2822
+			TQString lcpart = (*it).lower();
2823
+			if (lcpart.startsWith("cn=")) {
2824
+				login_name = lcpart.right(lcpart.length() - strlen("cn="));
2825
+			}
2826
+		}
2827
+		delete card_cert;
2828
+	}
2829
+
2830
+	if (login_name != "") {
2831
+		KUser user;
2832
+		if (login_name == user.loginName()) {
2833
+			// Activate appropriate VT
2834
+			DM dm;
2835
+			SessList sess;
2836
+			if (dm.localSessions(sess)) {
2837
+				TQString user, loc;
2838
+				for (SessList::ConstIterator it = sess.begin(); it != sess.end(); ++it) {
2839
+					DM::sess2Str2(*it, user, loc);
2840
+					if ((*it).self) {
2841
+						// Switch VTs
2842
+						DM().switchVT((*it).vt);
2843
+						break;
2844
+					}
2845
+				}
2846
+			}
2847
+
2848
+			// Pass login to the PAM stack...
2849
+			if (dynamic_cast<SAKDlg*>(currentDialog)) {
2850
+				dynamic_cast<SAKDlg*>(currentDialog)->closeDialogForced();
2851
+				TQTimer::singleShot(0, this, SLOT(signalPassDlgToAttemptCardLogin()));
2852
+			}
2853
+			else if (dynamic_cast<SecureDlg*>(currentDialog)) {
2854
+				dynamic_cast<SecureDlg*>(currentDialog)->closeDialogForced();
2855
+				TQTimer::singleShot(0, this, SLOT(signalPassDlgToAttemptCardLogin()));
2856
+			}
2857
+			else if (dynamic_cast<PasswordDlg*>(currentDialog)) {
2858
+				signalPassDlgToAttemptCardLogin();
2859
+			}
2860
+		}
2861
+	}
2862
+}
2863
+
2864
+void LockProcess::cryptographicCardRemoved(TDECryptographicCardDevice* cdevice) {
2865
+	PasswordDlg* passDlg = dynamic_cast<PasswordDlg*>(currentDialog);
2866
+	if (passDlg) {
2867
+		passDlg->resetCardLogin();
2868
+	}
2869
+	else {
2870
+		TQTimer::singleShot(0, this, SLOT(signalPassDlgToAttemptCardAbort()));
2871
+	}
2872
+}
2873
+
2874
+void LockProcess::signalPassDlgToAttemptCardLogin() {
2875
+	PasswordDlg* passDlg = dynamic_cast<PasswordDlg*>(currentDialog);
2876
+	if (passDlg) {
2877
+		passDlg->attemptCardLogin();
2878
+	}
2879
+	else {
2880
+		if (currentDialog) {
2881
+			// Try again later
2882
+			TQTimer::singleShot(0, this, SLOT(signalPassDlgToAttemptCardLogin()));
2883
+		}
2884
+	}
2885
+}
2886
+
2887
+void LockProcess::signalPassDlgToAttemptCardAbort() {
2888
+	PasswordDlg* passDlg = dynamic_cast<PasswordDlg*>(currentDialog);
2889
+	if (passDlg) {
2890
+		passDlg->resetCardLogin();
2891
+	}
2892
+	else {
2893
+		if (currentDialog) {
2894
+			// Try again later
2895
+			TQTimer::singleShot(0, this, SLOT(signalPassDlgToAttemptCardAbort()));
2896
+		}
2897
+	}
2898
+}
2899
+
2900
+void LockProcess::cryptographicCardPinRequested(TQString prompt, TDECryptographicCardDevice* cdevice) {
2901
+	TQCString password;
2902
+	const char * pin_entry;
2903
+
2904
+	QueryDlg qryDlg(this);
2905
+	qryDlg.updateLabel(prompt);
2906
+	qryDlg.setUnlockIcon();
2907
+	mForceReject = false;
2908
+	execDialog(&qryDlg);
2909
+	if (mForceReject == false) {
2910
+		pin_entry = qryDlg.getEntry();
2911
+		cdevice->setProvidedPin(pin_entry);
2912
+	}
2913
+	else {
2914
+		cdevice->setProvidedPin(TQString::null);
2915
+	}
2916
+}
2917
+
2798 2918
 void LockProcess::fullyOnline() {
2799 2919
 	if (!mFullyOnlineSent) {
2800 2920
 		if (kdesktop_pid > 0) {

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

@@ -10,6 +10,11 @@
10 10
 #ifndef __LOCKENG_H__
11 11
 #define __LOCKENG_H__
12 12
 
13
+#include <ksslcertificate.h>
14
+
15
+#include <tdehardwaredevices.h>
16
+#include <tdecryptographiccarddevice.h>
17
+
13 18
 #include <kgreeterplugin.h>
14 19
 
15 20
 #include <kprocess.h>
@@ -134,6 +139,11 @@ class LockProcess : public TQWidget
134 139
 		void startSecureDialog();
135 140
 		void slotMouseActivity(XEvent *event);
136 141
 		void processInputPipeCommand(TQString command);
142
+		void cryptographicCardInserted(TDECryptographicCardDevice*);
143
+		void cryptographicCardRemoved(TDECryptographicCardDevice*);
144
+		void cryptographicCardPinRequested(TQString prompt, TDECryptographicCardDevice* cdevice);
145
+		void signalPassDlgToAttemptCardLogin();
146
+		void signalPassDlgToAttemptCardAbort();
137 147
 
138 148
 	private:
139 149
 		void configure();

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

@@ -372,15 +372,23 @@ int main( int argc, char **argv )
372 372
 		KSimpleConfig* tdmconfig;
373 373
 		OPEN_TDMCONFIG_AND_SET_GROUP
374 374
 
375
+		sigset_t new_mask;
376
+		sigset_t orig_mask;
377
+
378
+		// Block reception of all signals in this thread
379
+		sigprocmask(SIG_BLOCK, &new_mask, NULL);
380
+
381
+		// Create new LockProcess, which also spawns threads inheriting the blocked signal mask
375 382
 		trinity_desktop_lock_process = new LockProcess;
376 383
 
384
+		// Unblock reception of all signals in this thread
385
+		sigprocmask(SIG_UNBLOCK, &new_mask, NULL);
386
+
377 387
 		// Start loading core functions, such as the desktop wallpaper interface
378 388
 		app->processEvents();
379 389
 
380 390
 		if (args->isSet( "internal" )) {
381 391
 			kdesktop_pid = atoi(args->getOption( "internal" ));
382
-			sigset_t new_mask;
383
-			sigset_t orig_mask;
384 392
 			struct sigaction act;
385 393
 
386 394
 			in_internal_mode = TRUE;

+ 67
- 15
kdesktop/lockeng.cc View File

@@ -11,10 +11,16 @@
11 11
 
12 12
 #include <stdlib.h>
13 13
 
14
+#include <ksslcertificate.h>
15
+
16
+#include <tdehardwaredevices.h>
17
+#include <tdecryptographiccarddevice.h>
18
+
14 19
 #include <kstandarddirs.h>
15 20
 #include <tdeapplication.h>
16 21
 #include <kservicegroup.h>
17 22
 #include <kdebug.h>
23
+#include <kuser.h>
18 24
 #include <tdelocale.h>
19 25
 #include <tqfile.h>
20 26
 #include <tqtimer.h>
@@ -82,6 +88,7 @@ SaverEngine::SaverEngine()
82 88
 	  mTerminationRequested(false),
83 89
 	  mSaverProcessReady(false),
84 90
 	  mNewVTAfterLockEngage(false),
91
+	  mValidCryptoCardInserted(false),
85 92
 	  mSwitchVTAfterLockEngage(-1),
86 93
 	  dBusLocal(0),
87 94
 	  dBusWatch(0),
@@ -158,6 +165,17 @@ SaverEngine::SaverEngine()
158 165
 	sigaddset(&mThreadBlockSet, SIGTTIN);
159 166
 	pthread_sigmask(SIG_BLOCK, &mThreadBlockSet, NULL);
160 167
 
168
+	// Initialize SmartCard readers
169
+	TDEGenericDevice *hwdevice;
170
+	TDEHardwareDevices *hwdevices = TDEGlobal::hardwareDevices();
171
+	TDEGenericHardwareList cardReaderList = hwdevices->listByDeviceClass(TDEGenericDeviceType::CryptographicCard);
172
+	for (hwdevice = cardReaderList.first(); hwdevice; hwdevice = cardReaderList.next()) {
173
+		TDECryptographicCardDevice* cdevice = static_cast<TDECryptographicCardDevice*>(hwdevice);
174
+		connect(cdevice, TQT_SIGNAL(certificateListAvailable(TDECryptographicCardDevice*)), this, TQT_SLOT(cryptographicCardInserted(TDECryptographicCardDevice*)));
175
+		connect(cdevice, TQT_SIGNAL(cardRemoved(TDECryptographicCardDevice*)), this, TQT_SLOT(cryptographicCardRemoved(TDECryptographicCardDevice*)));
176
+		cdevice->enableCardMonitoring(true);
177
+	}
178
+
161 179
 	dBusConnect();
162 180
 }
163 181
 
@@ -186,6 +204,43 @@ SaverEngine::~SaverEngine()
186 204
 	delete m_helperThread;
187 205
 }
188 206
 
207
+void SaverEngine::cryptographicCardInserted(TDECryptographicCardDevice* cdevice) {
208
+	TQString login_name = TQString::null;
209
+	X509CertificatePtrList certList = cdevice->cardX509Certificates();
210
+	if (certList.count() > 0) {
211
+		KSSLCertificate* card_cert = NULL;
212
+		card_cert = KSSLCertificate::fromX509(certList[0]);
213
+		TQStringList cert_subject_parts = TQStringList::split("/", card_cert->getSubject(), false);
214
+		for (TQStringList::Iterator it = cert_subject_parts.begin(); it != cert_subject_parts.end(); ++it ) {
215
+			TQString lcpart = (*it).lower();
216
+			if (lcpart.startsWith("cn=")) {
217
+				login_name = lcpart.right(lcpart.length() - strlen("cn="));
218
+			}
219
+		}
220
+		delete card_cert;
221
+	}
222
+
223
+	if (login_name != "") {
224
+		KUser user;
225
+		if (login_name == user.loginName()) {
226
+			mValidCryptoCardInserted = true;
227
+			// Disable saver
228
+			enable(false);
229
+		}
230
+	}
231
+}
232
+
233
+void SaverEngine::cryptographicCardRemoved(TDECryptographicCardDevice* cdevice) {
234
+	if (mValidCryptoCardInserted) {
235
+		// Restore saver timeout
236
+		configure();
237
+
238
+		// Force lock
239
+		lockScreen();
240
+	}
241
+	mValidCryptoCardInserted = false;
242
+}
243
+
189 244
 //---------------------------------------------------------------------------
190 245
 //
191 246
 // This should be called only using DCOP.
@@ -283,28 +338,25 @@ bool SaverEngine::enable( bool e )
283 338
 
284 339
 	mEnabled = e;
285 340
 
286
-	if (mEnabled)
287
-	{
341
+	if (mEnabled) {
288 342
 		if ( !mXAutoLock ) {
289 343
 			mXAutoLock = new XAutoLock();
290 344
 			connect(mXAutoLock, TQT_SIGNAL(timeout()), TQT_SLOT(idleTimeout()));
291 345
 		}
292
-			mXAutoLock->setTimeout(mTimeout);
293
-			mXAutoLock->setDPMS(true);
346
+		mXAutoLock->setTimeout(mTimeout);
347
+		mXAutoLock->setDPMS(true);
294 348
 		//mXAutoLock->changeCornerLockStatus( mLockCornerTopLeft, mLockCornerTopRight, mLockCornerBottomLeft, mLockCornerBottomRight);
295 349
 	
296
-			// We'll handle blanking
297
-			XSetScreenSaver(tqt_xdisplay(), mTimeout + 10, mXInterval, PreferBlanking, mXExposures);
298
-			kdDebug() << "XSetScreenSaver " << mTimeout + 10 << endl;
299
-	
300
-			mXAutoLock->start();
301
-	
302
-			kdDebug(1204) << "Saver Engine started, timeout: " << mTimeout << endl;
350
+		// We'll handle blanking
351
+		XSetScreenSaver(tqt_xdisplay(), mTimeout + 10, mXInterval, PreferBlanking, mXExposures);
352
+		kdDebug() << "XSetScreenSaver " << mTimeout + 10 << endl;
353
+
354
+		mXAutoLock->start();
355
+
356
+		kdDebug(1204) << "Saver Engine started, timeout: " << mTimeout << endl;
303 357
 	}
304
-	else
305
-	{
306
-		if (mXAutoLock)
307
-		{
358
+	else {
359
+		if (mXAutoLock) {
308 360
 			delete mXAutoLock;
309 361
 			mXAutoLock = 0;
310 362
 		}

+ 5
- 0
kdesktop/lockeng.h View File

@@ -18,6 +18,7 @@
18 18
 
19 19
 #include <tqdbusconnection.h>
20 20
 
21
+class TDECryptographicCardDevice;
21 22
 class DCOPClientTransaction;
22 23
 class TQT_DBusMessage;
23 24
 class TQT_DBusProxy;
@@ -134,6 +135,9 @@ private slots:
134 135
 	void handleSecureDialog();
135 136
 	void slotSAKProcessExited();
136 137
 
138
+	void cryptographicCardInserted(TDECryptographicCardDevice*);
139
+	void cryptographicCardRemoved(TDECryptographicCardDevice*);
140
+
137 141
 	/**
138 142
 	 * Enable wallpaper exports
139 143
 	 */
@@ -186,6 +190,7 @@ private:
186 190
 	bool mTerminationRequested;
187 191
 	bool mSaverProcessReady;
188 192
 	bool mNewVTAfterLockEngage;
193
+	bool mValidCryptoCardInserted;
189 194
 	int mSwitchVTAfterLockEngage;
190 195
 	struct sigaction mSignalAction;
191 196
 	TQT_DBusConnection dBusConn;

+ 1
- 0
tdm/CMakeLists.txt View File

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

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

@@ -180,7 +180,7 @@ PAM_conv( int num_msg,
180 180
 
181 181
 	ReInitErrorLog();
182 182
 	Debug( "PAM_conv\n" );
183
-	for (count = 0; count < num_msg; count++)
183
+	for (count = 0; count < num_msg; count++) {
184 184
 		switch (msg[count]->msg_style) {
185 185
 		case PAM_TEXT_INFO:
186 186
 			Debug( " PAM_TEXT_INFO: %s\n", msg[count]->msg );
@@ -201,9 +201,18 @@ PAM_conv( int num_msg,
201 201
 				/* case PAM_PROMPT_ECHO_ON: cannot happen */
202 202
 				case PAM_PROMPT_ECHO_OFF:
203 203
 					Debug( " PAM_PROMPT_ECHO_OFF (usecur): %s\n", msg[count]->msg );
204
-					if (!curpass)
205
-						pd->gconv( GCONV_PASS, 0 );
206
-					StrDup( &reply[count].resp, curpass );
204
+					// WARNING
205
+					// This is far from foolproof, but it's the best we can do at this time...
206
+					// Try to detect PIN entry requests
207
+					if (strstr(msg[count]->msg, "PIN")) {
208
+						reply[count].resp = pd->gconv(GCONV_HIDDEN, msg[count]->msg);
209
+					}
210
+					else {
211
+						if (!curpass) {
212
+							pd->gconv( GCONV_PASS, 0 );
213
+						}
214
+						StrDup( &reply[count].resp, curpass );
215
+					}
207 216
 					break;
208 217
 				default:
209 218
 					LogError( "Unknown PAM message style <%d>\n", msg[count]->msg_style );
@@ -237,6 +246,7 @@ PAM_conv( int num_msg,
237 246
 			}
238 247
 			reply[count].resp_retcode = PAM_SUCCESS; /* unused in linux-pam */
239 248
 		}
249
+	}
240 250
 	Debug( " PAM_conv success\n" );
241 251
 	*resp = reply;
242 252
 	return PAM_SUCCESS;
@@ -769,7 +779,6 @@ Verify( GConvFunc gconv, int rootok )
769 779
 	}
770 780
 
771 781
 #ifdef USE_PAM
772
-
773 782
 	Debug( " pam_acct_mgmt() ...\n" );
774 783
 	pretc = pam_acct_mgmt( pamh, 0 );
775 784
 	ReInitErrorLog();

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

@@ -0,0 +1,32 @@
1
+#################################################
2
+#
3
+#  (C) 2015 Timothy Pearson
4
+#  kb9vqf (AT) pearsoncomputing.net
5
+#
6
+#  Improvements and feedback are welcome
7
+#
8
+#  This file is released under GPL >= 2
9
+#
10
+#################################################
11
+
12
+include_directories(
13
+  ${CMAKE_CURRENT_BINARY_DIR}
14
+  ${CMAKE_SOURCE_DIR}/tdmlib
15
+  ${TDE_INCLUDE_DIR}
16
+  ${TQT_INCLUDE_DIRS}
17
+)
18
+
19
+link_directories(
20
+  ${TQT_LIBRARY_DIRS}
21
+)
22
+
23
+
24
+##### tdecryptocardwatcher (executable) #########
25
+
26
+tde_add_executable( tdecryptocardwatcher AUTOMOC
27
+  SOURCES main.cpp watcher.cc
28
+  LINK tdecore-shared tdeio-shared dmctl-static
29
+  DESTINATION ${BIN_INSTALL_DIR}
30
+  SETUID
31
+)
32
+

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

@@ -0,0 +1,139 @@
1
+/*
2
+ * Copyright 2015 Timothy Pearson <kb9vqf@pearsoncomputing.net>
3
+ * 
4
+ * This file is part of cryptocardwatcher, the TDE Cryptographic Card Session Monitor
5
+ * 
6
+ * cryptocardwatcher is free software: you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License as
8
+ * published by the Free Software Foundation, either version 3
9
+ * of the License, or (at your option) any later version.
10
+ *
11
+ * cryptocardwatcher is distributed in the hope that it will be useful, but
12
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU General Public
17
+ * License along with cryptocardwatcher. If not, see http://www.gnu.org/licenses/.
18
+ */
19
+
20
+#include <stdio.h>
21
+#include <stdlib.h>
22
+#include <exception>
23
+#include <string.h>
24
+#include <unistd.h>
25
+#include <errno.h>
26
+#include <fcntl.h>
27
+#include <limits.h>
28
+#include <sys/file.h>
29
+#include <sys/types.h>
30
+#include <sys/stat.h>
31
+#include <sys/select.h>
32
+#include <sys/time.h>
33
+#include <termios.h>
34
+#include <signal.h>
35
+#include <stdint.h>
36
+
37
+#include <tqobject.h>
38
+
39
+#include <tdeapplication.h>
40
+#include <tdecmdlineargs.h>
41
+
42
+#include <ksslcertificate.h>
43
+
44
+#include <tdehardwaredevices.h>
45
+#include <tdecryptographiccarddevice.h>
46
+
47
+#include "watcher.h"
48
+
49
+int lockfd = -1;
50
+char lockFileName[256];
51
+
52
+// --------------------------------------------------------------------------------------
53
+// Useful function from Stack Overflow
54
+// http://stackoverflow.com/questions/1599459/optimal-lock-file-method
55
+// --------------------------------------------------------------------------------------
56
+int tryGetLock(char const *lockName) {
57
+	mode_t m = umask( 0 );
58
+	int fd = open( lockName, O_RDWR|O_CREAT, 0666 );
59
+	umask( m );
60
+	if( fd >= 0 && flock( fd, LOCK_EX | LOCK_NB ) < 0 ) {
61
+		close( fd );
62
+		fd = -1;
63
+	}
64
+	return fd;
65
+}
66
+// --------------------------------------------------------------------------------------
67
+
68
+// --------------------------------------------------------------------------------------
69
+// Useful function from Stack Overflow
70
+// http://stackoverflow.com/questions/1599459/optimal-lock-file-method
71
+// --------------------------------------------------------------------------------------
72
+void releaseLock(int fd, char const *lockName) {
73
+	if( fd < 0 ) {
74
+		return;
75
+	}
76
+	remove( lockName );
77
+	close( fd );
78
+}
79
+// --------------------------------------------------------------------------------------
80
+
81
+void handle_sigterm(int signum) {
82
+	if (lockfd >= 0) {
83
+		releaseLock(lockfd, lockFileName);
84
+	}
85
+	exit(0);
86
+}
87
+
88
+static TDECmdLineOptions options[] =
89
+{
90
+	TDECmdLineLastOption
91
+};
92
+
93
+int main(int argc, char *argv[]) {
94
+	int ret = -1;
95
+
96
+	// Register cleanup handlers
97
+	struct sigaction action;
98
+	memset(&action, 0, sizeof(struct sigaction));
99
+	action.sa_handler = handle_sigterm;
100
+	sigaction(SIGTERM, &action, NULL);
101
+
102
+	// Ensure only one process is running
103
+	sprintf(lockFileName, "/var/lock/cryptocardwatcher.lock");
104
+	lockfd = tryGetLock(lockFileName);
105
+	if (lockfd < 0) {
106
+		printf ("[cryptocardwatcher] Another instance of this program is already running!\n[cryptocardwatcher] Lockfile detected at '%s'\n", lockFileName);
107
+		return -2;
108
+	}
109
+
110
+	// Parse command line arguments
111
+	TDECmdLineArgs::init(argc, argv, "cryptocardwatcher", "cryptocardwatcher", "TDE Cryptographic Card Session Monitor", "0.1");
112
+	TDECmdLineArgs::addCmdLineOptions(options);
113
+	TDEApplication::addCmdLineOptions();
114
+
115
+	// Initialize TDE application
116
+	TDEApplication tdeapp(false, false);
117
+	tdeapp.disableAutoDcopRegistration();
118
+	CardWatcher* watcher = new CardWatcher();
119
+
120
+	// Initialize SmartCard readers
121
+	TDEGenericDevice *hwdevice;
122
+	TDEHardwareDevices *hwdevices = TDEGlobal::hardwareDevices();
123
+	TDEGenericHardwareList cardReaderList = hwdevices->listByDeviceClass(TDEGenericDeviceType::CryptographicCard);
124
+	for (hwdevice = cardReaderList.first(); hwdevice; hwdevice = cardReaderList.next()) {
125
+		TDECryptographicCardDevice* cdevice = static_cast<TDECryptographicCardDevice*>(hwdevice);
126
+		TQObject::connect(cdevice, TQT_SIGNAL(cardInserted(TDECryptographicCardDevice*)), watcher, TQT_SLOT(cryptographicCardInserted(TDECryptographicCardDevice*)));
127
+		TQObject::connect(cdevice, TQT_SIGNAL(cardRemoved(TDECryptographicCardDevice*)), watcher, TQT_SLOT(cryptographicCardRemoved(TDECryptographicCardDevice*)));
128
+		cdevice->enableCardMonitoring(true);
129
+	}
130
+
131
+	// Start TDE application
132
+	ret = tdeapp.exec();
133
+
134
+	// Clean up
135
+	delete watcher;
136
+
137
+	releaseLock(lockfd, lockFileName);
138
+	return ret;
139
+}

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

@@ -0,0 +1,86 @@
1
+/*
2
+ * Copyright 2015 Timothy Pearson <kb9vqf@pearsoncomputing.net>
3
+ *
4
+ * This file is part of cryptocardwatcher, the TDE Cryptographic Card Session Monitor
5
+ *
6
+ * cryptocardwatcher is free software: you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License as
8
+ * published by the Free Software Foundation, either version 3
9
+ * of the License, or (at your option) any later version.
10
+ *
11
+ * cryptocardwatcher is distributed in the hope that it will be useful, but
12
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU General Public
17
+ * License along with cryptocardwatcher. If not, see http://www.gnu.org/licenses/.
18
+ */
19
+
20
+#include "watcher.h"
21
+
22
+#include <ksslcertificate.h>
23
+
24
+#include <tdehardwaredevices.h>
25
+#include <tdecryptographiccarddevice.h>
26
+
27
+#include <dmctl.h>
28
+#include <kuser.h>
29
+
30
+CardWatcher::CardWatcher() : TQObject() {
31
+	//
32
+}
33
+
34
+CardWatcher::~CardWatcher() {
35
+	//
36
+}
37
+
38
+void CardWatcher::cryptographicCardInserted(TDECryptographicCardDevice* cdevice) {
39
+	TQString login_name = TQString::null;
40
+	X509CertificatePtrList certList = cdevice->cardX509Certificates();
41
+	if (certList.count() > 0) {
42
+		KSSLCertificate* card_cert = NULL;
43
+		card_cert = KSSLCertificate::fromX509(certList[0]);
44
+		TQStringList cert_subject_parts = TQStringList::split("/", card_cert->getSubject(), false);
45
+		for (TQStringList::Iterator it = cert_subject_parts.begin(); it != cert_subject_parts.end(); ++it ) {
46
+			TQString lcpart = (*it).lower();
47
+			if (lcpart.startsWith("cn=")) {
48
+				login_name = lcpart.right(lcpart.length() - strlen("cn="));
49
+			}
50
+		}
51
+		delete card_cert;
52
+	}
53
+
54
+	if (login_name != "") {
55
+		// Determine if user already has an active session
56
+		DM dm;
57
+		SessList sess;
58
+		bool user_active = false;
59
+		if (dm.localSessions(sess)) {
60
+			TQString user, loc;
61
+			for (SessList::ConstIterator it = sess.begin(); it != sess.end(); ++it) {
62
+				DM::sess2Str2(*it, user, loc);
63
+				if (user.startsWith(login_name + ": ")) {
64
+					// Found active session
65
+					user_active = true;
66
+				}
67
+				if (user == "Unused") {
68
+					if ((*it).vt == dm.activeVT()) {
69
+						// Found active unused session
70
+						user_active = true;
71
+					}
72
+				}
73
+			}
74
+		}
75
+		if (!user_active) {
76
+			// Activate new VT
77
+			DM().startReserve();
78
+		}
79
+	}
80
+}
81
+
82
+void CardWatcher::cryptographicCardRemoved(TDECryptographicCardDevice* cdevice) {
83
+	//
84
+}
85
+
86
+#include "watcher.moc"

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

@@ -0,0 +1,40 @@
1
+/*
2
+ * Copyright 2015 Timothy Pearson <kb9vqf@pearsoncomputing.net>
3
+ * 
4
+ * This file is part of cryptocardwatcher, the TDE Cryptographic Card Session Monitor
5
+ * 
6
+ * cryptocardwatcher is free software: you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License as
8
+ * published by the Free Software Foundation, either version 3
9
+ * of the License, or (at your option) any later version.
10
+ *
11
+ * cryptocardwatcher is distributed in the hope that it will be useful, but
12
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU General Public
17
+ * License along with cryptocardwatcher. If not, see http://www.gnu.org/licenses/.
18
+ */
19
+
20
+#ifndef __TDECRYPTOCARDWATCHER_H__
21
+#define __TDECRYPTOCARDWATCHER_H__
22
+
23
+#include <tqobject.h>
24
+
25
+class TDECryptographicCardDevice;
26
+
27
+class CardWatcher : public TQObject
28
+{
29
+	Q_OBJECT
30
+
31
+	public:
32
+		CardWatcher();
33
+		~CardWatcher();
34
+
35
+	public slots:
36
+		void cryptographicCardInserted(TDECryptographicCardDevice*);
37
+		void cryptographicCardRemoved(TDECryptographicCardDevice*);
38
+};
39
+
40
+#endif // __TDECRYPTOCARDWATCHER_H__

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

@@ -68,7 +68,7 @@ tde_add_executable( tdm_greet AUTOMOC
68 68
     kfdialog.cpp kgdialog.cpp kchooser.cpp kgverify.cpp
69 69
     tdmshutdown.cpp tdmadmindialog.cpp kgreeter.cpp
70 70
     kgapp.cpp sakdlg.cc
71
-  LINK tdmthemer-static tdeui-shared Xtst ${TDMGREET_OPTIONAL_LINK}
71
+  LINK tdmthemer-static tdeui-shared tdeio-shared dmctl-static Xtst ${TDMGREET_OPTIONAL_LINK}
72 72
   DESTINATION ${BIN_INSTALL_DIR}
73 73
 )
74 74
 

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

@@ -72,6 +72,7 @@ bool has_twin = false;
72 72
 bool is_themed = false;
73 73
 bool trinity_desktop_lock_use_sak = TRUE;
74 74
 bool trinity_desktop_synchronize_keyboard_lights = TRUE;
75
+bool trinity_desktop_watch_cryptographic_cards = TRUE;
75 76
 TQPoint primaryScreenPosition;
76 77
 
77 78
 static int
@@ -216,6 +217,7 @@ kg_main( const char *argv0 )
216 217
 
217 218
 	TDEProcess *tsak = 0;
218 219
 	TDEProcess *kbdl = 0;
220
+	TDEProcess *ccsm = 0;
219 221
 	TDEProcess *proc = 0;
220 222
 	TDEProcess *comp = 0;
221 223
 	TDEProcess *dcop = 0;
@@ -252,6 +254,12 @@ kg_main( const char *argv0 )
252 254
 		kbdl->start();
253 255
 	}
254 256
 
257
+	if (trinity_desktop_watch_cryptographic_cards) {
258
+		ccsm = new TDEProcess;
259
+		*ccsm << TQCString( argv0, strrchr( argv0, '/' ) - argv0 + 2 ) + "tdecryptocardwatcher";
260
+		ccsm->start();
261
+	}
262
+
255 263
 	XSetErrorHandler( ignoreXError );
256 264
 	argb_visual_available = false;
257 265
 	char *display = 0;
@@ -518,6 +526,10 @@ kg_main( const char *argv0 )
518 526
 		kbdl->closeStdin();
519 527
 		kbdl->detach();
520 528
 	}
529
+	if (ccsm) {
530
+		ccsm->closeStdin();
531
+		ccsm->detach();
532
+	}
521 533
 	if (comp) {
522 534
 		if (comp->isRunning()) {
523 535
 			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.
33 33
 #include "themer/tdmitem.h"
34 34
 #include "themer/tdmlabel.h"
35 35
 
36
+#include <dmctl.h>
37
+
38
+#include <ksslcertificate.h>
39
+
40
+#include <tdehardwaredevices.h>
41
+#include <tdecryptographiccarddevice.h>
42
+
36 43
 #include <tdeapplication.h>
37 44
 #include <tdelocale.h>
38 45
 #include <kstandarddirs.h>
@@ -212,6 +219,17 @@ KGreeter::KGreeter( bool framed )
212 219
 		pluginList = KGVerify::init( _pluginsLogin );
213 220
 	}
214 221
 
222
+	// Initialize SmartCard readers
223
+	TDEGenericDevice *hwdevice;
224
+	TDEHardwareDevices *hwdevices = TDEGlobal::hardwareDevices();
225
+	TDEGenericHardwareList cardReaderList = hwdevices->listByDeviceClass(TDEGenericDeviceType::CryptographicCard);
226
+	for (hwdevice = cardReaderList.first(); hwdevice; hwdevice = cardReaderList.next()) {
227
+		TDECryptographicCardDevice* cdevice = static_cast<TDECryptographicCardDevice*>(hwdevice);
228
+		connect(cdevice, TQT_SIGNAL(certificateListAvailable(TDECryptographicCardDevice*)), this, TQT_SLOT(cryptographicCardInserted(TDECryptographicCardDevice*)));
229
+		connect(cdevice, TQT_SIGNAL(cardRemoved(TDECryptographicCardDevice*)), this, TQT_SLOT(cryptographicCardRemoved(TDECryptographicCardDevice*)));
230
+		cdevice->enableCardMonitoring(true);
231
+	}
232
+
215 233
 	mControlPipeHandlerThread = new TQEventLoopThread();
216 234
 	mControlPipeHandler = new ControlPipeHandlerObject();
217 235
 	mControlPipeHandler->mKGreeterParent = this;
@@ -829,6 +847,60 @@ KGreeter::verifySetUser( const TQString &user )
829 847
 	slotUserEntered();
830 848
 }
831 849
 
850
+void KGreeter::cryptographicCardInserted(TDECryptographicCardDevice* cdevice) {
851
+	TQString login_name = TQString::null;
852
+	X509CertificatePtrList certList = cdevice->cardX509Certificates();
853
+	if (certList.count() > 0) {
854
+		KSSLCertificate* card_cert = NULL;
855
+		card_cert = KSSLCertificate::fromX509(certList[0]);
856
+		TQStringList cert_subject_parts = TQStringList::split("/", card_cert->getSubject(), false);
857
+		for (TQStringList::Iterator it = cert_subject_parts.begin(); it != cert_subject_parts.end(); ++it ) {
858
+			TQString lcpart = (*it).lower();
859
+			if (lcpart.startsWith("cn=")) {
860
+				login_name = lcpart.right(lcpart.length() - strlen("cn="));
861
+			}
862
+		}
863
+		delete card_cert;
864
+	}
865
+
866
+	if (login_name != "") {
867
+		DM dm;
868
+		SessList sess;
869
+		bool vt_active = false;
870
+		bool user_active = false;
871
+		if (dm.localSessions(sess)) {
872
+			TQString user, loc;
873
+			for (SessList::ConstIterator it = sess.begin(); it != sess.end(); ++it) {
874
+				DM::sess2Str2(*it, user, loc);
875
+				if (user.startsWith(login_name + ": ")) {
876
+					// Found active session
877
+					user_active = true;
878
+				}
879
+				if ((*it).self) {
880
+					if ((*it).vt == dm.activeVT()) {
881
+						vt_active = true;
882
+					}
883
+				}
884
+			}
885
+		}
886
+
887
+		if (!user_active && vt_active) {
888
+			// Select the correct user
889
+			verify->setUser(login_name);
890
+			verifySetUser(login_name);
891
+			verify->lockUserEntry(true);
892
+
893
+			// Initiate login
894
+			verify->accept();
895
+		}
896
+	}
897
+}
898
+
899
+void KGreeter::cryptographicCardRemoved(TDECryptographicCardDevice* cdevice) {
900
+	verify->lockUserEntry(false);
901
+        verify->requestAbort();
902
+}
903
+
832 904
 KStdGreeter::KStdGreeter()
833 905
   : KGreeter()
834 906
   , clock( 0 )

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

@@ -46,6 +46,8 @@ class TQListViewItem;
46 46
 class KGreeter;
47 47
 class SAKDlg;
48 48
 
49
+class TDECryptographicCardDevice;
50
+
49 51
 struct SessType {
50 52
 	TQString name, type;
51 53
 	bool hid;
@@ -138,6 +140,8 @@ class KGreeter : public KGDialog, public KGVerifyHandler {
138 140
 
139 141
   private slots:
140 142
 	void slotLoadPrevWM();
143
+	void cryptographicCardInserted(TDECryptographicCardDevice*);
144
+	void cryptographicCardRemoved(TDECryptographicCardDevice*);
141 145
 
142 146
   private:
143 147
 	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.
30 30
 
31 31
 #include "themer/tdmthemer.h"
32 32
 #include "themer/tdmitem.h"
33
+#include "themer/tdmlabel.h"
33 34
 
34 35
 #include <tdeapplication.h>
35 36
 #include <tdelocale.h>
@@ -66,30 +67,31 @@ void KGVerifyHandler::updateStatus( bool, bool, int )
66 67
 {
67 68
 }
68 69
 
69
-KGVerify::KGVerify( KGVerifyHandler *_handler, KdmThemer *_themer,
70
-                    TQWidget *_parent, TQWidget *_predecessor,
71
-                    const TQString &_fixedUser,
72
-                    const PluginList &_pluginList,
73
-                    KGreeterPlugin::Function _func,
74
-                    KGreeterPlugin::Context _ctx )
70
+KGVerify::KGVerify(KGVerifyHandler *_handler, KdmThemer *_themer,
71
+			TQWidget *_parent, TQWidget *_predecessor,
72
+			const TQString &_fixedUser,
73
+			const PluginList &_pluginList,
74
+			KGreeterPlugin::Function _func,
75
+			KGreeterPlugin::Context _ctx)
75 76
 	: inherited()
76
-	, coreLock( 0 )
77
-	, fixedEntity( _fixedUser )
78
-	, pluginList( _pluginList )
79
-	, handler( _handler )
80
-	, themer( _themer )
81
-	, parent( _parent )
82
-	, predecessor( _predecessor )
83
-	, plugMenu( 0 )
84
-	, curPlugin( -1 )
85
-	, timedLeft( 0 )
86
-	, func( _func )
87
-	, ctx( _ctx )
88
-	, enabled( true )
89
-	, running( false )
90
-	, suspended( false )
91
-	, failed( false )
92
-	, isClear( true )
77
+	, coreLock(0)
78
+	, fixedEntity(_fixedUser)
79
+	, pluginList(_pluginList)
80
+	, handler(_handler)
81
+	, themer(_themer)
82
+	, parent(_parent)
83
+	, predecessor(_predecessor)
84
+	, plugMenu(0)
85
+	, curPlugin(-1)
86
+	, timedLeft(0)
87
+	, func(_func)
88
+	, ctx(_ctx)
89
+	, enabled(true)
90
+	, running(false)
91
+	, suspended(false)
92
+	, failed(false)
93
+	, isClear(true)
94
+	, abortRequested(false)
93 95
 {
94 96
 	connect( &timer, TQT_SIGNAL(timeout()), TQT_SLOT(slotTimeout()) );
95 97
 	connect( kapp, TQT_SIGNAL(activity()), TQT_SLOT(slotActivity()) );
@@ -269,6 +271,14 @@ KGVerify::setUser( const TQString &user )
269 271
 }
270 272
 
271 273
 void
274
+KGVerify::lockUserEntry(const bool lock)
275
+{
276
+	// assert( fixedEntity.isEmpty() );
277
+	Debug( "%s->lockUserEntry(%\"s)\n", pName.data(), lock );
278
+	greet->lockUserEntry(lock);
279
+}
280
+
281
+void
272 282
 KGVerify::setPassword( const TQString &pass )
273 283
 {
274 284
 	greet->setPassword( pass );
@@ -374,6 +384,12 @@ KGVerify::reject()
374 384
 	doReject( true );
375 385
 }
376 386
 
387
+void // not a slot - called manually by greeter
388
+KGVerify::requestAbort()
389
+{
390
+	abortRequested = true;
391
+}
392
+
377 393
 void
378 394
 KGVerify::setEnabled( bool on )
379 395
 {
@@ -478,27 +494,28 @@ KGVerify::VErrBox( TQWidget *parent, const TQString &user, const char *msg )
478 494
 }
479 495
 
480 496
 void // private static
481
-KGVerify::VInfoBox( TQWidget *parent, const TQString &user, const char *msg )
497
+KGVerify::VInfoBox(TQWidget *parent, const TQString &user, const char *msg)
482 498
 {
483 499
 	TQString mesg = TQString::fromLocal8Bit( msg );
484 500
 	TQRegExp rx( "^Warning: your account will expire in (\\d+) day" );
485
-	if (rx.search( mesg ) >= 0) {
486
-		int expire = rx.cap( 1 ).toInt();
501
+	if (rx.search(mesg) >= 0) {
502
+		int expire = rx.cap(1).toInt();
487 503
 		mesg = expire ?
488 504
 			i18n("Your account expires tomorrow.",
489 505
 			     "Your account expires in %n days.", expire) :
490 506
 			i18n("Your account expires today.");
491
-	} else {
507
+	}
508
+	else {
492 509
 		rx.setPattern( "^Warning: your password will expire in (\\d+) day" );
493
-		if (rx.search( mesg ) >= 0) {
494
-			int expire = rx.cap( 1 ).toInt();
510
+		if (rx.search(mesg) >= 0) {
511
+			int expire = rx.cap(1).toInt();
495 512
 			mesg = expire ?
496 513
 				i18n("Your password expires tomorrow.",
497 514
 				     "Your password expires in %n days.", expire) :
498 515
 				i18n("Your password expires today.");
499 516
 		}
500 517
 	}
501
-	VMsgBox( parent, user, infobox, mesg );
518
+	VMsgBox(parent, user, infobox, mesg);
502 519
 }
503 520
 
504 521
 bool // public static
@@ -597,9 +614,24 @@ KGVerify::handleVerify()
597 614
 			Debug( "  echo = %d\n", echo );
598 615
 			ndelay = GRecvInt();
599 616
 			Debug( "  ndelay = %d\n%s->textPrompt(...)\n", ndelay, pName.data() );
600
-			greet->textPrompt( msg, echo, ndelay );
601
-			if (msg)
602
-				free( msg );
617
+			if (abortRequested) {
618
+				greet->textPrompt("", echo, ndelay);
619
+				abortRequested = false;
620
+			}
621
+			else {
622
+				if (msg && (msg[0] != 0)) {
623
+					// Reset password entry and change text
624
+					setPassPromptText(msg);
625
+					greet->start();
626
+					greet->textPrompt(msg, echo, ndelay);
627
+				}
628
+				else {
629
+					greet->textPrompt(msg, echo, ndelay);
630
+				}
631
+			}
632
+			if (msg) {
633
+				free(msg);
634
+			}
603 635
 			return;
604 636
 		case V_GET_BINARY:
605 637
 			Debug( " V_GET_BINARY\n" );
@@ -607,9 +639,16 @@ KGVerify::handleVerify()
607 639
 			Debug( "  %d bytes prompt\n", ret );
608 640
 			ndelay = GRecvInt();
609 641
 			Debug( "  ndelay = %d\n%s->binaryPrompt(...)\n", ndelay, pName.data() );
610
-			greet->binaryPrompt( msg, ndelay );
611
-			if (msg)
612
-				free( msg );
642
+			if (abortRequested) {
643
+				gplugReturnBinary(NULL);
644
+				abortRequested = false;
645
+			}
646
+			else {
647
+				greet->binaryPrompt( msg, ndelay );
648
+			}
649
+			if (msg) {
650
+				free(msg);
651
+			}
613 652
 			return;
614 653
 		}
615 654
 
@@ -622,11 +661,12 @@ KGVerify::handleVerify()
622 661
 			curUser = user = TQString::fromLocal8Bit( msg );
623 662
 			// greet needs this to be able to return something useful from
624 663
 			// getEntity(). but the backend is still unable to tell a domain ...
625
-			Debug( "  %s->setUser(%\"s)\n", pName.data(), user.latin1() );
664
+			Debug("  %s->setUser(%\"s)\n", pName.data(), user.latin1());
626 665
 			greet->setUser( curUser );
627
-			handler->verifySetUser( curUser );
628
-			if (msg)
629
-				free( msg );
666
+			handler->verifySetUser(curUser);
667
+			if (msg) {
668
+				free(msg);
669
+			}
630 670
 			continue;
631 671
 		case V_PRE_OK: // this is only for func == AuthChAuthTok
632 672
 			Debug( " V_PRE_OK\n" );
@@ -636,8 +676,9 @@ KGVerify::handleVerify()
636 676
 			// is not implemented yet.
637 677
 			authTok = true;
638 678
 			cont = true;
639
-			Debug( "%s->succeeded()\n", pName.data() );
679
+			Debug("%s->succeeded()\n", pName.data());
640 680
 			greet->succeeded();
681
+			abortRequested = false;
641 682
 			continue;
642 683
 		case V_CHTOK_AUTH:
643 684
 			Debug( " V_CHTOK_AUTH\n" );
@@ -648,14 +689,16 @@ KGVerify::handleVerify()
648 689
 			Debug( " V_CHTOK\n" );
649 690
 			nfunc = KGreeterPlugin::ChAuthTok;
650 691
 			user = TQString::null;
651
-		  dchtok:
692
+		dchtok:
652 693
 			{
653 694
 				timer.stop();
654 695
 				Debug( "%s->succeeded()\n", pName.data() );
655 696
 				greet->succeeded();
697
+				abortRequested = false;
656 698
 				KGChTok chtok( parent, user, pluginList, curPlugin, nfunc, KGreeterPlugin::Login );
657
-				if (!chtok.exec())
699
+				if (!chtok.exec()) {
658 700
 					goto retry;
701
+				}
659 702
 				handler->verifyOk();
660 703
 				return;
661 704
 			}
@@ -665,11 +708,16 @@ KGVerify::handleVerify()
665 708
 			Debug( "  %s->textMessage(%\"s, true)\n", pName.data(), msg );
666 709
 			if (!greet->textMessage( msg, true )) {
667 710
 				Debug( "  message passed\n" );
668
-				VErrBox( parent, user, msg );
669
-			} else
711
+				if (!abortRequested) {
712
+					VErrBox( parent, user, msg );
713
+				}
714
+			}
715
+			else {
670 716
 				Debug( "  message swallowed\n" );
671
-			if (msg)
672
-				free( msg );
717
+			}
718
+			if (msg) {
719
+				free(msg);
720
+			}
673 721
 			continue;
674 722
 		case V_MSG_INFO:
675 723
 			Debug( " V_MSG_INFO\n" );
@@ -677,10 +725,14 @@ KGVerify::handleVerify()
677 725
 			Debug( "  %s->textMessage(%\"s, false)\n", pName.data(), msg );
678 726
 			if (!greet->textMessage( msg, false )) {
679 727
 				Debug( "  message passed\n" );
680
-				VInfoBox( parent, user, msg );
681
-			} else
682
-				Debug( "  message swallowed\n" );
683
-			free( msg );
728
+				if (!abortRequested) {
729
+					VInfoBox(parent, user, msg);
730
+				}
731
+			}
732
+			else {
733
+				Debug("  message swallowed\n");
734
+			}
735
+			free(msg);
684 736
 			continue;
685 737
 		}
686 738
 
@@ -698,6 +750,7 @@ KGVerify::handleVerify()
698 750
 				if (ent != fixedEntity) {
699 751
 					Debug( "%s->failed()\n", pName.data() );
700 752
 					greet->failed();
753
+					abortRequested = false;
701 754
 					MsgBox( sorrybox,
702 755
 					        i18n("Authenticated user (%1) does not match requested user (%2).\n")
703 756
 					        .arg( ent ).arg( fixedEntity ) );
@@ -706,12 +759,17 @@ KGVerify::handleVerify()
706 759
 			}
707 760
 			Debug( "%s->succeeded()\n", pName.data() );
708 761
 			greet->succeeded();
762
+			abortRequested = false;
709 763
 			handler->verifyOk();
710 764
 			return;
711 765
 		}
712 766
 
713 767
 		Debug( "%s->failed()\n", pName.data() );
714 768
 		greet->failed();
769
+		abortRequested = false;
770
+
771
+		// Reset password prompt text
772
+		setPassPromptText(TQString::null, true);
715 773
 
716 774
 		if (ret == V_AUTH) {
717 775
 			Debug( " V_AUTH\n" );
@@ -736,17 +794,36 @@ KGVerify::handleVerify()
736 794
 	}
737 795
 }
738 796
 
797
+void KGVerify::setPassPromptText(TQString text, bool use_default_text) {
798
+	if (themer) {
799
+		KdmItem* password_label = themer->findNode("password-label");
800
+		if (password_label) {
801
+			KdmLabel* pass_label = static_cast<KdmLabel*>(password_label);
802
+			if (use_default_text) {
803
+				pass_label->setText(pass_label->lookupStock("password-label"));
804
+			}
805
+			else {
806
+				pass_label->setText(text);
807
+			}
808
+			pass_label->update();
809
+			themer->updateGeometry(true);
810
+			static_cast<TQWidget *>(themer->parent())->repaint(true);
811
+		}
812
+	}
813
+}
814
+
739 815
 void
740 816
 KGVerify::gplugReturnText( const char *text, int tag )
741 817
 {
742
-	Debug( "%s: gplugReturnText(%\"s, %d)\n", pName.data(),
743
-	       tag & V_IS_SECRET ? "<masked>" : text, tag );
744
-	GSendStr( text );
818
+	Debug("%s: gplugReturnText(%\"s, %d)\n", pName.data(), tag & V_IS_SECRET ? "<masked>" : text, tag);
819
+	GSendStr(text);
745 820
 	if (text) {
746
-		GSendInt( tag );
821
+		GSendInt(tag);
747 822
 		handleVerify();
748
-	} else
823
+	}
824
+	else {
749 825
 		coreLock = 0;
826
+	}
750 827
 }
751 828
 
752 829
 void
@@ -755,12 +832,13 @@ KGVerify::gplugReturnBinary( const char *data )
755 832
 	if (data) {
756 833
 		unsigned const char *up = (unsigned const char *)data;
757 834
 		int len = up[3] | (up[2] << 8) | (up[1] << 16) | (up[0] << 24);
758
-		Debug( "%s: gplugReturnBinary(%d bytes)\n", pName.data(), len );
759
-		GSendArr( len, data );
835
+		Debug("%s: gplugReturnBinary(%d bytes)\n", pName.data(), len);
836
+		GSendArr(len, data);
760 837
 		handleVerify();
761
-	} else {
762
-		Debug( "%s: gplugReturnBinary(NULL)\n", pName.data() );
763
-		GSendArr( 0, 0 );
838
+	}
839
+	else {
840
+		Debug("%s: gplugReturnBinary(NULL)\n", pName.data());
841
+		GSendArr(0, 0);
764 842
 		coreLock = 0;
765 843
 	}
766 844
 }

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

@@ -100,6 +100,7 @@ class KGVerify : public TQObject, public KGreeterPluginHandler {
100 100
 	void presetEntity( const TQString &entity, int field );
101 101
 	TQString getEntity() const;
102 102
 	void setUser( const TQString &user );
103
+	void lockUserEntry( const bool lock );
103 104
 	void setPassword( const TQString &pass );
104 105
 	/* virtual */ void selectPlugin( int id );
105 106
 	bool entitiesLocal() const;
@@ -113,6 +114,7 @@ class KGVerify : public TQObject, public KGreeterPluginHandler {
113 114
 	void resume();
114 115
 	void accept();
115 116
 	void reject();
117
+	void requestAbort();
116 118
 
117 119
 	int coreLock;
118 120
 
@@ -146,6 +148,7 @@ class KGVerify : public TQObject, public KGreeterPluginHandler {
146 148
 	bool capsLocked;
147 149
 	bool enabled, running, suspended, failed, delayed, cont;
148 150
 	bool authTok, isClear, timeable;
151
+	bool abortRequested;
149 152
 
150 153
 	static void VMsgBox( TQWidget *parent, const TQString &user, TQMessageBox::Icon type, const TQString &mesg );
151 154
 	static void VErrBox( TQWidget *parent, const TQString &user, const char *msg );
@@ -158,6 +161,7 @@ class KGVerify : public TQObject, public KGreeterPluginHandler {
158 161
 	void performAutoLogin();
159 162
 	bool scheduleAutoLogin( bool initial );
160 163
 	void doReject( bool initial );
164
+	void setPassPromptText(TQString text, bool use_default_text=false);
161 165
 
162 166
   private slots:
163 167
 	//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
204 204
 	return 0;
205 205
 }
206 206
 
207
+KdmItem *
208
+KdmItem::findNodeByType( const TQString &_type ) const
209
+{
210
+	if (itemType == _type)
211
+		return const_cast<KdmItem *>( this );
212
+
213
+	TQValueList<KdmItem *>::ConstIterator it;
214
+	for (it = m_children.begin(); it != m_children.end(); ++it) {
215
+		KdmItem *t = (*it)->findNodeByType( _type );
216
+		if (t)
217
+			return t;
218
+	}
219
+
220
+	return 0;
221
+}
222
+
207 223
 void
208 224
 KdmItem::setWidget( TQWidget *widget )
209 225
 {
@@ -336,11 +352,6 @@ KdmItem::paint( TQPainter *p, const TQRect &rect )
336 352
               else {
337 353
 		// We have compositing support!
338 354
 		TQRgb blend_color = tqRgba(m_backgroundModifier, m_backgroundModifier, m_backgroundModifier, 0);   // RGBA overlay
339
-		float alpha = tqAlpha(blend_color) / 255.;
340
-		int pixel = tqAlpha(blend_color) << 24 |
341
-				int(tqRed(blend_color) * alpha) << 16 |
342
-				int(tqGreen(blend_color) * alpha) << 8  |
343
-				int(tqBlue(blend_color) * alpha);
344 355
 
345 356
 		TQImage img( myWidget->size(), 32 );
346 357
 		img = img.convertDepth(32);

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

@@ -152,6 +152,7 @@ public:
152 152
 	}
153 153
 
154 154
 	KdmItem *findNode( const TQString &id ) const;
155
+	KdmItem *findNodeByType( const TQString &type ) const;
155 156
 	virtual void setWidget( TQWidget *widget );
156 157
 	TQWidget *widget() const { return myWidget; }
157 158
 	virtual void setLayoutItem( TQLayoutItem *item );

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

@@ -40,6 +40,9 @@ public:
40 40
 	KdmLabel( KdmItem *parent, const TQDomNode &node, const char *name = 0 );
41 41
 	void setText( const TQString &txt );
42 42
 
43
+	/* Method to lookup the caption associated with an item */
44
+	TQString lookupStock( const TQString &stock );
45
+
43 46
 protected:
44 47
 	// reimplemented; returns the minimum size of rendered text
45 48
 	virtual TQSize sizeHint();
@@ -71,9 +74,6 @@ public slots:
71 74
 	void slotAccel();
72 75
 
73 76
 private:
74
-	/* Method to lookup the caption associated with an item */
75
-	TQString lookupStock( const TQString &stock );
76
-
77 77
 	/* Lookup variables in the text */
78 78
 	TQString lookupText( const TQString &t );
79 79
 

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

@@ -117,6 +117,12 @@ KdmThemer::findNode( const TQString &item ) const
117 117
 	return rootItem->findNode( item );
118 118
 }
119 119
 
120
+KdmItem *
121
+KdmThemer::findNodeByType( const TQString &item ) const
122
+{
123
+	return rootItem->findNodeByType( item );
124
+}
125
+
120 126
 void
121 127
 KdmThemer::updateGeometry( bool force )
122 128
 {

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

@@ -72,6 +72,7 @@ public:
72 72
 
73 73
 	virtual // just to put the reference in the vmt
74 74
 	KdmItem *findNode( const TQString & ) const;
75
+	KdmItem *findNodeByType( const TQString & ) const;
75 76
 
76 77
 	void updateGeometry( bool force ); // force = true for external calls
77 78
 

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

@@ -165,13 +165,13 @@
165 165
 	<normal color="#FF8080" alpha="0.0"/>
166 166
 	<pos anchor="w" y="50%" width="box" height="box"/>
167 167
         <box orientation="vertical" xpadding="0" ypadding="0" spacing="14">
168
-          <item type="label">
168
+          <item type="label" id="username-label">
169 169
             <pos anchor="ne" x="100%"/>
170 170
             <normal color="#000000" font="Sans 12"/>
171 171
      	 	<!-- Stock label for: Username: -->
172 172
      	 	<stock type="username-label"/>
173 173
           </item>
174
-          <item type="label">
174
+          <item type="label" id="password-label">
175 175
             <pos anchor="ne" x="100%"/>
176 176
             <normal color="#000000" font="Sans 12"/>
177 177
      	 	<!-- Stock label for: Password: -->

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

@@ -37,7 +37,7 @@
37 37
 	</item>	
38 38
 	
39 39
 <!-- user field -->	
40
-			<item type="label">
40
+			<item type="label" id="username-label">
41 41
 				<pos anchor="nw" x="145" y="225"/>
42 42
 				<normal font="Sans 11" color="#dfdbd2"/>
43 43
 				<stock type="username-label"/>
@@ -58,7 +58,7 @@
58 58
 	
59 59
 <!-- password field -->
60 60
 	
61
-			<item type="label">
61
+			<item type="label" id="password-label">
62 62
 				<pos anchor="nw" x="145" y="285"/>
63 63
 				<normal font="Sans 11" color="#dfdbd2"/>
64 64
 				<stock type="password-label"/>

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

@@ -54,12 +54,12 @@
54 54
 						<normal alpha="0.0" color="#000000" />
55 55
 						<pos width="box" y="50%" anchor="w" height="box" />
56 56
 						<box xpadding="10" spacing="10" ypadding="0" orientation="vertical" >
57
-							<item type="label" >
57
+							<item type="label"  id="username-label">
58 58
 								<pos x="100%" anchor="ne" />
59 59
 								<normal color="#000000" font="Sans Condensed 10" />
60 60
 								<stock type="username-label" />
61 61
 							</item>
62
-							<item type="label" >
62
+							<item type="label" id="password-label">
63 63
 								<pos x="100%" anchor="ne" />
64 64
 								<normal color="#000000" font="Sans Condensed 10" />
65 65
 								<stock type="password-label" />

+ 68
- 20
tdmlib/dmctl.cpp View File

@@ -25,6 +25,7 @@
25 25
 #include <dcopclient.h>
26 26
 
27 27
 #include <tqregexp.h>
28
+#include <tqfile.h>
28 29
 
29 30
 #include <X11/Xauth.h>
30 31
 #include <X11/Xlib.h>
@@ -37,8 +38,34 @@
37 38
 #include <fcntl.h>
38 39
 #include <errno.h>
39 40
 
41
+#include <config.h>
42
+
43
+static TQString readcfg(const char *cfg_file) {
44
+	TQString ctl = "/var/run/xdmctl";
45
+
46
+	TQStringList lines;
47
+	TQFile file(cfg_file);
48
+	if ( file.open( IO_ReadOnly ) ) {
49
+		TQTextStream stream(&file);
50
+		TQString line;
51
+		while ( !stream.atEnd() ) {
52
+			line = stream.readLine();
53
+			TQStringList keyvaluepair = TQStringList::split("=", line, false);
54
+			if (keyvaluepair.count() > 1) {
55
+				if (keyvaluepair[0].lower() == "FifoDir") {
56
+					ctl = keyvaluepair[1];
57
+				}
58
+			}
59
+		}
60
+		file.close();
61
+	}
62
+
63
+	return ctl;
64
+}
65
+
40 66
 static int DMType = DM::Unknown;
41
-static const char *ctl, *dpy;
67
+static const char *dpy;
68
+static TQString ctl;
42 69
 
43 70
 DM::DM() : fd( -1 )
44 71
 {
@@ -46,16 +73,27 @@ DM::DM() : fd( -1 )
46 73
 	struct sockaddr_un sa;
47 74
 
48 75
 	if (DMType == Unknown) {
49
-		if (!(dpy = ::getenv( "DISPLAY" )))
50
-			DMType = NoDM;
51
-		else if ((ctl = ::getenv( "DM_CONTROL" )))
76
+		if (!(dpy = ::getenv( "DISPLAY" ))) {
77
+			// Try to read TDM control file
78
+			if ((ctl = readcfg(KDE_CONFDIR "/tdm/tdmrc")) != TQString::null) {
79
+				DMType = NewTDM;
80
+			}
81
+			else {
82
+				DMType = NoDM;
83
+			}
84
+		}
85
+		else if ((ctl = ::getenv( "DM_CONTROL" )) != TQString::null) {
52 86
 			DMType = NewTDM;
53
-		else if ((ctl = ::getenv( "XDM_MANAGED" )) && ctl[0] == '/')
87
+		}
88
+		else if (((ctl = ::getenv( "XDM_MANAGED" )) != TQString::null) && ctl[0] == '/') {
54 89
 			DMType = OldTDM;
55
-		else if (::getenv( "GDMSESSION" ))
90
+		}
91
+		else if (::getenv( "GDMSESSION" )) {
56 92
 			DMType = GDM;
57
-		else
93
+		}
94
+		else {
58 95
 			DMType = NoDM;
96
+		}
59 97
 	}
60 98
 	switch (DMType) {
61 99
 	default:
@@ -76,12 +114,17 @@ DM::DM() : fd( -1 )
76 114
 				}
77 115
 			}
78 116
 			GDMAuthenticate();
79
-		} else {
80
-			if ((ptr = const_cast<char*>(strchr( dpy, ':' ))))
81
-				ptr = strchr( ptr, '.' );
82
-			snprintf( sa.sun_path, sizeof(sa.sun_path),
83
-			          "%s/dmctl-%.*s/socket",
84
-			          ctl, ptr ? int(ptr - dpy) : 512, dpy );
117
+		}
118
+		else {
119
+			if (!dpy) {
120
+				snprintf( sa.sun_path, sizeof(sa.sun_path), "%s/dmctl/socket", ctl.ascii() );
121
+			}
122
+			else {
123
+				if ((ptr = const_cast<char*>(strchr( dpy, ':' )))) {
124
+					ptr = strchr( ptr, '.' );
125
+				}
126
+				snprintf( sa.sun_path, sizeof(sa.sun_path), "%s/dmctl-%.*s/socket", ctl.ascii(), ptr ? int(ptr - dpy) : 512, dpy );
127
+			}
85 128
 			if (::connect( fd, (struct sockaddr *)&sa, sizeof(sa) )) {
86 129
 				::close( fd );
87 130
 				fd = -1;
@@ -100,8 +143,9 @@ DM::DM() : fd( -1 )
100 143
 
101 144
 DM::~DM()
102 145
 {
103
-	if (fd >= 0)
146
+	if (fd >= 0) {
104 147
 		close( fd );
148
+	}
105 149
 }
106 150
 
107 151
 bool
@@ -172,13 +216,15 @@ DM::exec( const char *cmd, TQCString &buf )
172 216
 bool
173 217
 DM::canShutdown()
174 218
 {
175
-	if (DMType == OldTDM)
176
-		return strstr( ctl, ",maysd" ) != 0;
219
+	if (DMType == OldTDM) {
220
+		return strstr( ctl.ascii(), ",maysd" ) != 0;
221
+	}
177 222
 
178 223
 	TQCString re;
179 224
 
180
-	if (DMType == GDM)
225
+	if (DMType == GDM) {
181 226
 		return exec( "QUERY_LOGOUT_ACTION\n", re ) && re.find("HALT") >= 0;
227
+	}
182 228
 
183 229
 	return exec( "caps\n", re ) && re.find( "\tshutdown" ) >= 0;
184 230
 }
@@ -282,7 +328,7 @@ DM::numReserve()
282 328
 		return 1; /* Bleh */
283 329
 
284 330
 	if (DMType == OldTDM)
285
-		return strstr( ctl, ",rsvd" ) ? 1 : -1;
331
+		return strstr( ctl.ascii(), ",rsvd" ) ? 1 : -1;
286 332
 
287 333
 	TQCString re;
288 334
 	int p;
@@ -304,8 +350,9 @@ DM::startReserve()
304 350
 bool
305 351
 DM::localSessions( SessList &list )
306 352
 {
307
-	if (DMType == OldTDM)
353
+	if (DMType == OldTDM) {
308 354
 		return false;
355
+	}
309 356
 
310 357
 	TQCString re;
311 358
 
@@ -325,8 +372,9 @@ DM::localSessions( SessList &list )
325 372
 			list.append( se );
326 373
 		}
327 374
 	} else {
328
-		if (!exec( "list\talllocal\n", re ))
375
+		if (!exec( "list\talllocal\n", re )) {
329 376
 			return false;
377
+		}
330 378
 		TQStringList sess = TQStringList::split( TQChar('\t'), re.data() + 3 );
331 379
 		for (TQStringList::ConstIterator it = sess.begin(); it != sess.end(); ++it) {
332 380
 			TQStringList ts = TQStringList::split( TQChar(','), *it, true );

+ 60
- 9
tdmlib/kgreet_classic.cpp View File

@@ -45,6 +45,15 @@ protected:
45 45
 
46 46
 static int echoMode;
47 47
 
48
+TQString KClassicGreeter::passwordPrompt() {
49
+	if (func == Authenticate) {
50
+		 return i18n("&Password:");
51
+	}
52
+	else {
53
+		return i18n("Current &password:");
54
+	}
55
+}
56
+
48 57
 KClassicGreeter::KClassicGreeter( KGreeterPluginHandler *_handler,
49 58
                                   KdmThemer *themer,
50 59
                                   TQWidget *parent, TQWidget *pred,
@@ -60,7 +69,7 @@ KClassicGreeter::KClassicGreeter( KGreeterPluginHandler *_handler,
60 69
 	running( false )
61 70
 {
62 71
 	KdmItem *user_entry = 0, *pw_entry = 0;
63
-	TQGridLayout *grid = 0;
72
+	grid = 0;
64 73
 	int line = 0;
65 74
 
66 75
 	layoutItem = 0;
@@ -120,11 +129,7 @@ KClassicGreeter::KClassicGreeter( KGreeterPluginHandler *_handler,
120 129
 			passwdEdit->adjustSize();
121 130
 			pw_entry->setWidget( passwdEdit );
122 131
 		} else {
123
-			passwdLabel = new TQLabel( passwdEdit,
124
-			                          func == Authenticate ?
125
-			                            i18n("&Password:") :
126
-			                            i18n("Current &password:"),
127
-			                          parent );
132
+			passwdLabel = new TQLabel( passwdEdit, passwordPrompt(), parent );
128 133
 			grid->addWidget( passwdLabel, line, 0 );
129 134
 			grid->addWidget( passwdEdit, line++, 1 );
130 135
 		}
@@ -217,6 +222,10 @@ KClassicGreeter::setUser( const TQString &user )
217 222
 	passwdEdit->selectAll();
218 223
 }
219 224
 
225
+void KClassicGreeter::lockUserEntry( const bool lock ) {
226
+	loginEdit->setEnabled(!lock);
227
+}
228
+
220 229
 void // virtual
221 230
 KClassicGreeter::setPassword( const TQString &pass )
222 231
 {
@@ -276,10 +285,24 @@ void // virtual
276 285
 KClassicGreeter::textPrompt( const char *prompt, bool echo, bool nonBlocking )
277 286
 {
278 287
 	pExp = exp;
279
-	if (echo)
288
+	if (echo) {
280 289
 		exp = 0;
281
-	else if (!authTok)
290
+	}
291
+	else if (!authTok) {
282 292
 		exp = 1;
293
+		if (passwdLabel) {
294
+			if (prompt && (prompt[0] != 0)) {
295
+				passwdLabel->setText(prompt);
296
+			}
297
+			else {
298
+				passwdLabel->setText(passwordPrompt());
299
+			}
300
+			if (grid) {
301
+				grid->invalidate();
302
+				grid->activate();
303
+			}
304
+		}
305
+	}
283 306
 	else {
284 307
 		TQString pr( prompt );
285 308
 		if (pr.find( TQRegExp( "\\bpassword\\b", false ) ) >= 0) {
@@ -294,7 +317,8 @@ KClassicGreeter::textPrompt( const char *prompt, bool echo, bool nonBlocking )
294 317
 				                          KGreeterPluginHandler::IsSecret );
295 318
 				return;
296 319
 			}
297
-		} else {
320
+		}
321
+		else {
298 322
 			handler->gplugMsgBox( TQMessageBox::Critical,
299 323
 			                      i18n("Unrecognized prompt \"%1\"")
300 324
 			                      .arg( prompt ) );
@@ -392,6 +416,15 @@ KClassicGreeter::succeeded()
392 416
 void // virtual
393 417
 KClassicGreeter::failed()
394 418
 {
419
+	if (passwdLabel) {
420
+		// reset password prompt
421
+		passwdLabel->setText(passwordPrompt());
422
+		if (grid) {
423
+			grid->invalidate();
424
+			grid->activate();
425
+		}
426
+	}
427
+
395 428
 	// assert( running || timed_login );
396 429
 	setActive( false );
397 430
 	setActive2( false );
@@ -402,6 +435,15 @@ KClassicGreeter::failed()
402 435
 void // virtual
403 436
 KClassicGreeter::revive()
404 437
 {
438
+	if (passwdLabel) {
439
+		// reset password prompt
440
+		passwdLabel->setText(passwordPrompt());
441
+		if (grid) {
442
+			grid->invalidate();
443
+			grid->activate();
444
+		}
445
+	}
446
+
405 447
 	// assert( !running );
406 448
 	setActive2( true );
407 449
 	if (authTok) {
@@ -425,6 +467,15 @@ KClassicGreeter::revive()
425 467
 void // virtual
426 468
 KClassicGreeter::clear()
427 469
 {
470
+	if (passwdLabel) {
471
+		// reset password prompt
472
+		passwdLabel->setText(passwordPrompt());
473
+		if (grid) {
474
+			grid->invalidate();
475
+			grid->activate();
476
+		}
477
+	}
478
+
428 479
 	// assert( !running && !passwd1Edit );
429 480
 	passwdEdit->erase();
430 481
 	if (loginEdit) {

+ 3
- 0
tdmlib/kgreet_classic.h View File

@@ -50,6 +50,7 @@ class KClassicGreeter : public TQObject, public KGreeterPlugin {
50 50
 	virtual void presetEntity( const TQString &entity, int field );
51 51
 	virtual TQString getEntity() const;
52 52
 	virtual void setUser( const TQString &user );
53
+	virtual void lockUserEntry( const bool lock );
53 54
 	virtual void setPassword( const TQString &pass );
54 55
 	virtual void setEnabled( bool on );
55 56
 	virtual bool textMessage( const char *message, bool error );
@@ -70,6 +71,7 @@ class KClassicGreeter : public TQObject, public KGreeterPlugin {
70 71
 	void slotActivity();
71 72
 
72 73
   private:
74
+	TQString passwordPrompt();
73 75
 	void setActive( bool enable );
74 76
 	void setActive2( bool enable );
75 77
 	void returnData();
@@ -81,6 +83,7 @@ class KClassicGreeter : public TQObject, public KGreeterPlugin {
81 83
 	TQString fixedUser, curUser;
82 84
 	Function func;
83 85
 	Context ctx;
86
+	TQGridLayout* grid;
84 87
 	int exp, pExp, has;
85 88
 	bool running, authTok;
86 89
 };

+ 4
- 0
tdmlib/kgreet_pam.cpp View File

@@ -263,6 +263,10 @@ KPamGreeter::setUser( const TQString &user )
263 263
         }
264 264
 }
265 265
 
266
+void KPamGreeter::lockUserEntry( const bool lock ) {
267
+	loginEdit->setEnabled(!lock);
268
+}
269
+
266 270
 void // virtual
267 271
 KPamGreeter::setPassword( const TQString &pass )
268 272
 {

+ 1
- 0
tdmlib/kgreet_pam.h View File

@@ -50,6 +50,7 @@ class KPamGreeter : public TQObject, public KGreeterPlugin {
50 50
 	virtual void presetEntity( const TQString &entity, int field );
51 51
 	virtual TQString getEntity() const;
52 52
 	virtual void setUser( const TQString &user );
53
+	virtual void lockUserEntry( const bool lock );
53 54
 	virtual void setPassword( const TQString &pass );
54 55
 	virtual void setEnabled( bool on );
55 56
 	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 )
297 297
 	passwdEdit->selectAll();
298 298
 }
299 299
 
300
+void KWinbindGreeter::lockUserEntry( const bool lock ) {
301
+	loginEdit->setEnabled(!lock);
302
+}
303
+
300 304
 void // virtual
301 305
 KWinbindGreeter::setPassword( const TQString &pass )
302 306
 {

+ 1
- 0
tdmlib/kgreet_winbind.h View File

@@ -54,6 +54,7 @@ class KWinbindGreeter : public TQObject, public KGreeterPlugin {
54 54
 	virtual void presetEntity( const TQString &entity, int field );
55 55
 	virtual TQString getEntity() const;
56 56
 	virtual void setUser( const TQString &user );
57
+	virtual void lockUserEntry( const bool lock );
57 58
 	virtual void setPassword( const TQString &pass );
58 59
 	virtual void setEnabled( bool on );
59 60
 	virtual bool textMessage( const char *message, bool error );

+ 7
- 1
tdmlib/kgreeterplugin.h View File

@@ -152,6 +152,12 @@ public:
152 152
     virtual void setUser( const TQString &user ) = 0;
153 153
 
154 154
     /**
155
+     * Lock or unlock editing of the username entry field
156
+     * @param lock true to lock, false to unlock
157
+     */
158
+    virtual void lockUserEntry( const bool lock ) = 0;
159
+
160
+    /**
155 161
      * "Push" a password into the talker.
156 162
      * @param pass the password to set.
157 163
      */
@@ -183,7 +189,7 @@ public:
183 189
 
184 190
     /**
185 191
      * Prompt the user for data. Reply by calling handler->gplugReturnText().
186
-     * @param propmt the prompt to display. It may be null, in which case
192
+     * @param prompt the prompt to display. It may be null, in which case
187 193
      *  "Username"/"Password" should be shown and the replies should be tagged
188 194
      *  with the respective Is* flag.
189 195
      * @param echo if true, a normal input widget can be used, otherwise one that

Loading…
Cancel
Save