From 98058c6c16819a360d4a74c7375b40766d798fb6 Mon Sep 17 00:00:00 2001 From: Timothy Pearson Date: Tue, 15 Jan 2013 19:35:55 -0600 Subject: Fix potential kadmin failures Export static kadmin process read method --- src/libtdeldap.cpp | 81 ++++++++++++++++++++++++++++++++++++++++-------------- src/libtdeldap.h | 5 ++++ 2 files changed, 66 insertions(+), 20 deletions(-) diff --git a/src/libtdeldap.cpp b/src/libtdeldap.cpp index 415a5a7..5c79891 100644 --- a/src/libtdeldap.cpp +++ b/src/libtdeldap.cpp @@ -40,6 +40,7 @@ #include #include #include +#include #include "libtdeldap.h" #include "ldaplogindlg.h" @@ -69,6 +70,16 @@ enum ErrorCauseLocation { ERRORCAUSE_LOCATION_BIND = 0 }; +bool fileExists(const char* filename) { + struct stat sts; + if (stat(filename, &sts) == -1 && errno == ENOENT) { + return false; + } + else { + return true; + } +} + LDAPManager::LDAPManager(TQString realm, TQString host, TQObject *parent, const char *name) : TQObject(parent, name), m_realm(realm), m_host(host), m_port(0), m_creds(0), m_ldap(0) { TQStringList domainChunks = TQStringList::split(".", realm.lower()); @@ -85,6 +96,13 @@ LDAPManager::~LDAPManager() { unbind(true); } +TQString LDAPManager::detailedKAdminErrorMessage(TQString initialMessage) { + if (initialMessage.contains("Looping detected inside krb5_get_in_tkt")) { + initialMessage.append("

