AuthHelperUtils.cpp [plain text]
#include "AuthHelperUtils.h"
#include "DSUtils.h"
#include "CDSPluginUtils.h"
#include "CRefTable.h"
#include <PasswordServer/AuthFile.h>
extern pid_t gDaemonPID;
extern in_addr_t gDaemonIPAddress;
extern CRefTable gRefTable;
tDirStatus ParseLocalCacheUserAuthData( const char *inAuthData,
char **outNodeName,
char **outRecordName,
char **outGUID )
{
char* authData = NULL;
char* current = NULL;
char* tempPtr = NULL;
tDirStatus result = eDSAuthFailed;
if ( inAuthData == NULL )
{
return eDSEmptyBuffer;
}
if ( outNodeName == NULL )
{
return eDSEmptyNodeName;
}
if ( outRecordName == NULL )
{
return eDSEmptyRecordName;
}
if ( outGUID == NULL )
{
return eDSEmptyParameter;
}
authData = strdup(inAuthData);
if (authData == NULL)
{
return eDSAuthFailed;
}
current = authData;
do {
tempPtr = strsep(¤t, ":");
if (tempPtr == NULL)
{
result = eDSEmptyNodeName;
break;
}
*outNodeName = strdup(tempPtr);
tempPtr = strsep(¤t, ":");
if (tempPtr == NULL)
{
result = eDSEmptyRecordName;
break;
}
*outRecordName = strdup(tempPtr);
tempPtr = strsep(¤t, ":");
if (tempPtr == NULL)
{
result = eDSEmptyParameter;
break;
}
*outGUID = strdup(tempPtr);
result = eDSNoErr;
} while (false);
free(authData);
authData = NULL;
if (result != eDSNoErr)
{
if (*outNodeName != NULL)
{
free(*outNodeName);
*outNodeName = NULL;
}
if (*outRecordName != NULL)
{
free(*outRecordName);
*outRecordName = NULL;
}
if (*outGUID != NULL)
{
free(*outGUID);
*outGUID = NULL;
}
}
return result;
}
tDirStatus GetStateFilePath( const char *inHashPath, char **outStateFilePath )
{
tDirStatus siResult = eDSNoErr;
if ( inHashPath == NULL || outStateFilePath == NULL )
return eParameterError;
*outStateFilePath = NULL;
char *stateFilePath = (char *) calloc( strlen(inHashPath) + sizeof(kShadowHashStateFileSuffix) + 1, 1 );
if ( stateFilePath != NULL )
{
strcpy( stateFilePath, inHashPath );
strcat( stateFilePath, kShadowHashStateFileSuffix );
*outStateFilePath = stateFilePath;
}
else
{
siResult = eMemoryError;
}
return siResult;
}
tDirStatus ReadShadowHash(
const char *inUserName,
const char *inGUIDString,
unsigned char outHashes[kHashTotalLength],
struct timespec *outModTime,
char **outUserHashPath,
SInt32 *outHashDataLen,
bool readHashes )
{
tDirStatus siResult = eDSAuthFailed;
char *path = NULL;
char hexHashes[kHashTotalHexLength + 1] = { 0 };
SInt32 readBytes = 0;
UInt32 outBytes = 0;
CFile *hashFile = NULL;
UInt32 pathSize = 0;
try
{
if ( outModTime != NULL )
{
outModTime->tv_sec = 0;
outModTime->tv_nsec = 0;
}
if ( outUserHashPath != NULL )
*outUserHashPath = NULL;
if ( outHashDataLen != NULL )
*outHashDataLen = 0;
if (inGUIDString != NULL)
{
pathSize = sizeof(kShadowHashDirPath) + strlen(inGUIDString) + 1;
}
else
{
pathSize = sizeof(kShadowHashDirPath) + strlen(inUserName) + 1;
}
path = (char*)::calloc(pathSize, 1);
if ( path != NULL )
{
if (inGUIDString != NULL)
{
strcpy( path, kShadowHashDirPath );
strcat( path, inGUIDString );
}
else
{
strcpy( path, kShadowHashDirPath );
strcat( path, inUserName );
}
try {
hashFile = new CFile(path, false);
} catch ( ... ) {
}
if (hashFile != NULL && hashFile->is_open())
{
if ( outModTime != NULL )
hashFile->ModDate( outModTime );
if ( readHashes )
{
bzero( hexHashes, sizeof(hexHashes) );
readBytes = hashFile->ReadBlock( hexHashes, kHashTotalHexLength );
delete(hashFile);
hashFile = NULL;
if ( readBytes < kHashShadowBothHexLength ) throw( eDSAuthFailed );
HexToBinaryConversion( hexHashes, &outBytes, outHashes );
if ( readBytes == (kHashTotalLength - 16)*2 )
{
memmove( outHashes + kHashOffsetToSaltedSHA1, outHashes + kHashOffsetToSaltedSHA1 - 16,
readBytes - kHashOffsetToSaltedSHA1 );
bzero( outHashes + kHashOffsetToCramMD5, kHashCramLength );
}
}
siResult = eDSNoErr;
}
else {
if (hashFile != NULL)
{
delete(hashFile);
hashFile = NULL;
}
free( path );
path = NULL;
path = (char*)::calloc(sizeof(kShadowHashOldDirPath) + strlen(inUserName) + 1, 1);
if ( path != NULL )
{
sprintf(path, "%s%s", kShadowHashOldDirPath, inUserName);
try
{
hashFile = new CFile(path, false);
if (hashFile->is_open())
{
if ( outModTime != NULL )
hashFile->ModDate( outModTime );
if ( readHashes )
{
readBytes = hashFile->ReadBlock( hexHashes, kHashShadowBothHexLength );
delete(hashFile);
hashFile = NULL;
if ( readBytes != kHashShadowBothHexLength ) throw( eDSAuthFailed );
HexToBinaryConversion( hexHashes, &outBytes, outHashes );
}
siResult = eDSNoErr;
}
}
catch( ... )
{
}
}
}
}
}
catch( ... )
{
siResult = eDSAuthFailed;
}
if ( path != NULL )
{
if ( outUserHashPath != NULL )
{
*outUserHashPath = path;
}
else
{
free( path );
path = NULL;
}
}
if (hashFile != NULL)
{
delete(hashFile);
hashFile = NULL;
}
bzero(hexHashes, kHashTotalHexLength);
if ( outHashDataLen != NULL )
*outHashDataLen = outBytes;
return( siResult );
}
tDirStatus ReadStateFile(
const char *inUserName,
const char *inGUIDString,
struct timespec *outModTime,
char **outUserHashPath,
char **outStateFilePath,
sHashState *inOutHashState,
SInt32 *outHashDataLen )
{
unsigned char hashes[kHashTotalLength];
if ( outStateFilePath == NULL || outUserHashPath == NULL )
return eParameterError;
*outStateFilePath = NULL;
tDirStatus siResult = ReadShadowHash( inUserName, inGUIDString, hashes, outModTime, outUserHashPath,
outHashDataLen, false );
if ( siResult == eDSNoErr )
siResult = GetStateFilePath( *outUserHashPath, outStateFilePath );
if ( siResult == eDSNoErr && inOutHashState != NULL )
{
siResult = (tDirStatus)ReadHashStateFile( *outStateFilePath, inOutHashState );
if (siResult != eDSNoErr)
{
siResult = eDSNoErr;
}
}
return siResult;
}
int ReadHashStateFile( const char *inFilePath, sHashState *inOutHashState )
{
CFStringRef myReplicaDataFilePathRef;
CFURLRef myReplicaDataFileRef;
CFReadStreamRef myReadStreamRef;
CFPropertyListRef myPropertyListRef;
CFStringRef errorString;
CFPropertyListFormat myPLFormat;
struct stat sb;
CFMutableDictionaryRef stateDict = NULL;
CFStringRef keyString = NULL;
CFDateRef dateValue = NULL;
CFNumberRef numberValue = NULL;
long aLongValue;
short aShortValue;
int returnValue = 0;
if ( inFilePath == NULL || inOutHashState == NULL )
return -1;
do
{
if ( stat( inFilePath, &sb ) != 0 )
{
time_t now;
time( &now );
gmtime_r( &now, &inOutHashState->creationDate );
returnValue = -1;
break;
}
myReplicaDataFilePathRef = CFStringCreateWithCString( kCFAllocatorDefault, inFilePath, kCFStringEncodingUTF8 );
if ( myReplicaDataFilePathRef == NULL )
{
returnValue = -1;
break;
}
myReplicaDataFileRef = CFURLCreateWithFileSystemPath( kCFAllocatorDefault, myReplicaDataFilePathRef,
kCFURLPOSIXPathStyle, false );
CFRelease( myReplicaDataFilePathRef );
if ( myReplicaDataFileRef == NULL )
{
returnValue = -1;
break;
}
myReadStreamRef = CFReadStreamCreateWithFile( kCFAllocatorDefault, myReplicaDataFileRef );
CFRelease( myReplicaDataFileRef );
if ( myReadStreamRef == NULL )
{
returnValue = -1;
break;
}
CFReadStreamOpen( myReadStreamRef );
errorString = NULL;
myPLFormat = kCFPropertyListXMLFormat_v1_0;
myPropertyListRef = CFPropertyListCreateFromStream( kCFAllocatorDefault, myReadStreamRef, 0,
kCFPropertyListMutableContainersAndLeaves, &myPLFormat, &errorString );
CFReadStreamClose( myReadStreamRef );
CFRelease( myReadStreamRef );
if ( errorString != NULL )
{
char errMsg[256];
if ( CFStringGetCString( errorString, errMsg, sizeof(errMsg), kCFStringEncodingUTF8 ) )
DbgLog(kLogPlugin, "ReadHashStateFile: could not load the state file, error = %s", errMsg );
CFRelease( errorString );
}
if ( myPropertyListRef == NULL )
{
DbgLog(kLogPlugin, "ReadHashStateFile: could not load the hash state file because the property list is empty." );
returnValue = -1;
break;
}
if ( CFGetTypeID(myPropertyListRef) != CFDictionaryGetTypeID() )
{
CFRelease( myPropertyListRef );
DbgLog(kLogPlugin, "ReadHashStateFile: could not load the hash state file because the property list is not a dictionary." );
returnValue = -1;
break;
}
stateDict = (CFMutableDictionaryRef)myPropertyListRef;
keyString = CFStringCreateWithCString( kCFAllocatorDefault, "CreationDate", kCFStringEncodingUTF8 );
if ( keyString != NULL )
{
if ( CFDictionaryGetValueIfPresent( stateDict, keyString, (const void **)&dateValue ) )
{
pwsf_ConvertCFDateToBSDTime( dateValue, &inOutHashState->creationDate );
}
CFRelease( keyString );
}
keyString = CFStringCreateWithCString( kCFAllocatorDefault, "LastLoginDate", kCFStringEncodingUTF8 );
if ( keyString != NULL )
{
if ( CFDictionaryGetValueIfPresent( stateDict, keyString, (const void **)&dateValue ) )
{
pwsf_ConvertCFDateToBSDTime( dateValue, &inOutHashState->lastLoginDate );
}
CFRelease( keyString );
}
keyString = CFStringCreateWithCString( kCFAllocatorDefault, "FailedLoginCount", kCFStringEncodingUTF8 );
if ( keyString != NULL )
{
if ( CFDictionaryGetValueIfPresent( stateDict, keyString, (const void **)&numberValue ) &&
CFGetTypeID(numberValue) == CFNumberGetTypeID() &&
CFNumberGetValue( (CFNumberRef)numberValue, kCFNumberLongType, &aLongValue) )
{
inOutHashState->failedLoginAttempts = (UInt16)aLongValue;
}
CFRelease( keyString );
}
keyString = CFStringCreateWithCString( kCFAllocatorDefault, "NewPasswordRequired", kCFStringEncodingUTF8 );
if ( keyString != NULL )
{
if ( CFDictionaryGetValueIfPresent( stateDict, keyString, (const void **)&numberValue ) &&
CFGetTypeID(numberValue) == CFNumberGetTypeID() &&
CFNumberGetValue( (CFNumberRef)numberValue, kCFNumberSInt16Type, &aShortValue) )
{
inOutHashState->newPasswordRequired = (UInt16)aShortValue;
}
CFRelease( keyString );
}
CFRelease( stateDict );
} while( false );
return returnValue;
}
tDirStatus GetUserPolicies(
CFMutableDictionaryRef inMutableRecordDict,
sHashState* inState,
CDSLocalPlugin* inPlugin,
char** outPolicyStr )
{
tDirStatus dirStatus = eDSNoErr;
char* internalPolicyStr = NULL;
long length = 0;
char* cStr = NULL;
size_t cStrSize = 0;
try
{
if ( outPolicyStr == NULL )
throw( eParameterError );
*outPolicyStr = NULL;
CFStringRef nativeAttr = inPlugin->AttrNativeTypeForStandardType( CFSTR( kDS1AttrPasswordPolicyOptions ) );
CFArrayRef attrValues = (CFArrayRef)CFDictionaryGetValue( inMutableRecordDict, nativeAttr );
CFStringRef xmlPolicyString = NULL;
if ( ( attrValues != NULL ) && ( CFArrayGetCount( attrValues ) > 0 ) )
xmlPolicyString = (CFStringRef)CFArrayGetValueAtIndex( attrValues, 0 );
if ( ( xmlPolicyString != NULL ) && ( CFStringGetLength( xmlPolicyString ) > 0 ) )
ConvertXMLPolicyToSpaceDelimited( CStrFromCFString( xmlPolicyString, &cStr, &cStrSize, NULL ),
&internalPolicyStr );
if ( inState != NULL )
{
if ( internalPolicyStr != NULL )
length = ::strlen( internalPolicyStr );
*outPolicyStr = (char*)::malloc( sizeof(kPWPolicyStr_newPasswordRequired) + 3 + length );
if ( (*outPolicyStr) != NULL )
{
::strcpy( (*outPolicyStr), kPWPolicyStr_newPasswordRequired );
::strcpy( (*outPolicyStr) + sizeof(kPWPolicyStr_newPasswordRequired) - 1,
inState->newPasswordRequired ? "=1" : "=0" );
if ( internalPolicyStr != NULL && length > 0 )
{
*((*outPolicyStr) + sizeof(kPWPolicyStr_newPasswordRequired) + 1) = ' ';
::strcpy( (*outPolicyStr) + sizeof(kPWPolicyStr_newPasswordRequired) + 2, internalPolicyStr );
::free( internalPolicyStr );
}
}
}
else
*outPolicyStr = internalPolicyStr;
}
catch( tDirStatus err )
{
DbgLog( kLogPlugin, "GetUserPolicies(): got error %d", err );
dirStatus = err;
}
if ( cStr != NULL )
::free( cStr );
return dirStatus;
}
tDirStatus
OpenPasswordServerNode(
CDSLocalPlugin *inPlugin,
CFMutableDictionaryRef inNodeDict,
const char *inServerAddr,
tDirReference *outDSRef,
tDirNodeReference *outNodeRef )
{
tDirStatus status = eDSNoErr;
tDirReference pwsDirRef = 0;
tDirNodeReference pwsNodeRef = 0;
try
{
CFNumberRef pwsDirRefNumber = (CFNumberRef)CFDictionaryGetValue( inNodeDict, CFSTR(kNodePWSDirRef) );
if ( pwsDirRefNumber != NULL )
CFNumberGetValue( pwsDirRefNumber, kCFNumberLongType, &pwsDirRef );
if ( pwsDirRef == 0 )
{
status = inPlugin->GetDirServiceRef( &pwsDirRef );
if ( status != eDSNoErr )
throw( status );
pwsDirRefNumber = CFNumberCreate( NULL, kCFNumberLongType, &pwsDirRef );
CFDictionaryAddValue( inNodeDict, CFSTR(kNodePWSDirRef), pwsDirRefNumber );
CFRelease( pwsDirRefNumber );
}
CFNumberRef pwsNodeRefNumber = (CFNumberRef)CFDictionaryGetValue( inNodeDict, CFSTR(kNodePWSNodeRef) );
if ( pwsNodeRefNumber != NULL )
CFNumberGetValue( pwsNodeRefNumber, kCFNumberLongType, &pwsNodeRef );
if ( pwsNodeRef == 0 )
{
CFStringRef pwsNodeName = CFStringCreateWithFormat( NULL, NULL, CFSTR("/PasswordServer/%s"), inServerAddr );
if ( pwsNodeName == NULL )
throw ( eMemoryError );
status = CDSLocalPlugin::OpenDirNodeFromPath( pwsNodeName, pwsDirRef, &pwsNodeRef );
CFRelease( pwsNodeName );
if ( status != eDSNoErr )
throw( status );
pwsNodeRefNumber = CFNumberCreate( NULL, kCFNumberLongType, &pwsNodeRef );
CFDictionaryAddValue( inNodeDict, CFSTR(kNodePWSNodeRef), pwsNodeRefNumber );
CFRelease( pwsNodeRefNumber );
}
}
catch ( tDirStatus catchStatus )
{
status = catchStatus;
}
*outDSRef = pwsDirRef;
*outNodeRef = pwsNodeRef;
return status;
}
tDirStatus
OpenLDAPNode(
CDSLocalPlugin *inPlugin,
CFMutableDictionaryRef inNodeDict,
tDataListPtr inNodeName,
tDirReference *outDSRef,
tDirNodeReference *outNodeRef )
{
tDirStatus status = eDSNoErr;
tDirReference ldapDirRef = 0;
tDirNodeReference ldapNodeRef = 0;
CFNumberRef ldapNodeRefNumber = NULL;
try
{
CFNumberRef ldapDirRefNumber = (CFNumberRef)CFDictionaryGetValue( inNodeDict, CFSTR(kNodeLDAPDirRef) );
if ( ldapDirRefNumber != NULL )
CFNumberGetValue( ldapDirRefNumber, kCFNumberLongType, &ldapDirRef );
if ( ldapDirRef == 0 )
{
status = inPlugin->GetDirServiceRef( &ldapDirRef );
if ( status != eDSNoErr )
throw( status );
ldapDirRefNumber = CFNumberCreate( NULL, kCFNumberLongType, &ldapDirRef );
CFDictionaryAddValue( inNodeDict, CFSTR(kNodeLDAPDirRef), ldapDirRefNumber );
CFRelease( ldapDirRefNumber );
}
ldapNodeRefNumber = (CFNumberRef)CFDictionaryGetValue( inNodeDict, CFSTR(kNodeLDAPNodeRef) );
if ( ldapNodeRefNumber != NULL )
{
CFNumberGetValue( ldapNodeRefNumber, kCFNumberLongType, &ldapNodeRef );
if ( ldapNodeRef != 0 ) {
dsCloseDirNode( ldapNodeRef );
ldapNodeRef = 0;
}
CFDictionaryRemoveValue( inNodeDict, CFSTR(kNodeLDAPNodeRef) );
ldapNodeRefNumber = NULL;
}
status = dsOpenDirNode( ldapDirRef, inNodeName, &ldapNodeRef );
if ( status == eDSNoErr )
{
ldapNodeRefNumber = CFNumberCreate( NULL, kCFNumberLongType, &ldapNodeRef );
CFDictionaryAddValue( inNodeDict, CFSTR(kNodeLDAPNodeRef), ldapNodeRefNumber );
CFRelease( ldapNodeRefNumber );
}
}
catch ( tDirStatus catchStatus )
{
status = catchStatus;
}
*outDSRef = ldapDirRef;
*outNodeRef = ldapNodeRef;
return status;
}
void LoadAuthAuthorities( CDSLocalPlugin* inPlugin, tRecordReference inRecordRef, CAuthAuthority &inOutAATank )
{
tDirStatus status = eDSNoErr;
tAttributeEntryPtr attributeInfo = NULL;
tAttributeValueEntryPtr valueEntryPtr = NULL;
status = inPlugin->GetRecAttribInfo( inRecordRef, kDSNAttrAuthenticationAuthority, &attributeInfo );
if ( status == eDSNoErr && attributeInfo != NULL )
{
for ( UInt32 avIndex = 1; avIndex <= attributeInfo->fAttributeValueCount; avIndex++ )
{
status = inPlugin->GetRecAttrValueByIndex( inRecordRef, kDSNAttrAuthenticationAuthority, avIndex, &valueEntryPtr );
if ( status == eDSNoErr ) {
inOutAATank.AddValue( valueEntryPtr->fAttributeValueData.fBufferData );
dsDeallocAttributeValueEntry( 0, valueEntryPtr );
}
}
dsDeallocAttributeEntry( 0, attributeInfo );
}
}
tDirStatus
SaveAuthAuthorities(
CDSLocalPlugin* inPlugin,
tDirNodeReference inNodeRef,
const char *inUsername,
CFStringRef inNativeRecType,
CAuthAuthority &inAATank )
{
tDirStatus siResult = eDSNoErr;
tRecordReference recordRef = 0;
CFStringRef recordName = NULL;
if ( inNodeRef == 0 )
return eDSInvalidNodeRef;
if ( inUsername == NULL )
return eDSUserUnknown;
if ( inNativeRecType == NULL )
return eParameterError;
recordName = CFStringCreateWithCString( kCFAllocatorDefault, inUsername, kCFStringEncodingUTF8 );
if ( recordName == NULL )
return( eMemoryError );
siResult = inPlugin->OpenRecord( inNativeRecType, recordName, &recordRef );
if ( siResult == eDSNoErr )
siResult = SaveAuthAuthoritiesWithRecordRef( inPlugin, inNodeRef, recordRef, inAATank );
if ( recordRef != 0 )
{
gRefTable.RemoveReference( recordRef ); recordRef = 0;
}
DSCFRelease( recordName );
return siResult;
}
tDirStatus
SaveAuthAuthoritiesWithRecordRef(
CDSLocalPlugin* inPlugin,
tDirNodeReference inNodeRef,
tRecordReference inRecordRef,
CAuthAuthority &inAATank )
{
tDirStatus siResult = eDSAuthFailed;
UInt32 avIndex = 0;
UInt32 avCount = 0;
char *aaStr = NULL;
CFMutableDictionaryRef nodeDict = NULL;
CFStringRef preRootAuthString = NULL;
tDataListPtr attrValueList = NULL;
try
{
CFDictionaryRef openRecordDict = inPlugin->RecordDictForRecordRef( inRecordRef );
if ( openRecordDict == NULL )
throw( eDSInvalidRecordRef );
nodeDict = (CFMutableDictionaryRef)CFDictionaryGetValue( openRecordDict, CFSTR(kOpenRecordDictNodeDict) );
if ( nodeDict == NULL )
throw( eDSInvalidNodeRef );
preRootAuthString = (CFStringRef) CFDictionaryGetValue( nodeDict, CFSTR(kNodeAuthenticatedUserName) );
if ( preRootAuthString != NULL )
CFRetain( preRootAuthString );
CFDictionarySetValue( nodeDict, CFSTR(kNodeAuthenticatedUserName), CFSTR("root") );
avCount = inAATank.GetValueCount();
if ( avCount == 0 )
{
siResult = inPlugin->RemoveAttribute( inRecordRef, CFSTR(kDSNAttrAuthenticationAuthority) );
}
else
{
attrValueList = dsDataListAllocate( 0 );
for ( avIndex = 0; avIndex < avCount; avIndex++ )
{
aaStr = inAATank.GetValueAtIndex( avIndex );
if ( aaStr != NULL )
{
siResult = dsAppendStringToListAlloc( 0, attrValueList, aaStr );
DSFreeString( aaStr );
if ( siResult != eDSNoErr )
throw( siResult );
}
}
tDataNodePtr attrTypeNode = dsDataNodeAllocateString( 0, kDSNAttrAuthenticationAuthority );
sSetAttributeValues apiData = { kSetAttributeValues, 0, inRecordRef, attrTypeNode, attrValueList };
char *recTypeStr = inPlugin->GetRecordTypeFromRef( inRecordRef );
siResult = inPlugin->SetAttributeValues( &apiData, recTypeStr );
DSFreeString( recTypeStr );
dsDataNodeDeAllocate( 0, attrTypeNode );
}
if ( siResult != eDSNoErr )
throw( siResult );
}
catch( tDirStatus err )
{
DbgLog( kLogPlugin, "SaveAuthAuthorities(): got error %d", err );
siResult = err;
}
if ( preRootAuthString != NULL ) {
CFDictionarySetValue( nodeDict, CFSTR(kNodeAuthenticatedUserName), preRootAuthString );
CFRelease( preRootAuthString );
}
else {
CFDictionaryRemoveValue( nodeDict, CFSTR(kNodeAuthenticatedUserName) );
}
DSFreeString( aaStr );
if ( attrValueList != NULL ) {
dsDataListDeallocate( 0, attrValueList );
free( attrValueList );
}
return siResult;
}
tDirStatus
SetUserAuthAuthorityAsRoot(
CFMutableDictionaryRef inMutableRecordDict,
CDSLocalPlugin* inPlugin,
CDSLocalPluginNode* inNode,
CFStringRef inStdRecType,
const char *inUsername,
const char *inAuthAuthority,
tDirNodeReference inNodeRef,
bool inRemoveBasic )
{
tDirStatus siResult = eDSAuthFailed;
tRecordReference recordRef = 0;
CFStringRef authAuthorityCFStr = NULL;
CFMutableArrayRef aaValueArray = NULL;
CFStringRef recordName = NULL;
char *aaVers = NULL;
char *aaTag = NULL;
char *aaData = NULL;
CAuthAuthority aaTank;
if ( inAuthAuthority == NULL )
return( eDSAuthFailed );
recordName = CFStringCreateWithCString( kCFAllocatorDefault, inUsername, kCFStringEncodingUTF8 );
if ( recordName == NULL )
return eMemoryError;
siResult = inPlugin->OpenRecord( inStdRecType, recordName, &recordRef );
CFRelease( recordName );
if ( siResult != eDSNoErr )
return siResult;
siResult = dsParseAuthAuthority( inAuthAuthority, &aaVers, &aaTag, &aaData );
if ( siResult == eDSNoErr )
{
LoadAuthAuthorities( inPlugin, recordRef, aaTank );
aaTank.SetValueForTag( aaTag, inAuthAuthority );
if ( inRemoveBasic )
aaTank.RemoveValueForTag( kDSTagAuthAuthorityBasic );
DSFreeString( aaVers );
DSFreeString( aaTag );
DSFreeString( aaData );
siResult = SaveAuthAuthoritiesWithRecordRef( inPlugin, inNodeRef, recordRef, aaTank );
}
if ( recordRef != 0 )
{
sFlushRecord params = { kFlushRecord, 0, recordRef };
inPlugin->FlushRecord( ¶ms );
gRefTable.RemoveReference( recordRef ); recordRef = 0;
}
DSCFRelease( authAuthorityCFStr );
DSCFRelease( aaValueArray );
return( siResult );
}
void
AddKerberosAuthAuthority(
tDirNodeReference inNodeRef,
const char *inPrincName,
const char *inAuthAuthorityTag,
CAuthAuthority &inAuthAuthorityList,
CFMutableDictionaryRef inMutableRecordDict,
CDSLocalPlugin* inPlugin,
CDSLocalPluginNode* inNode,
CFStringRef inNativeRecType,
bool inOKToChangeAuthAuthorities )
{
if ( !inOKToChangeAuthAuthorities )
return;
char *kerbAA = inAuthAuthorityList.GetValueForTag( inAuthAuthorityTag );
if ( kerbAA != NULL )
{
free( kerbAA );
return;
}
if ( inAuthAuthorityList.TagDisabled(inAuthAuthorityTag) )
return;
char *localKDCRealmStr = GetLocalKDCRealmWithCache( kLocalKDCRealmCacheTimeout );
if ( localKDCRealmStr != NULL )
{
char kerbAAStr[1024];
snprintf(
kerbAAStr, sizeof(kerbAAStr),
";%s;;%s@%s;%s;",
inAuthAuthorityTag, inPrincName, localKDCRealmStr, localKDCRealmStr );
inAuthAuthorityList.SetValueForTag( inAuthAuthorityTag, kerbAAStr );
tDirStatus siResult = SetUserAuthAuthorityAsRoot(
inMutableRecordDict,
inPlugin,
inNode,
inPlugin->RecordStandardTypeForNativeType(inNativeRecType),
inPrincName,
kerbAAStr,
inNodeRef,
false );
if ( siResult != eDSNoErr )
DbgLog( kLogPlugin, "SetUserAuthAuthorityAsRoot = %d", siResult );
DSFreeString( localKDCRealmStr );
}
}
char *
GetLocalKDCRealmWithCache(
time_t inMaxTimeUntilQuery )
{
static pthread_mutex_t sLocalRealmMutex = PTHREAD_MUTEX_INITIALIZER;
static char *localKDCRealmStr = NULL;
static time_t queryTime = 0;
time_t now = time(NULL);
char *returnValue = NULL;
pthread_mutex_lock( &sLocalRealmMutex );
if ( (localKDCRealmStr == NULL) || (now - queryTime > inMaxTimeUntilQuery) )
{
DSFreeString( localKDCRealmStr );
localKDCRealmStr = GetLocalKDCRealm();
}
returnValue = localKDCRealmStr ? strdup( localKDCRealmStr ) : NULL;
pthread_mutex_unlock( &sLocalRealmMutex );
return returnValue;
}
tDirStatus SASLErrToDirServiceError( int inSASLError )
{
tDirStatus dirServiceErr = eDSAuthFailed;
switch (inSASLError)
{
case SASL_CONTINUE: dirServiceErr = eDSNoErr; break;
case SASL_OK: dirServiceErr = eDSNoErr; break;
case SASL_FAIL: dirServiceErr = eDSAuthFailed; break;
case SASL_NOMEM: dirServiceErr = eMemoryError; break;
case SASL_BUFOVER: dirServiceErr = eDSBufferTooSmall; break;
case SASL_NOMECH: dirServiceErr = eDSAuthMethodNotSupported; break;
case SASL_BADPROT: dirServiceErr = eDSAuthParameterError; break;
case SASL_NOTDONE: dirServiceErr = eDSAuthFailed; break;
case SASL_BADPARAM: dirServiceErr = eDSAuthParameterError; break;
case SASL_TRYAGAIN: dirServiceErr = eDSAuthFailed; break;
case SASL_BADMAC: dirServiceErr = eDSAuthFailed; break;
case SASL_NOTINIT: dirServiceErr = eDSAuthFailed; break;
case SASL_INTERACT: dirServiceErr = eDSAuthParameterError; break;
case SASL_BADSERV: dirServiceErr = eDSAuthFailed; break;
case SASL_WRONGMECH: dirServiceErr = eDSAuthParameterError; break;
case SASL_BADAUTH: dirServiceErr = eDSAuthFailed; break;
case SASL_NOAUTHZ: dirServiceErr = eDSAuthFailed; break;
case SASL_TOOWEAK: dirServiceErr = eDSAuthMethodNotSupported; break;
case SASL_ENCRYPT: dirServiceErr = eDSAuthInBuffFormatError; break;
case SASL_TRANS: dirServiceErr = eDSAuthFailed; break;
case SASL_EXPIRED: dirServiceErr = eDSAuthFailed; break;
case SASL_DISABLED: dirServiceErr = eDSAuthFailed; break;
case SASL_NOUSER: dirServiceErr = eDSAuthUnknownUser; break;
case SASL_BADVERS: dirServiceErr = eDSAuthServerError; break;
case SASL_UNAVAIL: dirServiceErr = eDSAuthNoAuthServerFound; break;
case SASL_NOVERIFY: dirServiceErr = eDSAuthNoAuthServerFound; break;
case SASL_PWLOCK: dirServiceErr = eDSAuthFailed; break;
case SASL_NOCHANGE: dirServiceErr = eDSAuthFailed; break;
case SASL_WEAKPASS: dirServiceErr = eDSAuthBadPassword; break;
case SASL_NOUSERPASS: dirServiceErr = eDSAuthFailed; break;
}
return dirServiceErr;
}