#include <stdio.h>
#include <string.h> //used for strcpy, etc.
#include <stdlib.h> //used for malloc
#include <ctype.h> //use for isprint
#include <syslog.h> //error logging
#include <DirectoryService/DirServices.h>
#include <DirectoryService/DirServicesUtils.h>
#include <DirectoryService/DirServicesConst.h>
#include "CLDAPNode.h"
#include "CLDAPv3Configs.h"
#define OCSEPCHARS " '()$"
extern CPlugInRef *gConfigTable; extern uInt32 gConfigTableLen;
CLDAPNode::CLDAPNode ( void )
{
}
CLDAPNode::~CLDAPNode ( void )
{
}
sInt32 CLDAPNode::SafeOpen ( char *inNodeName,
LDAP **outLDAPHost,
uInt32 *outLDAPConfigTableIndex )
{
sInt32 siResult = eDSNoErr;
sLDAPNodeStruct *pLDAPNodeStruct = nil;
uInt32 iTableIndex = 0;
sLDAPConfigData *pConfig = nil;
int ldapPort = LDAP_PORT;
char *aLDAPName = nil;
bool bConfigFound = false;
LDAPNodeMapI aLDAPNodeMapI;
string aNodeName(inNodeName);
fLDAPNodeOpenMutex.Wait();
aLDAPNodeMapI = fLDAPNodeMap.find(aNodeName);
if (aLDAPNodeMapI == fLDAPNodeMap.end())
{
pLDAPNodeStruct = (sLDAPNodeStruct *) calloc(1, sizeof(sLDAPNodeStruct));
pLDAPNodeStruct->fRefCount = 1;
pLDAPNodeStruct->fLDAPSessionMutex = new DSMutexSemaphore();
for (iTableIndex=1; iTableIndex<gConfigTableLen; iTableIndex++)
{
pConfig = (sLDAPConfigData *)gConfigTable->GetItemData( iTableIndex );
if (pConfig != nil)
{
if (pConfig->fServerName != nil)
{
if (::strcmp(pConfig->fServerName,inNodeName) == 0)
{
ldapPort = pConfig->fServerPort;
bConfigFound = true;
pLDAPNodeStruct->fLDAPConfigTableIndex = iTableIndex;
pLDAPNodeStruct->fIdleTO = 2 * pConfig->fIdleTimeout;
pLDAPNodeStruct->fDelayRebindTry = pConfig->fDelayRebindTry;
break;
} } } }
if (!bConfigFound)
{
siResult = ParseLDAPNodeName( inNodeName, &aLDAPName, &ldapPort );
if (siResult == eDSNoErr)
{
pLDAPNodeStruct->fServerName = aLDAPName;
pLDAPNodeStruct->fDirectLDAPPort = ldapPort;
pLDAPNodeStruct->fLDAPConfigTableIndex = 0;
}
}
fLDAPNodeMap[aNodeName] = pLDAPNodeStruct;
fLDAPNodeOpenMutex.Signal();
}
else
{
pLDAPNodeStruct = aLDAPNodeMapI->second;
fLDAPNodeOpenMutex.Signal();
pConfig = (sLDAPConfigData *)gConfigTable->GetItemData( pLDAPNodeStruct->fLDAPConfigTableIndex );
ldapPort = pConfig->fServerPort;
pLDAPNodeStruct->fRefCount++;
}
if (siResult == eDSNoErr)
{
if (pLDAPNodeStruct->fLDAPSessionMutex != nil)
{
pLDAPNodeStruct->fLDAPSessionMutex->Wait();
}
siResult = BindProc( pLDAPNodeStruct );
if (pLDAPNodeStruct->fLDAPSessionMutex != nil)
{
pLDAPNodeStruct->fLDAPSessionMutex->Signal();
}
*outLDAPHost = pLDAPNodeStruct->fHost;
*outLDAPConfigTableIndex = pLDAPNodeStruct->fLDAPConfigTableIndex;
}
return(siResult);
}
sInt32 CLDAPNode::AuthOpen ( char *inNodeName,
LDAP *inHost,
char *inUserName,
void *inAuthCredential,
char *inAuthType,
LDAP **outLDAPHost,
uInt32 *inOutLDAPConfigTableIndex,
bool shouldCloseOld )
{
sInt32 siResult = eDSNoErr;
sLDAPNodeStruct *pLDAPNodeStruct = nil;
sLDAPNodeStruct *pLDAPAuthNodeStruct = nil;
int ldapPort = LDAP_PORT;
char *aLDAPName = nil;
LDAPNodeMapI aLDAPNodeMapI;
string aNodeName(inNodeName);
fLDAPNodeOpenMutex.Wait();
aLDAPNodeMapI = fLDAPNodeMap.find(aNodeName);
if (aLDAPNodeMapI != fLDAPNodeMap.end())
{
pLDAPNodeStruct = aLDAPNodeMapI->second;
pLDAPAuthNodeStruct = (sLDAPNodeStruct *) calloc(1, sizeof(sLDAPNodeStruct));
if (pLDAPNodeStruct->fLDAPConfigTableIndex != 0)
{
pLDAPAuthNodeStruct->fLDAPConfigTableIndex = pLDAPNodeStruct->fLDAPConfigTableIndex;
}
else
{
pLDAPAuthNodeStruct->fServerName = pLDAPNodeStruct->fServerName;
pLDAPAuthNodeStruct->fDirectLDAPPort = pLDAPNodeStruct->fDirectLDAPPort;
}
pLDAPAuthNodeStruct->fUserName = inUserName;
pLDAPAuthNodeStruct->fAuthCredential = inAuthCredential;
pLDAPAuthNodeStruct->fAuthType = inAuthType;
fLDAPNodeOpenMutex.Signal();
siResult = BindProc( pLDAPAuthNodeStruct );
if (siResult == eDSNoErr)
{
*outLDAPHost = pLDAPAuthNodeStruct->fHost;
*inOutLDAPConfigTableIndex = pLDAPNodeStruct->fLDAPConfigTableIndex;
if ( shouldCloseOld )
{
fLDAPNodeOpenMutex.Wait();
if (inHost == pLDAPNodeStruct->fHost)
{
pLDAPNodeStruct->fRefCount--;
if (pLDAPNodeStruct->fRefCount == 0)
{
CleanLDAPNodeStruct(pLDAPNodeStruct);
fLDAPNodeMap.erase(aNodeName);
}
}
fLDAPNodeOpenMutex.Signal();
}
}
if (pLDAPAuthNodeStruct != nil)
{
free(pLDAPAuthNodeStruct);
pLDAPAuthNodeStruct = nil;
}
}
else if (inHost != nil)
{
fLDAPNodeOpenMutex.Signal();
pLDAPAuthNodeStruct = (sLDAPNodeStruct *) calloc(1, sizeof(sLDAPNodeStruct));
siResult = ParseLDAPNodeName( inNodeName, &aLDAPName, &ldapPort );
if (siResult == eDSNoErr)
{
pLDAPAuthNodeStruct->fServerName = aLDAPName;
pLDAPAuthNodeStruct->fDirectLDAPPort = ldapPort;
pLDAPAuthNodeStruct->fLDAPConfigTableIndex = *inOutLDAPConfigTableIndex;
siResult = BindProc( pLDAPAuthNodeStruct );
if (siResult == eDSNoErr)
{
*outLDAPHost = pLDAPAuthNodeStruct->fHost;
if ( shouldCloseOld )
{
ldap_unbind( inHost );
inHost = nil;
}
}
else
{
siResult = eDSAuthFailed;
}
}
if (pLDAPAuthNodeStruct != nil)
{
if (pLDAPAuthNodeStruct->fServerName != nil)
{
free(pLDAPAuthNodeStruct->fServerName); }
free(pLDAPAuthNodeStruct);
pLDAPAuthNodeStruct = nil;
}
}
else
{
fLDAPNodeOpenMutex.Signal();
siResult = eDSOpenNodeFailed;
}
return(siResult);
}
sInt32 CLDAPNode::RebindSession( char *inNodeName,
LDAP *inHost,
LDAP **outLDAPHost )
{
sInt32 siResult = eDSNoErr;
sLDAPNodeStruct *pLDAPNodeStruct = nil;
LDAPNodeMapI aLDAPNodeMapI;
string aNodeName(inNodeName);
fLDAPNodeOpenMutex.Wait();
aLDAPNodeMapI = fLDAPNodeMap.find(aNodeName);
if (aLDAPNodeMapI != fLDAPNodeMap.end())
{
pLDAPNodeStruct = aLDAPNodeMapI->second;
if (pLDAPNodeStruct->fHost != inHost)
{
siResult = eDSOpenNodeFailed;
}
if (siResult == eDSNoErr)
{
if (pLDAPNodeStruct->fHost != nil)
{
ldap_unbind(pLDAPNodeStruct->fHost);
pLDAPNodeStruct->fHost = nil;
}
fLDAPNodeOpenMutex.Signal();
if (pLDAPNodeStruct->fLDAPSessionMutex != nil)
{
pLDAPNodeStruct->fLDAPSessionMutex->Wait();
}
siResult = BindProc( pLDAPNodeStruct );
if (pLDAPNodeStruct->fLDAPSessionMutex != nil)
{
pLDAPNodeStruct->fLDAPSessionMutex->Signal();
}
if (siResult == eDSNoErr)
{
*outLDAPHost = pLDAPNodeStruct->fHost;
}
}
else
{
fLDAPNodeOpenMutex.Signal();
}
}
else {
fLDAPNodeOpenMutex.Signal();
siResult = eDSOpenNodeFailed;
}
return(siResult);
}
sInt32 CLDAPNode::SimpleAuth( char *inNodeName,
char *inUserName,
void *inAuthCredential )
{
sInt32 siResult = eDSNoErr;
sLDAPNodeStruct *pLDAPAuthNodeStruct = nil;
sLDAPNodeStruct *pLDAPNodeStruct = nil;
LDAPNodeMapI aLDAPNodeMapI;
string aNodeName(inNodeName);
fLDAPNodeOpenMutex.Wait();
aLDAPNodeMapI = fLDAPNodeMap.find(aNodeName);
if (aLDAPNodeMapI != fLDAPNodeMap.end())
{
pLDAPNodeStruct = aLDAPNodeMapI->second;
pLDAPAuthNodeStruct = (sLDAPNodeStruct *) calloc(1, sizeof(sLDAPNodeStruct));
if (pLDAPNodeStruct->fLDAPConfigTableIndex != 0)
{
pLDAPAuthNodeStruct->fLDAPConfigTableIndex = pLDAPNodeStruct->fLDAPConfigTableIndex;
}
else
{
pLDAPAuthNodeStruct->fServerName = pLDAPNodeStruct->fServerName;
pLDAPAuthNodeStruct->fDirectLDAPPort = pLDAPNodeStruct->fDirectLDAPPort;
}
pLDAPAuthNodeStruct->fHost = nil; pLDAPAuthNodeStruct->fLDAPSessionMutex = nil;
pLDAPAuthNodeStruct->fUserName = inUserName;
pLDAPAuthNodeStruct->fAuthCredential = inAuthCredential;
siResult = BindProc( pLDAPAuthNodeStruct );
if (siResult != eDSNoErr)
{
siResult = eDSAuthFailed;
}
if (pLDAPAuthNodeStruct->fHost != nil)
{
ldap_unbind(pLDAPAuthNodeStruct->fHost);
}
free(pLDAPAuthNodeStruct);
fLDAPNodeOpenMutex.Signal();
}
else {
fLDAPNodeOpenMutex.Signal();
siResult = eDSAuthFailed;
}
return(siResult);
}
sInt32 CLDAPNode::RebindAuthSession( char *inNodeName,
LDAP *inHost,
char *inUserName,
void *inAuthCredential,
char *inAuthType,
uInt32 inLDAPConfigTableIndex,
LDAP **outLDAPHost )
{
sInt32 siResult = eDSNoErr;
sLDAPNodeStruct *pLDAPAuthNodeStruct = nil;
int ldapPort = LDAP_PORT;
char *aLDAPName = nil;
if (inHost != nil)
{
pLDAPAuthNodeStruct = (sLDAPNodeStruct *) calloc(1, sizeof(sLDAPNodeStruct));
siResult = ParseLDAPNodeName( inNodeName, &aLDAPName, &ldapPort );
if (siResult == eDSNoErr)
{
pLDAPAuthNodeStruct->fServerName = aLDAPName;
pLDAPAuthNodeStruct->fDirectLDAPPort = ldapPort;
pLDAPAuthNodeStruct->fHost = nil;
pLDAPAuthNodeStruct->fLDAPConfigTableIndex = inLDAPConfigTableIndex;
pLDAPAuthNodeStruct->fUserName = inUserName;
pLDAPAuthNodeStruct->fAuthCredential = inAuthCredential;
ldap_unbind(inHost);
siResult = BindProc( pLDAPAuthNodeStruct );
if (siResult == eDSNoErr)
{
*outLDAPHost = pLDAPAuthNodeStruct->fHost;
}
}
if (pLDAPAuthNodeStruct != nil)
{
if (pLDAPAuthNodeStruct->fServerName != nil)
{
free(pLDAPAuthNodeStruct->fServerName); }
free(pLDAPAuthNodeStruct);
pLDAPAuthNodeStruct = nil;
}
}
else
{
siResult = eDSOpenNodeFailed;
}
return(siResult);
}
sInt32 CLDAPNode::SafeClose ( char *inNodeName,
LDAP *inHost )
{
sInt32 siResult = eDSNoErr;
sLDAPNodeStruct *pLDAPNodeStruct = nil;
LDAPNodeMapI aLDAPNodeMapI;
string aNodeName(inNodeName);
fLDAPNodeOpenMutex.Wait();
if (inHost != nil)
{
ldap_unbind( inHost );
}
else
{
aLDAPNodeMapI = fLDAPNodeMap.find(aNodeName);
if (aLDAPNodeMapI != fLDAPNodeMap.end())
{
pLDAPNodeStruct = aLDAPNodeMapI->second;
pLDAPNodeStruct->fRefCount--;
if (pLDAPNodeStruct->fRefCount == 0)
{
CleanLDAPNodeStruct(pLDAPNodeStruct);
fLDAPNodeMap.erase(aNodeName);
free(pLDAPNodeStruct);
}
}
}
fLDAPNodeOpenMutex.Signal();
return(siResult);
}
void CLDAPNode::GetSchema ( sLDAPContextData *inContext )
{
sInt32 siResult = eDSNoErr;
sLDAPConfigData *pConfig = nil;
LDAPMessage *LDAPResult = nil;
BerElement *ber;
struct berval **bValues;
char *pAttr = nil;
sObjectClassSchema *aOCSchema = nil;
bool bSkipToTag = true;
char *lineEntry = nil;
char *strtokContext = nil;
LDAP *aHost = nil;
if ( inContext != nil )
{
pConfig = (sLDAPConfigData *)gConfigTable->GetItemData( inContext->fConfigTableIndex );
if (pConfig != nil)
{
aHost = LockSession(inContext);
if ( (aHost != nil) && !(pConfig->bOCBuilt) ) {
siResult = GetSchemaMessage( aHost, pConfig->fSearchTimeout, &LDAPResult);
if (siResult == eDSNoErr)
{
for ( pAttr = ldap_first_attribute (aHost, LDAPResult, &ber );
pAttr != NULL; pAttr = ldap_next_attribute(aHost, LDAPResult, ber ) )
{
if (( bValues = ldap_get_values_len (aHost, LDAPResult, pAttr )) != NULL)
{
ObjectClassMap *aOCClassMap = new(ObjectClassMap);
for (int i = 0; bValues[i] != NULL; i++ )
{
aOCSchema = nil;
if (lineEntry != nil) {
free(lineEntry);
lineEntry = nil;
}
lineEntry = (char *)calloc(1,bValues[i]->bv_len+1);
strcpy(lineEntry, bValues[i]->bv_val);
char *aToken = nil;
aToken = strtok_r(lineEntry,OCSEPCHARS, &strtokContext);
while ( (aToken != nil) && (strcmp(aToken,"NAME") != 0) )
{
aToken = strtok_r(NULL,OCSEPCHARS, &strtokContext);
}
if (aToken != nil)
{
aToken = strtok_r(NULL,OCSEPCHARS, &strtokContext);
if (aToken != nil)
{
if (aOCClassMap->find(aToken) == aOCClassMap->end())
{
aOCSchema = new(sObjectClassSchema);
(*aOCClassMap)[aToken] = aOCSchema;
}
}
}
if (aOCSchema == nil)
{
continue;
}
if (aToken == nil)
{
continue;
}
bSkipToTag = true;
while (bSkipToTag)
{
aToken = strtok_r(NULL,OCSEPCHARS, &strtokContext);
if (aToken == nil)
{
break;
}
bSkipToTag = IsTokenNotATag(aToken);
if (bSkipToTag)
{
aOCSchema->fOtherNames.insert(aOCSchema->fOtherNames.begin(),aToken);
}
}
if (aToken == nil)
{
continue;
}
if (strcmp(aToken,"DESC") == 0)
{
bSkipToTag = true;
while (bSkipToTag)
{
aToken = strtok_r(NULL,OCSEPCHARS, &strtokContext);
if (aToken == nil)
{
break;
}
bSkipToTag = IsTokenNotATag(aToken);
}
if (aToken == nil)
{
continue;
}
}
if (strcmp(aToken,"OBSOLETE") == 0)
{
bSkipToTag = true;
while (bSkipToTag)
{
aToken = strtok_r(NULL,OCSEPCHARS, &strtokContext);
if (aToken == nil)
{
break;
}
bSkipToTag = IsTokenNotATag(aToken);
}
if (aToken == nil)
{
continue;
}
}
if (strcmp(aToken,"SUP") == 0)
{
aToken = strtok_r(NULL,OCSEPCHARS, &strtokContext);
if (aToken == nil)
{
continue;
}
aOCSchema->fParentOCs.insert(aOCSchema->fParentOCs.begin(),aToken);
bSkipToTag = true;
while (bSkipToTag)
{
aToken = strtok_r(NULL,OCSEPCHARS, &strtokContext);
if (aToken == nil)
{
break;
}
bSkipToTag = IsTokenNotATag(aToken);
if (bSkipToTag)
{
aOCSchema->fParentOCs.insert(aOCSchema->fParentOCs.begin(),aToken);
}
}
if (aToken == nil)
{
continue;
}
}
if (strcmp(aToken,"ABSTRACT") == 0)
{
aOCSchema->fType = 0;
aToken = strtok_r(NULL,OCSEPCHARS, &strtokContext);
if (aToken == nil)
{
continue;
}
}
if (strcmp(aToken,"STRUCTURAL") == 0)
{
aOCSchema->fType = 1;
aToken = strtok_r(NULL,OCSEPCHARS, &strtokContext);
if (aToken == nil)
{
continue;
}
}
if (strcmp(aToken,"AUXILIARY") == 0)
{
aOCSchema->fType = 2;
aToken = strtok_r(NULL,OCSEPCHARS, &strtokContext);
if (aToken == nil)
{
continue;
}
}
if (strcmp(aToken,"MUST") == 0)
{
aToken = strtok_r(NULL,OCSEPCHARS, &strtokContext);
if (aToken == nil)
{
continue;
}
aOCSchema->fRequiredAttrs.insert(aOCSchema->fRequiredAttrs.begin(),aToken);
bSkipToTag = true;
while (bSkipToTag)
{
aToken = strtok_r(NULL,OCSEPCHARS, &strtokContext);
if (aToken == nil)
{
break;
}
bSkipToTag = IsTokenNotATag(aToken);
if (bSkipToTag)
{
aOCSchema->fRequiredAttrs.insert(aOCSchema->fRequiredAttrs.begin(),aToken);
}
}
if (aToken == nil)
{
continue;
}
}
if (strcmp(aToken,"MAY") == 0)
{
aToken = strtok_r(NULL,OCSEPCHARS, &strtokContext);
if (aToken == nil)
{
continue;
}
aOCSchema->fAllowedAttrs.insert(aOCSchema->fAllowedAttrs.begin(),aToken);
bSkipToTag = true;
while (bSkipToTag)
{
aToken = strtok_r(NULL,OCSEPCHARS, &strtokContext);
if (aToken == nil)
{
break;
}
bSkipToTag = IsTokenNotATag(aToken);
if (bSkipToTag)
{
aOCSchema->fAllowedAttrs.insert(aOCSchema->fAllowedAttrs.begin(),aToken);
}
}
if (aToken == nil)
{
continue;
}
}
}
if (lineEntry != nil) {
free(lineEntry);
lineEntry = nil;
}
ldap_value_free_len(bValues);
pConfig->fObjectClassSchema = aOCClassMap;
}
if (pAttr != nil)
{
ldap_memfree( pAttr );
}
}
if (ber != nil)
{
ber_free( ber, 0 );
}
ldap_msgfree( LDAPResult );
}
}
pConfig->bOCBuilt = true;
UnLockSession(inContext);
}
}
}
sInt32 CLDAPNode::ParseLDAPNodeName( char *inNodeName,
char **outLDAPName,
int *outLDAPPort )
{
sInt32 siResult = eDSNoErr;
char *portPos = nil;
uInt32 inLength = 0;
int ldapPort = LDAP_PORT;
char *ldapName = nil;
if (inNodeName != nil)
{
inLength = strlen(inNodeName);
portPos = strchr(inNodeName, ':');
if (portPos != nil)
{
portPos++;
if (portPos != nil)
{
ldapPort = strtoul(portPos,NULL,NULL);
if (ldapPort == 0)
{
ldapPort = LDAP_PORT;
}
inLength = inLength - strlen(portPos);
}
ldapName = (char *) calloc(1, inLength);
strncpy(ldapName, inNodeName, inLength-1);
}
else
{
ldapName = (char *) calloc(1, inLength+1);
strncpy(ldapName, inNodeName, inLength);
}
*outLDAPName = ldapName;
*outLDAPPort = ldapPort;
}
else
{
siResult = eDSNullParameter;
}
return(siResult);
}
sInt32 CLDAPNode::CleanLDAPNodeStruct ( sLDAPNodeStruct *inLDAPNodeStruct )
{
sInt32 siResult = eDSNoErr;
if (inLDAPNodeStruct != nil)
{
if (inLDAPNodeStruct->fLDAPSessionMutex != nil)
{
inLDAPNodeStruct->fLDAPSessionMutex->Wait();
}
if (inLDAPNodeStruct->fHost != nil)
{
ldap_unbind( inLDAPNodeStruct->fHost );
inLDAPNodeStruct->fHost = nil;
}
if (inLDAPNodeStruct->fLDAPSessionMutex != nil)
{
inLDAPNodeStruct->fLDAPSessionMutex->Signal();
delete(inLDAPNodeStruct->fLDAPSessionMutex);
inLDAPNodeStruct->fLDAPSessionMutex = nil;
}
if (inLDAPNodeStruct->fServerName != nil)
{
free( inLDAPNodeStruct->fServerName );
inLDAPNodeStruct->fServerName = nil;
}
if (inLDAPNodeStruct->fUserName != nil)
{
free( inLDAPNodeStruct->fUserName );
inLDAPNodeStruct->fUserName = nil;
}
if (inLDAPNodeStruct->fAuthCredential != nil)
{
free( inLDAPNodeStruct->fAuthCredential );
inLDAPNodeStruct->fAuthCredential = nil;
}
if (inLDAPNodeStruct->fAuthType != nil)
{
free( inLDAPNodeStruct->fAuthType );
inLDAPNodeStruct->fAuthType = nil;
}
inLDAPNodeStruct->fRefCount = 0;
inLDAPNodeStruct->fLDAPConfigTableIndex = 0;
inLDAPNodeStruct->fDirectLDAPPort = 389;
inLDAPNodeStruct->bHasFailed = false;
inLDAPNodeStruct->fDelayedBindTime = time( nil ) + 120;
inLDAPNodeStruct->fConnectionActiveCount = 0;
inLDAPNodeStruct->fIdleTOCount = 0;
inLDAPNodeStruct->fIdleTO = 4; inLDAPNodeStruct->fDelayRebindTry = 120;
}
return(siResult);
}
sInt32 CLDAPNode::BindProc ( sLDAPNodeStruct *inLDAPNodeStruct )
{
sInt32 siResult = eDSNoErr;
int bindMsgId = 0;
int version = -1;
sLDAPConfigData *pConfig = nil;
char *ldapAcct = nil;
char *ldapPasswd = nil;
int openTO = 0;
LDAP *inLDAPHost = inLDAPNodeStruct->fHost;
LDAPMessage *result = nil;
int ldapReturnCode = 0;
try
{
if ( inLDAPNodeStruct == nil ) throw( (sInt32)eDSNullParameter );
if (inLDAPNodeStruct->fLDAPSessionMutex != nil)
{
inLDAPNodeStruct->fLDAPSessionMutex->Wait();
}
if (inLDAPHost == NULL)
{
if (( inLDAPNodeStruct->fLDAPConfigTableIndex < gConfigTableLen) && ( inLDAPNodeStruct->fLDAPConfigTableIndex >= 1 ))
{
pConfig = (sLDAPConfigData *)gConfigTable->GetItemData( inLDAPNodeStruct->fLDAPConfigTableIndex );
if (pConfig != nil)
{
if ( (pConfig->bSecureUse) && (inLDAPNodeStruct->fUserName == nil) )
{
if (pConfig->fServerAccount != nil)
{
ldapAcct = new char[1+::strlen(pConfig->fServerAccount)];
::strcpy( ldapAcct, pConfig->fServerAccount );
}
if (pConfig->fServerPassword != nil)
{
ldapPasswd = new char[1+::strlen(pConfig->fServerPassword)];
::strcpy( ldapPasswd, pConfig->fServerPassword );
}
}
else
{
if (inLDAPNodeStruct->fUserName != nil)
{
ldapAcct = new char[1+::strlen(inLDAPNodeStruct->fUserName)];
::strcpy( ldapAcct, inLDAPNodeStruct->fUserName );
}
if (inLDAPNodeStruct->fAuthCredential != nil)
{
if (inLDAPNodeStruct->fAuthType != nil)
{
if (strcmp(inLDAPNodeStruct->fAuthType,kDSStdAuthClearText) == 0)
{
ldapPasswd = new char[1+::strlen((char*)(inLDAPNodeStruct->fAuthCredential))];
::strcpy( ldapPasswd, (char*)(inLDAPNodeStruct->fAuthCredential) );
}
}
else {
ldapPasswd = new char[1+::strlen((char*)(inLDAPNodeStruct->fAuthCredential))];
::strcpy( ldapPasswd, (char*)(inLDAPNodeStruct->fAuthCredential) );
}
}
}
openTO = pConfig->fOpenCloseTimeout;
}
}
if (inLDAPNodeStruct->fLDAPConfigTableIndex != 0)
{
if (pConfig != nil)
{
inLDAPHost = ldap_init( pConfig->fServerName, pConfig->fServerPort );
}
}
else
{
inLDAPHost = ldap_init( inLDAPNodeStruct->fServerName, inLDAPNodeStruct->fDirectLDAPPort );
}
if ( inLDAPHost == nil ) throw( (sInt32)eDSCannotAccessSession );
if (pConfig != nil)
{
if ( pConfig->bIsSSL )
{
int ldapOptVal = LDAP_OPT_X_TLS_HARD;
ldap_set_option(inLDAPHost, LDAP_OPT_X_TLS, &ldapOptVal);
}
}
version = LDAP_VERSION3;
ldap_set_option( inLDAPHost, LDAP_OPT_PROTOCOL_VERSION, &version );
if ( inLDAPNodeStruct->bHasFailed )
{
if ( time( nil ) < inLDAPNodeStruct->fDelayedBindTime )
{
throw( (sInt32)eDSCannotAccessSession );
}
else
{
inLDAPNodeStruct->bHasFailed = false;
}
}
bindMsgId = ldap_bind( inLDAPHost, ldapAcct, ldapPasswd, LDAP_AUTH_SIMPLE );
if (openTO == 0)
{
ldapReturnCode = ldap_result(inLDAPHost, bindMsgId, 0, NULL, &result);
}
else
{
struct timeval tv;
tv.tv_sec = openTO;
tv.tv_usec = 0;
ldapReturnCode = ldap_result(inLDAPHost, bindMsgId, 0, &tv, &result);
}
if ( ldapReturnCode == -1 )
{
throw( (sInt32)eDSCannotAccessSession );
}
else if ( ldapReturnCode == 0 )
{
ldap_abandon(inLDAPHost, bindMsgId);
if (pConfig != nil)
{
syslog(LOG_INFO,"DSLDAPv3PlugIn: Timed out in attempt to bind to [%s] LDAP server.", pConfig->fServerName);
syslog(LOG_INFO,"DSLDAPv3PlugIn: Disabled future attempts to bind to [%s] LDAP server for next %d seconds.", pConfig->fServerName, inLDAPNodeStruct->fDelayRebindTry);
}
else
{
syslog(LOG_INFO,"DSLDAPv3PlugIn: Timed out in attempt to bind to [%s] LDAP server.", inLDAPNodeStruct->fServerName);
syslog(LOG_INFO,"DSLDAPv3PlugIn: Disabled future attempts to bind to [%s] LDAP server for next %d seconds.", inLDAPNodeStruct->fServerName, inLDAPNodeStruct->fDelayRebindTry);
}
inLDAPNodeStruct->bHasFailed = true;
inLDAPNodeStruct->fDelayedBindTime = time( nil ) + inLDAPNodeStruct->fDelayRebindTry;
throw( (sInt32)eDSCannotAccessSession );
}
else if ( ldap_result2error(inLDAPHost, result, 1) != LDAP_SUCCESS )
{
inLDAPNodeStruct->fHost = inLDAPHost;
throw( (sInt32)eDSCannotAccessSession );
}
inLDAPNodeStruct->fHost = inLDAPHost;
result = nil;
}
}
catch ( sInt32 err )
{
siResult = err;
}
if (ldapAcct != nil)
{
delete (ldapAcct);
ldapAcct = nil;
}
if (ldapPasswd != nil)
{
delete (ldapPasswd);
ldapPasswd = nil;
}
if (inLDAPNodeStruct->fLDAPSessionMutex != nil)
{
inLDAPNodeStruct->fLDAPSessionMutex->Signal();
}
return (siResult);
}
sInt32 CLDAPNode::GetSchemaMessage ( LDAP *inHost, int inSearchTO, LDAPMessage **outResultMsg )
{
sInt32 siResult = eDSNoErr;
bool bResultFound = false;
int ldapMsgId = 0;
LDAPMessage *result = nil;
int ldapReturnCode = 0;
char *sattrs[2] = {"subschemasubentry",NULL};
char *attrs[2] = {"objectclasses",NULL};
char *subschemaDN = nil;
BerElement *ber;
struct berval **bValues;
char *pAttr = nil;
try
{
if ( (ldapMsgId = ldap_search( inHost, "", LDAP_SCOPE_BASE, "(objectclass=*)", sattrs, 0) ) == -1 )
{
bResultFound = false;
}
else
{
bResultFound = true;
if (inSearchTO == 0)
{
ldapReturnCode = ldap_result(inHost, ldapMsgId, 0, NULL, &result);
}
else
{
struct timeval tv;
tv.tv_sec = inSearchTO;
tv.tv_usec = 0;
ldapReturnCode = ldap_result(inHost, ldapMsgId, 0, &tv, &result);
}
}
if ( (bResultFound) &&
( ldapReturnCode == LDAP_RES_SEARCH_ENTRY ) )
{
siResult = eDSNoErr;
for ( pAttr = ldap_first_attribute (inHost, result, &ber );
pAttr != NULL; pAttr = ldap_next_attribute(inHost, result, ber ) )
{
if (( bValues = ldap_get_values_len (inHost, result, pAttr )) != NULL)
{
if ( bValues[0] != NULL )
{
subschemaDN = (char *) calloc(1, bValues[0]->bv_len + 1);
strcpy(subschemaDN,bValues[0]->bv_val);
}
ldap_value_free_len(bValues);
}
if (pAttr != nil)
{
ldap_memfree( pAttr );
}
}
if (ber != nil)
{
ber_free( ber, 0 );
}
ldap_msgfree( result );
result = nil;
} else if (ldapReturnCode == LDAP_TIMEOUT)
{
siResult = eDSServerTimeout;
if ( result != nil )
{
ldap_msgfree( result );
result = nil;
}
}
else
{
siResult = eDSRecordNotFound;
if ( result != nil )
{
ldap_msgfree( result );
result = nil;
}
}
if (subschemaDN != nil)
{
if ( (ldapMsgId = ldap_search( inHost, subschemaDN, LDAP_SCOPE_BASE, "(objectclass=subSchema)", attrs, 0) ) == -1 )
{
bResultFound = false;
}
else
{
bResultFound = true;
if (inSearchTO == 0)
{
ldapReturnCode = ldap_result(inHost, ldapMsgId, 0, NULL, &result);
}
else
{
struct timeval tv;
tv.tv_sec = inSearchTO;
tv.tv_usec = 0;
ldapReturnCode = ldap_result(inHost, ldapMsgId, 0, &tv, &result);
}
}
free(subschemaDN);
subschemaDN = nil;
if ( (bResultFound) &&
( ldapReturnCode == LDAP_RES_SEARCH_ENTRY ) )
{
siResult = eDSNoErr;
} else if (ldapReturnCode == LDAP_TIMEOUT)
{
siResult = eDSServerTimeout;
if ( result != nil )
{
ldap_msgfree( result );
result = nil;
}
}
else
{
siResult = eDSRecordNotFound;
if ( result != nil )
{
ldap_msgfree( result );
result = nil;
}
}
}
}
catch ( sInt32 err )
{
siResult = err;
}
if (result != nil)
{
*outResultMsg = result;
}
return( siResult );
}
bool CLDAPNode::IsTokenNotATag ( char *inToken )
{
if (inToken == nil)
{
return true;
}
switch(*inToken)
{
case 'N':
case 'D':
case 'O':
case 'S':
case 'A':
case 'M':
case 'X':
if (strcmp(inToken,"DESC") == 0)
{
return false;
}
if (strcmp(inToken,"SUP") == 0)
{
return false;
}
if (strlen(inToken) > 7)
{
if (strcmp(inToken,"OBSOLETE") == 0)
{
return false;
}
if (strcmp(inToken,"ABSTRACT") == 0)
{
return false;
}
if (strcmp(inToken,"STRUCTURAL") == 0)
{
return false;
}
if (strcmp(inToken,"AUXILIARY") == 0)
{
return false;
}
if (strcmp(inToken,"X-ORIGIN") == 0) {
return false;
}
}
if (strcmp(inToken,"MUST") == 0)
{
return false;
}
if (strcmp(inToken,"MAY") == 0)
{
return false;
}
if (strcmp(inToken,"NAME") == 0)
{
return false;
}
break;
default:
break;
}
return( true );
}
LDAP* CLDAPNode::LockSession( sLDAPContextData *inContext )
{
sLDAPNodeStruct *pLDAPNodeStruct = nil;
LDAPNodeMapI aLDAPNodeMapI;
if (inContext != nil)
{
if (inContext->authCallActive)
{
if (inContext->fLDAPSessionMutex != nil)
{
inContext->fLDAPSessionMutex->Wait();
}
return inContext->fHost;
}
else
{
string aNodeName(inContext->fName);
fLDAPNodeOpenMutex.Wait();
aLDAPNodeMapI = fLDAPNodeMap.find(aNodeName);
if (aLDAPNodeMapI != fLDAPNodeMap.end())
{
pLDAPNodeStruct = aLDAPNodeMapI->second;
pLDAPNodeStruct->fRefCount++;
}
fLDAPNodeOpenMutex.Signal();
if (pLDAPNodeStruct != nil)
{
if (pLDAPNodeStruct->fLDAPSessionMutex != nil)
{
pLDAPNodeStruct->fLDAPSessionMutex->Wait();
}
return pLDAPNodeStruct->fHost;
}
}
}
return nil;
}
void CLDAPNode::UnLockSession( sLDAPContextData *inContext, bool inNewMutex )
{
sLDAPNodeStruct *pLDAPNodeStruct = nil;
LDAPNodeMapI aLDAPNodeMapI;
if (inContext != nil)
{
if ( (inContext->authCallActive) && !inNewMutex )
{
if (inContext->fLDAPSessionMutex != nil)
{
inContext->fLDAPSessionMutex->Signal();
}
}
else
{
string aNodeName(inContext->fName);
fLDAPNodeOpenMutex.Wait();
aLDAPNodeMapI = fLDAPNodeMap.find(aNodeName);
if (aLDAPNodeMapI != fLDAPNodeMap.end())
{
pLDAPNodeStruct = aLDAPNodeMapI->second;
}
if (pLDAPNodeStruct != nil)
{
if (pLDAPNodeStruct->fLDAPSessionMutex != nil)
{
pLDAPNodeStruct->fLDAPSessionMutex->Signal();
}
pLDAPNodeStruct->fRefCount--;
if (pLDAPNodeStruct->fRefCount == 0)
{
CleanLDAPNodeStruct(pLDAPNodeStruct);
fLDAPNodeMap.erase(aNodeName);
}
}
fLDAPNodeOpenMutex.Signal();
}
}
}
void CLDAPNode::CheckIdles( void )
{
sLDAPNodeStruct *pLDAPNodeStruct = nil;
LDAPNodeMapI aLDAPNodeMapI;
fLDAPNodeOpenMutex.Wait();
for (aLDAPNodeMapI = fLDAPNodeMap.begin(); aLDAPNodeMapI != fLDAPNodeMap.end(); ++aLDAPNodeMapI)
{
pLDAPNodeStruct = aLDAPNodeMapI->second;
if ( (pLDAPNodeStruct->fConnectionActiveCount == 0) && (pLDAPNodeStruct->fIdleTO != 0) ) {
if (pLDAPNodeStruct->fIdleTOCount >= pLDAPNodeStruct->fIdleTO) {
if (pLDAPNodeStruct->fLDAPSessionMutex != nil)
{
pLDAPNodeStruct->fLDAPSessionMutex->Wait();
}
if (pLDAPNodeStruct->fHost != nil)
{
ldap_unbind( pLDAPNodeStruct->fHost ); pLDAPNodeStruct->fHost = nil;
}
if (pLDAPNodeStruct->fLDAPSessionMutex != nil)
{
pLDAPNodeStruct->fLDAPSessionMutex->Signal();
}
pLDAPNodeStruct->fIdleTOCount = 0;
}
else
{
pLDAPNodeStruct->fIdleTOCount++;
}
}
}
fLDAPNodeOpenMutex.Signal();
}
void CLDAPNode::ActiveConnection( char *inNodeName )
{
sLDAPNodeStruct *pLDAPNodeStruct = nil;
LDAPNodeMapI aLDAPNodeMapI;
if (inNodeName != nil)
{
fLDAPNodeOpenMutex.Wait();
string aNodeName(inNodeName);
aLDAPNodeMapI = fLDAPNodeMap.find(aNodeName);
if (aLDAPNodeMapI != fLDAPNodeMap.end())
{
pLDAPNodeStruct = aLDAPNodeMapI->second;
pLDAPNodeStruct->fConnectionActiveCount++;
pLDAPNodeStruct->fIdleTOCount = 0;
}
fLDAPNodeOpenMutex.Signal();
}
}
void CLDAPNode::IdleConnection( char *inNodeName )
{
sLDAPNodeStruct *pLDAPNodeStruct = nil;
LDAPNodeMapI aLDAPNodeMapI;
if (inNodeName != nil)
{
fLDAPNodeOpenMutex.Wait();
string aNodeName(inNodeName);
aLDAPNodeMapI = fLDAPNodeMap.find(aNodeName);
if (aLDAPNodeMapI != fLDAPNodeMap.end())
{
pLDAPNodeStruct = aLDAPNodeMapI->second;
if (pLDAPNodeStruct->fConnectionActiveCount != 0)
{
pLDAPNodeStruct->fConnectionActiveCount--;
}
}
fLDAPNodeOpenMutex.Signal();
}
}