From 53a442c926a03e8cbd6b901679b9c658ee29e02f Mon Sep 17 00:00:00 2001 From: Timothy Pearson Date: Tue, 29 Sep 2015 15:07:11 -0500 Subject: [PATCH] Allow Kerberos ticket init via cryptographic card --- src/ldappasswddlg.cpp | 12 +++++-- src/ldappasswddlg.h | 4 ++- src/libtdeldap.cpp | 81 ++++++++++++++++++++++++++++++++++++++++--- src/libtdeldap.h | 3 +- 4 files changed, 91 insertions(+), 9 deletions(-) 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 @@ LDAPPasswordDialog::LDAPPasswordDialog(TQWidget* parent, const char* name, bool 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 @@ class LDAPPasswordDialog : public KDialogBase 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 #include #include +#include #include #include @@ -286,7 +287,7 @@ int LDAPManager::bind(TQString* errstr) { 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 @@ LDAPRealmConfigList LDAPManager::fetchAndReadTDERealmList(TQString *defaultRealm 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 @@ int LDAPManager::getKerberosPassword(LDAPCredentials &creds, TQString prompt, bo 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 @@ int LDAPManager::getKerberosPassword(LDAPCredentials &creds, TQString prompt, bo 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::getKerberosPassword(LDAPCredentials &creds, TQString prompt, bo 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(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 @@ int LDAPManager::obtainKerberosTicket(LDAPCredentials creds, TQString principal, 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 @@ int LDAPManager::setLDAPMasterReplicationSettings(LDAPMasterReplicationInfo repl 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 @@ LDAPCredentials::LDAPCredentials() { // 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 @@ class LDAPCredentials TQString realm; bool use_tls; bool use_gssapi; + bool use_smartcard; TQString service; }; @@ -568,7 +569,7 @@ class LDAPManager : public TQObject { 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);