#pragma mark Includes
#include <string.h> //used for strcpy, etc.
#include <stdlib.h> //used for malloc
#include <ctype.h> //used for isprint
#include <syslog.h>
#include <arpa/inet.h>
#include <libkern/OSAtomic.h>
#include <CommonCrypto/CommonDigest.h>
#include <Security/Authorization.h>
#include <SystemConfiguration/SystemConfiguration.h> //required for the configd kicker operation
#include <SystemConfiguration/SCDynamicStoreCopyDHCPInfo.h>
#include <CoreFoundation/CFPriv.h>
#include <malloc/malloc.h>
#include <DirectoryService/DirServicesConstPriv.h>
#include <dispatch/dispatch.h>
#include "DirServices.h"
#include "DirServicesUtils.h"
#include "DirServicesUtilsPriv.h"
#include "DirServicesConst.h"
#include "DirServicesPriv.h"
extern "C" {
#include <sasl/saslutil.h>
};
#include "CLDAPv3Plugin.h"
#include <krb5.h>
using namespace std;
#include "ServerModuleLib.h"
#include "CRCCalc.h"
#include "CPlugInRef.h"
#include "CContinue.h"
#include "DSCThread.h"
#include "DSEventSemaphore.h"
#include "CSharedData.h"
#include "DSUtils.h"
#include "PrivateTypes.h"
#include "CLog.h"
#include "GetMACAddress.h"
#include "DSLDAPUtils.h"
#include "buffer_unpackers.h"
#include "CDSPluginUtils.h"
#include "LDAPv3SupportFunctions.h"
#include "CLDAPNodeConfig.h"
#include "CPlugInObjectRef.h"
#pragma mark -
#pragma mark Defines and Macros
#define LDAPURLOPT95SEPCHAR " "
#define LDAPCOMEXPSPECIALCHARS "()|&"
#define kLDAPRecordTypeUnknownStr "Record Type Unknown"
#define kLDAPRecordNameUnknownStr "Record Name Unknown"
#define kLDAPUnknownNodeLocationStr "Unknown Node Location"
#define kLDAPv3NodePrefix "/LDAPv3/"
#pragma mark -
#pragma mark Globals and Structures
extern bool gServerOS;
CContinue *gLDAPContinueTable = nil;
CPlugInObjectRef<sLDAPContextData *> *gLDAPContextTable = nil;
static DSEventSemaphore gNetworkTransition;
int gPWSReplicaListLoadedSeqNumber = 0;
int gConfigRecordChangeSeqNumber = 1;
char *gPWSReplicaListLastRSAStr = NULL;
tDataBufferPtr gPWSReplicaListXMLBuffer = NULL;
DSMutexSemaphore gPWSReplicaListXMLBufferMutex("::gPWSReplicaListXMLBufferMutex");
struct LDAPv3AuthAuthorityHandler
{
const char *fTag;
LDAPv3AuthAuthorityHandlerProc fHandler;
};
#define kLDAPv3AuthAuthorityHandlerProcs 3
static LDAPv3AuthAuthorityHandler sLDAPv3AuthAuthorityHandlerProcs[ kLDAPv3AuthAuthorityHandlerProcs ] =
{
{ kDSTagAuthAuthorityBasic, (LDAPv3AuthAuthorityHandlerProc)CLDAPv3Plugin::DoBasicAuth },
{ kDSTagAuthAuthorityPasswordServer, (LDAPv3AuthAuthorityHandlerProc)CLDAPv3Plugin::DoPasswordServerAuth },
{ kDSTagAuthAuthorityKerberosv5, (LDAPv3AuthAuthorityHandlerProc)CLDAPv3Plugin::DoKerberosAuth }
};
#pragma mark -
#pragma mark CLDAPv3Plugin Member Functions
CLDAPv3Plugin::CLDAPv3Plugin ( FourCharCode inSig, const char *inName )
: BaseDirectoryPlugin( inSig, inName )
{
if ( gLDAPContinueTable == NULL )
{
CContinue *pContinue = new CContinue( CLDAPv3Plugin::ContinueDeallocProc );
if ( OSAtomicCompareAndSwapPtrBarrier(NULL, pContinue, (void **) &gLDAPContinueTable) == true )
DbgLog( kLogPlugin, "CLDAPv3Plugin::CLDAPv3Plugin - created the Continue Data table" );
else
DSDelete( pContinue );
}
if ( gLDAPContextTable == NULL )
{
CPlugInObjectRef<sLDAPContextData *> *pRefTable = new CPlugInObjectRef<sLDAPContextData *>( gServerOS ? 1024 : 256 );
if ( OSAtomicCompareAndSwapPtrBarrier(NULL, pRefTable, (void **) &gLDAPContextTable) == true )
DbgLog( kLogPlugin, "CLDAPv3Plugin::CLDAPv3Plugin - created the Ref table" );
else
DSDelete( pRefTable );
}
gNetworkTransition.PostEvent();
fConfigFromXML = new CLDAPv3Configs( fPlugInSignature );
fLDAPConnectionMgr = new CLDAPConnectionManager( fConfigFromXML );
}
CLDAPv3Plugin::~CLDAPv3Plugin ( void )
{
DSDelete( fConfigFromXML );
DSDelete( fLDAPConnectionMgr );
}
SInt32 CLDAPv3Plugin::Validate ( const char *inVersionStr, const UInt32 inSignature )
{
fPlugInSignature = inSignature;
return( eDSNoErr );
}
SInt32 CLDAPv3Plugin::Initialize ( void )
{
tDataListPtr pldapName = dsBuildListFromStringsPriv( "LDAPv3", "DHCPChecked", NULL );
if (pldapName != NULL)
{
CServerPlugin::_RegisterNode( fPlugInSignature, pldapName, kDHCPLDAPv3NodeType );
dsDataListDeallocatePriv( pldapName );
DSFree( pldapName );
}
return BaseDirectoryPlugin::Initialize();
}
SInt32 CLDAPv3Plugin::SetPluginState ( const UInt32 inState )
{
static bool sbActive = false;
BaseDirectoryPlugin::SetPluginState( inState );
if ( (inState & kActive) != 0 && __sync_bool_compare_and_swap(&sbActive, false, true) == true )
{
dispatch_async( dispatch_get_concurrent_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT),
^(void) {
fConfigFromXML->RegisterAllNodes();
sbActive = false;
} );
}
else if ( inState & kInactive )
{
fConfigFromXML->UnregisterAllNodes();
}
return( eDSNoErr );
}
SInt32 CLDAPv3Plugin::ProcessRequest ( void *inData )
{
tDirStatus siResult = eDSNoErr;
char *pathStr = nil;
sHeader *pMsgHdr = (sHeader *) inData;
if ( inData == nil )
{
return( ePlugInDataError );
}
if (pMsgHdr->fType == kOpenDirNode)
{
if (((sOpenDirNode *)inData)->fInDirNodeName != nil)
{
pathStr = ::dsGetPathFromListPriv( ((sOpenDirNode *)inData)->fInDirNodeName, "/" );
if (pathStr != nil)
{
if (strncmp(pathStr,"/LDAPv3",7) != 0)
{
free(pathStr);
pathStr = nil;
return(eDSOpenNodeFailed);
}
free(pathStr);
pathStr = nil;
}
}
}
switch (pMsgHdr->fType)
{
case kKerberosMutex:
siResult = (tDirStatus) BaseDirectoryPlugin::ProcessRequest( inData );
break;
case kServerRunLoop:
siResult = (tDirStatus) BaseDirectoryPlugin::ProcessRequest( inData );
break;
default:
siResult = eDSNoErr;
break;
}
if (fState == kUnknownState)
{
return( ePlugInCallTimedOut );
}
if ( (fState & kFailedToInit) || !(fState & kInitialized) )
{
DbgLog( kLogPlugin, "CLDAPPlugin::ProcessRequest -14279 condition fState = %d", fState );
return( ePlugInFailedToInitialize );
}
if ( ((fState & kInactive) || !(fState & kActive))
&& (pMsgHdr->fType != kDoPlugInCustomCall)
&& (pMsgHdr->fType != kOpenDirNode) )
{
return( ePlugInNotActive );
}
fConfigFromXML->WaitForNodeRegistration();
siResult = (tDirStatus) HandleRequest( inData );
if ( siResult == eNotHandledByThisNode )
siResult = (tDirStatus) BaseDirectoryPlugin::ProcessRequest( inData );
return( siResult );
}
#pragma mark -
#pragma mark Support functions
SInt32 CLDAPv3Plugin::HandleRequest ( void *inData )
{
tDirStatus siResult = eDSNoErr;
sHeader *pMsgHdr = nil;
char *recTypeStr = NULL;
if ( inData == nil )
{
return( -8088 );
}
pMsgHdr = (sHeader *)inData;
switch ( pMsgHdr->fType )
{
case kSetRecordType:
siResult = eNotYetImplemented; break;
case kSetAttributeValues:
recTypeStr = GetRecordTypeFromRef( ((sAddAttribute *)inData)->fInRecRef );
siResult = SetAttributeValues( (sSetAttributeValues *)inData, recTypeStr );
break;
case kDoDirNodeAuthOnRecordType:
if ( ( ((sDoDirNodeAuthOnRecordType *)inData)->fInRecordType != NULL) &&
( ((sDoDirNodeAuthOnRecordType *)inData)->fInRecordType->fBufferData != NULL) )
{
siResult = (tDirStatus) DoAuthenticationOnRecordType( (sDoDirNodeAuthOnRecordType *)inData,
((sDoDirNodeAuthOnRecordType *)inData)->fInRecordType->fBufferData );
}
break;
case kDoAttributeValueSearch:
case kDoAttributeValueSearchWithData:
case kDoMultipleAttributeValueSearch:
case kDoMultipleAttributeValueSearchWithData:
siResult = DoAttributeValueSearchWithData( (sDoAttrValueSearchWithData *)inData );
break;
case kDoPlugInCustomCall:
siResult = DoPlugInCustomCall( (sDoPlugInCustomCall *)inData );
break;
case kHandleSystemWillSleep:
siResult = eDSNoErr;
fLDAPConnectionMgr->SystemGoingToSleep();
break;
case kHandleSystemWillPowerOn:
siResult = eDSNoErr;
fLDAPConnectionMgr->SystemWillPowerOn();
break;
default:
siResult = eNotHandledByThisNode;
break;
}
pMsgHdr->fResult = siResult;
DSFreeString( recTypeStr );
return( siResult );
}
tDirStatus CLDAPv3Plugin::OpenDirNode ( sOpenDirNode *inData )
{
char *pathStr = nil;
sLDAPContextData *pContext = nil;
tDirStatus siResult = eDSNoErr;
tDataListPtr pNodeList = nil;
pNodeList = inData->fInDirNodeName;
try
{
if ( inData != nil )
{
pathStr = dsGetPathFromListPriv( pNodeList, (char *)"/" );
if ( pathStr == nil ) throw( eDSNullNodeName );
if (strcmp(pathStr,"/LDAPv3") == 0)
{
pContext = new sLDAPContextData;
pContext->fUID = inData->fInUID;
pContext->fEffectiveUID = inData->fInEffectiveUID;
pContext->fLDAPConnection = new CLDAPConnection( NULL );
gLDAPContextTable->AddObjectForRefNum( inData->fOutNodeRef, pContext );
DSRelease( pContext );
}
else if ( strlen(pathStr) > (sizeof(kLDAPv3NodePrefix) - 1) &&
strncmp(pathStr, kLDAPv3NodePrefix, (sizeof(kLDAPv3NodePrefix) - 1)) == 0 )
{
char *ldapName = pathStr + 8;
if ( ldap_is_ldapi_url(ldapName) )
{
if ( inData->fInUID != 0 || inData->fInEffectiveUID != 0 )
throw( eDSOpenNodeFailed );
}
CLDAPConnection *pConnection = fLDAPConnectionMgr->GetConnection( ldapName );
if ( pConnection == NULL )
throw( eDSOpenNodeFailed );
pContext = new sLDAPContextData( pConnection );
pContext->fUID = inData->fInUID;
pContext->fEffectiveUID = inData->fInEffectiveUID;
pConnection->Release();
gLDAPContextTable->AddObjectForRefNum( inData->fOutNodeRef, pContext );
DSRelease( pContext );
} else
{
siResult = eDSOpenNodeFailed;
}
} else
{
siResult = eDSNullParameter;
}
} catch ( tDirStatus err )
{
siResult = err;
if (pContext != nil)
gLDAPContextTable->RemoveRefNum( inData->fOutNodeRef );
}
DSFree( pathStr );
return( siResult );
}
tDirStatus CLDAPv3Plugin::CloseDirNode ( sCloseDirNode *inData )
{
tDirStatus siResult = eDSNoErr;
sLDAPContextData *pContext = nil;
try
{
pContext = gLDAPContextTable->GetObjectForRefNum( inData->fInNodeRef );
if ( pContext == nil )
throw( eDSBadContextData );
gLDAPContinueTable->RemovePointersForRefNum( inData->fInNodeRef );
gLDAPContextTable->RemoveRefNum( inData->fInNodeRef );
DSRelease( pContext );
}
catch ( tDirStatus err )
{
siResult = err;
}
return( siResult );
}
tDirStatus CLDAPv3Plugin::GetRecordList ( sGetRecordList *inData )
{
tDirStatus siResult = eDSNoErr;
UInt32 uiTotal = 0;
UInt32 uiCount = 0;
char *pRecType = nil;
char *pLDAPSearchBase = nil;
bool bAttribOnly = false;
tDirPatternMatch pattMatch = eDSNoMatch1;
char **pRecNames = nil;
CAttributeList *cpRecTypeList = nil;
UInt32 cpRecTypeListCount = 0;
CAttributeList *cpAttrTypeList = nil;
sLDAPContextData *pContext = nil;
sLDAPContinueData *pLDAPContinue = nil;
CBuff *outBuff = nil;
bool bOCANDGroup = false;
CFArrayRef OCSearchList = nil;
ber_int_t scope = LDAP_SCOPE_SUBTREE;
tContextData uiContinue = 0;
if ( inData == nil ) return( eMemoryError );
if ( inData->fInDataBuff == NULL || inData->fInDataBuff->fBufferSize == 0 ) return( eDSEmptyBuffer );
if ( inData->fInRecNameList == nil ) return( eDSEmptyRecordNameList );
if ( inData->fInRecTypeList == nil ) return( eDSEmptyRecordTypeList );
if ( inData->fInAttribTypeList == nil ) return( eDSEmptyAttributeTypeList );
pContext = gLDAPContextTable->GetObjectForRefNum( inData->fInNodeRef );
if ( pContext == nil ) return eDSBadContextData;
if ( pContext->fLDAPConnection->ConnectionStatus() != kConnectionSafe ) return eDSCannotAccessSession;
try
{
if ( inData->fIOContinueData == 0 )
{
pLDAPContinue = new sLDAPContinueData;
uiContinue = gLDAPContinueTable->AddPointer( pLDAPContinue->Retain(), inData->fInNodeRef );
pLDAPContinue->fLDAPConnection = pContext->fLDAPConnection->Retain();
pLDAPContinue->fNodeRef = inData->fInNodeRef;
pLDAPContinue->fRecNameIndex = 1;
pLDAPContinue->fRecTypeIndex = 1;
pLDAPContinue->fTotalRecCount = 0;
pLDAPContinue->fLimitRecSearch = (inData->fOutRecEntryCount >= 0 ? inData->fOutRecEntryCount : 0);
}
else
{
pLDAPContinue = (sLDAPContinueData *) gLDAPContinueTable->GetPointer( inData->fIOContinueData );
if ( pLDAPContinue == NULL ) throw( eDSInvalidContinueData );
pLDAPContinue->Retain();
uiContinue = inData->fIOContinueData;
}
inData->fIOContinueData = 0;
inData->fOutRecEntryCount = 0;
outBuff = new CBuff();
if ( outBuff == nil ) throw( eMemoryError );
siResult = (tDirStatus) outBuff->Initialize( inData->fInDataBuff, true );
if ( siResult != eDSNoErr ) throw( siResult );
siResult = (tDirStatus) outBuff->GetBuffStatus();
if ( siResult != eDSNoErr ) throw( siResult );
siResult = (tDirStatus) outBuff->SetBuffType( 'StdA' );
if ( siResult != eDSNoErr ) throw( siResult );
pRecNames = dsAllocStringsFromList(0, inData->fInRecNameList);
if ( pRecNames == nil ) throw( eDSEmptyRecordNameList );
pattMatch = inData->fInPatternMatch;
cpRecTypeList = new CAttributeList( inData->fInRecTypeList );
if ( cpRecTypeList == nil ) throw( eDSEmptyRecordTypeList );
if ( (cpRecTypeListCount = cpRecTypeList->GetCount()) == 0 )
throw( eDSEmptyRecordTypeList );
cpAttrTypeList = new CAttributeList( inData->fInAttribTypeList );
if ( cpAttrTypeList == nil ) throw( eDSEmptyAttributeTypeList );
if (cpAttrTypeList->GetCount() == 0)
throw( eDSEmptyAttributeTypeList );
bAttribOnly = inData->fInAttribInfoOnly;
while ( siResult == eDSNoErr && cpRecTypeList->GetAttribute(pLDAPContinue->fRecTypeIndex, &pRecType) == eDSNoErr )
{
pLDAPSearchBase = MapRecToSearchBase( pContext, (const char *)pRecType, 1, &bOCANDGroup, &OCSearchList, &scope );
if ( pLDAPSearchBase == NULL )
{
pLDAPContinue->fRecTypeIndex++;
if ( pLDAPContinue->fRecTypeIndex > cpRecTypeListCount )
{
inData->fOutRecEntryCount = uiTotal;
outBuff->SetLengthToSize();
break;
}
continue;
}
if ( strcmp(pRecNames[0], kDSRecordsAll) == 0 ) {
siResult = GetAllRecords( pRecType, pLDAPSearchBase, cpAttrTypeList, pContext, pLDAPContinue, bAttribOnly, outBuff,
uiCount, bOCANDGroup, OCSearchList, scope );
}
else
{
siResult = GetTheseRecords( (char *)kDSNAttrRecordName, pRecNames, pRecType, pLDAPSearchBase, pattMatch, cpAttrTypeList,
pContext, pLDAPContinue, bAttribOnly, outBuff, uiCount, bOCANDGroup, OCSearchList, scope );
}
bOCANDGroup = false;
DSDelete( pLDAPSearchBase );
DSCFRelease( OCSearchList );
uiTotal += uiCount;
if ( siResult == eDSBufferTooSmall )
{
inData->fIOContinueData = uiContinue;
if ( uiTotal != 0 )
siResult = eDSNoErr;
inData->fOutRecEntryCount = uiTotal;
outBuff->SetLengthToSize();
break;
}
else if ( siResult == eDSNoErr )
{
pLDAPContinue->fRecTypeIndex++;
if ( pLDAPContinue->fRecTypeIndex > cpRecTypeListCount )
{
inData->fOutRecEntryCount = uiTotal;
outBuff->SetLengthToSize();
break;
}
}
}
if ( uiTotal == 0 )
outBuff->ClearBuff();
}
catch ( tDirStatus err )
{
siResult = err;
}
if ( inData->fIOContinueData == 0 && pLDAPContinue != NULL )
{
gLDAPContinueTable->RemoveContext( uiContinue );
}
DSRelease( pLDAPContinue );
DSDelete( pLDAPSearchBase );
DSDelete( cpRecTypeList );
DSDelete( cpAttrTypeList );
DSDelete( outBuff );
DSFreeStringList( pRecNames );
DSRelease( pContext );
return( (tDirStatus)siResult );
}
tDirStatus CLDAPv3Plugin::GetAllRecords (
char *inRecType,
char *inNativeRecType,
CAttributeList *inAttrTypeList,
sLDAPContextData *inContext,
sLDAPContinueData *inContinue,
bool inAttrOnly,
CBuff *inBuff,
UInt32 &outRecCount,
bool inbOCANDGroup,
CFArrayRef inOCSearchList,
ber_int_t inScope )
{
tDirStatus siResult = eDSNoErr;
SInt32 siValCnt = 0;
LDAPMessage *result = nil;
char *recName = nil;
CDataBuff *aRecData = nil;
CDataBuff *aAttrData = nil;
char *queryFilter = nil;
outRecCount = 0;
if ( inContext == NULL ) return( eDSInvalidContext );
if ( inContinue == NULL ) return( eDSInvalidContinueData );
if ( inContext->fLDAPConnection->ConnectionStatus() != kConnectionSafe ) return eDSCannotAccessSession;
if ( inContinue->fLDAPMsgId == 0 )
{
queryFilter = BuildLDAPQueryFilter( inContext,
nil,
nil,
eDSAnyMatch,
false,
inRecType,
inNativeRecType,
inbOCANDGroup,
inOCSearchList );
if ( queryFilter == NULL ) return eDSNoStdMappingAvailable;
}
char **attrs = MapAttrListToLDAPTypeArray( inRecType, inAttrTypeList, inContext );
try
{
aRecData = new CDataBuff();
if ( aRecData == nil ) throw( eMemoryError );
aAttrData = new CDataBuff();
if ( aAttrData == nil ) throw( eMemoryError );
do
{
siResult = DSInitiateOrContinueSearch( inContext, inContinue, inNativeRecType, attrs, inScope, queryFilter, &result );
if ( siResult == eDSNoErr && result != NULL )
{
aAttrData->Clear();
aRecData->Clear();
if ( inRecType != nil )
{
aRecData->AppendShort( strlen( inRecType ) );
aRecData->AppendString( inRecType );
} else
{
aRecData->AppendShort( sizeof(kLDAPRecordTypeUnknownStr) - 1 );
aRecData->AppendString( kLDAPRecordTypeUnknownStr );
}
recName = GetRecordName( inRecType, result, inContext, siResult );
if ( siResult != eDSNoErr ) break;
if ( recName != nil )
{
aRecData->AppendShort( strlen( recName ) );
aRecData->AppendString( recName );
DSFree( recName );
}
else
{
aRecData->AppendShort( sizeof(kLDAPRecordNameUnknownStr) - 1 );
aRecData->AppendString( kLDAPRecordNameUnknownStr );
}
aAttrData->Clear();
siResult = GetTheseAttributes( inRecType, inAttrTypeList, result, inAttrOnly, inContext, siValCnt, aAttrData );
if ( siResult != eDSNoErr ) break;
aRecData->AppendShort( siValCnt );
if ( siValCnt != 0 )
aRecData->AppendBlock( aAttrData->GetData(), aAttrData->GetLength() );
if ( inBuff->AddData( aRecData->GetData(), aRecData->GetLength()) == CBuff::kBuffFull )
{
siResult = eDSBufferTooSmall;
inContinue->fResult = result;
result = NULL;
break;
}
else
{
outRecCount++; inContinue->fTotalRecCount++;
ldap_msgfree( result );
result = NULL;
}
}
else if ( siResult == eDSRecordNotFound )
{
siResult = eDSNoErr;
break;
}
} while ( siResult == eDSNoErr &&
(inContinue->fLimitRecSearch == 0 || inContinue->fTotalRecCount < inContinue->fLimitRecSearch) );
} catch ( tDirStatus err )
{
siResult = err;
}
if ( result != NULL )
{
ldap_msgfree( result );
result = NULL;
}
DSFreeStringList( attrs );
DSFreeString( queryFilter );
DSDelete( aRecData );
DSDelete( aAttrData );
return siResult;
}
tDirStatus CLDAPv3Plugin::GetRecordEntry ( sGetRecordEntry *inData )
{
tDirStatus siResult = eDSNoErr;
UInt32 uiIndex = 0;
UInt32 uiCount = 0;
UInt32 uiOffset = 0;
UInt32 uberOffset = 0;
char *pData = nil;
tRecordEntryPtr pRecEntry = nil;
sLDAPContextData *pContext = nil;
CBuff inBuff;
UInt32 offset = 0;
UInt16 usTypeLen = 0;
char *pRecType = nil;
UInt16 usNameLen = 0;
char *pRecName = nil;
UInt16 usAttrCnt = 0;
UInt32 buffLen = 0;
if ( inData == nil ) return( eMemoryError );
if ( inData->fInOutDataBuff == nil || inData->fInOutDataBuff->fBufferSize == 0 )
return( eDSEmptyBuffer );
try
{
siResult = (tDirStatus) inBuff.Initialize( inData->fInOutDataBuff );
if ( siResult != eDSNoErr ) throw( siResult );
siResult = (tDirStatus) inBuff.GetDataBlockCount( &uiCount );
if ( siResult != eDSNoErr ) throw( siResult );
uiIndex = inData->fInRecEntryIndex;
if ( uiIndex == 0 ) throw( eDSInvalidIndex );
if ( uiIndex > uiCount ) throw( eDSIndexOutOfRange );
pData = inBuff.GetDataBlock( uiIndex, &uberOffset );
if ( pData == nil ) throw( eDSCorruptBuffer );
buffLen = inBuff.GetDataBlockLength( uiIndex );
pData += 4;
offset = 0;
if (offset + 2 > buffLen) throw( eDSInvalidBuffFormat );
memcpy( &usTypeLen, pData, 2 );
pData += 2;
offset += 2;
pRecType = pData;
pData += usTypeLen;
offset += usTypeLen;
if (offset + 2 > buffLen) throw( eDSInvalidBuffFormat );
memcpy( &usNameLen, pData, 2 );
pData += 2;
offset += 2;
pRecName = pData;
pData += usNameLen;
offset += usNameLen;
if (offset + 2 > buffLen) throw( eDSInvalidBuffFormat );
memcpy( &usAttrCnt, pData, 2 );
pRecEntry = (tRecordEntry *)calloc( 1, sizeof( tRecordEntry ) + usNameLen + usTypeLen + 4 + kBuffPad );
pRecEntry->fRecordNameAndType.fBufferSize = usNameLen + usTypeLen + 4 + kBuffPad;
pRecEntry->fRecordNameAndType.fBufferLength = usNameLen + usTypeLen + 4;
memcpy( pRecEntry->fRecordNameAndType.fBufferData, &usNameLen, 2 );
uiOffset += 2;
memcpy( pRecEntry->fRecordNameAndType.fBufferData + uiOffset, pRecName, usNameLen );
uiOffset += usNameLen;
memcpy( pRecEntry->fRecordNameAndType.fBufferData + uiOffset, &usTypeLen, 2 );
uiOffset += 2;
memcpy( pRecEntry->fRecordNameAndType.fBufferData + uiOffset, pRecType, usTypeLen );
pRecEntry->fRecordAttributeCount = usAttrCnt;
pContext = new sLDAPContextData;
if ( pContext == nil ) throw( eMemoryAllocError );
pContext->offset = uberOffset + offset + 4;
gLDAPContextTable->AddObjectForRefNum( inData->fOutAttrListRef, pContext );
inData->fOutRecEntryPtr = pRecEntry;
DSRelease( pContext );
}
catch ( tDirStatus err )
{
siResult = err;
}
return( (tDirStatus)siResult );
}
tDirStatus CLDAPv3Plugin::GetTheseAttributes ( char *inRecType,
CAttributeList *inAttrTypeList,
LDAPMessage *inResult,
bool inAttrOnly,
sLDAPContextData *inContext,
SInt32 &outCount,
CDataBuff *inDataBuff )
{
tDirStatus siResult = eDSNoErr;
SInt32 attrTypeIndex = 1;
char *pLDAPAttrType = nil;
char *pAttrType = nil;
char *pAttr = nil;
BerElement *ber = nil;
struct berval **bValues;
int numAttributes = 1;
int numStdAttributes = 1;
bool bTypeFound = false;
int valCount = 0;
char *pStdAttrType = nil;
bool bAtLeastOneTypeValid = false;
CDataBuff *aTmpData = nil;
CDataBuff *aTmp2Data = nil;
bool bStripCryptPrefix = false;
bool bUsePlus = true;
char *pLDAPPasswdAttrType = nil;
char *pLDAPIPv6AddressAttrType = nil;
char *pLDAPIPAddressAttrType = nil;
UInt32 literalLength = 0;
LDAP *aHost = nil;
if ( inContext == nil )
return( eDSBadContextData );
try
{
outCount = 0;
aTmpData = new CDataBuff();
if ( aTmpData == nil ) throw( eMemoryError );
aTmp2Data = new CDataBuff();
if ( aTmp2Data == nil ) throw( eMemoryError );
inDataBuff->Clear();
pLDAPPasswdAttrType = MapAttrToLDAPType( inContext, (const char *)inRecType, kDS1AttrPassword, 1, true );
pLDAPIPv6AddressAttrType = MapAttrToLDAPType( inContext, (const char *)inRecType, kDSNAttrIPv6Address, 1, true );
pLDAPIPAddressAttrType = MapAttrToLDAPType( inContext, (const char *)inRecType, kDSNAttrIPAddress, 1, true );
while ( inAttrTypeList->GetAttribute( attrTypeIndex++, &pAttrType ) == eDSNoErr && pAttrType != NULL )
{
siResult = eDSNoErr;
if ( strcmp( kDSNAttrMetaNodeLocation, pAttrType ) == 0 )
{
aTmpData->Clear();
aTmpData->AppendShort( strlen( pAttrType ) );
aTmpData->AppendString( pAttrType );
if ( inAttrOnly == false )
{
aTmpData->AppendShort( 1 );
char *tmpStr = nil;
CLDAPNodeConfig *nodeConfig = inContext->fLDAPConnection->fNodeConfig;
if ( nodeConfig != NULL && nodeConfig->fNodeName != nil )
{
tmpStr = (char *) calloc(1, sizeof(kLDAPv3NodePrefix) + strlen(nodeConfig->fNodeName));
strcpy( tmpStr, kLDAPv3NodePrefix );
strcat( tmpStr, nodeConfig->fNodeName );
}
else
{
tmpStr = strdup( kLDAPUnknownNodeLocationStr );
}
aTmpData->AppendLong( strlen( tmpStr ) );
aTmpData->AppendString( tmpStr );
delete( tmpStr );
} else
{
aTmpData->AppendShort( 0 );
}
outCount++;
inDataBuff->AppendLong( aTmpData->GetLength() );
inDataBuff->AppendBlock( aTmpData->GetData(), aTmpData->GetLength() );
aTmpData->Clear();
} else if ( strcmp( kDSNAttrRecordType, pAttrType ) == 0 )
{
aTmpData->Clear();
aTmpData->AppendShort( strlen( pAttrType ) );
aTmpData->AppendString( pAttrType );
if ( inAttrOnly == false )
{
aTmpData->AppendShort( 1 );
aTmpData->AppendLong( strlen( inRecType ) );
aTmpData->AppendString( inRecType );
} else
{
aTmpData->AppendShort( 0 );
}
outCount++;
inDataBuff->AppendLong( aTmpData->GetLength() );
inDataBuff->AppendBlock( aTmpData->GetData(), aTmpData->GetLength() );
aTmpData->Clear();
} else if ((strcmp(pAttrType,kDSAttributesAll) == 0) || (strcmp(pAttrType,kDSAttributesStandardAll) == 0) || (strcmp(pAttrType,kDSAttributesNativeAll) == 0))
{
if ((strcmp(pAttrType,kDSAttributesAll) == 0) || (strcmp(pAttrType,kDSAttributesStandardAll) == 0))
{
aTmpData->Clear();
aTmpData->AppendShort( sizeof( kDSNAttrMetaNodeLocation ) - 1 );
aTmpData->AppendString( kDSNAttrMetaNodeLocation );
if ( inAttrOnly == false )
{
aTmpData->AppendShort( 1 );
char *tmpStr = nil;
CLDAPNodeConfig *nodeConfig = inContext->fLDAPConnection->fNodeConfig;
if ( nodeConfig != NULL && nodeConfig->fNodeName != nil )
{
tmpStr = (char *) calloc(1, sizeof(kLDAPv3NodePrefix) + strlen(nodeConfig->fNodeName));
strcpy( tmpStr, kLDAPv3NodePrefix );
strcat( tmpStr, nodeConfig->fNodeName );
}
else
{
tmpStr = (char *) calloc(1, sizeof(kLDAPUnknownNodeLocationStr));
strcpy( tmpStr, kLDAPUnknownNodeLocationStr );
}
aTmpData->AppendLong( strlen( tmpStr ) );
aTmpData->AppendString( tmpStr );
delete( tmpStr );
}
else
{
aTmpData->AppendShort( 0 );
}
outCount++;
inDataBuff->AppendLong( aTmpData->GetLength() );
inDataBuff->AppendBlock( aTmpData->GetData(), aTmpData->GetLength() );
aTmpData->Clear();
aTmpData->AppendShort( sizeof(kDSNAttrRecordType) - 1 );
aTmpData->AppendString( kDSNAttrRecordType );
if ( inAttrOnly == false )
{
aTmpData->AppendShort( 1 );
aTmpData->AppendLong( strlen( inRecType ) );
aTmpData->AppendString( inRecType );
} else
{
aTmpData->AppendShort( 0 );
}
outCount++;
inDataBuff->AppendLong( aTmpData->GetLength() );
inDataBuff->AppendBlock( aTmpData->GetData(), aTmpData->GetLength() );
if (strcmp(inRecType, kDSStdRecordTypeAutomount) == 0)
{
aTmpData->Clear();
aTmpData->AppendShort( sizeof(kDS1AttrMetaAutomountMap) - 1 );
aTmpData->AppendString( kDS1AttrMetaAutomountMap );
if ( inAttrOnly == false )
{
char *mapName = CopyAutomountMapName( inContext, inResult );
if (mapName != NULL)
{
aTmpData->AppendShort( 1 );
aTmpData->AppendLong( strlen(mapName) );
aTmpData->AppendString( mapName );
free( mapName );
mapName = NULL;
}
else
{
aTmpData->AppendShort( 0 );
}
} else
{
aTmpData->AppendShort( 0 );
}
outCount++;
inDataBuff->AppendLong( aTmpData->GetLength() );
inDataBuff->AppendBlock( aTmpData->GetData(), aTmpData->GetLength() );
}
aTmpData->Clear();
numStdAttributes = 1;
pStdAttrType = GetNextStdAttrType( inRecType, inContext, numStdAttributes );
while ( pStdAttrType != nil )
{
numAttributes = 1;
pLDAPAttrType = MapAttrToLDAPType( inContext, (const char *)inRecType, pStdAttrType, numAttributes );
bAtLeastOneTypeValid = false;
bTypeFound = false;
while ( pLDAPAttrType != nil )
{
if (pLDAPAttrType[0] == '#') {
if (!bTypeFound)
{
aTmp2Data->Clear();
aTmp2Data->AppendShort( strlen( pStdAttrType ) );
aTmp2Data->AppendString( pStdAttrType );
bTypeFound = true;
valCount = 0;
aTmpData->Clear();
}
bAtLeastOneTypeValid = true;
char *vsReturnStr = nil;
vsReturnStr = MappingNativeVariableSubstitution( pLDAPAttrType, inContext, inResult, siResult );
if (vsReturnStr != nil)
{
literalLength = strlen(vsReturnStr) - 1;
}
else
{
if (siResult != eDSNoErr) throw (siResult);
literalLength = strlen(pLDAPAttrType) - 1;
}
if ( (inAttrOnly == false) && (literalLength > 0) )
{
valCount++;
if (vsReturnStr != nil)
{
aTmpData->AppendLong( literalLength );
aTmpData->AppendBlock( vsReturnStr + 1, literalLength );
}
else
{
aTmpData->AppendLong( literalLength );
aTmpData->AppendBlock( pLDAPAttrType + 1, literalLength );
}
} if (vsReturnStr != nil)
{
free( vsReturnStr );
vsReturnStr = nil;
}
}
else
{
aHost = inContext->fLDAPConnection->LockLDAPSession();
if (aHost != NULL)
{
if ( (bValues = ldap_get_values_len(aHost, inResult, pLDAPAttrType)) != NULL )
{
bStripCryptPrefix = false;
if (pLDAPPasswdAttrType != nil )
{
if ( strcmp( pStdAttrType, kDS1AttrPassword ) == 0 &&
strcasecmp( pLDAPAttrType, pLDAPPasswdAttrType ) == 0 )
{
bStripCryptPrefix = true;
bUsePlus = false;
}
}
else if (strcmp(inRecType, kDSStdRecordTypeUsers) != 0 &&
strcmp(inRecType, kDSStdRecordTypeComputers) != 0 &&
strcmp(inRecType, kDSStdRecordTypeGroups) != 0)
{
bUsePlus = false;
}
bAtLeastOneTypeValid = true;
if (!bTypeFound)
{
aTmp2Data->Clear();
aTmp2Data->AppendShort( strlen( pStdAttrType ) );
aTmp2Data->AppendString( pStdAttrType );
bTypeFound = true;
valCount = 0;
aTmpData->Clear();
}
if ( inAttrOnly == false )
{
if (bStripCryptPrefix)
{
bStripCryptPrefix = false;
for (int i = 0; bValues[i] != NULL; i++ )
{
if ( ( bValues[i]->bv_len > 7) &&
(strncasecmp(bValues[i]->bv_val,"{crypt}",7) == 0) )
{
aTmpData->AppendLong( bValues[i]->bv_len - 7 );
aTmpData->AppendBlock( (bValues[i]->bv_val) + 7, bValues[i]->bv_len - 7 );
}
else
{
aTmpData->AppendLong( bValues[i]->bv_len );
aTmpData->AppendBlock( bValues[i]->bv_val, bValues[i]->bv_len );
}
valCount++;
} }
else
{
bool bIPAttribute = false;
if ( strcmp(inRecType, kDSStdRecordTypeComputers) == 0 )
{
if ( pLDAPIPAddressAttrType != NULL && strcasecmp(pLDAPIPAddressAttrType, pLDAPAttrType) == 0 )
bIPAttribute = true;
if ( pLDAPIPv6AddressAttrType != NULL && strcasecmp(pLDAPIPAddressAttrType, pLDAPAttrType) == 0 )
bIPAttribute = true;
}
if ( bIPAttribute )
{
char buffer[16];
if ( strcmp(pStdAttrType, kDSNAttrIPv6Address) == 0 ) {
for (int i = 0; bValues[i] != NULL; i++ )
{
if ( inet_pton(AF_INET6, bValues[i]->bv_val, buffer) == 1 ) {
aTmpData->AppendLong( bValues[i]->bv_len );
aTmpData->AppendBlock( bValues[i]->bv_val, bValues[i]->bv_len );
valCount++;
DbgLog( kLogInfo, "CLDAPv3Plugin: GetTheseAttributes:: appending value %s to ipv6", bValues[i]->bv_val );
}
} }
else if ( strcmp(pStdAttrType, kDSNAttrIPAddress) == 0 ) {
for (int i = 0; bValues[i] != NULL; i++ )
{
if ( inet_pton(AF_INET, bValues[i]->bv_val, buffer) == 1 ) {
aTmpData->AppendLong( bValues[i]->bv_len );
aTmpData->AppendBlock( bValues[i]->bv_val, bValues[i]->bv_len );
valCount++;
DbgLog( kLogInfo, "CLDAPv3Plugin: GetTheseAttributes:: appending value %s to ipv4", bValues[i]->bv_val );
}
} }
}
else
{
for (int i = 0; bValues[i] != NULL; i++ )
{
aTmpData->AppendLong( bValues[i]->bv_len );
aTmpData->AppendBlock( bValues[i]->bv_val, bValues[i]->bv_len );
valCount++;
} }
}
}
ldap_value_free_len(bValues);
bValues = NULL;
}
inContext->fLDAPConnection->UnlockLDAPSession( aHost, false );
} }
DSFreeString( pLDAPAttrType );
numAttributes++;
pLDAPAttrType = MapAttrToLDAPType( inContext, (const char *)inRecType, pStdAttrType, numAttributes );
}
if (bAtLeastOneTypeValid)
{
aTmp2Data->AppendShort( valCount );
if (valCount > 0)
{
DbgLog( kLogInfo, "CLDAPv3Plugin: GetTheseAttributes:: adding %s - %d values, blocklen = %d", pStdAttrType, valCount, aTmpData->GetLength() );
aTmp2Data->AppendBlock( aTmpData->GetData(), aTmpData->GetLength() );
valCount = 0;
}
else
{
DbgLog( kLogInfo, "CLDAPv3Plugin: GetTheseAttributes:: adding %s - 0 values", pStdAttrType );
}
outCount++;
inDataBuff->AppendLong( aTmp2Data->GetLength() );
inDataBuff->AppendBlock( aTmp2Data->GetData(), aTmp2Data->GetLength() );
DbgLog( kLogInfo, "CLDAPv3Plugin: GetTheseAttributes:: appending attribute block %s - length = %d", pStdAttrType, aTmp2Data->GetLength() );
}
DSFree( pStdAttrType );
numStdAttributes++;
pStdAttrType = GetNextStdAttrType( inRecType, inContext, numStdAttributes );
}
if (bUsePlus)
{
aTmpData->Clear();
aTmpData->AppendShort( sizeof( kDS1AttrPasswordPlus )-1 );
aTmpData->AppendString( kDS1AttrPasswordPlus );
if ( inAttrOnly == false )
{
aTmpData->AppendShort( 1 );
aTmpData->AppendLong( sizeof(kDSValueNonCryptPasswordMarker)-1 );
aTmpData->AppendString( kDSValueNonCryptPasswordMarker );
}
else
{
aTmpData->AppendShort( 0 );
}
outCount++;
inDataBuff->AppendLong( aTmpData->GetLength() );
inDataBuff->AppendBlock( aTmpData->GetData(), aTmpData->GetLength() );
aTmpData->Clear();
}
} if ((strcmp(pAttrType,kDSAttributesAll) == 0) || (strcmp(pAttrType,kDSAttributesNativeAll) == 0))
{
aHost = inContext->fLDAPConnection->LockLDAPSession();
if (aHost != NULL)
{
for ( pAttr = ldap_first_attribute (aHost, inResult, &ber );
pAttr != NULL; pAttr = ldap_next_attribute(aHost, inResult, ber ) )
{
aTmpData->Clear();
aTmpData->AppendShort( (sizeof(kDSNativeAttrTypePrefix)-1) + strlen( pAttr ) );
aTmpData->AppendString( kDSNativeAttrTypePrefix );
aTmpData->AppendString( pAttr );
if (( inAttrOnly == false ) &&
(( bValues = ldap_get_values_len(aHost, inResult, pAttr )) != NULL) )
{
valCount = 0;
for (int ii = 0; bValues[ii] != NULL; ii++ )
valCount++;
aTmpData->AppendShort( valCount );
for (int i = 0; bValues[i] != NULL; i++ )
{
aTmpData->AppendLong( bValues[i]->bv_len );
aTmpData->AppendBlock( bValues[i]->bv_val, bValues[i]->bv_len );
} ldap_value_free_len(bValues);
bValues = NULL;
} else
{
aTmpData->AppendShort( 0 );
}
outCount++;
inDataBuff->AppendLong( aTmpData->GetLength() );
inDataBuff->AppendBlock( aTmpData->GetData(), aTmpData->GetLength() );
aTmpData->Clear();
ldap_memfree( pAttr );
pAttr = NULL;
}
if (ber != nil)
{
ber_free( ber, 0 );
ber = nil;
}
inContext->fLDAPConnection->UnlockLDAPSession( aHost, false );
} } }
else {
bStripCryptPrefix = false;
numAttributes = 1;
if (strcmp( kDS1AttrPasswordPlus, pAttrType ) == 0)
{
bStripCryptPrefix = true;
pLDAPAttrType = MapAttrToLDAPType( inContext, (const char *)inRecType, kDS1AttrPassword, numAttributes );
bAtLeastOneTypeValid = false;
bTypeFound = false;
if (pLDAPAttrType == nil)
{
bAtLeastOneTypeValid = true;
aTmp2Data->Clear();
aTmp2Data->AppendShort( strlen( pAttrType ) );
aTmp2Data->AppendString( pAttrType );
bTypeFound = true;
if (inAttrOnly == false)
{
valCount = 1;
aTmpData->Clear();
aTmpData->AppendLong( sizeof(kDSValueNonCryptPasswordMarker) - 1 );
aTmpData->AppendString( kDSValueNonCryptPasswordMarker );
}
}
}
else if (strcmp(inRecType, kDSStdRecordTypeAutomount) == 0 &&
strcmp(kDS1AttrMetaAutomountMap, pAttrType) == 0)
{
aTmpData->Clear();
aTmpData->AppendShort( sizeof(kDS1AttrMetaAutomountMap) - 1 );
aTmpData->AppendString( kDS1AttrMetaAutomountMap );
if ( inAttrOnly == false )
{
char *mapName = CopyAutomountMapName( inContext, inResult );
if (mapName != NULL)
{
aTmpData->AppendShort( 1 );
aTmpData->AppendLong( strlen(mapName) );
aTmpData->AppendString( mapName );
free( mapName );
mapName = NULL;
}
else
{
aTmpData->AppendShort( 0 );
}
} else
{
aTmpData->AppendShort( 0 );
}
outCount++;
inDataBuff->AppendLong( aTmpData->GetLength() );
inDataBuff->AppendBlock( aTmpData->GetData(), aTmpData->GetLength() );
}
else if (strcmp(inRecType, kDSStdRecordTypeComputers) == 0 &&
strcmp(kDSNAttrIPv6Address, pAttrType) == 0)
{
aTmpData->Clear();
aTmp2Data->Clear();
aTmp2Data->AppendShort( strlen( pAttrType ) );
aTmp2Data->AppendString( pAttrType );
valCount = 0;
if ( inAttrOnly == false )
{
char buffer[16];
char **vals;
aHost = inContext->fLDAPConnection->LockLDAPSession();
if (aHost != NULL)
{
pLDAPAttrType = MapAttrToLDAPType( inContext,kDSStdRecordTypeComputers, kDSNAttrIPv6Address, numAttributes );
if ( pLDAPAttrType != NULL )
{
if((vals = ldap_get_values(aHost, inResult,pLDAPAttrType)) != NULL)
{
for (int i = 0; vals[i] != NULL; i++ )
{
if(inet_pton(AF_INET6, vals[i], buffer) == 1 ) {
aTmpData->AppendLong( strlen(vals[i]) );
aTmpData->AppendString( vals[i] );
DbgLog( kLogInfo, "CLDAPv3Plugin: GetTheseAttributes:: appending value %s to ipv6", vals[i] );
valCount++;
}
} }
if (vals != NULL)
{
ldap_value_free(vals);
vals = NULL;
}
DSFree( pLDAPAttrType );
}
inContext->fLDAPConnection->UnlockLDAPSession( aHost, false );
}
}
}
else if (strcmp(inRecType, kDSStdRecordTypeComputers) == 0 &&
strcmp(kDSNAttrIPAddress, pAttrType) == 0)
{
aTmpData->Clear();
aTmp2Data->Clear();
aTmp2Data->AppendShort( strlen( pAttrType ) );
aTmp2Data->AppendString( pAttrType );
valCount = 0;
if ( inAttrOnly == false )
{
char buffer[16];
char **vals;
aHost = inContext->fLDAPConnection->LockLDAPSession();
if (aHost != NULL)
{
pLDAPAttrType = MapAttrToLDAPType( inContext,kDSStdRecordTypeComputers, kDSNAttrIPAddress, numAttributes );
if ( pLDAPAttrType != NULL )
{
if((vals = ldap_get_values(aHost, inResult,pLDAPAttrType)) != NULL)
{
for (int i = 0; vals[i] != NULL; i++ )
{
if(inet_pton(AF_INET, vals[i], buffer) == 1 ) {
aTmpData->AppendLong( strlen(vals[i]) );
aTmpData->AppendString( vals[i] );
DbgLog( kLogInfo, "CLDAPv3Plugin: GetTheseAttributes:: appending value %s to ipv4",vals[i] );
valCount++;
}
} }
if (vals != NULL)
{
ldap_value_free(vals);
vals = NULL;
}
DSFree( pLDAPAttrType );
}
inContext->fLDAPConnection->UnlockLDAPSession( aHost, false );
}
}
}
else
{
pLDAPAttrType = MapAttrToLDAPType( inContext, (const char *)inRecType, pAttrType, numAttributes );
bAtLeastOneTypeValid = false;
bTypeFound = false;
}
while ( pLDAPAttrType != nil )
{
if (!bTypeFound)
{
aTmp2Data->Clear();
aTmp2Data->AppendShort( strlen( pAttrType ) );
aTmp2Data->AppendString( pAttrType );
bTypeFound = true;
valCount = 0;
aTmpData->Clear();
}
if (pLDAPAttrType[0] == '#') {
bAtLeastOneTypeValid = true;
char *vsReturnStr = nil;
vsReturnStr = MappingNativeVariableSubstitution( pLDAPAttrType, inContext, inResult, siResult );
if (vsReturnStr != nil)
{
literalLength = strlen(vsReturnStr) - 1;
}
else
{
if (siResult != eDSNoErr) throw (siResult);
literalLength = strlen(pLDAPAttrType) - 1;
}
if ( (inAttrOnly == false) && (literalLength > 0) )
{
valCount++;
if(vsReturnStr != nil)
{
aTmpData->AppendLong( literalLength );
aTmpData->AppendBlock( vsReturnStr + 1, literalLength );
}
else
{
aTmpData->AppendLong( literalLength );
aTmpData->AppendBlock( pLDAPAttrType + 1, literalLength );
}
} if (vsReturnStr != nil)
{
free( vsReturnStr );
vsReturnStr = nil;
}
}
else
{
aHost = inContext->fLDAPConnection->LockLDAPSession();
if (aHost != NULL)
{
bValues = ldap_get_values_len (aHost, inResult, pLDAPAttrType );
if (bValues != NULL && bValues[0] != NULL)
{
bAtLeastOneTypeValid = true;
}
if ( ( inAttrOnly == false ) && (bValues != NULL) )
{
if (bStripCryptPrefix)
{
for (int ii = 0; bValues[ii] != NULL; ii++ )
valCount++;
if (valCount == 0)
{
valCount = 1;
aTmpData->AppendLong( sizeof(kDSValueNonCryptPasswordMarker)-1 );
aTmpData->AppendString( kDSValueNonCryptPasswordMarker );
}
for (int i = 0; bValues[i] != NULL; i++ )
{
if ( ( bValues[i]->bv_len > 7) &&
(strncasecmp(bValues[i]->bv_val,"{crypt}",7) == 0) )
{
aTmpData->AppendLong( bValues[i]->bv_len - 7 );
aTmpData->AppendBlock( (bValues[i]->bv_val) + 7, bValues[i]->bv_len - 7 );
}
else
{
aTmpData->AppendLong( bValues[i]->bv_len );
aTmpData->AppendBlock( bValues[i]->bv_val, bValues[i]->bv_len );
}
} ldap_value_free_len(bValues);
bValues = NULL;
}
else
{
for (int ii = 0; bValues[ii] != NULL; ii++ )
valCount++;
for (int i = 0; bValues[i] != NULL; i++ )
{
aTmpData->AppendLong( bValues[i]->bv_len );
aTmpData->AppendBlock( bValues[i]->bv_val, bValues[i]->bv_len );
} ldap_value_free_len(bValues);
bValues = NULL;
}
} else if ( (valCount == 0) && (bValues == NULL) && bStripCryptPrefix)
{
valCount = 1;
aTmpData->AppendLong( sizeof(kDSValueNonCryptPasswordMarker)-1 );
aTmpData->AppendString( kDSValueNonCryptPasswordMarker );
}
if (bValues != NULL)
{
ldap_value_free_len(bValues);
bValues = NULL;
}
inContext->fLDAPConnection->UnlockLDAPSession( aHost, false );
}
}
if (pLDAPAttrType != nil)
{
delete (pLDAPAttrType);
pLDAPAttrType = nil;
}
numAttributes++;
pLDAPAttrType = MapAttrToLDAPType( inContext, (const char *)inRecType, pAttrType, numAttributes );
}
if ((bAtLeastOneTypeValid && inAttrOnly) || (valCount > 0))
{
aTmp2Data->AppendShort( valCount );
if (valCount > 0)
{
aTmp2Data->AppendBlock( aTmpData->GetData(), aTmpData->GetLength() );
valCount = 0;
}
outCount++;
inDataBuff->AppendLong( aTmp2Data->GetLength() );
inDataBuff->AppendBlock( aTmp2Data->GetData(), aTmp2Data->GetLength() );
}
}
}
}
catch ( tDirStatus err )
{
siResult = err;
}
DSFree( pLDAPIPAddressAttrType );
DSFree( pLDAPIPv6AddressAttrType );
DSFree( pLDAPPasswdAttrType );
DSDelete( aTmpData );
DSDelete( aTmp2Data );
return( siResult );
}
char *CLDAPv3Plugin::GetRecordName ( char *inRecType,
LDAPMessage *inResult,
sLDAPContextData *inContext,
tDirStatus &errResult )
{
char *recName = nil;
char *pLDAPAttrType = nil;
struct berval **bValues;
int numAttributes = 1;
bool bTypeFound = false;
LDAP *aHost = nil;
if ( inContext == nil ) return( NULL );
try
{
errResult = eDSNoErr;
numAttributes = 1;
pLDAPAttrType = MapAttrToLDAPType( inContext, (const char *)inRecType, kDSNAttrRecordName, numAttributes, true );
if ( pLDAPAttrType == nil ) throw( eDSInvalidAttrListRef );
bTypeFound = false;
aHost = inContext->fLDAPConnection->LockLDAPSession();
if ( aHost != NULL )
{
while ( (pLDAPAttrType != nil) && (!bTypeFound) )
{
if ( (bValues = ldap_get_values_len(aHost, inResult, pLDAPAttrType)) != NULL )
{
recName = (char *) calloc(1, 1 + bValues[0]->bv_len);
strcpy( recName, bValues[0]->bv_val );
bTypeFound = true;
ldap_value_free_len(bValues);
bValues = NULL;
}
DSFreeString( pLDAPAttrType );
numAttributes++;
pLDAPAttrType = MapAttrToLDAPType( inContext, (const char *)inRecType, kDSNAttrRecordName, numAttributes, true );
} inContext->fLDAPConnection->UnlockLDAPSession( aHost, false );
}
DSFreeString( pLDAPAttrType );
} catch ( tDirStatus err )
{
errResult = err;
}
return( recName );
}
char** CLDAPv3Plugin::MapAttrListToLDAPTypeArray( char *inRecType, CAttributeList *inAttrTypeList, sLDAPContextData *inContext,
char *inSearchAttr )
{
char **outResult = nil;
char **mvResult = nil;
UInt32 uiStrLen = 0;
UInt32 uiNativeLen = strlen( kDSNativeAttrTypePrefix );
UInt32 uiStdLen = strlen( kDSStdAttrTypePrefix );
int countNative = 0;
char *pAttrType = nil;
SInt32 attrTypeIndex = 1;
bool bAddRecordName = true;
bool bRecordNameGiven= false;
bool bCleanUp = false;
inAttrTypeList->GetAttribute(attrTypeIndex++, &pAttrType);
while ( pAttrType != NULL || bAddRecordName )
{
if ( pAttrType == nil )
{
if ( bRecordNameGiven )
{
break;
}
else
{
bAddRecordName = false;
pAttrType = (char *)kDSNAttrRecordName;
bCleanUp = true;
}
}
else if ( ( strcmp(pAttrType,kDSAttributesAll) == 0 ) ||
( strcmp(pAttrType,kDSAttributesNativeAll) == 0 ) ||
( strcmp(pAttrType,kDSAttributesStandardAll) == 0 ) )
{
if (outResult != nil)
{
for (int ourIndex=0; ourIndex < countNative; ourIndex++) {
free(outResult[ourIndex]);
outResult[ourIndex] = nil;
}
free(outResult);
}
return(nil);
}
uiStrLen = strlen( pAttrType );
if ( strncmp( pAttrType, kDSNativeAttrTypePrefix, uiNativeLen ) == 0 )
{
if ( uiStrLen > uiNativeLen )
{
uiStrLen = uiStrLen - uiNativeLen;
if (outResult != nil)
{
mvResult = outResult;
outResult = (char **)calloc( countNative + 2, sizeof( char * ) );
for (int oldIndex=0; oldIndex < countNative; oldIndex++) {
outResult[oldIndex] = mvResult[oldIndex];
}
}
else
{
outResult = (char **)calloc( 2, sizeof( char * ) );
}
outResult[countNative] = (char *) calloc(1, uiStrLen + 1 );
strcpy( outResult[countNative], pAttrType + uiNativeLen );
DbgLog( kLogPlugin, "CLDAPv3Plugin: MapAttrListToLDAPTypeArray:: Warning:Native attribute type <%s> is being used", outResult[countNative] );
countNative++;
if (mvResult != nil)
{
free(mvResult);
mvResult = nil;
}
}
} else if ( strncmp( pAttrType, kDSStdAttrTypePrefix, uiStdLen ) == 0 )
{
if ( strcmp( pAttrType, (char *)kDSNAttrRecordName ) == 0 )
{
bRecordNameGiven = true;
}
char *singleMap = nil;
int aIndex = 1;
int mapCount = 0;
int usedMapCount= 0;
mapCount = AttrMapsCount( inContext, inRecType, pAttrType );
if (mapCount > 0)
{
if (outResult != nil)
{
mvResult = outResult;
outResult = (char **)calloc( countNative + mapCount + 1, sizeof( char * ) );
for (int oldIndex=0; oldIndex < countNative; oldIndex++) {
outResult[oldIndex] = mvResult[oldIndex];
}
}
else
{
outResult = (char **)calloc( mapCount + 1, sizeof( char * ) );
}
do
{
singleMap = ExtractAttrMap( inContext, inRecType, pAttrType, aIndex );
if (singleMap != nil)
{
if (singleMap[0] != '#')
{
outResult[countNative + usedMapCount] = singleMap; usedMapCount++;
}
else {
free(singleMap);
}
}
aIndex++;
}
while (singleMap != nil);
countNative += usedMapCount;
if (mvResult != nil)
{
free(mvResult);
mvResult = nil;
}
}
} else
{
if (outResult != nil)
{
mvResult = outResult;
outResult = (char **)::calloc( countNative + 2, sizeof( char * ) );
for (int oldIndex=0; oldIndex < countNative; oldIndex++) {
outResult[oldIndex] = mvResult[oldIndex];
}
}
else
{
outResult = (char **)::calloc( 2, sizeof( char * ) );
}
outResult[countNative] = (char *) calloc(1, strlen( pAttrType ) + 1 );
::strcpy( outResult[countNative], pAttrType );
DbgLog( kLogPlugin, "CLDAPv3Plugin::MapAttrListToLDAPTypeArray: Warning:Native attribute type with no "
"provided prefix <%s> is being used", outResult[countNative] );
countNative++;
if (mvResult != nil)
{
free(mvResult);
mvResult = nil;
}
} if (bCleanUp)
{
pAttrType = nil;
}
else
{
pAttrType = nil;
inAttrTypeList->GetAttribute(attrTypeIndex++, &pAttrType);
}
if ( pAttrType == NULL && DSIsStringEmpty(inSearchAttr) == false )
{
pAttrType = inSearchAttr;
inSearchAttr = NULL;
}
}
return( outResult );
}
tDirStatus CLDAPv3Plugin::MapLDAPWriteErrorToDS ( SInt32 inLDAPError, tDirStatus inDefaultError )
{
tDirStatus siOutError = eDSNoErr;
switch ( inLDAPError )
{
case LDAP_SUCCESS:
siOutError = eDSNoErr;
break;
case LDAP_AUTH_UNKNOWN:
case LDAP_AUTH_METHOD_NOT_SUPPORTED:
siOutError = eDSAuthMethodNotSupported;
break;
case LDAP_INAPPROPRIATE_AUTH:
case LDAP_INVALID_CREDENTIALS:
case LDAP_INSUFFICIENT_ACCESS:
case LDAP_STRONG_AUTH_REQUIRED:
siOutError = eDSPermissionError;
break;
case LDAP_NO_SUCH_ATTRIBUTE:
siOutError = eDSAttributeNotFound;
break;
case LDAP_NO_SUCH_OBJECT:
siOutError = eDSRecordNotFound;
break;
case LDAP_NO_MEMORY:
siOutError = eMemoryError;
break;
case LDAP_TIMEOUT:
siOutError = eDSServerTimeout;
break;
case LDAP_NAMING_VIOLATION:
case LDAP_OBJECT_CLASS_VIOLATION:
case LDAP_CONSTRAINT_VIOLATION:
case LDAP_INVALID_SYNTAX:
siOutError = eDSSchemaError;
break;
case LDAP_SERVER_DOWN:
siOutError = eDSCannotAccessSession;
break;
case LDAP_UNDEFINED_TYPE:
siOutError = eDSInvalidAttributeType;
break;
case LDAP_INVALID_DN_SYNTAX:
siOutError = eDSInvalidName;
break;
default:
siOutError = inDefaultError;
break;
}
DbgLog( kLogPlugin, "CLDAPv3Plugin: error code %d returned by LDAP framework", inLDAPError );
return( siOutError );
}
tDirStatus CLDAPv3Plugin::GetAttributeEntry ( sGetAttributeEntry *inData )
{
tDirStatus siResult = eDSNoErr;
UInt16 usAttrTypeLen = 0;
UInt16 usAttrCnt = 0;
UInt32 usAttrLen = 0;
UInt16 usValueCnt = 0;
UInt32 usValueLen = 0;
UInt32 i = 0;
UInt32 uiIndex = 0;
UInt32 uiAttrEntrySize = 0;
UInt32 uiOffset = 0;
UInt32 uiTotalValueSize = 0;
UInt32 offset = 4;
UInt32 buffSize = 0;
UInt32 buffLen = 0;
char *p = nil;
char *pAttrType = nil;
tDataBufferPtr pDataBuff = nil;
tAttributeEntryPtr pAttribInfo = nil;
sLDAPContextData *pAttrContext = nil;
sLDAPContextData *pValueContext = nil;
try
{
if ( inData == nil ) throw( eMemoryError );
pAttrContext = gLDAPContextTable->GetObjectForRefNum( inData->fInAttrListRef );
if ( pAttrContext == nil ) throw( eDSBadContextData );
uiIndex = inData->fInAttrInfoIndex;
if (uiIndex == 0) throw( eDSInvalidIndex );
pDataBuff = inData->fInOutDataBuff;
if ( pDataBuff == nil ) throw( eDSNullDataBuff );
buffSize = pDataBuff->fBufferSize;
p = pDataBuff->fBufferData + pAttrContext->offset;
offset = pAttrContext->offset;
if (offset + 2 > buffSize) throw( eDSInvalidBuffFormat );
memcpy( &usAttrCnt, p, 2 );
if (uiIndex > usAttrCnt) throw( eDSIndexOutOfRange );
p += 2;
offset += 2;
for ( i = 1; i < uiIndex; i++ )
{
if (offset + 4 > buffSize) throw( eDSInvalidBuffFormat );
memcpy( &usAttrLen, p, 4 );
p += 4 + usAttrLen;
offset += 4 + usAttrLen;
}
uiOffset = offset;
if (offset + 4 > buffSize) throw( eDSInvalidBuffFormat );
memcpy( &usAttrLen, p, 4 );
p += 4;
offset += 4;
buffLen = offset + usAttrLen;
if (offset + 2 > buffLen) throw( eDSInvalidBuffFormat );
memcpy( &usAttrTypeLen, p, 2 );
pAttrType = p + 2;
p += 2 + usAttrTypeLen;
offset += 2 + usAttrTypeLen;
if (offset + 2 > buffLen) throw( eDSInvalidBuffFormat );
memcpy( &usValueCnt, p, 2 );
p += 2;
offset += 2;
for ( i = 0; i < usValueCnt; i++ )
{
if (offset + 4 > buffLen) throw( eDSInvalidBuffFormat );
memcpy( &usValueLen, p, 4 );
p += 4 + usValueLen;
offset += 4 + usValueLen;
uiTotalValueSize += usValueLen;
}
uiAttrEntrySize = sizeof( tAttributeEntry ) + usAttrTypeLen + kBuffPad;
pAttribInfo = (tAttributeEntry *)calloc( 1, uiAttrEntrySize );
pAttribInfo->fAttributeValueCount = usValueCnt;
pAttribInfo->fAttributeDataSize = uiTotalValueSize;
pAttribInfo->fAttributeValueMaxSize = 512; pAttribInfo->fAttributeSignature.fBufferSize = usAttrTypeLen + kBuffPad;
pAttribInfo->fAttributeSignature.fBufferLength = usAttrTypeLen;
memcpy( pAttribInfo->fAttributeSignature.fBufferData, pAttrType, usAttrTypeLen );
pValueContext = new sLDAPContextData( *pAttrContext );
if ( pValueContext == nil ) throw( eMemoryAllocError );
pValueContext->offset = uiOffset;
gLDAPContextTable->AddObjectForRefNum( inData->fOutAttrValueListRef, pValueContext );
inData->fOutAttrInfoPtr = pAttribInfo;
DSRelease( pValueContext );
}
catch ( tDirStatus err )
{
siResult = err;
}
DSRelease( pAttrContext );
return( siResult );
}
tDirStatus CLDAPv3Plugin::GetAttributeValue ( sGetAttributeValue *inData )
{
tDirStatus siResult = eDSNoErr;
UInt16 usValueCnt = 0;
UInt32 usValueLen = 0;
UInt16 usAttrNameLen = 0;
UInt32 i = 0;
UInt32 uiIndex = 0;
UInt32 offset = 0;
char *p = nil;
tDataBuffer *pDataBuff = nil;
tAttributeValueEntry *pAttrValue = nil;
sLDAPContextData *pValueContext = nil;
UInt32 buffSize = 0;
UInt32 buffLen = 0;
UInt32 attrLen = 0;
try
{
pValueContext = gLDAPContextTable->GetObjectForRefNum( inData->fInAttrValueListRef );
if ( pValueContext == nil ) throw( eDSBadContextData );
uiIndex = inData->fInAttrValueIndex;
if (uiIndex == 0) throw( eDSInvalidIndex );
pDataBuff = inData->fInOutDataBuff;
if ( pDataBuff == nil ) throw( eDSNullDataBuff );
buffSize = pDataBuff->fBufferSize;
p = pDataBuff->fBufferData + pValueContext->offset;
offset = pValueContext->offset;
if (offset + 4 > buffSize) throw( eDSInvalidBuffFormat );
memcpy( &attrLen, p, 4 );
buffLen = attrLen + pValueContext->offset + 4;
if (buffLen > buffSize) throw( eDSInvalidBuffFormat );
p += 4;
offset += 4;
if (offset + 2 > buffLen) throw( eDSInvalidBuffFormat );
memcpy( &usAttrNameLen, p, 2 );
p += 2 + usAttrNameLen;
offset += 2 + usAttrNameLen;
if (offset + 2 > buffLen) throw( eDSInvalidBuffFormat );
memcpy( &usValueCnt, p, 2 );
p += 2;
offset += 2;
if (uiIndex > usValueCnt) throw( eDSIndexOutOfRange );
for ( i = 1; i < uiIndex; i++ )
{
if (offset + 4 > buffLen) throw( eDSInvalidBuffFormat );
memcpy( &usValueLen, p, 4 );
p += 4 + usValueLen;
offset += 4 + usValueLen;
}
if (offset + 4 > buffLen) throw( eDSInvalidBuffFormat );
memcpy( &usValueLen, p, 4 );
p += 4;
offset += 4;
pAttrValue = (tAttributeValueEntry *)calloc( 1, sizeof( tAttributeValueEntry ) + usValueLen + kBuffPad );
pAttrValue->fAttributeValueData.fBufferSize = usValueLen + kBuffPad;
pAttrValue->fAttributeValueData.fBufferLength = usValueLen;
if ( offset + usValueLen > buffLen )throw( eDSInvalidBuffFormat );
memcpy( pAttrValue->fAttributeValueData.fBufferData, p, usValueLen );
pAttrValue->fAttributeValueID = CalcCRC( pAttrValue->fAttributeValueData.fBufferData );
inData->fOutAttrValue = pAttrValue;
}
catch ( tDirStatus err )
{
siResult = err;
}
DSRelease( pValueContext );
return( siResult );
}
tDirStatus CLDAPv3Plugin::CheckAutomountNames( const char *inRecType,
char **inAttrValues,
char ***outValues,
char ***outMaps,
UInt32 *outCount )
{
char **aMaps = NULL;
char **aValues = NULL;
UInt32 iCount = 0;
tDirStatus dsStatus = eDSNoErr;
if (inRecType != NULL && strcmp(inRecType, kDSStdRecordTypeAutomount) == 0)
{
for (iCount = 0; inAttrValues[iCount] != NULL; iCount++);
if (iCount > 0)
{
aMaps = (char **) calloc( iCount + 1, sizeof(char *) );
aValues = (char **) calloc( iCount + 1, sizeof(char *) );
for ( UInt32 ii = 0; ii < iCount; ii++ )
{
char *pValue = inAttrValues[ii];
char *separator = strcasestr( pValue, ",automountMapName=" );
if (separator != NULL)
{
int length = separator - pValue;
char *automountName = dsCStrFromCharacters( pValue, length );
aMaps[ii] = strdup( separator + (sizeof(",automountMapName=") - 1) );
aValues[ii] = automountName;
}
else
{
dsStatus = eDSInvalidRecordName;
break;
}
}
}
}
if (iCount != 0 && dsStatus == eDSNoErr)
{
(*outMaps) = aMaps;
(*outValues) = aValues;
(*outCount) = iCount;
}
else
{
(*outMaps) = NULL;
(*outValues) = NULL;
(*outCount) = 0;
DSFreeStringList( aMaps );
DSFreeStringList( aValues );
}
return dsStatus;
}
char *CLDAPv3Plugin::CopyAutomountMapName( sLDAPContextData *inContext,
LDAPMessage *result )
{
char *mapName = nil;
bool failed = false;
if (inContext != NULL)
{
LDAP *aHost = inContext->fLDAPConnection->LockLDAPSession();
if ( aHost != NULL )
{
char *pMapAttrName = MapAttrToLDAPType( inContext,kDSStdRecordTypeAutomountMap, kDSNAttrRecordName, 1, true );
if ( pMapAttrName != NULL )
{
char *pDNStr = ldap_get_dn( aHost, result );
LDAPDN tmpDN = NULL;
if ( pDNStr != NULL )
{
if (ldap_str2dn(pDNStr, &tmpDN, LDAP_DN_FORMAT_LDAPV3) == LDAP_SUCCESS)
{
for (int iRDN = 0; tmpDN[iRDN] != NULL; iRDN++)
{
if (tmpDN[iRDN][0] != NULL && strcasecmp(tmpDN[iRDN][0]->la_attr.bv_val, pMapAttrName) == 0)
{
mapName = strdup( tmpDN[iRDN][0]->la_value.bv_val );
break;
}
}
ldap_dnfree( tmpDN );
}
free( pDNStr );
pDNStr = NULL;
}
else
{
DbgLog( kLogPlugin, "CLDAPv3Plugin::CopyAutomountMapName(): bad ldap session, no DN." );
failed = true;
}
free( pMapAttrName );
pMapAttrName = NULL;
}
inContext->fLDAPConnection->UnlockLDAPSession( aHost, failed );
}
}
return( mapName );
}
bool CLDAPv3Plugin::DoesThisMatchAutomount( sLDAPContextData *inContext,
UInt32 inCountMaps,
char **inMaps,
LDAPMessage *inResult )
{
bool bMatches = true;
if (inCountMaps > 0)
{
char *mapName = CopyAutomountMapName( inContext, inResult );
if (mapName != NULL)
{
bMatches = false;
for (UInt32 ii = 0; ii < inCountMaps; ii++)
{
if (inMaps[ii] != NULL && strcmp(inMaps[ii], mapName) == 0)
{
bMatches = true;
break;
}
}
free( mapName );
mapName = NULL;
}
}
return bMatches;
}
tDirStatus CLDAPv3Plugin::GetTheseRecords (
char *inConstAttrType,
char **inAttrNames,
char *inRecType,
char *inNativeRecType,
tDirPatternMatch patternMatch,
CAttributeList *inAttrTypeList,
sLDAPContextData *inContext,
sLDAPContinueData *inContinue,
bool inAttrOnly,
CBuff *inBuff,
UInt32 &outRecCount,
bool inbOCANDGroup,
CFArrayRef inOCSearchList,
ber_int_t inScope )
{
tDirStatus siResult = eDSNoErr;
SInt32 siValCnt = 0;
LDAPMessage *result = nil;
char *recName = nil;
char *queryFilter = nil;
CDataBuff *aRecData = nil;
CDataBuff *aAttrData = nil;
bool bFoundMatch = false;
char **aAutomountMaps = NULL;
char **aValues = NULL;
char **checkMaps = NULL;
char *aAutomountBase = NULL;
char *pMapAttrName = NULL;
UInt32 iCountMaps = 0;
char **tempNames = NULL;
char *altIdAttr = NULL;
char **altNames = NULL;
if ( inContext == NULL ) return( eDSInvalidContext );
if ( inContinue == NULL ) return( eDSInvalidContinueData );
outRecCount = 0;
if ( inContext->fLDAPConnection->ConnectionStatus() == kConnectionUnsafe )
return( eDSCannotAccessSession );
if (inConstAttrType != NULL && inRecType != NULL && strcmp(inRecType, kDSStdRecordTypeAutomount) == 0)
{
if ( strcmp(inConstAttrType, kDS1AttrMetaAutomountMap) == 0 )
{
char *value = inAttrNames[0];
if ( value == NULL )
return eDSEmptyPatternMatch;
pMapAttrName = MapAttrToLDAPType( inContext, kDSStdRecordTypeAutomountMap, kDSNAttrRecordName, 1, true );
if ( pMapAttrName == NULL )
return eDSNoStdMappingAvailable;
int length = strlen(pMapAttrName) + sizeof("=") + strlen(value) + strlen(inNativeRecType) + 1;
aAutomountBase = (char *) calloc( length, sizeof(char) );
snprintf( aAutomountBase, length, "%s=%s,%s", pMapAttrName, value, inNativeRecType );
inConstAttrType = nil;
inScope = LDAP_SCOPE_ONELEVEL;
inNativeRecType = aAutomountBase;
patternMatch = eDSAnyMatch;
DbgLog( kLogDebug, "CLDAPv3Plugin::GetTheseRecords - initiating automount search with searchbase \"%s\"", aAutomountBase );
}
else if ( strcmp(inConstAttrType, kDSNAttrRecordName) == 0 &&
(siResult = CheckAutomountNames(inRecType, inAttrNames, &aValues, &aAutomountMaps, &iCountMaps)) == eDSNoErr )
{
inAttrNames = aValues;
checkMaps = aAutomountMaps;
}
else if (siResult != eDSNoErr)
{
return siResult;
}
}
if ( inContinue->fLDAPMsgId == 0 )
{
if (inConstAttrType == nil)
{
queryFilter = BuildLDAPQueryFilter( inContext,
inConstAttrType,
nil,
eDSAnyMatch,
false,
(const char *)inRecType,
inNativeRecType,
inbOCANDGroup,
inOCSearchList );
}
else
{
queryFilter = BuildLDAPQueryMultiFilter( inConstAttrType,
inAttrNames,
patternMatch,
inContext,
false,
(const char *)inRecType,
inNativeRecType,
inbOCANDGroup,
inOCSearchList );
if ( queryFilter != NULL &&
(patternMatch == eDSiExact || patternMatch == eDSExact) &&
inAttrNames != NULL && inRecType != NULL &&
(strcmp(inRecType, kDSStdRecordTypeUsers) == 0 || strcmp(inRecType, kDSStdRecordTypeComputers) == 0) &&
strcmp(inConstAttrType, kDSNAttrRecordName) == 0 )
{
altIdAttr = MapAttrToLDAPType( inContext, inRecType, kDSNAttrAltSecurityIdentities, 1, true );
if ( altIdAttr != NULL )
{
int index = 0;
altNames = (char **) calloc( 1, malloc_size(inAttrNames) );
char *value = NULL;
int nameCount = 0;
for ( nameCount = 0; (value = inAttrNames[nameCount]) != NULL; nameCount++ )
{
int len = strlen( value );
if ( memchr(value, '@', len) != NULL )
{
size_t buffLen = len + sizeof("Kerberos:");
char *buffer = (char *) malloc( buffLen );
strlcpy( buffer, "Kerberos:", buffLen );
strlcat( buffer, value, buffLen );
altNames[index++] = buffer;
DbgLog( kLogInfo, "CLDAPv3Plugin::GetTheseRecords - searching AltSecurityIdentities for '%s'", buffer );
}
}
if ( index != 0 )
{
char *tempFilter = BuildLDAPQueryMultiFilter( (char *) kDSNAttrAltSecurityIdentities,
altNames,
patternMatch,
inContext,
false,
(const char *)inRecType,
inNativeRecType,
inbOCANDGroup,
inOCSearchList );
if ( tempFilter != NULL )
{
size_t len = 2 + strlen(queryFilter) + strlen(tempFilter) + 1 + 1;
char *newFilter = (char *) calloc( len, sizeof(char) );
snprintf( newFilter, len, "(|%s%s)", queryFilter, tempFilter );
DSFree( queryFilter );
DSFree( tempFilter );
queryFilter = newFilter;
}
tempNames = (char **) calloc( nameCount + index + 1, sizeof(char *) );
bcopy( inAttrNames, tempNames, nameCount * sizeof(char *) );
bcopy( altNames, tempNames + nameCount, index * sizeof(char *) );
inAttrNames = tempNames;
}
DSFreeString( altIdAttr );
}
}
}
if ( queryFilter == nil )
{
DSFreeStringList( aAutomountMaps );
DSFreeStringList( aValues );
DSFreeString( aAutomountBase );
DSFree( tempNames );
return eDSNoStdMappingAvailable;
}
}
char **attrs = MapAttrListToLDAPTypeArray( inRecType, inAttrTypeList, inContext, inConstAttrType );
if ( altIdAttr != NULL && tempNames != NULL ) {
char **oldPtr = attrs;
size_t currSize = (attrs ? malloc_size(attrs) : 0);
attrs = (char **) reallocf( attrs, currSize + sizeof(char *) );
char **tempList = attrs;
if ( oldPtr != NULL ) {
while ( (*tempList) != NULL ) tempList++;
}
tempList[0] = strdup( altIdAttr );
tempList[1] = NULL;
}
try
{
aRecData = new CDataBuff();
if ( aRecData == nil ) throw( eMemoryError );
aAttrData = new CDataBuff();
if ( aAttrData == nil ) throw( eMemoryError );
do
{
siResult = DSInitiateOrContinueSearch( inContext, inContinue, inNativeRecType, attrs, inScope, queryFilter, &result );
if ( siResult == eDSNoErr && result != NULL )
{
bFoundMatch = ( DoesThisMatchAutomount(inContext, iCountMaps, checkMaps, result) &&
DoAnyOfTheseAttributesMatch(inContext, inAttrNames, patternMatch, result) );
if ( bFoundMatch )
{
aRecData->Clear();
if ( inRecType != nil )
{
aRecData->AppendShort( strlen( inRecType ) );
aRecData->AppendString( inRecType );
}
else
{
aRecData->AppendShort( sizeof(kLDAPRecordTypeUnknownStr) - 1 );
aRecData->AppendString( kLDAPRecordTypeUnknownStr );
}
recName = GetRecordName( inRecType, result, inContext, siResult );
if ( siResult != eDSNoErr ) throw( siResult );
if ( recName != nil )
{
aRecData->AppendShort( strlen( recName ) );
aRecData->AppendString( recName );
DSDelete ( recName );
}
else
{
aRecData->AppendShort( sizeof(kLDAPRecordNameUnknownStr) - 1 );
aRecData->AppendString( kLDAPRecordNameUnknownStr );
}
aAttrData->Clear();
siResult = GetTheseAttributes( inRecType, inAttrTypeList, result, inAttrOnly, inContext, siValCnt, aAttrData );
if ( siResult != eDSNoErr ) throw( siResult );
aRecData->AppendShort( siValCnt );
if ( siValCnt != 0 )
aRecData->AppendBlock( aAttrData->GetData(), aAttrData->GetLength() );
if ( inBuff->AddData(aRecData->GetData(), aRecData->GetLength()) == CBuff::kBuffFull )
{
siResult = eDSBufferTooSmall;
inContinue->fResult = result;
result = NULL;
break;
}
}
if ( result != NULL )
{
ldap_msgfree( result );
result = NULL;
if ( bFoundMatch )
{
outRecCount++; inContinue->fTotalRecCount++;
}
}
}
else if ( siResult == eDSRecordNotFound )
{
siResult = eDSNoErr;
break;
}
} while ( siResult == eDSNoErr &&
(inContinue->fLimitRecSearch == 0 || inContinue->fTotalRecCount < inContinue->fLimitRecSearch) );
} catch ( tDirStatus err )
{
siResult = err;
}
DSFree( tempNames );
DSFreeStringList( altNames );
DSFreeStringList( attrs );
DSDelete( queryFilter );
DSDelete( aRecData );
DSDelete( aAttrData );
DSFreeStringList( aAutomountMaps );
DSFreeStringList( aValues );
DSFreeString( aAutomountBase );
DSFreeString( pMapAttrName );
return( siResult );
}
char *CLDAPv3Plugin::BuildLDAPQueryMultiFilter
( char *inConstAttrType,
char **inAttrNames,
tDirPatternMatch patternMatch,
sLDAPContextData *inContext,
bool useWellKnownRecType,
const char *inRecType,
char *inNativeRecType,
bool inbOCANDGroup,
CFArrayRef inOCSearchList )
{
char *queryFilter = nil;
UInt32 matchType = eDSExact;
char *nativeAttrType = nil;
UInt32 recNameLen = 0;
int numAttributes = 1;
CFMutableStringRef cfStringRef = nil;
CFMutableStringRef cfQueryStringRef = nil;
char **escapedStrings = nil;
UInt32 escapedIndex = 0;
UInt32 originalIndex = 0;
bool bOnceThru = false;
UInt32 offset = 3;
UInt32 callocLength = 0;
bool objClassAdded = false;
bool bGetAllDueToLiteralMapping = false;
int aOCSearchListCount = 0;
char **attrValues = inAttrNames;
char **nonEscapedStrings = NULL;
cfQueryStringRef = CFStringCreateMutable(kCFAllocatorDefault, 0);
if ( (inRecType != nil) && (inNativeRecType != nil) )
{
if (strncmp(inRecType,kDSStdRecordTypePrefix,strlen(kDSStdRecordTypePrefix)) == 0)
{
if (inOCSearchList != nil)
{
aOCSearchListCount = CFArrayGetCount(inOCSearchList);
for ( int iOCIndex = 0; iOCIndex < aOCSearchListCount; iOCIndex++ )
{
CFStringRef ocString;
ocString = (CFStringRef)::CFArrayGetValueAtIndex( inOCSearchList, iOCIndex );
if (ocString != nil)
{
if (!objClassAdded)
{
objClassAdded = true;
if (inbOCANDGroup)
{
CFStringAppendCString(cfQueryStringRef,"(&", kCFStringEncodingUTF8);
}
else
{
CFStringAppendCString(cfQueryStringRef,"(&(|", kCFStringEncodingUTF8);
}
}
CFStringAppendCString(cfQueryStringRef, "(objectclass=", kCFStringEncodingUTF8);
CFStringAppend(cfQueryStringRef, ocString);
CFStringAppendCString(cfQueryStringRef, ")", kCFStringEncodingUTF8);
}
} if (CFStringGetLength(cfQueryStringRef) != 0)
{
if (!inbOCANDGroup)
{
CFStringAppendCString(cfQueryStringRef,")", kCFStringEncodingUTF8);
}
}
}
} }
if ( (CFStringGetLength(cfQueryStringRef) == 0) && (inAttrNames == nil) )
{
CFStringAppendCString(cfQueryStringRef,"(&(objectclass=*)", kCFStringEncodingUTF8);
objClassAdded = true;
}
if ( ((patternMatch == eDSCompoundExpression) ||
(patternMatch == eDSiCompoundExpression)) && inAttrNames )
{
CFStringRef cfTempStringRef = inContext->fLDAPConnection->fNodeConfig->ParseCompoundExpression( inAttrNames[0], inRecType );
if (cfTempStringRef != nil)
{
CFStringAppend(cfQueryStringRef, cfTempStringRef);
DSCFRelease(cfTempStringRef);
}
}
else
{
if (inAttrNames != nil)
{
UInt32 strCount = 0; while(inAttrNames[strCount] != nil)
{
strCount++;
}
if (inRecType != NULL && strcmp(inRecType, kDSStdRecordTypeAutomount) == 0 &&
inConstAttrType != NULL && strcmp(inConstAttrType, kDSNAttrRecordName) == 0)
{
nonEscapedStrings = (char **) calloc( strCount + 1, sizeof (char *) );
attrValues = nonEscapedStrings;
}
escapedStrings = (char **) calloc( strCount +1, sizeof(char *) );
strCount = 0;
while(inAttrNames[strCount] != nil)
{
if (nonEscapedStrings != NULL)
{
char *attrValue = inAttrNames[strCount];
char *separator = strcasestr( attrValue, ",automountMapName=" );
if (separator != NULL)
{
int length = separator - attrValue;
nonEscapedStrings[strCount] = dsCStrFromCharacters( attrValue, length );
}
else
{
nonEscapedStrings[strCount] = strdup( attrValue );
}
}
recNameLen = strlen(attrValues[strCount]);
escapedStrings[strCount] = (char *)calloc(1, 3 * recNameLen + 1);
escapedIndex = 0;
originalIndex = 0;
while (originalIndex < recNameLen)
{
switch (attrValues[strCount][originalIndex])
{
case '*':
escapedStrings[strCount][escapedIndex] = '\\';
++escapedIndex;
escapedStrings[strCount][escapedIndex] = '2';
++escapedIndex;
escapedStrings[strCount][escapedIndex] = 'a';
++escapedIndex;
break;
case '(':
escapedStrings[strCount][escapedIndex] = '\\';
++escapedIndex;
escapedStrings[strCount][escapedIndex] = '2';
++escapedIndex;
escapedStrings[strCount][escapedIndex] = '8';
++escapedIndex;
break;
case ')':
escapedStrings[strCount][escapedIndex] = '\\';
++escapedIndex;
escapedStrings[strCount][escapedIndex] = '2';
++escapedIndex;
escapedStrings[strCount][escapedIndex] = '9';
++escapedIndex;
break;
case '\\':
escapedStrings[strCount][escapedIndex] = '\\';
++escapedIndex;
escapedStrings[strCount][escapedIndex] = '5';
++escapedIndex;
escapedStrings[strCount][escapedIndex] = 'c';
++escapedIndex;
break;
default:
escapedStrings[strCount][escapedIndex] = attrValues[strCount][originalIndex];
++escapedIndex;
break;
} ++originalIndex;
} strCount++;
}
numAttributes = 1;
nativeAttrType = MapAttrToLDAPType( inContext, inRecType, inConstAttrType, numAttributes, false );
if (nativeAttrType == nil )
{
if ( inConstAttrType == nil ) nativeAttrType = strdup("cn");
else
goto failed;
}
cfStringRef = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, CFSTR("(|"));
matchType = (UInt32) (patternMatch);
while ( nativeAttrType != nil )
{
if (nativeAttrType[0] == '#') {
if (strlen(nativeAttrType) > 1)
{
if (DoAnyMatch((const char *)(nativeAttrType+1), escapedStrings, patternMatch))
{
if (CFStringGetLength(cfQueryStringRef) == 0)
{
CFStringAppendCString(cfQueryStringRef,"(&(objectclass=*)", kCFStringEncodingUTF8);
objClassAdded = true;
}
bGetAllDueToLiteralMapping = true;
free(nativeAttrType);
nativeAttrType = nil;
continue;
}
}
}
else
{
if (bOnceThru)
{
if (useWellKnownRecType)
{
bOnceThru = false;
break;
}
offset = 0;
}
CFStringAppendCString(cfStringRef,"(|", kCFStringEncodingUTF8);
strCount = 0;
while(escapedStrings[strCount] != nil)
{
switch (matchType)
{
case eDSStartsWith:
case eDSiStartsWith:
CFStringAppendCString(cfStringRef,"(", kCFStringEncodingUTF8);
CFStringAppendCString(cfStringRef, nativeAttrType, kCFStringEncodingUTF8);
CFStringAppendCString(cfStringRef,"=", kCFStringEncodingUTF8);
CFStringAppendCString(cfStringRef, escapedStrings[strCount], kCFStringEncodingUTF8);
CFStringAppendCString(cfStringRef,"*)", kCFStringEncodingUTF8);
bOnceThru = true;
break;
case eDSEndsWith:
case eDSiEndsWith:
CFStringAppendCString(cfStringRef,"(", kCFStringEncodingUTF8);
CFStringAppendCString(cfStringRef, nativeAttrType, kCFStringEncodingUTF8);
CFStringAppendCString(cfStringRef,"=*", kCFStringEncodingUTF8);
CFStringAppendCString(cfStringRef, escapedStrings[strCount], kCFStringEncodingUTF8);
CFStringAppendCString(cfStringRef,")", kCFStringEncodingUTF8);
bOnceThru = true;
break;
case eDSContains:
case eDSiContains:
CFStringAppendCString(cfStringRef,"(", kCFStringEncodingUTF8);
CFStringAppendCString(cfStringRef, nativeAttrType, kCFStringEncodingUTF8);
CFStringAppendCString(cfStringRef,"=*", kCFStringEncodingUTF8);
CFStringAppendCString(cfStringRef, escapedStrings[strCount], kCFStringEncodingUTF8);
CFStringAppendCString(cfStringRef,"*)", kCFStringEncodingUTF8);
bOnceThru = true;
break;
case eDSWildCardPattern:
case eDSiWildCardPattern:
CFStringAppendCString(cfStringRef,"(", kCFStringEncodingUTF8);
CFStringAppendCString(cfStringRef, nativeAttrType, kCFStringEncodingUTF8);
CFStringAppendCString(cfStringRef,"=", kCFStringEncodingUTF8);
CFStringAppendCString(cfStringRef, attrValues[strCount], kCFStringEncodingUTF8);
CFStringAppendCString(cfStringRef,")", kCFStringEncodingUTF8);
bOnceThru = true;
break;
case eDSRegularExpression:
case eDSiRegularExpression:
CFStringAppendCString(cfStringRef, attrValues[strCount], kCFStringEncodingUTF8);
bOnceThru = true;
break;
case eDSExact:
case eDSiExact:
default:
CFStringAppendCString(cfStringRef,"(", kCFStringEncodingUTF8);
CFStringAppendCString(cfStringRef, nativeAttrType, kCFStringEncodingUTF8);
CFStringAppendCString(cfStringRef,"=", kCFStringEncodingUTF8);
CFStringAppendCString(cfStringRef, escapedStrings[strCount], kCFStringEncodingUTF8);
CFStringAppendCString(cfStringRef,")", kCFStringEncodingUTF8);
bOnceThru = true;
break;
} strCount++;
} CFStringAppendCString(cfStringRef,")", kCFStringEncodingUTF8);
}
if (nativeAttrType != nil)
{
free(nativeAttrType);
nativeAttrType = nil;
}
numAttributes++;
nativeAttrType = MapAttrToLDAPType( inContext,inRecType, inConstAttrType, numAttributes, false );
}
if (!bGetAllDueToLiteralMapping)
{
if (cfStringRef != nil)
{
if (offset == 3)
{
CFRange aRangeToDelete;
aRangeToDelete.location = 1;
aRangeToDelete.length = 2;
CFStringDelete(cfStringRef, aRangeToDelete);
}
else
{
CFStringAppendCString(cfStringRef,")", kCFStringEncodingUTF8);
}
CFStringAppend(cfQueryStringRef, cfStringRef);
}
}
DSCFRelease( cfStringRef );
} }
if (objClassAdded)
{
CFStringAppendCString(cfQueryStringRef,")", kCFStringEncodingUTF8);
}
if (CFStringGetLength(cfQueryStringRef) != 0)
{
callocLength = (UInt32) CFStringGetMaximumSizeForEncoding(CFStringGetLength(cfQueryStringRef), kCFStringEncodingUTF8) + 1;
queryFilter = (char *) calloc(1, callocLength);
CFStringGetCString( cfQueryStringRef, queryFilter, callocLength, kCFStringEncodingUTF8 );
}
failed:
DSCFRelease( cfQueryStringRef );
DSFreeStringList( nonEscapedStrings );
DSFreeStringList( escapedStrings );
return (queryFilter);
}
tDirStatus CLDAPv3Plugin::GetDirNodeInfo ( sGetDirNodeInfo *inData )
{
tDirStatus siResult = eDSNoErr;
UInt32 uiOffset = 0;
UInt32 uiCntr = 1;
UInt32 uiAttrCnt = 0;
CAttributeList *inAttrList = nil;
char *pAttrName = nil;
char *pData = nil;
sLDAPContextData *pContext = nil;
sLDAPContextData *pAttrContext = nil;
CBuff outBuff;
CDataBuff *aRecData = nil;
CDataBuff *aAttrData = nil;
CDataBuff *aTmpData = nil;
try
{
if ( inData == nil ) throw( eMemoryError );
pContext = gLDAPContextTable->GetObjectForRefNum( inData->fInNodeRef );
if ( pContext == nil ) throw( eDSBadContextData );
inAttrList = new CAttributeList( inData->fInDirNodeInfoTypeList );
if ( inAttrList == nil ) throw( eDSNullNodeInfoTypeList );
if (inAttrList->GetCount() == 0) throw( eDSEmptyNodeInfoTypeList );
siResult = (tDirStatus)outBuff.Initialize( inData->fOutDataBuff, true );
if ( siResult != eDSNoErr ) throw( siResult );
siResult = (tDirStatus)outBuff.SetBuffType( 'StdA' );
if ( siResult != eDSNoErr ) throw( siResult );
aRecData = new CDataBuff();
if ( aRecData == nil ) throw( eMemoryError );
aAttrData = new CDataBuff();
if ( aAttrData == nil ) throw( eMemoryError );
aTmpData = new CDataBuff();
if ( aTmpData == nil ) throw( eMemoryError );
aRecData->AppendShort( sizeof(kDSStdRecordTypeDirectoryNodeInfo)-1 );
aRecData->AppendString( kDSStdRecordTypeDirectoryNodeInfo );
aRecData->AppendShort( sizeof( "DirectoryNodeInfo" )-1 );
aRecData->AppendString( "DirectoryNodeInfo" );
CLDAPNodeConfig *nodeConfig = pContext->fLDAPConnection->fNodeConfig;
while ( inAttrList->GetAttribute( uiCntr++, &pAttrName ) == eDSNoErr )
{
if ((strcmp( pAttrName, kDSAttributesAll ) == 0) ||
(strcmp( pAttrName, kDSNAttrNodePath ) == 0) )
{
aTmpData->Clear();
uiAttrCnt++;
aTmpData->AppendShort( sizeof( kDSNAttrNodePath )-1 );
aTmpData->AppendString( kDSNAttrNodePath );
if ( inData->fInAttrInfoOnly == false )
{
aTmpData->AppendShort( 2 );
aTmpData->AppendLong( sizeof( "LDAPv3" )-1 );
aTmpData->AppendString( "LDAPv3" );
const char *tmpStr = kLDAPUnknownNodeLocationStr;
if (nodeConfig == NULL )
tmpStr = "LDAPv3 Configure";
else if (nodeConfig->fNodeName != nil)
tmpStr = nodeConfig->fNodeName;
aTmpData->AppendLong( strlen( tmpStr ) );
aTmpData->AppendString( tmpStr );
} else
{
aTmpData->AppendShort( 0 );
}
aAttrData->AppendLong( aTmpData->GetLength() );
aAttrData->AppendBlock( aTmpData->GetData(), aTmpData->GetLength() );
aTmpData->Clear();
}
if ( (strcmp( pAttrName, kDSAttributesAll ) == 0) ||
(strcmp( pAttrName, kDS1AttrReadOnlyNode ) == 0) )
{
aTmpData->Clear();
uiAttrCnt++;
aTmpData->AppendShort( sizeof( kDS1AttrReadOnlyNode )-1 );
aTmpData->AppendString( kDS1AttrReadOnlyNode );
if ( inData->fInAttrInfoOnly == false )
{
aTmpData->AppendShort( 1 );
if (nodeConfig == NULL)
{
aTmpData->AppendLong( sizeof("ReadOnly") - 1 );
aTmpData->AppendString( "ReadOnly" );
}
else
{
aTmpData->AppendLong( sizeof("ReadWrite") - 1 );
aTmpData->AppendString( "ReadWrite" );
}
}
else
{
aTmpData->AppendShort( 0 );
}
aAttrData->AppendLong( aTmpData->GetLength() );
aAttrData->AppendBlock( aTmpData->GetData(), aTmpData->GetLength() );
aTmpData->Clear();
}
if ( strcmp(pAttrName, kDSAttributesAll) == 0 || strcmp(pAttrName, kDSNAttrAuthMethod) == 0 )
{
aTmpData->Clear();
uiAttrCnt++;
aTmpData->AppendShort( sizeof( kDSNAttrAuthMethod )-1 );
aTmpData->AppendString( kDSNAttrAuthMethod );
if ( inData->fInAttrInfoOnly == false && nodeConfig != NULL )
{
aTmpData->AppendShort( 5 );
aTmpData->AppendLong( sizeof(kDSStdAuthCrypt) - 1 );
aTmpData->AppendString( kDSStdAuthCrypt );
aTmpData->AppendLong( sizeof(kDSStdAuthClearText) - 1 );
aTmpData->AppendString( kDSStdAuthClearText );
aTmpData->AppendLong( sizeof(kDSStdAuthNodeNativeClearTextOK) - 1 );
aTmpData->AppendString( kDSStdAuthNodeNativeClearTextOK );
aTmpData->AppendLong( sizeof(kDSStdAuthNodeNativeNoClearText) - 1 );
aTmpData->AppendString( kDSStdAuthNodeNativeNoClearText );
aTmpData->AppendLong( sizeof(kDSStdAuthKerberosTickets) - 1 );
aTmpData->AppendString( kDSStdAuthKerberosTickets );
} else
{
aTmpData->AppendShort( 0 );
}
aAttrData->AppendLong( aTmpData->GetLength() );
aAttrData->AppendBlock( aTmpData->GetData(), aTmpData->GetLength() );
aTmpData->Clear();
}
if ((strcmp( pAttrName, kDSAttributesAll ) == 0) ||
(strcmp( pAttrName, "dsAttrTypeStandard:AccountName" ) == 0) )
{
aTmpData->Clear();
uiAttrCnt++;
aTmpData->AppendShort( sizeof( "dsAttrTypeStandard:AccountName" )-1 );
aTmpData->AppendString( "dsAttrTypeStandard:AccountName" );
if ( inData->fInAttrInfoOnly == false )
{
aTmpData->AppendShort( 1 );
if ( DSIsStringEmpty(pContext->fLDAPConnection->fLDAPUsername) == false )
{
aTmpData->AppendLong( strlen(pContext->fLDAPConnection->fLDAPUsername) );
aTmpData->AppendString( pContext->fLDAPConnection->fLDAPUsername );
}
else
{
aTmpData->AppendLong( sizeof("No Account Name") - 1 );
aTmpData->AppendString( "No Account Name" );
}
} else
{
aTmpData->AppendShort( 0 );
}
aAttrData->AppendLong( aTmpData->GetLength() );
aAttrData->AppendBlock( aTmpData->GetData(), aTmpData->GetLength() );
aTmpData->Clear();
}
if ( strcmp( pAttrName, kDSNAttrDefaultLDAPPaths ) == 0 )
{
aTmpData->Clear();
uiAttrCnt++;
aTmpData->AppendShort( sizeof( kDSNAttrDefaultLDAPPaths )-1 );
aTmpData->AppendString( kDSNAttrDefaultLDAPPaths );
if ( inData->fInAttrInfoOnly == false )
{
char **defaultLDAPNodes = nil;
UInt32 aDefaultLDAPNodeCount = 0;
defaultLDAPNodes = fConfigFromXML->GetDHCPBasedLDAPNodes( &aDefaultLDAPNodeCount );
aTmpData->AppendShort( aDefaultLDAPNodeCount );
if ( (aDefaultLDAPNodeCount > 0) && (defaultLDAPNodes != nil) )
{
int listIndex = 0;
for (listIndex=0; defaultLDAPNodes[listIndex] != nil; listIndex++)
{
aTmpData->AppendLong( strlen( defaultLDAPNodes[listIndex] ) );
aTmpData->AppendString( defaultLDAPNodes[listIndex] );
}
}
DSFreeStringList(defaultLDAPNodes);
} else
{
aTmpData->AppendShort( 0 );
}
aAttrData->AppendLong( aTmpData->GetLength() );
aAttrData->AppendBlock( aTmpData->GetData(), aTmpData->GetLength() );
aTmpData->Clear();
}
if ((strcmp( pAttrName, kDSAttributesAll ) == 0) ||
(strcmp( pAttrName, kDS1AttrDistinguishedName ) == 0) )
{
aTmpData->Clear();
uiAttrCnt++;
aTmpData->AppendShort( sizeof( kDS1AttrDistinguishedName )-1 );
aTmpData->AppendString( kDS1AttrDistinguishedName );
if ( inData->fInAttrInfoOnly == false )
{
char *tmpStr;
if ( nodeConfig != NULL && (tmpStr = nodeConfig->CopyUIName()) != NULL )
{
aTmpData->AppendShort( 1 );
aTmpData->AppendLong( strlen( tmpStr ) );
aTmpData->AppendString( tmpStr );
DSFree( tmpStr );
}
else
{
aTmpData->AppendShort( 0 );
}
} else
{
aTmpData->AppendShort( 0 );
}
aAttrData->AppendLong( aTmpData->GetLength() );
aAttrData->AppendBlock( aTmpData->GetData(), aTmpData->GetLength() );
aTmpData->Clear();
}
if ( nodeConfig != NULL &&
((strcmp( pAttrName, kDSAttributesAll ) == 0) || (strcmp( pAttrName, kDSNAttrRecordType ) == 0)) )
{
CFDictionaryRef cfNormalizedMap = nodeConfig->CopyNormalizedMappings();
if ( cfNormalizedMap != NULL )
{
aTmpData->Clear();
uiAttrCnt++;
aTmpData->AppendShort( sizeof( kDSNAttrRecordType )-1 );
aTmpData->AppendString( kDSNAttrRecordType );
if ( inData->fInAttrInfoOnly == false )
{
CFIndex valueCount = CFDictionaryGetCount( cfNormalizedMap );
aTmpData->AppendShort( valueCount );
if( valueCount != 0 )
{
CFStringRef *keys = (CFStringRef *)calloc( valueCount, sizeof(CFStringRef) );
CFDictionaryGetKeysAndValues( cfNormalizedMap, (const void **)keys, NULL );
for ( CFIndex i = 0; i < valueCount; i++ )
{
char tempBuffer[1024];
CFStringGetCString( keys[i], tempBuffer, 1024, kCFStringEncodingUTF8 );
aTmpData->AppendLong( strlen( tempBuffer ) );
aTmpData->AppendString( tempBuffer );
}
DSFree( keys );
}
}
else
{
aTmpData->AppendShort( 0 );
}
aAttrData->AppendLong( aTmpData->GetLength() );
aAttrData->AppendBlock( aTmpData->GetData(), aTmpData->GetLength() );
aTmpData->Clear();
DSCFRelease( cfNormalizedMap );
}
}
if ( nodeConfig != NULL &&
(strcmp(pAttrName, kDSAttributesAll) == 0 || strcmp(pAttrName, "dsAttrTypeStandard:TrustInformation") == 0) )
{
aTmpData->Clear();
uiAttrCnt++;
aTmpData->AppendShort( sizeof( "dsAttrTypeStandard:TrustInformation" )-1 );
aTmpData->AppendString( "dsAttrTypeStandard:TrustInformation" );
if ( inData->fInAttrInfoOnly == false )
{
bool bAuthenticated = nodeConfig->fSecureUse;
bool bAnonymous = (bAuthenticated ? false : true); bool bFullTrust = false;
bool bPartialTrust = false;
bool bDHCP = nodeConfig->fDHCPLDAPServer;
bool bEncryption = (nodeConfig->fIsSSL || (nodeConfig->fSecurityLevel & kSecPacketEncryption));
if( bAuthenticated )
{
bFullTrust = ((nodeConfig->fSecurityLevel & (kSecManInMiddle | kSecPacketSigning)) == (kSecManInMiddle | kSecPacketSigning));
if( bFullTrust == false )
{
bPartialTrust = ((nodeConfig->fSecurityLevel & kSecManInMiddle) == kSecManInMiddle);
}
}
aTmpData->AppendShort( bAuthenticated + bAnonymous + bFullTrust + bPartialTrust + bDHCP + bEncryption );
if( bAuthenticated )
{
aTmpData->AppendLong( sizeof( "Authenticated" )-1 );
aTmpData->AppendString( "Authenticated" );
}
else if( bAnonymous )
{
aTmpData->AppendLong( sizeof( "Anonymous" )-1 );
aTmpData->AppendString( "Anonymous" );
}
if( bFullTrust )
{
aTmpData->AppendLong( sizeof( "FullTrust" )-1 );
aTmpData->AppendString( "FullTrust" );
}
else if( bPartialTrust )
{
aTmpData->AppendLong( sizeof( "PartialTrust" )-1 );
aTmpData->AppendString( "PartialTrust" );
}
if( bEncryption )
{
aTmpData->AppendLong( sizeof( "Encryption" )-1 );
aTmpData->AppendString( "Encryption" );
}
if( bDHCP )
{
aTmpData->AppendLong( sizeof( "DHCP" )-1 );
aTmpData->AppendString( "DHCP" );
}
}
else
{
aTmpData->AppendShort( 0 );
}
aAttrData->AppendLong( aTmpData->GetLength() );
aAttrData->AppendBlock( aTmpData->GetData(), aTmpData->GetLength() );
aTmpData->Clear();
}
if ( nodeConfig != NULL &&
(strcmp(pAttrName, kDSAttributesAll) == 0 || strcmp(pAttrName, kDS1AttrLDAPSearchBaseSuffix) == 0) )
{
aTmpData->Clear();
uiAttrCnt++;
aTmpData->AppendShort( sizeof( kDS1AttrLDAPSearchBaseSuffix )-1 );
aTmpData->AppendString( kDS1AttrLDAPSearchBaseSuffix );
if ( inData->fInAttrInfoOnly == false )
{
char *tmpStr = nodeConfig->CopyMapSearchBase();
if ( tmpStr != NULL )
{
aTmpData->AppendShort( 1 );
aTmpData->AppendLong( strlen(tmpStr) );
aTmpData->AppendString( tmpStr );
}
else
{
aTmpData->AppendShort( 0 );
}
DSFree( tmpStr );
} else
{
aTmpData->AppendShort( 0 );
}
aAttrData->AppendLong( aTmpData->GetLength() );
aAttrData->AppendBlock( aTmpData->GetData(), aTmpData->GetLength() );
aTmpData->Clear();
}
if ( pContext->fLDAPConnection != NULL &&
(strcmp(pAttrName, kDSAttributesAll) == 0 || strcmp(pAttrName, "dsAttrTypeStandard:ServerConnection") == 0) )
{
aTmpData->Clear();
uiAttrCnt++;
aTmpData->AppendShort( sizeof( "dsAttrTypeStandard:ServerConnection" )-1 );
aTmpData->AppendString( "dsAttrTypeStandard:ServerConnection" );
if ( inData->fInAttrInfoOnly == false )
{
char *tmpStr = pContext->fLDAPConnection->CopyReplicaIPAddress();
if ( tmpStr != NULL )
{
aTmpData->AppendShort( 1 );
aTmpData->AppendLong( strlen(tmpStr) );
aTmpData->AppendString( tmpStr );
}
else
{
aTmpData->AppendShort( 0 );
}
DSFree( tmpStr );
} else
{
aTmpData->AppendShort( 0 );
}
aAttrData->AppendLong( aTmpData->GetLength() );
aAttrData->AppendBlock( aTmpData->GetData(), aTmpData->GetLength() );
aTmpData->Clear();
}
}
aRecData->AppendShort( uiAttrCnt );
if (uiAttrCnt > 0)
{
aRecData->AppendBlock( aAttrData->GetData(), aAttrData->GetLength() );
}
outBuff.AddData( aRecData->GetData(), aRecData->GetLength() );
inData->fOutAttrInfoCount = uiAttrCnt;
pData = outBuff.GetDataBlock( 1, &uiOffset );
if ( pData != nil )
{
pAttrContext = new sLDAPContextData( *pContext );
if ( pAttrContext == nil ) throw( eMemoryAllocError );
pAttrContext->offset = uiOffset + 60;
gLDAPContextTable->AddObjectForRefNum( inData->fOutAttrListRef, pAttrContext );
DSRelease( pAttrContext );
}
else
{
siResult = eDSBufferTooSmall;
}
}
catch ( tDirStatus err )
{
siResult = err;
}
if ( inAttrList != nil )
{
delete( inAttrList );
inAttrList = nil;
}
if ( aRecData != nil )
{
delete( aRecData );
aRecData = nil;
}
if ( aAttrData != nil )
{
delete( aAttrData );
aAttrData = nil;
}
if ( aTmpData != nil )
{
delete( aTmpData );
aTmpData = nil;
}
DSRelease( pContext );
return( siResult );
}
tDirStatus CLDAPv3Plugin::OpenRecord ( sOpenRecord *inData )
{
tDirStatus siResult = eDSNoErr;
tDataNodePtr pRecName = nil;
tDataNodePtr pRecType = nil;
char *pLDAPSearchBase = nil;
sLDAPContextData *pContext = nil;
sLDAPContextData *pRecContext = nil;
char *queryFilter = nil;
LDAPMessage *result = nil;
int numRecTypes = 1;
bool bResultFound = false;
bool bOCANDGroup = false;
CFArrayRef OCSearchList = nil;
ber_int_t scope = LDAP_SCOPE_SUBTREE;
tDirStatus searchResult = eDSNoErr;
char **attrs = nil;
char *ldapDN = NULL;
pRecType = inData->fInRecType;
if ( pRecType == nil ) return( eDSNullRecType );
pRecName = inData->fInRecName;
if ( pRecName == nil ) return( eDSNullRecName );
if (pRecName->fBufferLength == 0) return( eDSEmptyRecordNameList );
if (pRecType->fBufferLength == 0) return( eDSEmptyRecordTypeList );
pContext = gLDAPContextTable->GetObjectForRefNum( inData->fInNodeRef );
if ( pContext == nil ) return eDSBadContextData;
if ( pContext->fLDAPConnection->ConnectionStatus() != kConnectionSafe ) return eDSCannotAccessSession;
pLDAPSearchBase = MapRecToSearchBase( pContext, (const char *)(pRecType->fBufferData), numRecTypes, &bOCANDGroup, &OCSearchList, &scope );
if ( pLDAPSearchBase == nil ) return eDSInvalidRecordType;
attrs = MapAttrToLDAPTypeArray( pContext, pRecType->fBufferData, kDSNAttrRecordName );
try
{
while ( (pLDAPSearchBase != nil) && (!bResultFound) )
{
queryFilter = BuildLDAPQueryFilter( pContext,
(char *)kDSNAttrRecordName,
pRecName->fBufferData,
eDSExact,
false,
(const char *)(pRecType->fBufferData),
pLDAPSearchBase,
bOCANDGroup,
OCSearchList );
if ( queryFilter == nil ) throw( eDSNoStdMappingAvailable );
searchResult = DSRetrieveSynchronous( pLDAPSearchBase, attrs, pContext, scope, queryFilter, &result, &ldapDN );
if ( searchResult == eDSNoErr )
break;
DSFreeString( queryFilter );
DSFreeString( pLDAPSearchBase );
DSCFRelease( OCSearchList );
numRecTypes++;
bOCANDGroup = false;
pLDAPSearchBase = MapRecToSearchBase( pContext, (const char *)(pRecType->fBufferData), numRecTypes, &bOCANDGroup,
&OCSearchList, &scope );
}
if ( searchResult == eDSNoErr )
{
pRecContext = new sLDAPContextData( *pContext );
if ( pRecContext == nil ) throw( eMemoryAllocError );
pRecContext->fType = 2;
if (pRecType->fBufferData != nil)
pRecContext->fOpenRecordType = strdup( pRecType->fBufferData );
pRecContext->fOpenRecordName = GetRecordName( pRecContext->fOpenRecordType, result, pContext, siResult );
if (pRecContext->fOpenRecordName == NULL)
pRecContext->fOpenRecordName = strdup( pRecName->fBufferData );
pRecContext->fOpenRecordDN = ldapDN;
ldapDN = NULL;
gLDAPContextTable->AddObjectForRefNum( inData->fOutRecRef, pRecContext );
DSRelease( pRecContext );
}
siResult = searchResult;
}
catch ( tDirStatus err )
{
siResult = err;
}
if ( result != nil )
{
ldap_msgfree( result );
result = nil;
}
DSCFRelease( OCSearchList );
DSFreeString( ldapDN );
DSFreeString( pLDAPSearchBase );
DSFreeString( queryFilter );
DSFreeStringList( attrs );
DSRelease( pContext );
return( siResult );
}
tDirStatus CLDAPv3Plugin::CloseRecord ( sCloseRecord *inData )
{
tDirStatus siResult = eDSNoErr;
sLDAPContextData *pContext = nil;
try
{
pContext = gLDAPContextTable->GetObjectForRefNum( inData->fInRecRef );
if ( pContext == nil ) throw( eDSBadContextData );
if ( pContext->fLDAPConnection )
{
if ( strcmp(pContext->fOpenRecordType, kDSStdRecordTypeUsers) == 0 )
dsNotifyUpdatedRecord( "LDAPv3", pContext->fLDAPConnection->fNodeConfig->fNodeName, "users" );
else if ( strcmp(pContext->fOpenRecordType, kDSStdRecordTypeGroups) == 0 )
dsNotifyUpdatedRecord( "LDAPv3", pContext->fLDAPConnection->fNodeConfig->fNodeName, "groups" );
else if ( strcmp(pContext->fOpenRecordType, kDSStdRecordTypeComputers) == 0 )
dsNotifyUpdatedRecord( "LDAPv3", pContext->fLDAPConnection->fNodeConfig->fNodeName, "computers" );
}
gLDAPContextTable->RemoveRefNum( inData->fInRecRef );
DSRelease( pContext );
}
catch ( tDirStatus err )
{
siResult = err;
}
return( siResult );
}
tDirStatus CLDAPv3Plugin::FlushRecord ( sFlushRecord *inData )
{
tDirStatus siResult = eDSNoErr;
sLDAPContextData *pContext = gLDAPContextTable->GetObjectForRefNum( inData->fInRecRef );
if ( pContext == nil ) return eDSBadContextData;
DSRelease( pContext );
return( siResult );
}
tDirStatus CLDAPv3Plugin::DeleteRecord ( sDeleteRecord *inData )
{
return DeleteRecord( inData, false );
}
tDirStatus CLDAPv3Plugin::DeleteRecord ( sDeleteRecord *inData, bool inDeleteCredentials )
{
tDirStatus siResult = eDSNoErr;
sLDAPContextData *pRecContext = nil;
char *pUserID = NULL;
char *pAdminID = NULL;
char *pServerAddress = NULL;
pRecContext = gLDAPContextTable->GetObjectForRefNum( inData->fInRecRef );
if ( pRecContext == nil )
return( eDSBadContextData );
CLDAPNodeConfig *nodeConfig = pRecContext->fLDAPConnection->fNodeConfig;
if ( pRecContext->fOpenRecordDN == nil )
{
DSRelease( pRecContext );
return( eDSNullRecName );
}
if ( strcmp(pRecContext->fOpenRecordType, kDSStdRecordTypeUsers) == 0 ||
strcmp(pRecContext->fOpenRecordType, kDSStdRecordTypeComputers) == 0 )
inDeleteCredentials = true;
if ( inDeleteCredentials && pRecContext->fOpenRecordName != NULL && pRecContext->fOpenRecordType != NULL &&
pRecContext->fLDAPConnection->fbAuthenticated && pRecContext->fLDAPConnection->fLDAPUsername )
{
char **dn = ldap_explode_dn( pRecContext->fLDAPConnection->fLDAPUsername, 1 );
pUserID = GetPWSIDforRecord( pRecContext, pRecContext->fOpenRecordName, pRecContext->fOpenRecordType );
if ( pUserID != NULL )
{
char *pComma = strchr( pUserID, ',' );
if ( pComma != NULL )
{
*pComma = '\0';
}
}
pAdminID = GetPWSIDforRecord( pRecContext, dn[0], kDSStdRecordTypeUsers );
if ( pAdminID != NULL )
{
pServerAddress = strchr( pAdminID, ':' );
if ( pServerAddress != NULL )
{
pServerAddress++; }
}
ldap_value_free( dn );
dn = NULL;
}
tDirStatus error = eDSNoErr;
if ( pUserID != NULL && pAdminID != NULL && pServerAddress != NULL )
{
tDirReference dsRef = 0;
tDirNodeReference nodeRef = 0;
error = dsOpenDirService( &dsRef );
if ( error == eDSNoErr )
{
char *nodeName = (char *)calloc(1,strlen(pServerAddress)+sizeof("/PasswordServer/")+1);
if( nodeName != NULL )
{
sprintf( nodeName, "/PasswordServer/%s", pServerAddress );
error = (tDirStatus)PWOpenDirNode( dsRef, nodeName, &nodeRef );
free( nodeName );
nodeName = NULL;
}
else
{
error = eMemoryAllocError;
}
}
if ( error == eDSNoErr )
{
int iUserIDLen = strlen( pUserID ) + 1; int iAdminIDLen = strlen( pAdminID ) + 1; int iPassLen = strlen( pRecContext->fLDAPConnection->fLDAPPassword ) + 1;
tDataBufferPtr pAuthMethod = dsDataNodeAllocateString( nodeRef, kDSStdAuthDeleteUser );
tDataBufferPtr pStepData = dsDataBufferAllocatePriv( sizeof(SInt32) + iAdminIDLen +
sizeof(SInt32) + iPassLen +
sizeof(SInt32) + iUserIDLen );
tDataBufferPtr pStepDataResp = dsDataBufferAllocatePriv( 1024 );
siResult = dsFillAuthBuffer(
pStepData, 3,
iAdminIDLen, pAdminID,
iPassLen, pRecContext->fLDAPConnection->fLDAPPassword,
iUserIDLen, pUserID );
if ( siResult == eDSNoErr )
{
siResult = dsDoDirNodeAuth( nodeRef, pAuthMethod, true, pStepData, pStepDataResp, NULL );
}
DbgLog( kLogPlugin, "CLDAPv3Plugin: Attempt to delete PWS ID associated with record returned status %d", siResult );
dsDataNodeDeAllocate( nodeRef, pAuthMethod );
dsDataNodeDeAllocate( nodeRef, pStepData );
dsDataNodeDeAllocate( nodeRef, pStepDataResp );
}
if ( nodeRef )
dsCloseDirNode( nodeRef );
if ( dsRef )
dsCloseDirService( dsRef );
}
if ( error == eDSNoErr && (siResult == eDSNoErr || siResult == eDSAuthFailed) )
{
LDAP *aHost = pRecContext->fLDAPConnection->LockLDAPSession();
if ( aHost != NULL )
{
if ( ldap_delete_s(aHost, pRecContext->fOpenRecordDN) != LDAP_SUCCESS )
siResult = eDSPermissionError;
pRecContext->fLDAPConnection->UnlockLDAPSession( aHost, false );
}
if ( strcmp(pRecContext->fOpenRecordType, kDSStdRecordTypeUsers) == 0 )
dsNotifyUpdatedRecord( "LDAPv3", nodeConfig->fNodeName, "users" );
else if ( strcmp(pRecContext->fOpenRecordType, kDSStdRecordTypeGroups) == 0 )
dsNotifyUpdatedRecord( "LDAPv3", nodeConfig->fNodeName, "groups" );
else if ( strcmp(pRecContext->fOpenRecordType, kDSStdRecordTypeComputers) == 0 )
dsNotifyUpdatedRecord( "LDAPv3", nodeConfig->fNodeName, "computers" );
gLDAPContextTable->RemoveRefNum( inData->fInRecRef );
}
DSRelease( pRecContext );
DSFreeString( pAdminID );
DSFreeString( pUserID );
return( siResult );
}
bool CLDAPv3Plugin::IsConfigRecordModify( tRecordReference inRecRef )
{
char *recTypeStr = NULL;
bool result = false;
recTypeStr = GetRecordTypeFromRef( inRecRef );
if ( strcmp(recTypeStr, kDSStdRecordTypeConfig) == 0 )
result = true;
DSFree( recTypeStr );
return result;
}
void CLDAPv3Plugin::IncrementChangeSeqNumber( void )
{
struct stat sb;
if ( lstat(kLDAPReplicaHintFilePath, &sb) == 0 )
unlink( kLDAPReplicaHintFilePath );
if ( ++gConfigRecordChangeSeqNumber < 0 )
{
gPWSReplicaListLoadedSeqNumber = 0;
gConfigRecordChangeSeqNumber = 1;
}
}
tDirStatus CLDAPv3Plugin::AddAttribute( sAddAttribute *inData, const char *inRecTypeStr )
{
tDirStatus siResult = eDSNoErr;
siResult = AddValue( inData->fInRecRef, inData->fInNewAttr, inData->fInFirstAttrValue );
if ( siResult == eDSNoErr && strcmp(inRecTypeStr, kDSStdRecordTypeConfig) == 0 )
IncrementChangeSeqNumber();
return( siResult );
}
tDirStatus CLDAPv3Plugin::AddAttributeValue( sAddAttributeValue *inData, const char *inRecTypeStr )
{
tDirStatus siResult = eDSNoErr;
siResult = AddValue( inData->fInRecRef, inData->fInAttrType, inData->fInAttrValue );
if ( siResult == eDSNoErr && strcmp(inRecTypeStr, kDSStdRecordTypeConfig) == 0 )
IncrementChangeSeqNumber();
return( siResult );
}
tDirStatus CLDAPv3Plugin::SetAttributes ( UInt32 inRecRef, CFDictionaryRef inDict )
{
tDirStatus siResult = eDSNoErr;
char *attrTypeStr = nil;
char *attrTypeLDAPStr = nil;
sLDAPContextData *pRecContext = nil;
UInt32 attrCount = 0;
UInt32 attrIndex = 0;
UInt32 valCount = 0;
UInt32 valIndex = 0;
struct berval **newValues = nil;
LDAPMod *mods[128]; int ldapReturnCode = 0;
char *attrValue = nil;
UInt32 attrLength = 0;
LDAP *aHost = nil;
UInt32 callocLength = 0;
bool bGotIt = false;
CFStringRef keyCFString = NULL;
try
{
pRecContext = gLDAPContextTable->GetObjectForRefNum( inRecRef );
if ( pRecContext == nil ) throw( eDSBadContextData );
if ( pRecContext->fOpenRecordDN == nil ) throw( eDSNullRecName );
if ( CFGetTypeID(inDict) != CFDictionaryGetTypeID() ) throw( eDSInvalidBuffFormat );
if ( IsConfigRecordModify(inRecRef) )
IncrementChangeSeqNumber();
for (UInt32 modsIndex=0; modsIndex < 128; modsIndex++)
{
mods[modsIndex] = NULL;
}
attrCount = (UInt32) CFDictionaryGetCount(inDict);
char** keys = (char**)calloc( attrCount + 1, sizeof( void* ) );
CFDictionaryGetKeysAndValues( inDict, (const void**)keys, NULL );
attrIndex = 0;
for( UInt32 keyIndex = 0; keyIndex < attrCount; keyIndex++ )
{
keyCFString = NULL;
if ( !(CFGetTypeID((CFStringRef)keys[keyIndex]) == CFStringGetTypeID() ) )
{
continue; }
else
{
keyCFString = (CFStringRef)keys[keyIndex];
}
attrTypeStr = (char *)CFStringGetCStringPtr( keyCFString, kCFStringEncodingUTF8 );
if (attrTypeStr == nil)
{
callocLength = (UInt32) CFStringGetMaximumSizeForEncoding(CFStringGetLength(keyCFString), kCFStringEncodingUTF8) + 1;
attrTypeStr = (char *)calloc( 1, callocLength );
if ( attrTypeStr == nil ) throw( eMemoryError );
bGotIt = CFStringGetCString( keyCFString, attrTypeStr, callocLength, kCFStringEncodingUTF8 );
if (bGotIt == false) throw( eMemoryError );
}
attrTypeLDAPStr = MapAttrToLDAPType( pRecContext, (const char *)(pRecContext->fOpenRecordType), attrTypeStr, 1, true );
if ( attrTypeLDAPStr == nil ) throw( eDSInvalidAttributeType );
CFArrayRef valuesCFArray = (CFArrayRef)CFDictionaryGetValue( inDict, keyCFString );
if ( !(CFGetTypeID(valuesCFArray) == CFArrayGetTypeID() ) )
{
if (bGotIt)
{
DSFreeString(attrTypeStr);
}
continue; }
valCount = (UInt32) CFArrayGetCount( valuesCFArray );
newValues = (struct berval**) calloc(1, (valCount + 1) *sizeof(struct berval *) );
valIndex = 0;
for (UInt32 i = 0; i < valCount; i++ ) {
CFTypeRef valueCFType = CFArrayGetValueAtIndex( valuesCFArray, (CFIndex)i );
if ( CFGetTypeID(valueCFType) == CFStringGetTypeID() )
{
CFStringRef valueCFString = (CFStringRef)valueCFType;
callocLength = (UInt32) CFStringGetMaximumSizeForEncoding(CFStringGetLength(valueCFString), kCFStringEncodingUTF8) + 1;
attrValue = (char *)calloc( 1, callocLength );
if ( attrValue == nil ) throw( eMemoryError );
bool bGotValue = CFStringGetCString( valueCFString, attrValue, callocLength, kCFStringEncodingUTF8 );
if (bGotValue == false) throw( eMemoryError );
attrLength = strlen(attrValue);
newValues[valIndex] = (struct berval*) calloc(1, sizeof(struct berval) );
newValues[valIndex]->bv_val = attrValue;
newValues[valIndex]->bv_len = attrLength;
valIndex++;
attrValue = nil;
}
else if ( CFGetTypeID(valueCFType) == CFDataGetTypeID() )
{
CFDataRef valueCFData = (CFDataRef)valueCFType;
attrLength = (UInt32) CFDataGetLength(valueCFData);
attrValue = (char *)calloc( 1, attrLength + 1 );
if ( attrValue == nil ) throw( eMemoryError );
CFDataGetBytes( valueCFData, CFRangeMake(0,attrLength), (UInt8*)attrValue );
newValues[valIndex] = (struct berval*) calloc(1, sizeof(struct berval) );
newValues[valIndex]->bv_val = attrValue;
newValues[valIndex]->bv_len = attrLength;
valIndex++;
attrValue = nil;
}
}
if (valIndex > 0) {
mods[attrIndex] = (LDAPMod *) calloc( 1, sizeof(LDAPMod) );
mods[attrIndex]->mod_op = LDAP_MOD_REPLACE | LDAP_MOD_BVALUES;
mods[attrIndex]->mod_type = attrTypeLDAPStr;
mods[attrIndex]->mod_bvalues= newValues;
attrTypeLDAPStr = nil;
attrIndex++;
if (attrIndex == 127) {
if (bGotIt)
{
DSFreeString(attrTypeStr);
}
break; }
}
if (bGotIt)
{
DSFreeString(attrTypeStr);
}
}
aHost = pRecContext->fLDAPConnection->LockLDAPSession();
if (aHost != NULL)
{
ldapReturnCode = ldap_modify_s( aHost, pRecContext->fOpenRecordDN, mods);
pRecContext->fLDAPConnection->UnlockLDAPSession( aHost, false );
}
else
{
ldapReturnCode = LDAP_LOCAL_ERROR;
}
if ( ldapReturnCode != LDAP_SUCCESS )
{
siResult = MapLDAPWriteErrorToDS( ldapReturnCode, eDSAttributeNotFound );
}
for (UInt32 modsIndex=0; ((modsIndex < 128) && (mods[modsIndex] != NULL)); modsIndex++)
{
DSFreeString(mods[modsIndex]->mod_type)
newValues = mods[modsIndex]->mod_bvalues;
if (newValues != NULL)
{
ldap_value_free_len(newValues);
newValues = NULL;
}
mods[modsIndex] = NULL;
}
}
catch ( tDirStatus err )
{
siResult = err;
}
DSRelease( pRecContext );
DSFreeString( attrTypeLDAPStr );
return( siResult );
}
tDirStatus CLDAPv3Plugin::RemoveAttribute ( sRemoveAttribute *inData, const char *inRecTypeStr )
{
tDirStatus siResult = eDSNoErr;
sLDAPContextData *pRecContext = nil;
int numAttributes = 1;
char *pLDAPAttrType = nil;
LDAPMod *mods[2];
int ldapReturnCode = 0;
try
{
pRecContext = gLDAPContextTable->GetObjectForRefNum( inData->fInRecRef );
if ( pRecContext == nil ) throw( eDSBadContextData );
if ( pRecContext->fOpenRecordDN == nil ) throw( eDSNullRecName );
if ( inData->fInAttribute->fBufferData == nil ) throw( eDSNullAttributeType );
numAttributes = 1;
pLDAPAttrType = MapAttrToLDAPType( pRecContext, (const char *)(pRecContext->fOpenRecordType), inData->fInAttribute->fBufferData,
numAttributes, true );
if ( pLDAPAttrType == nil ) throw( eDSInvalidAttributeType );
if ( strcmp(inRecTypeStr, kDSStdRecordTypeConfig) == 0 )
IncrementChangeSeqNumber();
mods[1] = NULL;
while ( pLDAPAttrType != nil )
{
{
LDAPMod mod;
mod.mod_op = LDAP_MOD_DELETE;
mod.mod_type = pLDAPAttrType;
mod.mod_values = NULL;
mods[0] = &mod;
LDAP *aHost = pRecContext->fLDAPConnection->LockLDAPSession();
if (aHost != NULL)
{
ldapReturnCode = ldap_modify_s( aHost, pRecContext->fOpenRecordDN, mods);
pRecContext->fLDAPConnection->UnlockLDAPSession( aHost, false );
}
else
{
ldapReturnCode = LDAP_LOCAL_ERROR;
}
if ( ( ldapReturnCode == LDAP_NO_SUCH_ATTRIBUTE ) || ( ldapReturnCode == LDAP_UNDEFINED_TYPE ) )
{
siResult = eDSNoErr;
}
else if ( ldapReturnCode != LDAP_SUCCESS )
{
siResult = MapLDAPWriteErrorToDS( ldapReturnCode, eDSAttributeNotFound );
}
}
DSFreeString(pLDAPAttrType);
numAttributes++;
pLDAPAttrType = MapAttrToLDAPType( pRecContext, (const char *)(pRecContext->fOpenRecordType),
inData->fInAttribute->fBufferData, numAttributes, true );
}
}
catch ( tDirStatus err )
{
siResult = err;
}
DSRelease( pRecContext );
return( siResult );
}
tDirStatus CLDAPv3Plugin::AddValue ( UInt32 inRecRef, tDataNodePtr inAttrType, tDataNodePtr inAttrValue )
{
tDirStatus siResult = eDSNoErr;
sLDAPContextData *pRecContext = nil;
char *attrValue = nil;
UInt32 attrLength = 0;
struct berval bval;
struct berval *bvals[2];
int numAttributes = 1;
char *pLDAPAttrType = nil;
LDAPMod *mods[2];
int ldapReturnCode = 0;
try
{
pRecContext = gLDAPContextTable->GetObjectForRefNum( inRecRef );
if ( pRecContext == nil ) throw( eDSBadContextData );
if ( pRecContext->fOpenRecordDN == nil ) throw( eDSNullRecName );
if ( inAttrType->fBufferData == nil ) throw( eDSNullAttributeType );
if ( (inAttrValue == nil) || (inAttrValue->fBufferLength < 1) )
{
throw( eDSEmptyAttributeValue );
}
else
{
attrLength = inAttrValue->fBufferLength;
attrValue = (char *) calloc(1, 1 + attrLength);
memcpy(attrValue, inAttrValue->fBufferData, attrLength);
}
if ( IsConfigRecordModify(inRecRef) )
IncrementChangeSeqNumber();
bval.bv_val = attrValue;
bval.bv_len = attrLength;
bvals[0] = &bval;
bvals[1] = NULL;
numAttributes = 1;
pLDAPAttrType = MapAttrToLDAPType( pRecContext, (const char *)(pRecContext->fOpenRecordType), inAttrType->fBufferData, numAttributes, true );
if ( pLDAPAttrType == nil ) throw( eDSInvalidAttributeType );
mods[1] = NULL;
if ( pLDAPAttrType != nil )
{
{
LDAPMod mod;
mod.mod_op = LDAP_MOD_ADD | LDAP_MOD_BVALUES;
mod.mod_type = pLDAPAttrType;
mod.mod_bvalues = bvals;
mods[0] = &mod;
LDAP *aHost = pRecContext->fLDAPConnection->LockLDAPSession();
if (aHost != NULL)
{
ldapReturnCode = ldap_modify_s( aHost, pRecContext->fOpenRecordDN, mods);
pRecContext->fLDAPConnection->UnlockLDAPSession( aHost, false );
}
else
{
ldapReturnCode = LDAP_LOCAL_ERROR;
}
if ( ldapReturnCode != LDAP_SUCCESS )
{
siResult = MapLDAPWriteErrorToDS( ldapReturnCode, eDSAttributeNotFound );
}
}
if (pLDAPAttrType != nil)
{
delete (pLDAPAttrType);
pLDAPAttrType = nil;
}
} }
catch ( tDirStatus err )
{
siResult = err;
}
DSFree(attrValue);
DSRelease( pRecContext );
return( siResult );
}
tDirStatus CLDAPv3Plugin::SetRecordName ( sSetRecordName *inData )
{
tDirStatus siResult = eDSNoErr;
sLDAPContextData *pRecContext = nil;
char *pLDAPAttrType = nil;
int ldapReturnCode = 0;
tDataNodePtr pRecName = nil;
char *ldapRDNString = nil;
UInt32 ldapRDNLength = 0;
try
{
pRecContext = gLDAPContextTable->GetObjectForRefNum( inData->fInRecRef );
if ( pRecContext == nil ) throw( eDSBadContextData );
pRecName = inData->fInNewRecName;
if ( pRecName == nil ) throw( eDSNullRecName );
if (pRecName->fBufferLength == 0) throw( eDSEmptyRecordNameList );
pLDAPAttrType = MapAttrToLDAPType( pRecContext, (const char *)(pRecContext->fOpenRecordType), kDSNAttrRecordName, 1, true );
if ( pLDAPAttrType == nil ) throw( eDSInvalidAttributeType );
ldapRDNLength = strlen(pLDAPAttrType) + 1 + 2*pRecName->fBufferLength;
ldapRDNString = (char *)calloc(1, ldapRDNLength + 1);
strcpy(ldapRDNString,pLDAPAttrType);
strcat(ldapRDNString,"=");
char *escapedString = BuildEscapedRDN(pRecName->fBufferData);
strcat(ldapRDNString,escapedString);
DSFreeString(escapedString);
LDAP *aHost = pRecContext->fLDAPConnection->LockLDAPSession();
if (aHost != NULL)
{
ldapReturnCode = ldap_rename_s( aHost, pRecContext->fOpenRecordDN, ldapRDNString, NULL, 1, NULL, NULL);
pRecContext->fLDAPConnection->UnlockLDAPSession( aHost, false );
}
else
{
ldapReturnCode = LDAP_LOCAL_ERROR;
}
if ( ldapReturnCode == LDAP_ALREADY_EXISTS )
{
siResult = eDSNoErr; }
else if ( ldapReturnCode != LDAP_SUCCESS )
{
siResult = MapLDAPWriteErrorToDS( ldapReturnCode, eDSRecordNotFound );
}
else {
DSFreeString(pRecContext->fOpenRecordName);
pRecContext->fOpenRecordName = (char *)calloc(1, 1+strlen(pRecName->fBufferData));
strcpy( pRecContext->fOpenRecordName, pRecName->fBufferData );
char *newldapDN = nil;
char *pLDAPSearchBase = nil;
pLDAPSearchBase = MapRecToSearchBase( pRecContext, (const char *)(pRecContext->fOpenRecordType), 1, nil, nil, nil );
if (pLDAPSearchBase != nil)
{
newldapDN = (char *) calloc(1, 1 + strlen(ldapRDNString) + 2 + strlen(pLDAPSearchBase));
strcpy(newldapDN,ldapRDNString);
strcat(newldapDN,", ");
strcat(newldapDN,pLDAPSearchBase);
DSFreeString(pRecContext->fOpenRecordDN);
pRecContext->fOpenRecordDN = newldapDN;
DSFreeString(pLDAPSearchBase);
}
}
}
catch ( tDirStatus err )
{
siResult = err;
}
DSFreeString(pLDAPAttrType);
DSFreeString(ldapRDNString);
DSRelease( pRecContext );
return( siResult );
}
tDirStatus CLDAPv3Plugin::CreateRecord ( sCreateRecord *inData )
{
tDirStatus siResult = eDSNoErr;
sLDAPContextData *pContext = nil;
sLDAPContextData *pRecContext = nil;
char *pLDAPAttrType = nil;
LDAPMod *mods[128]; UInt32 modIndex = 0;
int ldapReturnCode = 0;
tDataNodePtr pRecType = nil;
tDataNodePtr pRecName = nil;
char *pLDAPSearchBase = nil;
char *ldapDNString = nil;
UInt32 ldapDNLength = 0;
UInt32 ocCount = 0;
UInt32 raCount = 0;
LDAPMod ocmod;
LDAPMod rnmod;
char **ocvals = nil;
char *rnvals[2];
char *ocString = nil;
listOfStrings objectClassList;
listOfStrings reqAttrsList;
char **needsValueMarker= nil;
bool bOCANDGroup = false;
CFArrayRef OCSearchList = nil;
char *tmpBuff = nil;
const CFIndex cfBuffSize = 1024;
int aOCSearchListCount = 0;
char *recName = NULL;
int recNameLen = 0;
char **aValues = NULL;
char **aMaps = NULL;
try
{
pContext = gLDAPContextTable->GetObjectForRefNum( inData->fInNodeRef );
if ( pContext == nil ) throw( eDSBadContextData );
CLDAPNodeConfig *nodeConfig = pContext->fLDAPConnection->fNodeConfig;
pRecType = inData->fInRecType;
if ( pRecType == nil ) throw( eDSNullRecType );
pRecName = inData->fInRecName;
if ( pRecName == nil ) throw( eDSNullRecName );
if (pRecName->fBufferLength == 0) throw( eDSEmptyRecordNameList );
if (pRecType->fBufferLength == 0) throw( eDSEmptyRecordTypeList );
recName = pRecName->fBufferData;
recNameLen = pRecName->fBufferLength;
pLDAPAttrType = MapAttrToLDAPType( pContext, (const char *)(pRecType->fBufferData), kDSNAttrRecordName, 1, true );
if ( pLDAPAttrType == nil ) throw( eDSInvalidAttributeType );
pLDAPSearchBase = MapRecToSearchBase( pContext, (const char *)(pRecType->fBufferData), 1, &bOCANDGroup, &OCSearchList, nil );
if ( pLDAPSearchBase == nil ) throw( eDSInvalidRecordType );
if (strcmp(pRecType->fBufferData, kDSStdRecordTypeAutomount) == 0)
{
char *names[2] = { recName, NULL };
UInt32 count = 0;
char *pMapRecType = MapRecToSearchBase( pContext, kDSStdRecordTypeAutomountMap, 1, NULL, NULL, NULL );
if (pMapRecType == NULL) throw( eDSInvalidRecordType );
char *pMapAttrType = MapAttrToLDAPType( pContext,kDSStdRecordTypeAutomountMap, kDSNAttrRecordName, 1, true );
if (pMapAttrType == NULL) throw( eDSInvalidRecordType );
siResult = CheckAutomountNames( kDSStdRecordTypeAutomount, names, &aValues, &aMaps, &count );
if (siResult != eDSNoErr || count == 0 || aMaps[0][0] == '\0') throw( eDSInvalidRecordName );
recName = aValues[0];
recNameLen = strlen( recName );
char *escRecName = BuildEscapedRDN( recName );
char *escMapname = BuildEscapedRDN( aMaps[0] );
ldapDNLength = strlen(pLDAPAttrType) + 1 + strlen(escRecName) + 2 + strlen(pMapAttrType) + 1 + strlen(escMapname) + 2 + strlen(pMapRecType) + 1;
ldapDNString = (char *)calloc(1, ldapDNLength);
snprintf( ldapDNString, ldapDNLength, "%s=%s, %s=%s, %s", pLDAPAttrType, escRecName, pMapAttrType, escMapname, pMapRecType );
DSFreeString( escRecName );
DSFreeString( escMapname );
DSFreeString( pMapAttrType );
DSFreeString( pMapRecType );
}
else
{
ldapDNLength = strlen(pLDAPAttrType) + 1 + 2*recNameLen + 2 + strlen(pLDAPSearchBase);
ldapDNString = (char *)calloc(1, ldapDNLength + 1);
strcpy(ldapDNString,pLDAPAttrType);
strcat(ldapDNString,"=");
char *escapedString = BuildEscapedRDN(recName);
strcat(ldapDNString,escapedString);
DSFreeString(escapedString);
strcat(ldapDNString,", ");
strcat(ldapDNString,pLDAPSearchBase);
}
rnvals[0] = recName;
rnvals[1] = NULL;
rnmod.mod_op = 0;
rnmod.mod_type = pLDAPAttrType;
rnmod.mod_values = rnvals;
if ( (pRecType->fBufferData != nil) && (pLDAPSearchBase != nil) )
{
if (strncmp(pRecType->fBufferData,kDSStdRecordTypePrefix,strlen(kDSStdRecordTypePrefix)) == 0)
{
if (OCSearchList != nil)
{
CFStringRef ocCFString = nil;
tmpBuff = (char *)calloc(1, cfBuffSize);
if (!bOCANDGroup)
{
if (CFArrayGetCount(OCSearchList) >= 1)
{
ocCFString = (CFStringRef)CFArrayGetValueAtIndex( OCSearchList, 0 );
}
if (ocCFString != NULL)
{
CFStringGetCString(ocCFString, tmpBuff, cfBuffSize, kCFStringEncodingUTF8);
string ourString(tmpBuff);
objectClassList.push_back(ourString);
}
}
else
{
aOCSearchListCount = CFArrayGetCount(OCSearchList);
for ( int iOCIndex = 0; iOCIndex < aOCSearchListCount; iOCIndex++ )
{
bzero(tmpBuff, cfBuffSize);
ocCFString = (CFStringRef)CFArrayGetValueAtIndex( OCSearchList, iOCIndex );
if (ocCFString != nil)
{
CFStringGetCString(ocCFString, tmpBuff, cfBuffSize, kCFStringEncodingUTF8);
string ourString(tmpBuff);
objectClassList.push_back(ourString);
}
} }
} } }
mods[0] = &rnmod;
for (UInt32 modsIndex=1; modsIndex < 128; modsIndex++)
{
mods[modsIndex] = NULL;
}
modIndex = 1;
if (OCSearchList != nil)
{
if ( nodeConfig != NULL )
nodeConfig->GetReqAttrListForObjectList( pContext->fLDAPConnection, objectClassList, reqAttrsList );
raCount = reqAttrsList.size();
ocCount = objectClassList.size();
ocString = strdup("objectClass");
ocmod.mod_op = 0;
ocmod.mod_type = ocString;
ocmod.mod_values = nil;
ocvals = (char **)calloc(1,(ocCount+1)*sizeof(char **));
UInt32 ocValIndex = 0;
for (listOfStringsCI iter = objectClassList.begin(); iter != objectClassList.end(); ++iter)
{
const char *aString = (*iter).c_str();
ocvals[ocValIndex] = (char *)aString; ocValIndex++;
}
ocvals[ocCount] = nil;
ocmod.mod_values = ocvals;
mods[1] = &ocmod;
modIndex = 2;
}
needsValueMarker = (char **)calloc(1,2*sizeof(char *));
needsValueMarker[0] = (char *) "99";
needsValueMarker[1] = NULL;
if (raCount != 0)
{
for (listOfStringsCI addIter = reqAttrsList.begin(); addIter != reqAttrsList.end(); ++addIter)
{
if (modIndex == 127)
{
break;
}
if ( (strcasecmp((*addIter).c_str(), pLDAPAttrType) != 0) || (strcasecmp("sAMAccountName", pLDAPAttrType) == 0) )
{
LDAPMod *aLDAPMod = (LDAPMod *)calloc(1,sizeof(LDAPMod));
aLDAPMod->mod_op = 0;
const char *aString = (*addIter).c_str();
aLDAPMod->mod_type = (char *)aString; aLDAPMod->mod_values = needsValueMarker; mods[modIndex] = aLDAPMod;
modIndex++;
}
}
}
mods[modIndex] = NULL;
LDAP *aHost = pContext->fLDAPConnection->LockLDAPSession();
if (aHost != NULL)
{
ldapReturnCode = ldap_add_ext_s( aHost, ldapDNString, mods, NULL, NULL);
pContext->fLDAPConnection->UnlockLDAPSession( aHost, false );
}
else
{
ldapReturnCode = LDAP_LOCAL_ERROR;
}
if ( ldapReturnCode == LDAP_ALREADY_EXISTS )
{
siResult = eDSRecordAlreadyExists;
}
else if ( ldapReturnCode != LDAP_SUCCESS )
{
siResult = MapLDAPWriteErrorToDS( ldapReturnCode, eDSRecordNotFound );
}
if ( (inData->fInOpen == true) && (siResult == eDSNoErr) )
{
pRecContext = new sLDAPContextData( *pContext );
if ( pRecContext == nil ) throw( eMemoryAllocError );
pRecContext->fType = 2;
if (pRecType->fBufferData != nil)
{
pRecContext->fOpenRecordType = strdup( pRecType->fBufferData );
}
if (recName != nil)
{
pRecContext->fOpenRecordName = strdup( recName );
}
pRecContext->fOpenRecordDN = ldapDNString;
ldapDNString = nil;
gLDAPContextTable->AddObjectForRefNum( inData->fOutRecRef, pRecContext );
DSRelease( pRecContext );
}
}
catch ( tDirStatus err )
{
siResult = err;
}
DSFreeString(pLDAPAttrType);
DSFreeString(pLDAPSearchBase);
DSFreeString(ldapDNString);
DSFree(needsValueMarker);
DSFreeString(ocString);
DSFree(ocvals);
DSFreeStringList( aValues );
DSFreeStringList( aMaps );
UInt32 startIndex = 1;
if (OCSearchList != nil)
{
startIndex = 2;
}
for (UInt32 anIndex = startIndex; anIndex < modIndex; anIndex++)
{
free(mods[anIndex]);
mods[anIndex] = NULL;
}
DSCFRelease(OCSearchList);
DSFreeString(tmpBuff);
DSRelease( pContext );
return( siResult );
}
tDirStatus CLDAPv3Plugin::CreateRecordWithAttributes ( tDirNodeReference inNodeRef, const char* inRecType, const char* inRecName, CFDictionaryRef inDict )
{
tDirStatus siResult = eDSNoErr;
char *attrTypeStr = nil;
char *attrTypeLDAPStr = nil;
sLDAPContextData *pContext = nil;
UInt32 attrCount = 0;
UInt32 valCount = 0;
UInt32 valIndex = 0;
struct berval **newValues = nil;
LDAPMod *mods[128]; int ldapReturnCode = 0;
char *attrValue = nil;
UInt32 attrLength = 0;
LDAP *aHost = nil;
UInt32 callocLength = 0;
bool bGotIt = false;
CFStringRef keyCFString = NULL;
char *pLDAPSearchBase = nil;
char *recNameAttrType = nil;
char *ldapDNString = nil;
UInt32 ldapDNLength = 0;
UInt32 ocCount = 0;
UInt32 raCount = 0;
LDAPMod *ocmod;
LDAPMod *rnmod;
char **ocvals = nil;
char *rnvals[2];
listOfStrings objectClassList;
listOfStrings reqAttrsList;
bool bOCANDGroup = false;
CFArrayRef OCSearchList = nil;
char *tmpBuff = nil;
CFIndex cfBuffSize = 1024;
int aOCSearchListCount = 0;
UInt32 keyIndex = 0;
UInt32 modIndex = 0;
UInt32 bValueStartIndex= 0;
CFMutableDictionaryRef mergedDict = NULL;
char **aValues = NULL;
char **aMaps = NULL;
try
{
pContext = gLDAPContextTable->GetObjectForRefNum( inNodeRef );
if ( pContext == nil ) throw( eDSBadContextData );
CLDAPNodeConfig *nodeConfig = pContext->fLDAPConnection->fNodeConfig;
if ( CFGetTypeID(inDict) != CFDictionaryGetTypeID() ) throw( eDSInvalidBuffFormat );
if ( inRecType == nil ) throw( eDSNullRecType );
if ( inRecName == nil ) throw( eDSNullRecName );
for (UInt32 modsIndex=0; modsIndex < 128; modsIndex++)
{
mods[modsIndex] = NULL;
}
recNameAttrType = MapAttrToLDAPType( pContext, (const char *)inRecType, kDSNAttrRecordName, 1, true );
if ( recNameAttrType == nil ) throw( eDSInvalidAttributeType );
pLDAPSearchBase = MapRecToSearchBase( pContext, (const char *)inRecType, 1, &bOCANDGroup, &OCSearchList, nil );
if ( pLDAPSearchBase == nil ) throw( eDSInvalidRecordType );
if (strcmp(inRecType, kDSStdRecordTypeAutomount) == 0)
{
char *names[2] = { (char *) inRecName, NULL };
UInt32 count = 0;
char *pMapRecType = MapRecToSearchBase( pContext, kDSStdRecordTypeAutomountMap, 1, NULL, NULL, NULL );
if (pMapRecType == NULL) throw( eDSInvalidRecordType );
char *pMapAttrType = MapAttrToLDAPType( pContext,kDSStdRecordTypeAutomountMap, kDSNAttrRecordName, 1, true );
if (pMapAttrType == NULL) throw( eDSInvalidRecordType );
siResult = CheckAutomountNames( kDSStdRecordTypeAutomount, names, &aValues, &aMaps, &count );
if (siResult != eDSNoErr || count == 0 || aMaps[0][0] == '\0') throw( eDSInvalidRecordName );
inRecName = aValues[0];
char *escRecName = BuildEscapedRDN( inRecName );
char *escMapname = BuildEscapedRDN( aMaps[0] );
ldapDNLength = strlen(recNameAttrType) + 1 + strlen(escRecName) + 2 + strlen(pMapAttrType) + 1 + strlen(escMapname) + 2 + strlen(pMapRecType) + 1;
ldapDNString = (char *)calloc(1, ldapDNLength);
snprintf( ldapDNString, ldapDNLength, "%s=%s, %s=%s, %s", recNameAttrType, escRecName, pMapAttrType, escMapname, pMapRecType );
DSFreeString( escRecName );
DSFreeString( escMapname );
}
else
{
ldapDNLength = strlen(recNameAttrType) + 1 + 2*strlen(inRecName) + 2 + strlen(pLDAPSearchBase);
ldapDNString = (char *)calloc(1, ldapDNLength + 1);
strcpy(ldapDNString,recNameAttrType);
strcat(ldapDNString,"=");
char *escapedString = BuildEscapedRDN(inRecName);
strcat(ldapDNString,escapedString);
DSFreeString(escapedString);
strcat(ldapDNString,", ");
strcat(ldapDNString,pLDAPSearchBase);
}
rnmod = (LDAPMod *) calloc( 1, sizeof(LDAPMod) );
rnmod->mod_type = strdup(recNameAttrType);
CFArrayRef shortNames = (CFArrayRef)CFDictionaryGetValue( inDict, CFSTR( kDSNAttrRecordName ) );
CFIndex numShortNames = CFArrayGetCount( shortNames );
if( numShortNames == 1 )
{
rnvals[0] = (char *)inRecName;
rnvals[1] = NULL;
rnmod->mod_op = LDAP_MOD_ADD;
rnmod->mod_values = rnvals; }
else
{
newValues = (struct berval**) calloc(1, (numShortNames + 1) *sizeof(struct berval *) );
valIndex = 0;
for( CFIndex i=0; i<numShortNames; i++ )
{
CFStringRef shortName = (CFStringRef)CFArrayGetValueAtIndex( shortNames, i );
callocLength = (UInt32) CFStringGetMaximumSizeForEncoding(
CFStringGetLength(shortName), kCFStringEncodingUTF8) + 1;
attrValue = (char *)calloc( 1, callocLength );
if ( attrValue == NULL ) throw( eMemoryError );
bool bGotValue = CFStringGetCString( shortName, attrValue, callocLength, kCFStringEncodingUTF8 );
if (bGotValue == false) throw( eMemoryError );
attrLength = strlen(attrValue);
newValues[valIndex] = (struct berval*) calloc(1, sizeof(struct berval) );
newValues[valIndex]->bv_val = attrValue;
newValues[valIndex]->bv_len = attrLength;
valIndex++;
}
rnmod->mod_op = LDAP_MOD_ADD | LDAP_MOD_BVALUES;
rnmod->mod_bvalues = newValues;
}
if ( (inRecType != nil) && (pLDAPSearchBase != nil) )
{
if (strncmp(inRecType,kDSStdRecordTypePrefix,strlen(kDSStdRecordTypePrefix)) == 0)
{
if (OCSearchList != nil)
{
CFStringRef ocString = nil;
tmpBuff = (char *)calloc(1, 1024);
if (!bOCANDGroup)
{
if (CFArrayGetCount(OCSearchList) >= 1)
{
ocString = (CFStringRef)::CFArrayGetValueAtIndex( OCSearchList, 0 );
}
if (ocString != nil)
{
CFStringGetCString(ocString, tmpBuff, cfBuffSize, kCFStringEncodingUTF8);
string ourString(tmpBuff);
objectClassList.push_back(ourString);
}
}
else
{
aOCSearchListCount = CFArrayGetCount(OCSearchList);
for ( int iOCIndex = 0; iOCIndex < aOCSearchListCount; iOCIndex++ )
{
::memset(tmpBuff,0,1024);
ocString = (CFStringRef)::CFArrayGetValueAtIndex( OCSearchList, iOCIndex );
if (ocString != nil)
{
CFStringGetCString(ocString, tmpBuff, cfBuffSize, kCFStringEncodingUTF8);
string ourString(tmpBuff);
objectClassList.push_back(ourString);
}
} }
} } }
mods[0] = rnmod;
modIndex = 1;
bValueStartIndex = 1;
if (OCSearchList != nil && nodeConfig != NULL)
{
nodeConfig->GetReqAttrListForObjectList( pContext->fLDAPConnection, objectClassList, reqAttrsList );
raCount = reqAttrsList.size();
ocCount = objectClassList.size();
ocmod = (LDAPMod *) calloc( 1, sizeof(LDAPMod) );
ocmod->mod_op = LDAP_MOD_ADD;
ocmod->mod_type = strdup("objectClass");
ocmod->mod_values = nil;
ocvals = (char **)calloc(1,(ocCount+1)*sizeof(char **));
UInt32 ocValIndex = 0;
for (listOfStringsCI iter = objectClassList.begin(); iter != objectClassList.end(); ++iter)
{
const char *aString = (*iter).c_str();
ocvals[ocValIndex] = (char *)aString; ocValIndex++;
}
ocvals[ocCount] = nil;
ocmod->mod_values = ocvals;
mods[1] = ocmod;
modIndex = 2;
bValueStartIndex = 2;
}
mergedDict = CFDictionaryCreateMutable( kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
CFStringRef singleDefaultValue = CFStringCreateWithCString( kCFAllocatorDefault, "99", kCFStringEncodingUTF8 ); CFMutableArrayRef valueDefaultArray = CFArrayCreateMutable( kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks );
CFArrayAppendValue( valueDefaultArray, singleDefaultValue );
if (raCount != 0)
{
for (listOfStringsCI addIter = reqAttrsList.begin(); addIter != reqAttrsList.end(); ++addIter)
{
if ( (strcasecmp((*addIter).c_str(), recNameAttrType) != 0) || (strcasecmp("sAMAccountName", recNameAttrType) == 0) )
{
CFStringRef aString = CFStringCreateWithCString(kCFAllocatorDefault, (*addIter).c_str(), kCFStringEncodingUTF8);
CFDictionarySetValue( mergedDict, aString, valueDefaultArray );
CFRelease(aString);
}
}
}
CFRelease(singleDefaultValue);
CFRelease(valueDefaultArray);
attrCount = (UInt32) CFDictionaryGetCount(inDict);
char** keys = (char**)calloc( attrCount + 1, sizeof( void* ) );
CFDictionaryGetKeysAndValues( inDict, (const void**)keys, NULL );
CFArrayRef valuesCFArray = NULL;
for( keyIndex = 0; keyIndex < attrCount; keyIndex++ )
{
keyCFString = NULL;
if ( !(CFGetTypeID((CFStringRef)keys[keyIndex]) == CFStringGetTypeID() ) )
{
continue; }
else
{
keyCFString = (CFStringRef)keys[keyIndex];
}
attrTypeStr = (char *)CFStringGetCStringPtr( keyCFString, kCFStringEncodingUTF8 );
if (attrTypeStr == nil)
{
callocLength = (UInt32) CFStringGetMaximumSizeForEncoding(CFStringGetLength(keyCFString), kCFStringEncodingUTF8) + 1;
attrTypeStr = (char *)calloc( 1, callocLength );
if ( attrTypeStr == nil ) throw( eMemoryError );
bGotIt = CFStringGetCString( keyCFString, attrTypeStr, callocLength, kCFStringEncodingUTF8 );
if (bGotIt == false) throw( eMemoryError );
}
attrTypeLDAPStr = MapAttrToLDAPType( pContext, (const char *)inRecType, attrTypeStr, 1, true );
if ( attrTypeLDAPStr == nil ) throw( eDSInvalidAttributeType );
valuesCFArray = (CFArrayRef)CFDictionaryGetValue( inDict, keyCFString );
if (strcasecmp(attrTypeLDAPStr, recNameAttrType) != 0)
{ CFStringRef aString = CFStringCreateWithCString(kCFAllocatorDefault, attrTypeLDAPStr, kCFStringEncodingUTF8);
CFDictionarySetValue( mergedDict, aString, valuesCFArray );
CFRelease(aString);
}
if (bGotIt)
{
DSFreeString(attrTypeStr);
}
DSFreeString(attrTypeLDAPStr);
}
attrCount = (UInt32) CFDictionaryGetCount(mergedDict);
keys = (char**)calloc( attrCount + 1, sizeof( void* ) );
CFDictionaryGetKeysAndValues( mergedDict, (const void**)keys, NULL );
for( keyIndex = 0; keyIndex < attrCount; keyIndex++ )
{
keyCFString = NULL;
if ( !(CFGetTypeID((CFStringRef)keys[keyIndex]) == CFStringGetTypeID() ) )
{
continue; }
else
{
keyCFString = (CFStringRef)keys[keyIndex];
}
attrTypeStr = (char *)CFStringGetCStringPtr( keyCFString, kCFStringEncodingUTF8 );
if (attrTypeStr == nil)
{
callocLength = (UInt32) CFStringGetMaximumSizeForEncoding(CFStringGetLength(keyCFString), kCFStringEncodingUTF8) + 1;
attrTypeStr = (char *)calloc( 1, callocLength );
if ( attrTypeStr == nil ) throw( eMemoryError );
bGotIt = CFStringGetCString( keyCFString, attrTypeStr, callocLength, kCFStringEncodingUTF8 );
if (bGotIt == false) throw( eMemoryError );
}
valuesCFArray = (CFArrayRef)CFDictionaryGetValue( mergedDict, keyCFString );
if ( !(CFGetTypeID(valuesCFArray) == CFArrayGetTypeID() ) )
{
if (bGotIt)
{
DSFreeString(attrTypeStr);
}
continue; }
valCount = (UInt32) CFArrayGetCount( valuesCFArray );
newValues = (struct berval**) calloc(1, (valCount + 1) *sizeof(struct berval *) );
valIndex = 0;
for (UInt32 i = 0; i < valCount; i++ ) {
CFTypeRef valueCFType = CFArrayGetValueAtIndex( valuesCFArray, (CFIndex)i );
if ( CFGetTypeID(valueCFType) == CFStringGetTypeID() )
{
CFStringRef valueCFString = (CFStringRef)valueCFType;
callocLength = (UInt32) CFStringGetMaximumSizeForEncoding(CFStringGetLength(valueCFString), kCFStringEncodingUTF8) + 1;
attrValue = (char *)calloc( 1, callocLength );
if ( attrValue == nil ) throw( eMemoryError );
bool bGotValue = CFStringGetCString( valueCFString, attrValue, callocLength, kCFStringEncodingUTF8 );
if (bGotValue == false) throw( eMemoryError );
attrLength = strlen(attrValue);
newValues[valIndex] = (struct berval*) calloc(1, sizeof(struct berval) );
newValues[valIndex]->bv_val = attrValue;
newValues[valIndex]->bv_len = attrLength;
valIndex++;
attrValue = nil;
}
else if ( CFGetTypeID(valueCFType) == CFDataGetTypeID() )
{
CFDataRef valueCFData = (CFDataRef)valueCFType;
attrLength = (UInt32) CFDataGetLength(valueCFData);
attrValue = (char *)calloc( 1, attrLength + 1 );
if ( attrValue == nil ) throw( eMemoryError );
CFDataGetBytes( valueCFData, CFRangeMake(0,attrLength), (UInt8*)attrValue );
newValues[valIndex] = (struct berval*) calloc(1, sizeof(struct berval) );
newValues[valIndex]->bv_val = attrValue;
newValues[valIndex]->bv_len = attrLength;
valIndex++;
attrValue = nil;
}
}
if (valIndex > 0) {
mods[modIndex] = (LDAPMod *) calloc( 1, sizeof(LDAPMod) );
mods[modIndex]->mod_op = LDAP_MOD_ADD | LDAP_MOD_BVALUES;
mods[modIndex]->mod_type = strdup(attrTypeStr);
mods[modIndex]->mod_bvalues= newValues;
modIndex++;
if (modIndex == 127) {
if (bGotIt)
{
DSFreeString(attrTypeStr);
}
break; }
}
if (bGotIt)
{
DSFreeString(attrTypeStr);
}
attrTypeStr = nil;
}
aHost = pContext->fLDAPConnection->LockLDAPSession();
if (aHost != NULL)
{
ldapReturnCode = ldap_add_ext_s( aHost, ldapDNString, mods, NULL, NULL);
pContext->fLDAPConnection->UnlockLDAPSession( aHost, false );
}
else
{
ldapReturnCode = LDAP_LOCAL_ERROR;
}
if ( ldapReturnCode == LDAP_ALREADY_EXISTS )
{
siResult = eDSRecordAlreadyExists;
}
else if ( ldapReturnCode != LDAP_SUCCESS )
{
siResult = MapLDAPWriteErrorToDS( ldapReturnCode, eDSRecordNotFound );
}
for (UInt32 modsIndex=0; ((modsIndex < 128) && (mods[modsIndex] != NULL)); modsIndex++)
{
DSFreeString(mods[modsIndex]->mod_type);
if (modsIndex >= bValueStartIndex)
{
newValues = mods[modsIndex]->mod_bvalues;
if (newValues != NULL)
{
ldap_value_free_len(newValues);
newValues = NULL;
}
}
DSFree( mods[modsIndex] );
}
}
catch ( tDirStatus err )
{
siResult = err;
}
DSCFRelease(OCSearchList);
DSFree(ocvals);
DSFreeString( attrTypeLDAPStr );
DSFreeString( pLDAPSearchBase );
DSFreeString( recNameAttrType );
DSFreeStringList( aValues );
DSFreeStringList( aMaps );
DSFreeString( ldapDNString );
DSCFRelease(mergedDict);
DSRelease( pContext );
return( siResult );
}
tDirStatus CLDAPv3Plugin::RemoveAttributeValue ( sRemoveAttributeValue *inData, const char *inRecTypeStr )
{
tDirStatus siResult = eDSNoErr;
tDataNodePtr pAttrType = nil;
char *pLDAPAttrType = nil;
sLDAPContextData *pRecContext = nil;
LDAPMessage *result = nil;
struct berval **bValues = nil;
struct berval **newValues = nil;
UInt32 valCount = 0;
bool bFoundIt = false;
int numAttributes = 1;
UInt32 crcVal = 0;
LDAPMod *mods[2];
int ldapReturnCode = 0;
LDAP *aHost = nil;
char **attrs = nil;
try
{
pRecContext = gLDAPContextTable->GetObjectForRefNum( inData->fInRecRef );
if ( pRecContext == nil ) throw( eDSBadContextData );
if ( pRecContext->fOpenRecordDN == nil ) throw( eDSNullRecName );
pAttrType = inData->fInAttrType;
if ( pAttrType == nil ) throw( eDSEmptyAttributeType );
if ( pAttrType->fBufferData == nil ) throw( eDSEmptyAttributeType );
attrs = MapAttrToLDAPTypeArray( pRecContext, pRecContext->fOpenRecordType, pAttrType->fBufferData );
if ( attrs == nil ) throw( eDSInvalidAttributeType );
siResult = (tDirStatus)GetRecLDAPMessage( pRecContext, attrs, &result );
if ( siResult != eDSNoErr ) throw( siResult );
if ( strcmp(inRecTypeStr, kDSStdRecordTypeConfig) == 0 )
IncrementChangeSeqNumber();
if ( result != nil )
{
numAttributes = 1;
pLDAPAttrType = MapAttrToLDAPType( pRecContext, (const char *)(pRecContext->fOpenRecordType), pAttrType->fBufferData, numAttributes, true );
if ( pLDAPAttrType == nil ) throw( eDSInvalidAttributeType );
bFoundIt = false;
while ( ( pLDAPAttrType != nil ) && (!bFoundIt) )
{
valCount = 0;
aHost = pRecContext->fLDAPConnection->LockLDAPSession();
if ( aHost != NULL )
{
if ( (bValues = ldap_get_values_len(aHost, result, pLDAPAttrType)) != NULL )
{
for (int i = 0; bValues[i] != NULL; i++ )
{
valCount++;
}
newValues = (struct berval**) calloc(1, (valCount + 1) *sizeof(struct berval *) );
UInt32 newIndex = 0;
for (int i = 0; bValues[i] != NULL; i++ )
{
crcVal = CalcCRC( bValues[i]->bv_val );
if ( crcVal == inData->fInAttrValueID )
{
bFoundIt = true;
newValues[newIndex] = bValues[i];
newIndex++;
}
}
}
pRecContext->fLDAPConnection->UnlockLDAPSession( aHost, false );
}
if (bFoundIt)
{
{
LDAPMod mod;
mod.mod_op = LDAP_MOD_DELETE | LDAP_MOD_BVALUES;
mod.mod_type = pLDAPAttrType;
mod.mod_bvalues = newValues;
mods[0] = &mod;
mods[1] = NULL;
aHost = pRecContext->fLDAPConnection->LockLDAPSession();
if (aHost != NULL)
{
ldapReturnCode = ldap_modify_s( aHost, pRecContext->fOpenRecordDN, mods);
pRecContext->fLDAPConnection->UnlockLDAPSession( aHost, false );
}
else
{
ldapReturnCode = LDAP_LOCAL_ERROR;
}
if ( ldapReturnCode != LDAP_SUCCESS )
{
siResult = MapLDAPWriteErrorToDS( ldapReturnCode, eDSAttributeNotFound );
}
}
}
if (bValues != NULL)
{
ldap_value_free_len(bValues);
bValues = NULL;
}
DSFree(newValues);
DSFreeString(pLDAPAttrType);
numAttributes++;
pLDAPAttrType = MapAttrToLDAPType( pRecContext, (const char *)(pRecContext->fOpenRecordType), pAttrType->fBufferData, numAttributes, true );
}
} else
{
throw( eDSRecordNotFound ); }
}
catch ( tDirStatus err )
{
siResult = err;
}
DSFreeString( pLDAPAttrType );
DSFreeStringList( attrs );
if (result != nil)
{
ldap_msgfree( result );
result = nil;
}
DSRelease( pRecContext );
return( siResult );
}
tDirStatus CLDAPv3Plugin::SetAttributeValues ( sSetAttributeValues *inData, const char *inRecTypeStr )
{
tDirStatus siResult = eDSNoErr;
tDataNodePtr pAttrType = nil;
char *pLDAPAttrType = nil;
sLDAPContextData *pRecContext = nil;
CFIndex valCount = 0;
struct berval *replaceValue = nil;
struct berval **newValues = nil;
LDAPMod *mods[2];
int ldapReturnCode = 0;
char *attrValue = nil;
UInt32 attrLength = 0;
LDAP *aHost = nil;
try
{
pRecContext = gLDAPContextTable->GetObjectForRefNum( inData->fInRecRef );
if ( pRecContext == nil ) throw( eDSBadContextData );
if ( pRecContext->fOpenRecordDN == nil ) throw( eDSNullRecName );
if ( inData->fInAttrType == nil ) throw( eDSNullAttributeType );
if ( inData->fInAttrValueList == nil ) throw( eDSNullAttributeValue ); if ( inData->fInAttrValueList->fDataNodeCount <= 0 ) throw( eDSNullAttributeValue );
pAttrType = inData->fInAttrType;
if ( pAttrType == nil ) throw( eDSEmptyAttributeType );
if ( pAttrType->fBufferData == nil ) throw( eDSEmptyAttributeType );
if ( strcmp(inRecTypeStr, kDSStdRecordTypeConfig) == 0 )
IncrementChangeSeqNumber();
pLDAPAttrType = MapAttrToLDAPType( pRecContext, (const char *)(pRecContext->fOpenRecordType), pAttrType->fBufferData, 1, true );
if ( pLDAPAttrType == nil ) throw( eDSInvalidAttributeType );
CFArrayRef cfArray = dsConvertDataListToCFArray( inData->fInAttrValueList );
UInt32 jIndex = 0;
if( NULL != cfArray )
{
valCount = CFArrayGetCount( cfArray );
newValues = (struct berval**) calloc(1, ((UInt32)valCount + 1) *sizeof(struct berval *) );
for ( CFIndex i = 0; i < valCount; i++ ) {
CFDataRef cfRef = (CFDataRef) CFArrayGetValueAtIndex( cfArray, i );
CFIndex iLength = CFDataGetLength( cfRef );
if( iLength > 0 )
{
attrLength = iLength;
attrValue = (char *) calloc(1, 1 + attrLength);
CFDataGetBytes( cfRef, CFRangeMake(0,iLength), (UInt8*)attrValue );
replaceValue = (struct berval*) calloc(1, sizeof(struct berval) );
replaceValue->bv_val = attrValue;
replaceValue->bv_len = attrLength;
newValues[jIndex] = replaceValue;
jIndex++;
attrValue = nil;
replaceValue = nil;
}
}
DSCFRelease( cfArray );
}
if (jIndex > 0) {
LDAPMod mod;
mod.mod_op = LDAP_MOD_REPLACE | LDAP_MOD_BVALUES;
mod.mod_type = pLDAPAttrType;
mod.mod_bvalues = newValues;
mods[0] = &mod;
mods[1] = NULL;
aHost = pRecContext->fLDAPConnection->LockLDAPSession();
if (aHost != NULL)
{
ldapReturnCode = ldap_modify_s( aHost, pRecContext->fOpenRecordDN, mods);
pRecContext->fLDAPConnection->UnlockLDAPSession( aHost, false );
}
else
{
ldapReturnCode = LDAP_LOCAL_ERROR;
}
if ( ldapReturnCode != LDAP_SUCCESS )
{
siResult = MapLDAPWriteErrorToDS( ldapReturnCode, eDSAttributeNotFound );
}
if (newValues != NULL)
{
ldap_value_free_len(newValues);
newValues = NULL;
}
}
}
catch ( tDirStatus err )
{
siResult = err;
}
DSFreeString( pLDAPAttrType );
DSRelease( pRecContext );
return( siResult );
}
tDirStatus CLDAPv3Plugin::SetAttributeValue ( sSetAttributeValue *inData, const char *inRecTypeStr )
{
tDirStatus siResult = eDSNoErr;
tDataNodePtr pAttrType = nil;
char *pLDAPAttrType = nil;
sLDAPContextData *pRecContext = nil;
LDAPMessage *result = nil;
UInt32 valCount = 0;
struct berval **bValues = nil;
struct berval replaceValue;
struct berval **newValues = nil;
bool bFoundIt = false;
int numAttributes = 1;
UInt32 crcVal = 0;
LDAPMod *mods[2];
int ldapReturnCode = 0;
char *attrValue = nil;
UInt32 attrLength = 0;
LDAP *aHost = nil;
char **attrs = nil;
try
{
pRecContext = gLDAPContextTable->GetObjectForRefNum( inData->fInRecRef );
if ( pRecContext == nil ) throw( eDSBadContextData );
if ( pRecContext->fOpenRecordDN == nil ) throw( eDSNullRecName );
if ( inData->fInAttrValueEntry == nil ) throw( eDSNullAttributeValue );
if ( (inData->fInAttrValueEntry->fAttributeValueData.fBufferData == NULL) ||
(inData->fInAttrValueEntry->fAttributeValueData.fBufferLength < 1) )
{
throw( eDSEmptyAttributeValue );
}
else
{
attrLength = inData->fInAttrValueEntry->fAttributeValueData.fBufferLength;
attrValue = (char *) calloc(1, 1 + attrLength);
memcpy(attrValue, inData->fInAttrValueEntry->fAttributeValueData.fBufferData, attrLength);
}
if ( strcmp(inRecTypeStr, kDSStdRecordTypeConfig) == 0 )
IncrementChangeSeqNumber();
pAttrType = inData->fInAttrType;
if ( pAttrType == nil ) throw( eDSEmptyAttributeType );
if ( pAttrType->fBufferData == nil ) throw( eDSEmptyAttributeType );
attrs = MapAttrToLDAPTypeArray( pRecContext, pRecContext->fOpenRecordType, pAttrType->fBufferData );
if ( attrs == nil ) throw( eDSInvalidAttributeType );
siResult = (tDirStatus)GetRecLDAPMessage( pRecContext, attrs, &result );
if ( siResult != eDSNoErr ) throw( siResult );
if ( result != nil )
{
numAttributes = 1;
pLDAPAttrType = MapAttrToLDAPType( pRecContext, (const char *)(pRecContext->fOpenRecordType), pAttrType->fBufferData, numAttributes, true );
if ( pLDAPAttrType == nil ) throw( eDSInvalidAttributeType );
bFoundIt = false;
while ( ( pLDAPAttrType != nil ) && (!bFoundIt) )
{
valCount = 0;
aHost = pRecContext->fLDAPConnection->LockLDAPSession();
if ( aHost != NULL )
{
if ( (bValues = ldap_get_values_len(aHost, result, pLDAPAttrType)) != NULL )
{
for (int i = 0; bValues[i] != NULL; i++ )
{
valCount++;
}
newValues = (struct berval**) calloc(1, (valCount + 1) *sizeof(struct berval *) );
for (int i = 0; bValues[i] != NULL; i++ )
{
crcVal = CalcCRC( bValues[i]->bv_val );
if ( crcVal == inData->fInAttrValueEntry->fAttributeValueID )
{
bFoundIt = true;
replaceValue.bv_val = attrValue;
replaceValue.bv_len = attrLength;
newValues[i] = &replaceValue;
}
else
{
newValues[i] = bValues[i];
}
}
if (!bFoundIt) {
if (bValues != NULL)
{
ldap_value_free_len(bValues);
bValues = NULL;
}
if (newValues != NULL)
{
free(newValues); newValues = NULL;
}
siResult = eDSAttributeValueNotFound;
}
}
pRecContext->fLDAPConnection->UnlockLDAPSession( aHost, false );
}
if (bFoundIt)
{
{
LDAPMod mod;
mod.mod_op = LDAP_MOD_REPLACE | LDAP_MOD_BVALUES;
mod.mod_type = pLDAPAttrType;
mod.mod_bvalues = newValues;
mods[0] = &mod;
mods[1] = NULL;
aHost = pRecContext->fLDAPConnection->LockLDAPSession();
if (aHost != NULL)
{
ldapReturnCode = ldap_modify_s( aHost, pRecContext->fOpenRecordDN, mods);
pRecContext->fLDAPConnection->UnlockLDAPSession( aHost, false );
}
else
{
ldapReturnCode = LDAP_LOCAL_ERROR;
}
if ( ldapReturnCode != LDAP_SUCCESS )
{
siResult = MapLDAPWriteErrorToDS( ldapReturnCode, eDSAttributeNotFound );
}
}
}
if (bValues != NULL)
{
ldap_value_free_len(bValues);
bValues = NULL;
}
if (newValues != NULL)
{
free(newValues); newValues = NULL;
}
if (pLDAPAttrType != nil)
{
delete (pLDAPAttrType);
pLDAPAttrType = nil;
}
numAttributes++;
pLDAPAttrType = MapAttrToLDAPType( pRecContext, (const char *)(pRecContext->fOpenRecordType), pAttrType->fBufferData, numAttributes, true );
}
} else
{
throw( eDSRecordNotFound ); }
}
catch ( tDirStatus err )
{
siResult = err;
}
if ( result != nil )
{
ldap_msgfree( result );
result = nil;
}
DSFreeString(pLDAPAttrType);
DSFree(attrValue);
DSFreeStringList(attrs);
DSRelease( pRecContext );
return( siResult );
}
tDirStatus CLDAPv3Plugin::ReleaseContinueData ( sReleaseContinueData *inData )
{
tDirStatus siResult = eDSNoErr;
if ( gLDAPContinueTable->RemoveContext( inData->fInContinueData ) != eDSNoErr )
{
siResult = eDSInvalidContext;
}
return( siResult );
}
tDirStatus CLDAPv3Plugin::CloseAttributeList ( sCloseAttributeList *inData )
{
tDirStatus siResult = eDSNoErr;
sLDAPContextData *pContext = nil;
pContext = gLDAPContextTable->GetObjectForRefNum( inData->fInAttributeListRef );
if ( pContext != nil )
{
gLDAPContextTable->RemoveRefNum( inData->fInAttributeListRef );
DSRelease( pContext );
}
else
{
siResult = eDSInvalidAttrListRef;
}
return( siResult );
}
tDirStatus CLDAPv3Plugin::CloseAttributeValueList ( sCloseAttributeValueList *inData )
{
tDirStatus siResult = eDSNoErr;
sLDAPContextData *pContext = nil;
pContext = gLDAPContextTable->GetObjectForRefNum( inData->fInAttributeValueListRef );
if ( pContext != nil )
{
gLDAPContextTable->RemoveRefNum( inData->fInAttributeValueListRef );
DSRelease( pContext );
}
else
{
siResult = eDSInvalidAttrValueRef;
}
return( siResult );
}
tDirStatus CLDAPv3Plugin::GetRecRefInfo ( sGetRecRefInfo *inData )
{
tDirStatus siResult = eDSNoErr;
UInt32 uiRecSize = 0;
tRecordEntry *pRecEntry = nil;
sLDAPContextData *pContext = nil;
char *refType = nil;
UInt32 uiOffset = 0;
char *refName = nil;
pContext = gLDAPContextTable->GetObjectForRefNum( inData->fInRecRef );
if ( pContext == NULL )
return( eDSBadContextData );
if ( pContext->fOpenRecordType != nil)
{
refType = strdup( pContext->fOpenRecordType );
}
else {
refType = strdup( kLDAPRecordTypeUnknownStr );
}
if ( pContext->fOpenRecordName != nil)
{
refName = strdup( pContext->fOpenRecordName );
}
else {
refName = strdup( kLDAPRecordNameUnknownStr );
}
uiRecSize = sizeof( tRecordEntry ) + strlen( refType ) + strlen( refName ) + 4 + kBuffPad;
pRecEntry = (tRecordEntry *)calloc( 1, uiRecSize );
pRecEntry->fRecordNameAndType.fBufferSize = strlen( refType ) + strlen( refName ) + 4 + kBuffPad;
pRecEntry->fRecordNameAndType.fBufferLength = strlen( refType ) + strlen( refName ) + 4;
uiOffset = 0;
UInt16 strLen = 0;
strLen = strlen( refName );
memcpy( pRecEntry->fRecordNameAndType.fBufferData + uiOffset, &strLen, 2);
uiOffset += 2;
memcpy( pRecEntry->fRecordNameAndType.fBufferData + uiOffset, refName, strLen);
uiOffset += strLen;
strLen = strlen( refType );
memcpy( pRecEntry->fRecordNameAndType.fBufferData + uiOffset, &strLen, 2);
uiOffset += 2;
memcpy( pRecEntry->fRecordNameAndType.fBufferData + uiOffset, refType, strLen);
uiOffset += strLen;
inData->fOutRecInfo = pRecEntry;
DSDelete( refType );
DSDelete( refName );
DSRelease( pContext );
return( siResult );
}
tDirStatus CLDAPv3Plugin::GetRecAttribInfo ( sGetRecAttribInfo *inData )
{
tDirStatus siResult = eDSNoErr;
UInt32 uiTypeLen = 0;
UInt32 uiDataLen = 0;
tDataNodePtr pAttrType = nil;
char *pLDAPAttrType = nil;
tAttributeEntryPtr pOutAttrEntry = nil;
sLDAPContextData *pRecContext = nil;
LDAPMessage *result = nil;
struct berval **bValues;
int numAttributes = 1;
bool bTypeFound = false;
int valCount = 0;
LDAP *aHost = nil;
char **attrs = nil;
try
{
pRecContext = gLDAPContextTable->GetObjectForRefNum( inData->fInRecRef );
if ( pRecContext == nil ) throw( eDSBadContextData );
pAttrType = inData->fInAttrType;
if ( pAttrType == nil ) throw( eDSEmptyAttributeType );
if ( pAttrType->fBufferData == nil ) throw( eDSEmptyAttributeType );
attrs = MapAttrToLDAPTypeArray( pRecContext, pRecContext->fOpenRecordType, pAttrType->fBufferData );
if ( attrs == nil ) throw( eDSInvalidAttributeType );
siResult = (tDirStatus)GetRecLDAPMessage( pRecContext, attrs, &result );
if ( siResult != eDSNoErr ) throw( siResult);
if ( result != nil )
{
numAttributes = 1;
pLDAPAttrType = MapAttrToLDAPType( pRecContext, (const char *)(pRecContext->fOpenRecordType), pAttrType->fBufferData, numAttributes );
if ( pLDAPAttrType == nil ) throw( eDSInvalidAttributeType );
bTypeFound = false;
while ( pLDAPAttrType != nil )
{
if (!bTypeFound)
{
uiTypeLen = strlen( pAttrType->fBufferData );
pOutAttrEntry = (tAttributeEntry *)calloc( 1, sizeof( tAttributeEntry ) + uiTypeLen + kBuffPad );
pOutAttrEntry->fAttributeSignature.fBufferSize = uiTypeLen;
pOutAttrEntry->fAttributeSignature.fBufferLength = uiTypeLen;
memcpy( pOutAttrEntry->fAttributeSignature.fBufferData, pAttrType->fBufferData, uiTypeLen );
bTypeFound = true;
valCount = 0;
uiDataLen = 0;
}
if ( (pLDAPAttrType[0] == '#') && (strlen(pLDAPAttrType) > 1) )
{
char *vsReturnStr = nil;
vsReturnStr = MappingNativeVariableSubstitution( pLDAPAttrType, pRecContext, result, siResult );
if (vsReturnStr != nil)
{
valCount++;
uiDataLen += (strlen(vsReturnStr) - 1);
free( vsReturnStr );
vsReturnStr = nil;
}
else
{
if (siResult != eDSNoErr) throw (siResult);
valCount++;
uiDataLen += (strlen(pLDAPAttrType) - 1);
}
}
else
{
aHost = pRecContext->fLDAPConnection->LockLDAPSession();
if ( aHost != NULL )
{
if ( (bValues = ldap_get_values_len(aHost, result, pLDAPAttrType)) != NULL )
{
for (int ii = 0; bValues[ii] != NULL; ii++ )
valCount++;
for (int i = 0; bValues[i] != NULL; i++ )
{
uiDataLen += bValues[i]->bv_len;
} if (bValues != NULL)
{
ldap_value_free_len(bValues);
bValues = NULL;
}
}
pRecContext->fLDAPConnection->UnlockLDAPSession( aHost, false );
}
}
if (pLDAPAttrType != nil)
{
delete (pLDAPAttrType);
pLDAPAttrType = nil;
}
numAttributes++;
pLDAPAttrType = MapAttrToLDAPType( pRecContext, (const char *)(pRecContext->fOpenRecordType), pAttrType->fBufferData, numAttributes );
}
if ( pOutAttrEntry == nil )
{
inData->fOutAttrInfoPtr = nil;
throw( eDSAttributeNotFound );
}
if ( valCount > 0 )
{
pOutAttrEntry->fAttributeValueCount = valCount;
pOutAttrEntry->fAttributeValueMaxSize = 255;
pOutAttrEntry->fAttributeDataSize = uiDataLen;
inData->fOutAttrInfoPtr = pOutAttrEntry;
}
else
{
free( pOutAttrEntry );
pOutAttrEntry = nil;
inData->fOutAttrInfoPtr = nil;
siResult = eDSAttributeNotFound;
}
} else
{
siResult = eDSRecordNotFound;
}
}
catch ( tDirStatus err )
{
siResult = err;
}
if ( result != nil )
{
ldap_msgfree( result );
result = nil;
}
DSFreeString(pLDAPAttrType);
DSFreeStringList(attrs);
DSRelease( pRecContext );
return( siResult );
}
tDirStatus CLDAPv3Plugin::GetRecAttrValueByIndex ( sGetRecordAttributeValueByIndex *inData )
{
tDirStatus siResult = eDSNoErr;
UInt32 uiDataLen = 0;
tDataNodePtr pAttrType = nil;
char *pLDAPAttrType = nil;
tAttributeValueEntryPtr pOutAttrValue = nil;
sLDAPContextData *pRecContext = nil;
LDAPMessage *result = nil;
struct berval **bValues;
UInt32 valCount = 0;
bool bFoundIt = false;
int numAttributes = 1;
UInt32 literalLength = 0;
bool bStripCryptPrefix = false;
LDAP *aHost = nil;
char **attrs = nil;
try
{
if (inData->fInAttrValueIndex == 0) throw( eDSInvalidIndex );
pRecContext = gLDAPContextTable->GetObjectForRefNum( inData->fInRecRef );
if ( pRecContext == nil ) throw( eDSBadContextData );
pAttrType = inData->fInAttrType;
if ( pAttrType == nil ) throw( eDSEmptyAttributeType );
if ( pAttrType->fBufferData == nil ) throw( eDSEmptyAttributeType );
attrs = MapAttrToLDAPTypeArray( pRecContext, pRecContext->fOpenRecordType, pAttrType->fBufferData );
if ( attrs == nil ) throw( eDSInvalidAttributeType );
siResult = (tDirStatus)GetRecLDAPMessage( pRecContext, attrs, &result );
if ( siResult != eDSNoErr ) throw( siResult);
if ( result != nil )
{
if (strcmp( kDS1AttrPasswordPlus, pAttrType->fBufferData ) == 0)
{
bStripCryptPrefix = true;
}
numAttributes = 1;
pLDAPAttrType = MapAttrToLDAPType( pRecContext, (const char *)(pRecContext->fOpenRecordType), pAttrType->fBufferData, numAttributes );
if ( pLDAPAttrType == nil ) throw( eDSInvalidAttributeType );
bFoundIt = false;
while ( ( pLDAPAttrType != nil ) && (!bFoundIt) )
{
if (pLDAPAttrType[0] == '#')
{
valCount++;
literalLength = strlen(pLDAPAttrType + 1);
if ( (valCount == inData->fInAttrValueIndex) && (literalLength > 0) )
{
char *vsReturnStr = nil;
vsReturnStr = MappingNativeVariableSubstitution( pLDAPAttrType, pRecContext, result, siResult );
if (vsReturnStr != nil)
{
uiDataLen = strlen(vsReturnStr + 1);
pOutAttrValue = (tAttributeValueEntry *)calloc( 1, sizeof( tAttributeValueEntry ) + uiDataLen + kBuffPad );
pOutAttrValue->fAttributeValueData.fBufferSize = uiDataLen + kBuffPad;
pOutAttrValue->fAttributeValueData.fBufferLength = uiDataLen;
pOutAttrValue->fAttributeValueID = CalcCRC( pLDAPAttrType + 1 );
memcpy( pOutAttrValue->fAttributeValueData.fBufferData, vsReturnStr + 1, uiDataLen );
free(vsReturnStr);
vsReturnStr = nil;
}
else
{
if (siResult != eDSNoErr) throw (siResult);
uiDataLen = literalLength;
pOutAttrValue = (tAttributeValueEntry *)calloc( 1, sizeof( tAttributeValueEntry ) + uiDataLen + kBuffPad );
pOutAttrValue->fAttributeValueData.fBufferSize = uiDataLen + kBuffPad;
pOutAttrValue->fAttributeValueData.fBufferLength = uiDataLen;
pOutAttrValue->fAttributeValueID = CalcCRC( pLDAPAttrType + 1 );
memcpy( pOutAttrValue->fAttributeValueData.fBufferData, pLDAPAttrType + 1, uiDataLen );
}
bFoundIt = true;
}
}
else
{
aHost = pRecContext->fLDAPConnection->LockLDAPSession();
if ( aHost != NULL )
{
if ( (bValues = ldap_get_values_len(aHost, result, pLDAPAttrType)) != NULL )
{
for (int i = 0; bValues[i] != NULL; i++ )
{
valCount++;
if (valCount == inData->fInAttrValueIndex)
{
UInt32 anOffset = 0;
if (bStripCryptPrefix)
{
if ( ( bValues[i]->bv_len > 6) &&
(strncasecmp(bValues[i]->bv_val,"{crypt}",7) == 0) )
{
anOffset = 7;
}
}
uiDataLen = bValues[i]->bv_len - anOffset;
pOutAttrValue = (tAttributeValueEntry *)calloc( 1, sizeof( tAttributeValueEntry ) + uiDataLen + kBuffPad );
pOutAttrValue->fAttributeValueData.fBufferSize = uiDataLen + kBuffPad;
pOutAttrValue->fAttributeValueData.fBufferLength = uiDataLen;
if ( bValues[i]->bv_val != nil )
{
pOutAttrValue->fAttributeValueID = CalcCRC( bValues[i]->bv_val ); memcpy( pOutAttrValue->fAttributeValueData.fBufferData, bValues[i]->bv_val + anOffset, uiDataLen );
}
bFoundIt = true;
break;
} } if (bValues != NULL)
{
ldap_value_free_len(bValues);
bValues = NULL;
}
}
pRecContext->fLDAPConnection->UnlockLDAPSession( aHost, false );
}
}
if (bFoundIt)
{
inData->fOutEntryPtr = pOutAttrValue;
}
if (pLDAPAttrType != nil)
{
delete (pLDAPAttrType);
pLDAPAttrType = nil;
}
numAttributes++;
pLDAPAttrType = MapAttrToLDAPType( pRecContext, (const char *)(pRecContext->fOpenRecordType), pAttrType->fBufferData, numAttributes );
}
if (!bFoundIt)
{
if (valCount < inData->fInAttrValueIndex)
{
siResult = eDSIndexOutOfRange;
}
else
{
siResult = eDSAttributeNotFound;
}
}
} else
{
siResult = eDSRecordNotFound;
}
if (pLDAPAttrType != nil)
{
delete( pLDAPAttrType );
pLDAPAttrType = nil;
}
}
catch ( tDirStatus err )
{
siResult = err;
}
if (attrs != nil)
{
int aIndex = 0;
while (attrs[aIndex] != nil)
{
free(attrs[aIndex]);
attrs[aIndex] = nil;
aIndex++;
}
free(attrs);
attrs = nil;
}
if ( result != nil )
{
ldap_msgfree( result );
result = nil;
}
DSRelease( pRecContext );
return( siResult );
}
tDirStatus CLDAPv3Plugin::GetRecAttrValueByValue ( sGetRecordAttributeValueByValue *inData )
{
tDirStatus siResult = eDSNoErr;
UInt32 uiDataLen = 0;
tDataNodePtr pAttrType = nil;
char *pLDAPAttrType = nil;
tAttributeValueEntryPtr pOutAttrValue = nil;
sLDAPContextData *pRecContext = nil;
LDAPMessage *result = nil;
struct berval **bValues;
bool bFoundIt = false;
int numAttributes = 1;
UInt32 literalLength = 0;
bool bStripCryptPrefix = false;
LDAP *aHost = nil;
char **attrs = nil;
char *attrValue = nil;
UInt32 attrLength = 0;
try
{
pRecContext = gLDAPContextTable->GetObjectForRefNum( inData->fInRecRef );
if ( pRecContext == nil ) throw( eDSBadContextData );
pAttrType = inData->fInAttrType;
if ( pAttrType == nil ) throw( eDSEmptyAttributeType );
if ( pAttrType->fBufferData == nil ) throw( eDSEmptyAttributeType );
attrLength = inData->fInAttrValue->fBufferLength;
attrValue = (char *) calloc(1, 1 + attrLength);
memcpy(attrValue, inData->fInAttrValue->fBufferData, attrLength);
attrs = MapAttrToLDAPTypeArray( pRecContext, pRecContext->fOpenRecordType, pAttrType->fBufferData );
if ( attrs == nil ) throw( eDSInvalidAttributeType );
siResult = (tDirStatus)GetRecLDAPMessage( pRecContext, attrs, &result );
if ( siResult != eDSNoErr ) throw( siResult);
if ( result != nil )
{
if (strcmp( kDS1AttrPasswordPlus, pAttrType->fBufferData ) == 0)
{
bStripCryptPrefix = true;
}
numAttributes = 1;
pLDAPAttrType = MapAttrToLDAPType( pRecContext, (const char *)(pRecContext->fOpenRecordType), pAttrType->fBufferData, numAttributes );
if ( pLDAPAttrType == nil ) throw( eDSInvalidAttributeType );
bFoundIt = false;
while ( ( pLDAPAttrType != nil ) && (!bFoundIt) )
{
if (pLDAPAttrType[0] == '#')
{
literalLength = strlen(pLDAPAttrType + 1);
if ( literalLength > 0 )
{
char *vsReturnStr = nil;
vsReturnStr = MappingNativeVariableSubstitution( pLDAPAttrType, pRecContext, result, siResult );
if ( (vsReturnStr != nil) && (memcmp(vsReturnStr, attrValue, attrLength) == 0 ) )
{
bFoundIt = true;
uiDataLen = strlen(vsReturnStr + 1);
pOutAttrValue = (tAttributeValueEntry *)calloc( 1, sizeof( tAttributeValueEntry ) + uiDataLen + kBuffPad );
pOutAttrValue->fAttributeValueData.fBufferSize = uiDataLen + kBuffPad;
pOutAttrValue->fAttributeValueData.fBufferLength = uiDataLen;
pOutAttrValue->fAttributeValueID = CalcCRC( pLDAPAttrType + 1 );
memcpy( pOutAttrValue->fAttributeValueData.fBufferData, vsReturnStr + 1, uiDataLen );
free(vsReturnStr);
vsReturnStr = nil;
}
}
}
else
{
aHost = pRecContext->fLDAPConnection->LockLDAPSession();
if ( aHost != NULL )
{
if ( (bValues = ldap_get_values_len(aHost, result, pLDAPAttrType)) != NULL )
{
for (int i = 0; bValues[i] != NULL; i++ )
{
UInt32 anOffset = 0;
if (bStripCryptPrefix)
{
if ( ( bValues[i]->bv_len > 6) &&
(strncasecmp(bValues[i]->bv_val,"{crypt}",7) == 0) )
{
anOffset = 7;
}
}
if (memcmp((bValues[i]->bv_val)+anOffset, attrValue, attrLength-anOffset) == 0 )
{
uiDataLen = bValues[i]->bv_len - anOffset;
pOutAttrValue = (tAttributeValueEntry *)calloc( 1, sizeof( tAttributeValueEntry ) + uiDataLen + kBuffPad );
pOutAttrValue->fAttributeValueData.fBufferSize = uiDataLen + kBuffPad;
pOutAttrValue->fAttributeValueData.fBufferLength = uiDataLen;
if ( bValues[i]->bv_val != nil )
{
pOutAttrValue->fAttributeValueID = CalcCRC( bValues[i]->bv_val ); memcpy( pOutAttrValue->fAttributeValueData.fBufferData, bValues[i]->bv_val + anOffset, uiDataLen );
}
bFoundIt = true;
break;
}
} if (bValues != NULL)
{
ldap_value_free_len(bValues);
bValues = NULL;
}
}
pRecContext->fLDAPConnection->UnlockLDAPSession( aHost, false );
}
}
if (bFoundIt)
{
inData->fOutEntryPtr = pOutAttrValue;
}
if (pLDAPAttrType != nil)
{
delete (pLDAPAttrType);
pLDAPAttrType = nil;
}
numAttributes++;
pLDAPAttrType = MapAttrToLDAPType( pRecContext, (const char *)(pRecContext->fOpenRecordType), pAttrType->fBufferData, numAttributes );
}
if (!bFoundIt)
{
siResult = eDSAttributeNotFound;
}
} else
{
siResult = eDSRecordNotFound;
}
if (pLDAPAttrType != nil)
{
delete( pLDAPAttrType );
pLDAPAttrType = nil;
}
}
catch ( tDirStatus err )
{
siResult = err;
}
if (attrs != nil)
{
int aIndex = 0;
while (attrs[aIndex] != nil)
{
free(attrs[aIndex]);
attrs[aIndex] = nil;
aIndex++;
}
free(attrs);
attrs = nil;
}
if (attrValue != nil)
{
free(attrValue);
attrValue = nil;
}
if ( result != nil )
{
ldap_msgfree( result );
result = nil;
}
DSRelease( pRecContext );
return( siResult );
}
tDirStatus CLDAPv3Plugin::GetRecAttrValueByID ( sGetRecordAttributeValueByID *inData )
{
tDirStatus siResult = eDSAttributeNotFound;
UInt32 uiDataLen = 0;
tDataNodePtr pAttrType = nil;
char *pLDAPAttrType = nil;
tAttributeValueEntryPtr pOutAttrValue = nil;
sLDAPContextData *pRecContext = nil;
LDAPMessage *result = nil;
struct berval **bValues;
bool bFoundIt = false;
int numAttributes = 1;
UInt32 crcVal = 0;
UInt32 literalLength = 0;
bool bStripCryptPrefix = false;
LDAP *aHost = nil;
char **attrs = nil;
try
{
pRecContext = gLDAPContextTable->GetObjectForRefNum( inData->fInRecRef );
if ( pRecContext == nil ) throw( eDSBadContextData );
pAttrType = inData->fInAttrType;
if ( pAttrType == nil ) throw( eDSEmptyAttributeType );
if ( pAttrType->fBufferData == nil ) throw( eDSEmptyAttributeType );
attrs = MapAttrToLDAPTypeArray( pRecContext, pRecContext->fOpenRecordType, pAttrType->fBufferData );
if ( attrs == nil ) throw( eDSInvalidAttributeType );
siResult = (tDirStatus)GetRecLDAPMessage( pRecContext, attrs, &result );
if ( siResult != eDSNoErr ) throw( siResult);
if ( result != nil )
{
if (strcmp( kDS1AttrPasswordPlus, pAttrType->fBufferData ) == 0)
{
bStripCryptPrefix = true;
}
numAttributes = 1;
pLDAPAttrType = MapAttrToLDAPType( pRecContext, (const char *)(pRecContext->fOpenRecordType), pAttrType->fBufferData, numAttributes );
if ( pLDAPAttrType == nil ) throw( eDSInvalidAttributeType );
siResult = eDSAttributeValueNotFound;
bFoundIt = false;
while ( ( pLDAPAttrType != nil ) && (!bFoundIt) )
{
if (pLDAPAttrType[0] == '#')
{
literalLength = strlen(pLDAPAttrType + 1);
if (literalLength > 0)
{
crcVal = CalcCRC( pLDAPAttrType + 1 );
if ( crcVal == inData->fInValueID )
{
char *vsReturnStr = nil;
vsReturnStr = MappingNativeVariableSubstitution( pLDAPAttrType, pRecContext, result, siResult );
if (vsReturnStr != nil)
{
uiDataLen = strlen(vsReturnStr + 1);
pOutAttrValue = (tAttributeValueEntry *)calloc( 1, sizeof( tAttributeValueEntry ) + uiDataLen + kBuffPad );
pOutAttrValue->fAttributeValueData.fBufferSize = uiDataLen + kBuffPad;
pOutAttrValue->fAttributeValueData.fBufferLength = uiDataLen;
pOutAttrValue->fAttributeValueID = crcVal;
memcpy( pOutAttrValue->fAttributeValueData.fBufferData, vsReturnStr + 1, uiDataLen );
free(vsReturnStr);
vsReturnStr = nil;
}
else
{
if (siResult != eDSNoErr) throw (siResult);
uiDataLen = literalLength;
pOutAttrValue = (tAttributeValueEntry *)calloc( 1, sizeof( tAttributeValueEntry ) + uiDataLen + kBuffPad );
pOutAttrValue->fAttributeValueData.fBufferSize = uiDataLen + kBuffPad;
pOutAttrValue->fAttributeValueData.fBufferLength = uiDataLen;
pOutAttrValue->fAttributeValueID = crcVal;
memcpy( pOutAttrValue->fAttributeValueData.fBufferData, pLDAPAttrType + 1, uiDataLen );
}
bFoundIt = true;
siResult = eDSNoErr;
}
}
}
else
{
aHost = pRecContext->fLDAPConnection->LockLDAPSession();
if ( aHost != NULL )
{
if ( (bValues = ldap_get_values_len(aHost, result, pLDAPAttrType)) != NULL )
{
for (int i = 0; bValues[i] != NULL; i++ )
{
crcVal = CalcCRC( bValues[i]->bv_val );
if ( crcVal == inData->fInValueID )
{
UInt32 anOffset = 0;
if (bStripCryptPrefix)
{
if ( ( bValues[i]->bv_len > 6) &&
(strncasecmp(bValues[i]->bv_val,"{crypt}",7) == 0) )
{
anOffset = 7;
}
}
uiDataLen = bValues[i]->bv_len - anOffset;
pOutAttrValue = (tAttributeValueEntry *)calloc( 1, sizeof( tAttributeValueEntry ) + uiDataLen + kBuffPad );
pOutAttrValue->fAttributeValueData.fBufferSize = uiDataLen + kBuffPad;
pOutAttrValue->fAttributeValueData.fBufferLength = uiDataLen;
if ( bValues[i]->bv_val != nil )
{
pOutAttrValue->fAttributeValueID = crcVal;
memcpy( pOutAttrValue->fAttributeValueData.fBufferData, bValues[i]->bv_val + anOffset, uiDataLen );
}
bFoundIt = true;
siResult = eDSNoErr;
break;
} } ldap_value_free_len(bValues);
bValues = NULL;
} pRecContext->fLDAPConnection->UnlockLDAPSession( aHost, false );
}
}
if (bFoundIt)
{
inData->fOutEntryPtr = pOutAttrValue;
}
if (pLDAPAttrType != nil)
{
delete (pLDAPAttrType);
pLDAPAttrType = nil;
}
numAttributes++;
pLDAPAttrType = MapAttrToLDAPType( pRecContext, (const char *)(pRecContext->fOpenRecordType), pAttrType->fBufferData, numAttributes );
}
}
if (pLDAPAttrType != nil)
{
delete( pLDAPAttrType );
pLDAPAttrType = nil;
}
}
catch ( tDirStatus err )
{
siResult = err;
}
if (attrs != nil)
{
int aIndex = 0;
while (attrs[aIndex] != nil)
{
free(attrs[aIndex]);
attrs[aIndex] = nil;
aIndex++;
}
free(attrs);
attrs = nil;
}
if ( result != nil )
{
ldap_msgfree( result );
result = nil;
}
DSRelease( pRecContext );
return( siResult );
}
char* CLDAPv3Plugin::GetNextStdAttrType ( char *inRecType, sLDAPContextData *inContext, int &inputIndex )
{
char *outResult = nil;
if (inputIndex > 0)
{
outResult = ExtractStdAttrName( inContext, inRecType, inputIndex );
}
return( outResult );
}
tDirStatus CLDAPv3Plugin::DoAttributeValueSearch ( sDoAttrValueSearch *inData )
{
return this->DoAttributeValueSearchWithData( (sDoAttrValueSearchWithData *)inData );
}
tDirStatus CLDAPv3Plugin::DoAttributeValueSearchWithData( sDoAttrValueSearchWithData *inData )
{
tDirStatus siResult = eDSNoErr;
SInt32 siCBuffErr = 0;
bool bAttribOnly = false;
UInt32 uiCount = 0;
UInt32 uiTotal = 0;
char **pRecTypes = nil;
CAttributeList *cpAttrTypeList = nil;
char **pSearchStrings = nil;
char *pAttrType = nil;
char *pLDAPSearchBase = nil;
tDirPatternMatch pattMatch = eDSExact;
sLDAPContextData *pContext = nil;
sLDAPContinueData *pLDAPContinue = nil;
CBuff *outBuff = nil;
tDataList *pTmpDataList = nil;
UInt32 countDownRecTypes = 0;
bool bOCANDGroup = false;
CFArrayRef OCSearchList = nil;
ber_int_t scope = LDAP_SCOPE_SUBTREE;
UInt32 strCount = 0;
tContextData uiContinue = 0;
if ( inData == nil ) return( eMemoryError );
if ( inData->fOutDataBuff == nil ) return( eDSEmptyBuffer );
if ( inData->fOutDataBuff->fBufferSize == 0 ) return( eDSEmptyBuffer );
if ( inData->fInRecTypeList == nil ) return( eDSEmptyRecordTypeList );
pContext = gLDAPContextTable->GetObjectForRefNum( inData->fInNodeRef );
if ( pContext == nil ) return( eDSBadContextData );
if ( pContext->fLDAPConnection->ConnectionStatus() != kConnectionSafe ) return eDSCannotAccessSession;
try
{
if ( inData->fIOContinueData == 0 )
{
pLDAPContinue = new sLDAPContinueData;
uiContinue = gLDAPContinueTable->AddPointer( pLDAPContinue->Retain(), inData->fInNodeRef );
pLDAPContinue->fLDAPConnection = pContext->fLDAPConnection->Retain();
pLDAPContinue->fNodeRef = inData->fInNodeRef;
pLDAPContinue->fRecNameIndex = 1;
pLDAPContinue->fRecTypeIndex = 1;
pLDAPContinue->fTotalRecCount = 0;
pLDAPContinue->fLimitRecSearch = (inData->fOutMatchRecordCount >= 0 ? inData->fOutMatchRecordCount : 0);
}
else
{
pLDAPContinue = (sLDAPContinueData *) gLDAPContinueTable->GetPointer( inData->fIOContinueData );
if ( pLDAPContinue == NULL ) throw( eDSInvalidContinueData );
pLDAPContinue->Retain();
uiContinue = inData->fIOContinueData;
}
inData->fIOContinueData = nil;
inData->fOutMatchRecordCount = 0;
outBuff = new CBuff();
if ( outBuff == nil ) throw( eMemoryError );
siCBuffErr = outBuff->Initialize( inData->fOutDataBuff, true );
if ( siCBuffErr != eDSNoErr ) throw( (tDirStatus)siCBuffErr );
if ( (siCBuffErr = outBuff->GetBuffStatus()) != eDSNoErr )
throw( (tDirStatus)siCBuffErr );
if ( (siCBuffErr = outBuff->SetBuffType('StdA')) != eDSNoErr )
throw( (tDirStatus)siCBuffErr );
pRecTypes = dsAllocStringsFromList(0, inData->fInRecTypeList);
if ( pRecTypes == nil ) throw( eDSEmptyRecordTypeList );
bool bResetRecTypes = false;
while(pRecTypes[strCount] != nil)
{
if (strcmp(pRecTypes[strCount], kDSStdRecordTypeAll) == 0)
{
bResetRecTypes = true;
}
strCount++;
}
if (strCount == 0) throw( eDSEmptyRecordTypeList );
if (bResetRecTypes && pContext->fLDAPConnection->fNodeConfig != NULL )
{
DSFreeStringList(pRecTypes);
strCount = 0;
UInt32 i = 0;
CFDictionaryRef cfNormalizedMap = pContext->fLDAPConnection->fNodeConfig->CopyNormalizedMappings();
if( cfNormalizedMap != nil )
{
strCount = CFDictionaryGetCount( cfNormalizedMap );
if( strCount )
{
CFStringRef *keys = (CFStringRef *) calloc( strCount, sizeof(CFStringRef) );
pRecTypes = (char **) calloc(strCount+1, sizeof(char *));
CFDictionaryGetKeysAndValues( cfNormalizedMap, (const void **)keys, NULL );
for( i = 0; i < strCount; i++ )
{
CFIndex uiLength = CFStringGetMaximumSizeForEncoding( CFStringGetLength(keys[i]), kCFStringEncodingUTF8 );
pRecTypes[i] = (char *) calloc( uiLength, sizeof(char) );
CFStringGetCString( keys[i], pRecTypes[i], uiLength, kCFStringEncodingUTF8 );
}
DSFree( keys );
}
DSCFRelease( cfNormalizedMap );
}
if (strCount == 0) throw( eDSEmptyRecordTypeList );
}
countDownRecTypes = strCount - pLDAPContinue->fRecTypeIndex + 1;
pattMatch = inData->fInPattMatchType;
pAttrType = inData->fInAttrType->fBufferData;
if ( (pattMatch == eDSCompoundExpression) ||
(pattMatch == eDSiCompoundExpression) )
{
pAttrType = (char *) ""; }
else
{
if ( pAttrType == nil ) throw( eDSEmptyAttributeType );
}
if ( inData->fType == kDoAttributeValueSearchWithData || inData->fType == kDoAttributeValueSearch )
{
pSearchStrings = (char **) calloc(2, sizeof(char *));
pSearchStrings[0] = strdup(inData->fInPatt2Match->fBufferData);
if ( pSearchStrings == nil ) throw( eDSEmptyPattern2Match );
}
else
{
pSearchStrings = dsAllocStringsFromList(0, ((sDoMultiAttrValueSearchWithData *) inData)->fInPatterns2MatchList);
if ( pSearchStrings == nil ) throw( eDSEmptyPattern2Match );
}
if ( inData->fType == kDoAttributeValueSearchWithData || inData->fType == kDoMultipleAttributeValueSearchWithData )
{
cpAttrTypeList = new CAttributeList( inData->fInAttrTypeRequestList );
bAttribOnly = inData->fInAttrInfoOnly;
}
else
{
pTmpDataList = dsBuildListFromStringsPriv( kDSAttributesAll, nil );
if ( pTmpDataList != nil )
cpAttrTypeList = new CAttributeList( pTmpDataList );
}
if ( cpAttrTypeList == nil || cpAttrTypeList->GetCount() == 0 )
throw( eDSEmptyAttributeTypeList );
while ( siResult == eDSNoErr && pRecTypes[pLDAPContinue->fRecTypeIndex-1] != NULL )
{
pLDAPSearchBase = MapRecToSearchBase( pContext, pRecTypes[pLDAPContinue->fRecTypeIndex-1], 1, &bOCANDGroup, &OCSearchList, &scope );
if ( pLDAPSearchBase == NULL )
{
pLDAPContinue->fRecTypeIndex++;
continue;
}
if ( (strcmp( pAttrType, kDSAttributesAll ) == 0 ) ||
(strcmp( pAttrType, kDSAttributesStandardAll ) == 0 ) ||
(strcmp( pAttrType, kDSAttributesNativeAll ) == 0 ) )
{
siResult = GetTheseRecords( nil, pSearchStrings, pRecTypes[pLDAPContinue->fRecTypeIndex-1], pLDAPSearchBase,
pattMatch, cpAttrTypeList, pContext, pLDAPContinue, bAttribOnly, outBuff, uiCount,
bOCANDGroup, OCSearchList, scope );
}
else
{
siResult = GetTheseRecords( pAttrType, pSearchStrings, pRecTypes[pLDAPContinue->fRecTypeIndex-1], pLDAPSearchBase,
pattMatch, cpAttrTypeList, pContext, pLDAPContinue, bAttribOnly, outBuff, uiCount,
bOCANDGroup, OCSearchList, scope );
}
bOCANDGroup = false;
DSDelete( pLDAPSearchBase );
DSCFRelease( OCSearchList );
uiTotal += uiCount;
if ( siResult == eDSBufferTooSmall )
{
inData->fIOContinueData = uiContinue;
if ( uiTotal != 0 )
siResult = eDSNoErr;
break;
}
else if ( siResult == eDSNoErr )
{
pLDAPContinue->fRecTypeIndex++;
}
}
if ( uiTotal == 0 )
outBuff->ClearBuff();
}
catch ( tDirStatus err )
{
siResult = err;
}
if ( uiTotal > 0 )
{
inData->fOutMatchRecordCount = uiTotal;
outBuff->SetLengthToSize();
}
if ( (inData->fIOContinueData == 0) && (pLDAPContinue != nil) )
{
gLDAPContinueTable->RemoveContext( uiContinue );
}
DSRelease( pLDAPContinue );
DSDelete( pLDAPSearchBase );
DSDelete( cpAttrTypeList );
DSDelete( outBuff );
DSFreeStringList( pSearchStrings );
DSFreeStringList( pRecTypes );
DSRelease( pContext );
if ( pTmpDataList != nil )
{
dsDataListDeallocatePriv( pTmpDataList );
free(pTmpDataList);
pTmpDataList = nil;
}
return( siResult );
}
bool CLDAPv3Plugin::DoTheseAttributesMatch( sLDAPContextData *inContext,
char *inAttrName,
tDirPatternMatch pattMatch,
LDAPMessage *inResult)
{
char *pAttr = nil;
char *pVal = nil;
BerElement *ber = nil;
struct berval **bValues;
bool bFoundMatch = false;
LDAP *aHost = nil;
aHost = inContext->fLDAPConnection->LockLDAPSession();
if (aHost != NULL)
{
for ( pAttr = ldap_first_attribute(aHost, inResult, &ber );
pAttr != NULL; pAttr = ldap_next_attribute(aHost, inResult, ber ) )
{
if (( bValues = ldap_get_values_len(aHost, inResult, pAttr )) != NULL)
{
for (int i = 0; bValues[i] != NULL; i++ )
{
pVal = (char *) calloc(1,bValues[i]->bv_len + 1);
memcpy(pVal, bValues[i]->bv_val, bValues[i]->bv_len);
if (DoesThisMatch(pVal, inAttrName, pattMatch))
{
bFoundMatch = true;
free(pVal);
pVal = nil;
break;
}
else
{
free(pVal);
pVal = nil;
}
} ldap_value_free_len(bValues);
bValues = NULL;
if (bFoundMatch)
{
if (pAttr != nil)
{
ldap_memfree( pAttr );
}
break;
}
}
if (pAttr != nil)
{
ldap_memfree( pAttr );
}
} inContext->fLDAPConnection->UnlockLDAPSession( aHost, false );
}
if (ber != nil)
{
ber_free( ber, 0 );
}
return( bFoundMatch );
}
bool CLDAPv3Plugin::DoAnyOfTheseAttributesMatch( sLDAPContextData *inContext,
char **inAttrNames,
tDirPatternMatch pattMatch,
LDAPMessage *inResult)
{
char *pAttr = nil;
char *pVal = nil;
BerElement *ber = nil;
struct berval **bValues;
bool bFoundMatch = false;
LDAP *aHost = nil;
ber_len_t bvlen = 0;
switch ( pattMatch )
{
case eDSCompoundExpression:
case eDSWildCardPattern:
case eDSRegularExpression:
case eDSiCompoundExpression:
case eDSiWildCardPattern:
case eDSiRegularExpression:
case eDSAnyMatch:
return true;
default:
break;
}
aHost = inContext->fLDAPConnection->LockLDAPSession();
if ( aHost != NULL )
{
if ( inResult != nil )
{
for ( pAttr = ldap_first_attribute(aHost, inResult, &ber);
pAttr != NULL; pAttr = ldap_next_attribute(aHost, inResult, ber) )
{
if ( (bValues = ldap_get_values_len(aHost, inResult, pAttr)) != NULL)
{
for ( int i = 0; bValues[i] != NULL; i++ )
{
pVal = (char *) malloc((bvlen = bValues[i]->bv_len) + 1);
memcpy(pVal, bValues[i]->bv_val, bvlen);
pVal[bvlen] = '\0';
if (DoAnyMatch(pVal, inAttrNames, pattMatch))
{
bFoundMatch = true;
free(pVal);
pVal = nil;
break;
}
else
{
free(pVal);
pVal = nil;
}
} ldap_value_free_len(bValues);
bValues = NULL;
if (bFoundMatch)
{
if (pAttr != nil)
{
ldap_memfree( pAttr );
}
break;
}
}
if (pAttr != nil)
{
ldap_memfree( pAttr );
}
} } inContext->fLDAPConnection->UnlockLDAPSession( aHost, false );
}
if (ber != nil)
{
ber_free( ber, 0 );
}
return( bFoundMatch );
}
bool CLDAPv3Plugin::DoAnyMatch ( const char *inString,
char **inPatterns,
tDirPatternMatch inPattMatch )
{
const char *p = nil;
bool bMatched = false;
char *string1;
char *string2;
UInt32 length1 = 0;
UInt32 length2 = 0;
UInt32 uMatch = 0;
UInt16 usIndex = 0;
if ( (inString == nil) || (inPatterns == nil) )
return( false );
uMatch = (UInt32) inPattMatch;
length1 = strlen(inString);
if ( (inPattMatch >= eDSExact) && (inPattMatch <= eDSRegularExpression) )
{
string1 = strdup(inString);
}
else
{
string1 = (char *) malloc(length1 + 1);
p = inString;
for ( usIndex = 0; usIndex < length1; usIndex++ )
string1[usIndex] = toupper( *p++ );
string1[length1] = '\0';
}
UInt32 strCount = 0;
while(inPatterns[strCount] != nil)
{
length2 = strlen(inPatterns[strCount]);
if ( (inPattMatch >= eDSExact) && (inPattMatch <= eDSRegularExpression) )
{
string2 = strdup( inPatterns[strCount] );
}
else
{
string2 = (char *) malloc(length2 + 1);
p = inPatterns[strCount];
for ( usIndex = 0; usIndex < length2; usIndex++ )
string2[usIndex] = toupper( *p++ );
string2[length2] = '\0';
}
switch ( uMatch )
{
case eDSExact:
case eDSiExact:
{
if ( strcmp( string1, string2 ) == 0 )
{
bMatched = true;
}
}
break;
case eDSStartsWith:
case eDSiStartsWith:
{
if ( strncmp( string1, string2, length2 ) == 0 )
{
bMatched = true;
}
}
break;
case eDSEndsWith:
case eDSiEndsWith:
{
if ( length1 >= length2 )
{
if ( strcmp( string1 + length1 - length2, string2 ) == 0 )
{
bMatched = true;
}
}
}
break;
case eDSContains:
case eDSiContains:
{
if ( length1 >= length2 )
{
if ( strstr( string1, string2 ) != nil )
{
bMatched = true;
}
}
}
break;
case eDSLessThan:
case eDSiLessThan:
{
if ( strcmp( string1, string2 ) < 0 )
{
bMatched = true;
}
}
break;
case eDSGreaterThan:
case eDSiGreaterThan:
{
if ( strcmp( string1, string2 ) > 0 )
{
bMatched = true;
}
}
break;
case eDSLessEqual:
case eDSiLessEqual:
{
if ( strcmp( string1, string2 ) <= 0 )
{
bMatched = true;
}
}
break;
case eDSGreaterEqual:
case eDSiGreaterEqual:
{
if ( strcmp( string1, string2 ) >= 0 )
{
bMatched = true;
}
}
break;
case eDSAnyMatch:
default:
break;
}
if (string2 != nil)
{
delete(string2);
}
if (bMatched)
{
break;
}
strCount++;
}
DSFreeString(string1);
return( bMatched );
}
tDirStatus CLDAPv3Plugin::SetAttributeValueForDN( sLDAPContextData *inContext, char *inDN, const char *inRecordType, const char *inAttrType, const char **inValues )
{
tDirStatus siResult = eDSNoErr;
char *pLDAPAttrType = NULL;
if( inValues != NULL && *inValues != NULL )
{
pLDAPAttrType = MapAttrToLDAPType( inContext, (const char *)inRecordType, inAttrType, 1, true );
if( pLDAPAttrType != NULL )
{
LDAPMod stMod = { 0 };
int ldapReturnCode = 0;
berval **bvals = NULL;
LDAPMod *pMods[2];
while( *inValues )
{
berval *bval = (berval *) calloc( sizeof(berval), 1 );
if( bval != NULL ) {
bval->bv_val = (char *) *inValues;
bval->bv_len = strlen( *inValues );
ber_bvecadd( &bvals, bval );
}
else
{
siResult = eMemoryAllocError;
break;
}
inValues++;
};
if( bvals != NULL && siResult == eDSNoErr )
{
stMod.mod_op = LDAP_MOD_REPLACE | LDAP_MOD_BVALUES;
stMod.mod_type = pLDAPAttrType;
stMod.mod_bvalues = bvals;
pMods[0] = &stMod;
pMods[1] = NULL;
LDAP *aHost = inContext->fLDAPConnection->LockLDAPSession();
if( aHost != NULL )
{
ldapReturnCode = ldap_modify_s( aHost, inDN, pMods );
inContext->fLDAPConnection->UnlockLDAPSession( aHost, false );
}
else
{
ldapReturnCode = LDAP_LOCAL_ERROR;
}
if( ldapReturnCode != LDAP_SUCCESS )
{
siResult = MapLDAPWriteErrorToDS( ldapReturnCode, eDSAttributeNotFound );
}
}
delete( pLDAPAttrType );
pLDAPAttrType = NULL;
if( bvals )
{
ber_memvfree( (void **) bvals );
bvals = NULL;
}
} else
{
siResult = eDSNoStdMappingAvailable;
}
}
else
{
siResult = eDSNullParameter;
}
return( siResult );
}
SInt32
CLDAPv3Plugin::GetAuthAuthority( sLDAPContextData *inContext, const char *userName, int inUserNameBufferLength,
UInt32 *outAuthCount, char **outAuthAuthority[], const char *inRecordType )
{
tDataBufferPtr aaBuffer = NULL;
if ( userName == NULL )
return eDSNullDataBuff;
int nameLen = strlen( userName );
if ( inUserNameBufferLength > nameLen + (int)sizeof(kDSNameAndAATag) &&
strncmp(userName + nameLen + 1, kDSNameAndAATag, sizeof(kDSNameAndAATag) - 1) == 0 )
{
aaBuffer = (tDataBufferPtr)(userName + nameLen + sizeof(kDSNameAndAATag));
return UnpackUserWithAABuffer( aaBuffer, outAuthCount, outAuthAuthority );
}
return LookupAttribute( inContext, inRecordType, userName, kDSNAttrAuthenticationAuthority, outAuthCount, outAuthAuthority );
}
tDirStatus CLDAPv3Plugin::LookupAttribute ( sLDAPContextData *inContext,
const char *inRecordType,
const char *inRecordName,
const char *inAttribute,
UInt32 *outCount,
char **outData[] )
{
tDirStatus siResult = eDSRecordNotFound;
char *valueData = nil;
char *pLDAPSearchBase = nil;
char *queryFilter = nil;
LDAPMessage *result = nil;
LDAPMessage *entry = nil;
char *attr = nil;
BerElement *ber = nil;
int numRecTypes = 1;
char **attrs = nil;
bool bOCANDGroup = false;
CFArrayRef OCSearchList = nil;
struct berval **berVal = nil;
ber_int_t scope = LDAP_SCOPE_SUBTREE;
char *pLDAPAttrType = nil;
tDirStatus searchResult = eDSNoErr;
if ( inContext == nil ) return( eDSBadContextData );
if ( inRecordName == nil ) return( eDSNullDataBuff );
if ( outData == nil ) return( eDSNullParameter );
try
{
*outCount = 0;
*outData = nil;
attrs = MapAttrToLDAPTypeArray( inContext, inRecordType, inAttribute );
if ( attrs == nil ) throw( eDSInvalidAttributeType );
if (*attrs == nil) {
pLDAPAttrType = MapAttrToLDAPType( inContext,inRecordType, inAttribute, 1, false );
if (pLDAPAttrType != nil)
{
*outData = (char **)calloc( 2, sizeof(char *) );
(*outData)[0] = pLDAPAttrType;
siResult = eDSNoErr;
}
}
else {
DbgLog( kLogPlugin, "CLDAPv3Plugin: Attempting to get %s", inAttribute );
pLDAPSearchBase = MapRecToSearchBase( inContext, inRecordType, numRecTypes, &bOCANDGroup, &OCSearchList, &scope );
if ( pLDAPSearchBase == nil ) throw( eDSInvalidRecordType );
while ( pLDAPSearchBase != nil )
{
queryFilter = BuildLDAPQueryFilter(
inContext,
(char *)kDSNAttrRecordName,
inRecordName,
eDSExact,
false,
inRecordType,
pLDAPSearchBase,
bOCANDGroup,
OCSearchList );
if ( queryFilter == nil ) throw( eDSNoStdMappingAvailable );
searchResult = DSRetrieveSynchronous( pLDAPSearchBase, attrs, inContext, scope, queryFilter, &result, NULL );
if ( searchResult == eDSNoErr || searchResult == eDSCannotAccessSession )
break;
DSDelete( queryFilter );
DSDelete( pLDAPSearchBase );
DSCFRelease( OCSearchList );
numRecTypes++;
bOCANDGroup = false;
pLDAPSearchBase = MapRecToSearchBase( inContext, inRecordType, numRecTypes, &bOCANDGroup, &OCSearchList, &scope );
}
if ( searchResult == eDSNoErr )
siResult = eDSAttributeNotFound;
if ( searchResult == eDSNoErr && result != NULL )
{
LDAP *aHost = inContext->fLDAPConnection->LockLDAPSession();
if (aHost != NULL)
{
entry = ldap_first_entry( aHost, result );
if ( entry != nil )
{
attr = ldap_first_attribute( aHost, entry, &ber );
if ( attr != nil )
{
int idx;
int numValues = 0;
berVal = ldap_get_values_len( aHost, entry, attr );
if ( berVal != nil )
{
numValues = ldap_count_values_len( berVal );
if ( numValues > 0 )
{
*outCount = numValues;
*outData = (char **)calloc( numValues+1, sizeof(char *) );
}
for ( idx = 0; idx < numValues; idx++ )
{
valueData = dsCStrFromCharacters( berVal[idx]->bv_val, berVal[idx]->bv_len );
if ( valueData == nil )
{
inContext->fLDAPConnection->UnlockLDAPSession( aHost, false );
throw ( eMemoryError );
}
DbgLog( kLogPlugin, "CLDAPv3Plugin: LookupAttribute value found %s\n", valueData );
(*outData)[idx] = valueData;
}
siResult = eDSNoErr;
ldap_value_free_len( berVal );
berVal = nil;
}
ldap_memfree( attr );
attr = nil;
}
if ( ber != nil )
{
ber_free( ber, 0 );
}
}
inContext->fLDAPConnection->UnlockLDAPSession( aHost, false );
} } } }
catch ( tDirStatus err )
{
DbgLog( kLogPlugin, "CLDAPv3Plugin: LookupAttribute error %l", err );
siResult = err;
}
DSDelete( pLDAPSearchBase );
DSCFRelease( OCSearchList );
DSFreeStringList( attrs );
DSDelete( queryFilter );
if ( result != nil )
{
ldap_msgfree( result );
result = nil;
}
return( siResult );
}
tDirStatus CLDAPv3Plugin::DoPlugInCustomCall ( sDoPlugInCustomCall *inData )
{
tDirStatus siResult = eDSNoErr;
OSStatus status = 0;
UInt32 aRequest = 0;
sLDAPContextData *pContext = nil;
SInt32 xmlDataLength = 0;
CFDataRef xmlData = nil;
UInt32 bufLen = 0;
AuthorizationRef authRef = 0;
tDataListPtr dataList = NULL;
char* userName = NULL;
char* password = NULL;
char* xmlString = NULL;
AuthorizationExternalForm blankExtForm;
bool verifyAuthRef = true;
CFRange aRange = { 0, 0 };
char *recordTypeCStr = NULL;
char *recordNameCStr = NULL;
try
{
aRequest = inData->fInRequestCode;
if ( inData == nil ) throw( eDSNullParameter );
if( aRequest != eDSCustomCallLDAPv3ReadConfigDataServerList )
{
if ( inData->fInRequestData == nil ) throw( eDSNullDataBuff );
if ( inData->fInRequestData->fBufferData == nil ) throw( eDSEmptyBuffer );
}
pContext = gLDAPContextTable->GetObjectForRefNum( inData->fInNodeRef );
if ( pContext == nil ) throw( eDSBadContextData );
CLDAPNodeConfig *nodeConfig = pContext->fLDAPConnection->fNodeConfig;
if ( nodeConfig == NULL || aRequest == eDSCustomCallLDAPv3Reinitialize )
{
bufLen = inData->fInRequestData->fBufferLength;
switch ( aRequest )
{
case eDSCustomCallLDAPv3NewServerDiscovery:
case eDSCustomCallLDAPv3NewServerDiscoveryNoDupes:
case eDSCustomCallLDAPv3NewServerVerifySettings:
case eDSCustomCallLDAPv3NewServerGetConfig:
case eDSCustomCallLDAPv3WriteServerMappings:
case eDSCustomCallLDAPv3ReadConfigDataServerList:
break;
default:
if ( bufLen < sizeof( AuthorizationExternalForm ) ) throw( eDSInvalidBuffFormat );
if ( pContext->fEffectiveUID == 0 ) {
bzero(&blankExtForm,sizeof(AuthorizationExternalForm));
if (memcmp(inData->fInRequestData->fBufferData,&blankExtForm,
sizeof(AuthorizationExternalForm)) == 0) {
verifyAuthRef = false;
}
}
if (verifyAuthRef) {
status = AuthorizationCreateFromExternalForm((AuthorizationExternalForm *)inData->fInRequestData->fBufferData,
&authRef);
if (status != errAuthorizationSuccess)
{
DbgLog( kLogPlugin, "CLDAPv3Plugin: AuthorizationCreateFromExternalForm returned error %d", siResult );
throw( eDSPermissionError );
}
AuthorizationItem rights[] = { {"system.services.directory.configure", 0, 0, 0} };
AuthorizationItemSet rightSet = { sizeof(rights)/ sizeof(*rights), rights };
status = AuthorizationCopyRights(authRef, &rightSet, NULL,
kAuthorizationFlagExtendRights, NULL);
if (status != errAuthorizationSuccess)
{
DbgLog( kLogPlugin, "CLDAPv3Plugin: AuthorizationCopyRights returned error %d", siResult );
throw( eDSPermissionError );
}
}
break;
}
switch( aRequest )
{
case eDSCustomCallLDAPv3WriteServerMappings:
dataList = dsAuthBufferGetDataListAllocPriv(inData->fInRequestData);
if ( dataList == nil ) throw( eDSInvalidBuffFormat );
if ( dsDataListGetNodeCountPriv(dataList) != 3 ) throw( eDSInvalidBuffFormat );
userName = dsDataListGetNodeStringPriv(dataList, 1);
if ( userName == nil ) throw( eDSInvalidBuffFormat );
if ( strlen(userName) < 1 ) throw( eDSInvalidBuffFormat );
password = dsDataListGetNodeStringPriv(dataList, 2);
if ( password == nil ) throw( eDSInvalidBuffFormat );
xmlString = dsDataListGetNodeStringPriv(dataList, 3);
if ( xmlString == nil ) throw( eDSInvalidBuffFormat );
xmlData = CFDataCreate(NULL,(UInt8*)xmlString,strlen(xmlString));
siResult = (tDirStatus)fConfigFromXML->WriteServerMappings( userName, password, xmlData );
DSFree( userName );
DSFree( password );
DSFree( xmlString );
DSCFRelease( xmlData );
break;
case eDSCustomCallLDAPv3ReadConfigSize:
if ( inData->fOutRequestResponse == nil ) throw( eDSNullDataBuff );
if ( inData->fOutRequestResponse->fBufferData == nil ) throw( eDSEmptyBuffer );
if ( inData->fOutRequestResponse->fBufferSize < sizeof(int32_t) ) throw( eDSInvalidBuffFormat );
if (fConfigFromXML)
{
xmlData = fConfigFromXML->CopyLiveXMLConfig();
if (xmlData != 0)
{
*(int32_t *)(inData->fOutRequestResponse->fBufferData) = (int32_t) CFDataGetLength(xmlData);
inData->fOutRequestResponse->fBufferLength = sizeof( int32_t );
DSCFRelease( xmlData );
}
}
break;
case eDSCustomCallLDAPv3ReadConfigData:
if ( inData->fOutRequestResponse == nil ) throw( eDSNullDataBuff );
if ( inData->fOutRequestResponse->fBufferData == nil ) throw( eDSEmptyBuffer );
if (fConfigFromXML)
{
xmlData = fConfigFromXML->CopyLiveXMLConfig();
if (xmlData != 0)
{
aRange.location = 0;
aRange.length = CFDataGetLength(xmlData);
if ( inData->fOutRequestResponse->fBufferSize < (unsigned int)aRange.length ) throw( eDSBufferTooSmall );
CFDataGetBytes( xmlData, aRange, (UInt8*)(inData->fOutRequestResponse->fBufferData) );
inData->fOutRequestResponse->fBufferLength = aRange.length;
DSCFRelease(xmlData);
}
}
break;
case eDSCustomCallLDAPv3ReadConfigDataServerList:
if ( inData->fOutRequestResponse == nil ) throw( eDSNullDataBuff );
if ( inData->fOutRequestResponse->fBufferData == nil ) throw( eDSEmptyBuffer );
if (fConfigFromXML)
{
xmlData = fConfigFromXML->CopyLiveXMLConfig();
if (xmlData != 0)
{
CFMutableDictionaryRef serverList = CFDictionaryCreateMutable( kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks );
CFDictionaryRef configDict = (CFDictionaryRef)CFPropertyListCreateFromXMLData( kCFAllocatorDefault, xmlData,
kCFPropertyListImmutable, NULL );
if ( configDict != NULL )
{
CFTypeRef arrays[2] = { CFDictionaryGetValue(configDict, CFSTR(kXMLConfigArrayKey)),
CFDictionaryGetValue(configDict, CFSTR(kXMLDHCPConfigArrayKey)) };
CFMutableArrayRef servers = CFArrayCreateMutable( kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks );
for ( int ii = 0; ii < 2; ii++ )
{
CFArrayRef serverConfigs = (CFArrayRef) arrays[ii];
if ( serverConfigs != NULL && CFArrayGetCount(serverConfigs) > 0 )
{
for ( CFIndex iCnt = 0; iCnt < CFArrayGetCount( serverConfigs ); iCnt++ )
{
CFDictionaryRef serverEntry = (CFDictionaryRef)CFArrayGetValueAtIndex( serverConfigs, iCnt );
CFMutableDictionaryRef listEntry = CFDictionaryCreateMutable( kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks );
if (serverEntry != NULL)
{
if ( ii == 1 )
CFDictionaryAddValue( listEntry, CFSTR(kXMLMakeDefLDAPFlagKey), kCFBooleanTrue );
if ( CFDictionaryContainsKey( serverEntry, CFSTR(kXMLUserDefinedNameKey) ) )
{
CFDictionaryAddValue( listEntry, CFSTR(kXMLUserDefinedNameKey), CFDictionaryGetValue( serverEntry, CFSTR(kXMLUserDefinedNameKey) ) );
}
if ( CFDictionaryContainsKey( serverEntry, CFSTR(kXMLEnableUseFlagKey) ) )
{
CFDictionaryAddValue( listEntry, CFSTR(kXMLEnableUseFlagKey), CFDictionaryGetValue( serverEntry, CFSTR(kXMLEnableUseFlagKey) ) );
}
if ( CFDictionaryContainsKey( serverEntry, CFSTR(kXMLNodeName) ) )
{
CFDictionaryAddValue( listEntry, CFSTR(kXMLNodeName), CFDictionaryGetValue( serverEntry, CFSTR(kXMLNodeName) ) );
}
if ( CFDictionaryContainsKey( serverEntry, CFSTR(kXMLPortNumberKey) ) )
{
CFDictionaryAddValue( listEntry, CFSTR(kXMLPortNumberKey), CFDictionaryGetValue( serverEntry, CFSTR(kXMLPortNumberKey) ) );
}
if ( CFDictionaryContainsKey( serverEntry, CFSTR(kXMLSecureUseFlagKey) ) )
{
CFDictionaryAddValue( listEntry, CFSTR(kXMLSecureUseFlagKey), CFDictionaryGetValue( serverEntry, CFSTR(kXMLSecureUseFlagKey) ) );
}
if ( CFDictionaryContainsKey( serverEntry, CFSTR(kXMLServerKey) ) )
{
CFDictionaryAddValue( listEntry, CFSTR(kXMLServerKey), CFDictionaryGetValue( serverEntry, CFSTR(kXMLServerKey) ) );
}
CFArrayAppendValue( servers, listEntry );
DSCFRelease(listEntry);
}
}
}
}
CFDictionaryAddValue( serverList, CFSTR(kXMLConfigArrayKey), servers );
DSCFRelease(servers);
}
DSCFRelease(configDict);
DSCFRelease(xmlData);
xmlData = CFPropertyListCreateXMLData( kCFAllocatorDefault, serverList);
DSCFRelease(serverList);
aRange.location = 0;
aRange.length = CFDataGetLength(xmlData);
if ( inData->fOutRequestResponse->fBufferSize < (unsigned int)aRange.length ) throw( eDSBufferTooSmall );
CFDataGetBytes( xmlData, aRange, (UInt8*)(inData->fOutRequestResponse->fBufferData) );
inData->fOutRequestResponse->fBufferLength = aRange.length;
DSCFRelease(xmlData);
}
}
break;
case eDSCustomCallLDAPv3WriteConfigData:
{
CFPropertyListRef configPropertyList = NULL;
CFStringRef errorString = NULL;
xmlDataLength = bufLen - sizeof( AuthorizationExternalForm );
if ( xmlDataLength <= 0 ) throw( eDSInvalidBuffFormat );
xmlData = CFDataCreate(NULL,(UInt8 *)(inData->fInRequestData->fBufferData + sizeof( AuthorizationExternalForm )),
xmlDataLength);
if (xmlData != nil)
{
configPropertyList = CFPropertyListCreateFromXMLData( kCFAllocatorDefault,
xmlData,
kCFPropertyListMutableContainers, &errorString);
if (configPropertyList != nil )
{
if ( CFDictionaryGetTypeID() == CFGetTypeID( configPropertyList ) && CFDictionaryContainsKey( (CFDictionaryRef)configPropertyList, CFSTR(kXMLDHCPConfigArrayKey) ) )
{
CFDictionaryRemoveValue( (CFMutableDictionaryRef)configPropertyList, CFSTR(kXMLDHCPConfigArrayKey) );
CFRelease( xmlData );
xmlData = CFPropertyListCreateXMLData( kCFAllocatorDefault, configPropertyList);
}
CFRelease(configPropertyList);
configPropertyList = NULL;
}
}
siResult = (tDirStatus) fConfigFromXML->NewXMLConfig( xmlData );
if ( siResult == eDSNoErr )
Initialize();
DSCFRelease(xmlData);
break;
}
case eDSCustomCallLDAPv3Reinitialize:
if ( nodeConfig != NULL ) {
nodeConfig->ReinitializeReplicaList();
fLDAPConnectionMgr->NodeDeleted( nodeConfig->fNodeName );
}
break;
case eDSCustomCallLDAPv3AddServerConfig:
xmlDataLength = bufLen - sizeof(AuthorizationExternalForm);
if ( xmlDataLength <= 0 ) throw( eDSInvalidBuffFormat );
xmlData = CFDataCreate(NULL, (UInt8 *)(inData->fInRequestData->fBufferData + sizeof(AuthorizationExternalForm)), xmlDataLength);
if (fConfigFromXML)
{
siResult = (tDirStatus)fConfigFromXML->AddToXMLConfig( xmlData );
}
DSCFRelease( xmlData );
break;
case eDSCustomCallLDAPv3NewServerDiscovery:
case eDSCustomCallLDAPv3NewServerDiscoveryNoDupes:
siResult = (tDirStatus)DoNewServerDiscovery( inData );
break;
case eDSCustomCallLDAPv3NewServerVerifySettings:
siResult = (tDirStatus)DoNewServerVerifySettings( inData );
break;
case eDSCustomCallLDAPv3NewServerGetConfig:
siResult = (tDirStatus)DoNewServerGetConfig( inData );
break;
case eDSCustomCallLDAPv3NewServerBind: case eDSCustomCallLDAPv3NewServerForceBind: siResult = (tDirStatus)DoNewServerBind( inData );
break;
case eDSCustomCallLDAPv3NewServerAddConfig:
siResult = (tDirStatus)DoNewServerSetup( inData );
break;
case eDSCustomCallLDAPv3UnbindServerConfig: case eDSCustomCallLDAPv3ForceUnbindServerConfig: case eDSCustomCallLDAPv3RemoveServerConfig: siResult = (tDirStatus)DoRemoveServer( inData );
break;
case eDSCustomCallLDAPv3NewServerBindOther: case eDSCustomCallLDAPv3NewServerForceBindOther: siResult = (tDirStatus)DoNewServerBind2( inData );
break;
default:
break;
}
}
else if ( inData->fInRequestCode == eDSCustomCallLDAPv3CurrentAuthenticatedUser )
{
if ( pContext != NULL && pContext->fLDAPConnection != NULL && pContext->fLDAPConnection->fKerberosID != NULL )
{
UInt32 iLen = strlen( pContext->fLDAPConnection->fKerberosID );
if ( inData->fOutRequestResponse->fBufferSize > iLen )
{
strcpy( inData->fOutRequestResponse->fBufferData, pContext->fLDAPConnection->fKerberosID );
inData->fOutRequestResponse->fBufferLength = iLen;
siResult = eDSNoErr;
}
else
{
siResult = eDSBufferTooSmall;
}
}
else
{
siResult = eDSRecordNotFound;
}
}
else if( inData->fInRequestCode == eDSCustomCallDeleteRecordAndCredentials )
{
sDeleteRecord tempStruct;
tempStruct.fInRecRef = *((tRecordReference *)inData->fInRequestData->fBufferData);
siResult = DeleteRecord( &tempStruct, true );
}
else if( inData->fInRequestCode == eDSCustomCallExtendedRecordCallsAvailable ) {
if( inData->fOutRequestResponse->fBufferSize < 1 )
throw( eDSInvalidBuffFormat );
inData->fOutRequestResponse->fBufferLength = 1;
inData->fOutRequestResponse->fBufferData[0] = 1;
}
else if( inData->fInRequestCode == eDSCustomCallCreateRecordWithAttributes ) {
const char* recordType = NULL;
const char* recordName = NULL;
CFDictionaryRef recordDict = 0;
{ CFDataRef bufferCFData = CFDataCreateWithBytesNoCopy( kCFAllocatorDefault, (const UInt8*)inData->fInRequestData->fBufferData,
inData->fInRequestData->fBufferLength, kCFAllocatorNull );
if( bufferCFData == NULL )
throw( eDSInvalidBuffFormat );
CFStringRef errorString;
CFDictionaryRef bufferCFDict = (CFDictionaryRef)CFPropertyListCreateFromXMLData( kCFAllocatorDefault, bufferCFData,
kCFPropertyListImmutable, &errorString );
CFRelease( bufferCFData ); bufferCFData = 0;
CFStringRef recordTypeCFString = (CFStringRef)CFDictionaryGetValue( bufferCFDict, CFSTR( "Record Type" ) );
if ( recordTypeCFString == NULL || CFGetTypeID(recordTypeCFString) != CFStringGetTypeID() )
throw( eDSInvalidBuffFormat );
recordType = GetCStringFromCFString( recordTypeCFString, &recordTypeCStr );
recordDict = (CFDictionaryRef)CFDictionaryGetValue( bufferCFDict, CFSTR( "Attributes and Values" ) );
if( recordDict == NULL )
throw( eDSInvalidBuffFormat );
CFArrayRef recordNames = (CFArrayRef)CFDictionaryGetValue( recordDict, CFSTR( kDSNAttrRecordName ) );
if( recordNames == 0 || CFArrayGetCount( recordNames ) == 0 )
throw( eDSInvalidBuffFormat );
CFStringRef recordNameCFString = (CFStringRef)CFArrayGetValueAtIndex( recordNames, 0 );
if( recordNameCFString == NULL || CFGetTypeID(recordNameCFString) != CFStringGetTypeID())
throw( eDSInvalidBuffFormat );
recordName = GetCStringFromCFString( recordNameCFString, &recordNameCStr );
CFRetain( recordDict );
CFRelease( bufferCFDict ); bufferCFDict = NULL;
}
if( ( recordType != NULL ) &&( recordName != NULL ) && ( recordDict != 0 ) )
{
siResult = CreateRecordWithAttributes( inData->fInNodeRef, recordType, recordName, recordDict );
if( siResult != eDSNoErr )
throw( siResult );
}
}
else if( inData->fInRequestCode == eDSCustomCallSetAttributes ) {
tRecordReference recordRef = 0;
CFDictionaryRef recordDict = 0;
{ CFDataRef bufferCFData = CFDataCreateWithBytesNoCopy( kCFAllocatorDefault, (const UInt8*)inData->fInRequestData->fBufferData,
inData->fInRequestData->fBufferLength, kCFAllocatorNull );
if( bufferCFData == NULL )
throw( eDSInvalidBuffFormat );
CFStringRef errorString;
CFDictionaryRef bufferCFDict = (CFDictionaryRef)CFPropertyListCreateFromXMLData( kCFAllocatorDefault, bufferCFData,
kCFPropertyListImmutable, &errorString );
CFRelease( bufferCFData ); bufferCFData = 0;
CFNumberRef recordRefNumber = (CFNumberRef)CFDictionaryGetValue( bufferCFDict, CFSTR( "Record Reference" ) );
if( !CFNumberGetValue( recordRefNumber, kCFNumberLongType, &recordRef ) )
throw( eDSInvalidBuffFormat );
recordDict = (CFDictionaryRef)CFDictionaryGetValue( bufferCFDict, CFSTR( "Attributes and Values" ) );
if( recordDict == NULL )
throw( eDSInvalidBuffFormat );
CFRetain( recordDict );
CFRelease( bufferCFDict ); bufferCFDict = NULL;
}
if( ( recordRef != 0 ) && ( recordDict != 0 ) )
{
siResult = SetAttributes( recordRef, recordDict );
if( siResult != eDSNoErr )
throw( siResult );
}
CFRelease( recordDict ); }
}
catch ( tDirStatus err )
{
siResult = err;
}
if (authRef != 0)
{
AuthorizationFree(authRef, 0);
authRef = 0;
}
DSFree( recordTypeCStr );
DSFree( recordNameCStr );
DSRelease( pContext );
return( siResult );
}
#pragma mark -
#pragma mark Other functions
void CLDAPv3Plugin::ContinueDeallocProc ( void* inContinueData )
{
sLDAPContinueData *pLDAPContinue = (sLDAPContinueData *) inContinueData;
pLDAPContinue->Release();
}
tDirStatus CLDAPv3Plugin::GetRecLDAPMessage ( sLDAPContextData *inRecContext, char **inAttrs, LDAPMessage **outResultMsg )
{
tDirStatus siResult = eDSNoErr;
int numRecTypes = 1;
char *pLDAPSearchBase = nil;
bool bResultFound = false;
char *queryFilter = nil;
LDAPMessage *result = nil;
bool bOCANDGroup = false;
CFArrayRef OCSearchList = nil;
ber_int_t scope = LDAP_SCOPE_SUBTREE;
if ( inRecContext->fOpenRecordName == nil ) return eDSNullRecName;
if ( inRecContext->fOpenRecordType == nil ) return eDSNullRecType;
pLDAPSearchBase = MapRecToSearchBase( inRecContext, (const char *)(inRecContext->fOpenRecordType), numRecTypes, &bOCANDGroup, &OCSearchList, &scope );
if ( pLDAPSearchBase == NULL )
siResult = eDSInvalidRecordType;
while ( (pLDAPSearchBase != nil) && (!bResultFound) )
{
queryFilter = BuildLDAPQueryFilter( inRecContext,
(char *)kDSNAttrRecordName, inRecContext->fOpenRecordName,
eDSExact,
false,
(const char *)(inRecContext->fOpenRecordType),
pLDAPSearchBase,
bOCANDGroup,
OCSearchList );
if ( queryFilter == nil )
{
siResult = eDSNoStdMappingAvailable;
break;
}
siResult = DSRetrieveSynchronous( pLDAPSearchBase,
inAttrs,
inRecContext,
scope,
queryFilter,
&result,
NULL );
if ( siResult == eDSNoErr || siResult == eDSCannotAccessSession )
break;
numRecTypes++;
bOCANDGroup = false;
DSDelete( queryFilter );
DSDelete( pLDAPSearchBase );
DSCFRelease( OCSearchList );
pLDAPSearchBase = MapRecToSearchBase( inRecContext, (const char *)(inRecContext->fOpenRecordType), numRecTypes,
&bOCANDGroup, &OCSearchList, &scope );
}
DSCFRelease( OCSearchList );
DSFreeString( pLDAPSearchBase );
DSFreeString( queryFilter );
*outResultMsg = result;
return( siResult );
}
LDAPv3AuthAuthorityHandlerProc CLDAPv3Plugin::GetLDAPv3AuthAuthorityHandler ( const char* inTag )
{
if (inTag == NULL)
{
return NULL;
}
for (unsigned int i = 0; i < kLDAPv3AuthAuthorityHandlerProcs; ++i)
{
if (strcasecmp(inTag,sLDAPv3AuthAuthorityHandlerProcs[i].fTag) == 0)
{
return sLDAPv3AuthAuthorityHandlerProcs[i].fHandler;
}
}
return NULL;
}
SInt32 CLDAPv3Plugin::PeriodicTask ( void )
{
CLDAPv3Plugin::WaitForNetworkTransitionToFinish();
fLDAPConnectionMgr->PeriodicTask();
fConfigFromXML->PeriodicTask();
return( eDSNoErr );
}
void CLDAPv3Plugin::WaitForNetworkTransitionToFinishWithFunctionName( const char* callerFunction )
{
if( gNetworkTransition.WaitForEvent( 10 * kMilliSecsPerSec ) == false )
{
DbgLog( kLogPlugin, "CLDAPv3Plugin::WaitForNetworkTransitionToFinish %s timed out or reached maximum wait time", callerFunction );
}
}
char* CLDAPv3Plugin::MappingNativeVariableSubstitution( char *inLDAPAttrType,
sLDAPContextData *inContext,
LDAPMessage *inResult,
tDirStatus& outResult)
{
char *returnStr = nil;
char *tmpStr = nil;
char *vsPtr = nil;
char **tokens = nil;
char **tokenValues = nil;
struct berval **vsBValues;
int tokenCount = 0;
int returnStrCount = 0;
int vsShift = 0;
LDAP *aHost = nil;
int tokenStep = 0;
int index = 0;
char *lastPtr = nil;
const char delimiterChar = '$';
const char literalChar = '#';
const char nullChar = '\0';
int tokensMax = 0;
outResult = eDSNoErr;
if ( (inLDAPAttrType != nil) && (*inLDAPAttrType == literalChar) && ( strchr(inLDAPAttrType, delimiterChar) != nil) )
{
returnStrCount = strlen(inLDAPAttrType);
vsPtr = (char *)calloc(1, 1+returnStrCount);
memcpy(vsPtr, inLDAPAttrType, returnStrCount);
tmpStr = vsPtr;
while (vsPtr != nil)
{
tokensMax++;
vsPtr = strchr(vsPtr, delimiterChar);
if (vsPtr != nil)
{
vsPtr = vsPtr + 1;
}
}
tokens = (char **)calloc(sizeof(char *), tokensMax+1);
tokenValues = (char **)calloc(sizeof(char *), tokensMax+1);
vsPtr = tmpStr;
while ( (vsPtr != nil) && (*vsPtr != nullChar) )
{
if ( *vsPtr == delimiterChar )
{
*vsPtr = nullChar;
vsPtr = vsPtr + 1;
if (*vsPtr != nullChar)
{
lastPtr = strchr(vsPtr, delimiterChar);
if (lastPtr != nil)
{
tokens[tokenCount] = vsPtr;
if (vsPtr != lastPtr)
{
*lastPtr = nullChar;
}
else
{
tokenValues[tokenCount] = strdup("$");
}
tokenCount++;
vsPtr = lastPtr + 1;
}
else
{
outResult = eDSInvalidNativeMapping;
break;
}
}
else
{
outResult = eDSInvalidNativeMapping;
break;
}
}
else
{
tokens[tokenCount] = vsPtr;
tokenValues[tokenCount] = vsPtr;
tokenCount++;
while ( ( *vsPtr != nullChar ) && ( *vsPtr != delimiterChar ) )
{
vsPtr = vsPtr + 1;
}
}
}
if (outResult == eDSNoErr)
{
aHost = inContext->fLDAPConnection->LockLDAPSession();
if (aHost != NULL)
{
for ( tokenStep = 0; tokenStep < tokenCount; tokenStep++)
{
if (tokenValues[tokenStep] == nil)
{
vsBValues = ldap_get_values_len(aHost, inResult, tokens[tokenStep]);
if (vsBValues != nil)
{
returnStrCount += vsBValues[0]->bv_len; tokenValues[tokenStep] = (char *) calloc(vsBValues[0]->bv_len+1, sizeof(char));
memcpy(tokenValues[tokenStep], vsBValues[0]->bv_val, vsBValues[0]->bv_len);
ldap_value_free_len(vsBValues);
vsBValues = nil;
}
} } inContext->fLDAPConnection->UnlockLDAPSession( aHost, false );
}
returnStr = (char *) calloc(1+returnStrCount, sizeof(char));
for ( tokenStep = 0; tokenStep < tokenCount; tokenStep++)
{
if (tokenValues[tokenStep] != nil)
{
memcpy((returnStr + vsShift), tokenValues[tokenStep], (strlen(tokenValues[tokenStep])));
vsShift += strlen(tokenValues[tokenStep]);
}
}
for (index = 0; index < tokensMax; index++)
{
if ( (tokenValues[index] != nil) && ( tokenValues[index] != tokens[index] ) )
{
free(tokenValues[index]);
tokenValues[index] = nil;
}
}
}
free(tmpStr);
tmpStr = nil;
free(tokens);
free(tokenValues);
}
return(returnStr);
}
char *CLDAPv3Plugin::GetPWSIDforRecord( sLDAPContextData *pContext, const char *inRecName, const char *inRecType )
{
char **aaArray = NULL;
UInt32 aaCount = 0;
char *pUserID = NULL;
if ( GetAuthAuthority(pContext, inRecName, 0, &aaCount, &aaArray, inRecType) == eDSNoErr )
{
pUserID = GetPWSAuthData( aaArray, aaCount );
DSFree( aaArray );
}
return pUserID;
}
#pragma mark -
#pragma mark BaseDirectoryPlugin virtual functions
void CLDAPv3Plugin::NetworkTransition( void )
{
fLDAPConnectionMgr->NetworkTransition();
fConfigFromXML->NetworkTransition();
DbgLog( kLogPlugin, "CLDAPv3Plugin::Posting Network transition event now" );
gNetworkTransition.PostEvent();
}
CFDataRef CLDAPv3Plugin::CopyConfiguration( void )
{
return NULL;
}
bool CLDAPv3Plugin::NewConfiguration( const char *inData, UInt32 inLength )
{
return false;
}
bool CLDAPv3Plugin::CheckConfiguration( const char *inData, UInt32 inLength )
{
return false;
}
tDirStatus CLDAPv3Plugin::HandleCustomCall( sBDPINodeContext *pContext, sDoPlugInCustomCall *inData )
{
tDirStatus siResult = eNotHandledByThisNode;
return siResult;
}
bool CLDAPv3Plugin::IsConfigureNodeName( CFStringRef inNodeName )
{
return false;
}
BDPIVirtualNode *CLDAPv3Plugin::CreateNodeForPath( CFStringRef inPath, uid_t inUID, uid_t inEffectiveUID )
{
return NULL;
}