@ -40,6 +40,7 @@
# include <ldap.h>
# include <stdlib.h>
# include <sys/time.h>
# include <errno.h>
# 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 ( " <p> " ) . append ( i18n ( " Potential causes " ) ) . append ( " :<br> " ) . append ( i18n ( " * Invalid credentials " ) ) . append ( " <br> " ) . append ( i18n ( " * Clock skew between the realm's KDC and this machine " ) ) . append ( " <br> " ) . append ( i18n ( " * Inability to negotiate a compatible encryption type with the realm's KDC " ) ) . append ( " <br> " ) . 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 ;