Branch: master

53a442c9 2015-09-29 15:07:11 Timothy Pearson
Allow Kerberos ticket init via cryptographic card
M src/ldappasswddlg.cpp
M src/ldappasswddlg.h
M src/libtdeldap.cpp
M src/libtdeldap.h
diff --git a/src/ldappasswddlg.cpp b/src/ldappasswddlg.cpp
index b3c5f5a..70407ef 100644
--- a/src/ldappasswddlg.cpp
+++ b/src/ldappasswddlg.cpp
@@ -32,8 +32,8 @@
 #include "ldaplogindlg.h"
 #include "ldappasswddlg.h"
 
-LDAPPasswordDialog::LDAPPasswordDialog(TQWidget* parent, const char* name, bool allowGSSAPI)
-	: KDialogBase(parent, name, true, i18n("LDAP Authentication"), (allowGSSAPI)?Ok|Cancel|User1:Ok|Cancel, Ok, true, i18n("Authenticate with SASL/GSSAPI"))
+LDAPPasswordDialog::LDAPPasswordDialog(TQWidget* parent, const char* name, bool allowGSSAPI, bool allowSmartCard)
+	: KDialogBase(parent, name, true, i18n("LDAP Authentication"), Ok|Cancel|((allowGSSAPI)?User1:0)|((allowSmartCard)?User2:0), Ok, true, i18n("Authenticate with SASL/GSSAPI"), i18n("Authenticate with cryptographic card"))
 {
 	m_base = new LDAPLogin(this);
 
@@ -42,11 +42,19 @@
 
 void LDAPPasswordDialog::slotOk() {
 	use_gssapi = false;
+	use_smartcard = false;
 	accept();
 }
 
 void LDAPPasswordDialog::slotUser1() {
 	use_gssapi = true;
+	use_smartcard = false;
+	accept();
+}
+
+void LDAPPasswordDialog::slotUser2() {
+	use_gssapi = false;
+	use_smartcard = true;
 	accept();
 }
 
diff --git a/src/ldappasswddlg.h b/src/ldappasswddlg.h
index 18e1e54..ed216a3 100644
--- a/src/ldappasswddlg.h
+++ b/src/ldappasswddlg.h
@@ -31,15 +31,17 @@
 	Q_OBJECT
 
 public:
-	LDAPPasswordDialog(TQWidget* parent = 0, const char* name = 0, bool allowGSSAPI = true);
+	LDAPPasswordDialog(TQWidget* parent = 0, const char* name = 0, bool allowGSSAPI = true, bool allowSmartCard = false);
 
 public slots:
 	void slotOk();
 	void slotUser1();
+	void slotUser2();
 
 public:
 	LDAPLogin *m_base;
 	bool use_gssapi;
+	bool use_smartcard;
 };
 
 #endif
diff --git a/src/libtdeldap.cpp b/src/libtdeldap.cpp
index 772596a..7543268 100644
--- a/src/libtdeldap.cpp
+++ b/src/libtdeldap.cpp
@@ -38,6 +38,7 @@
 #include <tdesu/process.h>
 #include <ksslcertificate.h>
 #include <krfcdate.h>
+#include <tdehardwaredevices.h>
 #include <tdecryptographiccarddevice.h>
 
 #include <ldap.h>
@@ -286,7 +287,7 @@
 		havepass = true;
 	}
 	else {
-		LDAPPasswordDialog passdlg(0, 0, (m_krbTickets.count() > 0));
+		LDAPPasswordDialog passdlg(0, 0, (m_krbTickets.count() > 0), false);
 		passdlg.m_base->ldapAdminRealm->setEnabled(false);
 		passdlg.m_base->ldapAdminRealm->insertItem(m_realm);
 		passdlg.m_base->ldapUseTLS->setChecked(true);
@@ -1655,7 +1656,7 @@
 	return realms;
 }
 
-int LDAPManager::getKerberosPassword(LDAPCredentials &creds, TQString prompt, bool requestServicePrincipal, TQWidget* parent)
+int LDAPManager::getKerberosPassword(LDAPCredentials &creds, TQString prompt, bool requestServicePrincipal, bool allowSmartCard, TQWidget* parent)
 {
 	int i;
 
@@ -1665,7 +1666,7 @@
 	if (creds.realm != "") {
 		defaultRealm = creds.realm;
 	}
-	LDAPPasswordDialog passdlg(parent, 0, false);
+	LDAPPasswordDialog passdlg(parent, 0, false, allowSmartCard);
 	passdlg.m_base->ldapAdminRealm->setEnabled(true);
 	LDAPRealmConfigList::Iterator it;
 	i=0;
@@ -1693,6 +1694,13 @@
 		creds.realm = passdlg.m_base->ldapAdminRealm->currentText();
 		creds.service = passdlg.m_base->kerberosServicePrincipal->text();
 		creds.use_tls = passdlg.m_base->ldapUseTLS->isOn();
+		creds.use_gssapi = false;
+		if (allowSmartCard) {
+			creds.use_smartcard = passdlg.use_smartcard;
+		}
+		else {
+			creds.use_smartcard = false;
+		}
 	}
 	return ret;
 }