").append(i18n("Potential causes")).append(":
").append(i18n(" * Invalid credentials")).append("
").append(i18n(" * Clock skew between the realm's KDC and this machine")).append("
").append(i18n(" * Inability to negotiate a compatible encryption type with the realm's KDC")).append("
").append(i18n(" * No connectivity to the realm's KDC")); + } + return initialMessage; +} + TQString LDAPManager::ldapdnForRealm(TQString realm) { TQStringList domainChunks = TQStringList::split(".", realm.lower()); TQString basedc = "dc=" + domainChunks.join(",dc="); @@ -838,7 +856,7 @@ int LDAPManager::updateUserInfo(LDAPUserInfo user) { // To make matters worse, the colon does not uniquely designate the end of a line; for example the response "kadmin: ext openldap/foo.bar.baz: Principal does not exist" // One way around this would be to see if the first colon is part of a "kadmin:" string; if so, then the colon is not a reliable end of line indicator for the current line // (in fact only '\r' should be used as the end of line indicator in that case) -TQString readFullLineFromPtyProcess(PtyProcess* proc) { +TQString LDAPManager::readFullLineFromPtyProcess(PtyProcess* proc) { TQString result = ""; while ((!result.contains("\r")) && (!result.contains(">")) && @@ -897,6 +915,7 @@ int LDAPManager::setPasswordForUser(LDAPUserInfo user, TQString *errstr) { prompt = prompt.stripWhiteSpace(); if (prompt == "kadmin>") { command = TQCString("passwd "+user.name); + kadminProc.enableLocalEcho(false); kadminProc.writeLine(command, true); do { // Discard our own input prompt = readFullLineFromPtyProcess(&kadminProc); @@ -904,6 +923,7 @@ int LDAPManager::setPasswordForUser(LDAPUserInfo user, TQString *errstr) { } while (prompt == TQString(command)); prompt = prompt.stripWhiteSpace(); if ((prompt.endsWith(" Password:")) && (prompt.startsWith(TQString(user.name + "@")))) { + kadminProc.enableLocalEcho(false); kadminProc.writeLine(user.new_password, true); do { // Discard our own input prompt = readFullLineFromPtyProcess(&kadminProc); @@ -911,6 +931,7 @@ int LDAPManager::setPasswordForUser(LDAPUserInfo user, TQString *errstr) { } while (prompt == ""); prompt = prompt.stripWhiteSpace(); if ((prompt.endsWith(" Password:")) && (prompt.startsWith("Verify"))) { + kadminProc.enableLocalEcho(false); kadminProc.writeLine(user.new_password, true); do { // Discard our own input prompt = readFullLineFromPtyProcess(&kadminProc); @@ -927,6 +948,7 @@ int LDAPManager::setPasswordForUser(LDAPUserInfo user, TQString *errstr) { } } if (admincreds.password != "") { + kadminProc.enableLocalEcho(false); kadminProc.writeLine(admincreds.password, true); do { // Discard our own input prompt = readFullLineFromPtyProcess(&kadminProc); @@ -936,23 +958,27 @@ int LDAPManager::setPasswordForUser(LDAPUserInfo user, TQString *errstr) { } } if (prompt != "kadmin>") { - if (errstr) *errstr = prompt; + if (errstr) *errstr = detailedKAdminErrorMessage(prompt); + kadminProc.enableLocalEcho(false); kadminProc.writeLine("quit", true); return 1; } // Success! + kadminProc.enableLocalEcho(false); kadminProc.writeLine("quit", true); return 0; } else if (prompt == "kadmin>") { // Success! + kadminProc.enableLocalEcho(false); kadminProc.writeLine("quit", true); return 0; } // Failure - if (errstr) *errstr = prompt; + if (errstr) *errstr = detailedKAdminErrorMessage(prompt); + kadminProc.enableLocalEcho(false); kadminProc.writeLine("quit", true); return 1; } @@ -1243,6 +1269,7 @@ int LDAPManager::obtainKerberosTicket(LDAPCredentials creds, TQString principal, prompt = readFullLineFromPtyProcess(&kadminProc); prompt = prompt.stripWhiteSpace(); if (prompt.endsWith(" Password:")) { + kadminProc.enableLocalEcho(false); kadminProc.writeLine(creds.password, true); do { // Discard our own input prompt = readFullLineFromPtyProcess(&kadminProc); @@ -1251,7 +1278,7 @@ int LDAPManager::obtainKerberosTicket(LDAPCredentials creds, TQString principal, prompt = prompt.stripWhiteSpace(); } if ((prompt != "") && (prompt != "TDE process terminated")) { - if (errstr) *errstr = prompt; + if (errstr) *errstr = detailedKAdminErrorMessage(prompt); return 1; } @@ -1271,7 +1298,7 @@ int LDAPManager::obtainKerberosServiceTicket(TQString principal, TQString *errst pclose(output); if (ret != "") { - if (errstr) *errstr = ret; + if (errstr) *errstr = detailedKAdminErrorMessage(ret); return -1; } return 0; @@ -1289,7 +1316,7 @@ int LDAPManager::destroyKerberosTicket(TQString principal, TQString *errstr) { pclose(output); if (ret != "") { - if (errstr) *errstr = ret; + if (errstr) *errstr = detailedKAdminErrorMessage(ret); return -1; } return 0; @@ -1543,6 +1570,7 @@ int LDAPManager::addServiceInfo(LDAPServiceInfo service, TQString *errstr) { prompt = prompt.stripWhiteSpace(); if (prompt == "kadmin>") { command = TQCString("ank --random-key "+hoststring); + kadminProc.enableLocalEcho(false); kadminProc.writeLine(command, true); do { // Discard our own input prompt = readFullLineFromPtyProcess(&kadminProc); @@ -1560,6 +1588,7 @@ int LDAPManager::addServiceInfo(LDAPServiceInfo service, TQString *errstr) { } } if (admincreds.password != "") { + kadminProc.enableLocalEcho(false); kadminProc.writeLine(admincreds.password, true); do { // Discard our own input prompt = readFullLineFromPtyProcess(&kadminProc); @@ -1569,7 +1598,8 @@ int LDAPManager::addServiceInfo(LDAPServiceInfo service, TQString *errstr) { } } if (prompt.contains("authentication failed")) { - if (errstr) *errstr = prompt; + if (errstr) *errstr = detailedKAdminErrorMessage(prompt); + kadminProc.enableLocalEcho(false); kadminProc.writeLine("quit", true); return 1; } @@ -1583,6 +1613,7 @@ int LDAPManager::addServiceInfo(LDAPServiceInfo service, TQString *errstr) { defaultParam = prompt.mid(leftbracket, rightbracket-leftbracket); } command = TQCString(defaultParam); + kadminProc.enableLocalEcho(false); kadminProc.writeLine(command, true); do { // Discard our own input prompt = readFullLineFromPtyProcess(&kadminProc); @@ -1592,12 +1623,14 @@ int LDAPManager::addServiceInfo(LDAPServiceInfo service, TQString *errstr) { } } if (prompt != "kadmin>") { - if (errstr) *errstr = prompt; + if (errstr) *errstr = detailedKAdminErrorMessage(prompt); + kadminProc.enableLocalEcho(false); kadminProc.writeLine("quit", true); return 1; } // Success! + kadminProc.enableLocalEcho(false); kadminProc.writeLine("quit", true); unbind(true); // Using kadmin can disrupt our LDAP connection @@ -2143,9 +2176,11 @@ void LDAPManager::writeLDAPConfFile(LDAPRealmConfig realmcfg) { } // Create symbolic link to secondary LDAP configuration file - if (unlink(LDAP_SECONDARY_FILE) < 0) { - printf("ERROR: Unable to unlink \"%s\"\n\r", LDAP_SECONDARY_FILE); - return; + if (fileExists(LDAP_SECONDARY_FILE)) { + if (unlink(LDAP_SECONDARY_FILE) < 0) { + printf("ERROR: Unable to unlink \"%s\"\n\r", LDAP_SECONDARY_FILE); + return; + } } command = TQString("ln -s %1 %2").arg(LDAP_FILE).arg(LDAP_SECONDARY_FILE); if (system(command) < 0) { @@ -2154,9 +2189,11 @@ void LDAPManager::writeLDAPConfFile(LDAPRealmConfig realmcfg) { } // Create symbolic link to tertiary LDAP configuration file - if (unlink(LDAP_TERTIARY_FILE) < 0) { - printf("ERROR: Unable to unlink \"%s\"\n\r", LDAP_TERTIARY_FILE); - return; + if (fileExists(LDAP_TERTIARY_FILE)) { + if (unlink(LDAP_TERTIARY_FILE) < 0) { + printf("ERROR: Unable to unlink \"%s\"\n\r", LDAP_TERTIARY_FILE); + return; + } } command = TQString("ln -s %1 %2").arg(LDAP_FILE).arg(LDAP_TERTIARY_FILE); if (system(command) < 0) { @@ -2529,9 +2566,11 @@ int LDAPManager::generatePublicKerberosCertificate(LDAPCertConfig certinfo, LDAP printf("ERROR: Unable to change owner of \"%s\"\n\r", kdc_certfile.ascii()); return -1; } - if (unlink(kdc_reqfile.ascii()) < 0) { - printf("ERROR: Unable to unlink \"%s\"\n\r", kdc_reqfile.ascii()); - return -1; + if (fileExists(kdc_reqfile.ascii())) { + if (unlink(kdc_reqfile.ascii()) < 0) { + printf("ERROR: Unable to unlink \"%s\"\n\r", kdc_reqfile.ascii()); + return -1; + } } return 0; @@ -2565,9 +2604,11 @@ int LDAPManager::generatePublicLDAPCertificate(LDAPCertConfig certinfo, LDAPReal printf("ERROR: Unable to change owner of \"%s\"\n\r", ldap_certfile.ascii()); return -1; } - if (unlink(ldap_reqfile.ascii()) < 0) { - printf("ERROR: Unable to unlink \"%s\"\n\r", ldap_reqfile.ascii()); - return -1; + if (fileExists(ldap_reqfile.ascii())) { + if (unlink(ldap_reqfile.ascii()) < 0) { + printf("ERROR: Unable to unlink \"%s\"\n\r", ldap_reqfile.ascii()); + return -1; + } } return 0; diff --git a/src/libtdeldap.h b/src/libtdeldap.h index 341dff9..1bad94d 100644 --- a/src/libtdeldap.h +++ b/src/libtdeldap.h @@ -361,6 +361,8 @@ typedef TQValueList LDAPMachineInfoList; typedef TQValueList LDAPServiceInfoList; typedef TQValueList KerberosTicketInfoList; +class PtyProcess; + class LDAPManager : public TQObject { Q_OBJECT @@ -421,6 +423,9 @@ class LDAPManager : public TQObject { static int obtainKerberosServiceTicket(TQString principal, TQString *errstr=0); static int destroyKerberosTicket(TQString principal, TQString *errstr=0); + static TQString detailedKAdminErrorMessage(TQString initialMessage); + static TQString readFullLineFromPtyProcess(PtyProcess* proc); + private: LDAPUserInfo parseLDAPUserRecord(LDAPMessage* entry); LDAPGroupInfo parseLDAPGroupRecord(LDAPMessage* entry); -- cgit v1.2.3