#pragma mark Includes
#include <string.h> //used for strcpy, etc.
#include <stdlib.h> //used for malloc
#include <ctype.h> //use for isprint
#include <openssl/md5.h>
#include <syslog.h>
#include <Security/Authorization.h>
#include <SystemConfiguration/SCDynamicStoreCopyDHCPInfo.h>
#include <CoreFoundation/CFPriv.h>
#include "DirServices.h"
#include "DirServicesUtils.h"
#include "DirServicesConst.h"
#include "DirServicesPriv.h"
extern "C" {
#include "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"
#pragma mark -
#pragma mark Defines and Macros
#define LDAPURLOPT95SEPCHAR " "
#define LDAPCOMEXPSPECIALCHARS "()|&"
#pragma mark -
#pragma mark Globals and Structures
CLDAPNode CLDAPv3Plugin::fLDAPSessionMgr;
bool CLDAPv3Plugin::fHandlingNetworkTransition = false;
CFRunLoopTimerRef CLDAPv3Plugin::fTimerRef = NULL;
CLDAPv3Configs *gpConfigFromXML = NULL;
extern bool gServerOS;
extern bool gBlockLDAPNetworkChange;
DSMutexSemaphore *gLDAPKerberosMutex = nil;
CContinue *gLDAPContinueTable = nil;
CPlugInRef *gLDAPContextTable = nil;
static DSEventSemaphore *gKickLDAPv3Requests = nil;
CLDAPv3Plugin *gLDAPv3Plugin = nil;
struct LDAPv3AuthAuthorityHandler
{
char* fTag;
LDAPv3AuthAuthorityHandlerProc fHandler;
};
struct LDAPv3AuthTagStruct
{
string version;
string authData;
LDAPv3AuthTagStruct( char *inVersion, char *inAuthData )
{
if( inVersion ) version = inVersion;
if( inAuthData) authData = inAuthData;
}
};
#define kLDAPv3AuthAuthorityHandlerProcs 3
static LDAPv3AuthAuthorityHandler sLDAPv3AuthAuthorityHandlerProcs[ kLDAPv3AuthAuthorityHandlerProcs ] =
{
{ kDSTagAuthAuthorityBasic, (LDAPv3AuthAuthorityHandlerProc)CLDAPv3Plugin::DoBasicAuth },
{ kDSTagAuthAuthorityPasswordServer, (LDAPv3AuthAuthorityHandlerProc)CLDAPv3Plugin::DoPasswordServerAuth },
{ kDSTagAuthAuthorityKerberosv5, (LDAPv3AuthAuthorityHandlerProc)CLDAPv3Plugin::DoKerberosAuth }
};
enum
{
eRecordBlatAvailable = 1000,
eRecordBlatCreateRecWithAttrs = 1001,
eRecordBlatSetAttrs = 1002,
eRecordDeleteAndCredentials = 1003
};
#pragma mark -
#pragma mark Prototypes
extern int doSASLBindAttemptIfPossible( LDAP *inLDAPHost, sLDAPConfigData *pConfig, char *ldapAcct, char *ldapPasswd, char *kerberosID = NULL );
static void DoLDAPPINetworkChange(CFRunLoopTimerRef timer, void *info);
CFStringRef NetworkChangeLDAPPICopyStringCallback( const void *item );
void DSDoSearch ( char *inRecType,
char *inNativeRecType,
CAttributeList *inAttrTypeList,
sLDAPContextData *inContext,
sLDAPContinueData *inContinue,
ber_int_t inScope,
CLDAPNode &inLDAPSessionMgr,
char *inQueryFilter,
int &outLDAPReturnCode,
int inSearchTO,
LDAPMessage *&outResult);
sInt32 DSDoRetrieval ( char *inNativeRecType,
char **inAttrs,
sLDAPContextData *inContext,
ber_int_t inScope,
CLDAPNode &inLDAPSessionMgr,
char *inQueryFilter,
int &outLDAPReturnCode,
int inSearchTO,
LDAPMessage *&outResult,
bool &outResultFound,
int &ldapMsgId);
sInt32 DSSearchLDAP ( CLDAPNode &inLDAPSessionMgr,
sLDAPContextData *inContext,
char *inNativeRecType,
int scope,
char *queryFilter,
char **attrs,
int &ldapMsgId,
int &ldapReturnCode,
int recLimit);
sInt32 DSGetSearchLDAPResult ( CLDAPNode &inLDAPSessionMgr,
sLDAPContextData *inContext,
int inSearchTO,
LDAPMessage *&inResult,
int all,
int &inLDAPMsgId,
int &inLDAPReturnCode,
bool bErrorOnNoEntry);
void DSGetExtendedLDAPResult ( LDAP *inHost,
int inSearchTO,
int &inLDAPMsgId,
int &inLDAPReturnCode);
static int standard_password_replace( LDAP *ld, char *dn, char *oldPwd, char *newPwd );
static int standard_password_create( LDAP *ld, char *dn, char *newPwd );
static int exop_password_create( LDAP *ld, char *dn, char *newPwd );
static void RemoveKeytabEntry( char *inPrinc );
static int DetermineKVNO( char *inPrinc, char *inPass );
static void AddKeytabEntry( char *inPrinc, char *inPass );
#pragma mark -
#pragma mark Support Functions
void DoLDAPPINetworkChange(CFRunLoopTimerRef timer, void *info)
{
if ( info != nil )
{
((CLDAPv3Plugin *)info)->ReInitForNetworkTransition();
}
}
CFStringRef NetworkChangeLDAPPICopyStringCallback( const void *item )
{
return CFSTR("NetworkChangeLDAPPlugin");
}
sInt32 DSSearchLDAP ( CLDAPNode &inLDAPSessionMgr,
sLDAPContextData *inContext,
char *inNativeRecType,
int scope,
char *queryFilter,
char **attrs,
int &ldapMsgId,
int &ldapReturnCode,
int recLimit )
{
sInt32 siResult = eDSNoErr;
LDAPControl **serverctrls = nil;
LDAPControl **clientctrls = nil;
LDAP *aHost = nil;
aHost = inLDAPSessionMgr.LockSession(inContext);
if (aHost != nil)
{
ldapReturnCode = ldap_search_ext( aHost,
inNativeRecType,
scope,
queryFilter,
attrs,
0,
serverctrls,
clientctrls,
0, recLimit,
&ldapMsgId );
}
else
{
ldapReturnCode = LDAP_LOCAL_ERROR;
}
switch(ldapReturnCode)
{
case LDAP_SUCCESS:
break;
case LDAP_UNAVAILABLE:
case LDAP_SERVER_DOWN:
case LDAP_BUSY:
case LDAP_LOCAL_ERROR:
siResult = eDSCannotAccessSession;
break;
default:
siResult = eDSRecordNotFound;
break;
}
inLDAPSessionMgr.UnLockSession(inContext, (siResult == eDSRecordNotFound) );
if (serverctrls) ldap_controls_free( serverctrls );
if (clientctrls) ldap_controls_free( clientctrls );
return(siResult);
}
sInt32 DSGetSearchLDAPResult ( CLDAPNode &inLDAPSessionMgr,
sLDAPContextData *inContext,
int inSearchTO,
LDAPMessage *&inResult,
int all,
int &inLDAPMsgId,
int &inLDAPReturnCode,
bool bErrorOnNoEntry)
{
sInt32 siResult = eDSNoErr;
LDAP *aHost = nil;
aHost = inLDAPSessionMgr.LockSession(inContext);
if (aHost != nil)
{
double maxTime = dsTimestamp() + USEC_PER_SEC*((inSearchTO)?inSearchTO:kLDAPDefaultSearchTimeoutInSeconds);
struct timeval tv = {kLDAPDefaultNetworkTimeoutInSeconds,0};
inLDAPReturnCode = 0;
SetNetworkTimeoutsForHost( aHost, kLDAPDefaultNetworkTimeoutInSeconds );
while ( inLDAPReturnCode == 0 && dsTimestamp() < maxTime && CLDAPv3Plugin::HandlingNetworkTransition() == false )
{
inLDAPReturnCode = ldap_result(aHost, inLDAPMsgId, all, &tv, &inResult);
}
if ( inLDAPReturnCode == 0 )
{
ldap_abandon(aHost, inLDAPMsgId);
inLDAPReturnCode = -1;
}
}
else
{
inLDAPReturnCode = LDAP_LOCAL_ERROR;
}
inLDAPSessionMgr.UnLockSession(inContext, (inLDAPReturnCode == -1) );
switch(inLDAPReturnCode)
{
case LDAP_RES_SEARCH_ENTRY:
break;
case LDAP_RES_SEARCH_RESULT:
{
int ldapReturnCode2 = 0;
int err = 0;
char *matcheddn = nil;
char *text = nil;
char **refs = nil;
LDAPControl **ctrls = nil;
aHost = inLDAPSessionMgr.LockSession(inContext);
if (aHost != nil)
{
ldapReturnCode2 = ldap_parse_result(aHost, inResult, &err, &matcheddn, &text, &refs, &ctrls, 0);
}
else
{
ldapReturnCode2 = LDAP_LOCAL_ERROR;
}
inLDAPSessionMgr.UnLockSession(inContext);
if (ldapReturnCode2 == LDAP_LOCAL_ERROR)
{
break;
}
else
{
if ( (ldapReturnCode2 != LDAP_SUCCESS) && (ldapReturnCode2 != LDAP_MORE_RESULTS_TO_RETURN) )
{
aHost = inLDAPSessionMgr.LockSession(inContext);
ldap_abandon(aHost, inLDAPMsgId);
inLDAPSessionMgr.UnLockSession(inContext);
}
else
{
if (ldapReturnCode2 == LDAP_SUCCESS) inLDAPReturnCode = LDAP_SUCCESS;
if (text) ber_memfree( text );
if (matcheddn) ber_memfree( matcheddn );
if (refs) ber_memvfree( (void **) refs );
if (ctrls) ldap_controls_free( ctrls );
}
}
if (bErrorOnNoEntry)
{
siResult = eDSRecordNotFound;
}
break;
}
case LDAP_TIMEOUT:
siResult = eDSServerTimeout;
break;
case -1:
siResult = eDSCannotAccessSession;
break;
default:
siResult = eDSRecordNotFound;
break;
}
return (siResult);
}
void DSGetExtendedLDAPResult ( LDAP *inHost,
int inSearchTO,
int &inLDAPMsgId,
int &inLDAPReturnCode)
{
LDAPMessage* res = NULL;
double maxTime = dsTimestamp() + USEC_PER_SEC*((inSearchTO)?inSearchTO:kLDAPDefaultSearchTimeoutInSeconds);
struct timeval tv = {kLDAPDefaultNetworkTimeoutInSeconds,0};
inLDAPReturnCode = 0;
SetNetworkTimeoutsForHost( inHost, kLDAPDefaultNetworkTimeoutInSeconds );
while ( inLDAPReturnCode == 0 && dsTimestamp() < maxTime && CLDAPv3Plugin::HandlingNetworkTransition() == false )
{
inLDAPReturnCode = ldap_result(inHost, inLDAPMsgId, LDAP_MSG_ALL, &tv, &res);
}
switch(inLDAPReturnCode)
{
case LDAP_RES_SEARCH_ENTRY:
break;
case LDAP_RES_EXTENDED:
case LDAP_RES_SEARCH_RESULT:
{
int ldapReturnCode2 = 0;
int err = 0;
char *matcheddn = nil;
char *text = nil;
char **refs = nil;
LDAPControl **ctrls = nil;
ldapReturnCode2 = ldap_parse_result(inHost, res, &err, &matcheddn, &text, &refs, &ctrls, 0);
if ( (ldapReturnCode2 != LDAP_SUCCESS) && (ldapReturnCode2 != LDAP_MORE_RESULTS_TO_RETURN) )
{
ldap_abandon(inHost, inLDAPMsgId);
inLDAPReturnCode = ldapReturnCode2;
}
else
{
inLDAPReturnCode = err;
if (text && *text) ber_memfree( text );
if (matcheddn && *matcheddn) ber_memfree( matcheddn );
if (refs) ber_memvfree( (void **) refs );
if (ctrls) ldap_controls_free( ctrls );
}
}
break;
case LDAP_TIMEOUT:
case LDAP_SUCCESS:
case -1:
default:
break;
} }
static int standard_password_replace( LDAP *ld, char *dn, char *oldPwd, char *newPwd )
{
char *pwdDelete[2] = {};
pwdDelete[0] = oldPwd;
pwdDelete[1] = NULL;
LDAPMod modDelete = {};
modDelete.mod_op = LDAP_MOD_DELETE;
modDelete.mod_type = "userPassword";
modDelete.mod_values = pwdDelete;
char *pwdCreate[2] = {};
pwdCreate[0] = newPwd;
pwdCreate[1] = NULL;
LDAPMod modAdd = {};
modAdd.mod_op = LDAP_MOD_ADD;
modAdd.mod_type = "userPassword";
modAdd.mod_values = pwdCreate;
LDAPMod *mods[3] = {};
mods[0] = &modDelete;
mods[1] = &modAdd;
mods[2] = NULL;
return ldap_modify_s( ld, dn, mods );
}
static int standard_password_create( LDAP *ld, char *dn, char *newPwd )
{
char *pwdCreate[2] = {};
pwdCreate[0] = newPwd;
pwdCreate[1] = NULL;
LDAPMod modReplace = {};
modReplace.mod_op = LDAP_MOD_REPLACE;
modReplace.mod_type = "userPassword";
modReplace.mod_values = pwdCreate;
LDAPMod *mods[2] = {};
mods[0] = &modReplace;
mods[1] = NULL;
return ldap_modify_s( ld, dn, mods );
}
static int exop_password_create( LDAP *ld, char *dn, char *newPwd )
{
BerElement *ber = ber_alloc_t( LBER_USE_DER );
if( ber == NULL ) throw( (sInt32) eMemoryError );
ber_printf( ber, "{" );
ber_printf( ber, "ts", LDAP_TAG_EXOP_MODIFY_PASSWD_ID, dn );
ber_printf( ber, "ts", LDAP_TAG_EXOP_MODIFY_PASSWD_NEW, newPwd );
ber_printf( ber, "N}" );
struct berval *bv = NULL;
int rc = ber_flatten( ber, &bv );
if( rc < 0 ) throw( (sInt32) eMemoryError );
ber_free( ber, 1 );
int id;
rc = ldap_extended_operation( ld, LDAP_EXOP_MODIFY_PASSWD, bv, NULL, NULL, &id );
ber_bvfree( bv );
if ( rc == LDAP_SUCCESS ) {
DSGetExtendedLDAPResult( ld, 0, id, rc);
}
return rc;
}
void DSDoSearch ( char *inRecType,
char *inNativeRecType,
CAttributeList *inAttrTypeList,
sLDAPContextData *inContext,
sLDAPContinueData *inContinue,
ber_int_t inScope,
CLDAPNode &inLDAPSessionMgr,
char *inQueryFilter,
int &outLDAPReturnCode,
int inSearchTO,
LDAPMessage *&outResult)
{
sInt32 searchResult = eDSNoErr;
char **attrs = nil;
int ldapMsgId = 0;
int numRetries = 2;
try
{
if (inContinue->msgId == 0)
{
attrs = CLDAPv3Plugin::MapAttrListToLDAPTypeArray( inRecType, inAttrTypeList, inContext->fNodeName );
while (true)
{
searchResult = DSSearchLDAP( inLDAPSessionMgr,
inContext,
inNativeRecType,
inScope,
inQueryFilter,
attrs,
ldapMsgId,
outLDAPReturnCode,
inContinue->fLimitRecSearch );
if ( (searchResult == eDSNoErr) &&
((inContinue->fTotalRecCount < inContinue->fLimitRecSearch) || (inContinue->fLimitRecSearch == 0)) )
{
searchResult = DSGetSearchLDAPResult ( inLDAPSessionMgr,
inContext,
inSearchTO,
outResult,
LDAP_MSG_ONE,
ldapMsgId,
outLDAPReturnCode,
false);
}
if (searchResult == eDSRecordNotFound)
{
throw( (sInt32)eDSRecordNotFound );
}
else if (searchResult == eDSCannotAccessSession)
{
if (numRetries == 0)
{
throw( (sInt32)eDSCannotAccessSession );
}
else
{
CLDAPv3Plugin::RebindLDAPSession(inContext, inLDAPSessionMgr );
numRetries--;
}
}
else if (searchResult == eDSServerTimeout)
{
throw( (sInt32)eDSServerTimeout );
}
else
{
break;
}
}
inContinue->msgId = ldapMsgId;
} else
{
if ( (inContinue->fTotalRecCount < inContinue->fLimitRecSearch) || (inContinue->fLimitRecSearch == 0) )
{
if (inContinue->pResult != nil)
{
outResult = inContinue->pResult;
outLDAPReturnCode = LDAP_RES_SEARCH_ENTRY;
}
else
{
searchResult = DSGetSearchLDAPResult ( inLDAPSessionMgr,
inContext,
inSearchTO,
outResult,
LDAP_MSG_ONE,
inContinue->msgId,
outLDAPReturnCode,
false);
if (searchResult == eDSCannotAccessSession)
{
throw( (sInt32)eDSCannotAccessSession );
}
else if (searchResult == eDSServerTimeout)
{
throw( (sInt32)eDSServerTimeout );
}
}
}
}
}
catch ( sInt32 err )
{
searchResult = err;
}
if (attrs != nil)
{
int aIndex = 0;
while (attrs[aIndex] != nil)
{
free(attrs[aIndex]);
attrs[aIndex] = nil;
aIndex++;
}
free(attrs);
attrs = nil;
}
if (searchResult != eDSNoErr)
{
throw(searchResult);
}
}
sInt32 DSDoRetrieval ( char *inNativeRecType,
char **inAttrs,
sLDAPContextData *inContext,
ber_int_t inScope,
CLDAPNode &inLDAPSessionMgr,
char *inQueryFilter,
int &outLDAPReturnCode,
int inSearchTO,
LDAPMessage *&outResult,
bool &outResultFound,
int &ldapMsgId)
{
sInt32 searchResult = eDSNoErr;
int numRetries = 2;
try
{
while (true)
{
searchResult = DSSearchLDAP( inLDAPSessionMgr,
inContext,
inNativeRecType,
inScope,
inQueryFilter,
inAttrs,
ldapMsgId,
outLDAPReturnCode,
1 );
if (searchResult == eDSNoErr)
{
searchResult = DSGetSearchLDAPResult ( inLDAPSessionMgr,
inContext,
inSearchTO,
outResult,
LDAP_MSG_ONE,
ldapMsgId,
outLDAPReturnCode,
true);
}
outResultFound = false;
if (searchResult == eDSRecordNotFound)
{
break;
}
else if (searchResult == eDSCannotAccessSession)
{
if (numRetries == 0)
{
throw( (sInt32)eDSCannotAccessSession );
}
else
{
CLDAPv3Plugin::RebindLDAPSession(inContext, inLDAPSessionMgr );
numRetries--;
}
}
else if (searchResult == eDSServerTimeout)
{
break;
}
else
{
outResultFound = true;
break;
}
} }
catch ( sInt32 err )
{
searchResult = err;
}
if (searchResult == eDSCannotAccessSession)
{
throw(searchResult);
}
return(searchResult);
}
void AddKeytabEntry( char *inPrinc, char *inPass )
{
char ktname[MAXPATHLEN+sizeof("WRFILE:")+1];
krb5_keytab kt = NULL;
krb5_context kContext = NULL;
krb5_error_code retval;
krb5_keytab_entry entry;
krb5_data password;
krb5_data salt;
long types[] = { ENCTYPE_ARCFOUR_HMAC, ENCTYPE_DES_CBC_CRC, ENCTYPE_DES3_CBC_SHA1, 0 };
long *keyType = types;
memset( &entry, 0, sizeof(entry) );
memset( &password, 0, sizeof(password) );
memset( &salt, 0, sizeof(salt) );
password.data = strdup( inPass );
password.length = strlen( password.data );
password.magic = KV5M_PWD_DATA;
entry.magic = KV5M_KEYTAB;
RemoveKeytabEntry( inPrinc );
gLDAPKerberosMutex->Wait();
retval = krb5_init_context( &kContext );
if ( 0 == retval )
{
krb5_kt_default_name( kContext, &ktname[2], sizeof(ktname)-2 );
ktname[0] = 'W';
ktname[1] = 'R';
retval = krb5_kt_resolve( kContext, ktname, &kt );
}
if( 0 == retval )
{
retval = krb5_parse_name( kContext, inPrinc, &entry.principal );
}
if( 0 == retval )
{
retval = krb5_principal2salt( kContext, entry.principal, &salt );
}
if( 0 == retval )
{
entry.vno = DetermineKVNO( inPrinc, inPass );
if (entry.vno != 0) {
do
{
retval = krb5_c_string_to_key( kContext, *keyType, &password, &salt, &entry.key );
if( 0 == retval )
{
if (entry.vno != 0) {
krb5_kt_add_entry( kContext, kt, &entry );
}
krb5_free_keyblock_contents( kContext, &entry.key );
}
} while ( *(++keyType) );
}
krb5_free_data_contents( kContext, &salt );
}
krb5_free_keytab_entry_contents( kContext, &entry );
if( password.data )
{
memset( password.data, 0, password.length );
free( password.data );
password.data = NULL;
}
if( kt != NULL )
{
krb5_kt_close( kContext, kt );
kt = NULL;
}
if( kContext != NULL )
{
krb5_free_context( kContext );
kContext = NULL;
}
gLDAPKerberosMutex->Signal();
}
void RemoveKeytabEntry( char *inPrinc )
{
char ktname[MAXPATHLEN+sizeof("WRFILE:")+1];
krb5_kt_cursor cursor = NULL;
krb5_keytab_entry entry;
krb5_principal host_princ = NULL;
krb5_keytab kt = NULL;
krb5_context kContext = NULL;
krb5_error_code retval;
gLDAPKerberosMutex->Wait();
bzero( &entry, sizeof(entry) );
retval = krb5_init_context( &kContext );
if( 0 == retval )
{
krb5_kt_default_name( kContext, &ktname[2], sizeof(ktname)-2 );
ktname[0] = 'W';
ktname[1] = 'R';
}
retval = krb5_kt_resolve( kContext, ktname, &kt );
if( 0 == retval )
{
krb5_parse_name( kContext, inPrinc, &host_princ );
}
retval = krb5_kt_start_seq_get( kContext, kt, &cursor );
if( 0 == retval )
{
while( retval != KRB5_KT_END && retval != ENOENT )
{
if( retval = krb5_kt_next_entry(kContext, kt, &entry, &cursor) )
{
break;
}
if( krb5_principal_compare(kContext, entry.principal, host_princ) )
{
krb5_kt_end_seq_get( kContext, kt, &cursor );
krb5_kt_remove_entry( kContext, kt, &entry );
retval = krb5_kt_start_seq_get( kContext, kt, &cursor );
}
krb5_free_keytab_entry_contents( kContext, &entry );
}
if( cursor != NULL )
{
krb5_kt_end_seq_get( kContext, kt, &cursor );
}
}
if( host_princ )
{
krb5_free_principal( kContext, host_princ );
}
if( kt != NULL )
{
krb5_kt_close( kContext, kt );
kt = NULL;
}
if( kContext )
{
krb5_free_context( kContext );
kContext = NULL;
}
gLDAPKerberosMutex->Signal();
}
int DetermineKVNO( char *inPrinc, char *inPass )
{
int kvno = 0;
krb5_ticket *ticket = NULL;
krb5_creds my_creds;
krb5_creds kvno_creds;
krb5_creds *my_creds_out = NULL;
krb5_principal principal = NULL;
krb5_principal cachePrinc = NULL;
krb5_ccache krbCache = NULL;
krb5_error_code retval;
char *principalString = NULL;
char *pCacheName = NULL;
krb5_context krbContext = NULL;
bzero( &my_creds, sizeof(my_creds) );
bzero( &kvno_creds, sizeof(kvno_creds) );
if( inPrinc == NULL || inPass == NULL )
return 0;
gLDAPKerberosMutex->Wait();
retval = krb5_init_context( &krbContext );
if ( 0 == retval )
{
retval = krb5_parse_name( krbContext, inPrinc, &principal );
}
if ( 0 == retval )
{
retval = krb5_unparse_name( krbContext, principal, &principalString );
}
if ( 0 == retval )
{
pCacheName = (char *) malloc( strlen(principalString) + sizeof("MEMORY:") + 1 ); strcpy( pCacheName, "MEMORY:" );
strcat( pCacheName, principalString );
}
if ( 0 == retval )
{
retval = krb5_cc_resolve( krbContext, pCacheName, &krbCache);
}
if ( 0 == retval )
{
retval = krb5_cc_set_default_name( krbContext, pCacheName );
}
if ( 0 == retval )
{
retval = krb5_cc_initialize( krbContext, krbCache, principal );
}
if ( 0 == retval )
{
krb5_int32 startTime = 0;
krb5_get_init_creds_opt options;
krb5_get_init_creds_opt_init( &options );
krb5_get_init_creds_opt_set_forwardable( &options, 1 );
krb5_get_init_creds_opt_set_proxiable( &options, 1 );
krb5_get_init_creds_opt_set_address_list( &options, NULL );
krb5_get_init_creds_opt_set_tkt_life( &options, 300 );
retval = krb5_get_init_creds_password( krbContext, &my_creds, principal, inPass, NULL, 0, startTime, NULL, &options );
}
if ( 0 == retval )
{
retval = krb5_cc_store_cred( krbContext, krbCache, &my_creds );
}
if ( 0 == retval )
{
krb5_copy_principal( krbContext, my_creds.client, &kvno_creds.client );
krb5_copy_principal( krbContext, my_creds.client, &kvno_creds.server );
retval = krb5_get_credentials( krbContext, 0, krbCache, &kvno_creds, &my_creds_out );
}
if ( 0 == retval )
{
retval = krb5_decode_ticket( &(my_creds_out->ticket), &ticket );
if ( 0 == retval )
{
kvno = ticket->enc_part.kvno;
krb5_free_ticket( krbContext, ticket );
ticket = NULL;
}
}
DSDelete( pCacheName );
krb5_free_cred_contents( krbContext, &my_creds );
krb5_free_cred_contents( krbContext, &kvno_creds );
if ( my_creds_out != NULL )
{
krb5_free_creds( krbContext, my_creds_out );
my_creds_out = NULL;
}
if ( principalString )
{
krb5_free_unparsed_name( krbContext, principalString );
principalString = NULL;
}
if ( principal )
{
krb5_free_principal( krbContext, principal );
principal = NULL;
}
if ( cachePrinc )
{
krb5_free_principal( krbContext, cachePrinc );
cachePrinc = NULL;
}
if ( krbCache )
{
krb5_cc_destroy( krbContext, krbCache );
krbCache = NULL;
}
if( krbContext )
{
krb5_free_context( krbContext );
krbContext = NULL;
}
gLDAPKerberosMutex->Signal();
return kvno;
}
#pragma mark -
#pragma mark CLDAPv3Plugin Member Functions
CLDAPv3Plugin::CLDAPv3Plugin ( FourCharCode inSig, const char *inName ) : CServerPlugin(inSig, inName)
{
fState = kUnknownState;
fState += kInactive;
bDoNotInitTwiceAtStartUp= true;
fDHCPLDAPServersString = NULL;
fPrevDHCPLDAPServersString = NULL;
fServerRunLoop = nil; fHandlingNetworkTransition = false;
fInitFlag = false;
gLDAPv3Plugin = this;
if ( gLDAPContinueTable == nil )
{
if (gServerOS)
{
gLDAPContinueTable = new CContinue( CLDAPv3Plugin::ContinueDeallocProc, 256 );
}
else
{
gLDAPContinueTable = new CContinue( CLDAPv3Plugin::ContinueDeallocProc, 64 );
}
}
if ( gLDAPContextTable == nil )
{
if (gServerOS)
{
gLDAPContextTable = new CPlugInRef( CLDAPv3Plugin::ContextDeallocProc, 1024 );
}
else
{
gLDAPContextTable = new CPlugInRef( CLDAPv3Plugin::ContextDeallocProc, 256 );
}
}
if ( gKickLDAPv3Requests == nil )
{
gKickLDAPv3Requests = new DSEventSemaphore();
}
}
CLDAPv3Plugin::~CLDAPv3Plugin ( void )
{
if ( gpConfigFromXML != nil)
{
delete ( gpConfigFromXML );
gpConfigFromXML = nil;
}
}
sInt32 CLDAPv3Plugin::Validate ( const char *inVersionStr, const uInt32 inSignature )
{
fPlugInSignature = inSignature;
return( noErr );
}
sInt32 CLDAPv3Plugin::Initialize ( void )
{
int countNodes = 0;
sInt32 siResult = eDSNoErr;
tDataList *pldapName = nil;
sLDAPConfigData *pConfig = nil;
char *server = nil;
char *searchBase = nil;
int portNumber = 389;
bool bIsSSL = false;
fCheckInitFlag.Wait();
if (fInitFlag == true)
{
SRVRLOG( kLogPlugin, "CLDAPv3Plugin: Initialize:: Currently initializing so returning success to caller" );
fCheckInitFlag.Signal();
return(siResult);
}
fInitFlag = true;
fCheckInitFlag.Signal();
try
{
if ( gpConfigFromXML == nil )
{
gpConfigFromXML = new CLDAPv3Configs();
if ( gpConfigFromXML == nil ) throw( (sInt32)eDSOpenNodeFailed ); }
siResult = gpConfigFromXML->Init();
if ( siResult != eDSNoErr ) throw( siResult );
CFDictionaryRef ourDHCPInfo = NULL;
CFStringRef ourDHCPServers = NULL;
CFDataRef ourDHCPServersData = NULL;
UInt8 *byteData = NULL;
bool bNewDHCPConfig = false;
DSCFRelease(fPrevDHCPLDAPServersString);
fPrevDHCPLDAPServersString = fDHCPLDAPServersString;
if (fPrevDHCPLDAPServersString != NULL)
{
CFRetain(fPrevDHCPLDAPServersString);
}
ourDHCPInfo = SCDynamicStoreCopyDHCPInfo(NULL, NULL);
if (ourDHCPInfo != NULL)
{
ourDHCPServersData = (CFDataRef) DHCPInfoGetOptionData(ourDHCPInfo, 95);
if (ourDHCPServersData != NULL)
{
byteData = (UInt8 *) calloc(1, CFDataGetLength(ourDHCPServersData));
if (byteData != NULL)
{
CFDataGetBytes(ourDHCPServersData, CFRangeMake( 0,
CFDataGetLength(ourDHCPServersData)),
byteData);
if (byteData[0] != '\0')
{
ourDHCPServers = CFStringCreateWithBytes( kCFAllocatorDefault,
byteData,
CFDataGetLength(ourDHCPServersData),
kCFStringEncodingUTF8,
false);
}
free(byteData);
} }
if (ourDHCPServers != NULL)
{
if ( CFGetTypeID( ourDHCPServers ) == CFStringGetTypeID() )
{
if ( ( fDHCPLDAPServersString == NULL ) || (CFStringCompare(fDHCPLDAPServersString, ourDHCPServers, 0) != kCFCompareEqualTo) )
{
DSCFRelease(fDHCPLDAPServersString);
fDHCPLDAPServersString = ourDHCPServers;
bNewDHCPConfig = true; }
else
{
CFRelease(ourDHCPServers);
ourDHCPServers = nil;
}
int serverIndex = 1;
while( ParseNextDHCPLDAPServerString(&server, &searchBase, &portNumber, &bIsSSL, serverIndex) )
{
gpConfigFromXML->MakeServerBasedMappingsLDAPConfig( server,
searchBase,
kLDAPDefaultOpenCloseTimeoutInSeconds,
2,
kLDAPDefaultRebindTryTimeoutInSeconds,
kLDAPDefaultSearchTimeoutInSeconds,
portNumber,
bIsSSL,
true,
true,
false);
DSFreeString(server);
DSFreeString(searchBase);
portNumber = 389;
bIsSSL = false;
serverIndex++;
}
} } else
{
DSCFRelease(fDHCPLDAPServersString);
}
DSCFRelease(ourDHCPInfo);
} else
{
DSCFRelease(fDHCPLDAPServersString);
}
gpConfigFromXML->ConfigMapWait();
list <string> goneDHCPServers;
if ( (fDHCPLDAPServersString != NULL) || (fPrevDHCPLDAPServersString != NULL) )
{
char **defaultLDAPNodes = nil;
uInt32 aDefaultLDAPNodeCount = 0;
defaultLDAPNodes = gpConfigFromXML->GetDefaultLDAPNodeStrings(aDefaultLDAPNodeCount);
if ( (aDefaultLDAPNodeCount > 0) && (defaultLDAPNodes != nil) )
{
int listIndex = 0;
CFRange foundInPrev;
CFRange foundInCurr;
for (listIndex=0; defaultLDAPNodes[listIndex] != nil; listIndex++)
{
CFStringRef serverString = CFStringCreateWithCString( NULL, defaultLDAPNodes[listIndex], kCFStringEncodingUTF8 );
foundInPrev.location = 0;
foundInCurr.location = 0;
if (fPrevDHCPLDAPServersString != NULL)
foundInPrev = CFStringFind(fPrevDHCPLDAPServersString, serverString, kCFCompareCaseInsensitive);
if (fDHCPLDAPServersString != NULL)
foundInCurr = CFStringFind(fDHCPLDAPServersString, serverString, kCFCompareCaseInsensitive);
if ( (foundInPrev.location != kCFNotFound) && (foundInCurr.location == kCFNotFound) )
{
goneDHCPServers.push_back(string(defaultLDAPNodes[listIndex]));
}
DSCFRelease(serverString);
}
}
DSFreeStringList(defaultLDAPNodes);
}
LDAPConfigDataMap configMap = gpConfigFromXML->GetConfigMap();
LDAPConfigDataMapI configIter = configMap.begin();
list <string> deadNodenames;
while( configIter != configMap.end() )
{
pConfig = configIter->second;
if (pConfig != nil)
{
if (pConfig->fNodeName != nil)
{
if (pConfig->bUseAsDefaultLDAP) {
for ( list<string>::iterator goneIter = goneDHCPServers.begin(); goneIter != goneDHCPServers.end(); ++goneIter)
{
if ( ( pConfig->fServerName != nil) && ( strcasecmp( pConfig->fServerName, (*goneIter).c_str()) == 0) )
pConfig->bUpdated = false;
}
}
if (pConfig->bUpdated)
{
countNodes++;
pConfig->bAvail = true;
pldapName = dsBuildListFromStringsPriv((char *)"LDAPv3", pConfig->fNodeName, nil);
if (pldapName != nil)
{
CServerPlugin::_RegisterNode( fPlugInSignature, pldapName, kDirNodeType );
dsDataListDeallocatePriv( pldapName);
free(pldapName);
pldapName = nil;
}
if (pConfig->bServerMappings)
{
pConfig->bGetServerMappings = true;
}
pConfig->bBuildReplicaList = true; } else
{
pldapName = dsBuildListFromStringsPriv((char *)"LDAPv3", pConfig->fNodeName, nil);
if (pldapName != nil)
{
CServerPlugin::_UnregisterNode( fPlugInSignature, pldapName );
dsDataListDeallocatePriv( pldapName);
free(pldapName);
pldapName = nil;
}
deadNodenames.push_back(string(pConfig->fNodeName));
gpConfigFromXML->DeleteConfigFromMap( pConfig->fNodeName );
pConfig = nil;
}
} }
configIter++;
}
gpConfigFromXML->ConfigMapSignal();
for ( list<string>::iterator deadIter = deadNodenames.begin(); deadIter != deadNodenames.end(); ++deadIter)
{
fLDAPSessionMgr.ForcedSafeClose( (*deadIter).c_str() );
}
fLDAPSessionMgr.NetTransition();
pldapName = dsBuildListFromStringsPriv((char *)"LDAPv3", "DHCPChecked", nil);
if (pldapName != nil)
{
CServerPlugin::_RegisterNode( fPlugInSignature, pldapName, kDHCPLDAPv3NodeType );
dsDataListDeallocatePriv( pldapName);
free(pldapName);
pldapName = nil;
}
if (!(fState & kInitialized))
{
fState += kInitialized;
}
if (fState & kFailedToInit)
{
fState -= kFailedToInit;
}
WakeUpRequests();
if( bNewDHCPConfig )
{
CFStringRef service = CFStringCreateWithCString( NULL, "DirectoryService", kCFStringEncodingUTF8 );
if( service )
{
SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, service, NULL, NULL);
if (store != NULL)
{ CFStringRef notify = CFStringCreateWithCString( NULL, "com.apple.DirectoryService.NotifyTypeStandard:DHCP_LDAP_CHANGE", kCFStringEncodingUTF8 );
if( notify ) {
SCDynamicStoreNotifyValue( store, notify );
CFRelease( notify );
}
CFRelease( store );
}
CFRelease( service );
}
}
} catch ( sInt32 err )
{
siResult = err;
fState = kUnknownState;
fState += kFailedToInit;
fState += kInactive;
}
fCheckInitFlag.Wait();
fInitFlag = false;
fCheckInitFlag.Signal();
return( siResult );
}
bool CLDAPv3Plugin::ParseNextDHCPLDAPServerString ( char **inServer, char **inSearchBase, int *inPortNumber, bool *inIsSSL, int inServerIndex )
{
bool foundNext = false;
char *tmpBuff = nil;
char *aString = nil;
uInt32 callocLength = 0;
char *aToken = nil;
int aIndex = 1;
uInt32 strLength = 0;
char *ptr = nil;
if (fDHCPLDAPServersString == NULL)
{
return(foundNext);
}
callocLength = (uInt32) CFStringGetMaximumSizeForEncoding(CFStringGetLength(fDHCPLDAPServersString), kCFStringEncodingUTF8) + 1;
tmpBuff = (char *) calloc(1, callocLength);
CFStringGetCString( fDHCPLDAPServersString, tmpBuff, callocLength, kCFStringEncodingUTF8 );
aString = tmpBuff;
aToken = strsep(&aString,LDAPURLOPT95SEPCHAR);
if (inServerIndex > 1)
{
aIndex = inServerIndex;
while (aIndex != 1)
{
aToken = strsep(&aString, LDAPURLOPT95SEPCHAR);
aIndex--;
}
}
if (aToken != nil)
{
*inServer = nil;
*inSearchBase = nil;
if ( strncmp(aToken,"ldap://",7) == 0 )
{
*inPortNumber = 389;
*inIsSSL = false;
aToken = aToken + 7;
}
else if ( strncmp(aToken,"ldaps://",8) == 0 )
{
*inPortNumber = 636;
*inIsSSL = true;
aToken = aToken + 8;
}
else
{
syslog(LOG_ALERT,"DSLDAPv3PlugIn: DHCP option 95 error since obtained [%s] LDAP server prefix is not of the correct format.", aToken);
if ( tmpBuff != nil )
{
free(tmpBuff);
tmpBuff = nil;
}
return(foundNext);
}
ptr = aToken;
strLength = 0;
while ( (*ptr != '\0') && (*ptr != ':') && (*ptr != '/') )
{
strLength++;
ptr++;
}
if (strLength != 0)
{
*inServer = (char *) calloc(1, strLength+1);
strncpy(*inServer, aToken, strLength);
aToken = aToken + strLength;
foundNext = true;
}
else
{
syslog(LOG_ALERT,"DSLDAPv3PlugIn: DHCP option 95 error since can't extract LDAP server name from URL.");
if ( tmpBuff != nil )
{
free(tmpBuff);
tmpBuff = nil;
}
return(foundNext);
}
if (*ptr == ':')
{
ptr++;
aToken++;
strLength = 0;
while ( (*ptr != '\0') && (*ptr != '/') )
{
strLength++;
ptr++;
}
if (strLength != 0)
{
char *portStr = nil;
portStr = (char *) calloc(1, strLength+1);
strncpy(portStr, aToken, strLength);
*inPortNumber = atoi(portStr);
free(portStr);
portStr = nil;
aToken = aToken + strLength;
}
}
if (*ptr == '/')
{
ptr++;
aToken++;
strLength = 0;
while ( (*ptr != '\0') && (*ptr != '?') )
{
strLength++;
ptr++;
}
if (strLength != 0)
{
*inSearchBase = (char *) calloc(1, strLength+1);
strncpy(*inSearchBase, aToken, strLength);
ptr = *inSearchBase;
char *BasePtr = ptr;
while (*ptr != '\0')
{
if (*ptr == '%')
{
ptr++;
if (*ptr == '2')
{
ptr++;
if (*ptr == '0')
{
*ptr = ' ';
}
}
}
*BasePtr = *ptr;
ptr++;
BasePtr++;
}
*BasePtr = *ptr; }
}
}
if ( tmpBuff != nil )
{
free(tmpBuff);
tmpBuff = nil;
}
return(foundNext);
}
sInt32 CLDAPv3Plugin::SetPluginState ( const uInt32 inState )
{
tDataList *pldapName = nil;
sLDAPConfigData *pConfig = nil;
if (inState & kActive) {
if ( (fState & kInactive) && (!(fState & kActive)) )
{
if (bDoNotInitTwiceAtStartUp)
{
bDoNotInitTwiceAtStartUp = false;
}
else
{
Initialize();
}
fState += kActive;
fState -= kInactive;
}
}
if (inState & kInactive) {
if ( (fState & kActive) && (!(fState & kInactive)) )
{
gpConfigFromXML->ConfigMapWait();
LDAPConfigDataMap configMap = gpConfigFromXML->GetConfigMap();
LDAPConfigDataMapI configIter = configMap.begin();
while( configIter != configMap.end() )
{
pConfig = configIter->second;
if (pConfig != nil)
{
if (pConfig->fNodeName != nil)
{
pldapName = dsBuildListFromStringsPriv((char *)"LDAPv3", pConfig->fNodeName, nil);
if (pldapName != nil)
{
CServerPlugin::_UnregisterNode( fPlugInSignature, pldapName );
dsDataListDeallocatePriv( pldapName);
free(pldapName);
pldapName = nil;
}
} }
configIter++;
}
fState += kInactive;
fState -= kActive;
gpConfigFromXML->ConfigMapSignal();
}
}
return( eDSNoErr );
}
void CLDAPv3Plugin::WakeUpRequests ( void )
{
gKickLDAPv3Requests->Signal();
}
void CLDAPv3Plugin::WaitForInit ( void )
{
volatile uInt32 uiAttempts = 0;
if (!(fState & kActive))
{
while ( !(fState & kInitialized) &&
!(fState & kFailedToInit) )
{
if ( uiAttempts++ >= 240 )
{
return;
}
gKickLDAPv3Requests->Wait( (uInt32)(.5 * kMilliSecsPerSec) );
gKickLDAPv3Requests->Reset();
}
}}
sInt32 CLDAPv3Plugin::ProcessRequest ( void *inData )
{
sInt32 siResult = 0;
char *pathStr = nil;
if ( inData == nil )
{
return( ePlugInDataError );
}
if (((sHeader *)inData)->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;
}
}
}
if ( ((sHeader *)inData)->fType == kServerRunLoop )
{
if ( (((sHeader *)inData)->fContextData) != nil )
{
fServerRunLoop = (CFRunLoopRef)(((sHeader *)inData)->fContextData);
return (siResult);
}
}
if ( ((sHeader *)inData)->fType == kKerberosMutex )
{
if( (((sHeader *)inData)->fContextData) != nil )
{
gLDAPKerberosMutex = (DSMutexSemaphore *)(((sHeader *)inData)->fContextData);
return siResult;
}
}
WaitForInit();
if (fState == kUnknownState)
{
return( (sInt32)ePlugInCallTimedOut );
}
if ( (fState & kFailedToInit) || !(fState & kInitialized) )
{
return( (sInt32)ePlugInFailedToInitialize );
}
if ( ((fState & kInactive) || !(fState & kActive))
&& (((sHeader *)inData)->fType != kDoPlugInCustomCall)
&& (((sHeader *)inData)->fType != kOpenDirNode) )
{
return( ePlugInNotActive );
}
if ( ((sHeader *)inData)->fType == kHandleNetworkTransition )
{
if (!gBlockLDAPNetworkChange)
{
HandleMultipleNetworkTransitionsForLDAP();
}
}
else
{
siResult = HandleRequest( inData );
}
return( siResult );
}
sInt32 CLDAPv3Plugin::HandleRequest ( void *inData )
{
sInt32 siResult = 0;
sHeader *pMsgHdr = nil;
bool bWaitForInit= true;
DSSemaphore timedWait;
while(bWaitForInit)
{
fCheckInitFlag.Wait();
if (fInitFlag)
{
fCheckInitFlag.Signal();
timedWait.Wait( (uInt32)(.1 * kMilliSecsPerSec) );
}
else
{
fCheckInitFlag.Signal();
bWaitForInit = false;
}
}
if ( inData == nil )
{
return( -8088 );
}
pMsgHdr = (sHeader *)inData;
switch ( pMsgHdr->fType )
{
case kOpenDirNode:
siResult = OpenDirNode( (sOpenDirNode *)inData );
break;
case kCloseDirNode:
siResult = CloseDirNode( (sCloseDirNode *)inData );
break;
case kGetDirNodeInfo:
siResult = GetDirNodeInfo( (sGetDirNodeInfo *)inData );
break;
case kGetRecordList:
siResult = GetRecordList( (sGetRecordList *)inData );
break;
case kGetRecordEntry:
siResult = GetRecordEntry( (sGetRecordEntry *)inData );
break;
case kGetAttributeEntry:
siResult = GetAttributeEntry( (sGetAttributeEntry *)inData );
break;
case kGetAttributeValue:
siResult = GetAttributeValue( (sGetAttributeValue *)inData );
break;
case kOpenRecord:
siResult = OpenRecord( (sOpenRecord *)inData );
break;
case kGetRecordReferenceInfo:
siResult = GetRecRefInfo( (sGetRecRefInfo *)inData );
break;
case kGetRecordAttributeInfo:
siResult = GetRecAttribInfo( (sGetRecAttribInfo *)inData );
break;
case kGetRecordAttributeValueByIndex:
siResult = GetRecAttrValueByIndex( (sGetRecordAttributeValueByIndex *)inData );
break;
case kGetRecordAttributeValueByValue:
siResult = GetRecAttrValueByValue( (sGetRecordAttributeValueByValue *)inData );
break;
case kGetRecordAttributeValueByID:
siResult = GetRecordAttributeValueByID( (sGetRecordAttributeValueByID *)inData );
break;
case kFlushRecord:
siResult = FlushRecord( (sFlushRecord *)inData );
break;
case kCloseAttributeList:
siResult = CloseAttributeList( (sCloseAttributeList *)inData );
break;
case kCloseAttributeValueList:
siResult = CloseAttributeValueList( (sCloseAttributeValueList *)inData );
break;
case kCloseRecord:
siResult = CloseRecord( (sCloseRecord *)inData );
break;
case kReleaseContinueData:
siResult = ReleaseContinueData( (sReleaseContinueData *)inData );
break;
case kSetRecordName:
siResult = SetRecordName( (sSetRecordName *)inData );
break;
case kSetRecordType:
siResult = eNotYetImplemented; break;
case kDeleteRecord:
siResult = DeleteRecord( (sDeleteRecord *)inData );
break;
case kCreateRecord:
case kCreateRecordAndOpen:
siResult = CreateRecord( (sCreateRecord *)inData );
break;
case kAddAttribute:
siResult = AddAttribute( (sAddAttribute *)inData );
break;
case kRemoveAttribute:
siResult = RemoveAttribute( (sRemoveAttribute *)inData );
break;
case kAddAttributeValue:
siResult = AddAttributeValue( (sAddAttributeValue *)inData );
break;
case kRemoveAttributeValue:
siResult = RemoveAttributeValue( (sRemoveAttributeValue *)inData );
break;
case kSetAttributeValue:
siResult = SetAttributeValue( (sSetAttributeValue *)inData );
break;
case kSetAttributeValues:
siResult = SetAttributeValues( (sSetAttributeValues *)inData );
break;
case kDoDirNodeAuth:
siResult = DoAuthentication( (sDoDirNodeAuth *)inData );
break;
case kDoDirNodeAuthOnRecordType:
if ( ( ((sDoDirNodeAuthOnRecordType *)inData)->fInRecordType != NULL) &&
( ((sDoDirNodeAuthOnRecordType *)inData)->fInRecordType->fBufferData != NULL) )
{
siResult = DoAuthenticationOnRecordType( (sDoDirNodeAuthOnRecordType *)inData,
((sDoDirNodeAuthOnRecordType *)inData)->fInRecordType->fBufferData );
}
break;
case kDoAttributeValueSearch:
case kDoAttributeValueSearchWithData:
siResult = DoAttributeValueSearch( (sDoAttrValueSearchWithData *)inData );
break;
case kDoMultipleAttributeValueSearch:
case kDoMultipleAttributeValueSearchWithData:
siResult = DoMultipleAttributeValueSearch( (sDoMultiAttrValueSearchWithData *)inData );
break;
case kDoPlugInCustomCall:
siResult = DoPlugInCustomCall( (sDoPlugInCustomCall *)inData );
break;
case kHandleSystemWillSleep:
siResult = eDSNoErr;
fLDAPSessionMgr.SystemGoingToSleep();
break;
case kHandleSystemWillPowerOn:
siResult = eDSNoErr;
fLDAPSessionMgr.SystemWillPowerOn();
break;
default:
siResult = eNotHandledByThisNode;
break;
}
pMsgHdr->fResult = siResult;
return( siResult );
}
sInt32 CLDAPv3Plugin::OpenDirNode ( sOpenDirNode *inData )
{
char *ldapName = nil;
char *pathStr = nil;
char *subStr = nil;
sLDAPContextData *pContext = nil;
sInt32 siResult = eDSNoErr;
tDataListPtr pNodeList = nil;
pNodeList = inData->fInDirNodeName;
try
{
if ( inData != nil )
{
pathStr = dsGetPathFromListPriv( pNodeList, (char *)"/" );
if ( pathStr == nil ) throw( (sInt32)eDSNullNodeName );
if (::strcmp(pathStr,"/LDAPv3") == 0)
{
pContext = new sLDAPContextData;
pContext->fNodeName = strdup("LDAPv3 Configure");
pContext->fLDAPNodeStruct = new sLDAPNodeStruct;
pContext->fUID = inData->fInUID;
pContext->fEffectiveUID = inData->fInEffectiveUID;
gLDAPContextTable->AddItem( inData->fOutNodeRef, pContext );
}
else if ( (strlen(pathStr) > 8) && (::strncmp(pathStr,"/LDAPv3/",8) == 0) )
{
subStr = pathStr + 8;
ldapName = strdup( subStr );
if ( ldapName == nil ) throw( (sInt32)eDSNullNodeName );
::strcpy(ldapName,subStr);
pContext = new sLDAPContextData;
pContext->fNodeName = ldapName;
pContext->fUID = inData->fInUID;
pContext->fEffectiveUID = inData->fInEffectiveUID;
siResult = fLDAPSessionMgr.SafeOpen( (char *)ldapName, &(pContext->fLDAPNodeStruct) );
if ( siResult != eDSNoErr)
{
delete pContext;
pContext = nil;
throw( (sInt32)eDSOpenNodeFailed );
}
if (gpConfigFromXML != nil)
{
sLDAPConfigData *pConfig = gpConfigFromXML->ConfigWithNodeNameLock( ldapName );
if (pConfig != nil)
{
pContext->bLDAPv2ReadOnly = pConfig->bLDAPv2ReadOnly;
gpConfigFromXML->ConfigUnlock( pConfig );
pConfig = NULL;
}
}
gLDAPContextTable->AddItem( inData->fOutNodeRef, pContext );
} else
{
siResult = eDSOpenNodeFailed;
}
} else
{
siResult = eDSNullParameter;
}
} catch ( sInt32 err )
{
siResult = err;
if (pContext != nil)
{
gLDAPContextTable->RemoveItem( inData->fOutNodeRef );
}
}
if (pathStr != nil)
{
delete( pathStr );
pathStr = nil;
}
return( siResult );
}
sInt32 CLDAPv3Plugin::CloseDirNode ( sCloseDirNode *inData )
{
sInt32 siResult = eDSNoErr;
sLDAPContextData *pContext = nil;
sLDAPNodeStruct *pNodeStruct = nil;
try
{
pContext = (sLDAPContextData *)gLDAPContextTable->GetItemData( inData->fInNodeRef );
if ( pContext == nil ) throw( (sInt32)eDSBadContextData );
if( strcmp(pContext->fNodeName, "LDAPv3 Configure") == 0 )
{
pNodeStruct = pContext->fLDAPNodeStruct;
}
gLDAPContinueTable->RemoveItems( inData->fInNodeRef );
gLDAPContextTable->RemoveItem( inData->fInNodeRef );
DSDelete( pNodeStruct );
}
catch ( sInt32 err )
{
siResult = err;
}
return( siResult );
}
sInt32 CLDAPv3Plugin::GetRecordList ( sGetRecordList *inData )
{
sInt32 siResult = eDSNoErr;
uInt32 uiTotal = 0;
uInt32 uiCount = 0;
char *pRecType = nil;
char *pLDAPRecType = nil;
bool bAttribOnly = false;
tDirPatternMatch pattMatch = eDSNoMatch1;
char **pRecNames = nil;
CAttributeList *cpRecTypeList = nil;
CAttributeList *cpAttrTypeList = nil;
sLDAPContextData *pContext = nil;
sLDAPContinueData *pLDAPContinue = nil;
CBuff *outBuff = nil;
int numRecTypes = 1;
bool bBuffFull = false;
bool separateRecTypes = false;
uInt32 countDownRecTypes = 0;
bool bOCANDGroup = false;
CFArrayRef OCSearchList = nil;
ber_int_t scope = LDAP_SCOPE_SUBTREE;
try
{
if ( inData == nil ) throw( (sInt32) eMemoryError );
if ( inData->fInDataBuff == nil ) throw( (sInt32)eDSEmptyBuffer );
if (inData->fInDataBuff->fBufferSize == 0) throw( (sInt32)eDSEmptyBuffer );
if ( inData->fInRecNameList == nil ) throw( (sInt32)eDSEmptyRecordNameList );
if ( inData->fInRecTypeList == nil ) throw( (sInt32)eDSEmptyRecordTypeList );
if ( inData->fInAttribTypeList == nil ) throw( (sInt32)eDSEmptyAttributeTypeList );
pContext = (sLDAPContextData *)gLDAPContextTable->GetItemData( inData->fInNodeRef );
if ( pContext == nil ) throw( (sInt32)eDSBadContextData );
if ( inData->fIOContinueData == nil )
{
pLDAPContinue = (sLDAPContinueData *)::calloc( 1, sizeof( sLDAPContinueData ) );
gLDAPContinueTable->AddItem( pLDAPContinue, inData->fInNodeRef );
pLDAPContinue->fRecNameIndex = 1;
pLDAPContinue->fRecTypeIndex = 1;
pLDAPContinue->fTotalRecCount = 0;
pLDAPContinue->fLimitRecSearch = 0;
if (inData->fOutRecEntryCount >= 0)
{
pLDAPContinue->fLimitRecSearch = inData->fOutRecEntryCount;
}
}
else
{
pLDAPContinue = (sLDAPContinueData *)inData->fIOContinueData;
if ( gLDAPContinueTable->VerifyItem( pLDAPContinue ) == false )
{
throw( (sInt32)eDSInvalidContinueData );
}
}
inData->fIOContinueData = nil;
inData->fOutRecEntryCount = 0;
outBuff = new CBuff();
if ( outBuff == nil ) throw( (sInt32) eMemoryError );
siResult = outBuff->Initialize( inData->fInDataBuff, true );
if ( siResult != eDSNoErr ) throw( siResult );
siResult = outBuff->GetBuffStatus();
if ( siResult != eDSNoErr ) throw( siResult );
siResult = outBuff->SetBuffType( 'StdA' );
if ( siResult != eDSNoErr ) throw( siResult );
pRecNames = dsAllocStringsFromList(0, inData->fInRecNameList);
if ( pRecNames == nil ) throw( (sInt32)eDSEmptyRecordNameList );
pattMatch = inData->fInPatternMatch;
cpRecTypeList = new CAttributeList( inData->fInRecTypeList );
if ( cpRecTypeList == nil ) throw( (sInt32)eDSEmptyRecordTypeList );
countDownRecTypes = cpRecTypeList->GetCount() - pLDAPContinue->fRecTypeIndex + 1;
if (cpRecTypeList->GetCount() == 0) throw( (sInt32)eDSEmptyRecordTypeList );
cpAttrTypeList = new CAttributeList( inData->fInAttribTypeList );
if ( cpAttrTypeList == nil ) throw( (sInt32)eDSEmptyAttributeTypeList );
if (cpAttrTypeList->GetCount() == 0) throw( (sInt32)eDSEmptyAttributeTypeList );
bAttribOnly = inData->fInAttribInfoOnly;
while ((( cpRecTypeList->GetAttribute( pLDAPContinue->fRecTypeIndex, &pRecType ) == eDSNoErr ) && (!bBuffFull)) && (!separateRecTypes))
{
numRecTypes = 1;
bOCANDGroup = false;
if (OCSearchList != nil)
{
CFRelease(OCSearchList);
OCSearchList = nil;
}
pLDAPRecType = MapRecToLDAPType( (const char *)pRecType, pContext->fNodeName, numRecTypes, &bOCANDGroup, &OCSearchList, &scope );
if ( ( pLDAPRecType == nil ) && (countDownRecTypes == 1) )
throw( (sInt32)eDSInvalidRecordType );
while (( pLDAPRecType != nil ) && (!bBuffFull))
{
bBuffFull = false;
if ( ::strcmp( pRecNames[0], kDSRecordsAll ) == 0 ) {
siResult = GetAllRecords( pRecType, pLDAPRecType, cpAttrTypeList, pContext, pLDAPContinue, bAttribOnly, outBuff, uiCount, bOCANDGroup, OCSearchList, scope );
}
else
{
siResult = GetTheseRecords( (char *)kDSNAttrRecordName, pRecNames, pRecType, pLDAPRecType, pattMatch, cpAttrTypeList, pContext, pLDAPContinue, bAttribOnly, outBuff, uiCount, bOCANDGroup, OCSearchList, scope );
}
if ( siResult == CBuff::kBuffFull )
{
bBuffFull = true;
inData->fIOContinueData = pLDAPContinue;
if ( ( uiCount == 0 ) && ( uiTotal == 0 ) )
{
throw( (sInt32)eDSBufferTooSmall );
}
uiTotal += uiCount;
inData->fOutRecEntryCount = uiTotal;
outBuff->SetLengthToSize();
siResult = eDSNoErr;
}
else if ( siResult == eDSNoErr )
{
uiTotal += uiCount;
pLDAPContinue->fRecNameIndex++;
pLDAPContinue->msgId = 0;
}
if (pLDAPRecType != nil)
{
delete( pLDAPRecType );
pLDAPRecType = nil;
}
if (!bBuffFull)
{
numRecTypes++;
bOCANDGroup = false;
if (OCSearchList != nil)
{
CFRelease(OCSearchList);
OCSearchList = nil;
}
pLDAPContinue->fRecNameIndex = 1;
pLDAPRecType = MapRecToLDAPType( (const char *)pRecType, pContext->fNodeName, numRecTypes, &bOCANDGroup, &OCSearchList, &scope );
}
}
if (!bBuffFull)
{
pRecType = nil;
pLDAPContinue->fRecTypeIndex++;
pLDAPContinue->fRecNameIndex = 1;
pLDAPContinue->msgId = 0;
separateRecTypes = true;
inData->fIOContinueData = pLDAPContinue;
siResult = eDSNoErr;
countDownRecTypes--;
if (countDownRecTypes == 0)
{
inData->fIOContinueData = nil;
}
}
}
if (( siResult == eDSNoErr ) & (!bBuffFull))
{
if ( uiTotal == 0 )
{
outBuff->ClearBuff();
}
else
{
outBuff->SetLengthToSize();
}
inData->fOutRecEntryCount = uiTotal;
}
}
catch ( sInt32 err )
{
siResult = err;
}
if (OCSearchList != nil)
{
CFRelease(OCSearchList);
OCSearchList = nil;
}
if ( (inData->fIOContinueData == nil) && (pLDAPContinue != nil) )
{
gLDAPContinueTable->RemoveItem( pLDAPContinue );
pLDAPContinue = nil;
}
if (pLDAPRecType != nil)
{
delete( pLDAPRecType );
pLDAPRecType = nil;
}
if ( cpRecTypeList != nil )
{
delete( cpRecTypeList );
cpRecTypeList = nil;
}
if ( cpAttrTypeList != nil )
{
delete( cpAttrTypeList );
cpAttrTypeList = nil;
}
if ( outBuff != nil )
{
delete( outBuff );
outBuff = nil;
}
if (pRecNames != nil)
{
uInt32 strCnt = 0;
while(pRecNames[strCnt] != nil)
{
free(pRecNames[strCnt]);
pRecNames[strCnt] = nil;
strCnt++;
}
free(pRecNames);
pRecNames = nil;
}
return( siResult );
}
char* CLDAPv3Plugin::MapRecToLDAPType ( const char *inRecType, char *inConfigName, int inIndex, bool *outOCGroup, CFArrayRef *outOCListCFArray, ber_int_t *outScope )
{
char *outResult = nil;
uInt32 uiStrLen = 0;
uInt32 uiNativeLen = ::strlen( kDSNativeRecordTypePrefix );
uInt32 uiStdLen = ::strlen( kDSStdRecordTypePrefix );
if ( ( inRecType != nil ) && (inIndex > 0) )
{
uiStrLen = ::strlen( inRecType );
if ( uiStrLen >= uiNativeLen && ::strncmp( inRecType, kDSNativeRecordTypePrefix, uiNativeLen ) == 0 )
{
if ( ( uiStrLen > uiNativeLen ) && (inIndex == 1) )
{
uiStrLen = uiStrLen - uiNativeLen;
outResult = (char *) calloc(1, uiStrLen + 2);
::strcpy( outResult, inRecType + uiNativeLen );
DBGLOG1( kLogPlugin, "CLDAPv3Plugin: MapRecToLDAPType:: Warning:Native record type <%s> is being used", outResult );
}
} else if ( uiStrLen >= uiStdLen && ::strncmp( inRecType, kDSStdRecordTypePrefix, uiStdLen ) == 0 )
{
sLDAPConfigData *pConfig = gpConfigFromXML->ConfigWithNodeNameLock( inConfigName );
if (pConfig != nil)
{
if ( pConfig->fRecordAttrMapDict )
{
outResult = gpConfigFromXML->ExtractRecMap(inRecType, pConfig->fRecordAttrMapDict, inIndex, outOCGroup, outOCListCFArray, outScope );
}
else
{
}
gpConfigFromXML->ConfigUnlock( pConfig );
}
} else if( inIndex == 1 )
{
outResult = (char *) calloc( 1, 1 + ::strlen( inRecType ) );
::strcpy( outResult, inRecType );
DBGLOG1( kLogPlugin, "CLDAPv3Plugin: MapRecToLDAPType:: Warning:Native record type with no provided prefix <%s> is being used", outResult );
}
}
return( outResult );
}
sInt32 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 )
{
sInt32 siResult = eDSNoErr;
sInt32 siValCnt = 0;
int ldapReturnCode = 0;
bool bufferFull = false;
LDAPMessage *result = nil;
char *recName = nil;
sLDAPConfigData *pConfig = nil;
int searchTO = 0;
CDataBuff *aRecData = nil;
CDataBuff *aAttrData = nil;
char *queryFilter = nil;
queryFilter = BuildLDAPQueryFilter( nil,
nil,
eDSAnyMatch,
inContext->fNodeName,
false,
(const char *)inRecType,
inNativeRecType,
inbOCANDGroup,
inOCSearchList );
outRecCount = 0;
try
{
if (inContext == nil ) throw( (sInt32)eDSInvalidContext);
if (inContinue == nil ) throw( (sInt32)eDSInvalidContinueData);
if ( queryFilter == nil ) throw( (sInt32)eDSNullParameter );
aRecData = new CDataBuff();
if ( aRecData == nil ) throw( (sInt32) eMemoryError );
aAttrData = new CDataBuff();
if ( aAttrData == nil ) throw( (sInt32) eMemoryError );
pConfig = gpConfigFromXML->ConfigWithNodeNameLock( inContext->fNodeName );
if (pConfig != nil)
{
searchTO = pConfig->fSearchTimeout;
gpConfigFromXML->ConfigUnlock( pConfig );
pConfig = NULL;
}
DSDoSearch ( inRecType,
inNativeRecType,
inAttrTypeList,
inContext,
inContinue,
inScope,
fLDAPSessionMgr,
queryFilter,
ldapReturnCode,
searchTO,
result);
while ( ( (ldapReturnCode == LDAP_RES_SEARCH_ENTRY) || (ldapReturnCode == LDAP_RES_SEARCH_RESULT) )
&& !(bufferFull)
&& ( (inContinue->fTotalRecCount < inContinue->fLimitRecSearch) ||
(inContinue->fLimitRecSearch == 0) ) )
{
if (ldapReturnCode == LDAP_RES_SEARCH_ENTRY)
{
aAttrData->Clear();
aRecData->Clear();
if ( inRecType != nil )
{
aRecData->AppendShort( ::strlen( inRecType ) );
aRecData->AppendString( inRecType );
} else
{
aRecData->AppendShort( ::strlen( "Record Type Unknown" ) );
aRecData->AppendString( "Record Type Unknown" );
}
recName = GetRecordName( inRecType, result, inContext, siResult );
if ( siResult != eDSNoErr ) throw( siResult );
if ( recName != nil )
{
aRecData->AppendShort( ::strlen( recName ) );
aRecData->AppendString( recName );
delete ( recName );
recName = nil;
}
else
{
aRecData->AppendShort( ::strlen( "Record Name Unknown" ) );
aRecData->AppendString( "Record Name Unknown" );
}
aAttrData->Clear();
siResult = GetTheseAttributes( inRecType, inAttrTypeList, result, inAttrOnly, inContext, siValCnt, aAttrData );
if ( siResult != eDSNoErr ) throw( siResult );
if ( siValCnt == 0 )
{
aRecData->AppendShort( 0 );
}
else
{
aRecData->AppendShort( siValCnt );
aRecData->AppendBlock( aAttrData->GetData(), aAttrData->GetLength() );
}
siResult = inBuff->AddData( aRecData->GetData(), aRecData->GetLength() );
}
if (siResult == CBuff::kBuffFull)
{
bufferFull = true;
inContinue->pResult = result;
}
else if ( siResult == eDSNoErr )
{
ldap_msgfree( result );
result = nil;
if (ldapReturnCode == LDAP_RES_SEARCH_ENTRY)
{
outRecCount++; inContinue->fTotalRecCount++;
}
inContinue->pResult = nil;
DSGetSearchLDAPResult ( fLDAPSessionMgr,
inContext,
searchTO,
result,
LDAP_MSG_ONE,
inContinue->msgId,
ldapReturnCode,
false);
}
else
{
inContinue->pResult = nil;
throw( (sInt32)eDSInvalidBuffFormat );
}
}
if ( (result != inContinue->pResult) && (result != nil) )
{
ldap_msgfree( result );
result = nil;
}
if ( (siResult == eDSNoErr) && (inContinue != NULL) && (inContinue->msgId != 0) )
{
LDAP *aHost = nil;
aHost = fLDAPSessionMgr.LockSession(inContext);
if (aHost != nil)
{
DSSearchCleanUp(aHost, inContinue->msgId);
}
fLDAPSessionMgr.UnLockSession(inContext);
}
}
catch ( sInt32 err )
{
siResult = err;
}
if ( queryFilter != nil )
{
delete( queryFilter );
queryFilter = nil;
}
if (aRecData != nil)
{
delete (aRecData);
aRecData = nil;
}
if (aAttrData != nil)
{
delete (aAttrData);
aAttrData = nil;
}
return( siResult );
}
sInt32 CLDAPv3Plugin::GetRecordEntry ( sGetRecordEntry *inData )
{
sInt32 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;
try
{
if ( inData == nil ) throw( (sInt32) eMemoryError );
if ( inData->fInOutDataBuff == nil ) throw( (sInt32)eDSEmptyBuffer );
if (inData->fInOutDataBuff->fBufferSize == 0) throw( (sInt32)eDSEmptyBuffer );
siResult = inBuff.Initialize( inData->fInOutDataBuff );
if ( siResult != eDSNoErr ) throw( siResult );
siResult = inBuff.GetDataBlockCount( &uiCount );
if ( siResult != eDSNoErr ) throw( siResult );
uiIndex = inData->fInRecEntryIndex;
if ((uiIndex > uiCount) || (uiIndex == 0)) throw( (sInt32)eDSInvalidIndex );
pData = inBuff.GetDataBlock( uiIndex, &uberOffset );
if ( pData == nil ) throw( (sInt32)eDSCorruptBuffer );
buffLen = inBuff.GetDataBlockLength( uiIndex );
pData += 4;
offset = 0;
if (offset + 2 > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &usTypeLen, pData, 2 );
pData += 2;
offset += 2;
pRecType = pData;
pData += usTypeLen;
offset += usTypeLen;
if (offset + 2 > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &usNameLen, pData, 2 );
pData += 2;
offset += 2;
pRecName = pData;
pData += usNameLen;
offset += usNameLen;
if (offset + 2 > buffLen) throw( (sInt32)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( (sInt32) eMemoryAllocError );
pContext->offset = uberOffset + offset + 4;
gLDAPContextTable->AddItem( inData->fOutAttrListRef, pContext );
inData->fOutRecEntryPtr = pRecEntry;
}
catch ( sInt32 err )
{
siResult = err;
}
return( siResult );
}
sInt32 CLDAPv3Plugin::GetTheseAttributes ( char *inRecType,
CAttributeList *inAttrTypeList,
LDAPMessage *inResult,
bool inAttrOnly,
sLDAPContextData *inContext,
sInt32 &outCount,
CDataBuff *inDataBuff )
{
sInt32 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;
uInt32 literalLength = 0;
LDAP *aHost = nil;
try
{
if ( inContext == nil ) throw( (sInt32)eDSBadContextData );
outCount = 0;
aTmpData = new CDataBuff();
if ( aTmpData == nil ) throw( (sInt32) eMemoryError );
aTmp2Data = new CDataBuff();
if ( aTmp2Data == nil ) throw( (sInt32) eMemoryError );
inDataBuff->Clear();
while ( inAttrTypeList->GetAttribute( attrTypeIndex++, &pAttrType ) == eDSNoErr )
{
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;
if ( inContext->fNodeName != nil )
{
tmpStr = (char *) calloc(1, 1+8+::strlen(inContext->fNodeName));
::strcpy( tmpStr, "/LDAPv3/" );
::strcat( tmpStr, inContext->fNodeName );
}
else
{
tmpStr = (char *) calloc(1, 1+::strlen("Unknown Node Location"));
::strcpy( tmpStr, "Unknown Node Location" );
}
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( ::strlen( kDSNAttrMetaNodeLocation ) );
aTmpData->AppendString( kDSNAttrMetaNodeLocation );
if ( inAttrOnly == false )
{
aTmpData->AppendShort( 1 );
char *tmpStr = nil;
if ( inContext->fNodeName != nil )
{
tmpStr = (char *) calloc(1, 1+8+::strlen(inContext->fNodeName));
::strcpy( tmpStr, "/LDAPv3/" );
::strcat( tmpStr, inContext->fNodeName );
}
else
{
tmpStr = (char *) calloc(1, 1+::strlen("Unknown Node Location"));
::strcpy( tmpStr, "Unknown Node Location" );
}
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( ::strlen( kDSNAttrRecordType ) );
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() );
aTmpData->Clear();
pLDAPPasswdAttrType = MapAttrToLDAPType( (const char *)inRecType, kDS1AttrPassword, inContext->fNodeName, 1, true );
numStdAttributes = 1;
pStdAttrType = GetNextStdAttrType( inRecType, inContext->fNodeName, numStdAttributes );
while ( pStdAttrType != nil )
{
numAttributes = 1;
pLDAPAttrType = MapAttrToLDAPType( (const char *)inRecType, pStdAttrType, inContext->fNodeName, 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 = fLDAPSessionMgr.LockSession(inContext);
if (aHost != nil)
{
for ( pAttr = ldap_first_attribute (aHost, inResult, &ber );
pAttr != NULL; pAttr = ldap_next_attribute(aHost, inResult, ber ) )
{
bStripCryptPrefix = false;
if (::strcasecmp( pAttr, pLDAPAttrType ) == 0)
{
if (pLDAPPasswdAttrType != nil )
{
if ( ( ::strcasecmp( pAttr, pLDAPPasswdAttrType ) == 0 ) &&
( ::strcmp( pStdAttrType, kDS1AttrPassword ) == 0 ) )
{
bStripCryptPrefix = true;
bUsePlus = false;
free(pLDAPPasswdAttrType);
pLDAPPasswdAttrType = nil;
}
}
bAtLeastOneTypeValid = true;
if (!bTypeFound)
{
aTmp2Data->Clear();
aTmp2Data->AppendShort( ::strlen( pStdAttrType ) );
aTmp2Data->AppendString( pStdAttrType );
bTypeFound = true;
valCount = 0;
aTmpData->Clear();
}
if (( inAttrOnly == false ) &&
(( bValues = ldap_get_values_len (aHost, inResult, pAttr )) != NULL) )
{
if (bStripCryptPrefix)
{
bStripCryptPrefix = false; for (int ii = 0; bValues[ii] != NULL; ii++ )
valCount++;
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;
}
}
if (pAttr != nil)
{
ldap_memfree( pAttr );
}
break;
} if (pAttr != nil)
{
ldap_memfree( pAttr );
}
}
if (ber != nil)
{
ber_free( ber, 0 );
ber = nil;
}
} fLDAPSessionMgr.UnLockSession(inContext);
}
if (pLDAPAttrType != nil)
{
delete (pLDAPAttrType);
pLDAPAttrType = nil;
}
numAttributes++;
pLDAPAttrType = MapAttrToLDAPType( (const char *)inRecType, pStdAttrType, inContext->fNodeName, numAttributes );
}
if (bAtLeastOneTypeValid)
{
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() );
}
if (pStdAttrType != nil)
{
delete (pStdAttrType);
pStdAttrType = nil;
}
numStdAttributes++;
pStdAttrType = GetNextStdAttrType( inRecType, inContext->fNodeName, numStdAttributes );
}
if (bUsePlus)
{
aTmpData->Clear();
aTmpData->AppendShort( ::strlen( kDS1AttrPasswordPlus ) );
aTmpData->AppendString( kDS1AttrPasswordPlus );
if ( inAttrOnly == false )
{
aTmpData->AppendShort( 1 );
aTmpData->AppendLong( 8 );
aTmpData->AppendString( "********" );
}
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 = fLDAPSessionMgr.LockSession(inContext);
if (aHost != nil)
{
for ( pAttr = ldap_first_attribute (aHost, inResult, &ber );
pAttr != NULL; pAttr = ldap_next_attribute(aHost, inResult, ber ) )
{
aTmpData->Clear();
if ( pAttr != nil )
{
aTmpData->AppendShort( ::strlen( pAttr ) + ::strlen( kDSNativeAttrTypePrefix ) );
aTmpData->AppendString( (char *)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();
if (pAttr != nil)
{
ldap_memfree( pAttr );
}
}
if (ber != nil)
{
ber_free( ber, 0 );
ber = nil;
}
} fLDAPSessionMgr.UnLockSession(inContext);
} }
else {
bStripCryptPrefix = false;
numAttributes = 1;
if (::strcmp( kDS1AttrPasswordPlus, pAttrType ) == 0)
{
bStripCryptPrefix = true;
pLDAPAttrType = MapAttrToLDAPType( (const char *)inRecType, kDS1AttrPassword, inContext->fNodeName, 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( 8 );
aTmpData->AppendString( "********" );
}
}
}
else
{
pLDAPAttrType = MapAttrToLDAPType( (const char *)inRecType, pAttrType, inContext->fNodeName, 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 = fLDAPSessionMgr.LockSession(inContext);
if (aHost != nil)
{
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( 8 );
aTmpData->AppendString( "********" );
}
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( 8 );
aTmpData->AppendString( "********" );
}
if (bValues != NULL)
{
ldap_value_free_len(bValues);
bValues = NULL;
}
}
fLDAPSessionMgr.UnLockSession(inContext);
}
if (pLDAPAttrType != nil)
{
delete (pLDAPAttrType);
pLDAPAttrType = nil;
}
numAttributes++;
pLDAPAttrType = MapAttrToLDAPType( (const char *)inRecType, pAttrType, inContext->fNodeName, 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 ( sInt32 err )
{
siResult = err;
}
if ( pLDAPPasswdAttrType != nil )
{
free(pLDAPPasswdAttrType);
pLDAPPasswdAttrType = nil;
}
if ( aTmpData != nil )
{
delete( aTmpData );
aTmpData = nil;
}
if ( aTmp2Data != nil )
{
delete( aTmp2Data );
aTmp2Data = nil;
}
return( siResult );
}
char *CLDAPv3Plugin::GetRecordName ( char *inRecType,
LDAPMessage *inResult,
sLDAPContextData *inContext,
sInt32 &errResult )
{
char *recName = nil;
char *pLDAPAttrType = nil;
struct berval **bValues;
int numAttributes = 1;
bool bTypeFound = false;
LDAP *aHost = nil;
try
{
if ( inContext == nil ) throw( (sInt32)eDSBadContextData );
errResult = eDSNoErr;
numAttributes = 1;
pLDAPAttrType = MapAttrToLDAPType( (const char *)inRecType, kDSNAttrRecordName, inContext->fNodeName, numAttributes, true );
if (pLDAPAttrType == nil ) throw( (sInt32)eDSInvalidAttrListRef);
bTypeFound = false;
aHost = fLDAPSessionMgr.LockSession(inContext);
while ( (aHost != nil) && ( 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;
}
if (pLDAPAttrType != nil)
{
delete (pLDAPAttrType);
pLDAPAttrType = nil;
}
numAttributes++;
pLDAPAttrType = MapAttrToLDAPType( (const char *)inRecType, kDSNAttrRecordName, inContext->fNodeName, numAttributes, true );
} fLDAPSessionMgr.UnLockSession(inContext);
if (pLDAPAttrType != nil)
{
delete (pLDAPAttrType);
pLDAPAttrType = nil;
}
}
catch ( sInt32 err )
{
errResult = err;
}
return( recName );
}
char* CLDAPv3Plugin::MapAttrToLDAPType ( const char *inRecType, const char *inAttrType, char *inConfigName, int inIndex, bool bSkipLiteralMappings )
{
char *outResult = nil;
uInt32 uiStrLen = 0;
uInt32 uiNativeLen = ::strlen( kDSNativeAttrTypePrefix );
uInt32 uiStdLen = ::strlen( kDSStdAttrTypePrefix );
int aIndex = inIndex;
if (( inAttrType != nil ) && (inIndex > 0))
{
uiStrLen = ::strlen( inAttrType );
if ( ::strncmp( inAttrType, kDSNativeAttrTypePrefix, uiNativeLen ) == 0 )
{
if (( uiStrLen > uiNativeLen ) && (inIndex == 1))
{
uiStrLen = uiStrLen - uiNativeLen;
outResult = (char *) calloc(1, uiStrLen + 1 );
::strcpy( outResult, inAttrType + uiNativeLen );
DBGLOG1( kLogPlugin, "CLDAPv3Plugin: MapAttrToLDAPType:: Warning:Native attribute type <%s> is being used", outResult );
}
} else if ( ::strncmp( inAttrType, kDSStdAttrTypePrefix, uiStdLen ) == 0 )
{
sLDAPConfigData *pConfig = gpConfigFromXML->ConfigWithNodeNameLock( inConfigName );
if (pConfig != nil)
{
if ( pConfig->fRecordAttrMapDict == NULL )
{
}
else
{
if (bSkipLiteralMappings)
{
bool bKeepLooking = false;
do
{
bKeepLooking = false;
outResult = gpConfigFromXML->ExtractAttrMap(inRecType, inAttrType, pConfig->fRecordAttrMapDict, aIndex );
if ( (outResult != nil) && (outResult[0] == '#') )
{
free(outResult);
outResult = nil;
bKeepLooking = true;
}
aIndex++;
}
while ( bKeepLooking );
}
else
{
outResult = gpConfigFromXML->ExtractAttrMap(inRecType, inAttrType, pConfig->fRecordAttrMapDict, inIndex );
}
}
gpConfigFromXML->ConfigUnlock( pConfig );
}
} else
{
if ( inIndex == 1 )
{
outResult = (char *) calloc(1, 1 + ::strlen( inAttrType ) );
::strcpy( outResult, inAttrType );
DBGLOG1( kLogPlugin, "CLDAPv3Plugin: MapAttrToLDAPType:: Warning:Native attribute type with no provided prefix <%s> is being used", outResult );
}
} }
return( outResult );
}
char** CLDAPv3Plugin::MapAttrToLDAPTypeArray ( const char *inRecType, const char *inAttrType, char *inConfigName )
{
char **outResult = nil;
uInt32 uiStrLen = 0;
uInt32 uiNativeLen = ::strlen( kDSNativeAttrTypePrefix );
uInt32 uiStdLen = ::strlen( kDSStdAttrTypePrefix );
int countNative = 0;
if ( inAttrType != nil )
{
uiStrLen = ::strlen( inAttrType );
if ( ::strncmp( inAttrType, kDSNativeAttrTypePrefix, uiNativeLen ) == 0 )
{
if ( uiStrLen > uiNativeLen )
{
uiStrLen = uiStrLen - uiNativeLen;
outResult = (char **)::calloc( 2, sizeof( char * ) );
*outResult = (char *) calloc(1, uiStrLen + 1 );
::strcpy( *outResult, inAttrType + uiNativeLen );
DBGLOG1( kLogPlugin, "CLDAPv3Plugin: MapAttrToLDAPType:: Warning:Native attribute type <%s> is being used", *outResult );
}
} else if ( ::strncmp( inAttrType, kDSStdAttrTypePrefix, uiStdLen ) == 0 )
{
sLDAPConfigData *pConfig = gpConfigFromXML->ConfigWithNodeNameLock( inConfigName );
if (pConfig != nil)
{
char *singleMap = nil;
int aIndex = 1;
int usedIndex = 0;
if ( pConfig->fRecordAttrMapDict == NULL )
{
}
else
{
countNative = gpConfigFromXML->AttrMapsCount(inRecType, inAttrType, pConfig->fRecordAttrMapDict);
if (countNative > 0)
{
outResult = (char **)::calloc( countNative + 1, sizeof(char *) );
do
{
singleMap = gpConfigFromXML->ExtractAttrMap(inRecType, inAttrType, pConfig->fRecordAttrMapDict, aIndex );
if (singleMap != nil)
{
if (singleMap[0] != '#')
{
outResult[usedIndex] = singleMap; usedIndex++;
}
else {
free(singleMap);
}
}
aIndex++;
}
while (singleMap != nil);
}
}
gpConfigFromXML->ConfigUnlock( pConfig );
}
} else
{
outResult = (char **)::calloc( 2, sizeof(char *) );
*outResult = (char *) calloc(1, 1 + ::strlen( inAttrType ) );
::strcpy( *outResult, inAttrType );
DBGLOG1( kLogPlugin, "CLDAPv3Plugin: MapAttrToLDAPTypeArray:: Warning:Native attribute type with no provided prefix <%s> is being used", *outResult );
} }
return( outResult );
}
char** CLDAPv3Plugin::MapAttrListToLDAPTypeArray ( char *inRecType, CAttributeList *inAttrTypeList, char *inConfigName )
{
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 != nil ) || 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 );
DBGLOG1( 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;
}
sLDAPConfigData *pConfig = gpConfigFromXML->ConfigWithNodeNameLock( inConfigName );
if (pConfig != nil)
{
char *singleMap = nil;
int aIndex = 1;
int mapCount = 0;
int usedMapCount= 0;
if ( pConfig->fRecordAttrMapDict == NULL )
{
}
else
{
mapCount = gpConfigFromXML->AttrMapsCount(inRecType, pAttrType, pConfig->fRecordAttrMapDict);
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 = gpConfigFromXML->ExtractAttrMap(inRecType, pAttrType, pConfig->fRecordAttrMapDict, 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;
}
}
}
gpConfigFromXML->ConfigUnlock( pConfig );
}
} 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 );
DBGLOG1( 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 );
}
}
return( outResult );
}
sInt32 CLDAPv3Plugin::MapLDAPWriteErrorToDS ( sInt32 inLDAPError, sInt32 inDefaultError )
{
sInt32 siOutError = 0;
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;
}
DBGLOG1( kLogPlugin, "CLDAPv3Plugin: error code %d returned by LDAP framework", inLDAPError );
return( siOutError );
}
sInt32 CLDAPv3Plugin::GetAttributeEntry ( sGetAttributeEntry *inData )
{
sInt32 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( (sInt32) eMemoryError );
pAttrContext = (sLDAPContextData *)gLDAPContextTable->GetItemData( inData->fInAttrListRef );
if ( pAttrContext == nil ) throw( (sInt32)eDSBadContextData );
uiIndex = inData->fInAttrInfoIndex;
if (uiIndex == 0) throw( (sInt32)eDSInvalidIndex );
pDataBuff = inData->fInOutDataBuff;
if ( pDataBuff == nil ) throw( (sInt32)eDSNullDataBuff );
buffSize = pDataBuff->fBufferSize;
p = pDataBuff->fBufferData + pAttrContext->offset;
offset = pAttrContext->offset;
if (offset + 2 > buffSize) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &usAttrCnt, p, 2 );
if (uiIndex > usAttrCnt) throw( (sInt32)eDSInvalidIndex );
p += 2;
offset += 2;
for ( i = 1; i < uiIndex; i++ )
{
if (offset + 4 > buffSize) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &usAttrLen, p, 4 );
p += 4 + usAttrLen;
offset += 4 + usAttrLen;
}
uiOffset = offset;
if (offset + 4 > buffSize) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &usAttrLen, p, 4 );
p += 4;
offset += 4;
buffLen = offset + usAttrLen;
if (offset + 2 > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &usAttrTypeLen, p, 2 );
pAttrType = p + 2;
p += 2 + usAttrTypeLen;
offset += 2 + usAttrTypeLen;
if (offset + 2 > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &usValueCnt, p, 2 );
p += 2;
offset += 2;
for ( i = 0; i < usValueCnt; i++ )
{
if (offset + 4 > buffLen) throw( (sInt32)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;
if ( pValueContext == nil ) throw( (sInt32) eMemoryAllocError );
pValueContext->offset = uiOffset;
gLDAPContextTable->AddItem( inData->fOutAttrValueListRef, pValueContext );
inData->fOutAttrInfoPtr = pAttribInfo;
}
catch ( sInt32 err )
{
siResult = err;
}
return( siResult );
}
sInt32 CLDAPv3Plugin::GetAttributeValue ( sGetAttributeValue *inData )
{
sInt32 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 = (sLDAPContextData *)gLDAPContextTable->GetItemData( inData->fInAttrValueListRef );
if ( pValueContext == nil ) throw( (sInt32)eDSBadContextData );
uiIndex = inData->fInAttrValueIndex;
if (uiIndex == 0) throw( (sInt32)eDSInvalidIndex );
pDataBuff = inData->fInOutDataBuff;
if ( pDataBuff == nil ) throw( (sInt32)eDSNullDataBuff );
buffSize = pDataBuff->fBufferSize;
p = pDataBuff->fBufferData + pValueContext->offset;
offset = pValueContext->offset;
if (offset + 4 > buffSize) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &attrLen, p, 4 );
buffLen = attrLen + pValueContext->offset + 4;
if (buffLen > buffSize) throw( (sInt32)eDSInvalidBuffFormat );
p += 4;
offset += 4;
if (offset + 2 > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &usAttrNameLen, p, 2 );
p += 2 + usAttrNameLen;
offset += 2 + usAttrNameLen;
if (offset + 2 > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &usValueCnt, p, 2 );
p += 2;
offset += 2;
if (uiIndex > usValueCnt) throw( (sInt32)eDSInvalidIndex );
for ( i = 1; i < uiIndex; i++ )
{
if (offset + 4 > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &usValueLen, p, 4 );
p += 4 + usValueLen;
offset += 4 + usValueLen;
}
if (offset + 4 > buffLen) throw( (sInt32)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( (sInt32)eDSInvalidBuffFormat );
::memcpy( pAttrValue->fAttributeValueData.fBufferData, p, usValueLen );
pAttrValue->fAttributeValueID = CalcCRC( pAttrValue->fAttributeValueData.fBufferData );
inData->fOutAttrValue = pAttrValue;
}
catch ( sInt32 err )
{
siResult = err;
}
return( siResult );
}
sInt32 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 )
{
sInt32 siResult = eDSNoErr;
sInt32 siValCnt = 0;
int ldapReturnCode = 0;
bool bufferFull = false;
LDAPMessage *result = nil;
char *recName = nil;
char *queryFilter = nil;
sLDAPConfigData *pConfig = nil;
int searchTO = 0;
CDataBuff *aRecData = nil;
CDataBuff *aAttrData = nil;
bool bFoundMatch = false;
if (inConstAttrType == nil)
{
queryFilter = BuildLDAPQueryFilter( inConstAttrType,
nil,
eDSAnyMatch,
inContext->fNodeName,
false,
(const char *)inRecType,
inNativeRecType,
inbOCANDGroup,
inOCSearchList );
}
else
{
queryFilter = BuildLDAPQueryMultiFilter
( inConstAttrType,
inAttrNames,
patternMatch,
inContext->fNodeName,
false,
(const char *)inRecType,
inNativeRecType,
inbOCANDGroup,
inOCSearchList );
}
outRecCount = 0;
try
{
if (inContext == nil ) throw( (sInt32)eDSInvalidContext);
if (inContinue == nil ) throw( (sInt32)eDSInvalidContinueData);
if ( queryFilter == nil ) throw( (sInt32)eDSNullParameter );
aRecData = new CDataBuff();
if ( aRecData == nil ) throw( (sInt32) eMemoryError );
aAttrData = new CDataBuff();
if ( aAttrData == nil ) throw( (sInt32) eMemoryError );
pConfig = gpConfigFromXML->ConfigWithNodeNameLock( inContext->fNodeName );
if (pConfig != nil)
{
searchTO = pConfig->fSearchTimeout;
gpConfigFromXML->ConfigUnlock( pConfig );
pConfig = NULL; }
DSDoSearch ( inRecType,
inNativeRecType,
inAttrTypeList,
inContext,
inContinue,
inScope,
fLDAPSessionMgr,
queryFilter,
ldapReturnCode,
searchTO,
result);
while ( ( (ldapReturnCode == LDAP_RES_SEARCH_ENTRY) || (ldapReturnCode == LDAP_RES_SEARCH_RESULT) )
&& !(bufferFull)
&& ( (inContinue->fTotalRecCount < inContinue->fLimitRecSearch) ||
(inContinue->fLimitRecSearch == 0) ) )
{
if (ldapReturnCode == LDAP_RES_SEARCH_ENTRY)
{
bFoundMatch = false;
if ( DoAnyOfTheseAttributesMatch(inContext, inAttrNames, patternMatch, result) )
{
bFoundMatch = true;
aRecData->Clear();
if ( inRecType != nil )
{
aRecData->AppendShort( ::strlen( inRecType ) );
aRecData->AppendString( inRecType );
}
else
{
aRecData->AppendShort( ::strlen( "Record Type Unknown" ) );
aRecData->AppendString( "Record Type Unknown" );
}
recName = GetRecordName( inRecType, result, inContext, siResult );
if ( siResult != eDSNoErr ) throw( siResult );
if ( recName != nil )
{
aRecData->AppendShort( ::strlen( recName ) );
aRecData->AppendString( recName );
delete ( recName );
recName = nil;
}
else
{
aRecData->AppendShort( ::strlen( "Record Name Unknown" ) );
aRecData->AppendString( "Record Name Unknown" );
}
aAttrData->Clear();
siResult = GetTheseAttributes( inRecType, inAttrTypeList, result, inAttrOnly, inContext, siValCnt, aAttrData );
if ( siResult != eDSNoErr ) throw( siResult );
if ( siValCnt == 0 )
{
aRecData->AppendShort( 0 );
}
else
{
aRecData->AppendShort( siValCnt );
aRecData->AppendBlock( aAttrData->GetData(), aAttrData->GetLength() );
}
siResult = inBuff->AddData( aRecData->GetData(), aRecData->GetLength() );
} }
if (siResult == CBuff::kBuffFull)
{
bufferFull = true;
inContinue->pResult = result;
}
else if ( siResult == eDSNoErr )
{
ldap_msgfree( result );
result = nil;
if (bFoundMatch)
{
outRecCount++; inContinue->fTotalRecCount++;
}
inContinue->pResult = nil;
DSGetSearchLDAPResult ( fLDAPSessionMgr,
inContext,
searchTO,
result,
LDAP_MSG_ONE,
inContinue->msgId,
ldapReturnCode,
false);
}
else
{
inContinue->pResult = nil;
throw( (sInt32)eDSInvalidBuffFormat );
}
}
if ( (result != inContinue->pResult) && (result != nil) )
{
ldap_msgfree( result );
result = nil;
}
if ( (siResult == eDSNoErr) && (inContinue != NULL) && (inContinue->msgId != 0) )
{
LDAP *aHost = nil;
aHost = fLDAPSessionMgr.LockSession(inContext);
if (aHost != nil)
{
DSSearchCleanUp(aHost, inContinue->msgId);
}
fLDAPSessionMgr.UnLockSession(inContext);
}
}
catch ( sInt32 err )
{
siResult = err;
}
if ( queryFilter != nil )
{
delete( queryFilter );
queryFilter = nil;
}
if (aRecData != nil)
{
delete (aRecData);
aRecData = nil;
}
if (aAttrData != nil)
{
delete (aAttrData);
aAttrData = nil;
}
return( siResult );
}
char *CLDAPv3Plugin::BuildLDAPQueryFilter ( char *inConstAttrType,
const char *inConstAttrName,
tDirPatternMatch patternMatch,
char *inConfigName,
bool useWellKnownRecType,
const char *inRecType,
char *inNativeRecType,
bool inbOCANDGroup,
CFArrayRef inOCSearchList )
{
char *queryFilter = nil;
unsigned long matchType = eDSExact;
char *nativeAttrType = nil;
uInt32 recNameLen = 0;
int numAttributes = 1;
CFMutableStringRef cfStringRef = nil;
CFMutableStringRef cfQueryStringRef = nil;
char *escapedName = 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;
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) && (inConstAttrName == nil) )
{
CFStringAppendCString(cfQueryStringRef,"(&(objectclass=*)", kCFStringEncodingUTF8);
objClassAdded = true;
}
if ( (patternMatch == eDSCompoundExpression) ||
(patternMatch == eDSiCompoundExpression) )
{ cfStringRef = ParseCompoundExpression(inConstAttrName, inRecType, inConfigName );
if (cfStringRef != nil)
{
CFStringAppend(cfQueryStringRef, cfStringRef);
CFRelease(cfStringRef);
cfStringRef = nil;
}
}
else
{
if (inConstAttrName != nil)
{
recNameLen = strlen(inConstAttrName);
escapedName = (char *)::calloc(1, 3 * recNameLen + 1);
while (originalIndex < recNameLen)
{
switch (inConstAttrName[originalIndex])
{
case '*':
escapedName[escapedIndex] = '\\';
++escapedIndex;
escapedName[escapedIndex] = '2';
++escapedIndex;
escapedName[escapedIndex] = 'a';
++escapedIndex;
break;
case '(':
escapedName[escapedIndex] = '\\';
++escapedIndex;
escapedName[escapedIndex] = '2';
++escapedIndex;
escapedName[escapedIndex] = '8';
++escapedIndex;
break;
case ')':
escapedName[escapedIndex] = '\\';
++escapedIndex;
escapedName[escapedIndex] = '2';
++escapedIndex;
escapedName[escapedIndex] = '9';
++escapedIndex;
break;
case '\\':
escapedName[escapedIndex] = '\\';
++escapedIndex;
escapedName[escapedIndex] = '5';
++escapedIndex;
escapedName[escapedIndex] = 'c';
++escapedIndex;
break;
default:
escapedName[escapedIndex] = inConstAttrName[originalIndex];
++escapedIndex;
break;
}
++originalIndex;
}
cfStringRef = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, CFSTR("(|"));
numAttributes = 1;
nativeAttrType = MapAttrToLDAPType( inRecType, inConstAttrType, inConfigName, numAttributes, false );
if (nativeAttrType == nil) {
nativeAttrType = strdup("cn");
}
while ( nativeAttrType != nil )
{
if (nativeAttrType[0] == '#') {
if (strlen(nativeAttrType) > 1)
{
if (DoesThisMatch(escapedName, nativeAttrType+1, 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;
}
matchType = (unsigned long) (patternMatch);
switch (matchType)
{
case eDSStartsWith:
case eDSiStartsWith:
CFStringAppendCString(cfStringRef,"(", kCFStringEncodingUTF8);
CFStringAppendCString(cfStringRef, nativeAttrType, kCFStringEncodingUTF8);
CFStringAppendCString(cfStringRef,"=", kCFStringEncodingUTF8);
CFStringAppendCString(cfStringRef, escapedName, kCFStringEncodingUTF8);
CFStringAppendCString(cfStringRef,"*)", kCFStringEncodingUTF8);
bOnceThru = true;
break;
case eDSEndsWith:
case eDSiEndsWith:
CFStringAppendCString(cfStringRef,"(", kCFStringEncodingUTF8);
CFStringAppendCString(cfStringRef, nativeAttrType, kCFStringEncodingUTF8);
CFStringAppendCString(cfStringRef,"=*", kCFStringEncodingUTF8);
CFStringAppendCString(cfStringRef, escapedName, kCFStringEncodingUTF8);
CFStringAppendCString(cfStringRef,")", kCFStringEncodingUTF8);
bOnceThru = true;
break;
case eDSContains:
case eDSiContains:
CFStringAppendCString(cfStringRef,"(", kCFStringEncodingUTF8);
CFStringAppendCString(cfStringRef, nativeAttrType, kCFStringEncodingUTF8);
CFStringAppendCString(cfStringRef,"=*", kCFStringEncodingUTF8);
CFStringAppendCString(cfStringRef, escapedName, kCFStringEncodingUTF8);
CFStringAppendCString(cfStringRef,"*)", kCFStringEncodingUTF8);
bOnceThru = true;
break;
case eDSWildCardPattern:
case eDSiWildCardPattern:
CFStringAppendCString(cfStringRef,"(", kCFStringEncodingUTF8);
CFStringAppendCString(cfStringRef, nativeAttrType, kCFStringEncodingUTF8);
CFStringAppendCString(cfStringRef,"=", kCFStringEncodingUTF8);
CFStringAppendCString(cfStringRef, inConstAttrName, kCFStringEncodingUTF8);
CFStringAppendCString(cfStringRef,")", kCFStringEncodingUTF8);
bOnceThru = true;
break;
case eDSRegularExpression:
case eDSiRegularExpression:
CFStringAppendCString(cfStringRef, inConstAttrName, kCFStringEncodingUTF8);
bOnceThru = true;
break;
case eDSExact:
case eDSiExact:
default:
CFStringAppendCString(cfStringRef,"(", kCFStringEncodingUTF8);
CFStringAppendCString(cfStringRef, nativeAttrType, kCFStringEncodingUTF8);
CFStringAppendCString(cfStringRef,"=", kCFStringEncodingUTF8);
CFStringAppendCString(cfStringRef, escapedName, kCFStringEncodingUTF8);
CFStringAppendCString(cfStringRef,")", kCFStringEncodingUTF8);
bOnceThru = true;
break;
} }
if (nativeAttrType != nil)
{
free(nativeAttrType);
nativeAttrType = nil;
}
numAttributes++;
nativeAttrType = MapAttrToLDAPType( inRecType, inConstAttrType, inConfigName, 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);
}
}
if (cfStringRef != nil)
{
CFRelease(cfStringRef);
cfStringRef = nil;
}
if (escapedName != nil)
{
free(escapedName);
escapedName = nil;
}
} }
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 );
}
if (cfQueryStringRef != nil)
{
CFRelease(cfQueryStringRef);
cfQueryStringRef = nil;
}
return (queryFilter);
}
char *CLDAPv3Plugin::BuildLDAPQueryMultiFilter
( char *inConstAttrType,
char **inAttrNames,
tDirPatternMatch patternMatch,
char *inConfigName,
bool useWellKnownRecType,
const char *inRecType,
char *inNativeRecType,
bool inbOCANDGroup,
CFArrayRef inOCSearchList )
{
char *queryFilter = nil;
unsigned long 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;
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 = ParseCompoundExpression( inAttrNames[0], inRecType, inConfigName );
if (cfStringRef != nil)
{
CFStringAppend(cfQueryStringRef, cfStringRef);
CFRelease(cfStringRef);
cfStringRef = nil;
}
}
else
{
if (inAttrNames != nil)
{
uInt32 strCount = 0; while(inAttrNames[strCount] != nil)
{
strCount++;
}
escapedStrings = (char **) calloc( strCount + 1, sizeof (char *));
strCount = 0;
while(inAttrNames[strCount] != nil)
{
recNameLen = strlen(inAttrNames[strCount]);
escapedStrings[strCount] = (char *)::calloc(1, 3 * recNameLen + 1);
escapedIndex = 0;
originalIndex = 0;
while (originalIndex < recNameLen)
{
switch (inAttrNames[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] = inAttrNames[strCount][originalIndex];
++escapedIndex;
break;
} ++originalIndex;
} strCount++;
}
cfStringRef = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, CFSTR("(|"));
numAttributes = 1;
nativeAttrType = MapAttrToLDAPType( inRecType, inConstAttrType, inConfigName, numAttributes, false );
if (nativeAttrType == nil) {
nativeAttrType = strdup("cn");
}
matchType = (unsigned long) (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, inAttrNames[strCount], kCFStringEncodingUTF8);
CFStringAppendCString(cfStringRef,")", kCFStringEncodingUTF8);
bOnceThru = true;
break;
case eDSRegularExpression:
case eDSiRegularExpression:
CFStringAppendCString(cfStringRef, inAttrNames[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( inRecType, inConstAttrType, inConfigName, 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);
}
}
if (cfStringRef != nil)
{
CFRelease(cfStringRef);
cfStringRef = nil;
}
if (escapedStrings != nil)
{
strCount = 0;
while(escapedStrings[strCount] != nil)
{
free(escapedStrings[strCount]);
escapedStrings[strCount] = nil;
strCount++;
}
free(escapedStrings);
escapedStrings = nil;
}
} }
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 );
}
if (cfQueryStringRef != nil)
{
CFRelease(cfQueryStringRef);
cfQueryStringRef = nil;
}
return (queryFilter);
}
CFMutableStringRef CLDAPv3Plugin::ParseCompoundExpression ( const char *inConstAttrName, const char *inRecType, char *inConfigName )
{
CFMutableStringRef outExpression = NULL;
char *ourExpressionPtr= nil;
char *ourExp = nil;
char *attrExpression = nil;
uInt32 numChars = 0;
bool bNotDone = true;
char *attrType = nil;
char *pattMatch = nil;
bool bMultiMap = false;
if ( ( inConstAttrName != nil ) && ( inRecType != nil ) )
{
ourExpressionPtr = (char *) calloc(1, strlen(inConstAttrName) + 1);
if (ourExpressionPtr != nil)
{
ourExp = ourExpressionPtr;
strcpy(ourExpressionPtr, inConstAttrName);
outExpression = CFStringCreateMutable(kCFAllocatorDefault, 0);
numChars = strspn(ourExpressionPtr,LDAPCOMEXPSPECIALCHARS); if (numChars > 0)
{
attrExpression = (char *) calloc(1, numChars + 1);
if (attrExpression != nil)
{
strncpy(attrExpression, ourExpressionPtr, numChars);
CFStringAppendCString(outExpression, attrExpression, kCFStringEncodingUTF8);
ourExpressionPtr = ourExpressionPtr + numChars;
free(attrExpression);
attrExpression = nil;
}
}
while (bNotDone)
{
bMultiMap = false;
numChars = 0;
numChars = strcspn(ourExpressionPtr,LDAPCOMEXPSPECIALCHARS); if (numChars > 0) {
attrExpression = (char *) calloc(1, numChars + 1);
if (attrExpression != nil)
{
strncpy(attrExpression, ourExpressionPtr, numChars);
ourExpressionPtr = ourExpressionPtr + numChars;
attrType = strsep(&attrExpression,"=");
pattMatch= strsep(&attrExpression,"=");
if ((attrType != nil) && (pattMatch != nil) ) {
char *pLDAPAttrType = nil;
int numAttributes = 1;
pLDAPAttrType = MapAttrToLDAPType( inRecType, attrType, inConfigName, numAttributes, true );
if ( pLDAPAttrType != nil)
{
if ( (strcasecmp(attrType, pLDAPAttrType) == 0) || (strncmp(attrType, kDSNativeAttrTypePrefix, strlen(kDSNativeAttrTypePrefix)) == 0) ) {
CFStringAppendCString(outExpression, pLDAPAttrType, kCFStringEncodingUTF8);
CFStringAppendCString(outExpression, "=", kCFStringEncodingUTF8);
CFStringAppendCString(outExpression, pattMatch, kCFStringEncodingUTF8);
DSFreeString(pLDAPAttrType);
}
else
{
CFStringAppendCString(outExpression, "|", kCFStringEncodingUTF8); bMultiMap = true; }
}
while(pLDAPAttrType != nil)
{
CFStringAppendCString(outExpression, "(", kCFStringEncodingUTF8); CFStringAppendCString(outExpression, pLDAPAttrType, kCFStringEncodingUTF8);
CFStringAppendCString(outExpression, "=", kCFStringEncodingUTF8);
CFStringAppendCString(outExpression, pattMatch, kCFStringEncodingUTF8); numAttributes++;
DSFreeString(pLDAPAttrType);
pLDAPAttrType = MapAttrToLDAPType( inRecType, attrType, inConfigName, numAttributes, true );
if (pLDAPAttrType != nil)
{
CFStringAppendCString(outExpression, ")", kCFStringEncodingUTF8);
}
}
if (bMultiMap)
{
CFStringAppendCString(outExpression, ")", kCFStringEncodingUTF8);
}
} free(attrExpression);
attrExpression = nil;
} } else
{
bNotDone = false;
}
numChars = 0;
numChars = strspn(ourExpressionPtr,LDAPCOMEXPSPECIALCHARS); if (numChars > 0)
{
attrExpression = (char *) calloc(1, numChars + 1);
if (attrExpression != nil)
{
strncpy(attrExpression, ourExpressionPtr, numChars);
CFStringAppendCString(outExpression, attrExpression, kCFStringEncodingUTF8);
ourExpressionPtr = ourExpressionPtr + numChars;
free(attrExpression);
attrExpression = nil;
}
}
}
free(ourExp);
ourExp = nil;
} }
if (outExpression != NULL)
{
if (CFStringGetLength(outExpression) < 3) {
CFRelease(outExpression);
outExpression = NULL;
}
}
return( outExpression );
}
sInt32 CLDAPv3Plugin::GetDirNodeInfo ( sGetDirNodeInfo *inData )
{
sInt32 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;
sLDAPConfigData *pConfig = nil;
try
{
if ( inData == nil ) throw( (sInt32) eMemoryError );
pContext = (sLDAPContextData *)gLDAPContextTable->GetItemData( inData->fInNodeRef );
if ( pContext == nil ) throw( (sInt32)eDSBadContextData );
inAttrList = new CAttributeList( inData->fInDirNodeInfoTypeList );
if ( inAttrList == nil ) throw( (sInt32)eDSNullNodeInfoTypeList );
if (inAttrList->GetCount() == 0) throw( (sInt32)eDSEmptyNodeInfoTypeList );
siResult = outBuff.Initialize( inData->fOutDataBuff, true );
if ( siResult != eDSNoErr ) throw( siResult );
siResult = outBuff.SetBuffType( 'Gdni' ); if ( siResult != eDSNoErr ) throw( siResult );
aRecData = new CDataBuff();
if ( aRecData == nil ) throw( (sInt32) eMemoryError );
aAttrData = new CDataBuff();
if ( aAttrData == nil ) throw( (sInt32) eMemoryError );
aTmpData = new CDataBuff();
if ( aTmpData == nil ) throw( (sInt32) eMemoryError );
aRecData->AppendShort( ::strlen( "dsAttrTypeStandard:DirectoryNodeInfo" ) );
aRecData->AppendString( (char *)"dsAttrTypeStandard:DirectoryNodeInfo" );
aRecData->AppendShort( ::strlen( "DirectoryNodeInfo" ) );
aRecData->AppendString( (char *)"DirectoryNodeInfo" );
while ( inAttrList->GetAttribute( uiCntr++, &pAttrName ) == eDSNoErr )
{
if ((::strcmp( pAttrName, kDSAttributesAll ) == 0) ||
(::strcmp( pAttrName, kDSNAttrNodePath ) == 0) )
{
aTmpData->Clear();
uiAttrCnt++;
aTmpData->AppendShort( ::strlen( kDSNAttrNodePath ) );
aTmpData->AppendString( kDSNAttrNodePath );
if ( inData->fInAttrInfoOnly == false )
{
aTmpData->AppendShort( 2 );
aTmpData->AppendLong( ::strlen( "LDAPv3" ) );
aTmpData->AppendString( (char *)"LDAPv3" );
char *tmpStr = nil;
if (pContext->fNodeName != nil)
{
tmpStr = pContext->fNodeName;
}
else
{
tmpStr = "Unknown Node Location";
}
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( ::strlen( kDS1AttrReadOnlyNode ) );
aTmpData->AppendString( kDS1AttrReadOnlyNode );
if ( inData->fInAttrInfoOnly == false )
{
aTmpData->AppendShort( 1 );
if (pContext->bLDAPv2ReadOnly)
{
aTmpData->AppendLong( ::strlen( "ReadOnly" ) );
aTmpData->AppendString( "ReadOnly" );
}
else
{
aTmpData->AppendLong( ::strlen( "ReadWrite" ) );
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( ::strlen( kDSNAttrAuthMethod ) );
aTmpData->AppendString( kDSNAttrAuthMethod );
if ( inData->fInAttrInfoOnly == false )
{
char *tmpStr = nil;
aTmpData->AppendShort( 4 );
tmpStr = (char *) calloc(1, 1+::strlen( kDSStdAuthCrypt ));
::strcpy( tmpStr, kDSStdAuthCrypt );
aTmpData->AppendLong( ::strlen( tmpStr ) );
aTmpData->AppendString( tmpStr );
delete( tmpStr );
tmpStr = nil;
tmpStr = (char *) calloc(1, 1+::strlen( kDSStdAuthClearText ));
::strcpy( tmpStr, kDSStdAuthClearText );
aTmpData->AppendLong( ::strlen( tmpStr ) );
aTmpData->AppendString( tmpStr );
delete( tmpStr );
tmpStr = nil;
tmpStr = (char *) calloc(1, 1+::strlen( kDSStdAuthNodeNativeClearTextOK ));
::strcpy( tmpStr, kDSStdAuthNodeNativeClearTextOK );
aTmpData->AppendLong( ::strlen( tmpStr ) );
aTmpData->AppendString( tmpStr );
delete( tmpStr );
tmpStr = nil;
tmpStr = (char *) calloc(1, 1+::strlen( kDSStdAuthNodeNativeNoClearText ));
::strcpy( tmpStr, kDSStdAuthNodeNativeNoClearText );
aTmpData->AppendLong( ::strlen( tmpStr ) );
aTmpData->AppendString( tmpStr );
delete( tmpStr );
tmpStr = nil;
} 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( ::strlen( "dsAttrTypeStandard:AccountName" ) );
aTmpData->AppendString( (char *)"dsAttrTypeStandard:AccountName" );
if ( inData->fInAttrInfoOnly == false )
{
const char *tmpStr = (pContext->fAuthUserName ? pContext->fAuthUserName : "No Account Name");
aTmpData->AppendShort( 1 );
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, kDSNAttrDefaultLDAPPaths ) == 0 )
{
aTmpData->Clear();
uiAttrCnt++;
aTmpData->AppendShort( ::strlen( kDSNAttrDefaultLDAPPaths ) );
aTmpData->AppendString( (char *)kDSNAttrDefaultLDAPPaths );
if ( inData->fInAttrInfoOnly == false )
{
char **defaultLDAPNodes = nil;
uInt32 aDefaultLDAPNodeCount = 0;
defaultLDAPNodes = gpConfigFromXML->GetDefaultLDAPNodeStrings(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( ::strlen( kDS1AttrDistinguishedName ) );
aTmpData->AppendString( (char *)kDS1AttrDistinguishedName );
if ( inData->fInAttrInfoOnly == false )
{
pConfig = gpConfigFromXML->ConfigWithNodeNameLock( pContext->fNodeName );
char *tmpStr = nil;
if (pConfig != nil && pConfig->fUIName )
{
tmpStr = pConfig->fUIName;
}
else
{
tmpStr = "No Display Name";
}
aTmpData->AppendShort( 1 );
aTmpData->AppendLong( ::strlen( tmpStr ) );
aTmpData->AppendString( tmpStr );
if( pConfig )
{
gpConfigFromXML->ConfigUnlock( pConfig );
}
} else
{
aTmpData->AppendShort( 0 );
}
aAttrData->AppendLong( aTmpData->GetLength() );
aAttrData->AppendBlock( aTmpData->GetData(), aTmpData->GetLength() );
aTmpData->Clear();
}
if ( (::strcmp( pAttrName, kDSAttributesAll ) == 0) ||
(::strcmp( pAttrName, kDSNAttrRecordType ) == 0) )
{
aTmpData->Clear();
uiAttrCnt++;
aTmpData->AppendShort( ::strlen( kDSNAttrRecordType ) );
aTmpData->AppendString( kDSNAttrRecordType );
if ( inData->fInAttrInfoOnly == false )
{
int valueCount = 0;
int i = 0;
pConfig = gpConfigFromXML->ConfigWithNodeNameLock( pContext->fNodeName );
if (pConfig != nil && pConfig->fRecordAttrMapDict != nil )
{
valueCount = CFDictionaryGetCount( pConfig->fRecordAttrMapDict );
}
aTmpData->AppendShort( valueCount );
if( valueCount != 0 )
{
CFStringRef *keys = (CFStringRef *)calloc( valueCount, sizeof(CFStringRef) );
CFDictionaryGetKeysAndValues( pConfig->fRecordAttrMapDict, (const void **)keys, NULL );
for ( i = 0; i < valueCount; i++ )
{
char tempBuffer[1024];
CFStringGetCString( keys[i], tempBuffer, 1024, kCFStringEncodingUTF8 );
aTmpData->AppendLong( ::strlen( tempBuffer ) );
aTmpData->AppendString( tempBuffer );
}
DSFree( keys );
}
if( pConfig )
{
gpConfigFromXML->ConfigUnlock( pConfig );
}
}
else
{
aTmpData->AppendShort( 0 );
}
aAttrData->AppendLong( aTmpData->GetLength() );
aAttrData->AppendBlock( aTmpData->GetData(), aTmpData->GetLength() );
aTmpData->Clear();
}
if ( (::strcmp( pAttrName, kDSAttributesAll ) == 0) ||
(::strcmp( pAttrName, "dsAttrTypeStandard:TrustInformation" ) == 0) )
{
aTmpData->Clear();
uiAttrCnt++;
aTmpData->AppendShort( ::strlen( "dsAttrTypeStandard:TrustInformation" ) );
aTmpData->AppendString( "dsAttrTypeStandard:TrustInformation" );
if ( inData->fInAttrInfoOnly == false )
{
pConfig = gpConfigFromXML->ConfigWithNodeNameLock( pContext->fNodeName );
if (pConfig != nil)
{
bool bAuthenticated = (pConfig->bSecureUse && pConfig->fServerAccount != NULL && pConfig->fServerPassword != NULL);
bool bAnonymous = (bAuthenticated ? false : true); bool bFullTrust = false;
bool bPartialTrust = false;
bool bDHCP = pConfig->bUseAsDefaultLDAP;
bool bEncryption = (pConfig->bIsSSL || (pConfig->fSecurityLevel & kSecPacketEncryption));
if( bAuthenticated )
{
bFullTrust = ((pConfig->fSecurityLevel & (kSecManInMiddle | kSecPacketSigning)) == (kSecManInMiddle | kSecPacketSigning));
if( bFullTrust == false )
{
bPartialTrust = ((pConfig->fSecurityLevel & kSecManInMiddle) == kSecManInMiddle);
}
}
gpConfigFromXML->ConfigUnlock( pConfig );
aTmpData->AppendShort( bAuthenticated + bAnonymous + bFullTrust + bPartialTrust + bDHCP + bEncryption );
if( bAuthenticated )
{
aTmpData->AppendLong( ::strlen( "Authenticated" ) );
aTmpData->AppendString( "Authenticated" );
}
else if( bAnonymous )
{
aTmpData->AppendLong( ::strlen( "Anonymous" ) );
aTmpData->AppendString( "Anonymous" );
}
if( bFullTrust )
{
aTmpData->AppendLong( ::strlen( "FullTrust" ) );
aTmpData->AppendString( "FullTrust" );
}
else if( bPartialTrust )
{
aTmpData->AppendLong( ::strlen( "PartialTrust" ) );
aTmpData->AppendString( "PartialTrust" );
}
if( bEncryption )
{
aTmpData->AppendLong( ::strlen( "Encryption" ) );
aTmpData->AppendString( "Encryption" );
}
if( bDHCP )
{
aTmpData->AppendLong( ::strlen( "DHCP" ) );
aTmpData->AppendString( "DHCP" );
}
}
else
{
aTmpData->AppendShort( 0 );
}
}
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;
if ( pAttrContext == nil ) throw( (sInt32) eMemoryAllocError );
pAttrContext->fNodeName = strdup( pContext->fNodeName );
pAttrContext->offset = uiOffset + 61;
gLDAPContextTable->AddItem( inData->fOutAttrListRef, pAttrContext );
}
else
{
siResult = eDSBufferTooSmall;
}
}
catch ( sInt32 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;
}
return( siResult );
}
sInt32 CLDAPv3Plugin::OpenRecord ( sOpenRecord *inData )
{
sInt32 siResult = eDSNoErr;
tDataNodePtr pRecName = nil;
tDataNodePtr pRecType = nil;
char *pLDAPRecType = nil;
sLDAPContextData *pContext = nil;
sLDAPContextData *pRecContext = nil;
char *queryFilter = nil;
LDAPMessage *result = nil;
int ldapReturnCode = 0;
int numRecTypes = 1;
bool bResultFound = false;
sLDAPConfigData *pConfig = nil;
int searchTO = 0;
bool bOCANDGroup = false;
CFArrayRef OCSearchList = nil;
ber_int_t scope = LDAP_SCOPE_SUBTREE;
sInt32 searchResult = eDSNoErr;
char **attrs = nil;
int ldapMsgId = 0;
try
{
pContext = (sLDAPContextData *)gLDAPContextTable->GetItemData( inData->fInNodeRef );
if ( pContext == nil ) throw( (sInt32)eDSBadContextData );
pRecType = inData->fInRecType;
if ( pRecType == nil ) throw( (sInt32)eDSNullRecType );
pRecName = inData->fInRecName;
if ( pRecName == nil ) throw( (sInt32)eDSNullRecName );
if (pRecName->fBufferLength == 0) throw( (sInt32)eDSEmptyRecordNameList );
if (pRecType->fBufferLength == 0) throw( (sInt32)eDSEmptyRecordTypeList );
pConfig = gpConfigFromXML->ConfigWithNodeNameLock( pContext->fNodeName );
if (pConfig != nil)
{
searchTO = pConfig->fSearchTimeout;
gpConfigFromXML->ConfigUnlock( pConfig );
pConfig = NULL;
}
attrs = MapAttrToLDAPTypeArray( pRecType->fBufferData, kDSNAttrRecordName, pContext->fNodeName );
numRecTypes = 1;
bOCANDGroup = false;
if (OCSearchList != nil)
{
CFRelease(OCSearchList);
OCSearchList = nil;
}
pLDAPRecType = MapRecToLDAPType( (const char *)(pRecType->fBufferData), pContext->fNodeName, numRecTypes, &bOCANDGroup, &OCSearchList, &scope );
if ( pLDAPRecType == nil ) throw( (sInt32)eDSInvalidRecordType );
while ( (pLDAPRecType != nil) && (!bResultFound) )
{
queryFilter = BuildLDAPQueryFilter( (char *)kDSNAttrRecordName,
pRecName->fBufferData,
eDSExact,
pContext->fNodeName,
false,
(const char *)(pRecType->fBufferData),
pLDAPRecType,
bOCANDGroup,
OCSearchList );
if ( queryFilter == nil ) throw( (sInt32)eDSNullParameter );
searchResult = DSDoRetrieval ( pLDAPRecType,
attrs,
pContext,
scope,
fLDAPSessionMgr,
queryFilter,
ldapReturnCode,
searchTO,
result,
bResultFound,
ldapMsgId );
if ( queryFilter != nil )
{
delete( queryFilter );
queryFilter = nil;
}
if (pLDAPRecType != nil)
{
delete (pLDAPRecType);
pLDAPRecType = nil;
}
numRecTypes++;
bOCANDGroup = false;
if (OCSearchList != nil)
{
CFRelease(OCSearchList);
OCSearchList = nil;
}
pLDAPRecType = MapRecToLDAPType( (const char *)(pRecType->fBufferData), pContext->fNodeName, numRecTypes, &bOCANDGroup, &OCSearchList, &scope );
}
if ( (bResultFound) &&
( ldapReturnCode == LDAP_RES_SEARCH_ENTRY ) )
{
fLDAPSessionMgr.SessionMapMutexLock();
pRecContext = new sLDAPContextData( *pContext );
fLDAPSessionMgr.SessionMapMutexUnlock();
if ( pRecContext == nil ) throw( (sInt32) eMemoryAllocError );
pRecContext->fType = 2;
if (pRecType->fBufferData != nil)
{
pRecContext->fOpenRecordType = strdup( pRecType->fBufferData );
}
if (pRecName->fBufferData != nil)
{
pRecContext->fOpenRecordName = strdup( pRecName->fBufferData );
}
LDAP *aHost = fLDAPSessionMgr.LockSession(pRecContext);
if (aHost != nil)
{
pRecContext->fOpenRecordDN = ldap_get_dn(aHost, result);
DSSearchCleanUp(aHost, ldapMsgId);
}
fLDAPSessionMgr.UnLockSession(pRecContext);
gLDAPContextTable->AddItem( inData->fOutRecRef, pRecContext );
} else
{
siResult = searchResult;
}
}
catch ( sInt32 err )
{
siResult = err;
}
if (OCSearchList != nil)
{
CFRelease(OCSearchList);
OCSearchList = nil;
}
if ( result != nil )
{
ldap_msgfree( result );
result = nil;
}
if ( pLDAPRecType != nil )
{
delete( pLDAPRecType );
pLDAPRecType = nil;
}
if ( queryFilter != nil )
{
delete( queryFilter );
queryFilter = nil;
}
if (attrs != nil)
{
int aIndex = 0;
while (attrs[aIndex] != nil)
{
free(attrs[aIndex]);
attrs[aIndex] = nil;
aIndex++;
}
free(attrs);
attrs = nil;
}
return( siResult );
}
sInt32 CLDAPv3Plugin::CloseRecord ( sCloseRecord *inData )
{
sInt32 siResult = eDSNoErr;
sLDAPContextData *pContext = nil;
try
{
pContext = (sLDAPContextData *)gLDAPContextTable->GetItemData( inData->fInRecRef );
if ( pContext == nil ) throw( (sInt32)eDSBadContextData );
gLDAPContextTable->RemoveItem( inData->fInRecRef );
}
catch ( sInt32 err )
{
siResult = err;
}
return( siResult );
}
sInt32 CLDAPv3Plugin::FlushRecord ( sFlushRecord *inData )
{
sInt32 siResult = eDSNoErr;
sLDAPContextData *pContext = nil;
try
{
pContext = (sLDAPContextData *)gLDAPContextTable->GetItemData( inData->fInRecRef );
if ( pContext == nil ) throw( (sInt32)eDSBadContextData );
if ( pContext->bLDAPv2ReadOnly ) throw( (sInt32)eDSReadOnly);
}
catch ( sInt32 err )
{
siResult = err;
}
return( siResult );
}
sInt32 CLDAPv3Plugin::DeleteRecord ( sDeleteRecord *inData, bool inDeleteCredentials )
{
sInt32 siResult = eDSNoErr;
sLDAPContextData *pRecContext = nil;
char *pUserID = NULL;
char *pAdminID = NULL;
char *pServerAddress = NULL;
try
{
pRecContext = (sLDAPContextData *)gLDAPContextTable->GetItemData( inData->fInRecRef );
if ( pRecContext == nil ) throw( (sInt32)eDSBadContextData );
if ( pRecContext->bLDAPv2ReadOnly ) throw( (sInt32)eDSReadOnly);
if ( pRecContext->fOpenRecordDN == nil ) throw( (sInt32)eDSNullRecName );
if ( inDeleteCredentials && pRecContext->fOpenRecordName != NULL && pRecContext->fOpenRecordType != NULL && pRecContext->fLDAPNodeStruct->fLDAPUserName )
{
char **dn = ldap_explode_dn( pRecContext->fLDAPNodeStruct->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;
}
LDAP *aHost = fLDAPSessionMgr.LockSession(pRecContext);
if ( (aHost != nil) && ( ldap_delete_s( aHost, pRecContext->fOpenRecordDN) != LDAP_SUCCESS ) )
{
siResult = eDSPermissionError;
}
fLDAPSessionMgr.UnLockSession(pRecContext);
if ( siResult == eDSNoErr && pUserID != NULL && pAdminID != NULL && pServerAddress != NULL )
{
tDirReference dsRef = 0;
tDirNodeReference nodeRef = 0;
int 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 = PWOpenDirNode( dsRef, nodeName, &nodeRef );
free( nodeName );
nodeName = NULL;
}
else
{
error = eMemoryAllocError;
}
}
if( error == eDSNoErr )
{
int iUserIDLen = strlen( pUserID ) + 1; int iAdminIDLen = strlen( pAdminID ) + 1; tDataBufferPtr pAuthMethod = dsDataNodeAllocateString( nodeRef, kDSStdAuthDeleteUser );
tDataBufferPtr pStepData = dsDataBufferAllocatePriv( sizeof(long) + iAdminIDLen +
sizeof(long) + pRecContext->fLDAPNodeStruct->fLDAPCredentialsLen +
sizeof(long) + iUserIDLen );
tDataBufferPtr pStepDataResp = dsDataBufferAllocatePriv( 1024 );
char *pWorkingBuff = pStepData->fBufferData;
*((long *)pWorkingBuff) = iAdminIDLen;
pWorkingBuff += sizeof(long);
bcopy( pAdminID, pWorkingBuff, iAdminIDLen );
pWorkingBuff += iAdminIDLen;
*((long *)pWorkingBuff) = pRecContext->fLDAPNodeStruct->fLDAPCredentialsLen;
pWorkingBuff += sizeof(long);
bcopy( pRecContext->fLDAPNodeStruct->fLDAPCredentials, pWorkingBuff, pRecContext->fLDAPNodeStruct->fLDAPCredentialsLen );
pWorkingBuff += pRecContext->fLDAPNodeStruct->fLDAPCredentialsLen;
*((long *)pWorkingBuff) = iUserIDLen;
pWorkingBuff += sizeof(long);
bcopy( pUserID, pWorkingBuff, iUserIDLen );
pWorkingBuff += iUserIDLen;
pStepData->fBufferLength = pWorkingBuff - pStepData->fBufferData;
int result = dsDoDirNodeAuth( nodeRef, pAuthMethod, true, pStepData, pStepDataResp, NULL );
DBGLOG1( kLogPlugin, "CLDAPv3Plugin: Attempt to delete PWS ID associated with record returned status %d", result );
dsDataNodeDeAllocate( nodeRef, pAuthMethod );
dsDataNodeDeAllocate( nodeRef, pStepData );
dsDataNodeDeAllocate( nodeRef, pStepDataResp );
}
if ( nodeRef )
{
dsCloseDirNode( nodeRef );
}
if ( dsRef )
{
dsCloseDirService( dsRef );
}
}
gLDAPContextTable->RemoveItem( inData->fInRecRef );
}
catch ( sInt32 err )
{
siResult = err;
}
DSFreeString( pAdminID );
DSFreeString( pUserID );
return( siResult );
}
sInt32 CLDAPv3Plugin::AddAttribute( sAddAttribute *inData )
{
sInt32 siResult = eDSNoErr;
siResult = AddValue( inData->fInRecRef, inData->fInNewAttr, inData->fInFirstAttrValue );
return( siResult );
}
sInt32 CLDAPv3Plugin::AddAttributeValue( sAddAttributeValue *inData )
{
sInt32 siResult = eDSNoErr;
siResult = AddValue( inData->fInRecRef, inData->fInAttrType, inData->fInAttrValue );
return( siResult );
}
sInt32 CLDAPv3Plugin::SetAttributes ( unsigned long inRecRef, CFDictionaryRef inDict )
{
sInt32 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 = (sLDAPContextData *)gLDAPContextTable->GetItemData( inRecRef );
if ( pRecContext == nil ) throw( (sInt32)eDSBadContextData );
if ( pRecContext->bLDAPv2ReadOnly ) throw( (sInt32)eDSReadOnly);
if ( pRecContext->fOpenRecordDN == nil ) throw( (sInt32)eDSNullRecName );
if ( CFGetTypeID(inDict) != CFDictionaryGetTypeID() ) throw( (sInt32)eDSInvalidBuffFormat );
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( (sInt32)eMemoryError );
bGotIt = CFStringGetCString( keyCFString, attrTypeStr, callocLength, kCFStringEncodingUTF8 );
if (bGotIt == false) throw( (sInt32)eMemoryError );
}
attrTypeLDAPStr = MapAttrToLDAPType( (const char *)(pRecContext->fOpenRecordType), attrTypeStr, pRecContext->fNodeName, 1, true );
if ( attrTypeLDAPStr == nil ) throw( (sInt32)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( (sInt32)eMemoryError );
bool bGotValue = CFStringGetCString( valueCFString, attrValue, callocLength, kCFStringEncodingUTF8 );
if (bGotValue == false) throw( (sInt32)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( (sInt32)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 = fLDAPSessionMgr.LockSession(pRecContext);
if (aHost != nil)
{
ldapReturnCode = ldap_modify_s( aHost, pRecContext->fOpenRecordDN, mods);
}
else
{
ldapReturnCode = LDAP_LOCAL_ERROR;
}
fLDAPSessionMgr.UnLockSession(pRecContext);
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 ( sInt32 err )
{
siResult = err;
}
DSFreeString( attrTypeLDAPStr );
return( siResult );
}
sInt32 CLDAPv3Plugin::RemoveAttribute ( sRemoveAttribute *inData )
{
sInt32 siResult = eDSNoErr;
sLDAPContextData *pRecContext = nil;
int numAttributes = 1;
char *pLDAPAttrType = nil;
LDAPMod *mods[2];
int ldapReturnCode = 0;
try
{
pRecContext = (sLDAPContextData *)gLDAPContextTable->GetItemData( inData->fInRecRef );
if ( pRecContext == nil ) throw( (sInt32)eDSBadContextData );
if ( pRecContext->bLDAPv2ReadOnly ) throw( (sInt32)eDSReadOnly);
if ( pRecContext->fOpenRecordDN == nil ) throw( (sInt32)eDSNullRecName );
if ( inData->fInAttribute->fBufferData == nil ) throw( (sInt32)eDSNullAttributeType );
numAttributes = 1;
pLDAPAttrType = MapAttrToLDAPType( (const char *)(pRecContext->fOpenRecordType), inData->fInAttribute->fBufferData, pRecContext->fNodeName, numAttributes, true );
if ( pLDAPAttrType == nil ) throw( (sInt32)eDSInvalidAttributeType );
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 = fLDAPSessionMgr.LockSession(pRecContext);
if (aHost != nil)
{
ldapReturnCode = ldap_modify_s( aHost, pRecContext->fOpenRecordDN, mods);
}
else
{
ldapReturnCode = LDAP_LOCAL_ERROR;
}
fLDAPSessionMgr.UnLockSession(pRecContext);
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( (const char *)(pRecContext->fOpenRecordType), inData->fInAttribute->fBufferData, pRecContext->fNodeName, numAttributes, true );
}
}
catch ( sInt32 err )
{
siResult = err;
}
return( siResult );
}
sInt32 CLDAPv3Plugin::AddValue ( uInt32 inRecRef, tDataNodePtr inAttrType, tDataNodePtr inAttrValue )
{
sInt32 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 = (sLDAPContextData *)gLDAPContextTable->GetItemData( inRecRef );
if ( pRecContext == nil ) throw( (sInt32)eDSBadContextData );
if ( pRecContext->bLDAPv2ReadOnly ) throw( (sInt32)eDSReadOnly);
if ( pRecContext->fOpenRecordDN == nil ) throw( (sInt32)eDSNullRecName );
if ( inAttrType->fBufferData == nil ) throw( (sInt32)eDSNullAttributeType );
if ( (inAttrValue == nil) || (inAttrValue->fBufferLength < 1) )
{
throw( (sInt32)eDSEmptyAttributeValue );
}
else
{
attrLength = inAttrValue->fBufferLength;
attrValue = (char *) calloc(1, 1 + attrLength);
memcpy(attrValue, inAttrValue->fBufferData, attrLength);
}
bval.bv_val = attrValue;
bval.bv_len = attrLength;
bvals[0] = &bval;
bvals[1] = NULL;
numAttributes = 1;
pLDAPAttrType = MapAttrToLDAPType( (const char *)(pRecContext->fOpenRecordType), inAttrType->fBufferData, pRecContext->fNodeName, numAttributes, true );
if ( pLDAPAttrType == nil ) throw( (sInt32)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 = fLDAPSessionMgr.LockSession(pRecContext);
if (aHost != nil)
{
ldapReturnCode = ldap_modify_s( aHost, pRecContext->fOpenRecordDN, mods);
}
else
{
ldapReturnCode = LDAP_LOCAL_ERROR;
}
fLDAPSessionMgr.UnLockSession(pRecContext);
if ( ldapReturnCode != LDAP_SUCCESS )
{
siResult = MapLDAPWriteErrorToDS( ldapReturnCode, eDSAttributeNotFound );
}
}
if (pLDAPAttrType != nil)
{
delete (pLDAPAttrType);
pLDAPAttrType = nil;
}
} }
catch ( sInt32 err )
{
siResult = err;
}
DSFree(attrValue);
return( siResult );
}
sInt32 CLDAPv3Plugin::SetRecordName ( sSetRecordName *inData )
{
sInt32 siResult = eDSNoErr;
sLDAPContextData *pRecContext = nil;
char *pLDAPAttrType = nil;
int ldapReturnCode = 0;
tDataNodePtr pRecName = nil;
char *ldapRDNString = nil;
uInt32 ldapRDNLength = 0;
try
{
pRecContext = (sLDAPContextData *)gLDAPContextTable->GetItemData( inData->fInRecRef );
if ( pRecContext == nil ) throw( (sInt32)eDSBadContextData );
if ( pRecContext->bLDAPv2ReadOnly ) throw( (sInt32)eDSReadOnly);
pRecName = inData->fInNewRecName;
if ( pRecName == nil ) throw( (sInt32)eDSNullRecName );
if (pRecName->fBufferLength == 0) throw( (sInt32)eDSEmptyRecordNameList );
pLDAPAttrType = MapAttrToLDAPType( (const char *)(pRecContext->fOpenRecordType), kDSNAttrRecordName, pRecContext->fNodeName, 1, true );
if ( pLDAPAttrType == nil ) throw( (sInt32)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 = fLDAPSessionMgr.LockSession(pRecContext);
if (aHost != nil)
{
ldapReturnCode = ldap_rename_s( aHost, pRecContext->fOpenRecordDN, ldapRDNString, NULL, 1, NULL, NULL);
}
else
{
ldapReturnCode = LDAP_LOCAL_ERROR;
}
fLDAPSessionMgr.UnLockSession(pRecContext);
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 *pLDAPRecType = nil;
pLDAPRecType = MapRecToLDAPType( (const char *)(pRecContext->fOpenRecordType), pRecContext->fNodeName, 1, nil, nil, nil );
if (pLDAPRecType != nil)
{
newldapDN = (char *) calloc(1, 1 + strlen(ldapRDNString) + 2 + strlen(pLDAPRecType));
strcpy(newldapDN,ldapRDNString);
strcat(newldapDN,", ");
strcat(newldapDN,pLDAPRecType);
DSFreeString(pRecContext->fOpenRecordDN);
pRecContext->fOpenRecordDN = newldapDN;
DSFreeString(pLDAPRecType);
}
}
}
catch ( sInt32 err )
{
siResult = err;
}
DSFreeString(pLDAPAttrType);
DSFreeString(ldapRDNString);
return( siResult );
}
sInt32 CLDAPv3Plugin::CreateRecord ( sCreateRecord *inData )
{
sInt32 siResult = eDSNoErr;
sLDAPContextData *pContext = nil;
sLDAPContextData *pRecContext = nil;
char *pLDAPAttrType = nil;
LDAPMod *mods[128]; uInt32 modIndex = 0;
int ldapReturnCode = 0;
sLDAPConfigData *pConfig = nil;
tDataNodePtr pRecType = nil;
tDataNodePtr pRecName = nil;
char *pLDAPRecType = 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;
CFIndex cfBuffSize = 1024;
int aOCSearchListCount = 0;
bool bOCSchemaNil = false;
bool bOCSchemaBuilt = false;
try
{
pContext = (sLDAPContextData *)gLDAPContextTable->GetItemData( inData->fInNodeRef );
if ( pContext == nil ) throw( (sInt32)eDSBadContextData );
if ( pContext->bLDAPv2ReadOnly ) throw( (sInt32)eDSReadOnly);
pRecType = inData->fInRecType;
if ( pRecType == nil ) throw( (sInt32)eDSNullRecType );
pRecName = inData->fInRecName;
if ( pRecName == nil ) throw( (sInt32)eDSNullRecName );
if (pRecName->fBufferLength == 0) throw( (sInt32)eDSEmptyRecordNameList );
if (pRecType->fBufferLength == 0) throw( (sInt32)eDSEmptyRecordTypeList );
pLDAPAttrType = MapAttrToLDAPType( (const char *)(pRecType->fBufferData), kDSNAttrRecordName, pContext->fNodeName, 1, true );
if ( pLDAPAttrType == nil ) throw( (sInt32)eDSInvalidAttributeType );
pLDAPRecType = MapRecToLDAPType( (const char *)(pRecType->fBufferData), pContext->fNodeName, 1, &bOCANDGroup, &OCSearchList, nil );
if ( pLDAPRecType == nil ) throw( (sInt32)eDSInvalidRecordType );
ldapDNLength = strlen(pLDAPAttrType) + 1 + 2*pRecName->fBufferLength + 2 + strlen(pLDAPRecType);
ldapDNString = (char *)calloc(1, ldapDNLength + 1);
strcpy(ldapDNString,pLDAPAttrType);
strcat(ldapDNString,"=");
char *escapedString = BuildEscapedRDN(pRecName->fBufferData);
strcat(ldapDNString,escapedString);
DSFreeString(escapedString);
strcat(ldapDNString,", ");
strcat(ldapDNString,pLDAPRecType);
rnvals[0] = pRecName->fBufferData;
rnvals[1] = NULL;
rnmod.mod_op = 0;
rnmod.mod_type = pLDAPAttrType;
rnmod.mod_values = rnvals;
pConfig = gpConfigFromXML->ConfigWithNodeNameLock( pContext->fNodeName );
if( pConfig != nil )
{
if (pConfig->fObjectClassSchema == nil)
{
bOCSchemaNil = true;
}
if (pConfig->bOCBuilt)
{
bOCSchemaBuilt = true;
}
gpConfigFromXML->ConfigUnlock( pConfig );
pConfig = nil;
}
if ( (pRecType->fBufferData != nil) && (pLDAPRecType != nil) )
{
if (strncmp(pRecType->fBufferData,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;
for (uInt32 modsIndex=1; modsIndex < 128; modsIndex++)
{
mods[modsIndex] = NULL;
}
modIndex = 1;
if ( bOCSchemaNil && (!bOCSchemaBuilt) )
{
fLDAPSessionMgr.GetSchema( pContext );
}
if (OCSearchList != nil)
{
pConfig = gpConfigFromXML->ConfigWithNodeNameLock( pContext->fNodeName );
if (pConfig && pConfig->fObjectClassSchema != nil) {
for (listOfStringsCI iter = objectClassList.begin(); iter != objectClassList.end(); ++iter)
{
if (pConfig->fObjectClassSchema->count(*iter) != 0)
{
ObjectClassMap::iterator mapIter = pConfig->fObjectClassSchema->find(*iter);
for (AttrSetCI parentIter = mapIter->second->fParentOCs.begin(); parentIter != mapIter->second->fParentOCs.end(); ++parentIter)
{
bool addObjectClassName = true;
for (listOfStringsCI dupIter = objectClassList.begin(); dupIter != objectClassList.end(); ++dupIter)
{
if (*dupIter == *parentIter) {
addObjectClassName = false;
break;
}
}
if (addObjectClassName)
{
objectClassList.push_back(*parentIter);
}
}
}
}
for (listOfStringsCI iter = objectClassList.begin(); iter != objectClassList.end(); ++iter)
{
if (pConfig->fObjectClassSchema->count(*iter) != 0)
{
ObjectClassMap::iterator mapIter = pConfig->fObjectClassSchema->find(*iter);
for (AttrSetCI reqIter = mapIter->second->fRequiredAttrs.begin(); reqIter != mapIter->second->fRequiredAttrs.end(); ++reqIter)
{
if ( (*reqIter != "objectClass") && (*reqIter != "nTSecurityDescriptor") && (*reqIter != "objectCategory") && (*reqIter != "instanceType") ) {
bool addReqAttr = true;
for (listOfStringsCI dupIter = reqAttrsList.begin(); dupIter != reqAttrsList.end(); ++dupIter)
{
if (*dupIter == *reqIter) {
addReqAttr = false;
break;
}
}
if (addReqAttr)
{
reqAttrsList.push_back(*reqIter);
}
}
if (*reqIter == "nTSecurityDescriptor") {
string nameString("sAMAccountName");
reqAttrsList.push_back(nameString);
}
}
}
}
}
if (pConfig != nil)
{
gpConfigFromXML->ConfigUnlock( pConfig );
}
raCount = reqAttrsList.size();
ocCount = objectClassList.size();
ocString = (char *)calloc(1,12);
strcpy(ocString,"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] = "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 = fLDAPSessionMgr.LockSession(pContext);
if (aHost != nil)
{
ldapReturnCode = ldap_add_ext_s( aHost, ldapDNString, mods, NULL, NULL);
}
else
{
ldapReturnCode = LDAP_LOCAL_ERROR;
}
fLDAPSessionMgr.UnLockSession(pContext);
if ( ldapReturnCode == LDAP_ALREADY_EXISTS )
{
siResult = eDSRecordAlreadyExists;
}
else if ( ldapReturnCode != LDAP_SUCCESS )
{
siResult = MapLDAPWriteErrorToDS( ldapReturnCode, eDSRecordNotFound );
}
if ( (inData->fInOpen == true) && (siResult == eDSNoErr) )
{
fLDAPSessionMgr.SessionMapMutexLock();
pRecContext = new sLDAPContextData( *pContext );
fLDAPSessionMgr.SessionMapMutexUnlock();
if ( pRecContext == nil ) throw( (sInt32) eMemoryAllocError );
pRecContext->fType = 2;
if (pRecType->fBufferData != nil)
{
pRecContext->fOpenRecordType = strdup( pRecType->fBufferData );
}
if (pRecName->fBufferData != nil)
{
pRecContext->fOpenRecordName = strdup( pRecName->fBufferData );
}
pRecContext->fOpenRecordDN = ldapDNString;
ldapDNString = nil;
gLDAPContextTable->AddItem( inData->fOutRecRef, pRecContext );
}
}
catch ( sInt32 err )
{
siResult = err;
}
DSFreeString(pLDAPAttrType);
DSFreeString(pLDAPRecType);
DSFreeString(ldapDNString);
DSFree(needsValueMarker);
DSFreeString(ocString);
DSFree(ocvals);
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);
return( siResult );
}
sInt32 CLDAPv3Plugin::CreateRecordWithAttributes ( tDirNodeReference inNodeRef, const char* inRecType, const char* inRecName, CFDictionaryRef inDict )
{
sInt32 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 *pLDAPRecType = nil;
char *recNameAttrType = nil;
sLDAPConfigData *pConfig = 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;
bool bOCSchemaNil = false;
bool bOCSchemaBuilt = false;
uInt32 keyIndex = 0;
uInt32 modIndex = 0;
uInt32 bValueStartIndex= 0;
CFMutableDictionaryRef mergedDict = NULL;
try
{
pContext = (sLDAPContextData *)gLDAPContextTable->GetItemData( inNodeRef );
if ( pContext == nil ) throw( (sInt32)eDSBadContextData );
if ( pContext->bLDAPv2ReadOnly ) throw( (sInt32)eDSReadOnly);
if ( CFGetTypeID(inDict) != CFDictionaryGetTypeID() ) throw( (sInt32)eDSInvalidBuffFormat );
if ( inRecType == nil ) throw( (sInt32)eDSNullRecType );
if ( inRecName == nil ) throw( (sInt32)eDSNullRecName );
for (uInt32 modsIndex=0; modsIndex < 128; modsIndex++)
{
mods[modsIndex] = NULL;
}
recNameAttrType = MapAttrToLDAPType( (const char *)inRecType, kDSNAttrRecordName, pContext->fNodeName, 1, true );
if ( recNameAttrType == nil ) throw( (sInt32)eDSInvalidAttributeType );
pLDAPRecType = MapRecToLDAPType( (const char *)inRecType, pContext->fNodeName, 1, &bOCANDGroup, &OCSearchList, nil );
if ( pLDAPRecType == nil ) throw( (sInt32)eDSInvalidRecordType );
ldapDNLength = strlen(recNameAttrType) + 1 + 2*strlen(inRecName) + 2 + strlen(pLDAPRecType);
ldapDNString = (char *)calloc(1, ldapDNLength + 1);
strcpy(ldapDNString,recNameAttrType);
strcat(ldapDNString,"=");
char *escapedString = BuildEscapedRDN(inRecName);
strcat(ldapDNString,escapedString);
DSFreeString(escapedString);
strcat(ldapDNString,", ");
strcat(ldapDNString,pLDAPRecType);
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
{
struct berval **newValues = (struct berval**) calloc(1, (numShortNames + 1) *sizeof(struct berval *) );
uInt32 valIndex = 0;
for( CFIndex i=0; i<numShortNames; i++ )
{
CFStringRef shortName = (CFStringRef)CFArrayGetValueAtIndex( shortNames, i );
uInt32 callocLength = (uInt32) CFStringGetMaximumSizeForEncoding(
CFStringGetLength(shortName), kCFStringEncodingUTF8) + 1;
char* attrValue = (char *)::calloc( 1, callocLength );
if ( attrValue == NULL ) throw( (sInt32)eMemoryError );
bool bGotValue = CFStringGetCString( shortName, attrValue, callocLength, kCFStringEncodingUTF8 );
if (bGotValue == false) throw( (sInt32)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;
}
pConfig = gpConfigFromXML->ConfigWithNodeNameLock( pContext->fNodeName );
if( pConfig != nil )
{
if (pConfig->fObjectClassSchema == nil)
{
bOCSchemaNil = true;
}
if (pConfig->bOCBuilt)
{
bOCSchemaBuilt = true;
}
gpConfigFromXML->ConfigUnlock( pConfig );
pConfig = nil;
}
if ( (inRecType != nil) && (pLDAPRecType != 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 ( bOCSchemaNil && (!bOCSchemaBuilt) )
{
fLDAPSessionMgr.GetSchema( pContext );
}
if (OCSearchList != nil)
{
pConfig = gpConfigFromXML->ConfigWithNodeNameLock( pContext->fNodeName );
if (pConfig && pConfig->fObjectClassSchema != nil) {
for (listOfStringsCI iter = objectClassList.begin(); iter != objectClassList.end(); ++iter)
{
if (pConfig->fObjectClassSchema->count(*iter) != 0)
{
ObjectClassMap::iterator mapIter = pConfig->fObjectClassSchema->find(*iter);
for (AttrSetCI parentIter = mapIter->second->fParentOCs.begin(); parentIter != mapIter->second->fParentOCs.end(); ++parentIter)
{
bool addObjectClassName = true;
for (listOfStringsCI dupIter = objectClassList.begin(); dupIter != objectClassList.end(); ++dupIter)
{
if (*dupIter == *parentIter) {
addObjectClassName = false;
break;
}
}
if (addObjectClassName)
{
objectClassList.push_back(*parentIter);
}
}
}
}
for (listOfStringsCI iter = objectClassList.begin(); iter != objectClassList.end(); ++iter)
{
if (pConfig->fObjectClassSchema->count(*iter) != 0)
{
ObjectClassMap::iterator mapIter = pConfig->fObjectClassSchema->find(*iter);
for (AttrSetCI reqIter = mapIter->second->fRequiredAttrs.begin(); reqIter != mapIter->second->fRequiredAttrs.end(); ++reqIter)
{
if ( (*reqIter != "objectClass") && (*reqIter != "nTSecurityDescriptor") && (*reqIter != "objectCategory") && (*reqIter != "instanceType") ) {
bool addReqAttr = true;
for (listOfStringsCI dupIter = reqAttrsList.begin(); dupIter != reqAttrsList.end(); ++dupIter)
{
if (*dupIter == *reqIter) {
addReqAttr = false;
break;
}
}
if (addReqAttr)
{
reqAttrsList.push_back(*reqIter);
}
}
if (*reqIter == "nTSecurityDescriptor") {
string nameString("sAMAccountName");
reqAttrsList.push_back(nameString);
}
}
}
}
}
if (pConfig != nil)
{
gpConfigFromXML->ConfigUnlock( pConfig );
}
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( (sInt32)eMemoryError );
bGotIt = CFStringGetCString( keyCFString, attrTypeStr, callocLength, kCFStringEncodingUTF8 );
if (bGotIt == false) throw( (sInt32)eMemoryError );
}
attrTypeLDAPStr = MapAttrToLDAPType( (const char *)inRecType, attrTypeStr, pContext->fNodeName, 1, true );
if ( attrTypeLDAPStr == nil ) throw( (sInt32)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( (sInt32)eMemoryError );
bGotIt = CFStringGetCString( keyCFString, attrTypeStr, callocLength, kCFStringEncodingUTF8 );
if (bGotIt == false) throw( (sInt32)eMemoryError );
}
CFArrayRef 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( (sInt32)eMemoryError );
bool bGotValue = CFStringGetCString( valueCFString, attrValue, callocLength, kCFStringEncodingUTF8 );
if (bGotValue == false) throw( (sInt32)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( (sInt32)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 = fLDAPSessionMgr.LockSession(pContext);
if (aHost != nil)
{
ldapReturnCode = ldap_add_ext_s( aHost, ldapDNString, mods, NULL, NULL);
}
else
{
ldapReturnCode = LDAP_LOCAL_ERROR;
}
fLDAPSessionMgr.UnLockSession(pContext);
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;
}
}
mods[modsIndex] = NULL;
}
}
catch ( sInt32 err )
{
siResult = err;
}
DSCFRelease(OCSearchList);
DSFree(ocvals);
DSFreeString( attrTypeLDAPStr );
DSFreeString( pLDAPRecType );
DSFreeString( recNameAttrType );
DSCFRelease(mergedDict);
return( siResult );
}
sInt32 CLDAPv3Plugin::RemoveAttributeValue ( sRemoveAttributeValue *inData )
{
sInt32 siResult = eDSNoErr;
tDataNodePtr pAttrType = nil;
char *pLDAPAttrType = nil;
sLDAPContextData *pRecContext = nil;
LDAPMessage *result = nil;
struct berval **bValues = nil;
struct berval **newValues = nil;
unsigned long valCount = 0;
bool bFoundIt = false;
int numAttributes = 1;
uInt32 crcVal = 0;
LDAPMod *mods[2];
int ldapReturnCode = 0;
LDAP *aHost = nil;
char **attrs = nil;
int ldapMsgId = 0;
try
{
pRecContext = (sLDAPContextData *)gLDAPContextTable->GetItemData( inData->fInRecRef );
if ( pRecContext == nil ) throw( (sInt32)eDSBadContextData );
if ( pRecContext->bLDAPv2ReadOnly ) throw( (sInt32)eDSReadOnly);
if ( pRecContext->fOpenRecordDN == nil ) throw( (sInt32)eDSNullRecName );
pAttrType = inData->fInAttrType;
if ( pAttrType == nil ) throw( (sInt32)eDSEmptyAttributeType );
if ( pAttrType->fBufferData == nil ) throw( (sInt32)eDSEmptyAttributeType );
attrs = MapAttrToLDAPTypeArray( pRecContext->fOpenRecordType, pAttrType->fBufferData, pRecContext->fNodeName );
if ( attrs == nil ) throw( (sInt32)eDSInvalidAttributeType );
siResult = GetRecRefLDAPMessage( pRecContext, ldapMsgId, attrs, &result );
if ( siResult != eDSNoErr ) throw( siResult );
if ( result != nil )
{
numAttributes = 1;
pLDAPAttrType = MapAttrToLDAPType( (const char *)(pRecContext->fOpenRecordType), pAttrType->fBufferData, pRecContext->fNodeName, numAttributes, true );
if ( pLDAPAttrType == nil ) throw( (sInt32)eDSInvalidAttributeType );
bFoundIt = false;
while ( ( pLDAPAttrType != nil ) && (!bFoundIt) )
{
valCount = 0;
aHost = fLDAPSessionMgr.LockSession(pRecContext);
if ( (aHost != nil) && ( ( 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++;
}
}
} fLDAPSessionMgr.UnLockSession(pRecContext);
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 = fLDAPSessionMgr.LockSession(pRecContext);
if (aHost != nil)
{
ldapReturnCode = ldap_modify_s( aHost, pRecContext->fOpenRecordDN, mods);
}
else
{
ldapReturnCode = LDAP_LOCAL_ERROR;
}
fLDAPSessionMgr.UnLockSession(pRecContext);
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( (const char *)(pRecContext->fOpenRecordType), pAttrType->fBufferData, pRecContext->fNodeName, numAttributes, true );
}
} else
{
throw( (sInt32)eDSRecordNotFound ); }
}
catch ( sInt32 err )
{
siResult = err;
}
DSFreeString( pLDAPAttrType );
DSFreeStringList( attrs );
if (result != nil)
{
ldap_msgfree( result );
result = nil;
}
aHost = fLDAPSessionMgr.LockSession(pRecContext);
if (aHost != nil)
{
DSSearchCleanUp(aHost, ldapMsgId);
}
fLDAPSessionMgr.UnLockSession(pRecContext);
return( siResult );
}
sInt32 CLDAPv3Plugin::SetAttributeValues ( sSetAttributeValues *inData )
{
sInt32 siResult = eDSNoErr;
tDataNodePtr pAttrType = nil;
char *pLDAPAttrType = nil;
sLDAPContextData *pRecContext = nil;
unsigned long 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;
tDataNodePtr valuePtr = nil;
try
{
pRecContext = (sLDAPContextData *)gLDAPContextTable->GetItemData( inData->fInRecRef );
if ( pRecContext == nil ) throw( (sInt32)eDSBadContextData );
if ( pRecContext->bLDAPv2ReadOnly ) throw( (sInt32)eDSReadOnly);
if ( pRecContext->fOpenRecordDN == nil ) throw( (sInt32)eDSNullRecName );
if ( inData->fInAttrType == nil ) throw( (sInt32)eDSNullAttributeType );
if ( inData->fInAttrValueList == nil ) throw( (sInt32)eDSNullAttributeValue ); if ( inData->fInAttrValueList->fDataNodeCount <= 0 ) throw( (sInt32)eDSNullAttributeValue );
pAttrType = inData->fInAttrType;
if ( pAttrType == nil ) throw( (sInt32)eDSEmptyAttributeType );
if ( pAttrType->fBufferData == nil ) throw( (sInt32)eDSEmptyAttributeType );
pLDAPAttrType = MapAttrToLDAPType( (const char *)(pRecContext->fOpenRecordType), pAttrType->fBufferData, pRecContext->fNodeName, 1, true );
if ( pLDAPAttrType == nil ) throw( (sInt32)eDSInvalidAttributeType );
valCount = inData->fInAttrValueList->fDataNodeCount;
newValues = (struct berval**) calloc(1, (valCount + 1) *sizeof(struct berval *) );
uInt32 jIndex = 0;
for (uInt32 i = 0; i < valCount; i++ ) {
dsDataListGetNodeAlloc( 0, inData->fInAttrValueList, i+1, &valuePtr );
if ( (valuePtr != nil) && (valuePtr->fBufferLength > 0) )
{
attrLength = valuePtr->fBufferLength;
attrValue = (char *) calloc(1, 1 + attrLength);
memcpy(attrValue, valuePtr->fBufferData, attrLength);
replaceValue = (struct berval*) calloc(1, sizeof(struct berval) );
replaceValue->bv_val = attrValue;
replaceValue->bv_len = attrLength;
newValues[jIndex] = replaceValue;
jIndex++;
attrValue = nil;
replaceValue = nil;
}
if (valuePtr != NULL)
{
dsDataBufferDeallocatePriv(valuePtr);
valuePtr = NULL;
}
}
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 = fLDAPSessionMgr.LockSession(pRecContext);
if (aHost != nil)
{
ldapReturnCode = ldap_modify_s( aHost, pRecContext->fOpenRecordDN, mods);
}
else
{
ldapReturnCode = LDAP_LOCAL_ERROR;
}
fLDAPSessionMgr.UnLockSession(pRecContext);
if ( ldapReturnCode != LDAP_SUCCESS )
{
siResult = MapLDAPWriteErrorToDS( ldapReturnCode, eDSAttributeNotFound );
}
if (newValues != NULL)
{
ldap_value_free_len(newValues);
newValues = NULL;
}
}
}
catch ( sInt32 err )
{
siResult = err;
}
DSFreeString( pLDAPAttrType );
return( siResult );
}
sInt32 CLDAPv3Plugin::SetAttributeValue ( sSetAttributeValue *inData )
{
sInt32 siResult = eDSNoErr;
tDataNodePtr pAttrType = nil;
char *pLDAPAttrType = nil;
sLDAPContextData *pRecContext = nil;
LDAPMessage *result = nil;
unsigned long 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;
int ldapMsgId = 0;
try
{
pRecContext = (sLDAPContextData *)gLDAPContextTable->GetItemData( inData->fInRecRef );
if ( pRecContext == nil ) throw( (sInt32)eDSBadContextData );
if ( pRecContext->bLDAPv2ReadOnly ) throw( (sInt32)eDSReadOnly);
if ( pRecContext->fOpenRecordDN == nil ) throw( (sInt32)eDSNullRecName );
if ( inData->fInAttrValueEntry == nil ) throw( (sInt32)eDSNullAttributeValue );
if ( (inData->fInAttrValueEntry->fAttributeValueData.fBufferData == NULL) ||
(inData->fInAttrValueEntry->fAttributeValueData.fBufferLength < 1) )
{
throw( (sInt32)eDSEmptyAttributeValue );
}
else
{
attrLength = inData->fInAttrValueEntry->fAttributeValueData.fBufferLength;
attrValue = (char *) calloc(1, 1 + attrLength);
memcpy(attrValue, inData->fInAttrValueEntry->fAttributeValueData.fBufferData, attrLength);
}
pAttrType = inData->fInAttrType;
if ( pAttrType == nil ) throw( (sInt32)eDSEmptyAttributeType );
if ( pAttrType->fBufferData == nil ) throw( (sInt32)eDSEmptyAttributeType );
attrs = MapAttrToLDAPTypeArray( pRecContext->fOpenRecordType, pAttrType->fBufferData, pRecContext->fNodeName );
if ( attrs == nil ) throw( (sInt32)eDSInvalidAttributeType );
siResult = GetRecRefLDAPMessage( pRecContext, ldapMsgId, attrs, &result );
if ( siResult != eDSNoErr ) throw( siResult );
if ( result != nil )
{
numAttributes = 1;
pLDAPAttrType = MapAttrToLDAPType( (const char *)(pRecContext->fOpenRecordType), pAttrType->fBufferData, pRecContext->fNodeName, numAttributes, true );
if ( pLDAPAttrType == nil ) throw( (sInt32)eDSInvalidAttributeType );
bFoundIt = false;
while ( ( pLDAPAttrType != nil ) && (!bFoundIt) )
{
valCount = 0;
aHost = fLDAPSessionMgr.LockSession(pRecContext);
if ( (aHost != nil) && ( ( 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;
}
} fLDAPSessionMgr.UnLockSession(pRecContext);
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 = fLDAPSessionMgr.LockSession(pRecContext);
if (aHost != nil)
{
ldapReturnCode = ldap_modify_s( aHost, pRecContext->fOpenRecordDN, mods);
}
else
{
ldapReturnCode = LDAP_LOCAL_ERROR;
}
fLDAPSessionMgr.UnLockSession(pRecContext);
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( (const char *)(pRecContext->fOpenRecordType), pAttrType->fBufferData, pRecContext->fNodeName, numAttributes, true );
}
} else
{
throw( (sInt32)eDSRecordNotFound ); }
}
catch ( sInt32 err )
{
siResult = err;
}
if ( result != nil )
{
ldap_msgfree( result );
result = nil;
}
aHost = fLDAPSessionMgr.LockSession(pRecContext);
if (aHost != nil)
{
DSSearchCleanUp(aHost, ldapMsgId);
}
fLDAPSessionMgr.UnLockSession(pRecContext);
DSFreeString(pLDAPAttrType);
DSFree(attrValue);
DSFreeStringList(attrs);
return( siResult );
}
sInt32 CLDAPv3Plugin::ReleaseContinueData ( sReleaseContinueData *inData )
{
sInt32 siResult = eDSNoErr;
if ( gLDAPContinueTable->RemoveItem( inData->fInContinueData ) != eDSNoErr )
{
siResult = eDSInvalidContext;
}
return( siResult );
}
sInt32 CLDAPv3Plugin::CloseAttributeList ( sCloseAttributeList *inData )
{
sInt32 siResult = eDSNoErr;
sLDAPContextData *pContext = nil;
pContext = (sLDAPContextData *)gLDAPContextTable->GetItemData( inData->fInAttributeListRef );
if ( pContext != nil )
{
gLDAPContextTable->RemoveItem( inData->fInAttributeListRef );
}
else
{
siResult = eDSInvalidAttrListRef;
}
return( siResult );
}
sInt32 CLDAPv3Plugin::CloseAttributeValueList ( sCloseAttributeValueList *inData )
{
sInt32 siResult = eDSNoErr;
sLDAPContextData *pContext = nil;
pContext = (sLDAPContextData *)gLDAPContextTable->GetItemData( inData->fInAttributeValueListRef );
if ( pContext != nil )
{
gLDAPContextTable->RemoveItem( inData->fInAttributeValueListRef );
}
else
{
siResult = eDSInvalidAttrValueRef;
}
return( siResult );
}
sInt32 CLDAPv3Plugin::GetRecRefInfo ( sGetRecRefInfo *inData )
{
sInt32 siResult = eDSNoErr;
uInt32 uiRecSize = 0;
tRecordEntry *pRecEntry = nil;
sLDAPContextData *pContext = nil;
char *refType = nil;
uInt32 uiOffset = 0;
char *refName = nil;
try
{
pContext = (sLDAPContextData *)gLDAPContextTable->GetItemData( inData->fInRecRef );
if ( pContext == nil ) throw( (sInt32)eDSBadContextData );
if ( pContext->fOpenRecordType != nil)
{
refType = strdup( pContext->fOpenRecordType );
}
else {
refType = strdup( "Record Type Unknown" );
}
if ( pContext->fOpenRecordName != nil)
{
refName = strdup( pContext->fOpenRecordName );
}
else {
refName = strdup( "Record Name Unknown" );
}
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;
}
catch ( sInt32 err )
{
siResult = err;
}
if (refType != nil)
{
delete( refType );
refType = nil;
}
if (refName != nil)
{
delete( refName );
refName = nil;
}
return( siResult );
}
sInt32 CLDAPv3Plugin::GetRecAttribInfo ( sGetRecAttribInfo *inData )
{
sInt32 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;
int ldapMsgId = 0;
try
{
pRecContext = (sLDAPContextData *)gLDAPContextTable->GetItemData( inData->fInRecRef );
if ( pRecContext == nil ) throw( (sInt32)eDSBadContextData );
pAttrType = inData->fInAttrType;
if ( pAttrType == nil ) throw( (sInt32)eDSEmptyAttributeType );
if ( pAttrType->fBufferData == nil ) throw( (sInt32)eDSEmptyAttributeType );
attrs = MapAttrToLDAPTypeArray( pRecContext->fOpenRecordType, pAttrType->fBufferData, pRecContext->fNodeName );
if ( attrs == nil ) throw( (sInt32)eDSInvalidAttributeType );
siResult = GetRecRefLDAPMessage( pRecContext, ldapMsgId, attrs, &result );
if ( siResult != eDSNoErr ) throw( siResult);
if ( result != nil )
{
numAttributes = 1;
pLDAPAttrType = MapAttrToLDAPType( (const char *)(pRecContext->fOpenRecordType), pAttrType->fBufferData, pRecContext->fNodeName, numAttributes );
if ( pLDAPAttrType == nil ) throw( (sInt32)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 = fLDAPSessionMgr.LockSession(pRecContext);
if ( (aHost != nil) && ( ( 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;
}
} fLDAPSessionMgr.UnLockSession(pRecContext);
}
if (pLDAPAttrType != nil)
{
delete (pLDAPAttrType);
pLDAPAttrType = nil;
}
numAttributes++;
pLDAPAttrType = MapAttrToLDAPType( (const char *)(pRecContext->fOpenRecordType), pAttrType->fBufferData, pRecContext->fNodeName, numAttributes );
}
if ( pOutAttrEntry == nil )
{
inData->fOutAttrInfoPtr = nil;
throw( (sInt32)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 ( sInt32 err )
{
siResult = err;
}
if ( result != nil )
{
ldap_msgfree( result );
result = nil;
}
aHost = fLDAPSessionMgr.LockSession(pRecContext);
if (aHost != nil)
{
DSSearchCleanUp(aHost, ldapMsgId);
}
fLDAPSessionMgr.UnLockSession(pRecContext);
DSFreeString(pLDAPAttrType);
DSFreeStringList(attrs);
return( siResult );
}
sInt32 CLDAPv3Plugin::GetRecAttrValueByIndex ( sGetRecordAttributeValueByIndex *inData )
{
sInt32 siResult = eDSNoErr;
uInt32 uiDataLen = 0;
tDataNodePtr pAttrType = nil;
char *pLDAPAttrType = nil;
tAttributeValueEntryPtr pOutAttrValue = nil;
sLDAPContextData *pRecContext = nil;
LDAPMessage *result = nil;
struct berval **bValues;
unsigned long valCount = 0;
bool bFoundIt = false;
int numAttributes = 1;
uInt32 literalLength = 0;
bool bStripCryptPrefix = false;
LDAP *aHost = nil;
char **attrs = nil;
int ldapMsgId = 0;
try
{
if (inData->fInAttrValueIndex == 0) throw( (sInt32)eDSIndexOutOfRange );
pRecContext = (sLDAPContextData *)gLDAPContextTable->GetItemData( inData->fInRecRef );
if ( pRecContext == nil ) throw( (sInt32)eDSBadContextData );
pAttrType = inData->fInAttrType;
if ( pAttrType == nil ) throw( (sInt32)eDSEmptyAttributeType );
if ( pAttrType->fBufferData == nil ) throw( (sInt32)eDSEmptyAttributeType );
attrs = MapAttrToLDAPTypeArray( pRecContext->fOpenRecordType, pAttrType->fBufferData, pRecContext->fNodeName );
if ( attrs == nil ) throw( (sInt32)eDSInvalidAttributeType );
siResult = GetRecRefLDAPMessage( pRecContext, ldapMsgId, attrs, &result );
if ( siResult != eDSNoErr ) throw( siResult);
if ( result != nil )
{
if (::strcmp( kDS1AttrPasswordPlus, pAttrType->fBufferData ) == 0)
{
bStripCryptPrefix = true;
}
numAttributes = 1;
pLDAPAttrType = MapAttrToLDAPType( (const char *)(pRecContext->fOpenRecordType), pAttrType->fBufferData, pRecContext->fNodeName, numAttributes );
if ( pLDAPAttrType == nil ) throw( (sInt32)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 = fLDAPSessionMgr.LockSession(pRecContext);
if ( (aHost != nil) && ( ( 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;
}
} fLDAPSessionMgr.UnLockSession(pRecContext);
}
if (bFoundIt)
{
inData->fOutEntryPtr = pOutAttrValue;
}
if (pLDAPAttrType != nil)
{
delete (pLDAPAttrType);
pLDAPAttrType = nil;
}
numAttributes++;
pLDAPAttrType = MapAttrToLDAPType( (const char *)(pRecContext->fOpenRecordType), pAttrType->fBufferData, pRecContext->fNodeName, numAttributes );
}
if (!bFoundIt)
{
if (valCount < inData->fInAttrValueIndex)
{
siResult = eDSIndexOutOfRange;
}
else
{
siResult = eDSAttributeNotFound;
}
}
} else
{
siResult = eDSRecordNotFound;
}
if (pLDAPAttrType != nil)
{
delete( pLDAPAttrType );
pLDAPAttrType = nil;
}
}
catch ( sInt32 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;
}
aHost = fLDAPSessionMgr.LockSession(pRecContext);
if (aHost != nil)
{
DSSearchCleanUp(aHost, ldapMsgId);
}
fLDAPSessionMgr.UnLockSession(pRecContext);
return( siResult );
}
sInt32 CLDAPv3Plugin::GetRecAttrValueByValue ( sGetRecordAttributeValueByValue *inData )
{
sInt32 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;
int ldapMsgId = 0;
try
{
pRecContext = (sLDAPContextData *)gLDAPContextTable->GetItemData( inData->fInRecRef );
if ( pRecContext == nil ) throw( (sInt32)eDSBadContextData );
pAttrType = inData->fInAttrType;
if ( pAttrType == nil ) throw( (sInt32)eDSEmptyAttributeType );
if ( pAttrType->fBufferData == nil ) throw( (sInt32)eDSEmptyAttributeType );
attrLength = inData->fInAttrValue->fBufferLength;
attrValue = (char *) calloc(1, 1 + attrLength);
memcpy(attrValue, inData->fInAttrValue->fBufferData, attrLength);
attrs = MapAttrToLDAPTypeArray( pRecContext->fOpenRecordType, pAttrType->fBufferData, pRecContext->fNodeName );
if ( attrs == nil ) throw( (sInt32)eDSInvalidAttributeType );
siResult = GetRecRefLDAPMessage( pRecContext, ldapMsgId, attrs, &result );
if ( siResult != eDSNoErr ) throw( siResult);
if ( result != nil )
{
if (::strcmp( kDS1AttrPasswordPlus, pAttrType->fBufferData ) == 0)
{
bStripCryptPrefix = true;
}
numAttributes = 1;
pLDAPAttrType = MapAttrToLDAPType( (const char *)(pRecContext->fOpenRecordType), pAttrType->fBufferData, pRecContext->fNodeName, numAttributes );
if ( pLDAPAttrType == nil ) throw( (sInt32)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 = fLDAPSessionMgr.LockSession(pRecContext);
if ( (aHost != nil) && ( ( 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;
}
} fLDAPSessionMgr.UnLockSession(pRecContext);
}
if (bFoundIt)
{
inData->fOutEntryPtr = pOutAttrValue;
}
if (pLDAPAttrType != nil)
{
delete (pLDAPAttrType);
pLDAPAttrType = nil;
}
numAttributes++;
pLDAPAttrType = MapAttrToLDAPType( (const char *)(pRecContext->fOpenRecordType), pAttrType->fBufferData, pRecContext->fNodeName, numAttributes );
}
if (!bFoundIt)
{
siResult = eDSAttributeNotFound;
}
} else
{
siResult = eDSRecordNotFound;
}
if (pLDAPAttrType != nil)
{
delete( pLDAPAttrType );
pLDAPAttrType = nil;
}
}
catch ( sInt32 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;
}
aHost = fLDAPSessionMgr.LockSession(pRecContext);
if (aHost != nil)
{
DSSearchCleanUp(aHost, ldapMsgId);
}
fLDAPSessionMgr.UnLockSession(pRecContext);
return( siResult );
}
sInt32 CLDAPv3Plugin::GetRecordAttributeValueByID ( sGetRecordAttributeValueByID *inData )
{
sInt32 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;
int ldapMsgId = 0;
try
{
pRecContext = (sLDAPContextData *)gLDAPContextTable->GetItemData( inData->fInRecRef );
if ( pRecContext == nil ) throw( (sInt32)eDSBadContextData );
pAttrType = inData->fInAttrType;
if ( pAttrType == nil ) throw( (sInt32)eDSEmptyAttributeType );
if ( pAttrType->fBufferData == nil ) throw( (sInt32)eDSEmptyAttributeType );
attrs = MapAttrToLDAPTypeArray( pRecContext->fOpenRecordType, pAttrType->fBufferData, pRecContext->fNodeName );
if ( attrs == nil ) throw( (sInt32)eDSInvalidAttributeType );
siResult = GetRecRefLDAPMessage( pRecContext, ldapMsgId, attrs, &result );
if ( siResult != eDSNoErr ) throw( siResult);
if ( result != nil )
{
if (::strcmp( kDS1AttrPasswordPlus, pAttrType->fBufferData ) == 0)
{
bStripCryptPrefix = true;
}
numAttributes = 1;
pLDAPAttrType = MapAttrToLDAPType( (const char *)(pRecContext->fOpenRecordType), pAttrType->fBufferData, pRecContext->fNodeName, numAttributes );
if ( pLDAPAttrType == nil ) throw( (sInt32)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 = fLDAPSessionMgr.LockSession(pRecContext);
if ( (aHost != nil) && ( ( 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;
} fLDAPSessionMgr.UnLockSession(pRecContext);
}
if (bFoundIt)
{
inData->fOutEntryPtr = pOutAttrValue;
}
if (pLDAPAttrType != nil)
{
delete (pLDAPAttrType);
pLDAPAttrType = nil;
}
numAttributes++;
pLDAPAttrType = MapAttrToLDAPType( (const char *)(pRecContext->fOpenRecordType), pAttrType->fBufferData, pRecContext->fNodeName, numAttributes );
}
}
if (pLDAPAttrType != nil)
{
delete( pLDAPAttrType );
pLDAPAttrType = nil;
}
}
catch ( sInt32 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;
}
aHost = fLDAPSessionMgr.LockSession(pRecContext);
if (aHost != nil)
{
DSSearchCleanUp(aHost, ldapMsgId);
}
fLDAPSessionMgr.UnLockSession(pRecContext);
return( siResult );
}
char* CLDAPv3Plugin::GetNextStdAttrType ( char *inRecType, char *inConfigName, int &inputIndex )
{
char *outResult = nil;
sLDAPConfigData *pConfig = nil;
if (inputIndex > 0)
{
pConfig = gpConfigFromXML->ConfigWithNodeNameLock( inConfigName );
if (pConfig != nil)
{
if ( pConfig->fRecordAttrMapDict == NULL )
{
}
else
{
outResult = gpConfigFromXML->ExtractStdAttrName( inRecType, pConfig->fRecordAttrMapDict, inputIndex );
}
gpConfigFromXML->ConfigUnlock( pConfig );
}
}
return( outResult );
}
sInt32 CLDAPv3Plugin::DoAttributeValueSearch ( sDoAttrValueSearchWithData *inData )
{
sInt32 siResult = eDSNoErr;
bool bAttribOnly = false;
uInt32 uiCount = 0;
uInt32 uiTotal = 0;
char **pRecTypes = nil;
CAttributeList *cpAttrTypeList = nil;
char **pSearchStrings = nil;
char *pAttrType = nil;
char *pLDAPRecType = nil;
tDirPatternMatch pattMatch = eDSExact;
sLDAPContextData *pContext = nil;
sLDAPContinueData *pLDAPContinue = nil;
CBuff *outBuff = nil;
tDataList *pTmpDataList = nil;
int numRecTypes = 1;
bool bBuffFull = false;
bool separateRecTypes = false;
uInt32 countDownRecTypes = 0;
bool bOCANDGroup = false;
CFArrayRef OCSearchList = nil;
char *aCompoundExp = " "; ber_int_t scope = LDAP_SCOPE_SUBTREE;
try
{
if ( inData == nil ) throw( (sInt32) eMemoryError );
if ( inData->fOutDataBuff == nil ) throw( (sInt32)eDSEmptyBuffer );
if (inData->fOutDataBuff->fBufferSize == 0) throw( (sInt32)eDSEmptyBuffer );
if ( inData->fInRecTypeList == nil ) throw( (sInt32)eDSEmptyRecordTypeList );
pContext = (sLDAPContextData *)gLDAPContextTable->GetItemData( inData->fInNodeRef );
if ( pContext == nil ) throw( (sInt32)eDSBadContextData );
if ( inData->fIOContinueData == nil )
{
pLDAPContinue = (sLDAPContinueData *)::calloc( 1, sizeof( sLDAPContinueData ) );
gLDAPContinueTable->AddItem( pLDAPContinue, inData->fInNodeRef );
pLDAPContinue->fRecTypeIndex = 1;
pLDAPContinue->fTotalRecCount = 0;
pLDAPContinue->fLimitRecSearch = 0;
if (inData->fOutMatchRecordCount >= 0)
{
pLDAPContinue->fLimitRecSearch = inData->fOutMatchRecordCount;
}
}
else
{
pLDAPContinue = (sLDAPContinueData *)inData->fIOContinueData;
if ( gLDAPContinueTable->VerifyItem( pLDAPContinue ) == false )
{
throw( (sInt32)eDSInvalidContinueData );
}
}
inData->fIOContinueData = nil;
inData->fOutMatchRecordCount = 0;
outBuff = new CBuff();
if ( outBuff == nil ) throw( (sInt32) eMemoryError );
siResult = outBuff->Initialize( inData->fOutDataBuff, true );
if ( siResult != eDSNoErr ) throw( siResult );
siResult = outBuff->GetBuffStatus();
if ( siResult != eDSNoErr ) throw( siResult );
siResult = outBuff->SetBuffType( 'StdA' );
if ( siResult != eDSNoErr ) throw( siResult );
pRecTypes = dsAllocStringsFromList(0, inData->fInRecTypeList);
if ( pRecTypes == nil ) throw( (sInt32)eDSEmptyRecordTypeList );
uInt32 strCnt = 0;
bool bResetRecTypes = false;
while(pRecTypes[strCnt] != nil)
{
if (strcmp(pRecTypes[strCnt], kDSStdRecordTypeAll) == 0)
{
bResetRecTypes = true;
}
strCnt++;
}
if (strCnt == 0) throw( (sInt32)eDSEmptyRecordTypeList );
if (bResetRecTypes)
{
DSFreeStringList(pRecTypes);
strCnt = 0;
uInt32 i = 0;
sLDAPConfigData *pConfig = gpConfigFromXML->ConfigWithNodeNameLock( pContext->fNodeName );
if (pConfig != nil )
{
if( pConfig->fRecordAttrMapDict != nil )
{
strCnt = CFDictionaryGetCount( pConfig->fRecordAttrMapDict );
if( strCnt )
{
CFStringRef *keys = (CFStringRef *) calloc( strCnt, sizeof(CFStringRef) );
pRecTypes = (char **) calloc(strCnt+1, sizeof(char *));
CFDictionaryGetKeysAndValues( pConfig->fRecordAttrMapDict, (const void **)keys, NULL );
for( i = 0; i < strCnt; i++ )
{
CFIndex uiLength = CFStringGetMaximumSizeForEncoding( CFStringGetLength(keys[i]), kCFStringEncodingUTF8 );
pRecTypes[i] = (char *) calloc( uiLength, sizeof(char) );
CFStringGetCString( keys[i], pRecTypes[i], uiLength, kCFStringEncodingUTF8 );
}
DSFree( keys );
}
}
gpConfigFromXML->ConfigUnlock( pConfig );
}
if (strCnt == 0) throw( (sInt32)eDSEmptyRecordTypeList );
}
countDownRecTypes = strCnt - pLDAPContinue->fRecTypeIndex + 1;
pattMatch = inData->fInPattMatchType;
pAttrType = inData->fInAttrType->fBufferData;
if ( (pattMatch == eDSCompoundExpression) ||
(pattMatch == eDSiCompoundExpression) )
{
pAttrType = aCompoundExp; }
else
{
if ( pAttrType == nil ) throw( (sInt32)eDSEmptyAttributeType );
}
pSearchStrings = (char **) calloc(2, sizeof(char *));
pSearchStrings[0] = strdup(inData->fInPatt2Match->fBufferData);
if ( pSearchStrings == nil ) throw( (sInt32)eDSEmptyPattern2Match );
if ( inData->fType == kDoAttributeValueSearchWithData )
{
cpAttrTypeList = new CAttributeList( inData->fInAttrTypeRequestList );
if ( cpAttrTypeList == nil ) throw( (sInt32)eDSEmptyAttributeTypeList );
if (cpAttrTypeList->GetCount() == 0) throw( (sInt32)eDSEmptyAttributeTypeList );
bAttribOnly = inData->fInAttrInfoOnly;
}
else
{
pTmpDataList = dsBuildListFromStringsPriv( kDSAttributesAll, nil );
if ( pTmpDataList != nil )
{
cpAttrTypeList = new CAttributeList( pTmpDataList );
if ( cpAttrTypeList == nil ) throw( (sInt32)eDSEmptyAttributeTypeList );
if (cpAttrTypeList->GetCount() == 0) throw( (sInt32)eDSEmptyAttributeTypeList );
}
}
while ((( pRecTypes[pLDAPContinue->fRecTypeIndex-1] != nil ) && (!bBuffFull)) && (!separateRecTypes))
{
numRecTypes = 1;
bOCANDGroup = false;
if (OCSearchList != nil)
{
CFRelease(OCSearchList);
OCSearchList = nil;
}
pLDAPRecType = MapRecToLDAPType( (const char *)pRecTypes[pLDAPContinue->fRecTypeIndex-1], pContext->fNodeName, numRecTypes, &bOCANDGroup, &OCSearchList, &scope );
if ( ( pLDAPRecType == nil ) && (countDownRecTypes == 1) )
throw( (sInt32)eDSInvalidRecordType );
while (( pLDAPRecType != nil ) && (!bBuffFull))
{
bBuffFull = false;
if ( (::strcmp( pAttrType, kDSAttributesAll ) == 0 ) ||
(::strcmp( pAttrType, kDSAttributesStandardAll ) == 0 ) ||
(::strcmp( pAttrType, kDSAttributesNativeAll ) == 0 ) )
{
siResult = GetTheseRecords( nil, pSearchStrings, pRecTypes[pLDAPContinue->fRecTypeIndex-1], pLDAPRecType, pattMatch, cpAttrTypeList, pContext, pLDAPContinue, bAttribOnly, outBuff, uiCount, bOCANDGroup, OCSearchList, scope );
}
else
{
siResult = FindTheseRecords( pAttrType, pSearchStrings, pRecTypes[pLDAPContinue->fRecTypeIndex-1], pLDAPRecType, pattMatch, cpAttrTypeList, pContext, pLDAPContinue, bAttribOnly, outBuff, uiCount, bOCANDGroup, OCSearchList, scope );
}
if ( siResult == CBuff::kBuffFull )
{
bBuffFull = true;
inData->fIOContinueData = pLDAPContinue;
if ( ( uiCount == 0 ) && ( uiTotal == 0 ) )
{
throw( (sInt32)eDSBufferTooSmall );
}
uiTotal += uiCount;
inData->fOutMatchRecordCount = uiTotal;
outBuff->SetLengthToSize();
siResult = eDSNoErr;
}
else if ( siResult == eDSNoErr )
{
uiTotal += uiCount;
pLDAPContinue->msgId = 0;
}
if (pLDAPRecType != nil)
{
delete( pLDAPRecType );
pLDAPRecType = nil;
}
if (!bBuffFull)
{
numRecTypes++;
bOCANDGroup = false;
if (OCSearchList != nil)
{
CFRelease(OCSearchList);
OCSearchList = nil;
}
pLDAPRecType = MapRecToLDAPType( (const char *)pRecTypes[pLDAPContinue->fRecTypeIndex-1], pContext->fNodeName, numRecTypes, &bOCANDGroup, &OCSearchList, &scope );
}
}
if (!bBuffFull)
{
pLDAPContinue->fRecTypeIndex++;
pLDAPContinue->msgId = 0;
separateRecTypes = true;
inData->fIOContinueData = pLDAPContinue;
siResult = eDSNoErr;
countDownRecTypes--;
if (countDownRecTypes == 0)
{
inData->fIOContinueData = nil;
}
}
}
if (( siResult == eDSNoErr ) & (!bBuffFull))
{
if ( uiTotal == 0 )
{
outBuff->ClearBuff();
}
else
{
outBuff->SetLengthToSize();
}
inData->fOutMatchRecordCount = uiTotal;
}
}
catch ( sInt32 err )
{
siResult = err;
}
if (OCSearchList != nil)
{
CFRelease(OCSearchList);
OCSearchList = nil;
}
if ( (inData->fIOContinueData == nil) && (pLDAPContinue != nil) )
{
gLDAPContinueTable->RemoveItem( pLDAPContinue );
pLDAPContinue = nil;
}
if (pLDAPRecType != nil)
{
delete( pLDAPRecType );
pLDAPRecType = nil;
}
if ( cpAttrTypeList != nil )
{
delete( cpAttrTypeList );
cpAttrTypeList = nil;
}
if ( pTmpDataList != nil )
{
dsDataListDeallocatePriv( pTmpDataList );
free(pTmpDataList);
pTmpDataList = nil;
}
if ( outBuff != nil )
{
delete( outBuff );
outBuff = nil;
}
DSFreeStringList(pSearchStrings);
DSFreeStringList(pRecTypes);
return( siResult );
}
sInt32 CLDAPv3Plugin::DoMultipleAttributeValueSearch ( sDoMultiAttrValueSearchWithData *inData )
{
sInt32 siResult = eDSNoErr;
bool bAttribOnly = false;
uInt32 uiCount = 0;
uInt32 uiTotal = 0;
char **pRecTypes = nil;
CAttributeList *cpAttrTypeList = nil;
char **pSearchStrings = nil;
char *pAttrType = nil;
char *pLDAPRecType = nil;
tDirPatternMatch pattMatch = eDSExact;
sLDAPContextData *pContext = nil;
sLDAPContinueData *pLDAPContinue = nil;
CBuff *outBuff = nil;
tDataList *pTmpDataList = nil;
int numRecTypes = 1;
bool bBuffFull = false;
bool separateRecTypes = false;
uInt32 countDownRecTypes = 0;
bool bOCANDGroup = false;
CFArrayRef OCSearchList = nil;
char *aCompoundExp = " "; ber_int_t scope = LDAP_SCOPE_SUBTREE;
try
{
if ( inData == nil ) throw( (sInt32) eMemoryError );
if ( inData->fOutDataBuff == nil ) throw( (sInt32)eDSEmptyBuffer );
if (inData->fOutDataBuff->fBufferSize == 0) throw( (sInt32)eDSEmptyBuffer );
if ( inData->fInRecTypeList == nil ) throw( (sInt32)eDSEmptyRecordTypeList );
pContext = (sLDAPContextData *)gLDAPContextTable->GetItemData( inData->fInNodeRef );
if ( pContext == nil ) throw( (sInt32)eDSBadContextData );
if ( inData->fIOContinueData == nil )
{
pLDAPContinue = (sLDAPContinueData *)::calloc( 1, sizeof( sLDAPContinueData ) );
gLDAPContinueTable->AddItem( pLDAPContinue, inData->fInNodeRef );
pLDAPContinue->fRecTypeIndex = 1;
pLDAPContinue->fTotalRecCount = 0;
pLDAPContinue->fLimitRecSearch = 0;
if (inData->fOutMatchRecordCount >= 0)
{
pLDAPContinue->fLimitRecSearch = inData->fOutMatchRecordCount;
}
}
else
{
pLDAPContinue = (sLDAPContinueData *)inData->fIOContinueData;
if ( gLDAPContinueTable->VerifyItem( pLDAPContinue ) == false )
{
throw( (sInt32)eDSInvalidContinueData );
}
}
inData->fIOContinueData = nil;
inData->fOutMatchRecordCount = 0;
outBuff = new CBuff();
if ( outBuff == nil ) throw( (sInt32) eMemoryError );
siResult = outBuff->Initialize( inData->fOutDataBuff, true );
if ( siResult != eDSNoErr ) throw( siResult );
siResult = outBuff->GetBuffStatus();
if ( siResult != eDSNoErr ) throw( siResult );
siResult = outBuff->SetBuffType( 'StdA' );
if ( siResult != eDSNoErr ) throw( siResult );
pRecTypes = dsAllocStringsFromList(0, inData->fInRecTypeList);
if ( pRecTypes == nil ) throw( (sInt32)eDSEmptyRecordTypeList );
uInt32 strCnt = 0;
bool bResetRecTypes = false;
while(pRecTypes[strCnt] != nil)
{
if (strcmp(pRecTypes[strCnt], kDSStdRecordTypeAll) == 0)
{
bResetRecTypes = true;
}
strCnt++;
}
if (strCnt == 0) throw( (sInt32)eDSEmptyRecordTypeList );
if (bResetRecTypes)
{
DSFreeStringList(pRecTypes);
strCnt = 0;
uInt32 i = 0;
sLDAPConfigData *pConfig = gpConfigFromXML->ConfigWithNodeNameLock( pContext->fNodeName );
if (pConfig != nil )
{
if( pConfig->fRecordAttrMapDict != nil )
{
strCnt = CFDictionaryGetCount( pConfig->fRecordAttrMapDict );
if( strCnt )
{
CFStringRef *keys = (CFStringRef *) calloc( strCnt, sizeof(CFStringRef) );
pRecTypes = (char **) calloc(strCnt+1, sizeof(char *));
CFDictionaryGetKeysAndValues( pConfig->fRecordAttrMapDict, (const void **)keys, NULL );
for( i = 0; i < strCnt; i++ )
{
CFIndex uiLength = CFStringGetMaximumSizeForEncoding( CFStringGetLength(keys[i]), kCFStringEncodingUTF8 );
pRecTypes[i] = (char *) calloc( uiLength, sizeof(char) );
CFStringGetCString( keys[i], pRecTypes[i], uiLength, kCFStringEncodingUTF8 );
}
DSFree( keys );
}
}
gpConfigFromXML->ConfigUnlock( pConfig );
}
if (strCnt == 0) throw( (sInt32)eDSEmptyRecordTypeList );
}
countDownRecTypes = strCnt - pLDAPContinue->fRecTypeIndex + 1;
pattMatch = inData->fInPattMatchType;
pAttrType = inData->fInAttrType->fBufferData;
if ( (pattMatch == eDSCompoundExpression) ||
(pattMatch == eDSiCompoundExpression) )
{
pAttrType = aCompoundExp; }
else
{
if ( pAttrType == nil ) throw( (sInt32)eDSEmptyAttributeType );
}
pSearchStrings = dsAllocStringsFromList(0, inData->fInPatterns2MatchList);
if ( pSearchStrings == nil ) throw( (sInt32)eDSEmptyPattern2Match );
if ( inData->fType == kDoMultipleAttributeValueSearchWithData )
{
cpAttrTypeList = new CAttributeList( inData->fInAttrTypeRequestList );
if ( cpAttrTypeList == nil ) throw( (sInt32)eDSEmptyAttributeTypeList );
if (cpAttrTypeList->GetCount() == 0) throw( (sInt32)eDSEmptyAttributeTypeList );
bAttribOnly = inData->fInAttrInfoOnly;
}
else
{
pTmpDataList = dsBuildListFromStringsPriv( kDSAttributesAll, nil );
if ( pTmpDataList != nil )
{
cpAttrTypeList = new CAttributeList( pTmpDataList );
if ( cpAttrTypeList == nil ) throw( (sInt32)eDSEmptyAttributeTypeList );
if (cpAttrTypeList->GetCount() == 0) throw( (sInt32)eDSEmptyAttributeTypeList );
}
}
while ((( pRecTypes[pLDAPContinue->fRecTypeIndex-1] != nil ) && (!bBuffFull)) && (!separateRecTypes))
{
numRecTypes = 1;
bOCANDGroup = false;
if (OCSearchList != nil)
{
CFRelease(OCSearchList);
OCSearchList = nil;
}
pLDAPRecType = MapRecToLDAPType( (const char *)pRecTypes[pLDAPContinue->fRecTypeIndex-1], pContext->fNodeName, numRecTypes, &bOCANDGroup, &OCSearchList, &scope );
if ( ( pLDAPRecType == nil ) && (countDownRecTypes == 1) )
throw( (sInt32)eDSInvalidRecordType );
while (( pLDAPRecType != nil ) && (!bBuffFull))
{
bBuffFull = false;
if ( (::strcmp( pAttrType, kDSAttributesAll ) == 0 ) ||
(::strcmp( pAttrType, kDSAttributesStandardAll ) == 0 ) ||
(::strcmp( pAttrType, kDSAttributesNativeAll ) == 0 ) )
{
siResult = GetTheseRecords( nil, pSearchStrings, pRecTypes[pLDAPContinue->fRecTypeIndex-1], pLDAPRecType, pattMatch, cpAttrTypeList, pContext, pLDAPContinue, bAttribOnly, outBuff, uiCount, bOCANDGroup, OCSearchList, scope );
}
else
{
siResult = FindTheseRecords( pAttrType, pSearchStrings, pRecTypes[pLDAPContinue->fRecTypeIndex-1], pLDAPRecType, pattMatch, cpAttrTypeList, pContext, pLDAPContinue, bAttribOnly, outBuff, uiCount, bOCANDGroup, OCSearchList, scope );
}
if ( siResult == CBuff::kBuffFull )
{
bBuffFull = true;
inData->fIOContinueData = pLDAPContinue;
if ( ( uiCount == 0 ) && ( uiTotal == 0 ) )
{
throw( (sInt32)eDSBufferTooSmall );
}
uiTotal += uiCount;
inData->fOutMatchRecordCount = uiTotal;
outBuff->SetLengthToSize();
siResult = eDSNoErr;
}
else if ( siResult == eDSNoErr )
{
uiTotal += uiCount;
pLDAPContinue->msgId = 0;
}
if (pLDAPRecType != nil)
{
delete( pLDAPRecType );
pLDAPRecType = nil;
}
if (!bBuffFull)
{
numRecTypes++;
bOCANDGroup = false;
if (OCSearchList != nil)
{
CFRelease(OCSearchList);
OCSearchList = nil;
}
pLDAPRecType = MapRecToLDAPType( (const char *)pRecTypes[pLDAPContinue->fRecTypeIndex-1], pContext->fNodeName, numRecTypes, &bOCANDGroup, &OCSearchList, &scope );
}
}
if (!bBuffFull)
{
pLDAPContinue->fRecTypeIndex++;
pLDAPContinue->msgId = 0;
separateRecTypes = true;
inData->fIOContinueData = pLDAPContinue;
siResult = eDSNoErr;
countDownRecTypes--;
if (countDownRecTypes == 0)
{
inData->fIOContinueData = nil;
}
}
}
if (( siResult == eDSNoErr ) & (!bBuffFull))
{
if ( uiTotal == 0 )
{
outBuff->ClearBuff();
}
else
{
outBuff->SetLengthToSize();
}
inData->fOutMatchRecordCount = uiTotal;
}
}
catch ( sInt32 err )
{
siResult = err;
}
if (OCSearchList != nil)
{
CFRelease(OCSearchList);
OCSearchList = nil;
}
if ( (inData->fIOContinueData == nil) && (pLDAPContinue != nil) )
{
gLDAPContinueTable->RemoveItem( pLDAPContinue );
pLDAPContinue = nil;
}
if (pLDAPRecType != nil)
{
delete( pLDAPRecType );
pLDAPRecType = nil;
}
if ( cpAttrTypeList != nil )
{
delete( cpAttrTypeList );
cpAttrTypeList = nil;
}
if ( pTmpDataList != nil )
{
dsDataListDeallocatePriv( pTmpDataList );
free(pTmpDataList);
pTmpDataList = nil;
}
if ( outBuff != nil )
{
delete( outBuff );
outBuff = nil;
}
DSFreeStringList(pSearchStrings);
DSFreeStringList(pRecTypes);
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 = fLDAPSessionMgr.LockSession(inContext);
if (aHost != 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 *) 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 );
}
} } fLDAPSessionMgr.UnLockSession(inContext);
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;
aHost = fLDAPSessionMgr.LockSession(inContext);
if (aHost != 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 *) calloc(1,bValues[i]->bv_len + 1);
memcpy(pVal, bValues[i]->bv_val, bValues[i]->bv_len);
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 );
}
} } fLDAPSessionMgr.UnLockSession(inContext);
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);
string1 = (char *) calloc(1, length1 + 1);
if ( (inPattMatch >= eDSExact) && (inPattMatch <= eDSRegularExpression) )
{
strcpy(string1,inString);
}
else
{
p = inString;
for ( usIndex = 0; usIndex < length1; usIndex++ )
{
string1[usIndex] = toupper( *p );
p++;
}
}
uInt32 strCount = 0;
while(inPatterns[strCount] != nil)
{
length2 = strlen(inPatterns[strCount]);
string2 = (char *) calloc(1, length2 + 1);
if ( (inPattMatch >= eDSExact) && (inPattMatch <= eDSRegularExpression) )
{
strcpy(string2,inPatterns[strCount]);
}
else
{
p = inPatterns[strCount];
for ( usIndex = 0; usIndex < length2; usIndex++ )
{
string2[usIndex] = toupper( *p );
p++;
}
}
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++;
}
if (string1 != nil)
{
delete(string1);
}
return( bMatched );
}
sInt32 CLDAPv3Plugin::FindTheseRecords ( 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 )
{
sInt32 siResult = eDSNoErr;
sInt32 siValCnt = 0;
int ldapReturnCode = 0;
bool bufferFull = false;
LDAPMessage *result = nil;
char *recName = nil;
char *queryFilter = nil;
sLDAPConfigData *pConfig = nil;
int searchTO = 0;
CDataBuff *aRecData = nil;
CDataBuff *aAttrData = nil;
queryFilter = BuildLDAPQueryMultiFilter
( inConstAttrType,
inAttrNames,
patternMatch,
inContext->fNodeName,
false,
(const char *)inRecType,
inNativeRecType,
inbOCANDGroup,
inOCSearchList );
outRecCount = 0;
try
{
if (inContext == nil ) throw( (sInt32)eDSInvalidContext);
if (inContinue == nil ) throw( (sInt32)eDSInvalidContinueData);
if ( queryFilter == nil ) throw( (sInt32)eDSNullParameter );
aRecData = new CDataBuff();
if ( aRecData == nil ) throw( (sInt32) eMemoryError );
aAttrData = new CDataBuff();
if ( aAttrData == nil ) throw( (sInt32) eMemoryError );
pConfig = gpConfigFromXML->ConfigWithNodeNameLock( inContext->fNodeName );
if (pConfig != nil)
{
searchTO = pConfig->fSearchTimeout;
gpConfigFromXML->ConfigUnlock( pConfig );
pConfig = NULL;
}
DSDoSearch ( inRecType,
inNativeRecType,
inAttrTypeList,
inContext,
inContinue,
inScope,
fLDAPSessionMgr,
queryFilter,
ldapReturnCode,
searchTO,
result );
while ( ( (ldapReturnCode == LDAP_RES_SEARCH_ENTRY) || (ldapReturnCode == LDAP_RES_SEARCH_RESULT) )
&& !(bufferFull)
&& ( (inContinue->fTotalRecCount < inContinue->fLimitRecSearch) ||
(inContinue->fLimitRecSearch == 0) ) )
{
if (ldapReturnCode == LDAP_RES_SEARCH_ENTRY)
{
aRecData->Clear();
if ( inRecType != nil )
{
aRecData->AppendShort( ::strlen( inRecType ) );
aRecData->AppendString( inRecType );
}
else
{
aRecData->AppendShort( ::strlen( "Record Type Unknown" ) );
aRecData->AppendString( "Record Type Unknown" );
}
recName = GetRecordName( inRecType, result, inContext, siResult );
if ( siResult != eDSNoErr ) throw( siResult );
if ( recName != nil )
{
aRecData->AppendShort( ::strlen( recName ) );
aRecData->AppendString( recName );
delete ( recName );
recName = nil;
}
else
{
aRecData->AppendShort( ::strlen( "Record Name Unknown" ) );
aRecData->AppendString( "Record Name Unknown" );
}
aAttrData->Clear();
siResult = GetTheseAttributes( inRecType, inAttrTypeList, result, inAttrOnly, inContext, siValCnt, aAttrData );
if ( siResult != eDSNoErr ) throw( siResult );
if ( siValCnt == 0 )
{
aRecData->AppendShort( 0 );
}
else
{
aRecData->AppendShort( siValCnt );
aRecData->AppendBlock( aAttrData->GetData(), aAttrData->GetLength() );
}
siResult = inBuff->AddData( aRecData->GetData(), aRecData->GetLength() );
}
if (siResult == CBuff::kBuffFull)
{
bufferFull = true;
inContinue->pResult = result;
}
else if ( siResult == eDSNoErr )
{
ldap_msgfree( result );
result = nil;
if (ldapReturnCode == LDAP_RES_SEARCH_ENTRY)
{
outRecCount++; inContinue->fTotalRecCount++;
}
inContinue->pResult = nil;
DSGetSearchLDAPResult ( fLDAPSessionMgr,
inContext,
searchTO,
result,
LDAP_MSG_ONE,
inContinue->msgId,
ldapReturnCode,
false);
}
else
{
inContinue->pResult = nil;
throw( (sInt32)eDSInvalidBuffFormat );
}
}
if ( (result != inContinue->pResult) && (result != nil) )
{
ldap_msgfree( result );
result = nil;
}
if ( (siResult == eDSNoErr) && (inContinue != NULL) && (inContinue->msgId != 0) )
{
LDAP *aHost = nil;
aHost = fLDAPSessionMgr.LockSession(inContext);
if (aHost != nil)
{
DSSearchCleanUp(aHost, inContinue->msgId);
}
fLDAPSessionMgr.UnLockSession(inContext);
}
}
catch ( sInt32 err )
{
siResult = err;
}
if ( queryFilter != nil )
{
delete( queryFilter );
queryFilter = nil;
}
if ( aRecData != nil )
{
delete( aRecData );
aRecData = nil;
}
if ( aAttrData != nil )
{
delete( aAttrData );
aAttrData = nil;
}
return( siResult );
}
sInt32 CLDAPv3Plugin::SetAttributeValueForDN( sLDAPContextData *pContext, char *inDN, const char *inRecordType, char *inAttrType, char **inValues )
{
sInt32 siResult = eDSNoErr;
char *pLDAPAttrType = NULL;
if( inValues != NULL && *inValues != NULL )
{
pLDAPAttrType = MapAttrToLDAPType( (const char *)inRecordType, inAttrType, pContext->fNodeName, 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 = *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 = fLDAPSessionMgr.LockSession( pContext );
if( aHost != NULL )
{
ldapReturnCode = ldap_modify_s( aHost, inDN, pMods );
}
else
{
ldapReturnCode = LDAP_LOCAL_ERROR;
}
fLDAPSessionMgr.UnLockSession( pContext );
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::TryPWSPasswordSet( tDirNodeReference inNodeRef, uInt32 inAuthMethodCode, sLDAPContextData *pContext, tDataBufferPtr inAuthBuffer, const char *inRecordType )
{
tDataBufferPtr newAuthMethod = NULL;
tDataBufferPtr authResult = dsDataBufferAllocatePriv( 2048 );
tContextData continueData = NULL;
sInt32 siResult = eDSAuthFailed;
char **dn = NULL;
char *pUsername = NULL;
int userBufferItem = 1;
switch( inAuthMethodCode )
{
case kAuthNewUserWithPolicy:
case kAuthNewUser:
userBufferItem = 3;
break;
default:
newAuthMethod = dsDataNodeAllocateString( inNodeRef, kDSStdAuthNewUser );
}
if( authResult != NULL )
{
if( pContext->fLDAPNodeStruct->bAuthCallActive && GetUserNameFromAuthBuffer(inAuthBuffer, userBufferItem, &pUsername) == eDSNoErr )
{
dn = ldap_explode_dn( pContext->fLDAPNodeStruct->fLDAPUserName, 1 );
}
}
if( dn != NULL )
{
tDataBufferPtr authData = NULL;
char *pUserID = NULL;
char **aaArray = NULL;
unsigned long aaCount = 0;
siResult = GetAuthAuthority( pContext, dn[0], 0, fLDAPSessionMgr, &aaCount, &aaArray, kDSStdRecordTypeUsers );
if ( siResult == eDSNoErr )
{
unsigned long idx = 0;
while ( idx < aaCount )
{
char *aaVersion = NULL;
char *aaTag = NULL;
char *aaData = NULL;
siResult = ParseAuthAuthority( aaArray[idx], &aaVersion, &aaTag, &aaData );
if ( aaArray[idx] )
{
free( aaArray[idx] );
aaArray[idx] = NULL;
}
if( strcasecmp( aaTag, kDSTagAuthAuthorityPasswordServer ) == 0 )
{
pUserID = aaData;
aaData = NULL;
}
if( aaVersion != NULL )
{
free( aaVersion );
aaVersion = NULL;
}
if( aaTag != NULL )
{
free( aaTag );
aaTag = NULL;
}
if( aaData != NULL )
{
free( aaData );
aaData = NULL;
}
++idx;
}
if( aaArray != NULL )
{
free( aaArray );
aaArray = NULL;
}
}
if( pUserID != NULL && (authData = dsDataBufferAllocatePriv(1024)) != NULL )
{
char *pPtr = authData->fBufferData;
long lTempLength;
lTempLength = strlen( pUserID ) + 1;
*((long *) pPtr) = lTempLength;
pPtr += sizeof(long);
bcopy( pUserID, pPtr, lTempLength );
pPtr += lTempLength;
lTempLength = pContext->fLDAPNodeStruct->fLDAPCredentialsLen+1;
*((long *) pPtr) = lTempLength;
pPtr += sizeof(long);
bcopy( pContext->fLDAPNodeStruct->fLDAPCredentials, pPtr, lTempLength );
pPtr += lTempLength;
bcopy( inAuthBuffer->fBufferData, pPtr, inAuthBuffer->fBufferLength );
pPtr += inAuthBuffer->fBufferLength;
authData->fBufferLength = pPtr - authData->fBufferData;
char *ipAddress = strchr( pUserID, ':' ) + 1;
if( ipAddress != NULL && strlen(ipAddress) )
{
char *newAuthority = NULL;
char *newKerbAuthority = NULL;
char *newPWSid = NULL;
tDataBufferPtr pAuthType = NULL;
unsigned long newPWSlength = 0;
int iLength = 0;
if ( newAuthMethod != NULL )
{
siResult = dsDoDirNodeAuth( inNodeRef, newAuthMethod, true, authData, authResult, &continueData );
if( siResult == eDSNoErr )
{
newPWSlength = *((unsigned long *)authResult->fBufferData);
newPWSid = (char *) calloc( sizeof(char), newPWSlength + 1 );
strncpy( newPWSid, authResult->fBufferData + sizeof(newPWSlength), newPWSlength );
}
}
else
{
if ( pContext->fPWSUserID != NULL )
{
newPWSlength = pContext->fPWSUserIDLength;
newPWSid = pContext->fPWSUserID;
pContext->fPWSUserID = NULL;
}
else
{
siResult = eDSBadContextData; }
}
if( siResult == eDSNoErr )
{
iLength = strlen( kDSValueAuthAuthorityPasswordServerPrefix ) + newPWSlength + strlen( ipAddress ) + 2;
newAuthority = (char *) calloc( sizeof(char), iLength );
strcpy( newAuthority, kDSValueAuthAuthorityPasswordServerPrefix );
strcat( newAuthority, newPWSid );
strcat( newAuthority, ":" );
strcat( newAuthority, ipAddress );
}
if( siResult == eDSNoErr && newPWSid && (pAuthType = dsDataNodeAllocateString(inNodeRef, kDSStdAuthGetKerberosPrincipal)) != NULL )
{
bcopy( &newPWSlength, authData->fBufferData, sizeof(newPWSlength) );
bcopy( newPWSid, authData->fBufferData+sizeof(newPWSlength), newPWSlength );
authData->fBufferLength = sizeof(newPWSlength) + newPWSlength;
if( dsDoDirNodeAuth(inNodeRef, pAuthType, true, authData, authResult, NULL) == eDSNoErr )
{
long lLength = *((long *)authResult->fBufferData);
char *kerbPrinc = (char *) calloc( sizeof(char), lLength );
char *cr = NULL;
char *comma = strchr( newPWSid, ',' );
int iTmpLen = comma - newPWSid;
newKerbAuthority = (char *) calloc( sizeof(char), 1024 );
if( kerbPrinc != NULL && newKerbAuthority != NULL )
{
bcopy( authResult->fBufferData+sizeof(long), kerbPrinc, lLength );
if( cr = strstr( kerbPrinc, "\r\n" ) )
{
*cr = '\0';
}
char *atSign = strchr( kerbPrinc, '@' );
if( atSign )
{
strcpy( newKerbAuthority, kDSValueAuthAuthorityKerberosv5 );
strncat( newKerbAuthority, newPWSid, iTmpLen );
strcat( newKerbAuthority, ";" );
strcat( newKerbAuthority, kerbPrinc );
strcat( newKerbAuthority, ";" );
strcat( newKerbAuthority, atSign+1 );
strcat( newKerbAuthority, ";" );
strcat( newKerbAuthority, comma+1 );
strcat( newKerbAuthority, ":" );
strcat( newKerbAuthority, ipAddress );
}
}
if( kerbPrinc )
{
free( kerbPrinc );
kerbPrinc = NULL;
}
}
if( newAuthority )
{
char *pUserDN = GetDNForRecordName( pUsername, pContext, fLDAPSessionMgr, inRecordType );
if( pUserDN )
{
char *pValues[] = { newAuthority, newKerbAuthority, NULL };
siResult = SetAttributeValueForDN( pContext, pUserDN, inRecordType, kDSNAttrAuthenticationAuthority, pValues );
if( siResult == eDSNoErr )
{
char *pValues[] = { kDSValueNonCryptPasswordMarker, NULL };
SetAttributeValueForDN( pContext, pUserDN, inRecordType, kDS1AttrPassword, pValues );
}
free( pUserDN );
pUserDN = NULL;
}
}
}
if( newKerbAuthority != NULL )
{
free( newKerbAuthority );
newKerbAuthority = NULL;
}
if( newAuthority )
{
free( newAuthority );
newAuthority = NULL;
}
if( newPWSid != NULL )
{
free( newPWSid );
newPWSid = NULL;
}
if( pAuthType != NULL )
{
dsDataBufferDeAllocate( inNodeRef, pAuthType );
pAuthType = NULL;
}
}
free( pUserID );
pUserID = NULL;
}
if( authData != NULL )
{
dsDataBufferDeAllocate( inNodeRef, authData );
authData = NULL;
}
ldap_value_free( dn );
dn = NULL;
}
if( pUsername != NULL )
{
free( pUsername );
pUsername = NULL;
}
if( authResult )
{
dsDataBufferDeAllocate( inNodeRef, authResult );
authResult = NULL;
}
if( newAuthMethod )
{
dsDataBufferDeAllocate( inNodeRef, newAuthMethod );
newAuthMethod = NULL;
}
return siResult;
}
sInt32 CLDAPv3Plugin::DoAuthentication ( sDoDirNodeAuth *inData )
{
sInt32 siResult = eDSAuthFailed;
siResult = DoAuthenticationOnRecordType( (sDoDirNodeAuthOnRecordType *)inData, (const char *)kDSStdRecordTypeUsers );
return( siResult );
}
sInt32 CLDAPv3Plugin::DoAuthenticationOnRecordType ( sDoDirNodeAuthOnRecordType *inData, const char* inRecordType )
{
sInt32 siResult = eDSAuthFailed;
uInt32 uiAuthMethod = 0;
sLDAPContextData *pContext = nil;
sLDAPContinueData *pContinueData = NULL;
char* userName = NULL;
int userNameBuffLen = 0;
LDAPv3AuthAuthorityHandlerProc handlerProc = NULL;
try
{
pContext = (sLDAPContextData *)gLDAPContextTable->GetItemData( inData->fInNodeRef );
if ( pContext == nil ) throw( (sInt32)eDSInvalidNodeRef );
if ( inData->fInAuthStepData == nil ) throw( (sInt32)eDSNullAuthStepData );
if ( inRecordType == nil ) throw( (sInt32)eDSNullRecType );
if ( inData->fIOContinueData != NULL )
{
pContinueData = (sLDAPContinueData *)inData->fIOContinueData;
if ( gLDAPContinueTable->VerifyItem( pContinueData ) == false )
{
throw( (sInt32)eDSInvalidContinueData );
}
if ( eDSInvalidContinueData == nil ) throw( (sInt32)(pContinueData->fAuthHandlerProc) );
handlerProc = (LDAPv3AuthAuthorityHandlerProc)(pContinueData->fAuthHandlerProc);
if (handlerProc != NULL)
{
siResult = (handlerProc)(inData->fInNodeRef, inData->fInAuthMethod, pContext,
&pContinueData, inData->fInAuthStepData,
inData->fOutAuthStepDataResponse,
inData->fInDirNodeAuthOnlyFlag,
pContinueData->fAuthAuthorityData, NULL,
fLDAPSessionMgr, inRecordType);
}
}
else
{
unsigned long idx = 0;
unsigned long aaCount = 0;
char **aaArray;
if (inData->fInAuthMethod != nil)
{
DBGLOG1( kLogPlugin, "CLDAPv3Plugin: DoAuthenticationOnRecordType - Attempting use of authentication method %s", inData->fInAuthMethod->fBufferData );
}
siResult = dsGetAuthMethodEnumValue( inData->fInAuthMethod, &uiAuthMethod );
if ( ( siResult != eDSNoErr ) && ( siResult != eDSAuthMethodNotSupported ) )
throw(siResult);
if ( ( siResult == eDSNoErr) && ( uiAuthMethod == kAuth2WayRandom ) )
{
if ( inData->fInAuthStepData->fBufferLength > inData->fInAuthStepData->fBufferSize ) throw( (sInt32)eDSInvalidBuffFormat );
userName = (char*)calloc( inData->fInAuthStepData->fBufferLength + 1, 1 );
strncpy( userName, inData->fInAuthStepData->fBufferData, inData->fInAuthStepData->fBufferLength );
}
else if ( ( siResult == eDSNoErr) && ( uiAuthMethod == kAuthGetPolicy ) )
{
siResult = GetUserNameFromAuthBuffer( inData->fInAuthStepData, 3, &userName, &userNameBuffLen );
if ( siResult != eDSNoErr ) throw( siResult );
}
else
{
siResult = GetUserNameFromAuthBuffer( inData->fInAuthStepData, 1, &userName, &userNameBuffLen );
if ( siResult != eDSNoErr ) throw( siResult );
}
siResult = GetAuthAuthority( pContext,
userName,
userNameBuffLen,
fLDAPSessionMgr,
&aaCount,
&aaArray, inRecordType );
if ( siResult == eDSNoErr )
{
bool bLoopAll = IsWriteAuthRequest( uiAuthMethod );
bool bIsSecondary = false;
char* aaVersion = NULL;
char* aaTag = NULL;
char* aaData = NULL;
siResult = eDSAuthMethodNotSupported;
map<string, LDAPv3AuthTagStruct> authMethods;
for( idx = 0; idx < aaCount; idx++ )
{
if( aaArray[idx] )
{
if( ParseAuthAuthority(aaArray[idx], &aaVersion, &aaTag, &aaData) == eDSNoErr )
{
if( aaTag )
{
authMethods.insert( make_pair(string(aaTag), LDAPv3AuthTagStruct(aaVersion,aaData)) );
free( aaTag );
aaTag = NULL;
}
if( aaVersion )
{
free( aaVersion );
aaVersion = NULL;
}
if( aaData )
{
free( aaData );
aaData = NULL;
}
}
free( aaArray[idx] );
aaArray[idx] = NULL;
}
}
map<string,LDAPv3AuthTagStruct>::iterator authIterator = authMethods.begin();
LDAPv3AuthTagStruct *kerbAuthAuthority = NULL;
map<string,LDAPv3AuthTagStruct>::iterator kerbIterator = authMethods.find(string(kDSTagAuthAuthorityKerberosv5));
if( kerbIterator != authMethods.end() )
{
kerbAuthAuthority = &(kerbIterator->second);
}
while ( authIterator != authMethods.end() &&
(siResult == eDSAuthMethodNotSupported || (bLoopAll && siResult == eDSNoErr)) )
{
LDAPv3AuthTagStruct authData = authIterator->second;
handlerProc = GetLDAPv3AuthAuthorityHandler( authIterator->first.c_str() );
if (handlerProc != NULL)
{
siResult = (handlerProc)(inData->fInNodeRef, inData->fInAuthMethod, pContext,
&pContinueData,
inData->fInAuthStepData,
inData->fOutAuthStepDataResponse,
inData->fInDirNodeAuthOnlyFlag,(char *) authData.authData.c_str(), (char *)(kerbAuthAuthority ? kerbAuthAuthority->authData.c_str() : NULL),
fLDAPSessionMgr, inRecordType);
if ( siResult == eDSNoErr )
{
if ( pContinueData != NULL )
{
pContinueData->fAuthHandlerProc = (void*)handlerProc;
pContinueData->fAuthAuthorityData = (char *)authData.authData.c_str();
break;
}
else
{
bIsSecondary = true;
}
}
}
else
{
siResult = eDSAuthMethodNotSupported;
}
++authIterator;
}
if( pContext->fPWSNodeRef != 0 &&
(uiAuthMethod == kAuthNewUser || uiAuthMethod == kAuthNewUserWithPolicy ) )
{
TryPWSPasswordSet( pContext->fPWSNodeRef, uiAuthMethod, pContext, inData->fInAuthStepData, inRecordType );
}
if ( bIsSecondary && siResult == eDSAuthMethodNotSupported )
siResult = eDSNoErr;
if (aaArray != NULL) {
free( aaArray );
aaArray = NULL;
}
}
else
{
if( pContext->fPWSNodeRef != 0 &&
(uiAuthMethod == kAuthSetPasswd || uiAuthMethod == kAuthSetPasswdAsRoot) )
{
siResult = TryPWSPasswordSet( pContext->fPWSNodeRef, uiAuthMethod, pContext, inData->fInAuthStepData, inRecordType );
}
if( siResult != eDSNoErr )
{
siResult = DoBasicAuth(inData->fInNodeRef,inData->fInAuthMethod, pContext,
&pContinueData, inData->fInAuthStepData,
inData->fOutAuthStepDataResponse,
inData->fInDirNodeAuthOnlyFlag, NULL, NULL,
fLDAPSessionMgr, inRecordType);
if (pContinueData != NULL && siResult == eDSNoErr)
{
pContinueData->fAuthHandlerProc = (void*)CLDAPv3Plugin::DoBasicAuth;
}
}
}
}
}
catch( sInt32 err )
{
siResult = err;
}
if ( siResult == eDSNoErr && uiAuthMethod == kAuthSetPasswdAsRoot && pContext->fLDAPNodeStruct->bAuthCallActive )
{
char *accountId = GetDNForRecordName ( userName, pContext, fLDAPSessionMgr, inRecordType );
if( accountId && strcmp( accountId, (char *)pContext->fLDAPNodeStruct->fLDAPUserName) == 0 )
{
char *password = NULL;
GetUserNameFromAuthBuffer( inData->fInAuthStepData, 2, &password );
pContext->fLDAPNodeStruct->updateCredentials( password, strlen(password), kDSStdAuthClearText );
fLDAPSessionMgr.CredentialChange( pContext->fLDAPNodeStruct, accountId );
DBGLOG( kLogPlugin, "CLDAPv3Plugin: DoAuthenticationOnRecordType - Updated session password" );
DSFreePassword( password );
}
DSFree( accountId );
}
DSFree(userName);
inData->fResult = siResult;
inData->fIOContinueData = pContinueData;
return( siResult );
}
bool CLDAPv3Plugin::IsWriteAuthRequest ( uInt32 uiAuthMethod )
{
switch ( uiAuthMethod )
{
case kAuthSetPasswd:
case kAuthSetPasswdAsRoot:
case kAuthChangePasswd:
return true;
default:
return false;
}
}
sInt32 CLDAPv3Plugin::DoKerberosAuth( tDirNodeReference inNodeRef,
tDataNodePtr inAuthMethod,
sLDAPContextData* inContext,
sLDAPContinueData** inOutContinueData,
tDataBufferPtr inAuthData,
tDataBufferPtr outAuthData,
bool inAuthOnly,
char* inAuthAuthorityData,
char* inKerberosId,
CLDAPNode& inLDAPSessionMgr,
const char *inRecordType )
{
sInt32 result = eDSAuthFailed;
krb5_creds credentials;
krb5_context krbContext = NULL;
krb5_principal principal = NULL;
krb5_get_init_creds_opt options;
char *pKerberosID = NULL;
char *pPassword = NULL;
unsigned long uiAuthMethod = 0;
DBGLOG( kLogPlugin, "CLDAPv3Plugin: DoKerberosAuth::" );
if ( inAuthOnly == false )
{
result = eDSAuthMethodNotSupported;
}
else if ( inAuthData->fBufferData != NULL )
{
DBGLOG1( kLogPlugin, "CLDAPv3Plugin: DoKerberosAuth - Attempting use of authentication method %s", inAuthMethod->fBufferData );
if( NULL == pKerberosID )
GetUserNameFromAuthBuffer( inAuthData, 1, &pKerberosID );
else
pKerberosID = strdup( inKerberosId );
GetUserNameFromAuthBuffer( inAuthData, 2, &pPassword );
if( pKerberosID != NULL && pPassword != NULL )
{
gLDAPKerberosMutex->Wait();
result = dsGetAuthMethodEnumValue( inAuthMethod, &uiAuthMethod );
if ( eDSNoErr == result )
{
switch( uiAuthMethod )
{
case kAuthNativeClearTextOK:
case kAuthClearText:
case kAuthNativeNoClearText:
case kAuthCrypt:
result = krb5_init_context( &krbContext );
if( 0 == result )
result = krb5_parse_name( krbContext, inKerberosId, &principal );
bzero( &credentials, sizeof(credentials) );
if( 0 == result )
{
krb5_get_init_creds_opt_init( &options );
krb5_get_init_creds_opt_set_tkt_life( &options, 30 );
krb5_get_init_creds_opt_set_address_list( &options, NULL );
result = krb5_get_init_creds_password( krbContext, &credentials, principal, pPassword, NULL, 0, 0, NULL, &options );
}
if( 0 != result ||
(0 == result && (credentials.ticket_flags & TKT_FLG_PRE_AUTH) == 0) )
{
result = eDSAuthFailed;
}
krb5_free_principal( krbContext, principal );
krb5_free_cred_contents( krbContext, &credentials );
krb5_free_context( krbContext );
break;
case kAuthChangePasswd:
default:
result = eDSAuthMethodNotSupported;
break;
}
}
gLDAPKerberosMutex->Signal();
}
else
{
result = eDSAuthParameterError;
}
}
else
{
result = eDSNullDataBuff;
}
DSFree( pKerberosID );
DSFreePassword( pPassword );
return result;
}
sInt32 CLDAPv3Plugin::DoPasswordServerAuth(
tDirNodeReference inNodeRef,
tDataNodePtr inAuthMethod,
sLDAPContextData* inContext,
sLDAPContinueData** inOutContinueData,
tDataBufferPtr inAuthData,
tDataBufferPtr outAuthData,
bool inAuthOnly,
char* inAuthAuthorityData,
char* inKerberosId,
CLDAPNode& inLDAPSessionMgr,
const char *inRecordType )
{
sInt32 result = eDSAuthFailed;
sInt32 error;
uInt32 authMethod;
char *serverAddr;
char *uidStr = NULL;
long uidStrLen;
tDataBufferPtr authDataBuff = NULL;
tDataBufferPtr authDataBuffTemp = NULL;
char *nodeName = NULL;
char *userName = NULL;
char *accountId = NULL;
char *password = NULL;
sLDAPContinueData *pContinue = NULL;
tContextData continueData = NULL;
unsigned long aaCount = 0;
char **aaArray;
if ( !inAuthAuthorityData || *inAuthAuthorityData == '\0' )
return eDSAuthParameterError;
try
{
serverAddr = strchr( inAuthAuthorityData, ':' );
if ( serverAddr )
{
uidStrLen = serverAddr - inAuthAuthorityData;
uidStr = (char *) calloc(1, uidStrLen+1);
if ( uidStr == nil ) throw( (sInt32)eMemoryError );
strncpy( uidStr, inAuthAuthorityData, uidStrLen );
serverAddr++;
DBGLOG( kLogPlugin, "CLDAPv3Plugin: DoPasswordServerAuth::" );
if (inAuthMethod != nil)
{
DBGLOG1( kLogPlugin, "CLDAPv3Plugin: Attempting use of authentication method %s", inAuthMethod->fBufferData );
}
error = dsGetAuthMethodEnumValue( inAuthMethod, &authMethod );
switch( authMethod )
{
case kAuth2WayRandom:
if ( inOutContinueData == nil )
throw( (sInt32)eDSNullParameter );
if ( *inOutContinueData == nil )
{
pContinue = (sLDAPContinueData *)::calloc( 1, sizeof( sLDAPContinueData ) );
gLDAPContinueTable->AddItem( pContinue, inNodeRef );
authDataBuff = ::dsDataBufferAllocatePriv( uidStrLen + 1 );
if ( authDataBuff == nil ) throw ( (sInt32)eMemoryError );
strcpy( authDataBuff->fBufferData, uidStr );
authDataBuff->fBufferLength = uidStrLen;
}
else
{
pContinue = *inOutContinueData;
if ( gLDAPContinueTable->VerifyItem( pContinue ) == false )
throw( (sInt32)eDSInvalidContinueData );
}
break;
case kAuthSetPasswd:
case kAuthSetPolicy:
{
char* aaVersion = NULL;
char* aaTag = NULL;
char* aaData = NULL;
unsigned int idx;
sInt32 lookupResult;
char* endPtr = NULL;
error = GetUserNameFromAuthBuffer( inAuthData, 3, &userName );
if ( error != eDSNoErr ) throw( error );
error = GetAuthAuthority( inContext,
userName,
0,
inLDAPSessionMgr,
&aaCount,
&aaArray,
inRecordType );
if ( error != eDSNoErr ) throw( (sInt32)eDSAuthFailed );
lookupResult = eDSAuthFailed;
for ( idx = 0; idx < aaCount && lookupResult == eDSAuthFailed; idx++ )
{
error = ParseAuthAuthority( aaArray[idx], &aaVersion, &aaTag, &aaData );
if ( aaArray[idx] ) {
free( aaArray[idx] );
aaArray[idx] = NULL;
}
if ( error != eDSNoErr )
lookupResult = eParameterError;
if ( error == eDSNoErr && strcmp(aaTag, kDSTagAuthAuthorityPasswordServer) == 0 )
{
endPtr = strchr( aaData, ':' );
if ( endPtr == NULL )
{
lookupResult = eParameterError;
}
else
{
*endPtr = '\0';
lookupResult = eDSNoErr;
}
}
DSFreeString(aaVersion);
DSFreeString(aaTag);
if (lookupResult != eDSNoErr) {
DSFreeString(aaData);
}
}
if ( lookupResult != eDSNoErr ) throw( (sInt32)eDSAuthFailed );
error = RepackBufferForPWServer( inAuthData, uidStr, 1, &authDataBuffTemp );
if ( error != eDSNoErr ) throw( error );
error = RepackBufferForPWServer( authDataBuffTemp, aaData, 3, &authDataBuff );
DSFreeString(aaData);
if ( error != eDSNoErr ) throw( error );
}
break;
case kAuthNTSessionKey:
{
char* aaVersion = NULL;
char* aaTag = NULL;
char* aaData = NULL;
unsigned int idx;
sInt32 lookupResult;
char* endPtr = NULL;
error = GetUserNameFromAuthBuffer( inAuthData, 4, &userName );
if ( error != eDSNoErr ) throw( error );
if ( !DSIsStringEmpty(userName) )
{
error = GetAuthAuthority( inContext,
userName,
0,
inLDAPSessionMgr,
&aaCount,
&aaArray,
inRecordType );
if ( error != eDSNoErr ) throw( (sInt32)eDSAuthFailed );
lookupResult = eDSAuthFailed;
for ( idx = 0; idx < aaCount && lookupResult == eDSAuthFailed; idx++ )
{
error = ParseAuthAuthority( aaArray[idx], &aaVersion, &aaTag, &aaData );
if ( aaArray[idx] ) {
free( aaArray[idx] );
aaArray[idx] = NULL;
}
if ( error != eDSNoErr )
lookupResult = eParameterError;
if ( error == eDSNoErr && strcmp(aaTag, kDSTagAuthAuthorityPasswordServer) == 0 )
{
endPtr = strchr( aaData, ':' );
if ( endPtr == NULL )
{
lookupResult = eParameterError;
}
else
{
*endPtr = '\0';
lookupResult = eDSNoErr;
}
}
DSFreeString(aaVersion);
DSFreeString(aaTag);
if (lookupResult != eDSNoErr) {
DSFreeString(aaData);
}
}
if ( lookupResult != eDSNoErr ) throw( (sInt32)eDSAuthFailed );
error = RepackBufferForPWServer( inAuthData, uidStr, 1, &authDataBuffTemp );
if ( error != eDSNoErr ) throw( error );
error = RepackBufferForPWServer( authDataBuffTemp, aaData, 4, &authDataBuff );
DSFreeString(aaData);
if ( error != eDSNoErr ) throw( error );
}
else
{
error = RepackBufferForPWServer( inAuthData, uidStr, 1, &authDataBuff );
if ( error != eDSNoErr ) throw( error );
}
}
break;
case kAuthGetPolicy:
{
char* aaVersion = NULL;
char* aaTag = NULL;
char* aaData = NULL;
unsigned int idx;
sInt32 lookupResult;
char* endPtr = NULL;
error = GetUserNameFromAuthBuffer( inAuthData, 1, &userName );
if ( error != eDSNoErr ) throw( error );
error = RepackBufferForPWServer( inAuthData, uidStr, 3, &authDataBuffTemp );
if ( error != eDSNoErr ) throw( error );
if ( userName[0] != '\0' )
{
error = GetAuthAuthority( inContext,
userName,
0,
inLDAPSessionMgr,
&aaCount,
&aaArray,
inRecordType );
if ( error != eDSNoErr ) throw( (sInt32)eDSAuthFailed );
lookupResult = eDSAuthFailed;
for ( idx = 0; idx < aaCount && lookupResult == eDSAuthFailed; idx++ )
{
error = ParseAuthAuthority( aaArray[idx], &aaVersion, &aaTag, &aaData );
if ( aaArray[idx] ) {
free( aaArray[idx] );
aaArray[idx] = NULL;
}
if ( error != eDSNoErr )
lookupResult = eParameterError;
if ( error == eDSNoErr && strcmp(aaTag, kDSTagAuthAuthorityPasswordServer) == 0 )
{
endPtr = strchr( aaData, ':' );
if ( endPtr == NULL )
{
lookupResult = eParameterError;
}
else
{
*endPtr = '\0';
lookupResult = eDSNoErr;
}
}
DSFreeString(aaVersion);
DSFreeString(aaTag);
if (lookupResult != eDSNoErr) {
DSFreeString(aaData);
}
}
if ( lookupResult != eDSNoErr ) throw( (sInt32)eDSAuthFailed );
error = RepackBufferForPWServer( authDataBuffTemp, aaData, 1, &authDataBuff );
if ( error != eDSNoErr ) throw( error );
DSFreeString(aaData);
}
else
{
error = RepackBufferForPWServer( authDataBuffTemp, uidStr, 1, &authDataBuff );
if ( error != eDSNoErr ) throw( error );
}
}
break;
case kAuthClearText:
case kAuthNativeClearTextOK:
case kAuthNativeNoClearText:
case kAuthNewUser:
case kAuthNewUserWithPolicy:
{
tDataListPtr dataList = dsAuthBufferGetDataListAllocPriv(inAuthData);
if (dataList != NULL)
{
userName = dsDataListGetNodeStringPriv(dataList, 1);
password = dsDataListGetNodeStringPriv(dataList, 2);
dsDataListDeallocatePriv(dataList);
free(dataList);
dataList = NULL;
}
}
default:
error = RepackBufferForPWServer( inAuthData, uidStr, 1, &authDataBuff );
if ( error != eDSNoErr ) throw( error );
}
if ( inContext->fPWSRef == 0 )
{
error = ::dsOpenDirService( &inContext->fPWSRef );
if ( error != eDSNoErr ) throw( error );
}
if ( inContext->fPWSNodeRef == 0 )
{
nodeName = (char *)calloc(1,strlen(serverAddr)+17);
if ( nodeName == nil ) throw ( (sInt32)eMemoryError );
sprintf( nodeName, "/PasswordServer/%s", serverAddr );
error = PWOpenDirNode( inContext->fPWSRef, nodeName, &inContext->fPWSNodeRef );
if ( error != eDSNoErr ) throw( (sInt32)eDSAuthServerError );
}
if ( pContinue )
continueData = pContinue->fPassPlugContinueData;
result = dsDoDirNodeAuth( inContext->fPWSNodeRef, inAuthMethod, inAuthOnly,
authDataBuff, outAuthData, &continueData );
if ( result == eDSAuthNoAuthServerFound || result == eDSAuthServerError )
{
result = PWSetReplicaData( inContext, uidStr, inLDAPSessionMgr );
if ( result == eDSNoErr )
result = dsDoDirNodeAuth( inContext->fPWSNodeRef, inAuthMethod, inAuthOnly,
authDataBuff, outAuthData, &continueData );
}
if ( pContinue )
pContinue->fPassPlugContinueData = continueData;
if ( authMethod == kAuthNewUser || authMethod == kAuthNewUserWithPolicy )
{
if ( outAuthData->fBufferLength > sizeof(unsigned long) )
{
if ( inContext->fPWSUserID != NULL ) {
free( inContext->fPWSUserID );
inContext->fPWSUserID = NULL;
}
inContext->fPWSUserIDLength = *((unsigned long *)outAuthData->fBufferData);
inContext->fPWSUserID = (char *) malloc( inContext->fPWSUserIDLength + 1 );
if ( inContext->fPWSUserID == NULL ) throw( (sInt32)eMemoryError );
strlcpy( inContext->fPWSUserID, outAuthData->fBufferData + sizeof(unsigned long), inContext->fPWSUserIDLength + 1 );
}
}
if ( (result == eDSNoErr) && (inAuthOnly == false) && (userName != NULL) && (password != NULL) )
{
accountId = GetDNForRecordName ( userName, inContext, inLDAPSessionMgr, inRecordType );
if( accountId ) {
result = inLDAPSessionMgr.AuthOpen( accountId,
inKerberosId,
password,
strlen(password),
kDSStdAuthClearText,
&(inContext->fLDAPNodeStruct) );
if( result == eDSCannotAccessSession )
{
result = eDSAuthMasterUnreachable;
}
}
}
}
}
catch(sInt32 err )
{
result = err;
}
catch( ... )
{
result = eDSAuthFailed;
}
if ( nodeName )
free( nodeName );
if ( uidStr != NULL )
{
free( uidStr );
uidStr = NULL;
}
if ( userName != NULL )
{
free( userName );
userName = NULL;
}
if ( password != NULL )
{
bzero(password, strlen(password));
free( password );
password = NULL;
}
if ( accountId != NULL )
{
free( accountId );
accountId = NULL;
}
if ( authDataBuff )
dsDataBufferDeallocatePriv( authDataBuff );
if ( authDataBuffTemp )
dsDataBufferDeallocatePriv( authDataBuffTemp );
return( result );
}
sInt32 CLDAPv3Plugin::DoBasicAuth(
tDirNodeReference inNodeRef,
tDataNodePtr inAuthMethod,
sLDAPContextData* inContext,
sLDAPContinueData** inOutContinueData,
tDataBufferPtr inAuthData,
tDataBufferPtr outAuthData,
bool inAuthOnly,
char* inAuthAuthorityData,
char* inKerberosId,
CLDAPNode& inLDAPSessionMgr,
const char *inRecordType )
{
sInt32 siResult = noErr;
UInt32 uiAuthMethod = 0;
try
{
DBGLOG( kLogPlugin, "CLDAPv3Plugin: DoBasicAuth::" );
if (inAuthMethod != nil)
{
DBGLOG1( kLogPlugin, "CLDAPv3Plugin: DoBasicAuth - Attempting use of authentication method %s", inAuthMethod->fBufferData );
}
siResult = dsGetAuthMethodEnumValue( inAuthMethod, &uiAuthMethod );
if ( siResult == noErr )
{
switch( uiAuthMethod )
{
case kAuthSetPolicy:
siResult = eDSAuthMethodNotSupported;
break;
case kAuthCrypt:
case kAuthNativeNoClearText:
siResult = DoUnixCryptAuth( inContext, inAuthData, inLDAPSessionMgr, inRecordType );
if( siResult == eDSAuthFailedClearTextOnly )
{
sLDAPConfigData *pConfig = gpConfigFromXML->ConfigWithNodeNameLock( inContext->fNodeName );
if( pConfig != nil )
{
if( pConfig->bIsSSL )
{
siResult = DoClearTextAuth( inContext, inAuthData, inKerberosId, inAuthOnly, inLDAPSessionMgr, inRecordType );
}
gpConfigFromXML->ConfigUnlock( pConfig );
}
}
break;
case kAuthNativeClearTextOK:
if ( inAuthOnly == true )
{
siResult = DoUnixCryptAuth( inContext, inAuthData, inLDAPSessionMgr, inRecordType );
if ( siResult == eDSNoErr )
{
if ( outAuthData->fBufferSize > ::strlen( kDSStdAuthCrypt ) )
{
::strcpy( outAuthData->fBufferData, kDSStdAuthCrypt );
}
}
}
if ( (siResult != eDSNoErr) || (inAuthOnly == false) )
{
siResult = DoClearTextAuth( inContext, inAuthData, inKerberosId, inAuthOnly, inLDAPSessionMgr, inRecordType );
if ( siResult == eDSNoErr )
{
if ( outAuthData->fBufferSize > ::strlen( kDSStdAuthClearText ) )
{
::strcpy( outAuthData->fBufferData, kDSStdAuthClearText );
}
}
}
break;
case kAuthClearText:
siResult = DoClearTextAuth( inContext, inAuthData, inKerberosId, inAuthOnly, inLDAPSessionMgr, inRecordType );
if ( siResult == eDSNoErr )
{
if ( outAuthData->fBufferSize > ::strlen( kDSStdAuthClearText ) )
{
::strcpy( outAuthData->fBufferData, kDSStdAuthClearText );
}
}
break;
case kAuthSetPasswd:
siResult = DoSetPassword( inContext, inAuthData, inKerberosId, inLDAPSessionMgr, inRecordType );
break;
case kAuthSetPasswdAsRoot:
siResult = DoSetPasswordAsRoot( inContext, inAuthData, inKerberosId, inLDAPSessionMgr, inRecordType );
break;
case kAuthChangePasswd:
siResult = DoChangePassword( inContext, inAuthData, inKerberosId, inLDAPSessionMgr, inRecordType );
break;
default:
siResult = eDSAuthMethodNotSupported;
break;
}
}
}
catch ( sInt32 err )
{
siResult = err;
}
return( siResult );
}
sInt32 CLDAPv3Plugin::DoSetPassword ( sLDAPContextData *inContext, tDataBuffer *inAuthData, char *inKerberosId,
CLDAPNode& inLDAPSessionMgr, const char *inRecordType )
{
sInt32 siResult = eDSAuthFailed;
char *pData = nil;
char *userName = nil;
uInt32 userNameLen = 0;
char *userPwd = nil;
uInt32 userPwdLen = 0;
char *rootName = nil;
uInt32 rootNameLen = 0;
char *rootPwd = nil;
uInt32 rootPwdLen = 0;
uInt32 offset = 0;
uInt32 buffSize = 0;
uInt32 buffLen = 0;
char *accountId = nil;
try
{
if ( inContext == nil ) throw( (sInt32)eDSAuthFailed );
if ( inAuthData == nil ) throw( (sInt32)eDSNullAuthStepData );
pData = inAuthData->fBufferData;
buffSize = inAuthData->fBufferSize;
buffLen = inAuthData->fBufferLength;
if ( buffLen > buffSize ) throw( (sInt32)eDSInvalidBuffFormat );
if ( buffLen < 4 * sizeof( unsigned long ) + 2 ) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &userNameLen, pData, sizeof( unsigned long ) );
pData += sizeof( unsigned long );
offset += sizeof( unsigned long );
if (userNameLen == 0) throw( (sInt32)eDSInvalidBuffFormat );
if (offset + userNameLen > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
userName = (char *)::calloc( 1, userNameLen + 1 );
::memcpy( userName, pData, userNameLen );
pData += userNameLen;
offset += userNameLen;
if (offset + sizeof( unsigned long ) > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &userPwdLen, pData, sizeof( unsigned long ) );
pData += sizeof( unsigned long );
offset += sizeof( unsigned long );
if (offset + userPwdLen > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
if (userPwdLen < 1) throw( (sInt32)eDSAuthPasswordTooShort);
userPwd = (char *)::calloc( 1, userPwdLen + 1 );
::memcpy( userPwd, pData, userPwdLen );
pData += userPwdLen;
offset += userPwdLen;
if (offset + sizeof( unsigned long ) > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &rootNameLen, pData, sizeof( unsigned long ) );
pData += sizeof( unsigned long );
offset += sizeof( unsigned long );
if (rootNameLen == 0) throw( (sInt32)eDSInvalidBuffFormat );
if (rootNameLen > (buffSize - offset)) throw( (sInt32)eDSInvalidBuffFormat );
rootName = (char *)::calloc( 1, rootNameLen + 1 );
::memcpy( rootName, pData, rootNameLen );
pData += rootNameLen;
offset += rootNameLen;
if (sizeof( unsigned long ) > (buffSize - offset)) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &rootPwdLen, pData, sizeof( unsigned long ) );
pData += sizeof( unsigned long );
offset += sizeof( unsigned long );
if (rootPwdLen > (buffSize - offset)) throw( (sInt32)eDSInvalidBuffFormat );
rootPwd = (char *)::calloc( 1, rootPwdLen + 1 );
::memcpy( rootPwd, pData, rootPwdLen );
pData += rootPwdLen;
offset += rootPwdLen;
if (rootName)
{
accountId = GetDNForRecordName ( rootName, inContext, inLDAPSessionMgr, inRecordType );
}
sLDAPNodeStruct *origNodeStruct = inContext->fLDAPNodeStruct;
fLDAPSessionMgr.LockSession( inContext );
origNodeStruct->ChangeRefCountBy( 1 );
fLDAPSessionMgr.UnLockSession( inContext, false );
siResult = inLDAPSessionMgr.AuthOpen( accountId,
inKerberosId,
rootPwd,
strlen(rootPwd),
kDSStdAuthClearText,
&(inContext->fLDAPNodeStruct) );
if( siResult == eDSNoErr )
{
LDAP *aHost = inLDAPSessionMgr.LockSession(inContext);
int rc = exop_password_create( aHost, accountId, userPwd );
if( rc != LDAP_SUCCESS ) {
rc = standard_password_create( aHost, accountId, userPwd );
}
if( rc == LDAP_SUCCESS && strcmp(accountId, (char *)inContext->fLDAPNodeStruct->fLDAPUserName) == 0 )
{
inContext->fLDAPNodeStruct->updateCredentials( userPwd, strlen(userPwd), kDSStdAuthClearText );
inLDAPSessionMgr.CredentialChange( inContext->fLDAPNodeStruct, accountId );
DBGLOG( kLogPlugin, "CLDAPv3Plugin: DoSetPassword - Updated session password" );
}
if ( ( rc == LDAP_INSUFFICIENT_ACCESS ) || ( rc == LDAP_INVALID_CREDENTIALS ) ) {
siResult = eDSPermissionError;
}
else if ( rc == LDAP_NOT_SUPPORTED ) {
siResult = eDSAuthMethodNotSupported;
}
else if ( rc == LDAP_SUCCESS ) {
DBGLOG1( kLogPlugin, "CLDAPv3Plugin: DoSetPassword succeeded for %s", accountId );
siResult = eDSNoErr;
}
else
{
siResult = eDSAuthFailed;
}
inContext->fLDAPNodeStruct->ChangeRefCountBy( -1 ); inLDAPSessionMgr.UnLockSession(inContext);
inContext->fLDAPNodeStruct = origNodeStruct; }
else
{
inLDAPSessionMgr.LockSession( inContext );
origNodeStruct->ChangeRefCountBy( -1 ); inLDAPSessionMgr.UnLockSession( inContext, false );
siResult = eDSAuthFailed;
}
}
catch( sInt32 err )
{
siResult = err;
}
if ( userName != nil )
{
free( userName );
userName = nil;
}
if ( userPwd != nil )
{
bzero(userPwd, strlen(userPwd));
free( userPwd );
userPwd = nil;
}
if ( rootName != nil )
{
free( rootName );
rootName = nil;
}
if ( rootPwd != nil )
{
bzero(rootPwd, strlen(rootPwd));
free( rootPwd );
rootPwd = nil;
}
return( siResult );
}
sInt32 CLDAPv3Plugin::DoSetPasswordAsRoot ( sLDAPContextData *inContext, tDataBuffer *inAuthData, char *inKerberosId,
CLDAPNode& inLDAPSessionMgr, const char *inRecordType )
{
sInt32 siResult = eDSAuthFailed;
char *pData = nil;
char *userName = nil;
uInt32 userNameLen = 0;
char *newPasswd = nil;
uInt32 newPwdLen = 0;
uInt32 offset = 0;
uInt32 buffSize = 0;
uInt32 buffLen = 0;
char *accountId = nil;
int rc = LDAP_LOCAL_ERROR;
try
{
if ( inContext == nil ) throw( (sInt32)eDSAuthFailed );
if ( inAuthData == nil ) throw( (sInt32)eDSNullAuthStepData );
pData = inAuthData->fBufferData;
buffSize = inAuthData->fBufferSize;
buffLen = inAuthData->fBufferLength;
if ( buffLen > buffSize ) throw( (sInt32)eDSInvalidBuffFormat );
if ( buffLen < 2 * sizeof( unsigned long ) + 1 ) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &userNameLen, pData, sizeof( unsigned long ) );
pData += sizeof( unsigned long );
offset += sizeof( unsigned long );
if (userNameLen == 0) throw( (sInt32)eDSInvalidBuffFormat );
if (userNameLen > (buffSize - offset)) throw( (sInt32)eDSInvalidBuffFormat );
userName = (char *)::calloc( 1, userNameLen + 1 );
::memcpy( userName, pData, userNameLen );
pData += userNameLen;
offset += userNameLen;
if (offset + sizeof( unsigned long ) > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &newPwdLen, pData, sizeof( unsigned long ) );
pData += sizeof( unsigned long );
offset += sizeof( unsigned long );
if (newPwdLen > (buffSize - offset)) throw( (sInt32)eDSInvalidBuffFormat );
if (newPwdLen < 1) throw( (sInt32)eDSAuthPasswordTooShort);
newPasswd = (char *)::calloc( 1, newPwdLen + 1 );
::memcpy( newPasswd, pData, newPwdLen );
pData += newPwdLen;
offset += newPwdLen;
if (userName)
{
accountId = GetDNForRecordName ( userName, inContext, inLDAPSessionMgr, inRecordType );
}
LDAP *aHost = inLDAPSessionMgr.LockSession(inContext);
if (aHost != nil)
{
rc = exop_password_create( aHost, accountId, newPasswd );
if( rc != LDAP_SUCCESS )
rc = standard_password_create( aHost, accountId, newPasswd );
if( rc == LDAP_SUCCESS && strcmp( accountId, (char *)inContext->fLDAPNodeStruct->fLDAPUserName) == 0 )
{
inContext->fLDAPNodeStruct->updateCredentials( newPasswd, strlen(newPasswd), kDSStdAuthClearText );
inLDAPSessionMgr.CredentialChange( inContext->fLDAPNodeStruct, accountId );
DBGLOG( kLogPlugin, "CLDAPv3Plugin: DoSetPasswordAsRoot - Updated session password" );
}
}
else
{
rc = LDAP_LOCAL_ERROR;
}
inLDAPSessionMgr.UnLockSession(inContext);
if ( ( rc == LDAP_INSUFFICIENT_ACCESS ) || ( rc == LDAP_INVALID_CREDENTIALS ) )
{
siResult = eDSPermissionError;
}
else if ( rc == LDAP_NOT_SUPPORTED )
{
siResult = eDSAuthMethodNotSupported;
}
else if ( rc == LDAP_SUCCESS )
{
DBGLOG1( kLogPlugin, "CLDAPv3Plugin: DoSetPasswordAsRoot succeeded for %s", accountId );
siResult = eDSNoErr;
}
else
{
siResult = eDSAuthFailed;
}
}
catch( sInt32 err )
{
siResult = err;
}
if ( userName != nil )
{
free( userName );
userName = nil;
}
if ( newPasswd != nil )
{
bzero(newPasswd, strlen(newPasswd));
free( newPasswd );
newPasswd = nil;
}
return( siResult );
}
sInt32 CLDAPv3Plugin::DoChangePassword ( sLDAPContextData *inContext, tDataBuffer *inAuthData, char *inKerberosId,
CLDAPNode& inLDAPSessionMgr, const char *inRecordType )
{
sInt32 siResult = eDSAuthFailed;
char *pData = nil;
char *name = nil;
uInt32 nameLen = 0;
char *oldPwd = nil;
uInt32 OldPwdLen = 0;
char *newPwd = nil;
uInt32 newPwdLen = 0;
uInt32 offset = 0;
uInt32 buffSize = 0;
uInt32 buffLen = 0;
char *pathStr = nil;
char *accountId = nil;
try
{
if ( inContext == nil ) throw( (sInt32)eDSAuthFailed );
if ( inAuthData == nil ) throw( (sInt32)eDSNullAuthStepData );
pData = inAuthData->fBufferData;
buffSize = inAuthData->fBufferSize;
buffLen = inAuthData->fBufferLength;
if ( buffLen > buffSize ) throw( (sInt32)eDSInvalidBuffFormat );
if ( buffLen < 3 * sizeof( unsigned long ) + 1 ) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &nameLen, pData, sizeof( unsigned long ) );
pData += sizeof( unsigned long );
offset += sizeof( unsigned long );
if (nameLen == 0) throw( (sInt32)eDSInvalidBuffFormat );
if (offset + nameLen > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
name = (char *)::calloc( 1, nameLen + 1 );
::memcpy( name, pData, nameLen );
pData += nameLen;
offset += nameLen;
if (offset + sizeof( unsigned long ) > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &OldPwdLen, pData, sizeof( unsigned long ) );
pData += sizeof( unsigned long );
offset += sizeof( unsigned long );
if (offset + OldPwdLen > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
oldPwd = (char *)::calloc( 1, OldPwdLen + 1 );
::memcpy( oldPwd, pData, OldPwdLen );
pData += OldPwdLen;
offset += OldPwdLen;
if (offset + sizeof( unsigned long ) > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &newPwdLen, pData, sizeof( unsigned long ) );
pData += sizeof( unsigned long );
offset += sizeof( unsigned long );
if (offset + newPwdLen > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
if (newPwdLen < 1) throw( (sInt32)eDSAuthPasswordTooShort);
newPwd = (char *)::calloc( 1, newPwdLen + 1 );
::memcpy( newPwd, pData, newPwdLen );
pData += newPwdLen;
offset += newPwdLen;
if (name)
{
accountId = GetDNForRecordName ( name, inContext, inLDAPSessionMgr, inRecordType );
}
if (accountId == nil)
{
throw( (sInt32)eDSAuthFailed );
}
sLDAPNodeStruct *origNodeStruct = inContext->fLDAPNodeStruct;
inLDAPSessionMgr.LockSession( inContext );
origNodeStruct->ChangeRefCountBy( 1 );
inLDAPSessionMgr.UnLockSession( inContext, false );
siResult = inLDAPSessionMgr.AuthOpen( accountId,
inKerberosId,
oldPwd,
strlen(oldPwd),
kDSStdAuthClearText,
&(inContext->fLDAPNodeStruct) );
if( siResult == eDSNoErr ) {
LDAP *aHost = inLDAPSessionMgr.LockSession(inContext);
int rc = exop_password_create( aHost, accountId, newPwd );
if( rc != LDAP_SUCCESS ) {
rc = standard_password_create( aHost, accountId, newPwd );
if ( rc != LDAP_SUCCESS ) {
rc = standard_password_replace( aHost, accountId, oldPwd, newPwd );\
}
}
if( rc == LDAP_SUCCESS && strcmp( accountId, (char *)inContext->fLDAPNodeStruct->fLDAPUserName) == 0 )
{
inContext->fLDAPNodeStruct->updateCredentials( newPwd, strlen(newPwd), kDSStdAuthClearText );
inLDAPSessionMgr.CredentialChange( inContext->fLDAPNodeStruct, accountId );
DBGLOG( kLogPlugin, "CLDAPv3Plugin: DoChangePassword - Updated session password" );
}
if ( ( rc == LDAP_INSUFFICIENT_ACCESS ) || ( rc == LDAP_INVALID_CREDENTIALS ) )
{
siResult = eDSPermissionError;
}
else if ( rc == LDAP_NOT_SUPPORTED )
{
siResult = eDSAuthMethodNotSupported;
}
else if ( rc == LDAP_SUCCESS )
{
DBGLOG1( kLogPlugin, "CLDAPv3Plugin: DoChangePassword succeeded for %s", accountId );
siResult = eDSNoErr;
}
else
{
siResult = eDSAuthFailed;
}
inContext->fLDAPNodeStruct->ChangeRefCountBy( -1 ); inLDAPSessionMgr.UnLockSession(inContext);
inContext->fLDAPNodeStruct = origNodeStruct; }
else
{
fLDAPSessionMgr.LockSession( inContext );
origNodeStruct->ChangeRefCountBy( -1 ); fLDAPSessionMgr.UnLockSession( inContext, false );
siResult = eDSAuthFailed;
}
}
catch( sInt32 err )
{
siResult = err;
}
if ( pathStr != nil )
{
free( pathStr );
pathStr = nil;
}
if ( name != nil )
{
free( name );
name = nil;
}
if ( newPwd != nil )
{
bzero(newPwd, strlen(newPwd));
free( newPwd );
newPwd = nil;
}
if ( oldPwd != nil )
{
bzero(oldPwd, strlen(oldPwd));
free( oldPwd );
oldPwd = nil;
}
return( siResult );
}
sInt32 CLDAPv3Plugin::PWSetReplicaData( sLDAPContextData *inContext, const char *inAuthorityData, CLDAPNode& inLDAPSessionMgr )
{
sInt32 error = eDSNoErr;
bool bFoundWithHash = false;
long replicaListLen = 0;
char *rsaKeyPtr = NULL;
tDataBufferPtr replicaBuffer = NULL;
tDataBufferPtr replyBuffer = NULL;
unsigned long valueCount = 0;
char **valueData = NULL;
char recordName[64];
char hashStr[34];
rsaKeyPtr = strchr( inAuthorityData, ',' );
if ( rsaKeyPtr != NULL )
{
MD5_CTX ctx;
unsigned char pubKeyHash[MD5_DIGEST_LENGTH];
MD5_Init( &ctx );
rsaKeyPtr++;
MD5_Update( &ctx, rsaKeyPtr, strlen(rsaKeyPtr) );
MD5_Final( pubKeyHash, &ctx );
BinaryToHexConversion( pubKeyHash, MD5_DIGEST_LENGTH, hashStr );
sprintf( recordName, "passwordserver_%s", hashStr );
error = LookupAttribute( inContext, kDSStdRecordTypeConfig, recordName, kDS1AttrPasswordServerList, inLDAPSessionMgr, &valueCount, &valueData );
if ( error == eDSNoErr && valueCount > 0 )
bFoundWithHash = true;
}
if ( ! bFoundWithHash )
{
error = LookupAttribute( inContext, kDSStdRecordTypeConfig, "passwordserver", kDS1AttrPasswordServerList, inLDAPSessionMgr, &valueCount, &valueData );
if ( error != eDSNoErr )
return error;
}
try
{
if ( valueCount >= 1 )
{
replicaListLen = strlen( valueData[0] );
replicaBuffer = ::dsDataBufferAllocatePriv( replicaListLen + 1 );
if ( replicaBuffer == nil ) throw( (sInt32)eMemoryError );
replyBuffer = ::dsDataBufferAllocatePriv( 1 );
if ( replyBuffer == nil ) throw( (sInt32)eMemoryError );
replicaBuffer->fBufferLength = replicaListLen;
memcpy( replicaBuffer->fBufferData, valueData[0], replicaListLen );
error = dsDoPlugInCustomCall( inContext->fPWSNodeRef, 1, replicaBuffer, replyBuffer );
::dsDataBufferDeallocatePriv( replicaBuffer );
::dsDataBufferDeallocatePriv( replyBuffer );
}
}
catch( sInt32 catchErr )
{
error = catchErr;
}
if ( valueData != NULL )
{
for ( unsigned long index = 0; index < valueCount; index++ )
if ( valueData[index] != NULL )
free( valueData[index] );
free( valueData );
}
return error;
}
sInt32
CLDAPv3Plugin::GetAuthAuthority( sLDAPContextData *inContext, const char *userName, int inUserNameBufferLength,
CLDAPNode& inLDAPSessionMgr, unsigned long *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, inLDAPSessionMgr, outAuthCount, outAuthAuthority );
}
sInt32 CLDAPv3Plugin::LookupAttribute ( sLDAPContextData *inContext,
const char *inRecordType,
const char *inRecordName,
const char *inAttribute,
CLDAPNode& inLDAPSessionMgr,
unsigned long *outCount,
char **outData[] )
{
sInt32 siResult = eDSAuthFailed;
char *valueData = nil;
char *pLDAPRecType = nil;
char *queryFilter = nil;
LDAPMessage *result = nil;
LDAPMessage *entry = nil;
char *attr = nil;
BerElement *ber = nil;
int ldapReturnCode = 0;
int numRecTypes = 1;
bool bResultFound = false;
char **attrs = nil;
int searchTO = 0;
bool bOCANDGroup = false;
CFArrayRef OCSearchList = nil;
struct berval **berVal = nil;
ber_int_t scope = LDAP_SCOPE_SUBTREE;
sInt32 searchResult = eDSNoErr;
char *pLDAPAttrType = nil;
int ldapMsgId = 0;
try
{
if ( inContext == nil ) throw( (sInt32)eDSBadContextData );
if ( inRecordName == nil ) throw( (sInt32)eDSNullDataBuff );
if ( outData == nil ) throw( (sInt32)eDSNullParameter );
*outCount = 0;
*outData = nil;
attrs = MapAttrToLDAPTypeArray( inRecordType, inAttribute, inContext->fNodeName );
if ( attrs == nil ) throw( (sInt32)eDSInvalidAttributeType );
if (*attrs == nil) {
pLDAPAttrType = MapAttrToLDAPType( inRecordType, inAttribute, inContext->fNodeName, 1, false );
if (pLDAPAttrType != nil)
{
*outData = (char **)calloc( 2, sizeof(char *) );
(*outData)[0] = pLDAPAttrType;
siResult = eDSNoErr;
}
}
else {
DBGLOG1( kLogPlugin, "CLDAPv3Plugin: Attempting to get %s", inAttribute );
sLDAPConfigData *pConfig = gpConfigFromXML->ConfigWithNodeNameLock( inContext->fNodeName );
if (pConfig != nil)
{
searchTO = pConfig->fSearchTimeout;
gpConfigFromXML->ConfigUnlock( pConfig );
pConfig = NULL;
}
numRecTypes = 1;
bOCANDGroup = false;
if (OCSearchList != nil)
{
CFRelease(OCSearchList);
OCSearchList = nil;
}
pLDAPRecType = MapRecToLDAPType( inRecordType, inContext->fNodeName, numRecTypes, &bOCANDGroup, &OCSearchList, &scope );
if ( pLDAPRecType == nil ) throw( (sInt32)eDSInvalidRecordType );
while ( (pLDAPRecType != nil) && (!bResultFound) )
{
queryFilter = BuildLDAPQueryFilter( (char *)kDSNAttrRecordName,
inRecordName,
eDSExact,
inContext->fNodeName,
false,
inRecordType,
pLDAPRecType,
bOCANDGroup,
OCSearchList );
if ( queryFilter == nil ) throw( (sInt32)eDSNullParameter );
searchResult = DSDoRetrieval ( pLDAPRecType,
attrs,
inContext,
scope,
inLDAPSessionMgr,
queryFilter,
ldapReturnCode,
searchTO,
result,
bResultFound,
ldapMsgId );
if (queryFilter != nil)
{
delete (queryFilter);
queryFilter = nil;
}
if (pLDAPRecType != nil)
{
delete (pLDAPRecType);
pLDAPRecType = nil;
}
numRecTypes++;
bOCANDGroup = false;
if (OCSearchList != nil)
{
CFRelease(OCSearchList);
OCSearchList = nil;
}
pLDAPRecType = MapRecToLDAPType( inRecordType, inContext->fNodeName, numRecTypes, &bOCANDGroup, &OCSearchList, &scope );
}
if ( (bResultFound) &&
( ldapReturnCode == LDAP_RES_SEARCH_ENTRY ) )
{
LDAP *aHost = inLDAPSessionMgr.LockSession(inContext);
if (aHost != nil)
{
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 = (char *)malloc( berVal[idx]->bv_len + 1 );
if ( valueData == nil ) throw ( eMemoryError );
strncpy( valueData, berVal[idx]->bv_val, berVal[idx]->bv_len );
valueData[berVal[idx]->bv_len] = '\0';
DBGLOG1( 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 );
}
}
DSSearchCleanUp(aHost, ldapMsgId);
} inLDAPSessionMgr.UnLockSession(inContext);
} else
{
siResult = searchResult;
}
} }
catch ( sInt32 err )
{
DBGLOG1( kLogPlugin, "CLDAPv3Plugin: LookupAttribute error %l", err );
siResult = err;
}
if (OCSearchList != nil)
{
CFRelease(OCSearchList);
OCSearchList = nil;
}
if ( attrs != nil )
{
for ( int i = 0; attrs[i] != nil; ++i )
{
free( attrs[i] );
}
free( attrs );
attrs = nil;
}
if ( queryFilter != nil )
{
delete( queryFilter );
queryFilter = nil;
}
if ( result != nil )
{
ldap_msgfree( result );
result = nil;
}
return( siResult );
}
sInt32 CLDAPv3Plugin::ParseAuthAuthority ( const char * inAuthAuthority,
char ** outVersion,
char ** outAuthTag,
char ** outAuthData )
{
char* authAuthority = NULL;
char* current = NULL;
char* tempPtr = NULL;
sInt32 result = eDSAuthFailed;
if ( inAuthAuthority == NULL || outVersion == NULL
|| outAuthTag == NULL || outAuthData == NULL )
{
return eDSAuthFailed;
}
authAuthority = strdup(inAuthAuthority);
if (authAuthority == NULL)
{
return eDSAuthFailed;
}
current = authAuthority;
do {
tempPtr = strsep(¤t, ";");
if (tempPtr == NULL) break;
*outVersion = strdup(tempPtr);
tempPtr = strsep(¤t, ";");
if (tempPtr == NULL) break;
*outAuthTag = strdup(tempPtr);
if( strcmp(tempPtr, kDSTagAuthAuthorityKerberosv5) == 0 )
{
tempPtr = strsep(¤t, ";");
}
tempPtr = strsep(¤t, ";");
if (tempPtr == NULL) break;
*outAuthData = strdup(tempPtr);
result = eDSNoErr;
} while (false);
free(authAuthority);
authAuthority = NULL;
if (result != eDSNoErr)
{
DSFreeString(*outVersion);
DSFreeString(*outAuthTag);
DSFreeString(*outAuthData);
}
return result;
}
sInt32 CLDAPv3Plugin::DoUnixCryptAuth ( sLDAPContextData *inContext, tDataBuffer *inAuthData, CLDAPNode& inLDAPSessionMgr, const char *inRecordType )
{
sInt32 siResult = eDSAuthFailed;
char *pData = nil;
uInt32 offset = 0;
uInt32 buffSize = 0;
uInt32 buffLen = 0;
char *userName = nil;
sInt32 nameLen = 0;
char *pwd = nil;
sInt32 pwdLen = 0;
char *cryptPwd = nil;
char *pLDAPRecType = nil;
char *queryFilter = nil;
LDAPMessage *result = nil;
LDAPMessage *entry = nil;
char *attr = nil;
char **vals = nil;
BerElement *ber = nil;
int ldapReturnCode = 0;
int numRecTypes = 1;
bool bResultFound = false;
char **attrs = nil;
int searchTO = 0;
bool bOCANDGroup = false;
CFArrayRef OCSearchList = nil;
ber_int_t scope = LDAP_SCOPE_SUBTREE;
sInt32 searchResult = eDSNoErr;
int ldapMsgId = 0;
try
{
if ( inContext == nil ) throw( (sInt32)eDSBadContextData );
if ( inAuthData == nil ) throw( (sInt32)eDSNullDataBuff );
pData = inAuthData->fBufferData;
if ( pData == nil ) throw( (sInt32)eDSNullDataBuff );
buffSize = inAuthData->fBufferSize;
buffLen = inAuthData->fBufferLength;
if (buffLen > buffSize) throw( (sInt32)eDSInvalidBuffFormat );
if ( offset + (2 * sizeof( unsigned long ) + 1) > buffLen ) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &nameLen, pData, sizeof( unsigned long ) );
if (nameLen == 0) throw( (sInt32)eDSInvalidBuffFormat );
pData += sizeof( unsigned long );
offset += sizeof( unsigned long );
userName = (char *)::calloc(1, nameLen + 1);
if ( userName == nil ) throw( (sInt32)eMemoryError );
if ( offset + nameLen > buffLen ) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( userName, pData, nameLen );
pData += nameLen;
offset += nameLen;
if ( offset + sizeof( unsigned long ) > buffLen ) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &pwdLen, pData, sizeof( unsigned long ) );
pData += sizeof( unsigned long );
offset += sizeof( unsigned long );
pwd = (char *)::calloc(1, pwdLen + 1);
if ( pwd == nil ) throw( (sInt32)eMemoryError );
if ( offset + pwdLen > buffLen ) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( pwd, pData, pwdLen );
attrs = MapAttrToLDAPTypeArray( inRecordType, kDS1AttrPassword, inContext->fNodeName );
if( attrs == nil ) throw ( (sInt32)eDSAuthFailedClearTextOnly );
DBGLOG( kLogPlugin, "CLDAPv3Plugin: Attempting Crypt Authentication" );
sLDAPConfigData *pConfig = gpConfigFromXML->ConfigWithNodeNameLock( inContext->fNodeName );
if (pConfig != nil)
{
searchTO = pConfig->fSearchTimeout;
gpConfigFromXML->ConfigUnlock( pConfig );
pConfig = NULL;
}
numRecTypes = 1;
bOCANDGroup = false;
if (OCSearchList != nil)
{
CFRelease(OCSearchList);
OCSearchList = nil;
}
pLDAPRecType = MapRecToLDAPType( inRecordType, inContext->fNodeName, numRecTypes, &bOCANDGroup, &OCSearchList, &scope );
if ( pLDAPRecType == nil ) throw( (sInt32)eDSInvalidRecordType );
while ( (pLDAPRecType != nil) && (!bResultFound) )
{
queryFilter = BuildLDAPQueryFilter( (char *)kDSNAttrRecordName,
userName,
eDSExact,
inContext->fNodeName,
false,
inRecordType,
pLDAPRecType,
bOCANDGroup,
OCSearchList );
if ( queryFilter == nil ) throw( (sInt32)eDSNullParameter );
searchResult = DSDoRetrieval ( pLDAPRecType,
attrs,
inContext,
scope,
inLDAPSessionMgr,
queryFilter,
ldapReturnCode,
searchTO,
result,
bResultFound,
ldapMsgId );
if (queryFilter != nil)
{
delete (queryFilter);
queryFilter = nil;
}
if (pLDAPRecType != nil)
{
delete (pLDAPRecType);
pLDAPRecType = nil;
}
numRecTypes++;
bOCANDGroup = false;
if (OCSearchList != nil)
{
CFRelease(OCSearchList);
OCSearchList = nil;
}
pLDAPRecType = MapRecToLDAPType( inRecordType, inContext->fNodeName, numRecTypes, &bOCANDGroup, &OCSearchList, &scope );
}
if ( (bResultFound) &&
( ldapReturnCode == LDAP_RES_SEARCH_ENTRY ) )
{
LDAP *aHost = gLDAPv3Plugin->fLDAPSessionMgr.LockSession(inContext);
if (aHost != nil)
{
entry = ldap_first_entry( aHost, result );
if ( entry != nil )
{
attr = ldap_first_attribute( aHost, entry, &ber );
if ( attr != nil )
{
vals = ldap_get_values( aHost, entry, attr );
if ( vals != nil )
{
if ( vals[0] != nil )
{
cryptPwd = vals[0];
}
else
{
cryptPwd = (char *)""; }
if (::strncasecmp(cryptPwd,"{SMD5}",6) == 0)
{
cryptPwd = cryptPwd + 6;
if ( *cryptPwd != '\0' )
{
unsigned outlen;
int result;
unsigned char hashResult[MD5_DIGEST_LENGTH];
MD5_CTX ctx;
char targetStr[128];
result = sasl_decode64( cryptPwd, strlen(cryptPwd), targetStr, sizeof(targetStr), &outlen );
if ( result == SASL_OK )
{
MD5_Init( &ctx );
MD5_Update( &ctx, pwd, strlen( pwd ) );
MD5_Update( &ctx, targetStr + MD5_DIGEST_LENGTH, outlen - MD5_DIGEST_LENGTH );
MD5_Final( hashResult, &ctx );
if ( memcmp( hashResult, targetStr, MD5_DIGEST_LENGTH ) == 0 )
{
siResult = eDSNoErr;
}
bzero(hashResult, MD5_DIGEST_LENGTH);
}
}
}
else
{
if (::strncasecmp(cryptPwd,"{crypt}",7) == 0)
{
cryptPwd = cryptPwd + 7;
}
if (::strcmp(cryptPwd,"") != 0)
{
char salt[ 9 ];
char hashPwd[ 32 ];
salt[ 0 ] = cryptPwd[0];
salt[ 1 ] = cryptPwd[1];
salt[ 2 ] = '\0';
::memset( hashPwd, 0, 32 );
::strcpy( hashPwd, ::crypt( pwd, salt ) );
siResult = eDSAuthFailed;
if ( ::strcmp( hashPwd, cryptPwd ) == 0 )
{
siResult = eDSNoErr;
}
bzero(hashPwd, 32);
}
else {
if ( ::strcmp(pwd,"") == 0 )
{
siResult = eDSNoErr;
}
}
}
ldap_value_free( vals );
vals = nil;
}
ldap_memfree( attr );
attr = nil;
}
if ( ber != nil )
{
ber_free( ber, 0 );
}
}
DSSearchCleanUp(aHost, ldapMsgId);
} gLDAPv3Plugin->fLDAPSessionMgr.UnLockSession(inContext);
}
if ( result != nil )
{
ldap_msgfree( result );
result = nil;
}
}
catch ( sInt32 err )
{
DBGLOG1( kLogPlugin, "CLDAPv3Plugin: Crypt authentication error %l", err );
siResult = err;
}
if (OCSearchList != nil)
{
CFRelease(OCSearchList);
OCSearchList = nil;
}
if ( attrs != nil )
{
for ( int i = 0; attrs[i] != nil; ++i )
{
free( attrs[i] );
}
free( attrs );
attrs = nil;
}
if ( userName != nil )
{
free( userName );
userName = nil;
}
if ( pwd != nil )
{
bzero(pwd, strlen(pwd));
free( pwd );
pwd = nil;
}
if ( queryFilter != nil )
{
free( queryFilter );
queryFilter = nil;
}
if ( cryptPwd == nil )
{
siResult = eDSAuthFailedClearTextOnly;
}
return( siResult );
}
sInt32 CLDAPv3Plugin::DoClearTextAuth ( sLDAPContextData *inContext, tDataBuffer *inAuthData, char *inKerberosId, bool authCheckOnly, CLDAPNode& inLDAPSessionMgr, const char *inRecordType )
{
sInt32 siResult = eDSAuthFailed;
char *pData = nil;
char *userName = nil;
char *accountId = nil;
sInt32 nameLen = 0;
char *pwd = nil;
sInt32 pwdLen = 0;
try
{
if ( inContext == nil ) throw( (sInt32)eDSBadContextData );
if ( inAuthData == nil ) throw( (sInt32)eDSNullDataBuff );
pData = inAuthData->fBufferData;
if ( pData == nil ) throw( (sInt32)eDSNullDataBuff );
::memcpy( &nameLen, pData, sizeof( long ) );
if (nameLen > 0)
{
userName = (char *) calloc(1, nameLen + 1);
if ( userName == nil ) throw( (sInt32) eMemoryError );
pData += sizeof( long );
::memcpy( userName, pData, nameLen );
pData += nameLen;
}
::memcpy( &pwdLen, pData, sizeof( long ) );
if (pwdLen > 0)
{
pwd = (char *) calloc(1, pwdLen + 1);
if ( pwd == nil ) throw( (sInt32) eMemoryError );
pData += sizeof( long );
::memcpy( pwd, pData, pwdLen );
pData += pwdLen;
}
DBGLOG( kLogPlugin, "CLDAPv3Plugin: Attempting Cleartext Authentication" );
if (userName)
{
accountId = GetDNForRecordName ( userName, inContext, inLDAPSessionMgr, inRecordType );
}
if (accountId == nil)
{
throw( (sInt32)eDSAuthFailed );
}
if ((pwd != NULL) && (pwd[0] != '\0') && (nameLen != 0))
{
if (!authCheckOnly)
{
siResult = inLDAPSessionMgr.AuthOpen( accountId,
inKerberosId,
pwd,
strlen(pwd),
kDSStdAuthClearText,
&(inContext->fLDAPNodeStruct) );
if( siResult == eDSCannotAccessSession )
{
siResult = eDSAuthMasterUnreachable;
}
}
else {
siResult = inLDAPSessionMgr.SimpleAuth( inContext->fLDAPNodeStruct,
accountId,
pwd, strlen(pwd), inKerberosId );
}
}
}
catch ( sInt32 err )
{
DBGLOG1( kLogPlugin, "CLDAPv3Plugin: Cleartext authentication error %l", err );
siResult = err;
}
if ( accountId != nil )
{
free( accountId );
accountId = nil;
}
if ( userName != nil )
{
free( userName );
userName = nil;
}
if ( pwd != nil )
{
bzero(pwd, strlen(pwd));
free( pwd );
pwd = nil;
}
return( siResult );
}
char* CLDAPv3Plugin::GetDNForRecordName ( char* inRecName, sLDAPContextData *inContext, CLDAPNode& inLDAPSessionMgr, const char *inRecordType )
{
char *ldapDN = nil;
char *pLDAPRecType = nil;
char *queryFilter = nil;
LDAPMessage *result = nil;
int ldapReturnCode = 0;
int numRecTypes = 1;
bool bResultFound = false;
int searchTO = 0;
bool bOCANDGroup = false;
CFArrayRef OCSearchList = nil;
ber_int_t scope = LDAP_SCOPE_SUBTREE;
sInt32 searchResult = eDSNoErr;
int ldapMsgId = 0;
try
{
if ( inRecName == nil ) throw( (sInt32)eDSNullRecName );
if ( inContext == nil ) throw( (sInt32)eDSBadContextData );
sLDAPConfigData *pConfig = gpConfigFromXML->ConfigWithNodeNameLock( inContext->fNodeName );
if (pConfig != nil)
{
searchTO = pConfig->fSearchTimeout;
gpConfigFromXML->ConfigUnlock( pConfig );
pConfig = NULL;
}
numRecTypes = 1;
bOCANDGroup = false;
if (OCSearchList != nil)
{
CFRelease(OCSearchList);
OCSearchList = nil;
}
pLDAPRecType = MapRecToLDAPType( inRecordType, inContext->fNodeName, numRecTypes, &bOCANDGroup, &OCSearchList, &scope );
if ( pLDAPRecType == nil ) throw( (sInt32)eDSInvalidRecordType );
while ( (pLDAPRecType != nil) && (!bResultFound) )
{
queryFilter = BuildLDAPQueryFilter( (char *)kDSNAttrRecordName,
inRecName,
eDSExact,
inContext->fNodeName,
false,
inRecordType,
pLDAPRecType,
bOCANDGroup,
OCSearchList );
if ( queryFilter == nil ) throw( (sInt32)eDSNullParameter );
searchResult = DSDoRetrieval ( pLDAPRecType,
NULL,
inContext,
scope,
inLDAPSessionMgr,
queryFilter,
ldapReturnCode,
searchTO,
result,
bResultFound,
ldapMsgId );
if (queryFilter != nil)
{
delete (queryFilter);
queryFilter = nil;
}
if (pLDAPRecType != nil)
{
delete (pLDAPRecType);
pLDAPRecType = nil;
}
numRecTypes++;
bOCANDGroup = false;
if (OCSearchList != nil)
{
CFRelease(OCSearchList);
OCSearchList = nil;
}
pLDAPRecType = MapRecToLDAPType( inRecordType, inContext->fNodeName, numRecTypes, &bOCANDGroup, &OCSearchList, &scope );
}
if ( (bResultFound) &&
( ldapReturnCode == LDAP_RES_SEARCH_ENTRY ) )
{
LDAP *aHost = gLDAPv3Plugin->fLDAPSessionMgr.LockSession(inContext);
if (aHost != nil)
{
ldapDN = ldap_get_dn(aHost, result);
DSSearchCleanUp(aHost, ldapMsgId);
}
gLDAPv3Plugin->fLDAPSessionMgr.UnLockSession(inContext);
}
if ( result != nil )
{
ldap_msgfree( result );
result = nil;
}
}
catch ( sInt32 err )
{
ldapDN = nil;
}
if (OCSearchList != nil)
{
CFRelease(OCSearchList);
OCSearchList = nil;
}
if ( pLDAPRecType != nil )
{
delete( pLDAPRecType );
pLDAPRecType = nil;
}
if ( queryFilter != nil )
{
delete( queryFilter );
queryFilter = nil;
}
return( ldapDN );
}
sInt32 CLDAPv3Plugin::DoPlugInCustomCall ( sDoPlugInCustomCall *inData )
{
sInt32 siResult = eDSNoErr;
unsigned long aRequest = 0;
sLDAPContextData *pContext = nil;
sInt32 xmlDataLength = 0;
CFDataRef xmlData = nil;
unsigned long bufLen = 0;
AuthorizationRef authRef = 0;
tDataListPtr dataList = NULL;
char* userName = NULL;
char* password = NULL;
char* xmlString = NULL;
AuthorizationExternalForm blankExtForm;
bool verifyAuthRef = true;
try
{
if ( inData == nil ) throw( (sInt32)eDSNullParameter );
if ( inData->fInRequestData == nil ) throw( (sInt32)eDSNullDataBuff );
if ( inData->fInRequestData->fBufferData == nil ) throw( (sInt32)eDSEmptyBuffer );
pContext = (sLDAPContextData *)gLDAPContextTable->GetItemData( inData->fInNodeRef );
if ( pContext == nil ) throw( (sInt32)eDSBadContextData );
if ( strcmp(pContext->fNodeName,"LDAPv3 Configure") == 0 )
{
aRequest = inData->fInRequestCode;
bufLen = inData->fInRequestData->fBufferLength;
if ( aRequest != eDSCustomCallLDAPv3WriteServerMappings )
{
if ( bufLen < sizeof( AuthorizationExternalForm ) ) throw( (sInt32)eDSInvalidBuffFormat );
if ( pContext->fEffectiveUID == 0 ) {
bzero(&blankExtForm,sizeof(AuthorizationExternalForm));
if (memcmp(inData->fInRequestData->fBufferData,&blankExtForm,
sizeof(AuthorizationExternalForm)) == 0) {
verifyAuthRef = false;
}
}
if (verifyAuthRef) {
siResult = AuthorizationCreateFromExternalForm((AuthorizationExternalForm *)inData->fInRequestData->fBufferData,
&authRef);
if (siResult != errAuthorizationSuccess)
{
DBGLOG1( kLogPlugin, "CLDAPv3Plugin: AuthorizationCreateFromExternalForm returned error %d", siResult );
syslog( LOG_ALERT, "AuthorizationCreateFromExternalForm returned error %d", siResult );
throw( (sInt32)eDSPermissionError );
}
AuthorizationItem rights[] = { {"system.services.directory.configure", 0, 0, 0} };
AuthorizationItemSet rightSet = { sizeof(rights)/ sizeof(*rights), rights };
siResult = AuthorizationCopyRights(authRef, &rightSet, NULL,
kAuthorizationFlagExtendRights, NULL);
if (siResult != errAuthorizationSuccess)
{
DBGLOG1( kLogPlugin, "CLDAPv3Plugin: AuthorizationCopyRights returned error %d", siResult );
syslog( LOG_ALERT, "AuthorizationCopyRights returned error %d", siResult );
throw( (sInt32)eDSPermissionError );
}
}
}
switch( aRequest )
{
case eDSCustomCallLDAPv3WriteServerMappings:
dataList = dsAuthBufferGetDataListAllocPriv(inData->fInRequestData);
if ( dataList == nil ) throw( (sInt32)eDSInvalidBuffFormat );
if ( dsDataListGetNodeCountPriv(dataList) != 3 ) throw( (sInt32)eDSInvalidBuffFormat );
userName = dsDataListGetNodeStringPriv(dataList, 1);
if ( userName == nil ) throw( (sInt32)eDSInvalidBuffFormat );
if ( strlen(userName) < 1 ) throw( (sInt32)eDSInvalidBuffFormat );
password = dsDataListGetNodeStringPriv(dataList, 2);
if ( password == nil ) throw( (sInt32)eDSInvalidBuffFormat );
xmlString = dsDataListGetNodeStringPriv(dataList, 3);
if ( xmlString == nil ) throw( (sInt32)eDSInvalidBuffFormat );
xmlData = CFDataCreate(NULL,(UInt8*)xmlString,strlen(xmlString));
siResult = gpConfigFromXML->WriteServerMappings( userName, password, xmlData );
if (userName != nil)
{
free(userName);
userName = nil;
}
if (password != nil)
{
free(password);
password = nil;
}
if (xmlString != nil)
{
free(xmlString);
xmlString = nil;
}
break;
case eDSCustomCallLDAPv3ReadConfigSize:
if ( inData->fOutRequestResponse == nil ) throw( (sInt32)eDSNullDataBuff );
if ( inData->fOutRequestResponse->fBufferData == nil ) throw( (sInt32)eDSEmptyBuffer );
if ( inData->fOutRequestResponse->fBufferSize < sizeof( CFIndex ) ) throw( (sInt32)eDSInvalidBuffFormat );
if (gpConfigFromXML)
{
xmlData = gpConfigFromXML->CopyXMLConfig();
if (xmlData != 0)
{
*(CFIndex*)(inData->fOutRequestResponse->fBufferData) = CFDataGetLength(xmlData);
inData->fOutRequestResponse->fBufferLength = sizeof( CFIndex );
CFRelease( xmlData );
xmlData = 0;
}
}
break;
case eDSCustomCallLDAPv3ReadConfigData:
CFRange aRange;
if ( inData->fOutRequestResponse == nil ) throw( (sInt32)eDSNullDataBuff );
if ( inData->fOutRequestResponse->fBufferData == nil ) throw( (sInt32)eDSEmptyBuffer );
if (gpConfigFromXML)
{
xmlData = gpConfigFromXML->CopyXMLConfig();
if (xmlData != 0)
{
aRange.location = 0;
aRange.length = CFDataGetLength(xmlData);
if ( inData->fOutRequestResponse->fBufferSize < (unsigned int)aRange.length ) throw( (sInt32)eDSBufferTooSmall );
CFDataGetBytes( xmlData, aRange, (UInt8*)(inData->fOutRequestResponse->fBufferData) );
inData->fOutRequestResponse->fBufferLength = aRange.length;
CFRelease(xmlData);
xmlData = 0;
}
}
break;
case eDSCustomCallLDAPv3WriteConfigData:
{
CFPropertyListRef configPropertyList = NULL;
CFStringRef errorString = NULL;
xmlDataLength = (sInt32) bufLen - sizeof( AuthorizationExternalForm );
if ( xmlDataLength <= 0 ) throw( (sInt32)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 ) && CFDictionaryContainsValue( (CFDictionaryRef)configPropertyList, CFSTR(kXMLDHCPConfigArrayKey) ) )
{
CFDictionaryRemoveValue( (CFMutableDictionaryRef)configPropertyList, CFSTR(kXMLDHCPConfigArrayKey) );
CFRelease( xmlData );
xmlData = CFPropertyListCreateXMLData( kCFAllocatorDefault, configPropertyList);
}
CFRelease(configPropertyList);
configPropertyList = NULL;
}
}
if (gpConfigFromXML)
{
siResult = gpConfigFromXML->SetXMLConfig(xmlData);
Initialize();
}
CFRelease(xmlData);
break;
}
case eDSCustomCallLDAPv3Reinitialize:
fLDAPSessionMgr.RereadDefinedReplicas( pContext->fLDAPNodeStruct );
break;
case eDSCustomCallLDAPv3AddServerConfig:
xmlDataLength = (sInt32) bufLen - sizeof(AuthorizationExternalForm);
if ( xmlDataLength <= 0 ) throw( (sInt32)eDSInvalidBuffFormat );
xmlData = CFDataCreate(NULL, (UInt8 *)(inData->fInRequestData->fBufferData + sizeof(AuthorizationExternalForm)), xmlDataLength);
if (gpConfigFromXML)
{
siResult = gpConfigFromXML->AddToConfig(xmlData);
if (siResult == eDSNoErr)
{
Initialize();
}
}
CFRelease(xmlData);
break;
case eDSCustomCallLDAPv3NewServerDiscovery:
case eDSCustomCallLDAPv3NewServerDiscoveryNoDupes:
siResult = DoNewServerDiscovery( inData );
break;
case eDSCustomCallLDAPv3NewServerVerifySettings:
siResult = DoNewServerVerifySettings( inData );
break;
case eDSCustomCallLDAPv3NewServerGetConfig:
siResult = DoNewServerGetConfig( inData );
break;
case eDSCustomCallLDAPv3NewServerBind: case eDSCustomCallLDAPv3NewServerForceBind: siResult = DoNewServerBind( inData );
break;
case eDSCustomCallLDAPv3NewServerAddConfig:
siResult = DoNewServerSetup( inData );
break;
case eDSCustomCallLDAPv3UnbindServerConfig: case eDSCustomCallLDAPv3ForceUnbindServerConfig: case eDSCustomCallLDAPv3RemoveServerConfig: siResult = DoRemoveServer( inData );
break;
case eDSCustomCallLDAPv3NewServerBindOther: case eDSCustomCallLDAPv3NewServerForceBindOther: siResult = DoNewServerBind2( inData );
break;
default:
break;
}
}
else if( inData->fInRequestCode == eRecordDeleteAndCredentials )
{
sDeleteRecord tempStruct;
tempStruct.fInRecRef = *((tRecordReference *)inData->fInRequestData->fBufferData);
siResult = DeleteRecord( &tempStruct, true );
}
#define LDAPV3_PLUGIN_RECORD_BLAT 1
#if LDAPV3_PLUGIN_RECORD_BLAT
else if( inData->fInRequestCode == eRecordBlatAvailable ) {
if( inData->fOutRequestResponse->fBufferSize < 1 )
throw( (sInt32)eDSInvalidBuffFormat );
inData->fOutRequestResponse->fBufferLength = 1;
inData->fOutRequestResponse->fBufferData[0] = 1;
}
else if( inData->fInRequestCode == eRecordBlatCreateRecWithAttrs ) {
dsBool recordTypeAllocated = false;
dsBool recordNameAllocated = false;
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( (sInt32)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 != 0 )
recordType = CFStringGetCStringPtr( recordTypeCFString, kCFStringEncodingUTF8 );
if( recordType == NULL )
{
recordTypeAllocated = true;
CFIndex bufferSize = CFStringGetLength( recordTypeCFString ) * 2;
char* recordTypeCStr = (char*)calloc( bufferSize, sizeof( char ) );
if( !CFStringGetCString( recordTypeCFString, recordTypeCStr, bufferSize, kCFStringEncodingUTF8 ) )
throw( (sInt32)eDSInvalidBuffFormat );
recordType = recordTypeCStr;
}
recordDict = (CFDictionaryRef)CFDictionaryGetValue( bufferCFDict, CFSTR( "Attributes and Values" ) );
if( recordDict == NULL )
throw( (sInt32)eDSInvalidBuffFormat );
CFArrayRef recordNames = (CFArrayRef)CFDictionaryGetValue( recordDict, CFSTR( kDSNAttrRecordName ) );
if( recordNames == 0 )
throw( (sInt32)eDSInvalidBuffFormat );
CFStringRef recordNameCFString = (CFStringRef)CFArrayGetValueAtIndex( recordNames, 0 );
if( recordNameCFString == 0 )
throw( (sInt32)eDSInvalidBuffFormat );
if( recordNameCFString != 0 )
recordName = CFStringGetCStringPtr( recordNameCFString, kCFStringEncodingUTF8 );
if( recordName == NULL )
{
recordNameAllocated = true;
CFIndex bufferSize = CFStringGetLength( recordNameCFString ) * 2;
char* recordNameCStr = (char*)calloc( bufferSize, sizeof( char ) );
if( !CFStringGetCString( recordNameCFString, recordNameCStr, bufferSize, kCFStringEncodingUTF8 ) )
throw( (sInt32)eDSInvalidBuffFormat );
recordName = 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( (sInt32)siResult );
}
if( recordTypeAllocated )
free( (char*)recordType );
if( recordNameAllocated )
free( (char*)recordName );
}
else if( inData->fInRequestCode == eRecordBlatSetAttrs ) {
tRecordReference recordRef = 0;
CFDictionaryRef recordDict = 0;
{ CFDataRef bufferCFData = CFDataCreateWithBytesNoCopy( kCFAllocatorDefault, (const UInt8*)inData->fInRequestData->fBufferData,
inData->fInRequestData->fBufferLength, kCFAllocatorNull );
if( bufferCFData == NULL )
throw( (sInt32)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( (sInt32)eDSInvalidBuffFormat );
recordDict = (CFDictionaryRef)CFDictionaryGetValue( bufferCFDict, CFSTR( "Attributes and Values" ) );
if( recordDict == NULL )
throw( (sInt32)eDSInvalidBuffFormat );
CFRetain( recordDict );
CFRelease( bufferCFDict ); bufferCFDict = NULL;
}
if( ( recordRef != 0 ) && ( recordDict != 0 ) )
{
siResult = SetAttributes( recordRef, recordDict );
if( siResult != eDSNoErr )
throw( (sInt32)siResult );
}
CFRelease( recordDict ); }
#endif // LDAPV3_PLUGIN_RECORD_BLAT
}
catch ( sInt32 err )
{
siResult = err;
}
if (authRef != 0)
{
AuthorizationFree(authRef, 0);
authRef = 0;
}
return( siResult );
}
#pragma mark -
#pragma mark New Server Setup Utility Functions
LDAP *CLDAPv3Plugin::DoSimpleLDAPBind( char *pServer, bool bSSL, bool bLDAPv2ReadOnly, char *pUsername, char *pPassword, bool bNoCleartext, sInt32 *outFailureCode )
{
int iVersion = LDAP_VERSION3;
timeval stTimeout = { kLDAPDefaultOpenCloseTimeoutInSeconds, 0 }; sInt32 siResult = eDSAuthServerError;
LDAP *pLD = NULL;
int ldapReturnCode = 0;
pLD = ldap_init( pServer, (bSSL ? LDAPS_PORT : LDAP_PORT) );
if (!bLDAPv2ReadOnly)
{
ldap_set_option( pLD, LDAP_OPT_PROTOCOL_VERSION, &iVersion );
}
ldap_set_option( pLD, LDAP_OPT_REFERRALS, LDAP_OPT_OFF ); SetNetworkTimeoutsForHost( pLD, kLDAPDefaultNetworkTimeoutInSeconds );
if( bSSL && !bLDAPv2ReadOnly )
{
int ldapOptVal = LDAP_OPT_X_TLS_HARD;
ldap_set_option( pLD, LDAP_OPT_X_TLS, &ldapOptVal );
}
if( !bSSL && pUsername != NULL && strlen(pUsername) && pPassword != NULL && strlen(pPassword) && !bLDAPv2ReadOnly )
{
sLDAPConfigData stConfig;
stConfig.fSASLmethods = (CFMutableArrayRef) GetSASLMethods( pLD );
if( stConfig.fSASLmethods != NULL )
{
ldapReturnCode = doSASLBindAttemptIfPossible( pLD, &stConfig, pUsername, pPassword );
if( ldapReturnCode == LDAP_SUCCESS )
{
siResult = eDSNoErr;
}
else if( ldapReturnCode == LDAP_TIMEOUT )
{
siResult = eDSServerTimeout;
}
else if( ldapReturnCode == LDAP_LOCAL_ERROR || ldapReturnCode == LDAP_LOCAL_ERROR )
{ siResult = eDSAuthServerError;
}
else
{
siResult = eDSAuthFailed;
}
}
if( stConfig.fSASLmethods != NULL )
{
CFRelease( stConfig.fSASLmethods );
stConfig.fSASLmethods = NULL;
}
}
if( (!bNoCleartext || bSSL || pUsername == NULL || pPassword == NULL) && siResult == eDSAuthServerError )
{
LDAPMessage *pLdapResult = NULL;
int siBindMsgID = ldap_simple_bind( pLD, pUsername, pPassword );
ldapReturnCode = ldap_result( pLD, siBindMsgID, 0, &stTimeout, &pLdapResult );
if( ldapReturnCode == 0 || ldapReturnCode == -1 )
{
siResult = eDSServerTimeout;
}
else if( pLdapResult )
{
if( ldap_parse_result( pLD, pLdapResult, &ldapReturnCode, NULL, NULL, NULL, NULL, 0 ) == LDAP_SUCCESS )
{
if( ldapReturnCode == LDAP_SUCCESS )
{
siResult = eDSNoErr;
}
else if( ldapReturnCode == LDAP_TIMEOUT )
{
siResult = eDSServerTimeout;
}
else if( ldapReturnCode == LDAP_PROTOCOL_ERROR )
{
siResult = eDSReadOnly;
}
}
else
{
siResult = eDSAuthFailed;
}
}
if( pLdapResult )
{
ldap_msgfree( pLdapResult );
pLdapResult = NULL;
}
}
if( siResult != eDSNoErr )
{
ldap_unbind_ext_s( pLD, NULL, NULL );
pLD = NULL;
}
if( outFailureCode )
{
*outFailureCode = siResult;
}
return pLD;
}
CFArrayRef CLDAPv3Plugin::GetSASLMethods( LDAP *pLD )
{
char *pAttributes[] = { "supportedSASLMechanisms", NULL };
timeval stTimeout = { 30, 0 }; CFArrayRef cfSASLMechs = NULL;
LDAPMessage *pLDAPResult = NULL;
if( ldap_search_ext_s( pLD, LDAP_ROOT_DSE, LDAP_SCOPE_BASE, "(objectclass=*)", pAttributes, false, NULL, NULL, &stTimeout, 0, &pLDAPResult ) == LDAP_SUCCESS )
{
cfSASLMechs = GetLDAPAttributeFromResult( pLD, pLDAPResult, "supportedSASLMechanisms" );
}
if( pLDAPResult )
{
ldap_msgfree( pLDAPResult );
pLDAPResult = NULL;
}
return cfSASLMechs;
}
CFMutableArrayRef CLDAPv3Plugin::GetLDAPAttributeFromResult( LDAP *pLD, LDAPMessage *pMessage, char *pAttribute )
{
berval **pBValues = NULL;
CFMutableArrayRef cfResult = CFArrayCreateMutable( kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks );
if( (pBValues = ldap_get_values_len(pLD, pMessage, pAttribute)) != NULL )
{
uInt32 ii = 0;
while( pBValues[ii] != NULL )
{
CFStringRef cfAttrib = CFStringCreateWithBytes( kCFAllocatorDefault, (UInt8 *)pBValues[ii]->bv_val, pBValues[ii]->bv_len, kCFStringEncodingUTF8, false );
CFArrayAppendValue( cfResult, cfAttrib );
CFRelease( cfAttrib );
ii++;
}
ldap_value_free_len( pBValues );
pBValues = NULL;
}
if( CFArrayGetCount(cfResult) == 0 )
{
CFRelease( cfResult );
cfResult = NULL;
}
return cfResult;
}
char *CLDAPv3Plugin::GenerateSearchString( CFDictionaryRef inRecordDict )
{
CFStringRef cfGroupStyle = (CFStringRef) CFDictionaryGetValue( inRecordDict, CFSTR(kXMLGroupObjectClasses) );
CFArrayRef cfObjectClasses = (CFArrayRef) CFDictionaryGetValue( inRecordDict, CFSTR(kXMLObjectClasses) );
char *pSearchString = NULL;
if( cfObjectClasses != NULL && CFArrayGetCount(cfObjectClasses) != 0 )
{
pSearchString = (char *) calloc( sizeof(char), 256 );
if( cfGroupStyle != NULL && CFStringCompare(cfGroupStyle, CFSTR("AND"), 0) == kCFCompareEqualTo )
{
strcpy( pSearchString, "(&" );
} else {
strcpy( pSearchString, "(|" );
}
CFIndex iCount = CFArrayGetCount( cfObjectClasses );
for( CFIndex ii = 0; ii < iCount; ii++ )
{
CFStringRef cfObjectClass = (CFStringRef) CFArrayGetValueAtIndex( cfObjectClasses, ii );
if( cfObjectClass != NULL && CFGetTypeID(cfObjectClass) == CFStringGetTypeID() )
{
strcat( pSearchString, "(objectclass=" );
uInt32 iLength = strlen(pSearchString);
CFStringGetCString( cfObjectClass, pSearchString+iLength, 256-iLength, kCFStringEncodingUTF8 );
strcat( pSearchString, ")" );
}
}
strcat( pSearchString, ")" );
}
return pSearchString;
}
CFDictionaryRef CLDAPv3Plugin::CreateMappingFromConfig( CFDictionaryRef inDict, CFStringRef inRecordType )
{
CFArrayRef cfRecordMap = (CFArrayRef) CFDictionaryGetValue( inDict, CFSTR(kXMLRecordTypeMapArrayKey) );
CFMutableDictionaryRef cfReturnDict = NULL;
if( cfRecordMap != NULL && CFGetTypeID(cfRecordMap) == CFArrayGetTypeID() )
{
CFIndex iCount = CFArrayGetCount( cfRecordMap );
CFDictionaryRef cfRecordDict = NULL;
for( CFIndex ii = 0; ii < iCount; ii++ )
{
CFDictionaryRef cfMapDict = (CFDictionaryRef) CFArrayGetValueAtIndex( cfRecordMap, ii );
if( CFGetTypeID(cfMapDict) == CFDictionaryGetTypeID() )
{
CFStringRef cfMapName = (CFStringRef) CFDictionaryGetValue( cfMapDict, CFSTR(kXMLStdNameKey) );
if( cfMapName != NULL && CFStringCompare( cfMapName, inRecordType, 0) == kCFCompareEqualTo )
{
cfRecordDict = cfMapDict;
break;
}
}
}
if( cfRecordDict != NULL )
{
CFArrayRef cfNativeMap = (CFArrayRef) CFDictionaryGetValue( cfRecordDict, CFSTR(kXMLNativeMapArrayKey) );
if( cfNativeMap != NULL && CFGetTypeID(cfNativeMap) == CFArrayGetTypeID() )
{
if( CFArrayGetCount(cfNativeMap) > 0 )
{
cfReturnDict = CFDictionaryCreateMutable( kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks );
CFDictionaryRef cfNativeDict = (CFDictionaryRef) CFArrayGetValueAtIndex( cfNativeMap, 0 );
if( cfNativeDict != NULL && CFGetTypeID(cfNativeDict) == CFDictionaryGetTypeID() )
{
CFStringRef cfSearchbase = (CFStringRef) CFDictionaryGetValue( cfNativeDict, CFSTR(kXMLSearchBase) );
if( cfSearchbase != NULL && CFGetTypeID(cfSearchbase) == CFStringGetTypeID() )
CFDictionarySetValue( cfReturnDict, CFSTR(kXMLSearchBase), cfSearchbase );
CFStringRef cfGroupStyle = (CFStringRef) CFDictionaryGetValue( cfNativeDict, CFSTR(kXMLGroupObjectClasses) );
if( cfGroupStyle != NULL && CFGetTypeID(cfGroupStyle) == CFStringGetTypeID() )
CFDictionarySetValue( cfReturnDict, CFSTR(kXMLGroupObjectClasses), cfGroupStyle );
CFArrayRef cfObjectClasses = (CFArrayRef) CFDictionaryGetValue( cfNativeDict, CFSTR(kXMLObjectClasses) );
if( cfObjectClasses != NULL && CFGetTypeID(cfObjectClasses) == CFArrayGetTypeID() )
CFDictionarySetValue( cfReturnDict, CFSTR(kXMLObjectClasses), cfObjectClasses );
}
}
}
CFArrayRef cfAttribMap = (CFArrayRef) CFDictionaryGetValue( cfRecordDict, CFSTR(kXMLAttrTypeMapArrayKey) );
if( cfAttribMap != NULL && CFGetTypeID(cfAttribMap) == CFArrayGetTypeID() )
{
CFMutableDictionaryRef cfAttribDict = CFDictionaryCreateMutable( kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
CFDictionarySetValue( cfReturnDict, CFSTR("Attributes"), cfAttribDict );
CFRelease( cfAttribDict );
CFIndex iCount = CFArrayGetCount( cfAttribMap );
for( CFIndex ii = 0; ii < iCount; ii++ )
{
CFDictionaryRef cfMapDict = (CFDictionaryRef) CFArrayGetValueAtIndex( cfAttribMap, ii );
if( cfMapDict != NULL && CFGetTypeID(cfMapDict) == CFDictionaryGetTypeID() )
{
CFStringRef cfName = (CFStringRef) CFDictionaryGetValue( cfMapDict, CFSTR(kXMLStdNameKey) );
if( cfName != NULL && CFGetTypeID(cfName) == CFStringGetTypeID())
{
CFArrayRef cfNativeMap = (CFArrayRef) CFDictionaryGetValue( cfMapDict, CFSTR(kXMLNativeMapArrayKey) );
if( cfNativeMap != NULL && CFGetTypeID(cfNativeMap) == CFArrayGetTypeID() )
{
CFDictionarySetValue( cfAttribDict, cfName, cfNativeMap );
}
}
}
}
}
cfAttribMap = (CFArrayRef) CFDictionaryGetValue( inDict, CFSTR(kXMLAttrTypeMapArrayKey) );
if( cfAttribMap != NULL && CFGetTypeID(cfAttribMap) == CFArrayGetTypeID() )
{
CFMutableDictionaryRef cfAttribDict = (CFMutableDictionaryRef) CFDictionaryGetValue( cfReturnDict, CFSTR("Attributes") );
if( cfAttribDict == NULL )
{
cfAttribDict = CFDictionaryCreateMutable( kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
CFDictionarySetValue( cfReturnDict, CFSTR("Attributes"), cfAttribDict );
CFRelease( cfAttribDict ); }
CFIndex iCount = CFArrayGetCount( cfAttribMap );
for( CFIndex ii = 0; ii < iCount; ii++ )
{
CFDictionaryRef cfMapDict = (CFDictionaryRef) CFArrayGetValueAtIndex( cfAttribMap, ii );
if( cfMapDict != NULL && CFGetTypeID(cfMapDict) == CFDictionaryGetTypeID() )
{
CFStringRef cfName = (CFStringRef) CFDictionaryGetValue( cfMapDict, CFSTR(kXMLStdNameKey) );
if( cfName != NULL && CFGetTypeID(cfName) == CFStringGetTypeID())
{
CFArrayRef cfNativeMap = (CFArrayRef) CFDictionaryGetValue( cfMapDict, CFSTR(kXMLNativeMapArrayKey) );
if( cfNativeMap != NULL && CFGetTypeID(cfNativeMap) == CFArrayGetTypeID() )
{
if( CFDictionaryGetValue(cfAttribDict, cfName) == NULL )
{
CFDictionarySetValue( cfAttribDict, cfName, cfNativeMap );
}
}
}
}
}
}
}
}
return cfReturnDict;
}
CFArrayRef CLDAPv3Plugin::GetAttribFromRecordDict( CFDictionaryRef inDict, CFStringRef inAttribute, char **outFirstAttribute, CFStringRef *outCFFirstAttribute )
{
CFArrayRef cfAttributeArray = NULL;
CFDictionaryRef cfAttribMap = (CFDictionaryRef) CFDictionaryGetValue( inDict, CFSTR("Attributes") );
if( cfAttribMap != NULL )
{
cfAttributeArray = (CFArrayRef) CFDictionaryGetValue( cfAttribMap, inAttribute );
if( (outFirstAttribute != NULL || outCFFirstAttribute != NULL) && cfAttributeArray != NULL && CFGetTypeID(cfAttributeArray) == CFArrayGetTypeID() )
{
CFStringRef cfAttribute = (CFStringRef) CFArrayGetValueAtIndex( cfAttributeArray, 0 );
if( cfAttribute != NULL && CFGetTypeID(cfAttribute) == CFStringGetTypeID() )
{
if( outFirstAttribute != NULL )
{
uInt32 iLength = (uInt32) CFStringGetMaximumSizeForEncoding( CFStringGetLength(cfAttribute), kCFStringEncodingUTF8) + 1;
*outFirstAttribute = (char *) calloc( sizeof(char), iLength );
CFStringGetCString( cfAttribute, *outFirstAttribute, iLength, kCFStringEncodingUTF8 );
}
if( outCFFirstAttribute != NULL )
{
*outCFFirstAttribute = cfAttribute;
}
}
}
} else if( outCFFirstAttribute ) {
*outCFFirstAttribute = NULL;
}
return cfAttributeArray;
}
bool CLDAPv3Plugin::IsServerInConfig( CFDictionaryRef inConfig, CFStringRef inServerName, CFIndex *outIndex, CFMutableDictionaryRef *outConfig )
{
bool bReturn = false;
bool bFreeInConfig = false;
if( inConfig == NULL )
{
CFDataRef cfTempData = gpConfigFromXML->CopyXMLConfig();
inConfig = (CFDictionaryRef) CFPropertyListCreateFromXMLData( kCFAllocatorDefault, cfTempData, kCFPropertyListImmutable, NULL );
CFRelease( cfTempData );
cfTempData = NULL;
bFreeInConfig = true;
}
CFMutableArrayRef cfConfigList = (CFMutableArrayRef) CFDictionaryGetValue( inConfig, CFSTR(kXMLConfigArrayKey) );
if( cfConfigList != NULL )
{
CFIndex iCount = CFArrayGetCount( cfConfigList );
for( CFIndex ii = 0; ii < iCount; ii++ )
{
CFMutableDictionaryRef cfConfigServerDict = (CFMutableDictionaryRef) CFArrayGetValueAtIndex( cfConfigList, ii );
CFStringRef cfTempServer = (CFStringRef) CFDictionaryGetValue( cfConfigServerDict, CFSTR(kXMLServerKey) );
if( cfTempServer && CFStringCompare( cfTempServer, inServerName, kCFCompareCaseInsensitive) == kCFCompareEqualTo )
{
if( outConfig )
{
*outConfig = cfConfigServerDict;
CFRetain( cfConfigServerDict ); }
if( outIndex )
{
*outIndex = ii;
}
bReturn = true;
break;
}
}
}
if( bFreeInConfig )
{
CFRelease( inConfig );
inConfig = NULL;
}
return bReturn;
}
CFStringRef CLDAPv3Plugin::GetServerInfoFromConfig( CFDictionaryRef inDict, char **outServer, bool *outSSL, bool *outLDAPv2ReadOnly, char **pUsername, char **pPassword )
{
CFStringRef cfServer = (CFStringRef) CFDictionaryGetValue( inDict, CFSTR(kXMLServerKey) );
if( cfServer != NULL && CFGetTypeID(cfServer) == CFStringGetTypeID() && outServer != NULL )
{
uInt32 iLength = (uInt32) CFStringGetMaximumSizeForEncoding( CFStringGetLength(cfServer), kCFStringEncodingUTF8) + 1;
*outServer = (char *) calloc( sizeof(char), iLength );
CFStringGetCString( cfServer, *outServer, iLength, kCFStringEncodingUTF8 );
}
if( outSSL )
{
CFBooleanRef cfBool = (CFBooleanRef) CFDictionaryGetValue( inDict, CFSTR(kXMLIsSSLFlagKey) );
if( cfBool != NULL && CFGetTypeID(cfBool) == CFBooleanGetTypeID() )
{
*outSSL = CFBooleanGetValue( cfBool );
}
}
if( outLDAPv2ReadOnly )
{
CFBooleanRef cfBool = (CFBooleanRef) CFDictionaryGetValue( inDict, CFSTR(kXMLLDAPv2ReadOnlyKey) );
if( cfBool != NULL && CFGetTypeID(cfBool) == CFBooleanGetTypeID() )
{
*outLDAPv2ReadOnly = CFBooleanGetValue( cfBool );
}
}
if( pUsername )
{
CFStringRef cfUsername = (CFStringRef) CFDictionaryGetValue( inDict, CFSTR(kXMLServerAccountKey) );
if( cfUsername != NULL && CFGetTypeID(cfUsername) == CFStringGetTypeID() && CFStringGetLength(cfUsername) != 0 )
{
uInt32 iLength = (uInt32) CFStringGetMaximumSizeForEncoding( CFStringGetLength(cfUsername), kCFStringEncodingUTF8) + 1;
*pUsername = (char *) calloc( sizeof(char), iLength );
CFStringGetCString( cfUsername, *pUsername, iLength, kCFStringEncodingUTF8 );
}
}
if( pPassword )
{
CFStringRef cfPassword = (CFStringRef) CFDictionaryGetValue( inDict, CFSTR(kXMLServerPasswordKey) );
if( cfPassword != NULL && CFGetTypeID(cfPassword) == CFStringGetTypeID() && CFStringGetLength(cfPassword) != 0 )
{
uInt32 iLength = (uInt32) CFStringGetMaximumSizeForEncoding( CFStringGetLength(cfPassword), kCFStringEncodingUTF8) + 1;
*pPassword = (char *) calloc( sizeof(char), iLength );
CFStringGetCString( cfPassword, *pPassword, iLength, kCFStringEncodingUTF8 );
}
}
return cfServer;
}
CFMutableDictionaryRef CLDAPv3Plugin::GetXMLFromBuffer( tDataBufferPtr inBuffer )
{
sInt32 iBufLen = inBuffer->fBufferLength;
CFMutableDictionaryRef cfXMLDict = NULL;
sInt32 iXMLDataLength = iBufLen - sizeof( AuthorizationExternalForm );
if( iXMLDataLength > 0 )
{
CFDataRef cfXMLData = CFDataCreate( kCFAllocatorDefault, (UInt8 *)(inBuffer->fBufferData + sizeof(AuthorizationExternalForm)), iXMLDataLength );
if( cfXMLData != NULL )
{
cfXMLDict = (CFMutableDictionaryRef) CFPropertyListCreateFromXMLData( kCFAllocatorDefault, cfXMLData, kCFPropertyListMutableContainersAndLeaves, NULL );
CFRelease( cfXMLData ); cfXMLData = NULL;
}
}
return cfXMLDict;
}
sInt32 CLDAPv3Plugin::PutXMLInBuffer( CFDictionaryRef inXMLDict, tDataBufferPtr outBuffer )
{
CFDataRef cfReturnData = (CFDataRef) CFPropertyListCreateXMLData( kCFAllocatorDefault, inXMLDict );
sInt32 siResult = eDSNoErr;
if( cfReturnData )
{
CFRange stRange = CFRangeMake( 0, CFDataGetLength(cfReturnData) );
if ( outBuffer->fBufferSize < (unsigned int) stRange.length )
{
siResult = eDSBufferTooSmall;
}
else
{
CFDataGetBytes( cfReturnData, stRange, (UInt8*)(outBuffer->fBufferData) );
outBuffer->fBufferLength = stRange.length;
}
CFRelease( cfReturnData );
cfReturnData = 0;
}
return siResult;
}
#pragma mark -
#pragma mark New Server Setup Functions
sInt32 CLDAPv3Plugin::DoNewServerDiscovery( sDoPlugInCustomCall *inData )
{
sInt32 siResult = eDSBogusServer;
bool bSSL = false;
bool bLDAPv2ReadOnly = false;
CFMutableDictionaryRef cfXMLDict = NULL;
LDAP *pLD = NULL;
char *pServer = NULL;
try {
cfXMLDict = GetXMLFromBuffer( inData->fInRequestData );
if( cfXMLDict == NULL ) {
throw( (sInt32) eDSInvalidBuffFormat );
}
CFStringRef cfServer = GetServerInfoFromConfig( cfXMLDict, &pServer, &bSSL, &bLDAPv2ReadOnly, NULL, NULL );
if( cfServer == NULL )
{
throw( (sInt32) eDSInvalidBuffFormat );
}
if( inData->fInRequestCode == eDSCustomCallLDAPv3NewServerDiscoveryNoDupes && IsServerInConfig(NULL, cfServer, NULL, NULL) )
{
throw( (sInt32) eDSRecordAlreadyExists );
}
char *pAttributes[] = { "namingContexts", "defaultNamingContext", NULL };
timeval stTimeout = { kLDAPDefaultOpenCloseTimeoutInSeconds, 0 }; LDAPMessage *pLDAPResult = NULL;
sInt32 bindResult = eDSNoErr;
if( (pLD = DoSimpleLDAPBind(pServer, bSSL, bLDAPv2ReadOnly, NULL, NULL, false, &bindResult)) == NULL )
{
if( bindResult == eDSReadOnly)
{
bLDAPv2ReadOnly = true;
if( (pLD = DoSimpleLDAPBind(pServer, bSSL, bLDAPv2ReadOnly, NULL, NULL)) == NULL ) {
throw( (sInt32) eDSBogusServer );
}
}
else if( !bSSL && !bLDAPv2ReadOnly )
{
bSSL = true;
if( (pLD = DoSimpleLDAPBind(pServer, bSSL, bLDAPv2ReadOnly, NULL, NULL)) == NULL ) {
throw( (sInt32) eDSBogusServer );
}
}
else
{
throw( (sInt32) eDSBogusServer );
}
}
int iLDAPRetCode = ldap_search_ext_s( pLD, LDAP_ROOT_DSE, LDAP_SCOPE_BASE, "(objectclass=*)", pAttributes, false, NULL, NULL, &stTimeout, 0, &pLDAPResult );
if( iLDAPRetCode != LDAP_SUCCESS && !bLDAPv2ReadOnly )
{
throw( (sInt32) eDSBogusServer );
}
CFArrayRef cfNameContext = GetLDAPAttributeFromResult( pLD, pLDAPResult, "defaultNamingContext" );
if( cfNameContext == NULL )
{
cfNameContext = GetLDAPAttributeFromResult( pLD, pLDAPResult, "namingContexts" );
}
if( pLDAPResult )
{
ldap_msgfree( pLDAPResult );
pLDAPResult = NULL;
}
siResult = eDSNoErr;
if( cfNameContext )
{
CFIndex iNumContexts = CFArrayGetCount( cfNameContext );
bool bFound = false;
char *pAttributes[] = { "description", NULL };
berval **pBValues = NULL;
for( CFIndex ii = 0; ii < iNumContexts && !bFound; ii++ )
{
CFStringRef cfSearchbase = (CFStringRef) CFArrayGetValueAtIndex( cfNameContext, ii );
if( iNumContexts == 1 )
{
CFDictionarySetValue( cfXMLDict, CFSTR("Template Search Base Suffix"), cfSearchbase );
}
uInt32 iLength = (uInt32) CFStringGetMaximumSizeForEncoding( CFStringGetLength(cfSearchbase), kCFStringEncodingUTF8) + 1;
char *pSearchbase = (char *) calloc( sizeof(char), iLength );
CFStringGetCString( cfSearchbase, pSearchbase, iLength, kCFStringEncodingUTF8 );
int iLDAPRetCode = ldap_search_ext_s( pLD, pSearchbase, LDAP_SCOPE_SUBTREE, "(&(objectclass=organizationalUnit)(ou=macosxodconfig))", pAttributes, false, NULL, NULL, &stTimeout, 0, &pLDAPResult );
if( iLDAPRetCode == LDAP_SUCCESS )
{
if( (pBValues = ldap_get_values_len(pLD, pLDAPResult, "description")) != NULL )
{
CFDataRef cfXMLData = CFDataCreate( kCFAllocatorDefault, (UInt8 *)(pBValues[0]->bv_val), pBValues[0]->bv_len );
if( cfXMLData != NULL )
{
CFMutableDictionaryRef cfTempDict = (CFMutableDictionaryRef) CFPropertyListCreateFromXMLData( kCFAllocatorDefault, cfXMLData, kCFPropertyListMutableContainersAndLeaves, NULL );
if( cfTempDict && CFGetTypeID(cfTempDict) == CFDictionaryGetTypeID() && CFDictionaryGetCount(cfTempDict) )
{
CFArrayRef cfRecordMap = (CFArrayRef) CFDictionaryGetValue( cfTempDict, CFSTR(kXMLRecordTypeMapArrayKey) );
if( cfRecordMap && CFArrayGetCount(cfRecordMap) != 0 )
{
CFDictionarySetValue( cfTempDict, CFSTR(kXMLServerKey), cfServer );
CFDictionarySetValue( cfTempDict, CFSTR(kXMLServerMappingsFlagKey), kCFBooleanTrue );
CFRelease( cfXMLDict );
cfXMLDict = cfTempDict;
cfTempDict = NULL;
bFound = true;
}
}
if( cfTempDict != NULL )
{
CFRelease( cfTempDict );
cfTempDict = NULL;
}
CFRelease( cfXMLData ); cfXMLData = NULL;
}
ldap_value_free_len( pBValues );
pBValues = NULL;
}
ldap_msgfree( pLDAPResult );
pLDAPResult = NULL;
}
if( pSearchbase )
{
free( pSearchbase );
pSearchbase = NULL;
}
}
CFRelease( cfNameContext );
cfNameContext = NULL;
}
int iPortNumber = (bSSL ? LDAPS_PORT : LDAP_PORT);
CFNumberRef cfPortNumber = CFNumberCreate( kCFAllocatorDefault, kCFNumberIntType, &iPortNumber );
CFDictionarySetValue( cfXMLDict, CFSTR(kXMLPortNumberKey), cfPortNumber );
CFDictionarySetValue( cfXMLDict, CFSTR(kXMLIsSSLFlagKey), (bSSL ? kCFBooleanTrue : kCFBooleanFalse) );
CFDictionarySetValue( cfXMLDict, CFSTR(kXMLLDAPv2ReadOnlyKey), (bLDAPv2ReadOnly ? kCFBooleanTrue : kCFBooleanFalse) );
CFRelease( cfPortNumber );
cfPortNumber = NULL;
} catch( sInt32 err ) {
siResult = err;
} catch( ... ) {
siResult = eUndefinedError;
}
if( pServer != NULL )
{
free( pServer );
pServer = NULL;
}
if( pLD != NULL )
{
ldap_unbind_ext_s( pLD, NULL, NULL );
pLD = NULL;
}
if( cfXMLDict != NULL )
{
if( siResult == eDSNoErr )
{
sInt32 iError = PutXMLInBuffer( cfXMLDict, inData->fOutRequestResponse );
if( iError != eDSNoErr ) {
siResult = iError;
}
}
CFRelease( cfXMLDict );
cfXMLDict = NULL;
}
return siResult;
}
sInt32 CLDAPv3Plugin::DoNewServerVerifySettings( sDoPlugInCustomCall *inData )
{
sInt32 siResult = eDSInvalidNativeMapping;
sInt32 siBindResult = eDSAuthFailed;
LDAP *pLD = NULL;
CFMutableDictionaryRef cfXMLDict = NULL;
bool bSSL = false;
char *pServer = NULL;
char *pObjectSearchString = NULL;
char *pSearchbase = NULL;
LDAPMessage *pLDAPResult = NULL;
char *pUsername = NULL;
char *pPassword = NULL;
timeval stTimeout = { 30, 0 }; CFDictionaryRef cfRecordMap = NULL;
bool bLDAPv2ReadOnly = false;
try
{
cfXMLDict = GetXMLFromBuffer( inData->fInRequestData );
if( cfXMLDict == NULL ) {
throw( (sInt32) eDSInvalidBuffFormat );
}
CFStringRef cfServer = GetServerInfoFromConfig( cfXMLDict, &pServer, &bSSL, &bLDAPv2ReadOnly, &pUsername, &pPassword );
if( cfServer == NULL )
{
throw( (sInt32) eDSInvalidBuffFormat );
}
cfRecordMap = CreateMappingFromConfig( cfXMLDict, CFSTR(kDSStdRecordTypeUsers) );
if( cfRecordMap == NULL )
{
cfRecordMap = CreateMappingFromConfig( cfXMLDict, CFSTR(kDSStdRecordTypeGroups) );
if( cfRecordMap == NULL )
{
cfRecordMap = CreateMappingFromConfig( cfXMLDict, CFSTR(kDSStdRecordTypeComputers) );
if( cfRecordMap == NULL )
{
throw( (sInt32) eDSInvalidNativeMapping );
}
}
}
if( (pLD = DoSimpleLDAPBind(pServer, bSSL, bLDAPv2ReadOnly, pUsername, pPassword, false, &siBindResult)) == NULL )
{
throw( siBindResult );
}
CFStringRef cfSearchbase = (CFStringRef) CFDictionaryGetValue( cfRecordMap, CFSTR(kXMLSearchBase) );
if( cfSearchbase != NULL)
{
uInt32 iLength = (uInt32) CFStringGetMaximumSizeForEncoding( CFStringGetLength(cfSearchbase), kCFStringEncodingUTF8) + 1;
pSearchbase = (char *) calloc( sizeof(char), iLength );
CFStringGetCString( cfSearchbase, pSearchbase, iLength, kCFStringEncodingUTF8 );
}
pObjectSearchString = GenerateSearchString( cfRecordMap );
if( pObjectSearchString == NULL )
{
throw( (sInt32) eDSInvalidNativeMapping );
}
int iLDAPRetCode = ldap_search_ext_s( pLD, pSearchbase, LDAP_SCOPE_SUBTREE, pObjectSearchString, NULL, true, NULL, NULL, &stTimeout, 1, &pLDAPResult );
if( iLDAPRetCode == LDAP_SUCCESS || iLDAPRetCode == LDAP_SIZELIMIT_EXCEEDED )
{
int iCount = ldap_count_entries( pLD, pLDAPResult );
if( iCount == 0 )
{
siResult = eDSAuthParameterError;
}
else
{
siResult = eDSNoErr;
}
}
if( pLDAPResult != NULL )
{
ldap_msgfree( pLDAPResult );
pLDAPResult = NULL;
}
} catch( sInt32 iError ) {
siResult = iError;
} catch( ... ) {
siResult = eUndefinedError;
}
DSCFRelease( cfRecordMap );
DSFreeString( pObjectSearchString );
DSFreeString( pSearchbase );
DSFreeString( pServer );
DSFreeString( pUsername );
if( pPassword != NULL )
{
free( pPassword );
pPassword = NULL;
}
if( pLD != NULL )
{
ldap_unbind_ext_s( pLD, NULL, NULL );
pLD = NULL;
}
if( cfXMLDict != NULL )
{
if( siResult == eDSNoErr )
{
sInt32 iError = PutXMLInBuffer( cfXMLDict, inData->fOutRequestResponse );
if( iError != eDSNoErr ) {
siResult = iError;
}
}
CFRelease( cfXMLDict );
cfXMLDict = NULL;
}
return siResult;
}
sInt32 CLDAPv3Plugin::DoNewServerGetConfig( sDoPlugInCustomCall *inData )
{
bool bSSL = false;
sInt32 siResult = eDSInvalidNativeMapping;
sInt32 siBindResult = eDSNoErr;
timeval stTimeout = { 30, 0 }; CFMutableDictionaryRef cfXMLDict = NULL;
CFDictionaryRef cfConfigMap = NULL;
CFMutableDictionaryRef cfSupportedSecLevel = NULL;
LDAP *pLD = NULL;
char *pServer = NULL;
char *pSearchString = NULL;
char *pKerbSearchString = NULL;
char *pSearchbase = NULL;
char *pAttribute = NULL;
char *pUsername = NULL;
char *pPassword = NULL;
bool bLDAPv2ReadOnly = false;
try {
cfXMLDict = GetXMLFromBuffer( inData->fInRequestData );
if( cfXMLDict == NULL )
{
throw( (sInt32) eDSInvalidBuffFormat );
}
CFStringRef cfServer = GetServerInfoFromConfig( cfXMLDict, &pServer, &bSSL, &bLDAPv2ReadOnly, &pUsername, &pPassword );
if( cfServer == NULL )
{
throw( (sInt32) eDSInvalidBuffFormat );
}
if( (pLD = DoSimpleLDAPBind(pServer, bSSL, bLDAPv2ReadOnly, pUsername, pPassword, false, &siBindResult)) == NULL )
{
throw( siBindResult );
}
cfSupportedSecLevel = CFDictionaryCreateMutable( kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks );
CFDictionarySetValue( cfXMLDict, CFSTR(kXMLSupportedSecurityKey), cfSupportedSecLevel );
if( bSSL )
{
CFDictionarySetValue( cfSupportedSecLevel, CFSTR(kXMLSecurityNoClearTextAuths), kCFBooleanTrue );
CFDictionarySetValue( cfSupportedSecLevel, CFSTR(kXMLSecurityPacketEncryption), kCFBooleanTrue );
}
CFArrayRef cfSASLMechs = GetSASLMethods( pLD );
if( cfSASLMechs )
{
CFRange stRange = CFRangeMake( 0, CFArrayGetCount(cfSASLMechs) );
if( CFArrayContainsValue( cfSASLMechs, stRange, CFSTR("CRAM-MD5")) && fLDAPSessionMgr.isSASLMethodSupported(CFSTR("CRAM-MD5")) )
{
CFDictionarySetValue( cfSupportedSecLevel, CFSTR(kXMLSecurityNoClearTextAuths), kCFBooleanTrue );
}
if( CFArrayContainsValue( cfSASLMechs, stRange, CFSTR("GSSAPI")) && fLDAPSessionMgr.isSASLMethodSupported(CFSTR("GSSAPI")) )
{
CFDictionarySetValue( cfSupportedSecLevel, CFSTR(kXMLSecurityNoClearTextAuths), kCFBooleanTrue );
CFDictionarySetValue( cfSupportedSecLevel, CFSTR(kXMLSecurityManInTheMiddle), kCFBooleanTrue );
CFDictionarySetValue( cfSupportedSecLevel, CFSTR(kXMLSecurityPacketSigning), kCFBooleanTrue );
CFDictionarySetValue( cfSupportedSecLevel, CFSTR(kXMLSecurityPacketEncryption), kCFBooleanTrue );
}
CFRelease( cfSASLMechs );
cfSASLMechs = NULL;
}
cfConfigMap = CreateMappingFromConfig( cfXMLDict, CFSTR(kDSStdRecordTypeConfig) );
if( cfConfigMap == NULL )
{
throw( (sInt32) eDSNoErr );
}
CFStringRef cfSearchbase = (CFStringRef) CFDictionaryGetValue( cfConfigMap, CFSTR(kXMLSearchBase) );
if( cfSearchbase != NULL)
{
uInt32 iLength = (uInt32) CFStringGetMaximumSizeForEncoding( CFStringGetLength(cfSearchbase), kCFStringEncodingUTF8) + 1;
pSearchbase = (char *) calloc( sizeof(char), iLength );
CFStringGetCString( cfSearchbase, pSearchbase, iLength, kCFStringEncodingUTF8 );
}
char *pObjectSearchString = GenerateSearchString( cfConfigMap );
if( pObjectSearchString != NULL )
{
pSearchString = (char *) calloc( sizeof(char), strlen(pObjectSearchString) + 22 + 1 );
strcpy( pSearchString, "(&" ); strcat( pSearchString, pObjectSearchString ); strcat( pSearchString, "(cn=macosxodpolicy)" ); strcat( pSearchString, ")" );
pKerbSearchString = (char *) calloc( sizeof(char), 2 + strlen(pObjectSearchString) + 19 + 1 );
strcpy( pKerbSearchString, "(&" ); strcat( pKerbSearchString, pObjectSearchString ); strcat( pKerbSearchString, "(cn=KerberosClient)" ); strcat( pKerbSearchString, ")" );
free( pObjectSearchString );
pObjectSearchString = NULL;
}
else
{
throw( (sInt32) eDSNoErr );
}
CFArrayRef cfAttributeArray = GetAttribFromRecordDict( cfConfigMap, CFSTR(kDS1AttrXMLPlist), &pAttribute );
if( cfAttributeArray == NULL )
{
throw( (sInt32) eDSNoErr );
}
LDAPMessage *pLDAPResult = NULL;
int iLDAPRetCode = ldap_search_ext_s( pLD, pSearchbase, LDAP_SCOPE_SUBTREE, pSearchString, NULL, false, NULL, NULL, &stTimeout, 0, &pLDAPResult );
if( iLDAPRetCode == LDAP_SUCCESS )
{
berval **pBValues = NULL;
if( (pBValues = ldap_get_values_len(pLD, pLDAPResult, pAttribute)) != NULL )
{
CFDataRef cfXMLData = CFDataCreate( kCFAllocatorDefault, (UInt8 *)(pBValues[0]->bv_val), pBValues[0]->bv_len );
if( cfXMLData != NULL )
{
CFDictionaryRef cfTempDict = (CFDictionaryRef) CFPropertyListCreateFromXMLData( kCFAllocatorDefault, cfXMLData, kCFPropertyListImmutable, NULL );
if( cfTempDict )
{
CFDictionaryRef cfSecurityLevel = (CFDictionaryRef) CFDictionaryGetValue( cfTempDict, CFSTR(kXMLConfiguredSecurityKey) );
if( cfSecurityLevel != NULL && CFGetTypeID(cfSecurityLevel) == CFDictionaryGetTypeID() )
{
CFDictionarySetValue( cfXMLDict, CFSTR(kXMLConfiguredSecurityKey), cfSecurityLevel );
}
CFBooleanRef cfBindingActive = (CFBooleanRef) CFDictionaryGetValue( cfTempDict, CFSTR(kXMLDirectoryBindingKey) );
if( cfBindingActive != NULL && CFGetTypeID(cfBindingActive) == CFBooleanGetTypeID() )
{
CFDictionarySetValue( cfXMLDict, CFSTR(kXMLDirectoryBindingKey), cfBindingActive );
}
CFRelease( cfTempDict );
cfTempDict = NULL;
}
CFRelease( cfXMLData ); cfXMLData = NULL;
}
ldap_value_free_len( pBValues );
pBValues = NULL;
}
}
if( pLDAPResult )
{
ldap_msgfree( pLDAPResult );
pLDAPResult = NULL;
}
iLDAPRetCode = ldap_search_ext_s( pLD, pSearchbase, LDAP_SCOPE_SUBTREE, pKerbSearchString, NULL, false, NULL, NULL, &stTimeout, 0, &pLDAPResult );
if( iLDAPRetCode == LDAP_SUCCESS )
{
berval **pBValues = NULL;
if( (pBValues = ldap_get_values_len(pLD, pLDAPResult, pAttribute)) != NULL )
{
CFDataRef cfXMLData = CFDataCreate( kCFAllocatorDefault, (UInt8 *)(pBValues[0]->bv_val), pBValues[0]->bv_len );
if( cfXMLData != NULL )
{
CFDictionaryRef cfTempDict = (CFDictionaryRef) CFPropertyListCreateFromXMLData( kCFAllocatorDefault, cfXMLData, kCFPropertyListImmutable, NULL );
if( cfTempDict != NULL )
{
CFDictionaryRef cfWorkingDict;
cfWorkingDict = (CFDictionaryRef) CFDictionaryGetValue( cfTempDict, CFSTR("edu.mit.kerberos") );
if( cfWorkingDict != NULL )
{
cfWorkingDict = (CFDictionaryRef) CFDictionaryGetValue( cfWorkingDict, CFSTR("libdefaults") );
if( cfWorkingDict != NULL )
{
CFStringRef cfString = (CFStringRef) CFDictionaryGetValue( cfWorkingDict, CFSTR("default_realm") );
if( cfString != NULL )
{
uInt32 iLength = (uInt32) CFStringGetMaximumSizeForEncoding( CFStringGetLength(cfString), kCFStringEncodingUTF8) + 1;
char *pKerberosRealm = (char *) calloc( sizeof(char), iLength );
CFStringGetCString( cfString, pKerberosRealm, iLength, kCFStringEncodingUTF8 );
gpConfigFromXML->VerifyKerberosForRealm( pKerberosRealm, pServer );
CFStringRef cfKerbID = CFStringCreateWithFormat( kCFAllocatorDefault, NULL, CFSTR("@%@"), cfString );
CFDictionarySetValue( cfXMLDict, CFSTR(kXMLKerberosId), cfKerbID );
CFRelease( cfKerbID );
free( pKerberosRealm );
pKerberosRealm = NULL;
}
}
}
CFRelease( cfTempDict );
cfTempDict = NULL;
}
CFRelease( cfXMLData ); cfXMLData = NULL;
}
ldap_value_free_len( pBValues );
pBValues = NULL;
}
}
if( pLDAPResult )
{
ldap_msgfree( pLDAPResult );
pLDAPResult = NULL;
}
siResult = eDSNoErr;
} catch( sInt32 iError ) {
siResult = iError;
} catch( ... ) {
siResult = eUndefinedError;
}
DSCFRelease( cfSupportedSecLevel );
DSCFRelease( cfConfigMap );
DSFreeString( pServer );
DSFreeString( pKerbSearchString );
DSFreeString( pSearchString );
DSFreeString( pSearchbase );
DSFreeString( pAttribute );
DSFreeString( pUsername );
if( pPassword != NULL )
{
free( pPassword );
pPassword = NULL;
}
if( pLD != NULL )
{
ldap_unbind_ext_s( pLD, NULL, NULL );
pLD = NULL;
}
if( cfXMLDict != NULL )
{
if( siResult == eDSNoErr )
{
sInt32 iError = PutXMLInBuffer( cfXMLDict, inData->fOutRequestResponse );
if( iError != eDSNoErr ) {
siResult = iError;
}
}
CFRelease( cfXMLDict );
cfXMLDict = NULL;
}
return siResult;
}
sInt32 CLDAPv3Plugin::DoNewServerBind( sDoPlugInCustomCall *inData )
{
sInt32 siResult = eDSInvalidNativeMapping;
CFMutableDictionaryRef cfXMLDict = NULL;
char *pUsername = NULL;
char *pPassword = NULL;
CFDataRef cfCurrentConfigData = NULL;
try
{
cfXMLDict = GetXMLFromBuffer( inData->fInRequestData );
if( cfXMLDict == NULL ) {
throw( (sInt32) eDSInvalidBuffFormat );
}
CFStringRef cfServer = GetServerInfoFromConfig( cfXMLDict, NULL, NULL, NULL, &pUsername, &pPassword );
if( cfServer == NULL )
{
throw( (sInt32) eDSInvalidBuffFormat );
}
if( pUsername == NULL || pPassword == NULL )
{
throw( (sInt32) eDSAuthParameterError );
}
CFDictionarySetValue( cfXMLDict, CFSTR(kXMLSecureUseFlagKey), kCFBooleanFalse );
cfCurrentConfigData = gpConfigFromXML->CopyXMLConfig();
CFMutableDictionaryRef cfConfigXML = (CFMutableDictionaryRef) CFPropertyListCreateFromXMLData( kCFAllocatorDefault, cfCurrentConfigData, kCFPropertyListMutableContainersAndLeaves, NULL );
CFMutableArrayRef cfConfigList = (CFMutableArrayRef) CFDictionaryGetValue( cfConfigXML, CFSTR(kXMLConfigArrayKey) );
CFIndex iIndex = 0;
if( IsServerInConfig(cfConfigXML, cfServer, &iIndex, NULL) )
{
CFArraySetValueAtIndex( cfConfigList, iIndex, cfXMLDict );
}
else
{
if( cfConfigList == NULL )
{
cfConfigList = CFArrayCreateMutable( kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks );
CFDictionarySetValue( cfConfigXML, CFSTR(kXMLConfigArrayKey), cfConfigList );
CFRelease( cfConfigList ); }
CFArrayAppendValue( cfConfigList, cfXMLDict );
}
CFDataRef cfNewConfig = (CFDataRef) CFPropertyListCreateXMLData( kCFAllocatorDefault, cfConfigXML );
gpConfigFromXML->SetXMLConfig( cfNewConfig );
CFRelease( cfNewConfig );
cfNewConfig = NULL;
CFRelease( cfConfigXML );
cfConfigXML = NULL;
Initialize();
siResult = DoNewServerBind2( inData );
} catch( sInt32 iError ) {
siResult = iError;
} catch( ... ) {
siResult = eUndefinedError;
}
if( pUsername != NULL )
{
free( pUsername );
pUsername = NULL;
}
if( pPassword != NULL )
{
memset( pPassword, 0, strlen(pPassword) );
free( pPassword );
pPassword = NULL;
}
if( cfXMLDict )
{
CFRelease( cfXMLDict );
cfXMLDict = NULL;
}
if( cfCurrentConfigData != NULL )
{
gpConfigFromXML->SetXMLConfig( cfCurrentConfigData );
Initialize();
CFRelease( cfCurrentConfigData );
cfCurrentConfigData = NULL;
}
return siResult;
}
sInt32 CLDAPv3Plugin::DoNewServerBind2( sDoPlugInCustomCall *inData )
{
sInt32 siResult = eDSInvalidNativeMapping;
CFMutableDictionaryRef cfXMLDict = NULL;
char *pServer = NULL;
char *pUsername = NULL;
char *pPassword = NULL;
char *pComputerID = NULL;
CFDictionaryRef cfComputerMap = NULL;
tDirReference dsRef = 0;
tDirNodeReference dsNodeRef = 0;
tDataNodePtr pRecType = ::dsDataNodeAllocateString( dsRef, kDSStdRecordTypeComputers );;
tDataBufferPtr responseDataBufPtr = ::dsDataBufferAllocatePriv( 1024 );
tDataBufferPtr sendDataBufPtr = ::dsDataBufferAllocatePriv( 1024 );
tDataNodePtr pAuthType = NULL;
tDataNodePtr pRecName = NULL;
tDataList dataList = { 0 };
try
{
cfXMLDict = GetXMLFromBuffer( inData->fInRequestData );
if( cfXMLDict == NULL ) {
throw( (sInt32) eDSInvalidBuffFormat );
}
CFStringRef cfServer = GetServerInfoFromConfig( cfXMLDict, &pServer, NULL, NULL, &pUsername, &pPassword );
if( cfServer == NULL )
{
throw( (sInt32) eDSInvalidBuffFormat );
}
if( pUsername == NULL || pPassword == NULL )
{
throw( (sInt32) eDSAuthParameterError );
}
CFDictionarySetValue( cfXMLDict, CFSTR(kXMLSecureUseFlagKey), kCFBooleanFalse );
cfComputerMap = CreateMappingFromConfig( cfXMLDict, CFSTR(kDSStdRecordTypeComputers) );
if( cfComputerMap == NULL )
{
throw( (sInt32) eDSNoStdMappingAvailable );
}
CFStringRef cfComputerName = (CFStringRef) CFDictionaryGetValue( cfXMLDict, CFSTR(kXMLUserDefinedNameKey) );
if( cfComputerName != NULL && CFGetTypeID(cfComputerName) == CFStringGetTypeID() )
{
uInt32 iLength = (uInt32) CFStringGetMaximumSizeForEncoding( CFStringGetLength(cfComputerName), kCFStringEncodingUTF8) + 1;
pComputerID = (char *) calloc( sizeof(char), iLength );
CFStringGetCString( cfComputerName, pComputerID, iLength, kCFStringEncodingUTF8 );
} else {
throw( (sInt32) eDSInvalidRecordName );
}
siResult = ::dsOpenDirService( &dsRef );
if( siResult != eDSNoErr )
{
throw( (sInt32) siResult );
}
char pNodeName[255];
strcpy( pNodeName, "/LDAPv3/" );
strcat( pNodeName, pServer );
tDataList *nodeString = ::dsBuildFromPathPriv( pNodeName, "/" );
siResult = ::dsOpenDirNode( dsRef, nodeString, &dsNodeRef );
::dsDataListDeallocatePriv( nodeString );
free( nodeString );
if( siResult != eDSNoErr )
{
DBGLOG1( kLogPlugin, "CLDAPv3Plugin: Bind Request - Unable to open Directory Node %s", pNodeName );
throw( (sInt32) siResult );
}
uInt32 iNameLen = strlen( pUsername );
uInt32 iPassLen = strlen( pPassword );
uInt32 authDataSize = iNameLen + iPassLen + (2 * sizeof(uInt32));
pAuthType = ::dsDataNodeAllocateString( dsRef, kDSStdAuthNodeNativeNoClearText );
sendDataBufPtr->fBufferLength = authDataSize;
char *ptr = (char*)(sendDataBufPtr->fBufferData);
*((uInt32 *)ptr) = iNameLen;
ptr += sizeof(uInt32);
bcopy( pUsername, ptr, iNameLen );
ptr += iNameLen;
*((uInt32 *)ptr) = iPassLen;
ptr += sizeof(uInt32);
bcopy( pPassword, ptr, iPassLen );
DBGLOG1( kLogPlugin, "CLDAPv3Plugin: Bind Request - Attempting to authenticate as provided user - %s", pUsername );
if( (siResult = dsDoDirNodeAuth( dsNodeRef, pAuthType, false, sendDataBufPtr, responseDataBufPtr, 0)) != eDSNoErr )
{
DBGLOG1( kLogPlugin, "CLDAPv3Plugin: Bind Request - Credentials for %s failed", pUsername );
throw( (sInt32) siResult );
}
if( pAuthType != NULL )
{
::dsDataNodeDeAllocate( dsRef, pAuthType );
pAuthType = NULL;
}
tRecordReference recRef = 0;
pRecName = ::dsDataNodeAllocateString( dsRef, pComputerID );
siResult = dsOpenRecord( dsNodeRef, pRecType, pRecName, &recRef );
if( siResult == eDSNoErr )
{
if( inData->fInRequestCode == eDSCustomCallLDAPv3NewServerBind || inData->fInRequestCode == eDSCustomCallLDAPv3NewServerBindOther )
{
DBGLOG1( kLogPlugin, "CLDAPv3Plugin: Bind Request - Existing computer record %s", pComputerID );
throw( (sInt32) eDSRecordAlreadyExists );
}
}
if( recRef == 0 )
{
DBGLOG1( kLogPlugin, "CLDAPv3Plugin: Bind Request - Attempting to Create computer record and open - %s", pComputerID );
siResult = dsCreateRecordAndOpen( dsNodeRef, pRecType, pRecName, &recRef );
if( siResult != eDSNoErr )
{
DBGLOG2( kLogPlugin, "CLDAPv3Plugin: Bind Request - Error %d attempting to Create computer record and open - %s", siResult, pComputerID );
throw( (sInt32) siResult );
}
}
tDataNodePtr pAttrName = ::dsDataNodeAllocateString( dsRef, kDS1AttrDistinguishedName );
DBGLOG1( kLogPlugin, "CLDAPv3Plugin: Bind Request - Attempting to set Distinguished Name value - %s", pComputerID );
::dsBuildListFromNodesAlloc( dsRef, &dataList, pRecName, NULL );
siResult = ::dsSetAttributeValues( recRef, pAttrName, &dataList );
::dsDataListDeallocatePriv( &dataList );
::dsDataNodeDeAllocate( dsRef, pAttrName );
pAttrName = NULL;
if( siResult != eDSNoErr && siResult != eDSNoStdMappingAvailable )
{
DBGLOG2( kLogPlugin, "CLDAPv3Plugin: Bind Request - Error %d attempting to set DistinguishedName value - %s", siResult, pComputerID );
throw( (sInt32) siResult );
}
CFUUIDRef cfUUID = CFUUIDCreate( kCFAllocatorDefault );
if( cfUUID )
{
CFStringRef cfUUIDStr = CFUUIDCreateString( kCFAllocatorDefault, cfUUID );
uInt32 iLength = (uInt32) CFStringGetMaximumSizeForEncoding( CFStringGetLength(cfUUIDStr), kCFStringEncodingUTF8) + 1;
char *pUUID = (char *) calloc( sizeof(char), iLength );
CFStringGetCString( cfUUIDStr, pUUID, iLength, kCFStringEncodingUTF8 );
tDataNodePtr pAttrName = ::dsDataNodeAllocateString( dsRef, kDS1AttrGeneratedUID );
::dsBuildListFromStringsAlloc( dsRef, &dataList, pUUID, NULL );
DBGLOG1( kLogPlugin, "CLDAPv3Plugin: Bind Request - Attempting to set GeneratedUID value - %s", pUUID );
siResult = ::dsSetAttributeValues( recRef, pAttrName, &dataList );
::dsDataListDeallocatePriv( &dataList );
::dsDataNodeDeAllocate( dsRef, pAttrName );
pAttrName = NULL;
CFRelease( cfUUID );
cfUUID = NULL;
CFRelease( cfUUIDStr );
cfUUIDStr = NULL;
free( pUUID );
pUUID = NULL;
if( siResult != eDSNoErr && siResult != eDSNoStdMappingAvailable )
{
DBGLOG1( kLogPlugin, "CLDAPv3Plugin: Bind Request - Error %d attempting to set GeneratedUID", siResult );
throw( (sInt32) siResult );
}
}
CFStringRef cfEnetAddr = NULL;
if( inData->fInRequestCode == eDSCustomCallLDAPv3NewServerBindOther || inData->fInRequestCode == eDSCustomCallLDAPv3NewServerForceBindOther )
{
CFStringRef cfTempAddr = (CFStringRef) CFDictionaryGetValue( cfXMLDict, CFSTR(kDS1AttrENetAddress) );
if( cfTempAddr != NULL && CFGetTypeID(cfTempAddr) == CFStringGetTypeID() )
{
CFRetain( cfTempAddr ); cfEnetAddr = cfTempAddr;
DBGLOG( kLogPlugin, "CLDAPv3Plugin: Bind Request - Received MAC Address for bind other request" );
}
else
{
DBGLOG( kLogPlugin, "CLDAPv3Plugin: Bind Request - Did not receive MAC Address for bind other request" );
}
CFDictionaryRemoveValue( cfXMLDict, CFSTR(kDS1AttrENetAddress) );
}
else
{
GetMACAddress( &cfEnetAddr, NULL );
DBGLOG( kLogPlugin, "CLDAPv3Plugin: Bind Request - Determined MAC Address from local host information" );
}
if( cfEnetAddr )
{
uInt32 iLength = (uInt32) CFStringGetMaximumSizeForEncoding( CFStringGetLength(cfEnetAddr), kCFStringEncodingUTF8) + 1;
char *pLinkAddr = (char *) calloc( sizeof(char), iLength );
CFStringGetCString( cfEnetAddr, pLinkAddr, iLength, kCFStringEncodingUTF8 );
tDataNodePtr pAttrName = ::dsDataNodeAllocateString( dsRef, kDS1AttrENetAddress );
::dsBuildListFromStringsAlloc( dsRef, &dataList, pLinkAddr, NULL );
DBGLOG1( kLogPlugin, "CLDAPv3Plugin: Bind Request - Attempting to set MAC Address - %s", pLinkAddr );
siResult = ::dsSetAttributeValues( recRef, pAttrName, &dataList );
::dsDataNodeDeAllocate( dsRef, pAttrName );
pAttrName = NULL;
::dsDataListDeallocatePriv( &dataList );
DSFreeString( pLinkAddr );
DSCFRelease( cfEnetAddr );
if( siResult != eDSNoErr && siResult != eDSNoStdMappingAvailable )
{
DBGLOG1( kLogPlugin, "CLDAPv3Plugin: Bind Request - Error %d attempting to set MAC Address", siResult );
throw( (sInt32) siResult );
}
}
const int iPassLength = 20;
char *pCompPassword = (char *) calloc( sizeof(char), iPassLength+1 );
int ii = 0;
srandomdev(); while( ii < iPassLength )
{
char cTemp = (char) (random() % 0x7f);
if( isprint(cTemp) && !isspace(cTemp) )
{
pCompPassword[ii] = cTemp;
ii++;
}
}
pAuthType = ::dsDataNodeAllocateString( dsRef, kDSStdAuthSetPasswdAsRoot );
char *pPtr = sendDataBufPtr->fBufferData;
int len = strlen( pComputerID );
*((long*)pPtr) = len;
pPtr += sizeof(long);
bcopy( pComputerID, pPtr, len );
pPtr += len;
len = strlen( pCompPassword );
*((long*)pPtr) = len;
pPtr += sizeof(long);
bcopy( pCompPassword, pPtr, len );
pPtr += len;
sendDataBufPtr->fBufferLength = pPtr - sendDataBufPtr->fBufferData;
DBGLOG1( kLogPlugin, "CLDAPv3Plugin: Bind Request - Attempting to set Password for Computer account - %s", pComputerID );
siResult = dsDoDirNodeAuthOnRecordType( dsNodeRef, pAuthType, true, sendDataBufPtr, responseDataBufPtr, 0, pRecType );
if( siResult == eDSNoErr )
{
CFDataRef cfPassword = CFDataCreate( kCFAllocatorDefault, (UInt8*)pCompPassword, strlen(pCompPassword) );
CFStringRef cfQualifier = NULL;
CFStringRef cfMapBase = (CFStringRef) CFDictionaryGetValue( cfComputerMap, CFSTR(kXMLSearchBase) );
GetAttribFromRecordDict( cfComputerMap, CFSTR(kDSNAttrRecordName), NULL, &cfQualifier );
CFStringRef cfDN = CFStringCreateWithFormat( kCFAllocatorDefault, NULL, CFSTR("%@=%@,%@"), cfQualifier, cfComputerName, cfMapBase );
if( cfDN != NULL )
{
CFDictionarySetValue( cfXMLDict, CFSTR(kXMLSecureUseFlagKey), kCFBooleanTrue );
CFDictionarySetValue( cfXMLDict, CFSTR(kXMLServerAccountKey), cfDN );
CFDictionarySetValue( cfXMLDict, CFSTR(kXMLServerPasswordKey), cfPassword );
CFDictionarySetValue( cfXMLDict, CFSTR(kXMLBoundDirectoryKey), kCFBooleanTrue );
if( dsOpenRecord(dsNodeRef, pRecType, pRecName, &recRef) == eDSNoErr )
{
tDataNodePtr pAuthAuthority = ::dsDataNodeAllocateString( dsRef, kDSNAttrAuthenticationAuthority );
tAttributeEntryPtr attribInfo = NULL;
if( dsGetRecordAttributeInfo(recRef, pAuthAuthority, &attribInfo) == eDSNoErr )
{
for( unsigned int ii = 1; ii <= attribInfo->fAttributeValueCount; ii++ )
{
tAttributeValueEntryPtr authEntry = NULL;
if( dsGetRecordAttributeValueByIndex( recRef, pAuthAuthority, ii, &authEntry ) == eDSNoErr )
{
if( strstr( authEntry->fAttributeValueData.fBufferData, kDSValueAuthAuthorityKerberosv5 ) )
{
char *pAuth = authEntry->fAttributeValueData.fBufferData;
int ii = 0;
while( strsep(&pAuth, ";") && ii++ < 2 );
if( pAuth )
{
char *pKerbIDTemp = strsep( &pAuth, ";" );
if( pKerbIDTemp && *pKerbIDTemp )
{
CFStringRef cfKerberosID = CFStringCreateWithCString( kCFAllocatorDefault, pKerbIDTemp, kCFStringEncodingUTF8 );
CFDictionarySetValue( cfXMLDict, CFSTR(kXMLKerberosId), cfKerberosID );
AddKeytabEntry( pKerbIDTemp, pCompPassword );
CFRelease( cfKerberosID );
}
}
}
dsDeallocAttributeValueEntry( dsRef, authEntry );
authEntry = NULL;
}
}
dsDeallocAttributeEntry( dsRef, attribInfo );
attribInfo = NULL;
}
dsDataNodeDeAllocate( dsRef, pAuthAuthority );
pAuthAuthority = NULL;
}
CFRelease( cfDN );
cfDN = NULL;
}
CFRelease( cfPassword );
cfPassword = NULL;
}
else
{
DBGLOG2( kLogPlugin, "CLDAPv3Plugin: Bind Request - Error %d attempting to set Password for Computer account - %s", siResult, pComputerID );
}
if( pCompPassword != NULL )
{
free( pCompPassword );
pCompPassword = NULL;
}
dsCloseRecord( recRef );
} catch( sInt32 iError ) {
siResult = iError;
} catch( ... ) {
siResult = eUndefinedError;
}
if( pRecName != NULL )
{
::dsDataNodeDeAllocate( dsRef, pRecName );
pRecName = NULL;
}
if( pAuthType != NULL )
{
::dsDataNodeDeAllocate( dsRef, pAuthType );
pAuthType = NULL;
}
if( sendDataBufPtr != NULL )
{
::dsDataBufferDeallocatePriv( sendDataBufPtr );
sendDataBufPtr = NULL;
}
if( responseDataBufPtr != NULL )
{
::dsDataBufferDeallocatePriv( responseDataBufPtr );
responseDataBufPtr = NULL;
}
DSCFRelease( cfComputerMap );
if( pServer != NULL )
{
free( pServer );
pServer = NULL;
}
DSFreeString( pUsername );
if( pPassword != NULL )
{
memset( pPassword, 0, strlen(pPassword) );
free( pPassword );
pPassword = NULL;
}
DSFreeString( pComputerID );
if( pRecType != NULL )
{
::dsDataNodeDeAllocate( dsRef, pRecType );
pRecType = NULL;
}
if( dsNodeRef )
{
dsCloseDirNode( dsNodeRef );
dsNodeRef = 0;
}
if( dsRef )
{
dsCloseDirService( dsRef );
dsRef = 0;
}
if( cfXMLDict != NULL )
{
if( siResult == eDSNoErr )
{
sInt32 iError = PutXMLInBuffer( cfXMLDict, inData->fOutRequestResponse );
if( iError != eDSNoErr ) {
siResult = iError;
}
}
CFRelease( cfXMLDict );
cfXMLDict = NULL;
}
return siResult;
}
sInt32 CLDAPv3Plugin::DoNewServerSetup( sDoPlugInCustomCall *inData )
{
sInt32 siResult = eDSInvalidBuffFormat;
CFMutableDictionaryRef cfXMLDict = NULL;
CFMutableDictionaryRef cfConfigXML = NULL;
CFDataRef cfTempData = NULL;
CFIndex iIndex = 0;
cfXMLDict = GetXMLFromBuffer( inData->fInRequestData );
if( cfXMLDict != NULL )
{
cfTempData = gpConfigFromXML->CopyXMLConfig();
cfConfigXML = (CFMutableDictionaryRef) CFPropertyListCreateFromXMLData( kCFAllocatorDefault, cfTempData, kCFPropertyListMutableContainersAndLeaves, NULL );
CFRelease( cfTempData );
cfTempData = NULL;
CFMutableArrayRef cfConfigList = (CFMutableArrayRef) CFDictionaryGetValue( cfConfigXML, CFSTR(kXMLConfigArrayKey) );
CFStringRef cfServer = GetServerInfoFromConfig( cfXMLDict, NULL, NULL, NULL, NULL, NULL );
if( IsServerInConfig(cfConfigXML, cfServer, &iIndex, NULL) )
{
CFArraySetValueAtIndex( cfConfigList, iIndex, cfXMLDict );
}
else
{
if( cfConfigList == NULL )
{
cfConfigList = CFArrayCreateMutable( kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks );
CFDictionarySetValue( cfConfigXML, CFSTR(kXMLConfigArrayKey), cfConfigList );
CFRelease( cfConfigList ); }
CFArrayAppendValue( cfConfigList, cfXMLDict );
}
CFStringRef cfPassword = (CFStringRef) CFDictionaryGetValue( cfXMLDict, CFSTR(kXMLServerPasswordKey) );
if( cfPassword && CFGetTypeID(cfPassword) == CFStringGetTypeID() )
{
CFDataRef cfPassData = CFStringCreateExternalRepresentation( kCFAllocatorDefault, cfPassword, kCFStringEncodingUTF8, 0 );
CFDictionarySetValue( cfXMLDict, CFSTR(kXMLServerPasswordKey), cfPassData );
CFRelease( cfPassData );
}
cfTempData = (CFDataRef) CFPropertyListCreateXMLData( kCFAllocatorDefault, cfConfigXML );
CFRelease( cfConfigXML );
cfConfigXML = NULL;
siResult = gpConfigFromXML->SetXMLConfig( cfTempData );
CFRelease( cfTempData );
cfTempData = NULL;
Initialize();
}
if( cfXMLDict != NULL )
{
if( siResult == eDSNoErr )
{
sInt32 iError = PutXMLInBuffer( cfXMLDict, inData->fOutRequestResponse );
if( iError != eDSNoErr ) {
siResult = iError;
}
}
CFRelease( cfXMLDict );
cfXMLDict = NULL;
}
return siResult;
}
sInt32 CLDAPv3Plugin::DoRemoveServer( sDoPlugInCustomCall *inData )
{
sInt32 siResult = eDSNoErr;
CFDictionaryRef cfXMLDict = NULL; CFDictionaryRef cfConfigDict = NULL; CFMutableDictionaryRef cfServerDict = NULL; CFIndex iConfigIndex = 0;
char *pServer = NULL;
char *pUsername = NULL;
char *pPassword = NULL;
char *pComputerID = NULL;
tDirReference dsRef = 0;
tDirNodeReference dsNodeRef = 0;
tDataNodePtr pRecType = ::dsDataNodeAllocateString( dsRef, kDSStdRecordTypeComputers );;
tDataBufferPtr responseDataBufPtr = ::dsDataBufferAllocatePriv( 1024 );
tDataBufferPtr sendDataBufPtr = ::dsDataBufferAllocatePriv( 1024 );
tDataNodePtr pAuthType = NULL;
tDataNodePtr pRecName = NULL;
CFMutableArrayRef cfConfigList = NULL;
try
{
cfXMLDict = GetXMLFromBuffer( inData->fInRequestData );
if( cfXMLDict == NULL ) {
throw( (sInt32) eDSInvalidBuffFormat );
}
CFStringRef cfServer = GetServerInfoFromConfig( cfXMLDict, &pServer, NULL, NULL, &pUsername, &pPassword );
if( cfServer == NULL )
{
throw( (sInt32) eDSInvalidBuffFormat );
}
CFDataRef cfTempData = gpConfigFromXML->CopyXMLConfig();
cfConfigDict = (CFMutableDictionaryRef) CFPropertyListCreateFromXMLData( kCFAllocatorDefault, cfTempData, kCFPropertyListMutableContainersAndLeaves, NULL );
cfConfigList = (CFMutableArrayRef) CFDictionaryGetValue( cfConfigDict, CFSTR(kXMLConfigArrayKey) );
CFRelease( cfTempData );
cfTempData = NULL;
if( IsServerInConfig( cfConfigDict, cfServer, &iConfigIndex, &cfServerDict ) == false )
{
throw( (sInt32) eDSBogusServer );
}
CFBooleanRef cfBound = (CFBooleanRef) CFDictionaryGetValue( cfServerDict, CFSTR(kXMLBoundDirectoryKey) );
bool bBound = false;
if( cfBound != NULL && CFGetTypeID(cfBound) == CFBooleanGetTypeID() )
{
bBound = CFBooleanGetValue( cfBound );
}
if( bBound )
{
if( pUsername == NULL || pPassword == NULL )
{
throw( (sInt32) eDSAuthParameterError );
}
char *pComputerDN = NULL;
GetServerInfoFromConfig( cfServerDict, NULL, NULL, NULL, &pComputerDN, NULL );
if( pComputerDN == NULL )
{
throw( (sInt32) eDSBogusServer );
}
char **pDN = ldap_explode_dn( pComputerDN, 1 );
if( pDN != NULL )
{
pComputerID = strdup( pDN[0] );
ldap_value_free( pDN );
pDN = NULL;
}
free( pComputerDN );
pComputerDN = NULL;
siResult = ::dsOpenDirService( &dsRef );
if( siResult != eDSNoErr )
{
throw( siResult );
}
char *pNodeName = (char *) calloc(1, strlen(pServer)+10);
strcpy( pNodeName, "/LDAPv3/" );
strcat( pNodeName, pServer );
tDataList *nodeString = ::dsBuildFromPathPriv( pNodeName, "/" );
delete pNodeName;
pNodeName = NULL;
siResult = ::dsOpenDirNode( dsRef, nodeString, &dsNodeRef );
::dsDataListDeallocatePriv( nodeString );
free( nodeString );
nodeString = NULL;
if( siResult == eDSOpenNodeFailed && inData->fInRequestCode == eDSCustomCallLDAPv3ForceUnbindServerConfig )
{
throw( (sInt32) eDSNoErr );
}
else if( siResult != eDSNoErr )
{
throw( siResult );
}
uInt32 iNameLen = strlen( pUsername );
uInt32 iPassLen = strlen( pPassword );
uInt32 authDataSize = iNameLen + iPassLen + (2 * sizeof(uInt32));
pAuthType = ::dsDataNodeAllocateString( dsRef, kDSStdAuthNodeNativeNoClearText );
sendDataBufPtr->fBufferLength = authDataSize;
char *ptr = (char*)(sendDataBufPtr->fBufferData);
*((uInt32 *)ptr) = iNameLen;
ptr += sizeof(uInt32);
bcopy( pUsername, ptr, iNameLen );
ptr += iNameLen;
*((uInt32 *)ptr) = iPassLen;
ptr += sizeof(uInt32);
bcopy( pPassword, ptr, iPassLen );
if( (siResult = dsDoDirNodeAuth( dsNodeRef, pAuthType, false, sendDataBufPtr, responseDataBufPtr, 0)) != eDSNoErr )
{
throw( (sInt32) siResult );
}
if( pAuthType != NULL )
{
::dsDataNodeDeAllocate( dsRef, pAuthType );
pAuthType = NULL;
}
tRecordReference recRef = 0;
pRecName = ::dsDataNodeAllocateString( dsRef, pComputerID );
siResult = dsOpenRecord( dsNodeRef, pRecType, pRecName, &recRef );
if( siResult == eDSNoErr )
{
sendDataBufPtr->fBufferLength = sizeof( recRef );
bcopy( &recRef, sendDataBufPtr->fBufferData, sizeof(recRef) );
siResult = ::dsDoPlugInCustomCall( dsNodeRef, eRecordDeleteAndCredentials, sendDataBufPtr, responseDataBufPtr );
if( siResult != eDSNoErr )
{
if( inData->fInRequestCode == eDSCustomCallLDAPv3UnbindServerConfig ) {
throw( (sInt32) siResult );
}
}
}
if( inData->fInRequestCode == eDSCustomCallLDAPv3ForceUnbindServerConfig ) {
siResult = eDSNoErr;
}
else
{
throw( siResult );
}
}
siResult = eDSNoErr;
} catch( sInt32 iError ) {
siResult = iError;
} catch( ... ) {
siResult = eUndefinedError;
}
if( siResult == eDSNoErr )
{
CFStringRef kerberosID = (CFStringRef) CFDictionaryGetValue( cfServerDict, CFSTR(kXMLKerberosId) );
char *pKerberosID = NULL;
if (kerberosID != NULL && CFStringGetLength(kerberosID) > 0)
{
uInt32 callocLength = (uInt32) CFStringGetMaximumSizeForEncoding(CFStringGetLength(kerberosID), kCFStringEncodingUTF8) + 1;
pKerberosID = (char *) calloc( 1, callocLength );
CFStringGetCString( kerberosID, pKerberosID, callocLength, kCFStringEncodingUTF8 );
}
if( pKerberosID != NULL )
{
krb5_context krbContext = NULL;
krb5_principal principal = NULL;
krb5_ccache krbCache = NULL;
char *principalString = NULL;
char *pCacheName = NULL;
RemoveKeytabEntry( pKerberosID );
int retval = krb5_init_context( &krbContext );
if( 0 == retval )
retval = krb5_parse_name( krbContext, pKerberosID, &principal );
if( 0 == retval )
retval = krb5_unparse_name( krbContext, principal, &principalString );
if( 0 == retval )
{
pCacheName = (char *) malloc( strlen(principalString) + sizeof("MEMORY:") + 1 );
strcpy( pCacheName, "MEMORY:" );
strcat( pCacheName, principalString );
retval = krb5_cc_resolve( krbContext, pCacheName, &krbCache );
}
if( NULL != principal )
{
krb5_free_principal( krbContext, principal );
principal = NULL;
}
if( NULL != krbCache )
{
krb5_cc_destroy( krbContext, krbCache );
krbCache = NULL;
DBGLOG1( kLogPlugin, "CLDAPv3Plugin: Destroying kerberos Memory cache for %s", principalString );
}
if( NULL != krbContext )
{
krb5_free_context( krbContext );
krbContext = NULL;
}
DSFreeString( pCacheName );
DSFreeString( principalString );
}
DSFreeString( pKerberosID );
CFDictionarySetValue( cfServerDict, CFSTR(kXMLBoundDirectoryKey), kCFBooleanFalse );
CFDictionarySetValue( cfServerDict, CFSTR(kXMLSecureUseFlagKey), kCFBooleanFalse );
CFDictionarySetValue( cfServerDict, CFSTR(kXMLServerAccountKey), CFSTR("") );
CFDictionarySetValue( cfServerDict, CFSTR(kXMLServerPasswordKey), CFSTR("") );
CFDictionarySetValue( cfServerDict, CFSTR(kXMLKerberosId), CFSTR("") );
if( inData->fInRequestCode == eDSCustomCallLDAPv3RemoveServerConfig )
{
CFArrayRemoveValueAtIndex( cfConfigList, iConfigIndex );
}
CFDataRef cfTempData = (CFDataRef) CFPropertyListCreateXMLData( kCFAllocatorDefault, cfConfigDict );
siResult = gpConfigFromXML->SetXMLConfig( cfTempData );
CFRelease( cfTempData );
cfTempData = NULL;
Initialize();
}
if( pRecName != NULL )
{
::dsDataNodeDeAllocate( dsRef, pRecName );
pRecName = NULL;
}
if( pAuthType != NULL )
{
::dsDataNodeDeAllocate( dsRef, pAuthType );
pAuthType = NULL;
}
if( sendDataBufPtr != NULL )
{
::dsDataBufferDeallocatePriv( sendDataBufPtr );
sendDataBufPtr = NULL;
}
if( responseDataBufPtr != NULL )
{
::dsDataBufferDeallocatePriv( responseDataBufPtr );
responseDataBufPtr = NULL;
}
DSFreeString( pServer );
DSFreeString( pUsername );
if( pPassword != NULL )
{
memset( pPassword, 0, strlen(pPassword) );
free( pPassword );
pPassword = NULL;
}
DSFreeString( pComputerID );
if( pRecType != NULL )
{
::dsDataNodeDeAllocate( dsRef, pRecType );
pRecType = NULL;
}
if( dsNodeRef )
{
dsCloseDirNode( dsNodeRef );
dsNodeRef = 0;
}
if( dsRef )
{
dsCloseDirService( dsRef );
dsRef = 0;
}
if( cfServerDict != NULL )
{
if( siResult == eDSNoErr )
{
sInt32 iError = PutXMLInBuffer( cfServerDict, inData->fOutRequestResponse );
if( iError != eDSNoErr ) {
siResult = iError;
}
}
CFRelease( cfServerDict );
cfServerDict = NULL;
}
DSCFRelease( cfConfigDict );
DSCFRelease( cfXMLDict );
return siResult;
}
#pragma mark -
#pragma mark Other functions
void CLDAPv3Plugin::ContextDeallocProc ( void* inContextData )
{
sLDAPContextData *pContext = (sLDAPContextData *) inContextData;
if ( pContext != nil )
{
delete pContext;
pContext = nil;
}
}
void CLDAPv3Plugin::ContinueDeallocProc ( void* inContinueData )
{
sLDAPContinueData *pLDAPContinue = (sLDAPContinueData *)inContinueData;
uInt32 refNum = 0;
sLDAPContextData *pContext = nil;
LDAP *aHost = nil;
int rc = 0;
if ( pLDAPContinue != nil )
{
if (pLDAPContinue->pResult != nil)
{
ldap_msgfree( pLDAPContinue->pResult );
pLDAPContinue->pResult = nil;
}
if (pLDAPContinue->msgId != 0)
{
refNum = gLDAPContinueTable->GetRefNumForItem( inContinueData );
pContext = (sLDAPContextData *)gLDAPContextTable->GetItemData( refNum );
if (pContext != nil)
{
aHost = fLDAPSessionMgr.LockSession(pContext);
if (aHost != nil)
{
rc = ldap_abandon(aHost,pLDAPContinue->msgId);
pLDAPContinue->msgId = 0;
}
fLDAPSessionMgr.UnLockSession(pContext,false);
}
}
free( pLDAPContinue );
pLDAPContinue = nil;
}
}
sInt32 CLDAPv3Plugin:: RebindLDAPSession ( sLDAPContextData *inContext, CLDAPNode& inLDAPSessionMgr )
{
sInt32 siResult = eDSNoErr;
if (inContext != nil)
{
siResult = inLDAPSessionMgr.RebindSession( inContext->fLDAPNodeStruct );
}
else
{
siResult = eDSNullParameter;
}
return (siResult);
}
sInt32 CLDAPv3Plugin::GetRecRefLDAPMessage ( sLDAPContextData *inRecContext, int &ldapMsgId, char **inAttrs, LDAPMessage **outResultMsg )
{
sInt32 siResult = eDSNoErr;
int searchTO = 0;
int numRecTypes = 1;
char *pLDAPRecType = nil;
bool bResultFound = false;
char *queryFilter = nil;
LDAPMessage *result = nil;
int ldapReturnCode = 0;
bool bOCANDGroup = false;
CFArrayRef OCSearchList = nil;
ber_int_t scope = LDAP_SCOPE_SUBTREE;
sInt32 searchResult = eDSNoErr;
try
{
if ( inRecContext->fOpenRecordName == nil ) throw( (sInt32)eDSNullRecName );
if ( inRecContext->fOpenRecordType == nil ) throw( (sInt32)eDSNullRecType );
sLDAPConfigData *pConfig = gpConfigFromXML->ConfigWithNodeNameLock( inRecContext->fNodeName );
if (pConfig != nil)
{
searchTO = pConfig->fSearchTimeout;
gpConfigFromXML->ConfigUnlock( pConfig );
pConfig = NULL;
}
numRecTypes = 1;
bOCANDGroup = false;
if (OCSearchList != nil)
{
CFRelease(OCSearchList);
OCSearchList = nil;
}
pLDAPRecType = MapRecToLDAPType( (const char *)(inRecContext->fOpenRecordType), inRecContext->fNodeName, numRecTypes, &bOCANDGroup, &OCSearchList, &scope );
if ( pLDAPRecType == nil ) throw( (sInt32)eDSInvalidRecordType );
while ( (pLDAPRecType != nil) && (!bResultFound) )
{
queryFilter = BuildLDAPQueryFilter( (char *)kDSNAttrRecordName, inRecContext->fOpenRecordName,
eDSExact,
inRecContext->fNodeName,
false,
(const char *)(inRecContext->fOpenRecordType),
pLDAPRecType,
bOCANDGroup,
OCSearchList );
if ( queryFilter == nil ) throw( (sInt32)eDSNullParameter );
searchResult = DSDoRetrieval ( pLDAPRecType,
inAttrs,
inRecContext,
scope,
fLDAPSessionMgr,
queryFilter,
ldapReturnCode,
searchTO,
result,
bResultFound,
ldapMsgId );
if ( queryFilter != nil )
{
delete( queryFilter );
queryFilter = nil;
}
if (pLDAPRecType != nil)
{
delete (pLDAPRecType);
pLDAPRecType = nil;
}
numRecTypes++;
bOCANDGroup = false;
if (OCSearchList != nil)
{
CFRelease(OCSearchList);
OCSearchList = nil;
}
pLDAPRecType = MapRecToLDAPType( (const char *)(inRecContext->fOpenRecordType), inRecContext->fNodeName, numRecTypes, &bOCANDGroup, &OCSearchList, &scope );
}
if ( (bResultFound) &&
( ldapReturnCode == LDAP_RES_SEARCH_ENTRY ) )
{
siResult = eDSNoErr;
} else
{
siResult = searchResult;
if ( result != nil )
{
ldap_msgfree( result );
result = nil;
}
}
}
catch ( sInt32 err )
{
siResult = err;
}
DSCFRelease(OCSearchList);
DSFreeString(pLDAPRecType);
DSFreeString(queryFilter);
if (result != nil)
{
*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 )
{
if ( HandlingNetworkTransition() == false )
fLDAPSessionMgr.CheckIdles();
return( eDSNoErr );
}
void CLDAPv3Plugin::HandleMultipleNetworkTransitionsForLDAP ( void )
{
void *ptInfo = nil;
if (fServerRunLoop != nil)
{
if( fTimerRef != NULL )
{
DBGLOG1( kLogPlugin, "T[%X] CLDAPv3Plugin::HandleMultipleNetworkTransitionsForLDAP invalidating previous timer", pthread_self() );
CFRunLoopTimerInvalidate( fTimerRef );
CFRelease( fTimerRef );
fTimerRef = NULL;
}
DBGLOG1( kLogPlugin, "T[%X] CLDAPv3Plugin::HandleMultipleNetworkTransitionsForLDAP, setting fHandlingNetworkTransition to true", pthread_self() );
fHandlingNetworkTransition = true;
ptInfo = (void *)this;
CFRunLoopTimerContext c = {0, (void*)ptInfo, NULL, NULL, NetworkChangeLDAPPICopyStringCallback};
fTimerRef = CFRunLoopTimerCreate( NULL,
CFAbsoluteTimeGetCurrent() + 5.0,
0,
0,
0,
DoLDAPPINetworkChange,
(CFRunLoopTimerContext*)&c);
CFRunLoopAddTimer(fServerRunLoop, fTimerRef, kCFRunLoopDefaultMode);
}
}
void CLDAPv3Plugin::ReInitForNetworkTransition ( void )
{
if ( fHandlingNetworkTransition )
{
Initialize();
DBGLOG1( kLogPlugin, "T[%X] CLDAPv3Plugin::ReInitForNetworkTransition, setting fHandlingNetworkTransition to false", pthread_self() );
fHandlingNetworkTransition = false;
}
}
void CLDAPv3Plugin::WaitForNetworkTransitionToFinishWithFunctionName( const char* callerFunction )
{
if ( fHandlingNetworkTransition )
{
DSSemaphore timedWait;
double waitTime = dsTimestamp() + USEC_PER_SEC*10;
DBGLOG2( kLogPlugin, "T[%X] %s called, waiting for WaitForNetworkTransitionToFinish", pthread_self(), callerFunction );
while( fHandlingNetworkTransition )
{
timedWait.Wait( (uInt32)(.5 * kMilliSecsPerSec) );
if ( dsTimestamp() > waitTime )
{
DBGLOG2( kLogPlugin, "T[%X] %s called, waited as long as we are going to for WaitForNetworkTransitionToFinish", pthread_self(), callerFunction );
break;
}
}
DBGLOG2( kLogPlugin, "T[%X] %s called, finished WaitForNetworkTransitionToFinish", pthread_self(), callerFunction );
}
}
char* CLDAPv3Plugin::MappingNativeVariableSubstitution( char *inLDAPAttrType,
sLDAPContextData *inContext,
LDAPMessage *inResult,
sInt32& 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 = fLDAPSessionMgr.LockSession(inContext);
if (aHost != nil)
{
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, sizeof(char));
::memcpy(tokenValues[tokenStep], vsBValues[0]->bv_val, vsBValues[0]->bv_len);
ldap_value_free_len(vsBValues);
vsBValues = nil;
}
} } }
fLDAPSessionMgr.UnLockSession(inContext);
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::BuildEscapedRDN( const char *inLDAPRDN )
{
char *outLDAPRDN = nil;
uInt32 recNameLen = 0;
uInt32 originalIndex = 0;
uInt32 escapedIndex = 0;
if (inLDAPRDN != nil)
{
recNameLen = strlen(inLDAPRDN);
outLDAPRDN = (char *)::calloc(1, 2 * recNameLen + 1);
while (originalIndex < recNameLen)
{
switch (inLDAPRDN[originalIndex])
{
case ' ':
outLDAPRDN[escapedIndex] = '\\';
++escapedIndex;
outLDAPRDN[escapedIndex] = inLDAPRDN[originalIndex];
++escapedIndex;
break;
case '#':
if (originalIndex == 0 )
{
outLDAPRDN[escapedIndex] = '\\';
++escapedIndex;
outLDAPRDN[escapedIndex] = inLDAPRDN[originalIndex];
++escapedIndex;
}
break;
case ',':
case '+':
case '"':
case '\\':
case '<':
case '>':
case ';':
outLDAPRDN[escapedIndex] = '\\';
++escapedIndex;
default:
outLDAPRDN[escapedIndex] = inLDAPRDN[originalIndex];
++escapedIndex;
break;
}
++originalIndex;
}
}
return(outLDAPRDN);
}
char *CLDAPv3Plugin::GetPWSIDforRecord( sLDAPContextData *pContext, char *inRecName, char *inRecType )
{
char **aaArray = NULL;
unsigned long aaCount = 0;
char *pUserID = NULL;
int siResult = GetAuthAuthority( pContext, inRecName, 0, fLDAPSessionMgr, &aaCount, &aaArray, inRecType );
if ( siResult == eDSNoErr )
{
for ( unsigned long idx = 0; idx < aaCount; idx++ )
{
char *aaVersion = NULL;
char *aaTag = NULL;
char *aaData = NULL;
siResult = ParseAuthAuthority( aaArray[idx], &aaVersion, &aaTag, &aaData );
if( aaTag != NULL && strcasecmp( aaTag, kDSTagAuthAuthorityPasswordServer ) == 0 )
{
pUserID = aaData;
aaData = NULL;
}
DSFreeString( aaArray[idx] )
DSFreeString( aaVersion );
DSFreeString( aaTag );
DSFreeString( aaData );
}
DSFree( aaArray );
}
return pUserID;
}