@@ -1700,6 +1708,58 @@
 int LDAPManager::obtainKerberosTicket(LDAPCredentials creds, TQString principal, TQString *errstr) {
 	TQCString command = "kinit";
 	QCStringList args;
+	if (creds.use_smartcard) {
+		// Get PKCS#11 slot number from the LDAP configuration file
+		KSimpleConfig* systemconfig = new KSimpleConfig( TQString::fromLatin1( KDE_CONFDIR "/ldap/ldapconfigrc" ));
+		systemconfig->setGroup(NULL);
+		int pkcs11_login_card_slot = systemconfig->readNumEntry("PKCS11LoginCardSlot", 0);
+		delete systemconfig;
+
+		TQString pkcsProviderString = "PKCS11:" + TDECryptographicCardDevice::pkcsProviderLibrary();
+		if (pkcs11_login_card_slot != 0) {
+			 pkcsProviderString.append(TQString(",slot=%1").arg(pkcs11_login_card_slot));
+		}
+		args << TQCString("-C") << TQCString(pkcsProviderString);
+
+		// Find certificate on card and set credentials to match
+		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);
+			TQString username = TQString::null;
+			TQString realm = TQString::null;
+			X509CertificatePtrList certList = cdevice->cardX509Certificates();
+			if (certList.count() > 0) {
+				TQStringList::Iterator it;
+				KSSLCertificate* card_cert = NULL;
+				card_cert = KSSLCertificate::fromX509(certList[0]);
+				TQStringList cert_subject_parts = TQStringList::split("/", card_cert->getSubject(), false);
+				TQStringList reversed_cert_subject_parts;
+				for (it = cert_subject_parts.begin(); it != cert_subject_parts.end(); it++) {
+					reversed_cert_subject_parts.prepend(*it);
+				}
+				for (it = reversed_cert_subject_parts.begin(); it != reversed_cert_subject_parts.end(); ++it ) {
+					TQString lcpart = (*it).lower();
+					if (lcpart.startsWith("cn=")) {
+						username = lcpart.right(lcpart.length() - strlen("cn="));
+					}
+					else if (lcpart.startsWith("dc=")) {
+						realm.append(lcpart.right(lcpart.length() - strlen("dc=")) + ".");
+					}
+				}
+				if (realm.endsWith(".")) {
+					realm.truncate(realm.length() - 1);
+				}
+				delete card_cert;
+			}
+			if (username != "") {
+				creds.username = username;
+				creds.realm = realm;
+				break;
+			}
+		}
+	}
 	if (principal == "") {
 		args << TQCString(creds.username + "@" + creds.realm.upper());
 	}
@@ -1712,7 +1772,17 @@
 	kinitProc.exec(command, args);
 	prompt = readFullLineFromPtyProcess(&kinitProc);
 	prompt = prompt.stripWhiteSpace();
-	if (prompt.endsWith(" Password:")) {
+	while (prompt.endsWith(" Password:") || (creds.use_smartcard && prompt.contains("PIN"))) {
+		if (creds.use_smartcard) {
+			TQCString password;
+			int result = KPasswordDialog::getPassword(password, prompt);
+			if (result == KPasswordDialog::Accepted) {
+				creds.password = password;
+			}
+			else {
+				return 0;
+			}
+		}
 		kinitProc.enableLocalEcho(false);
 		kinitProc.writeLine(creds.password, true);
 		do { // Discard our own input
@@ -3560,7 +3630,7 @@
 				replicationinfo.syncDN = "cn=admin," + m_basedc;
 			}
 			if (!errstr && replicationinfo.syncPassword.isNull()) {
-				LDAPPasswordDialog passdlg(0, 0, false);
+				LDAPPasswordDialog passdlg(0, 0, false, false);
 				passdlg.m_base->ldapAdminRealm->setEnabled(false);
 				passdlg.m_base->ldapAdminRealm->insertItem(m_realm);
 				passdlg.m_base->ldapUseTLS->hide();
@@ -5433,6 +5503,7 @@
 	// TQStrings are always initialized to TQString::null, so they don't need initialization here...
 	use_tls = true;
 	use_gssapi = false;
+	use_smartcard = false;
 }
 
 LDAPCredentials::~LDAPCredentials() {
diff --git a/src/libtdeldap.h b/src/libtdeldap.h
index 69e7805..4c249e1 100644
--- a/src/libtdeldap.h
+++ b/src/libtdeldap.h
@@ -180,6 +180,7 @@
 		TQString realm;
 		bool use_tls;
 		bool use_gssapi;
+		bool use_smartcard;
 		TQString service;
 };
 
@@ -568,7 +569,7 @@
 		static TQString cnFromDn(TQString dn);
 
 		static KerberosTicketInfoList getKerberosTicketList(TQString cache=TQString::null, TQString *cacheFileName=0);
-		static int getKerberosPassword(LDAPCredentials &creds, TQString prompt, bool requestServicePrincipal=false, TQWidget* parent=0);
+		static int getKerberosPassword(LDAPCredentials &creds, TQString prompt, bool requestServicePrincipal=false, bool allowSmartCard=false, TQWidget* parent=0);
 		static int obtainKerberosTicket(LDAPCredentials creds, TQString principal, TQString *errstr=0);
 		static int obtainKerberosServiceTicket(TQString principal, TQString *errstr=0);
 		static int destroyKerberosTicket(TQString principal, TQString *errstr=0);