#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <pwd.h>
#include <ctype.h>
#include <regex.h>
#include <syslog.h> // for syslog() to log calls
#include <openssl/md5.h>
#include <openssl/sha.h>
#include <openssl/evp.h>
#include <mach/mach_time.h>
#include <sasl.h>
#include <Security/Authorization.h>
#include <PasswordServer/AuthFile.h>
#include <PasswordServer/CAuthFileBase.h>
#include <PasswordServer/CPolicyGlobalXML.h>
#include <PasswordServer/CPolicyXML.h>
#include "CNiPlugIn.h"
#include "CNetInfoPlugin.h"
#include "SMBAuth.h"
#include "CBuff.h"
#include "CSharedData.h"
#include "CString.h"
#include "CFile.h"
#include "NiLib2.h"
#include "NiLib3.h"
#include "DSUtils.h"
#include "DirServicesConst.h"
#include "DirServices.h"
#include "DirServicesUtils.h"
#include "DirServicesPriv.h"
#include "ServerModuleLib.h"
#include "CRecTypeList.h"
#include "CRecNameList.h"
#include "SharedConsts.h"
#include "PrivateTypes.h"
#include "CPlugInRef.h"
#include "CContinue.h"
#include "CRCCalc.h"
#include "CDataBuff.h"
#include "CLog.h"
#include "TimConditional.h"
#include "netinfo_open.h"
#include "buffer_unpackers.h"
#include "CNiMaps.h"
#include "CNiUtilities.h"
#include "CDSPluginUtils.h"
#include "ServerControl.h"
#ifdef TIM_CLIENT_PRESENT
#include <TimClient/TimClient.h>
#endif
typedef struct NetInfoAuthAuthorityHandler {
char* fTag;
NetInfoAuthAuthorityHandlerProc fHandler;
} NetInfoAuthAuthorityHandler;
#define kNetInfoAuthAuthorityHandlerProcs 6
static NetInfoAuthAuthorityHandler sNetInfoAuthAuthorityHandlerProcs[ kNetInfoAuthAuthorityHandlerProcs ] =
{
{ kDSTagAuthAuthorityBasic, (NetInfoAuthAuthorityHandlerProc)CNiPlugIn::DoBasicAuth },
{ kDSTagAuthAuthorityLocalWindowsHash, (NetInfoAuthAuthorityHandlerProc)CNiPlugIn::DoShadowHashAuth },
{ kDSTagAuthAuthorityShadowHash, (NetInfoAuthAuthorityHandlerProc)CNiPlugIn::DoShadowHashAuth },
{ kDSTagAuthAuthorityPasswordServer, (NetInfoAuthAuthorityHandlerProc)CNiPlugIn::DoPasswordServerAuth },
{ kDSTagAuthAuthorityDisabledUser, (NetInfoAuthAuthorityHandlerProc)CNiPlugIn::DoDisabledAuth },
{ kDSTagAuthAuthorityLocalCachedUser, (NetInfoAuthAuthorityHandlerProc)CNiPlugIn::DoLocalCachedUserAuth }
};
CPlugInRef *gNINodeRef = nil;
CContinue *gNIContinue = nil;
time_t gCheckTimAgainTime = 0;
double gAllowNetInfoParentOpenTime = 0;
bool gTimIsRunning = false;
static const uInt32 kNodeInfoBuffTag = 'NInf';
static unsigned int sHashList;
HashAuthFailedMap gHashAuthFailedMap;
extern DSMutexSemaphore *gNetInfoMutex;
extern DSMutexSemaphore *gHashAuthFailedMapLock;
extern uInt32 gDelayFailedLocalAuthReturnsDeltaInSeconds;
extern bool gServerOS;
extern sInt32 gProcessPID;
typedef enum
{
eHasAuthMethod = -7000,
eNoAuthServer = -7001,
eNoAuthMethods = -7002,
eAuthMethodNotFound = -7003
} eAuthValues;
CNiPlugIn::CNiPlugIn ( void )
{
struct stat sb;
if ( gNINodeRef == nil )
{
if (gServerOS)
{
gNINodeRef = new CPlugInRef( CNiPlugIn::ContextDeallocProc, 1024 );
}
else
{
gNINodeRef = new CPlugInRef( CNiPlugIn::ContextDeallocProc, 256 );
}
}
if ( gNIContinue == nil )
{
if (gServerOS)
{
gNIContinue = new CContinue( CNiPlugIn::ContinueDeallocProc, 256 );
}
else
{
gNIContinue = new CContinue( CNiPlugIn::ContinueDeallocProc, 64 );
}
}
fRecData = new CDataBuff();
fAttrData = new CDataBuff();
fTmpData = new CDataBuff();
fHashList = kNiPluginHashDefaultSet;
if ( gServerOS && gProcessPID < 100 && stat("/var/db/netinfo/network.nidb",&sb) == 0 )
{
gAllowNetInfoParentOpenTime = dsTimestamp() + USEC_PER_SEC * 45;
}
}
CNiPlugIn::~CNiPlugIn ( void )
{
if ( fRecData != nil )
{
delete( fRecData );
fRecData = nil;
}
if ( fAttrData != nil )
{
delete( fAttrData );
fAttrData = nil;
}
if ( fTmpData != nil )
{
delete( fTmpData );
fTmpData = nil;
}
}
sInt32 CNiPlugIn::HandleRequest ( void *inData )
{
sInt32 siResult = 0;
sHeader *pMsgHdr = nil;
if ( inData == nil )
{
return( -8088 );
}
pMsgHdr = (sHeader *)inData;
switch ( pMsgHdr->fType )
{
case kReleaseContinueData:
siResult = ReleaseContinueData( (sReleaseContinueData *)inData );
break;
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 kCloseAttributeList:
siResult = CloseAttributeList( (sCloseAttributeList *)inData );
break;
case kCloseAttributeValueList:
siResult = CloseAttributeValueList( (sCloseAttributeValueList *)inData );
break;
case kOpenRecord:
siResult = OpenRecord( (sOpenRecord *)inData );
break;
case kGetRecordReferenceInfo:
siResult = GetRecRefInfo( (sGetRecRefInfo *)inData );
break;
case kGetRecordAttributeInfo:
siResult = GetRecAttribInfo( (sGetRecAttribInfo *)inData );
break;
case kGetRecordAttributeValueByID:
siResult = GetRecordAttributeValueByID( (sGetRecordAttributeValueByID *)inData );
break;
case kGetRecordAttributeValueByIndex:
siResult = GetRecAttrValueByIndex( (sGetRecordAttributeValueByIndex *)inData );
break;
case kGetRecordAttributeValueByValue:
siResult = GetRecAttrValueByValue( (sGetRecordAttributeValueByValue *)inData );
break;
case kCloseRecord:
siResult = CloseRecord( (sCloseRecord *)inData );
break;
case kSetRecordName:
siResult = SetRecordName( (sSetRecordName *)inData );
break;
case kSetRecordType:
siResult = SetRecordType( (sSetRecordType *)inData );
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:
siResult = DoAuthenticationOnRecordType( (sDoDirNodeAuthOnRecordType *)inData );
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 kFlushRecord:
siResult = eDSNoErr;
break;
default:
siResult = eNotHandledByThisNode;
break;
}
pMsgHdr->fResult = siResult;
return( siResult );
}
sInt32 CNiPlugIn::ReleaseContinueData ( sReleaseContinueData *inData )
{
sInt32 siResult = eDSNoErr;
gNetInfoMutex->Wait();
if ( gNIContinue->RemoveItem( inData->fInContinueData ) != eDSNoErr )
{
siResult = eDSInvalidContext;
}
gNetInfoMutex->Signal();
return( siResult );
}
#pragma mark -
#pragma mark DS API Service Routines
#pragma mark -
sInt32 CNiPlugIn::OpenDirNode ( sOpenDirNode *inData )
{
sInt32 siResult = eDSNoErr;
char *nameStr = nil;
char *pathStr = nil;
char *domName = nil;
sInt32 timeOutSecs = 3;
sNIContextData *pContext = nil;
try
{
nameStr = ::dsGetPathFromListPriv( inData->fInDirNodeName, kstrDelimiter );
if ( nameStr == nil ) throw( (sInt32)eDSNullNodeName );
pathStr = BuildDomainPathFromName( nameStr ); if ( pathStr == nil ) throw( (sInt32)eDSUnknownNodeName );
if ( gAllowNetInfoParentOpenTime != 0 && strcmp( pathStr, kstrParentDotDot ) == 0 )
{
if ( dsTimestamp() > gAllowNetInfoParentOpenTime )
{
gAllowNetInfoParentOpenTime = 0;
}
else
{
throw( (sInt32)eDSOpenNodeFailed );
}
}
gNetInfoMutex->Wait();
siResult = CNetInfoPlugin::SafeOpen( pathStr, timeOutSecs, &domName );
gNetInfoMutex->Signal();
if ( siResult != eDSNoErr ) throw( siResult );
if (::strcmp(domName,"") == 0)
{
siResult = eDSOpenNodeFailed;
if ( siResult != eDSNoErr ) throw( siResult );
}
pContext = MakeContextData();
if ( pContext == nil ) throw( (sInt32)eMemoryAllocError );
pContext->fDomain = nil; pContext->fDomainName = domName; pContext->fDomainPath = pathStr; pathStr = nil;
pContext->fUID = inData->fInUID;
pContext->fEffectiveUID = inData->fInEffectiveUID;
if (strcmp(pContext->fDomainPath,".") == 0 )
{
pContext->bIsLocal = true;
}
gNINodeRef->AddItem( inData->fOutNodeRef, pContext );
}
catch( sInt32 err )
{
siResult = err;
}
DSFreeString( pathStr );
DSFreeString( nameStr );
return( siResult );
}
sInt32 CNiPlugIn::CloseDirNode ( sCloseDirNode *inData )
{
sInt32 siResult = NI_OK;
sNIContextData *pContext = nil;
try
{
pContext = (sNIContextData *)gNINodeRef->GetItemData( inData->fInNodeRef );
if ( pContext == nil ) throw( (sInt32)eDSInvalidNodeRef );
gNINodeRef->RemoveItem( inData->fInNodeRef );
gNIContinue->RemoveItems( inData->fInNodeRef );
}
catch( sInt32 err )
{
siResult = err;
}
return( siResult );
}
sInt32 CNiPlugIn::GetDirNodeInfo ( sGetDirNodeInfo *inData )
{
sInt32 siResult = eDSNoErr;
uInt32 uiOffset = 0;
#ifdef TIM_CLIENT_PRESENT
sInt32 siTimStatus = eDSNoErr;
TIMHandle *timHndl = nil;
Buffer *pTmp = nil;
Buffer *pTimInfo = nil;
uInt32 timAuthCount = 0;
char *pBuffStr = nil;
CString *pAuthStr = nil;
uInt32 timAuthAvail = 0;
#endif
uInt32 i = 0;
uInt32 authCount = 0;
uInt32 uiCntr = 1;
uInt32 uiAttrCnt = 0;
CAttributeList *inAttrList = nil;
char *pAttrName = nil;
char *pData = nil;
sNIContextData *pContext = nil;
sNIContextData *pAttrContext = nil;
char *niDomNameStr = nil;
tDataList *pNodePath = nil;
tDataNode *pDataNode = nil;
CBuff outBuff;
time_t delayedNI = 0;
ni_id niDirID;
ni_entrylist niEntryList;
ni_proplist niPropList;
ni_index niIndex = 0;
gNetInfoMutex->Wait();
try
{
if ( inData == nil ) throw( (sInt32)eMemoryError );
pContext = (sNIContextData *)gNINodeRef->GetItemData( inData->fInNodeRef );
if ( pContext == nil ) throw( (sInt32)eDSInvalidNodeRef );
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 );
fRecData->Clear();
fAttrData->Clear();
fRecData->AppendShort( ::strlen( "dsAttrTypeStandard:DirectoryNodeInfo" ) );
fRecData->AppendString( "dsAttrTypeStandard:DirectoryNodeInfo" );
fRecData->AppendShort( ::strlen( "DirectoryNodeInfo" ) );
fRecData->AppendString( "DirectoryNodeInfo" );
while ( inAttrList->GetAttribute( uiCntr++, &pAttrName ) == eDSNoErr )
{
if ( (::strcmp( pAttrName, kDSAttributesAll ) == 0) ||
(::strcmp( pAttrName, kDSNAttrAuthMethod ) == 0) )
{
fTmpData->Clear();
uiAttrCnt++;
fTmpData->AppendShort( ::strlen( kDSNAttrAuthMethod ) );
fTmpData->AppendString( kDSNAttrAuthMethod );
if ( inData->fInAttrInfoOnly == false )
{
#ifdef TIM_CLIENT_PRESENT
if ( IsTimRunning() )
{
authCount = 7;
void * aNIDomain = RetrieveNIDomain(pContext);
if (aNIDomain != NULL)
{
timHndl = ::timServerForDomain( aNIDomain );
if ( timHndl != nil )
{
siTimStatus = ::timGetOperations( timHndl, TimOpAuthentication, &pTimInfo );
if ( siTimStatus == eDSNoErr )
{
timAuthCount = ::bufferArrayCount( pTimInfo );
if ( timAuthCount != 0 )
{
for ( i = 0; i < timAuthCount; i++ )
{
pTmp = ::bufferArrayBufferAtIndex( pTimInfo, i );
if ( pTmp != nil )
{
pBuffStr = ::bufferToString( pTmp );
pAuthStr = GetAuthTypeStr( pBuffStr );
if ( pAuthStr != nil )
{
if (strcmp(kDSStdAuth2WayRandom,pAuthStr->GetData()) == 0)
{
authCount++;
timAuthAvail |= 1;
}
if (strcmp(kDSStdAuthSMB_NT_Key,pAuthStr->GetData()) == 0)
{
authCount++;
timAuthAvail |= 2;
}
if (strcmp(kDSStdAuthSMB_LM_Key,pAuthStr->GetData()) == 0)
{
authCount++;
timAuthAvail |= 4;
}
delete( pAuthStr );
pAuthStr = nil;
}
::bufferRelease( pTmp );
pTmp = nil;
if ( pBuffStr != nil )
{
free( pBuffStr );
pBuffStr = nil;
}
}
}
}
}
if ( pTimInfo != nil )
{
::bufferRelease( pTimInfo );
pTimInfo = nil;
}
::timHandleFree( timHndl );
timHndl = nil;
}
}
fTmpData->AppendShort( authCount );
if (timAuthAvail & 1)
{
fTmpData->AppendLong( ::strlen( kDSStdAuth2WayRandom ) );
fTmpData->AppendString( kDSStdAuth2WayRandom );
}
if (timAuthAvail & 2)
{
fTmpData->AppendLong( ::strlen( kDSStdAuthSMB_NT_Key ) );
fTmpData->AppendString( kDSStdAuthSMB_NT_Key );
}
if (timAuthAvail & 4)
{
fTmpData->AppendLong( ::strlen( kDSStdAuthSMB_LM_Key ) );
fTmpData->AppendString( kDSStdAuthSMB_LM_Key );
}
}
else #endif
{
authCount = 7;
fTmpData->AppendShort( authCount );
}
fTmpData->AppendLong( ::strlen( kDSStdAuthClearText ) );
fTmpData->AppendString( kDSStdAuthClearText );
fTmpData->AppendLong( ::strlen( kDSStdAuthCrypt ) );
fTmpData->AppendString( kDSStdAuthCrypt );
fTmpData->AppendLong( ::strlen( kDSStdAuthSetPasswd ) );
fTmpData->AppendString( kDSStdAuthSetPasswd );
fTmpData->AppendLong( ::strlen( kDSStdAuthChangePasswd ) );
fTmpData->AppendString( kDSStdAuthChangePasswd );
fTmpData->AppendLong( ::strlen( kDSStdAuthSetPasswdAsRoot ) );
fTmpData->AppendString( kDSStdAuthSetPasswdAsRoot );
fTmpData->AppendLong( ::strlen( kDSStdAuthNodeNativeClearTextOK ) );
fTmpData->AppendString( kDSStdAuthNodeNativeClearTextOK );
fTmpData->AppendLong( ::strlen( kDSStdAuthNodeNativeNoClearText ) );
fTmpData->AppendString( kDSStdAuthNodeNativeNoClearText );
}
else
{
fTmpData->AppendShort( 0 );
}
fAttrData->AppendLong( fTmpData->GetLength() );
fAttrData->AppendBlock( fTmpData->GetData(), fTmpData->GetLength() );
fTmpData->Clear();
}
if ( (::strcmp( pAttrName, kDSAttributesAll ) == 0) ||
(::strcmp( pAttrName, kDS1AttrReadOnlyNode ) == 0) )
{
fTmpData->Clear();
uiAttrCnt++;
fTmpData->AppendShort( ::strlen( kDS1AttrReadOnlyNode ) );
fTmpData->AppendString( kDS1AttrReadOnlyNode );
if ( inData->fInAttrInfoOnly == false )
{
fTmpData->AppendShort( 1 );
fTmpData->AppendLong( ::strlen( "ReadWrite" ) );
fTmpData->AppendString( "ReadWrite" );
}
else
{
fTmpData->AppendShort( 0 );
}
fAttrData->AppendLong( fTmpData->GetLength() );
fAttrData->AppendBlock( fTmpData->GetData(), fTmpData->GetLength() );
fTmpData->Clear();
}
if ( (::strcmp( pAttrName, kDSAttributesAll ) == 0) ||
(::strcmp( pAttrName, kDSNAttrNodePath ) == 0) )
{
DBGLOG( kLogPlugin, "CNiPlugIn::GetDirNodeInfo: Try to retrieve a netinfo domain path from netinfo_domainname" );
void *aNIDomain = RetrieveSharedNIDomain(pContext);
if (aNIDomain != NULL)
{
delayedNI = time(nil) + 2; niDomNameStr = netinfo_domainname( aNIDomain );
if ( delayedNI < time(nil) )
{
if (pContext->fDomainName != nil)
{
syslog(LOG_ALERT,"GetDirNodeInfo::Call to netinfo_domainname was with argument domain name: %s and lasted %d seconds.", pContext->fDomainName, (uInt32)(2 + time(nil) - delayedNI));
DBGLOG2( kLogPlugin, "CNiPlugIn::GetDirNodeInfo: Call to netinfo_domainname was with argument domain name: %s and lasted %d seconds.", pContext->fDomainName, (uInt32)(2 + time(nil) - delayedNI) );
}
else
{
syslog(LOG_ALERT,"GetDirNodeInfo::Call to netinfo_domainname lasted %d seconds.", (uInt32)(2 + time(nil) - delayedNI));
DBGLOG1( kLogPlugin, "CNiPlugIn::GetDirNodeInfo: Call to netinfo_domainname lasted %d seconds.", (uInt32)(2 + time(nil) - delayedNI) );
}
if (niDomNameStr != nil)
{
syslog(LOG_ALERT,"GetDirNodeInfo::Call to netinfo_domainname returned domain name: %s.", niDomNameStr);
DBGLOG1( kLogPlugin, "CNiPlugIn::GetDirNodeInfo: Call to netinfo_domainname returned domain name: %s.", niDomNameStr );
}
}
if ( niDomNameStr == nil )
{
syslog(LOG_ALERT,"GetDirNodeInfo::Call to netinfo_domainname failed or returned nil name.");
DBGLOG( kLogPlugin, "CNiPlugIn::GetDirNodeInfo: Call to netinfo_domainname failed or returned nil name." );
niDomNameStr = (char *) calloc(1,2);
strcpy(niDomNameStr,"/");
}
}
else
{
if (pContext->fDomainName != nil)
{
syslog(LOG_ALERT,"GetDirNodeInfo::Call to netinfo_domainname was with argument domain name: %s but failed to connect to domain.", pContext->fDomainName );
DBGLOG1( kLogPlugin, "CNiPlugIn::GetDirNodeInfo: Call to netinfo_domainname was with argument domain name: %s but failed to connect to domain.", pContext->fDomainName );
}
throw( (sInt32)eDSInvalidSession );
}
if (niDomNameStr != nil)
{
DBGLOG1( kLogPlugin, "CNiPlugIn::GetDirNodeInfo: Used netinfo domain path value of <%s>", niDomNameStr );
fTmpData->Clear();
uiAttrCnt++;
fTmpData->AppendShort( sizeof( kDSNAttrNodePath ) - 1 );
fTmpData->AppendString( kDSNAttrNodePath );
if ( inData->fInAttrInfoOnly == false )
{
if ( ::strcmp( niDomNameStr, "/" ) == 0 )
{
fTmpData->AppendShort( 2 );
fTmpData->AppendLong( sizeof( kstrNetInfoName ) - 1 );
fTmpData->AppendString( kstrNetInfoName );
if ( ::strcmp( pContext->fDomainName, kstrDefaultLocalNodeName ) == 0 )
{
fTmpData->AppendLong( sizeof( kstrDefaultLocalNode ) - 1 );
fTmpData->AppendString( kstrDefaultLocalNode );
}
else
{
fTmpData->AppendLong( sizeof( kstrRootOnly ) - 1 );
fTmpData->AppendString( kstrRootOnly );
}
}
else
{
pNodePath = ::dsBuildFromPathPriv( niDomNameStr, "/" );
if ( pNodePath == nil ) throw( (sInt32)eMemoryAllocError );
fTmpData->AppendShort( ::dsDataListGetNodeCountPriv( pNodePath ) + 2 );
fTmpData->AppendLong( sizeof( kstrNetInfoName ) - 1 );
fTmpData->AppendString( kstrNetInfoName );
fTmpData->AppendLong( sizeof( kstrRootOnly ) - 1 );
fTmpData->AppendString( kstrRootOnly );
i = 1;
while ( ::dsDataListGetNodeAllocPriv( pNodePath, i, &pDataNode ) == eDSNoErr )
{
fTmpData->AppendLong( ::strlen( pDataNode->fBufferData ) );
fTmpData->AppendString( pDataNode->fBufferData );
::dsDataBufferDeallocatePriv( pDataNode );
pDataNode = nil;
i++;
}
::dsDataListDeallocatePriv( pNodePath );
free( pNodePath );
pNodePath = nil;
}
}
else
{
fTmpData->AppendShort( 0 );
}
fAttrData->AppendLong( fTmpData->GetLength() );
fAttrData->AppendBlock( fTmpData->GetData(), fTmpData->GetLength() );
fTmpData->Clear();
DSFreeString(niDomNameStr);
}
}
if ( (::strcmp( pAttrName, kDSAttributesAll ) == 0) ||
(::strcmp( pAttrName, kDSNAttrRecordType ) == 0) )
{
fTmpData->Clear();
uiAttrCnt++;
fTmpData->AppendShort( ::strlen( kDSNAttrRecordType ) );
fTmpData->AppendString( kDSNAttrRecordType );
if ( inData->fInAttrInfoOnly == false )
{
void * aNIDomain = RetrieveNIDomain(pContext);
if (aNIDomain != NULL)
{
int valueCount = 0;
NI_INIT( &niDirID );
NI_INIT( &niEntryList );
siResult = ::ni_pathsearch( aNIDomain, &niDirID, "/" );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
siResult = ::ni_list( aNIDomain, &niDirID, "name", &niEntryList );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
if ( niEntryList.ni_entrylist_val == NULL )
{
niEntryList.ni_entrylist_len = 0;
}
for ( i = 0; i < niEntryList.ni_entrylist_len; i++ )
{
char* dsType = MapNetInfoRecToDSType(niEntryList.ni_entrylist_val[i].names->ni_namelist_val[0]);
if (dsType != NULL)
{
if (strncmp(dsType,kDSStdRecordTypePrefix,strlen(kDSStdRecordTypePrefix)) == 0)
{
valueCount++;
}
delete( dsType );
dsType = NULL;
}
}
fTmpData->AppendShort( valueCount );
for ( i = 0; i < niEntryList.ni_entrylist_len; i++ )
{
char* dsType = MapNetInfoRecToDSType(niEntryList.ni_entrylist_val[i].names->ni_namelist_val[0]);
if (dsType != NULL)
{
if (strncmp(dsType,kDSStdRecordTypePrefix,strlen(kDSStdRecordTypePrefix)) == 0)
{
fTmpData->AppendLong( ::strlen( dsType ) );
fTmpData->AppendString( dsType );
}
delete( dsType );
dsType = NULL;
}
}
if ( niEntryList.ni_entrylist_len > 0 )
{
ni_entrylist_free(&niEntryList);
}
}
else
{
throw( (sInt32)eDSInvalidSession );
}
}
else
{
fTmpData->AppendShort( 0 );
}
fAttrData->AppendLong( fTmpData->GetLength() );
fAttrData->AppendBlock( fTmpData->GetData(), fTmpData->GetLength() );
fTmpData->Clear();
}
if ( (::strcmp( pAttrName, kDSAttributesAll ) == 0) ||
(::strcmp( pAttrName, kDSNAttrSubNodes ) == 0) )
{
fTmpData->Clear();
uiAttrCnt++;
fTmpData->AppendShort( ::strlen( kDSNAttrSubNodes ) );
fTmpData->AppendString( kDSNAttrSubNodes );
if ( inData->fInAttrInfoOnly == false )
{
int valueCount = 0;
set<string> nodeNames;
set<string>::const_iterator iter;
siResult = this->GetSubNodes( pContext, nodeNames );
valueCount = nodeNames.size();
fTmpData->AppendShort( valueCount );
for (iter = nodeNames.begin(); iter != nodeNames.end(); ++iter)
{
const char* subnode = (*iter).c_str();
fTmpData->AppendLong( ::strlen( subnode ) );
fTmpData->AppendString( subnode );
}
}
else
{
fTmpData->AppendShort( 0 );
}
fAttrData->AppendLong( fTmpData->GetLength() );
fAttrData->AppendBlock( fTmpData->GetData(), fTmpData->GetLength() );
fTmpData->Clear();
}
if ( (::strcmp( pAttrName, kDSAttributesAll ) == 0) ||
(::strcmp( pAttrName, kDS1AttrDataStamp ) == 0) )
{
fTmpData->Clear();
uiAttrCnt++;
fTmpData->AppendShort( ::strlen( kDS1AttrDataStamp ) );
fTmpData->AppendString( kDS1AttrDataStamp );
if ( inData->fInAttrInfoOnly == false )
{
void * aNIDomain = RetrieveNIDomain(pContext);
if (aNIDomain != NULL)
{
fTmpData->AppendShort( 1 );
NI_INIT( &niPropList );
ni_statistics(aNIDomain, &niPropList);
niIndex = ::ni_proplist_match( niPropList, "checksum", NULL );
if ( niIndex == NI_INDEX_NULL || niPropList.nipl_val[ niIndex ].nip_val.ninl_len == 0 )
{
fTmpData->AppendLong( ::strlen( "0" ) );
fTmpData->AppendString( "0" );
}
else
{
fTmpData->AppendLong( ::strlen( niPropList.nipl_val[ niIndex ].nip_val.ninl_val[ 0 ] ) );
fTmpData->AppendString( niPropList.nipl_val[ niIndex ].nip_val.ninl_val[ 0 ] );
}
::ni_proplist_free( &niPropList );
}
else
{
throw( (sInt32)eDSInvalidSession );
}
}
else
{
fTmpData->AppendShort( 0 );
}
fAttrData->AppendLong( fTmpData->GetLength() );
fAttrData->AppendBlock( fTmpData->GetData(), fTmpData->GetLength() );
fTmpData->Clear();
}
if ( (::strcmp( pAttrName, kDSAttributesAll ) == 0) ||
(::strcmp( pAttrName, "dsAttrTypeStandard:TrustInformation" ) == 0) )
{
fTmpData->Clear();
uiAttrCnt++;
fTmpData->AppendShort( ::strlen( "dsAttrTypeStandard:TrustInformation" ) );
fTmpData->AppendString( "dsAttrTypeStandard:TrustInformation" );
if ( inData->fInAttrInfoOnly == false )
{
if( pContext != NULL && pContext->bIsLocal )
{
fTmpData->AppendShort( 1 );
fTmpData->AppendLong( ::strlen( "FullTrust" ) );
fTmpData->AppendString( "FullTrust" );
}
else
{
fTmpData->AppendShort( 1 );
fTmpData->AppendLong( ::strlen( "Anonymous" ) );
fTmpData->AppendString( "Anonymous" );
}
}
else
{
fTmpData->AppendShort( 0 );
}
fAttrData->AppendLong( fTmpData->GetLength() );
fAttrData->AppendBlock( fTmpData->GetData(), fTmpData->GetLength() );
fTmpData->Clear();
}
}
fRecData->AppendShort( uiAttrCnt );
fRecData->AppendBlock( fAttrData->GetData(), fAttrData->GetLength() );
outBuff.AddData( fRecData->GetData(), fRecData->GetLength() );
inData->fOutAttrInfoCount = uiAttrCnt;
pData = outBuff.GetDataBlock( 1, &uiOffset );
if ( pData != nil )
{
pAttrContext = MakeContextData();
if ( pAttrContext == nil ) throw( (sInt32)eMemoryAllocError );
pAttrContext->offset = uiOffset + 61;
gNINodeRef->AddItem( inData->fOutAttrListRef, pAttrContext );
}
else
{
siResult = eDSBufferTooSmall;
}
}
catch( sInt32 err )
{
siResult = err;
}
gNetInfoMutex->Signal();
if ( inAttrList != nil )
{
delete( inAttrList );
inAttrList = nil;
}
return( siResult );
}
sInt32 CNiPlugIn::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 = 0;
uInt32 buffSize = 0;
uInt32 buffLen = 0;
char *p = nil;
char *pAttrType = nil;
tDataBuffer *pDataBuff = nil;
tAttributeValueListRef attrValueListRef = 0;
tAttributeEntryPtr pAttribInfo = nil;
sNIContextData *pAttrContext = nil;
sNIContextData *pValueContext = nil;
try
{
if ( inData == nil ) throw( (sInt32)eMemoryError );
pAttrContext = (sNIContextData *)gNINodeRef->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 (2 + offset > 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 (4 + offset > buffSize) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &usAttrLen, p, 4 );
p += 4 + usAttrLen;
offset += 4 + usAttrLen;
}
uiOffset = offset;
if (4 + offset > buffSize) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &usAttrLen, p, 4 );
p += 4;
offset += 4;
buffLen = offset + usAttrLen;
if (2 + offset > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &usAttrTypeLen, p, 2 );
pAttrType = p + 2;
p += 2 + usAttrTypeLen;
offset += 2 + usAttrTypeLen;
if (2 + offset > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &usValueCnt, p, 2 );
p += 2;
offset += 2;
for ( i = 0; i < usValueCnt; i++ )
{
if (4 + offset > 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 );
attrValueListRef = inData->fOutAttrValueListRef;
pValueContext = MakeContextData();
if ( pValueContext == nil ) throw( (sInt32)eMemoryAllocError );
pValueContext->offset = uiOffset;
gNINodeRef->AddItem( inData->fOutAttrValueListRef, pValueContext );
inData->fOutAttrInfoPtr = pAttribInfo;
}
catch( sInt32 err )
{
siResult = err;
}
return( siResult );
}
sInt32 CNiPlugIn::GetRecordEntry ( sGetRecordEntry *inData )
{
sInt32 siResult = eDSNoErr;
uInt32 uiIndex = 0;
uInt32 uiCount = 0;
uInt32 uiOffset = 0;
uInt32 uberOffset = 0;
char *pData = nil;
tRecordEntryPtr pRecEntry = nil;
sNIContextData *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 (2 + offset > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &usTypeLen, pData, 2 );
pData += 2;
offset += 2;
pRecType = pData;
pData += usTypeLen;
offset += usTypeLen;
if (2 + offset > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &usNameLen, pData, 2 );
pData += 2;
offset += 2;
pRecName = pData;
pData += usNameLen;
offset += usNameLen;
if (2 + offset > 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 = MakeContextData();
if ( pContext == nil ) throw( (sInt32)eMemoryAllocError );
pContext->offset = uberOffset + offset + 4;
gNINodeRef->AddItem( inData->fOutAttrListRef, pContext );
inData->fOutRecEntryPtr = pRecEntry;
}
catch( sInt32 err )
{
siResult = err;
}
return( siResult );
}
sInt32 CNiPlugIn::GetRecordList ( sGetRecordList *inData )
{
sInt32 siResult = eDSNoErr;
uInt32 uiTotal = 0;
uInt32 uiCount = 0;
char *pRecName = nil;
char *pRecType = nil;
char *pNIRecType = nil;
bool bAttribOnly = false;
tDirPatternMatch pattMatch = eDSNoMatch1;
CRecNameList *cpRecNameList = nil;
CRecTypeList *cpRecTypeList = nil;
CAttributeList *cpAttrTypeList = nil;
sNIContextData *pContext = nil;
sNIContinueData *pContinue = nil;
CBuff *outBuff = nil;
bool bBuffFull = false;
bool separateRecTypes = false;
uInt32 countDownRecTypes = 0;
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 = (sNIContextData *)gNINodeRef->GetItemData( inData->fInNodeRef );
if ( pContext == nil ) throw( (sInt32)eDSInvalidNodeRef );
if ( inData->fIOContinueData == nil )
{
pContinue = (sNIContinueData *)::calloc( sizeof( sNIContinueData ), sizeof( char ) );
gNIContinue->AddItem( pContinue, inData->fInNodeRef );
pContinue->fRecNameIndex = 1;
pContinue->fAllRecIndex = 0;
pContinue->fTotalRecCount = 0;
pContinue->fMultiMapIndex = 0;
pContinue->fRecTypeIndex = 1;
pContinue->fAttrIndex = 1;
pContinue->fLimitRecSearch = 0;
if (inData->fOutRecEntryCount >= 0)
{
pContinue->fLimitRecSearch = inData->fOutRecEntryCount;
}
}
else
{
pContinue = (sNIContinueData *)inData->fIOContinueData;
if ( gNIContinue->VerifyItem( pContinue ) == 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 );
cpRecNameList = new CRecNameList( inData->fInRecNameList );
if ( cpRecNameList == nil ) throw( (sInt32)eDSEmptyRecordNameList );
if (cpRecNameList->GetCount() == 0) throw( (sInt32)eDSEmptyRecordNameList );
pattMatch = inData->fInPatternMatch;
siResult = VerifyPatternMatch( pattMatch );
if ( siResult != eDSNoErr ) throw( (sInt32)eDSInvalidPatternMatchType );
cpRecTypeList = new CRecTypeList( inData->fInRecTypeList );
if ( cpRecTypeList == nil ) throw( (sInt32)eDSEmptyRecordTypeList );
if (cpRecTypeList->GetCount() == 0) throw( (sInt32)eDSEmptyRecordTypeList );
countDownRecTypes = cpRecTypeList->GetCount() - pContinue->fRecTypeIndex + 1;
cpAttrTypeList = new CAttributeList( inData->fInAttribTypeList );
if ( cpAttrTypeList == nil ) throw( (sInt32)eDSEmptyAttributeTypeList );
if (cpAttrTypeList->GetCount() == 0) throw( (sInt32)eDSEmptyAttributeTypeList );
bAttribOnly = inData->fInAttribInfoOnly;
while ( ( cpRecTypeList->GetAttribute( pContinue->fRecTypeIndex, &pRecType ) == eDSNoErr ) &&
(!bBuffFull) && (!separateRecTypes) )
{
pNIRecType = MapRecToNetInfoType( pRecType );
if ( pNIRecType != nil )
{
while ( (cpRecNameList->GetAttribute( pContinue->fRecNameIndex, &pRecName ) == eDSNoErr) &&
(siResult == eDSNoErr) && (!bBuffFull) )
{
bBuffFull = false;
if ( ::strcmp( pRecName, kDSRecordsAll ) == 0 )
{
siResult = GetAllRecords( (const char *)pRecType,
pNIRecType,
cpAttrTypeList,
pContinue,
pContext,
bAttribOnly,
outBuff,
uiCount );
}
else
{
siResult = GetTheseRecords ( pRecName,
(const char *)pRecType,
pNIRecType,
pattMatch,
cpAttrTypeList,
pContext,
bAttribOnly,
outBuff,
pContinue,
uiCount );
}
if ( siResult == CBuff::kBuffFull )
{
bBuffFull = true;
inData->fIOContinueData = pContinue;
if ( ( uiCount == 0 ) && ( uiTotal == 0 ) )
{
throw( (sInt32)eDSBufferTooSmall );
}
uiTotal += uiCount;
inData->fOutRecEntryCount = uiTotal;
outBuff->SetLengthToSize();
siResult = eDSNoErr;
}
else if ( siResult == eDSNoErr )
{
uiTotal += uiCount;
pContinue->fRecNameIndex++;
}
} delete( pNIRecType );
pNIRecType = nil;
}
else
{
siResult = eDSInvalidRecordType;
}
if ( !bBuffFull )
{
pRecType = nil;
pContinue->fRecTypeIndex++;
pContinue->fRecNameIndex = 1;
separateRecTypes = true;
inData->fIOContinueData = pContinue;
if ( pContinue->fNIEntryList.ni_entrylist_len > 0 )
{
::ni_entrylist_free(&(pContinue->fNIEntryList));
pContinue->fNIEntryList.ni_entrylist_len = 0;
}
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 ( (inData->fIOContinueData == nil) && (pContinue != nil) )
{
gNetInfoMutex->Wait();
gNIContinue->RemoveItem( pContinue );
gNetInfoMutex->Signal();
pContinue = nil;
}
if ( cpRecNameList != nil )
{
delete( cpRecNameList );
cpRecNameList = nil;
}
if ( cpRecTypeList != nil )
{
delete( cpRecTypeList );
cpRecTypeList = nil;
}
if ( cpAttrTypeList != nil )
{
delete( cpAttrTypeList );
cpAttrTypeList = nil;
}
if ( outBuff != nil )
{
delete( outBuff );
outBuff = nil;
}
if ( pNIRecType != nil )
{
delete( pNIRecType );
pNIRecType = nil;
}
return( siResult );
}
sInt32 CNiPlugIn::GetAllRecords ( const char *inRecType,
char *inNI_RecType,
CAttributeList *inAttrTypeList,
sNIContinueData *inContinue,
sNIContextData *inContext,
bool inAttrOnly,
CBuff *inBuff,
uInt32 &outRecCount )
{
sInt32 siResult = eDSNoErr;
sInt32 siValCnt = 0;
char *pDS_RecType = 0;
u_int en = 0;
ni_index niIndex = 0;
ni_id niDirID;
ni_entry niEntry;
ni_proplist niPropList;
ni_entrylist niEntryList;
void *aNIDomain = NULL;
gNetInfoMutex->Wait();
try
{
NI_INIT( &niDirID );
NI_INIT( &niEntry );
NI_INIT( &niPropList );
NI_INIT( &niEntryList );
outRecCount = 0;
aNIDomain = RetrieveNIDomain(inContext);
if (aNIDomain != NULL)
{
siResult = ::ni_pathsearch( aNIDomain, &niDirID, inNI_RecType );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
if ( inContinue->fNIEntryList.ni_entrylist_len == 0 )
{
siResult = ::ni_list( aNIDomain, &niDirID, "name", &(inContinue->fNIEntryList) );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
}
niEntryList = inContinue->fNIEntryList;
if (niEntryList.ni_entrylist_val == NULL)
{
niEntryList.ni_entrylist_len = 0;
}
for ( en = inContinue->fAllRecIndex; (en < niEntryList.ni_entrylist_len) &&
(((inContinue->fTotalRecCount) < inContinue->fLimitRecSearch) ||
(inContinue->fLimitRecSearch == 0)); en++ )
{
niEntry = niEntryList.ni_entrylist_val[ en ];
niDirID.nii_object = niEntry.id;
siResult = ::ni_read( aNIDomain, &niDirID, &niPropList );
if ( siResult == NI_OK )
{
siResult = GetTheseAttributes( inAttrTypeList, &niPropList, inAttrOnly, aNIDomain, inContext->fDomainName, inRecType, siValCnt );
if ( siResult == eDSNoErr )
{
fRecData->Clear();
pDS_RecType = MapNetInfoRecToDSType( inNI_RecType );
if ( pDS_RecType != nil )
{
fRecData->AppendShort( ::strlen( pDS_RecType ) );
fRecData->AppendString( pDS_RecType );
delete( pDS_RecType );
pDS_RecType = nil;
}
niIndex = ::ni_proplist_match( niPropList, "name", NULL );
if ( niIndex == NI_INDEX_NULL || niPropList.nipl_val[ niIndex ].nip_val.ninl_len == 0 )
{
fRecData->AppendShort( ::strlen( "*** No Name ***" ) );
fRecData->AppendString( "*** No Name ***" );
}
else
{
fRecData->AppendShort( ::strlen( niPropList.nipl_val[ niIndex ].nip_val.ninl_val[ 0 ] ) );
fRecData->AppendString( niPropList.nipl_val[ niIndex ].nip_val.ninl_val[ 0 ] );
}
if ( siValCnt == 0 )
{
fRecData->AppendShort( 0 );
}
else
{
fRecData->AppendShort( siValCnt );
fRecData->AppendBlock( fAttrData->GetData(), fAttrData->GetLength() );
}
siResult = inBuff->AddData( fRecData->GetData(), fRecData->GetLength() );
if ( siResult == CBuff::kBuffFull )
{
inContinue->fAllRecIndex = en;
::ni_proplist_free( &niPropList );
break;
}
else if ( siResult == eDSNoErr )
{
outRecCount++;
inContinue->fTotalRecCount++;
}
else
{
inContinue->fAllRecIndex = 0;
::ni_proplist_free( &niPropList );
siResult = eDSInvalidBuffFormat;
break;
}
}
::ni_proplist_free( &niPropList );
}
}
if ( siResult == eDSNoErr )
{
inContinue->fAllRecIndex = 0;
}
}
else
{
throw( (sInt32)eDSInvalidSession );
}
}
catch( sInt32 err )
{
siResult = err;
}
gNetInfoMutex->Signal();
return( siResult );
}
sInt32 CNiPlugIn:: GetTheseRecords (char *inConstRecName,
const char *inConstRecType,
char *inNativeRecType,
tDirPatternMatch inPattMatch,
CAttributeList *inAttrTypeList,
sNIContextData *inContext,
bool inAttrOnly,
CBuff *inBuff,
sNIContinueData *inContinue,
uInt32 &outRecCount )
{
sInt32 siResult = eDSNoErr;
sInt32 siCount = 0;
u_int en = 0;
ni_status niStatus = NI_OK;
ni_index niIndex = 0;
ni_index niIndexComp = 0;
ni_id niDirID;
ni_proplist niPropList;
ni_entry niEntry;
ni_entrylist niEntryList;
bool bGetThisOne = true;
char *normalizedRecName = nil;
char *inConstRegExpRecName = nil;
bool bGotAMatch = false;
void *aNIDomain = NULL;
gNetInfoMutex->Wait();
try
{
NI_INIT( &niDirID );
NI_INIT( &niEntry );
NI_INIT( &niPropList );
NI_INIT( &niEntryList );
outRecCount = 0;
fRecData->Clear();
aNIDomain = RetrieveNIDomain(inContext);
if (aNIDomain != NULL)
{
if ( (::strcmp( inNativeRecType, "users" ) == 0 ) &&
((inContinue->fMultiMapIndex == 0) || (inContinue->fMultiMapIndex == 2) || (inContinue->fMultiMapIndex == 3)) )
{
niStatus = ::ni_pathsearch( aNIDomain, &niDirID, "/users" );
if ( niStatus == NI_OK )
{
inConstRegExpRecName = BuildRegExp(inConstRecName);
niStatus = ::ni_search( aNIDomain, &niDirID, (char *)"name", inConstRegExpRecName, REG_ICASE, &niEntryList );
DSFreeString(inConstRegExpRecName);
if ( (niStatus == NI_OK) && (niEntryList.ni_entrylist_val != NULL) &&
((inContinue->fMultiMapIndex == 0) || (inContinue->fMultiMapIndex == 2)) )
{
for ( en = inContinue->fAllRecIndex; (en < niEntryList.ni_entrylist_len) &&
(((inContinue->fTotalRecCount) < inContinue->fLimitRecSearch) ||
(inContinue->fLimitRecSearch == 0)); en++ )
{
niEntry = niEntryList.ni_entrylist_val[ en ];
niDirID.nii_object = niEntry.id;
niStatus = ::ni_read( aNIDomain, &niDirID, &niPropList );
if ( niStatus == NI_OK )
{
niIndex = ::ni_proplist_match( niPropList, "name", NULL );
if ( niIndex != NI_INDEX_NULL )
{
bGotAMatch = false;
for ( uInt32 pv = 0; pv < niPropList.nipl_val[ niIndex ].nip_val.ninl_len; pv++ )
{
if ( DoesThisMatch( (const char*)(niPropList.nipl_val[ niIndex ].nip_val.ninl_val[ pv ]),
(const char*)inConstRecName,
inPattMatch ) )
{
bGotAMatch = true;
break;
}
}
if (bGotAMatch)
{
fRecData->AppendShort( ::strlen( inConstRecType ) );
fRecData->AppendString( inConstRecType );
niIndex = ::ni_proplist_match( niPropList, "name", NULL );
if ( niIndex == NI_INDEX_NULL || niPropList.nipl_val[ niIndex ].nip_val.ninl_len == 0 )
{
fRecData->AppendShort( ::strlen( "*** No Name ***" ) );
fRecData->AppendString( "*** No Name ***" );
}
else
{
fRecData->AppendShort( ::strlen( niPropList.nipl_val[ niIndex ].nip_val.ninl_val[ 0 ] ) );
fRecData->AppendString( niPropList.nipl_val[ niIndex ].nip_val.ninl_val[ 0 ] );
}
siResult = GetTheseAttributes( inAttrTypeList, &niPropList, inAttrOnly, aNIDomain, inContext->fDomainName, inConstRecType, siCount );
if ( siResult == eDSNoErr )
{
if ( siCount == 0 )
{
fRecData->AppendShort( 0 );
}
else
{
fRecData->AppendShort( siCount );
fRecData->AppendBlock( fAttrData->GetData(), fAttrData->GetLength() );
}
siResult = inBuff->AddData( fRecData->GetData(), fRecData->GetLength() );
fRecData->Clear();
if ( siResult == CBuff::kBuffFull )
{
inContinue->fMultiMapIndex = 2;
inContinue->fAllRecIndex = en;
::ni_proplist_free( &niPropList );
throw( siResult );
}
else if ( siResult == eDSNoErr )
{
inContinue->fMultiMapIndex = 0;
outRecCount++;
inContinue->fTotalRecCount++;
}
else
{
inContinue->fMultiMapIndex = 0;
::ni_proplist_free( &niPropList );
throw( (sInt32)eDSInvalidBuffFormat );
}
} } }
::ni_proplist_free( &niPropList );
}
} }
if (niEntryList.ni_entrylist_len > 0)
{
::ni_entrylist_free( &niEntryList );
niEntryList.ni_entrylist_len = 0;
}
NI_INIT( &niEntryList );
if ( (inContinue->fTotalRecCount < inContinue->fLimitRecSearch) || (inContinue->fLimitRecSearch == 0) )
{
NI_INIT( &niDirID );
niStatus = ::ni_pathsearch( aNIDomain, &niDirID, "/users" );
if ( niStatus == NI_OK )
{
normalizedRecName = NormalizeNIString( inConstRecName, "realname" );
inConstRegExpRecName = BuildRegExp(normalizedRecName);
niStatus = ::ni_search( aNIDomain, &niDirID, (char *)"realname", inConstRegExpRecName, REG_ICASE, &niEntryList );
DSFreeString(inConstRegExpRecName);
if ( (niStatus == NI_OK) && (niEntryList.ni_entrylist_val != NULL) &&
((inContinue->fMultiMapIndex == 0) || (inContinue->fMultiMapIndex == 3)) )
{
for ( en = inContinue->fAllRecIndex; (en < niEntryList.ni_entrylist_len) &&
(((inContinue->fTotalRecCount) < inContinue->fLimitRecSearch) ||
(inContinue->fLimitRecSearch == 0)); en++ )
{
niEntry = niEntryList.ni_entrylist_val[ en ];
niDirID.nii_object = niEntry.id;
niStatus = ::ni_read( aNIDomain, &niDirID, &niPropList );
if ( niStatus == NI_OK )
{
niIndex = ::ni_proplist_match( niPropList, "realname", NULL );
if ( niIndex != NI_INDEX_NULL )
{
bGotAMatch = false;
for ( uInt32 pv = 0; pv < niPropList.nipl_val[ niIndex ].nip_val.ninl_len; pv++ )
{
if ( DoesThisMatch( (const char*)(niPropList.nipl_val[ niIndex ].nip_val.ninl_val[ pv ]),
(const char*)normalizedRecName,
inPattMatch ) )
{
bGotAMatch = true;
break;
}
}
if (bGotAMatch)
{
bGetThisOne = true;
niIndexComp = ::ni_proplist_match( niPropList, "name", NULL );
if ( niIndexComp != NI_INDEX_NULL )
{
for ( uInt32 pv = 0; pv < niPropList.nipl_val[ niIndexComp ].nip_val.ninl_len; pv++ )
{
if ( DoesThisMatch( (const char*)(niPropList.nipl_val[ niIndexComp ].nip_val.ninl_val[ pv ]),
(const char*)normalizedRecName,
inPattMatch ) )
{
bGetThisOne = false;
break;
}
}
}
if (bGetThisOne)
{
fRecData->AppendShort( ::strlen( inConstRecType ) );
fRecData->AppendString( inConstRecType );
niIndex = ::ni_proplist_match( niPropList, "name", NULL );
if ( niIndex == NI_INDEX_NULL || niPropList.nipl_val[ niIndex ].nip_val.ninl_len == 0 )
{
fRecData->AppendShort( ::strlen( "*** No Name ***" ) );
fRecData->AppendString( "*** No Name ***" );
}
else
{
fRecData->AppendShort( ::strlen( niPropList.nipl_val[ niIndex ].nip_val.ninl_val[ 0 ] ) );
fRecData->AppendString( niPropList.nipl_val[ niIndex ].nip_val.ninl_val[ 0 ] );
}
siResult = GetTheseAttributes( inAttrTypeList, &niPropList, inAttrOnly, aNIDomain, inContext->fDomainName, inConstRecType, siCount );
if ( siResult == eDSNoErr )
{
if ( siCount == 0 )
{
fRecData->AppendShort( 0 );
}
else
{
fRecData->AppendShort( siCount );
fRecData->AppendBlock( fAttrData->GetData(), fAttrData->GetLength() );
}
siResult = inBuff->AddData( fRecData->GetData(), fRecData->GetLength() );
fRecData->Clear();
if ( siResult == CBuff::kBuffFull )
{
inContinue->fMultiMapIndex = 3;
inContinue->fAllRecIndex = en;
::ni_proplist_free( &niPropList );
if ( siResult != eDSNoErr ) throw( siResult );
}
else if ( siResult == eDSNoErr )
{
inContinue->fMultiMapIndex = 0;
outRecCount++;
inContinue->fTotalRecCount++;
}
else
{
inContinue->fMultiMapIndex = 0;
::ni_proplist_free( &niPropList );
throw( (sInt32)eDSInvalidBuffFormat );
}
}
} } }
::ni_proplist_free( &niPropList );
} } } if ( niEntryList.ni_entrylist_len > 0 )
{
::ni_entrylist_free(&niEntryList);
niEntryList.ni_entrylist_len = 0;
}
} } } }
else if ( (inContinue->fMultiMapIndex == 0) || (inContinue->fMultiMapIndex == 1) )
{
niStatus = ::ni_pathsearch( aNIDomain, &niDirID, inNativeRecType );
if ( niStatus == NI_OK )
{
inConstRegExpRecName = BuildRegExp(inConstRecName);
if ( (strcmp(inConstRecName,"/") == 0) &&
((inContinue->fMultiMapIndex == 0) || (inContinue->fMultiMapIndex == 1)) )
{
niStatus = ::ni_read( aNIDomain, &niDirID, &niPropList );
if ( niStatus == NI_OK )
{
fRecData->AppendShort( ::strlen( inConstRecType ) );
fRecData->AppendString( inConstRecType );
fRecData->AppendShort( 1 );
fRecData->AppendString( "/" );
siResult = GetTheseAttributes( inAttrTypeList, &niPropList, inAttrOnly, aNIDomain, inContext->fDomainName, inConstRecType, siCount );
if ( siResult == eDSNoErr )
{
if ( siCount == 0 )
{
fRecData->AppendShort( 0 );
}
else
{
fRecData->AppendShort( siCount );
fRecData->AppendBlock( fAttrData->GetData(), fAttrData->GetLength() );
}
siResult = inBuff->AddData( fRecData->GetData(), fRecData->GetLength() );
fRecData->Clear();
if ( siResult == CBuff::kBuffFull )
{
inContinue->fMultiMapIndex = 1;
inContinue->fAllRecIndex = en;
::ni_proplist_free( &niPropList );
if ( siResult != eDSNoErr ) throw( siResult );
}
else if ( siResult == eDSNoErr )
{
inContinue->fMultiMapIndex = 0;
outRecCount++;
inContinue->fTotalRecCount++;
}
else
{
inContinue->fMultiMapIndex = 0;
::ni_proplist_free( &niPropList );
throw( (sInt32)eDSInvalidBuffFormat );
}
} ::ni_proplist_free( &niPropList );
} }
else
{
niStatus = ::ni_search( aNIDomain, &niDirID, (char *)"name", inConstRegExpRecName, REG_ICASE, &niEntryList );
if ( (niStatus == NI_OK) && (niEntryList.ni_entrylist_val != NULL) &&
((inContinue->fMultiMapIndex == 0) || (inContinue->fMultiMapIndex == 1)) )
{
for ( en = inContinue->fAllRecIndex; (en < niEntryList.ni_entrylist_len) &&
(((inContinue->fTotalRecCount) < inContinue->fLimitRecSearch) ||
(inContinue->fLimitRecSearch == 0)); en++ )
{
niEntry = niEntryList.ni_entrylist_val[ en ];
niDirID.nii_object = niEntry.id;
niStatus = ::ni_read( aNIDomain, &niDirID, &niPropList );
if ( niStatus == NI_OK )
{
niIndex = ::ni_proplist_match( niPropList, "name", NULL );
if ( niIndex != NI_INDEX_NULL )
{
bGotAMatch = false;
for ( uInt32 pv = 0; pv < niPropList.nipl_val[ niIndex ].nip_val.ninl_len; pv++ )
{
if ( DoesThisMatch( (const char*)(niPropList.nipl_val[ niIndex ].nip_val.ninl_val[ pv ]),
(const char*)inConstRecName,
inPattMatch ) )
{
bGotAMatch = true;
break;
}
}
if (bGotAMatch)
{
fRecData->AppendShort( ::strlen( inConstRecType ) );
fRecData->AppendString( inConstRecType );
niIndex = ::ni_proplist_match( niPropList, "name", NULL );
if ( niIndex == NI_INDEX_NULL || niPropList.nipl_val[ niIndex ].nip_val.ninl_len == 0 )
{
fRecData->AppendShort( ::strlen( "*** No Name ***" ) );
fRecData->AppendString( "*** No Name ***" );
}
else
{
fRecData->AppendShort( ::strlen( niPropList.nipl_val[ niIndex ].nip_val.ninl_val[ 0 ] ) );
fRecData->AppendString( niPropList.nipl_val[ niIndex ].nip_val.ninl_val[ 0 ] );
}
siResult = GetTheseAttributes( inAttrTypeList, &niPropList, inAttrOnly, aNIDomain, inContext->fDomainName, inConstRecType, siCount );
if ( siResult == eDSNoErr )
{
if ( siCount == 0 )
{
fRecData->AppendShort( 0 );
}
else
{
fRecData->AppendShort( siCount );
fRecData->AppendBlock( fAttrData->GetData(), fAttrData->GetLength() );
}
siResult = inBuff->AddData( fRecData->GetData(), fRecData->GetLength() );
fRecData->Clear();
if ( siResult == CBuff::kBuffFull )
{
inContinue->fMultiMapIndex = 1;
inContinue->fAllRecIndex = en;
::ni_proplist_free( &niPropList );
if ( siResult != eDSNoErr ) throw( siResult );
}
else if ( siResult == eDSNoErr )
{
inContinue->fMultiMapIndex = 0;
outRecCount++;
inContinue->fTotalRecCount++;
}
else
{
inContinue->fMultiMapIndex = 0;
::ni_proplist_free( &niPropList );
throw( (sInt32)eDSInvalidBuffFormat );
}
} } }
::ni_proplist_free( &niPropList );
} }
} if ( niEntryList.ni_entrylist_len > 0 )
{
::ni_entrylist_free(&niEntryList);
niEntryList.ni_entrylist_len = 0;
}
}
DSFreeString(inConstRegExpRecName);
} }
inContinue->fMultiMapIndex = 0;
inContinue->fAllRecIndex = 0;
}
else
{
throw( (sInt32)eDSInvalidSession );
}
}
catch( sInt32 err )
{
if ( niEntryList.ni_entrylist_len > 0 )
{
::ni_entrylist_free(&niEntryList);
niEntryList.ni_entrylist_len = 0;
}
siResult = err;
}
if ( normalizedRecName != inConstRecName )
{
DSFreeString( normalizedRecName );
}
gNetInfoMutex->Signal();
return( siResult );
}
sInt32 CNiPlugIn::GetTheseAttributes ( CAttributeList *inAttrTypeList,
ni_proplist *inPropList,
bool inAttrOnly,
void *inDomain,
char *inDomainName,
const char *inRecType,
sInt32 &outCount )
{
sInt32 siResult = eDSNoErr;
uInt32 pn = 0;
uInt32 pv = 0;
sInt32 attrTypeIndex = 1;
char *pNI_AttrType = nil;
char *pDS_AttrType = nil;
char *pDS_AttrName = nil;
ni_index niIndex = 0;
ni_property niProp;
ni_namelist niNameList;
gNetInfoMutex->Wait();
try
{
outCount = 0;
fAttrData->Clear();
while ( inAttrTypeList->GetAttribute( attrTypeIndex++, &pDS_AttrType ) == eDSNoErr )
{
siResult = eDSNoErr;
pNI_AttrType = MapAttrToNetInfoType( pDS_AttrType );
if ( pNI_AttrType != nil )
{
if ( ::strcmp( kDSNAttrMetaNodeLocation, pNI_AttrType ) == 0 )
{
fTmpData->Clear();
outCount++;
fTmpData->AppendShort( ::strlen( pDS_AttrType ) );
fTmpData->AppendString( pDS_AttrType );
if ( inAttrOnly == false )
{
fTmpData->AppendShort( 1 );
fTmpData->AppendLong( ::strlen( inDomainName ) );
fTmpData->AppendString( inDomainName );
}
else
{
fTmpData->AppendShort( 0 );
}
fAttrData->AppendLong( fTmpData->GetLength() );
fAttrData->AppendBlock( fTmpData->GetData(), fTmpData->GetLength() );
fTmpData->Clear();
}
else if ( ::strcmp( kDSNAttrRecordType, pNI_AttrType ) == 0 )
{
fTmpData->Clear();
fTmpData->AppendShort( ::strlen( pNI_AttrType ) );
fTmpData->AppendString( pNI_AttrType );
if ( inAttrOnly == false )
{
fTmpData->AppendShort( 1 );
fTmpData->AppendLong( ::strlen( inRecType ) );
fTmpData->AppendString( inRecType );
} else
{
fTmpData->AppendShort( 0 );
}
outCount++;
fAttrData->AppendLong( fTmpData->GetLength() );
fAttrData->AppendBlock( fTmpData->GetData(), fTmpData->GetLength() );
fTmpData->Clear();
} else
{
if ( ( ::strcmp( kDSAttributesAll, pNI_AttrType ) == 0 ) ||
( ::strcmp( kDSAttributesStandardAll, pNI_AttrType ) == 0 ) )
{
fTmpData->Clear();
fTmpData->AppendShort( ::strlen( kDSNAttrMetaNodeLocation ) );
fTmpData->AppendString( kDSNAttrMetaNodeLocation );
if ( inAttrOnly == false )
{
fTmpData->AppendShort( 1 );
fTmpData->AppendLong( ::strlen( inDomainName ) );
fTmpData->AppendString( inDomainName );
}
else
{
fTmpData->AppendShort( 0 );
}
outCount++;
fAttrData->AppendLong( fTmpData->GetLength() );
fAttrData->AppendBlock( fTmpData->GetData(), fTmpData->GetLength() );
fTmpData->Clear();
fTmpData->AppendShort( ::strlen( kDSNAttrRecordType ) );
fTmpData->AppendString( kDSNAttrRecordType );
if ( inAttrOnly == false )
{
fTmpData->AppendShort( 1 );
fTmpData->AppendLong( ::strlen( inRecType ) );
fTmpData->AppendString( inRecType );
} else
{
fTmpData->AppendShort( 0 );
}
outCount++;
fAttrData->AppendLong( fTmpData->GetLength() );
fAttrData->AppendBlock( fTmpData->GetData(), fTmpData->GetLength() );
fTmpData->Clear();
for ( pn = 0; pn < inPropList->ni_proplist_len; pn++ )
{
niProp = inPropList->ni_proplist_val[ pn ];
fTmpData->Clear();
pDS_AttrName = MapNetInfoAttrToDSType( niProp.nip_name );
if ( pDS_AttrName != nil )
{
if ( ( ::strncmp(pDS_AttrName,kDSNativeAttrTypePrefix,strlen(kDSNativeAttrTypePrefix)) == 0 ) &&
( ::strcmp( kDSAttributesStandardAll, pNI_AttrType ) == 0 ) )
{
delete( pDS_AttrName );
pDS_AttrName = nil;
continue;
}
else
{
fTmpData->AppendShort( ::strlen( pDS_AttrName ) );
fTmpData->AppendString( pDS_AttrName );
outCount++;
delete( pDS_AttrName );
pDS_AttrName = nil;
if ( inAttrOnly == false )
{
niNameList = niProp.nip_val;
fTmpData->AppendShort( niNameList.ni_namelist_len );
for ( pv = 0; pv < niNameList.ni_namelist_len; pv++ )
{
fTmpData->AppendLong( ::strlen( niNameList.ni_namelist_val[ pv ] ) );
fTmpData->AppendString( niNameList.ni_namelist_val[ pv ] );
}
}
else
{
fTmpData->AppendShort( 0 );
}
fAttrData->AppendLong( fTmpData->GetLength() );
fAttrData->AppendBlock( fTmpData->GetData(), fTmpData->GetLength() );
fTmpData->Clear();
} } }
}
else
{
niIndex = ::ni_proplist_match( *inPropList, pNI_AttrType, NULL );
if ( niIndex != NI_INDEX_NULL )
{
fTmpData->Clear();
outCount++;
fTmpData->AppendShort( ::strlen( pDS_AttrType ) );
fTmpData->AppendString( pDS_AttrType );
if ( inAttrOnly == false )
{
niNameList = inPropList->nipl_val[ niIndex ].nip_val;
fTmpData->AppendShort( niNameList.ni_namelist_len );
for ( pv = 0; pv < niNameList.ni_namelist_len; pv++ )
{
fTmpData->AppendLong( ::strlen( niNameList.ni_namelist_val[ pv ] ) );
fTmpData->AppendString( niNameList.ni_namelist_val[ pv ] );
}
}
else
{
fTmpData->AppendShort( 0 );
}
fAttrData->AppendLong( fTmpData->GetLength() );
fAttrData->AppendBlock( fTmpData->GetData(), fTmpData->GetLength() );
fTmpData->Clear();
}
}
}
delete( pNI_AttrType );
pNI_AttrType = nil;
}
}
}
catch( sInt32 err )
{
siResult = err;
}
gNetInfoMutex->Signal();
return( siResult );
}
sInt32 CNiPlugIn::AddAttribute ( sAddAttribute *inData )
{
sInt32 siResult = eDSNoErr;
tDataNode *pNewAttr = nil;
char *pAttrKey = nil;
tDataNode *pAttrValue = nil;
sNIContextData *pContext = nil;
char *pEmptyValue = (char *)"";
char *pValue = nil;
ni_namelist niValues;
char *authUser = nil;
gNetInfoMutex->Wait();
try
{
pContext = (sNIContextData *)gNINodeRef->GetItemData( inData->fInRecRef );
if ( pContext == nil ) throw( (sInt32)eDSInvalidRecordRef );
pNewAttr = inData->fInNewAttr;
if ( pNewAttr == nil ) throw( (sInt32)eDSNullAttribute );
pAttrKey = MapAttrToNetInfoType( pNewAttr->fBufferData );
if ( pAttrKey == nil ) throw( (sInt32)eDSNullAttribute );
pAttrValue = inData->fInFirstAttrValue;
if ( pAttrValue == nil )
{
pValue = pEmptyValue;
}
else
{
pValue = pAttrValue->fBufferData;
}
void * aNIDomain = RetrieveNIDomain(pContext);
if (aNIDomain != NULL)
{
if ( ( pContext->fEffectiveUID != 0 )
&& ( (pContext->fAuthenticatedUserName == NULL)
|| (strcmp(pContext->fAuthenticatedUserName,"root") != 0) ) )
{
authUser = pContext->fAuthenticatedUserName;
if ( ( authUser == NULL ) && (strcmp(pAttrKey,"picture") == 0) )
{
authUser = GetUserNameForUID( pContext->fEffectiveUID, aNIDomain );
}
ni_proplist niPropList;
siResult = ::ni_read( aNIDomain, &pContext->dirID, &niPropList );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
siResult = NiLib2::ValidateDir( authUser, &niPropList );
::ni_proplist_free( &niPropList );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
}
NI_INIT( &niValues );
::ni_namelist_insert( &niValues, pValue, NI_INDEX_NULL );
NormalizeNINameList(&niValues, pAttrKey);
siResult = DoAddAttribute( aNIDomain, &pContext->dirID, pAttrKey, niValues );
::ni_namelist_free( &niValues );
if (siResult == eDSNoErr)
{
pContext->bDidWriteOperation = true;
}
}
else
{
throw( (sInt32)eDSInvalidSession );
}
}
catch( sInt32 err )
{
siResult = err;
}
if (authUser != nil)
{
if (pContext != nil)
{
if (pContext->fAuthenticatedUserName == nil)
{
free(authUser);
authUser = nil;
}
}
}
if ( pAttrKey != nil )
{
delete( pAttrKey );
pAttrKey = nil;
}
gNetInfoMutex->Signal();
return( siResult );
}
sInt32 CNiPlugIn::DoAddAttribute ( void *inDomain,
ni_id *inDir,
const ni_name inKey,
ni_namelist inValues )
{
sInt32 siResult = eDSNoErr;
ni_index where = 0;
ni_property niPropList;
ni_namelist niNameList;
gNetInfoMutex->Wait();
try
{
::ni_needwrite( inDomain, 1 );
NI_INIT( &niNameList );
siResult = ::ni_listprops( inDomain, inDir, &niNameList );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
where = ::ni_namelist_match( niNameList, inKey );
::ni_namelist_free( &niNameList );
if ( where == NI_INDEX_NULL )
{
NI_INIT( &niPropList );
niPropList.nip_name = ::ni_name_dup( inKey );
niPropList.nip_val = ::ni_namelist_dup( inValues );
siResult = ::ni_createprop( inDomain, inDir, niPropList, NI_INDEX_NULL );
::ni_prop_free( &niPropList );
}
else
{
siResult = ::ni_writeprop( inDomain, inDir, where, inValues );
}
siResult = MapNetInfoErrors( siResult );
}
catch( sInt32 err )
{
siResult = err;
}
gNetInfoMutex->Signal();
return( siResult );
}
sInt32 CNiPlugIn::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;
sNIContextData *pValueContext = nil;
uInt32 buffSize = 0;
uInt32 buffLen = 0;
uInt32 attrLen = 0;
try
{
pValueContext = (sNIContextData *)gNINodeRef->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 (4 + offset > buffSize) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &attrLen, p, 4 );
buffLen = attrLen + pValueContext->offset + 4;
if (buffLen > buffSize) throw( (sInt32)eDSInvalidBuffFormat );
p += 4;
offset += 4;
if (2 + offset > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &usAttrNameLen, p, 2 );
p += 2 + usAttrNameLen;
offset += 2 + usAttrNameLen;
if (2 + offset > 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 (4 + offset > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &usValueLen, p, 4 );
p += 4 + usValueLen;
offset += 4 + usValueLen;
}
if (4 + offset > 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 ( usValueLen + offset > 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 CNiPlugIn::GetRecAttribInfo ( sGetRecAttribInfo *inData )
{
bool bFound = false;
sInt32 siResult = eDSNoErr;
ni_status niStatus = NI_OK;
uInt32 uiPv = 0;
uInt32 uiTypeLen = 0;
uInt32 uiDataLen = 0;
tDataNodePtr pAttrType = nil;
char *pNI_AttrType = nil;
tAttributeEntryPtr pOutAttrEntry = nil;
sNIContextData *pContext = nil;
ni_id niDirID;
ni_namelist niNameList; ni_index niIndex;
gNetInfoMutex->Wait();
try
{
pContext = (sNIContextData *)gNINodeRef->GetItemData( inData->fInRecRef );
if ( pContext == nil ) throw( (sInt32)eDSInvalidRecordRef );
pAttrType = inData->fInAttrType;
if ( pAttrType == nil ) throw( (sInt32)eDSEmptyAttributeType );
pNI_AttrType = MapAttrToNetInfoType( pAttrType->fBufferData );
if ( pNI_AttrType == nil ) throw( (sInt32)eDSInvalidAttributeType );
void * aNIDomain = RetrieveNIDomain(pContext);
if (aNIDomain != NULL)
{
::memcpy( &niDirID, &pContext->dirID, sizeof( ni_id ) );
NI_INIT( &niNameList );
niStatus = ::ni_listprops( aNIDomain, &niDirID, &niNameList );
if ( niStatus == NI_OK )
{
niIndex = ::ni_namelist_match( niNameList, pNI_AttrType );
::ni_namelist_free( &niNameList );
if ( niIndex != NI_INDEX_NULL )
{
NI_INIT( &niNameList );
niStatus = ::ni_readprop( aNIDomain, &niDirID, niIndex, &niNameList );
if ( niStatus == NI_OK )
{
uiTypeLen = ::strlen( pAttrType->fBufferData );
pOutAttrEntry = (tAttributeEntry *)::calloc( (sizeof( tAttributeEntry ) + uiTypeLen + kBuffPad), sizeof( char ) );
pOutAttrEntry->fAttributeSignature.fBufferSize = uiTypeLen;
pOutAttrEntry->fAttributeSignature.fBufferLength = uiTypeLen;
::memcpy( pOutAttrEntry->fAttributeSignature.fBufferData, pAttrType->fBufferData, uiTypeLen );
pOutAttrEntry->fAttributeValueCount = niNameList.ni_namelist_len;
pOutAttrEntry->fAttributeValueMaxSize = 255;
for ( uiPv = 0; uiPv < niNameList.ni_namelist_len; uiPv++ )
{
uiDataLen += ::strlen( niNameList.ni_namelist_val[ uiPv ] );
}
pOutAttrEntry->fAttributeDataSize = uiDataLen;
inData->fOutAttrInfoPtr = pOutAttrEntry;
bFound = true;
::ni_namelist_free( &niNameList );
}
}
else
{
siResult = eDSAttributeNotFound;
}
}
else
{
siResult = MapNetInfoErrors( niStatus );
}
delete( pNI_AttrType );
pNI_AttrType = nil;
}
else
{
throw( (sInt32)eDSInvalidSession );
}
}
catch( sInt32 err )
{
siResult = err;
}
gNetInfoMutex->Signal();
return( siResult );
}
sInt32 CNiPlugIn::GetRecordAttributeValueByID ( sGetRecordAttributeValueByID *inData )
{
bool done = false;
sInt32 siResult = eDSAttributeNotFound;
ni_status niStatus = NI_OK;
uInt32 crcVal = 0;
uInt32 uiDataLen = 0;
uInt32 pv = 0;
char *pNI_AttrType = nil;
tAttributeValueEntryPtr pOutAttrValue = nil;
sNIContextData *pContext = nil;
ni_namelist niNameList; ni_index niIndex;
gNetInfoMutex->Wait();
try
{
pContext = (sNIContextData *)gNINodeRef->GetItemData( inData->fInRecRef );
if ( pContext == nil ) throw( (sInt32)eDSInvalidRecordRef );
if ( inData->fInAttrType == nil ) throw( (sInt32)eDSEmptyAttributeType );
pNI_AttrType = MapAttrToNetInfoType( inData->fInAttrType->fBufferData );
if ( pNI_AttrType == nil ) throw( (sInt32)eDSInvalidAttributeType );
void * aNIDomain = RetrieveNIDomain(pContext);
if (aNIDomain != NULL)
{
NI_INIT( &niNameList );
niStatus = ::ni_listprops( aNIDomain, &pContext->dirID, &niNameList );
if ( niStatus == NI_OK )
{
niIndex = ::ni_namelist_match( niNameList, pNI_AttrType );
::ni_namelist_free( &niNameList );
if ( niIndex != NI_INDEX_NULL )
{
NI_INIT( &niNameList );
niStatus = ::ni_readprop( aNIDomain, &pContext->dirID, niIndex, &niNameList );
if ( niStatus == NI_OK )
{
siResult = eDSAttributeValueNotFound;
for ( pv = 0; (pv < niNameList.ni_namelist_len) && (done == false); pv++ )
{
crcVal = CalcCRC( niNameList.ni_namelist_val[ pv ] );
if ( crcVal == inData->fInValueID )
{
if ( niNameList.ni_namelist_val[ pv ] != nil )
{
uiDataLen = ::strlen( niNameList.ni_namelist_val[ pv ] );
}
else
{
uiDataLen = 0;
}
pOutAttrValue = (tAttributeValueEntry *)::calloc( (sizeof( tAttributeValueEntry ) + uiDataLen + kBuffPad), sizeof( char ) );
pOutAttrValue->fAttributeValueData.fBufferSize = uiDataLen;
pOutAttrValue->fAttributeValueData.fBufferLength = uiDataLen;
if ( niNameList.ni_namelist_val[ pv ] != nil )
{
pOutAttrValue->fAttributeValueID = crcVal;
::memcpy( pOutAttrValue->fAttributeValueData.fBufferData, niNameList.ni_namelist_val[ pv ], uiDataLen );
}
inData->fOutEntryPtr = pOutAttrValue;
done = true;
siResult = eDSNoErr;
break;
}
}
::ni_namelist_free( &niNameList );
}
}
}
delete( pNI_AttrType );
pNI_AttrType = nil;
}
else
{
throw( (sInt32)eDSInvalidSession );
}
}
catch( sInt32 err )
{
siResult = err;
}
gNetInfoMutex->Signal();
return( siResult );
}
sInt32 CNiPlugIn::GetRecAttrValueByIndex ( sGetRecordAttributeValueByIndex *inData )
{
sInt32 siResult = eDSNoErr;
ni_status niStatus = NI_OK;
uInt32 uiDataLen = 0;
uInt32 uiIndex = 0;
char *pNI_AttrType = nil;
tAttributeValueEntryPtr pOutAttrValue = nil;
sNIContextData *pContext = nil;
ni_id niDirID;
ni_namelist niNameList; ni_index niIndex;
gNetInfoMutex->Wait();
try
{
pContext = (sNIContextData *)gNINodeRef->GetItemData( inData->fInRecRef );
if ( pContext == nil ) throw( (sInt32)eDSInvalidRecordRef );
if ( inData->fInAttrType == nil ) throw( (sInt32)eDSEmptyAttributeType );
pNI_AttrType = MapAttrToNetInfoType( inData->fInAttrType->fBufferData );
if ( pNI_AttrType == nil ) throw( (sInt32)eDSInvalidAttributeType );
uiIndex = inData->fInAttrValueIndex;
void * aNIDomain = RetrieveNIDomain(pContext);
if (aNIDomain != NULL)
{
::memcpy( &niDirID, &pContext->dirID, sizeof( ni_id ) );
NI_INIT( &niNameList );
niStatus = ::ni_listprops( aNIDomain, &niDirID, &niNameList );
if ( niStatus == NI_OK )
{
niIndex = ::ni_namelist_match( niNameList, pNI_AttrType );
::ni_namelist_free( &niNameList );
if ( niIndex != NI_INDEX_NULL )
{
NI_INIT( &niNameList );
niStatus = ::ni_readprop( aNIDomain, &niDirID, niIndex, &niNameList );
if ( niStatus == NI_OK )
{
if ( ( niNameList.ni_namelist_len >= uiIndex ) && (uiIndex > 0) )
{
if ( niNameList.ni_namelist_val[ uiIndex - 1 ] != nil )
{
uiDataLen = ::strlen( niNameList.ni_namelist_val[ uiIndex - 1 ] );
}
else
{
uiDataLen = 0;
}
pOutAttrValue = (tAttributeValueEntry *)::calloc( 1, sizeof( tAttributeValueEntry ) + uiDataLen + kBuffPad );
pOutAttrValue->fAttributeValueData.fBufferSize = uiDataLen;
pOutAttrValue->fAttributeValueData.fBufferLength = uiDataLen;
if ( niNameList.ni_namelist_val[ uiIndex - 1 ] != nil )
{
pOutAttrValue->fAttributeValueID = CalcCRC( niNameList.ni_namelist_val[ uiIndex - 1 ] );
::memcpy( pOutAttrValue->fAttributeValueData.fBufferData, niNameList.ni_namelist_val[ uiIndex - 1 ], uiDataLen );
}
inData->fOutEntryPtr = pOutAttrValue;
}
else
{
siResult = eDSIndexOutOfRange;
}
::ni_namelist_free( &niNameList );
}
}
else
{
siResult = eDSAttributeNotFound;
}
}
delete( pNI_AttrType );
pNI_AttrType = nil;
}
else
{
throw( (sInt32)eDSInvalidSession );
}
}
catch( sInt32 err )
{
siResult = err;
}
gNetInfoMutex->Signal();
return( siResult );
}
sInt32 CNiPlugIn::GetRecAttrValueByValue ( sGetRecordAttributeValueByValue *inData )
{
sInt32 siResult = eDSNoErr;
uInt32 uiDataLen = 0;
char *pNIRecType = nil;
char *pNI_AttrType = nil;
char *pAttrValue = nil;
char *pRecValuePath = nil;
tAttributeValueEntryPtr pOutAttrValue = nil;
sNIContextData *pContext = nil;
ni_namelist niNameList;
gNetInfoMutex->Wait();
try
{
pContext = (sNIContextData *)gNINodeRef->GetItemData( inData->fInRecRef );
if ( pContext == nil ) throw( (sInt32)eDSInvalidRecordRef );
if ( pContext->fRecType == nil ) throw( (sInt32)eDSEmptyRecordType );
if ( pContext->fRecName == nil ) throw( (sInt32)eDSEmptyRecordName );
if ( inData->fInAttrType == nil ) throw( (sInt32)eDSEmptyAttributeType );
if ( inData->fInAttrValue == nil ) throw( (sInt32)eDSEmptyAttributeValue );
pNIRecType = MapRecToNetInfoType( pContext->fRecType );
if ( pNIRecType == nil ) throw( (sInt32)eDSInvalidRecordType );
pNI_AttrType = MapAttrToNetInfoType( inData->fInAttrType->fBufferData );
if ( pNI_AttrType == nil ) throw( (sInt32)eDSInvalidAttributeType );
pAttrValue = NormalizeNIString( inData->fInAttrValue->fBufferData, pNI_AttrType );
if ( pAttrValue == nil ) throw( (sInt32)eDSNullAttributeValue );
void * aNIDomain = RetrieveNIDomain(pContext);
if (aNIDomain != NULL)
{
ni_id recordDirID;
pRecValuePath = (char*)calloc( 1 + strlen( pNIRecType ) + 1 + strlen(pContext->fRecName) + 1, 1 );
pRecValuePath[0] = '/';
strcat( pRecValuePath, pNIRecType );
strcat( pRecValuePath, "/" );
strcat( pRecValuePath, pContext->fRecName );
siResult = ::ni_pathsearch( aNIDomain, &recordDirID, pRecValuePath);
if (siResult == eDSNoErr)
{
siResult = ni_lookupprop( aNIDomain, &recordDirID, pNI_AttrType, &niNameList );
if ( siResult == eDSNoErr )
{
siResult = eDSAttributeValueNotFound;
sInt32 valIndex = 0;
valIndex = niNameList.ni_namelist_len - 1;
while (valIndex >= 0)
{
if (niNameList.ni_namelist_val[valIndex] != nil)
{
if (strcmp(niNameList.ni_namelist_val[valIndex], pAttrValue) == 0)
{
uiDataLen = strlen(pAttrValue);
pOutAttrValue = (tAttributeValueEntry *)::calloc( 1, sizeof( tAttributeValueEntry ) + uiDataLen + kBuffPad );
pOutAttrValue->fAttributeValueData.fBufferSize = uiDataLen;
pOutAttrValue->fAttributeValueData.fBufferLength = uiDataLen;
pOutAttrValue->fAttributeValueID = CalcCRC( pAttrValue );
::memcpy( pOutAttrValue->fAttributeValueData.fBufferData, pAttrValue, uiDataLen );
inData->fOutEntryPtr = pOutAttrValue;
siResult = eDSNoErr;
valIndex = 0; }
}
valIndex--;
}
ni_namelist_free(&niNameList);
}
else
{
siResult = eDSAttributeNotFound;
}
}
else
{
siResult = eDSAttributeNotFound;
}
}
else
{
throw( (sInt32)eDSInvalidSession );
}
}
catch( sInt32 err )
{
siResult = err;
}
gNetInfoMutex->Signal();
DSFreeString( pNI_AttrType );
DSFreeString( pRecValuePath );
if ( ( pAttrValue != nil) && ( pAttrValue != inData->fInAttrValue->fBufferData ) )
{
DSFreeString( pAttrValue );
}
return( siResult );
}
sInt32 CNiPlugIn::CreateRecord ( sCreateRecord *inData )
{
volatile sInt32 siResult = eDSNoErr;
tDataNodePtr pRecName = nil;
tDataNodePtr pRecType = nil;
char *pNIRecType = nil;
char *pNIRecName = nil;
sNIContextData *pContext = nil;
sNIContextData *pRecContext = nil;
ni_id niDirID;
char *pPath = nil;
char *pRecTypePath = nil;
ni_namelist niValues;
char *authUser = nil;
gNetInfoMutex->Wait();
try
{
pContext = (sNIContextData *)gNINodeRef->GetItemData( inData->fInNodeRef );
if ( pContext == nil ) throw( (sInt32)eDSInvalidNodeRef );
pRecType = inData->fInRecType;
if ( pRecType == nil ) throw( (sInt32)eDSNullRecType );
pRecName = inData->fInRecName;
if ( pRecName == nil ) throw( (sInt32)eDSNullRecName );
pNIRecType = MapRecToNetInfoType( pRecType->fBufferData );
if ( pNIRecType == nil ) throw( (sInt32)eDSInvalidRecordType );
pNIRecName = pRecName->fBufferData;
if ( pNIRecName == nil ) throw( (sInt32)eDSInvalidRecordName );
pPath = BuildRecordNamePath( pNIRecName, pNIRecType );
if ( pPath == nil ) throw( (sInt32)eDSInvalidRecordName );
void * aNIDomain = RetrieveNIDomain(pContext);
if (aNIDomain != NULL)
{
NI_INIT( &niDirID );
(void)::ni_root( aNIDomain, &niDirID );
if ( ( pContext->fEffectiveUID != 0 )
&& ( (pContext->fAuthenticatedUserName == NULL)
|| (strcmp(pContext->fAuthenticatedUserName,"root") != 0) ) )
{
authUser = pContext->fAuthenticatedUserName;
ni_proplist niPropList;
ni_id typeDirID;
pRecTypePath = (char*)calloc( strlen( pNIRecType ) + 2, 1 );
pRecTypePath[0] = '/';
strcpy( pRecTypePath + 1, pNIRecType );
siResult = ::ni_pathsearch( aNIDomain, &typeDirID, pRecTypePath);
while ((siResult != eDSNoErr) && (pRecTypePath[0] != '\0'))
{
char *lastSlashPtr = nil;
lastSlashPtr = strrchr(pRecTypePath, '/');
lastSlashPtr[0] = '\0';
siResult = ::ni_pathsearch( aNIDomain, &typeDirID, pRecTypePath);
}
if ( siResult == eDSNoErr )
{
siResult = ::ni_read( aNIDomain, &typeDirID, &niPropList );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
siResult = NiLib2::ValidateDir( authUser, &niPropList );
::ni_proplist_free( &niPropList );
}
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
}
siResult = DoCreateRecord( aNIDomain, &niDirID, pPath );
if ( siResult != eDSNoErr ) throw( siResult );
if ( (siResult == eDSNoErr) && (strcmp(pNIRecType,"users") == 0) )
{
NI_INIT( &niValues );
::ni_namelist_insert( &niValues, pRecName->fBufferData, NI_INDEX_NULL );
siResult = DoAddAttribute( aNIDomain, &niDirID, (const ni_name)"_writers_passwd", niValues );
#ifdef TIM_CLIENT_PRESENT
siResult = DoAddAttribute( aNIDomain, &niDirID, (const ni_name)"_writers_tim_password", niValues );
#endif
siResult = DoAddAttribute( aNIDomain, &niDirID, (const ni_name)"_writers_picture", niValues );
::ni_namelist_free( &niValues );
}
free(pPath);
pPath = nil;
if ( inData->fInOpen == true )
{
pRecContext = MakeContextData();
if ( pRecContext == nil ) throw( (sInt32)eMemoryAllocError );
if (pContext->fDomainName != nil)
{
pRecContext->fDomainName = strdup(pContext->fDomainName);
}
if ( pContext->fDomainPath != nil)
{
pRecContext->fDomainPath = strdup(pContext->fDomainPath);
}
pRecContext->bIsLocal = pContext->bIsLocal;
::memcpy( &pRecContext->dirID, &niDirID, sizeof( ni_id ) );
pRecContext->fUID = pContext->fUID;
pRecContext->fEffectiveUID = pContext->fEffectiveUID;
if (pContext->fAuthenticatedUserName != NULL)
{
pRecContext->fAuthenticatedUserName = strdup( pContext->fAuthenticatedUserName );
}
pRecContext->fRecType = (char *)::malloc( ::strlen( pRecType->fBufferData ) + 2 );
pRecContext->fRecType[0] = '\0';
::strcpy( pRecContext->fRecType, pRecType->fBufferData );
pRecContext->fRecName = (char *)::malloc( pRecName->fBufferLength + 2 );
pRecContext->fRecName[0] = '\0';
::strcpy( pRecContext->fRecName, pRecName->fBufferData );
gNINodeRef->AddItem( inData->fOutRecRef, pRecContext );
}
}
else
{
throw( (sInt32)eDSInvalidSession );
}
}
catch( sInt32 err )
{
siResult = err;
DSFreeString(pPath);
}
if (authUser != nil)
{
if (pContext != nil)
{
if (pContext->fAuthenticatedUserName == nil)
{
free(authUser);
authUser = nil;
}
}
}
DSFreeString( pRecTypePath );
DSDelete( pNIRecType );
gNetInfoMutex->Signal();
return( siResult );
}
sInt32 CNiPlugIn::DoCreateRecord ( void *inDomain, ni_id *inDir, char *inPathName )
{
sInt32 siResult = eDSNoErr;
ni_status niStatus = NI_OK;
sInt32 siCntr1 = 0;
sInt32 siCntr2 = 0;
sInt32 siLen = 0;
bool bSimple = false;
bool bMadeOne = false;
ni_id niTmpDir;
CString csDirName( 128 );
gNetInfoMutex->Wait();
try
{
siCntr1 = 0;
while ( (inPathName[ siCntr1 ] != '\0') && (niStatus == NI_OK) )
{
bSimple = true;
for ( siCntr2 = siCntr1; inPathName[ siCntr2 ] != '\0' && bSimple; siCntr2++ )
{
if ( inPathName[ siCntr2 ] == '\\' && inPathName[ siCntr2 + 1 ] == '/' )
{
if ( inPathName[ siCntr2 + 2 ] == '/' )
{
bSimple = false;
}
siCntr2++;
}
else if ( inPathName[ siCntr2 ] == '/' )
{
bSimple = false;
}
}
siLen = siCntr2 - siCntr1;
if ( !bSimple )
{
siLen--;
}
csDirName.Set( inPathName + siCntr1, siLen );
siCntr1 = siCntr2;
::memcpy( &niTmpDir, inDir, sizeof( ni_id ) );
niStatus = ::ni_pathsearch( inDomain, inDir, csDirName.GetData() );
if ( niStatus == NI_NODIR )
{
::memcpy( inDir, &niTmpDir, sizeof( ni_id ) );
niStatus = DoCreateChild( inDomain, inDir, csDirName.GetData() );
bMadeOne = true;
}
}
if ( niStatus == NI_OK )
{
if ( bMadeOne == false )
{
siResult = eDSRecordAlreadyExists;
}
}
else
{
siResult = MapNetInfoErrors( niStatus );
}
}
catch( sInt32 err )
{
siResult = err;
}
gNetInfoMutex->Signal();
return( siResult );
}
ni_status CNiPlugIn::DoCreateChild ( void *inDomain, ni_id *inDir, const ni_name inDirName )
{
ni_status niStatus = NI_OK;
sInt32 siCntr1 = 0;
sInt32 siCntr2 = 0;
sInt32 siLen = 0;
ni_proplist niPropList;
ni_id niChild;
char *pKey = nil;
char *pValue = nil;
gNetInfoMutex->Wait();
try
{
pKey = (char *)::malloc( 5 );
strcpy( pKey, "name" );
siLen = strlen( inDirName );
pValue = (char *)::malloc( siLen + 1 );
for ( siCntr1 = 0, siCntr2 = 0; siCntr1 < siLen; siCntr1++, siCntr2++ )
{
if ( inDirName[ siCntr1 ] == '\\'
&& ( (inDirName[ siCntr1 + 1 ] == '/') || (inDirName[ siCntr1 + 1 ] == '\\') ) )
{
siCntr1++;
}
pValue[ siCntr2 ] = inDirName[ siCntr1 ];
}
pValue[ siCntr2 ] = '\0';
NI_INIT( &niPropList );
NiLib3::AppendProp( &niPropList, pKey, pValue );
niStatus = ::ni_create( inDomain, inDir, niPropList, &niChild, NI_INDEX_NULL );
if ( niStatus == NI_OK )
{
::memcpy( inDir, &niChild, sizeof( ni_id ) );
}
::ni_proplist_free( &niPropList );
if ( pKey != nil )
{
free( pKey );
pKey = nil;
}
if ( pValue != nil )
{
free( pValue );
pValue = nil;
}
}
catch( sInt32 err )
{
niStatus = (ni_status)err;
}
gNetInfoMutex->Signal();
return( niStatus );
}
sInt32 CNiPlugIn::CloseAttributeList ( sCloseAttributeList *inData )
{
sInt32 siResult = eDSNoErr;
sNIContextData *pContext = nil;
pContext = (sNIContextData *)gNINodeRef->GetItemData( inData->fInAttributeListRef );
if ( pContext != nil )
{
gNINodeRef->RemoveItem( inData->fInAttributeListRef );
}
else
{
siResult = eDSInvalidAttrListRef;
}
return( siResult );
}
sInt32 CNiPlugIn::CloseAttributeValueList ( sCloseAttributeValueList *inData )
{
sInt32 siResult = eDSNoErr;
sNIContextData *pContext = nil;
pContext = (sNIContextData *)gNINodeRef->GetItemData( inData->fInAttributeValueListRef );
if ( pContext != nil )
{
gNINodeRef->RemoveItem( inData->fInAttributeValueListRef );
}
else
{
siResult = eDSInvalidAttrValueRef;
}
return( siResult );
}
sInt32 CNiPlugIn::OpenRecord ( sOpenRecord *inData )
{
sInt32 siResult = eDSNoErr;
tDataNodePtr pRecName = nil;
tDataNodePtr pRecType = nil;
char *pNIRecName = nil;
char *pNIRecType = nil;
sNIContextData *pContext = nil;
sNIContextData *pRecContext = nil;
ni_id niDirID;
bool bFoundRealname = false;
char *aRealname = nil;
gNetInfoMutex->Wait();
try
{
pContext = (sNIContextData *)gNINodeRef->GetItemData( inData->fInNodeRef );
if ( pContext == nil ) throw( (sInt32)eDSInvalidNodeRef );
pRecType = inData->fInRecType;
if ( pRecType == nil ) throw( (sInt32)eDSNullRecType );
pRecName = inData->fInRecName;
if ( pRecName == nil ) throw( (sInt32)eDSNullRecName );
pNIRecName = pRecName->fBufferData;
pNIRecType = MapRecToNetInfoType( pRecType->fBufferData );
if ( pNIRecType == nil ) throw( (sInt32)eDSInvalidRecordType );
if (pRecName->fBufferLength == 0) throw( (sInt32)eDSEmptyRecordNameList );
if (pRecType->fBufferLength == 0) throw( (sInt32)eDSEmptyRecordTypeList );
void * aNIDomain = RetrieveNIDomain(pContext);
if (aNIDomain != NULL)
{
NI_INIT( &niDirID );
siResult = IsValidRecordName( pNIRecName, pNIRecType, aNIDomain, niDirID );
if (siResult != eDSNoErr)
{
if (::strcmp(pNIRecType,"users") == 0)
{
siResult = IsValidRealname( pNIRecName, aNIDomain, &aRealname );
if (siResult == eDSNoErr)
{
bFoundRealname = true;
siResult = IsValidRecordName( aRealname, pNIRecType, aNIDomain, niDirID );
}
}
if ( siResult != eDSNoErr ) throw( siResult );
}
pRecContext = MakeContextData();
if ( pRecContext == nil ) throw( (sInt32)eMemoryAllocError );
if (pContext->fDomainName != nil)
{
pRecContext->fDomainName = strdup(pContext->fDomainName);
}
if ( pContext->fDomainPath != nil)
{
pRecContext->fDomainPath = strdup(pContext->fDomainPath);
}
pRecContext->bIsLocal = pContext->bIsLocal;
pRecContext->fUID = pContext->fUID;
pRecContext->fEffectiveUID = pContext->fEffectiveUID;
if (pContext->fAuthenticatedUserName != NULL)
{
pRecContext->fAuthenticatedUserName = strdup( pContext->fAuthenticatedUserName );
}
pRecContext->fRecType = strdup( pRecType->fBufferData );
if (bFoundRealname)
{
if (aRealname != nil)
{
pRecContext->fRecName = aRealname;
}
}
else
{
pRecContext->fRecName = strdup( pNIRecName );
}
::memcpy( &pRecContext->dirID, &niDirID, sizeof( ni_id ) );
gNINodeRef->AddItem( inData->fOutRecRef, pRecContext );
}
else
{
throw( (sInt32)eDSInvalidSession );
}
}
catch( sInt32 err )
{
if (siResult == eDSInvalidRecordName)
{
siResult = eDSRecordNotFound; }
else
{
siResult = err;
}
}
DSDelete( pNIRecType );
gNetInfoMutex->Signal();
return( siResult );
}
sInt32 CNiPlugIn::GetRecRefInfo ( sGetRecRefInfo *inData )
{
sInt32 siResult = eDSNoErr;
uInt32 uiRecSize = 0;
uInt32 uiRecTypeSize = 0;
uInt32 uiRecNameSize = 0;
tRecordEntry *pRecEntry = nil;
sNIContextData *pContext = nil;
gNetInfoMutex->Wait();
try
{
pContext = (sNIContextData *)gNINodeRef->GetItemData( inData->fInRecRef );
if ( pContext == nil ) throw( (sInt32)eDSInvalidRecordRef );
if ( pContext->fRecType != nil )
{
uiRecTypeSize = ::strlen( pContext->fRecType );
}
if ( pContext->fRecName != nil )
{
uiRecNameSize = ::strlen( pContext->fRecName );
}
uiRecSize = sizeof( tRecordEntry ) + uiRecTypeSize + uiRecNameSize + 8;
pRecEntry = (tRecordEntry *)::calloc( 1, uiRecSize );
fRecData->Clear();
fRecData->AppendShort( uiRecNameSize );
fRecData->AppendString( pContext->fRecName );
fRecData->AppendShort( uiRecTypeSize );
fRecData->AppendString( pContext->fRecType );
::memcpy( pRecEntry->fRecordNameAndType.fBufferData, fRecData->GetData(), fRecData->GetLength() );
pRecEntry->fRecordNameAndType.fBufferSize = uiRecTypeSize + uiRecNameSize + 8;
pRecEntry->fRecordNameAndType.fBufferLength = fRecData->GetLength();
inData->fOutRecInfo = pRecEntry;
}
catch( sInt32 err )
{
siResult = err;
}
gNetInfoMutex->Signal();
return( siResult );
}
sInt32 CNiPlugIn::CloseRecord ( sCloseRecord *inData )
{
sInt32 siResult = eDSNoErr;
sNIContextData *pContext = nil;
bool bResetCache = false;
gNetInfoMutex->Wait();
pContext = (sNIContextData *)gNINodeRef->GetItemData( inData->fInRecRef );
if ( pContext != nil )
{
if ( (pContext->bIsLocal) && (pContext->bDidWriteOperation) )
{
char* pNIRecType = MapRecToNetInfoType( pContext->fRecType );
if (pNIRecType != nil)
{
if ( (strcmp(pNIRecType,"users") == 0) || (strcmp(pNIRecType,"groups") == 0) )
{
bResetCache = true;
}
DSFreeString(pNIRecType);
}
}
gNINodeRef->RemoveItem( inData->fInRecRef );
}
else
{
siResult = eDSInvalidRecordRef;
}
gNetInfoMutex->Signal();
if ( bResetCache )
{
gSrvrCntl->HandleMemberDaemonFlushCache();
}
return( siResult );
}
sInt32 CNiPlugIn::SetRecordType ( sSetRecordType *inData )
{
sInt32 siResult = eDSNoErr;
tDataNode *pData = nil;
char *pNewType = nil;
char *pNIRecType = nil;
char *pRecTypePath = nil;
sNIContextData *pContext = nil;
char *pPath = nil;
char *authUser = nil;
gNetInfoMutex->Wait();
try
{
pData = inData->fInNewRecType;
if ( pData == nil ) throw( (sInt32)eDSNullRecType );
pNewType = pData->fBufferData;
pContext = (sNIContextData *)gNINodeRef->GetItemData( inData->fInRecRef );
if ( pContext == nil ) throw( (sInt32)eDSInvalidRecordRef );
pNIRecType = MapRecToNetInfoType( pNewType );
if ( pNIRecType == nil ) throw( (sInt32)eDSInvalidRecordType );
pPath = BuildRecordNamePath( pContext->fRecName, pNIRecType );
if ( pPath == nil ) throw( (sInt32)eDSInvalidRecordName );
void * aNIDomain = RetrieveNIDomain(pContext);
if (aNIDomain != NULL)
{
if ( ( pContext->fEffectiveUID != 0 )
&& ( (pContext->fAuthenticatedUserName == NULL)
|| (strcmp(pContext->fAuthenticatedUserName,"root") != 0) ) )
{
authUser = pContext->fAuthenticatedUserName;
ni_proplist niPropList;
ni_id niDirID;
ni_index tempIndex = NI_INDEX_NULL;
::memcpy( &niDirID, &pContext->dirID, sizeof( ni_id ) );
siResult = ::ni_parent( aNIDomain, &niDirID, &tempIndex );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
niDirID.nii_object = tempIndex;
siResult = ::ni_self( aNIDomain, &niDirID );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
siResult = ::ni_read( aNIDomain, &niDirID, &niPropList );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
siResult = NiLib2::ValidateDir( authUser, &niPropList );
::ni_proplist_free( &niPropList );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
pRecTypePath = (char*)calloc( strlen( pNIRecType ) + 2, 1 );
pRecTypePath[0] = '/';
strcpy( pRecTypePath + 1, pNIRecType );
siResult = ::ni_pathsearch( aNIDomain, &niDirID, pRecTypePath );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
siResult = ::ni_read( aNIDomain, &niDirID, &niPropList );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
siResult = NiLib2::ValidateDir( authUser, &niPropList );
::ni_proplist_free( &niPropList );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
}
siResult = NiLib2::Copy( aNIDomain, &pContext->dirID, pPath, aNIDomain, true );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
siResult = NiLib2::Destroy( aNIDomain, &pContext->dirID );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
siResult = ::ni_pathsearch( aNIDomain, &pContext->dirID, pPath );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
DSFreeString(pPath);
pContext->bDidWriteOperation = true;
}
else
{
throw( (sInt32)eDSInvalidSession );
}
}
catch( sInt32 err )
{
siResult = err;
DSFreeString(pPath);
}
if (authUser != nil)
{
if (pContext != nil)
{
if (pContext->fAuthenticatedUserName == nil)
{
free(authUser);
authUser = nil;
}
}
}
if ( pRecTypePath != nil )
{
free( pRecTypePath );
pRecTypePath = nil;
}
gNetInfoMutex->Signal();
return( siResult );
}
sInt32 CNiPlugIn::DeleteRecord ( sDeleteRecord *inData )
{
sInt32 siResult = eDSNoErr;
ni_status niStatus = NI_OK;
sNIContextData *pContext = nil;
char *authUser = nil;
ni_namelist niValuesGUID;
bool bResetCache = false;
gNetInfoMutex->Wait();
try
{
pContext = (sNIContextData *)gNINodeRef->GetItemData( inData->fInRecRef );
if ( pContext != nil )
{
void * aNIDomain = RetrieveNIDomain(pContext);
if (aNIDomain != NULL)
{
if ( ( pContext->fEffectiveUID != 0 )
&& ( (pContext->fAuthenticatedUserName == NULL)
|| (strcmp(pContext->fAuthenticatedUserName,"root") != 0) ) )
{
authUser = pContext->fAuthenticatedUserName;
ni_proplist niPropList;
ni_id parentDir;
ni_index tempIndex = NI_INDEX_NULL;
::memcpy( &parentDir, &pContext->dirID, sizeof( ni_id ) );
siResult = ::ni_parent( aNIDomain, &parentDir, &tempIndex );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
parentDir.nii_object = tempIndex;
siResult = ::ni_self( aNIDomain, &parentDir );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
siResult = ::ni_read( aNIDomain, &parentDir, &niPropList );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
siResult = NiLib2::ValidateDir( authUser, &niPropList );
::ni_proplist_free( &niPropList );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
}
{
ni_status niResultGUID = ni_lookupprop( aNIDomain, &pContext->dirID,
"generateduid", &niValuesGUID );
char* GUIDString = nil;
if (niResultGUID == NI_OK)
{
if (niValuesGUID.ni_namelist_len > 0)
{
if (niValuesGUID.ni_namelist_val[0] != nil)
{
GUIDString = strdup(niValuesGUID.ni_namelist_val[0]);
}
ni_namelist_free(&niValuesGUID);
}
}
RemoveShadowHash( pContext->fRecName, GUIDString, true );
if (GUIDString != nil)
{
free(GUIDString);
GUIDString = nil;
}
}
niStatus = NiLib2::Destroy( aNIDomain, &pContext->dirID );
if ( niStatus == NI_NODIR )
{
siResult = eDSRecordNotFound;
}
else if ( niStatus != NI_OK )
{
siResult = MapNetInfoErrors( niStatus );
}
else
{
if (pContext->bIsLocal)
{
char* pNIRecType = MapRecToNetInfoType( pContext->fRecType );
if (pNIRecType != nil)
{
if ( (strcmp(pNIRecType,"users") == 0) || (strcmp(pNIRecType,"groups") == 0) )
{
bResetCache = true;
}
DSFreeString(pNIRecType);
}
}
gNINodeRef->RemoveItem( inData->fInRecRef );
}
}
else
{
throw( (sInt32)eDSInvalidSession );
}
}
else
{
siResult = eDSInvalidRecordRef;
}
}
catch( sInt32 err )
{
siResult = err;
}
if (authUser != nil)
{
if (pContext != nil)
{
if (pContext->fAuthenticatedUserName == nil)
{
free(authUser);
authUser = nil;
}
}
}
gNetInfoMutex->Signal();
if ( bResetCache )
{
gSrvrCntl->HandleMemberDaemonFlushCache();
}
return( siResult );
}
sInt32 CNiPlugIn::SetRecordName ( sSetRecordName *inData )
{
sInt32 siResult = eDSNoErr;
bool bFreePropList = false;
uInt32 uiNameLen = 0;
char *pNewName = nil;
sNIContextData *pContext = nil;
ni_proplist niPropList;
ni_index niWhere;
ni_namelist niValues;
ni_namelist niCurrentName;
char *pOldName = nil;
uInt32 pv = 0;
ni_namelist niValue;
ni_property niProp;
ni_namelist niNameList;
bool bDidNotFindValue= true;
char *pNIRecType = nil;
char *authUser = nil;
gNetInfoMutex->Wait();
try
{
pContext = (sNIContextData *)gNINodeRef->GetItemData( inData->fInRecRef );
if ( pContext == nil ) throw( (sInt32)eDSInvalidRecordRef );
void * aNIDomain = RetrieveNIDomain(pContext);
if (aNIDomain != NULL)
{
::ni_needwrite( aNIDomain, 1 );
siResult = ::ni_read( aNIDomain, &pContext->dirID, &niPropList );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
bFreePropList = true;
niWhere = ::ni_proplist_match( niPropList, "name", nil );
if (niWhere == NI_INDEX_NULL) throw( (sInt32)ePlugInError );
if ( ( pContext->fEffectiveUID != 0 )
&& ( (pContext->fAuthenticatedUserName == NULL)
|| (strcmp(pContext->fAuthenticatedUserName,"root") != 0) ) )
{
authUser = pContext->fAuthenticatedUserName;
siResult = NiLib2::ValidateDir( authUser, &niPropList );
if ( siResult != NI_OK )
{
siResult = NiLib2::ValidateName( authUser, &niPropList, niWhere );
}
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
}
NI_INIT(&niCurrentName);
siResult = ::ni_readprop(aNIDomain, &pContext->dirID, niWhere, &niCurrentName);
pOldName = strdup( niCurrentName.ni_namelist_val[ 0 ] );
::ni_namelist_free( &niCurrentName );
pNewName = inData->fInNewRecName->fBufferData;
if ( pNewName == nil ) throw( (sInt32)eMemoryAllocError );
uiNameLen = ::strlen( pNewName );
if (uiNameLen == 0) throw( (sInt32)eDSNullRecName );
this->MakeGood( pNewName, pNewName );
siResult = ::ni_writename( aNIDomain, &pContext->dirID, niWhere, 0, pNewName );
siResult = MapNetInfoErrors( siResult );
if (pContext->fRecType != nil)
{
pNIRecType = MapRecToNetInfoType( pContext->fRecType );
}
if ( (siResult == eDSNoErr) && (pNIRecType != nil) && (::strcmp(pNIRecType,"users") == 0) )
{
niWhere = ::ni_proplist_match( niPropList, "_writers_passwd", nil );
if (niWhere != NI_INDEX_NULL)
{
niProp = niPropList.ni_proplist_val[ niWhere ];
niValue = niProp.nip_val;
for ( pv = 0; pv < niValue.ni_namelist_len; pv++ )
{
if ( strcmp( niValue.ni_namelist_val[ pv ], pOldName ) == 0 )
{
NI_INIT( &niNameList );
::ni_namelist_insert( &niNameList, niValue.ni_namelist_val[ pv ], NI_INDEX_NULL );
siResult = NiLib2::DestroyDirVal( aNIDomain, &pContext->dirID, (const ni_name)"_writers_passwd", niNameList );
siResult = NiLib2::InsertDirVal( aNIDomain, &pContext->dirID, (const ni_name)"_writers_passwd", pNewName, pv );
siResult = MapNetInfoErrors( siResult );
::ni_namelist_free( &niNameList );
bDidNotFindValue = false;
break;
}
}
if (bDidNotFindValue)
{
siResult = NiLib2::InsertDirVal( aNIDomain, &pContext->dirID, (const ni_name)"_writers_passwd", pNewName, niValue.ni_namelist_len );
siResult = MapNetInfoErrors( siResult );
}
}
else
{
NI_INIT( &niValues );
::ni_namelist_insert( &niValues, pNewName, NI_INDEX_NULL );
siResult = DoAddAttribute( aNIDomain, &pContext->dirID, (const ni_name)"_writers_passwd", niValues );
::ni_namelist_free( &niValues );
}
niWhere = ::ni_proplist_match( niPropList, "_writers_picture", nil );
if (niWhere != NI_INDEX_NULL)
{
niProp = niPropList.ni_proplist_val[ niWhere ];
niValue = niProp.nip_val;
for ( pv = 0; pv < niValue.ni_namelist_len; pv++ )
{
if ( strcmp( niValue.ni_namelist_val[ pv ], pOldName ) == 0 )
{
NI_INIT( &niNameList );
::ni_namelist_insert( &niNameList, niValue.ni_namelist_val[ pv ], NI_INDEX_NULL );
siResult = NiLib2::DestroyDirVal( aNIDomain, &pContext->dirID, (const ni_name)"_writers_picture", niNameList );
siResult = NiLib2::InsertDirVal( aNIDomain, &pContext->dirID, (const ni_name)"_writers_picture", pNewName, pv );
siResult = MapNetInfoErrors( siResult );
::ni_namelist_free( &niNameList );
bDidNotFindValue = false;
break;
}
}
if (bDidNotFindValue)
{
siResult = NiLib2::InsertDirVal( aNIDomain, &pContext->dirID, (const ni_name)"_writers_picture", pNewName, niValue.ni_namelist_len );
siResult = MapNetInfoErrors( siResult );
}
}
else
{
NI_INIT( &niValues );
::ni_namelist_insert( &niValues, pNewName, NI_INDEX_NULL );
siResult = DoAddAttribute( aNIDomain, &pContext->dirID, (const ni_name)"_writers_picture", niValues );
::ni_namelist_free( &niValues );
}
if (siResult == eDSNoErr)
{
pContext->bDidWriteOperation = true;
}
#ifdef TIM_CLIENT_PRESENT
bDidNotFindValue = true;
niWhere = ::ni_proplist_match( niPropList, "_writers_tim_password", nil );
if (niWhere != NI_INDEX_NULL)
{
niProp = niPropList.ni_proplist_val[ niWhere ];
niValue = niProp.nip_val;
for ( pv = 0; pv < niValue.ni_namelist_len; pv++ )
{
if ( strcmp( niValue.ni_namelist_val[ pv ], pOldName ) == 0 )
{
NI_INIT( &niNameList );
::ni_namelist_insert( &niNameList, niValue.ni_namelist_val[ pv ], NI_INDEX_NULL );
siResult = NiLib2::DestroyDirVal( aNIDomain, &pContext->dirID, (const ni_name)"_writers_tim_password", niNameList );
siResult = NiLib2::InsertDirVal( aNIDomain, &pContext->dirID, (const ni_name)"_writers_tim_password", pNewName, pv );
siResult = MapNetInfoErrors( siResult );
::ni_namelist_free( &niNameList );
bDidNotFindValue = false;
break;
}
}
if (bDidNotFindValue)
{
siResult = NiLib2::InsertDirVal( aNIDomain, &pContext->dirID, (const ni_name)"_writers_tim_password", pNewName, niValue.ni_namelist_len );
siResult = MapNetInfoErrors( siResult );
}
}
else
{
NI_INIT( &niValues );
::ni_namelist_insert( &niValues, pNewName, NI_INDEX_NULL );
siResult = DoAddAttribute( aNIDomain, &pContext->dirID, (const ni_name)"_writers_tim_password", niValues );
::ni_namelist_free( &niValues );
}
#endif
}
}
else
{
throw( (sInt32)eDSInvalidSession );
}
}
catch( sInt32 err )
{
siResult = err;
}
if (authUser != nil)
{
if (pContext != nil)
{
if (pContext->fAuthenticatedUserName == nil)
{
free(authUser);
authUser = nil;
}
}
}
if ( bFreePropList == true )
{
::ni_proplist_free( &niPropList );
}
gNetInfoMutex->Signal();
DSFreeString( pNIRecType );
DSFreeString( pOldName );
return( siResult );
}
sInt32 CNiPlugIn::RemoveAttribute ( sRemoveAttribute *inData )
{
sInt32 siResult = eDSNoErr;
char *pAttrType = nil;
sNIContextData *pContext = nil;
ni_namelist niAttribute;
char *authUser = nil;
gNetInfoMutex->Wait();
try
{
pContext = (sNIContextData *)gNINodeRef->GetItemData( inData->fInRecRef );
if ( pContext == nil ) throw( (sInt32)eDSInvalidRecordRef );
pAttrType = MapAttrToNetInfoType( inData->fInAttribute->fBufferData );
if ( pAttrType == nil ) throw( (sInt32)eDSInvalidAttributeType );
void * aNIDomain = RetrieveNIDomain(pContext);
if (aNIDomain != NULL)
{
if ( ( pContext->fEffectiveUID != 0 )
&& ( (pContext->fAuthenticatedUserName == NULL)
|| (strcmp(pContext->fAuthenticatedUserName,"root") != 0) ) )
{
authUser = pContext->fAuthenticatedUserName;
if ( ( authUser == NULL ) && (strcmp(pAttrType,"picture") == 0) )
{
authUser = GetUserNameForUID( pContext->fEffectiveUID, aNIDomain );
}
ni_proplist niPropList;
siResult = ::ni_read( aNIDomain, &pContext->dirID, &niPropList );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
siResult = NiLib2::ValidateDir( authUser, &niPropList );
::ni_proplist_free( &niPropList );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
}
if ( (pAttrType != nil) && (strcmp(pAttrType,"authentication_authority") == 0) )
{
ni_namelist niValues;
ni_namelist niValuesGUID;
NI_INIT( &niValues );
NI_INIT( &niValuesGUID );
siResult = ni_lookupprop( aNIDomain, &pContext->dirID, "authentication_authority", &niValues );
if ( (siResult == eDSNoErr) && (niValues.ni_namelist_len > 0) && (niValues.ni_namelist_val[0] != nil))
{
if ( strcasestr(niValues.ni_namelist_val[0], kDSValueAuthAuthorityShadowHash) != nil )
{
siResult = ni_lookupprop( aNIDomain, &pContext->dirID, "generateduid", &niValuesGUID );
if ( (siResult == eDSNoErr) && (niValuesGUID.ni_namelist_len > 0) && (niValuesGUID.ni_namelist_val[0] != nil))
{
RemoveShadowHash( pContext->fRecName, niValuesGUID.ni_namelist_val[0], true );
}
if (niValuesGUID.ni_namelist_len > 0)
{
ni_namelist_free(&niValuesGUID);
}
}
}
if (niValues.ni_namelist_len > 0)
{
ni_namelist_free(&niValues);
}
}
NI_INIT( &niAttribute );
::ni_namelist_insert( &niAttribute, pAttrType, NI_INDEX_NULL );
siResult = NiLib2::DestroyDirProp( aNIDomain, &pContext->dirID, niAttribute );
siResult = MapNetInfoErrors( siResult );
::ni_namelist_free( &niAttribute );
if (siResult == eDSNoErr)
{
pContext->bDidWriteOperation = true;
}
if ( pAttrType != nil )
{
delete( pAttrType );
pAttrType = nil;
}
}
else
{
throw( (sInt32)eDSInvalidSession );
}
}
catch( sInt32 err )
{
siResult = err;
}
if (authUser != nil)
{
if (pContext != nil)
{
if (pContext->fAuthenticatedUserName == nil)
{
free(authUser);
authUser = nil;
}
}
}
gNetInfoMutex->Signal();
return( siResult );
}
sInt32 CNiPlugIn::AddAttributeValue ( sAddAttributeValue *inData )
{
sInt32 siResult = eDSNoErr;
char *pAttrType = nil;
char *pAttrValue = nil;
sNIContextData *pContext = nil;
ni_namelist niNameList;
char *authUser = nil;
gNetInfoMutex->Wait();
try
{
pContext = (sNIContextData *)gNINodeRef->GetItemData( inData->fInRecRef );
if ( pContext == nil ) throw( (sInt32)eDSInvalidRecordRef );
pAttrType = MapAttrToNetInfoType( inData->fInAttrType->fBufferData );
pAttrValue = NormalizeNIString( inData->fInAttrValue->fBufferData, pAttrType );
if ( pAttrType == nil ) throw( (sInt32)eDSInvalidAttributeType );
void * aNIDomain = RetrieveNIDomain(pContext);
if (aNIDomain != NULL)
{
if ( ( pContext->fEffectiveUID != 0 )
&& ( (pContext->fAuthenticatedUserName == NULL)
|| (strcmp(pContext->fAuthenticatedUserName,"root") != 0) ) )
{
authUser = pContext->fAuthenticatedUserName;
if ( ( authUser == NULL ) && (strcmp(pAttrType,"picture") == 0) )
{
authUser = GetUserNameForUID( pContext->fEffectiveUID, aNIDomain );
}
ni_proplist niPropList;
ni_index niIndex;
siResult = ::ni_read( aNIDomain, &pContext->dirID, &niPropList );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
siResult = NiLib2::ValidateDir( authUser, &niPropList );
if ( siResult != NI_OK )
{
niIndex = ::ni_proplist_match( niPropList, pAttrType, NULL );
if ( niIndex != NI_INDEX_NULL )
siResult = NiLib2::ValidateName( authUser, &niPropList, niIndex );
}
::ni_proplist_free( &niPropList );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
}
NI_INIT( &niNameList );
::ni_namelist_insert( &niNameList, pAttrValue, NI_INDEX_NULL );
siResult = NiLib2::AppendDirProp( aNIDomain, &pContext->dirID, pAttrType, niNameList );
siResult = MapNetInfoErrors( siResult );
::ni_namelist_free( &niNameList );
if (siResult == eDSNoErr)
{
pContext->bDidWriteOperation = true;
}
DSDelete( pAttrType );
}
else
{
throw( (sInt32)eDSInvalidSession );
}
}
catch( sInt32 err )
{
siResult = err;
}
if (authUser != nil)
{
if (pContext != nil)
{
if (pContext->fAuthenticatedUserName == nil)
{
free(authUser);
authUser = nil;
}
}
}
if ( pAttrValue != inData->fInAttrValue->fBufferData )
{
DSFreeString( pAttrValue );
}
DSDelete( pAttrType );
gNetInfoMutex->Signal();
return( siResult );
}
sInt32 CNiPlugIn::RemoveAttributeValue ( sRemoveAttributeValue *inData )
{
bool done = false;
sInt32 siResult = eDSNoErr;
bool bFreePropList = false;
uInt32 pn = 0;
uInt32 pv = 0;
char *pAttrType = nil;
sNIContextData *pContext = nil;
ni_namelist niNameList;
ni_namelist niValue;
ni_property niProp;
ni_proplist niPropList;
char *authUser = nil;
gNetInfoMutex->Wait();
try
{
pContext = (sNIContextData *)gNINodeRef->GetItemData( inData->fInRecRef );
if ( pContext == nil ) throw( (sInt32)eDSInvalidRecordRef );
void * aNIDomain = RetrieveNIDomain(pContext);
if (aNIDomain != NULL)
{
pAttrType = MapAttrToNetInfoType( inData->fInAttrType->fBufferData );
siResult = ::ni_read( aNIDomain, &pContext->dirID, &niPropList );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
bFreePropList = true;
if ( ( pContext->fEffectiveUID != 0 )
&& ( (pContext->fAuthenticatedUserName == NULL)
|| (strcmp(pContext->fAuthenticatedUserName,"root") != 0) ) )
{
authUser = pContext->fAuthenticatedUserName;
if ( ( authUser == NULL ) && (strcmp(pAttrType,"picture") == 0) )
{
authUser = GetUserNameForUID( pContext->fEffectiveUID, aNIDomain );
}
ni_index niIndex;
siResult = NiLib2::ValidateDir( authUser, &niPropList );
if ( siResult != NI_OK )
{
niIndex = ::ni_proplist_match( niPropList, pAttrType, NULL );
siResult = NiLib2::ValidateName( authUser, &niPropList, niIndex );
}
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
}
siResult = eDSAttributeNotFound;
for ( pn = 0; (pn < niPropList.ni_proplist_len) && (done == false); pn++ )
{
niProp = niPropList.ni_proplist_val[ pn ];
if ( (pAttrType != nil) && (::strcmp( niProp.nip_name, pAttrType ) == 0) )
{
niValue = niProp.nip_val;
for ( pv = 0; (pv < niValue.ni_namelist_len) && (done == false); pv++ )
{
uInt32 crcVal = CalcCRC( niValue.ni_namelist_val[ pv ] );
if ( crcVal == inData->fInAttrValueID )
{
if ( (pAttrType != nil) && (strcmp(pAttrType,"authentication_authority") == 0) )
{
ni_namelist niValues;
ni_namelist niValuesGUID;
NI_INIT( &niValues );
NI_INIT( &niValuesGUID );
siResult = ni_lookupprop( aNIDomain, &pContext->dirID, "authentication_authority", &niValues );
if ( (siResult == eDSNoErr) && (niValues.ni_namelist_len > 0) && (niValues.ni_namelist_val[0] != nil))
{
if ( strcasestr(niValues.ni_namelist_val[0], kDSValueAuthAuthorityShadowHash) != nil )
{
siResult = ni_lookupprop( aNIDomain, &pContext->dirID, "generateduid", &niValuesGUID );
if ( (siResult == eDSNoErr) && (niValuesGUID.ni_namelist_len > 0) && (niValuesGUID.ni_namelist_val[0] != nil))
{
RemoveShadowHash( pContext->fRecName, niValuesGUID.ni_namelist_val[0], true );
}
if (niValuesGUID.ni_namelist_len > 0)
{
ni_namelist_free(&niValuesGUID);
}
}
}
if (niValues.ni_namelist_len > 0)
{
ni_namelist_free(&niValues);
}
}
NI_INIT( &niNameList );
::ni_namelist_insert( &niNameList, niValue.ni_namelist_val[ pv ], NI_INDEX_NULL );
siResult = NiLib2::DestroyDirVal( aNIDomain, &pContext->dirID, pAttrType, niNameList );
siResult = MapNetInfoErrors( siResult );
if ( siResult != eDSNoErr ) throw( siResult );
::ni_namelist_free( &niNameList );
pContext->bDidWriteOperation = true;
done = true;
break;
}
}
}
}
if ( pAttrType != nil )
{
delete( pAttrType );
pAttrType = nil;
}
}
else
{
throw( (sInt32)eDSInvalidSession );
}
}
catch( sInt32 err )
{
siResult = err;
}
if (authUser != nil)
{
if (pContext != nil)
{
if (pContext->fAuthenticatedUserName == nil)
{
free(authUser);
authUser = nil;
}
}
}
if (bFreePropList)
{
::ni_proplist_free( &niPropList );
}
gNetInfoMutex->Signal();
return( siResult );
}
sInt32 CNiPlugIn::SetAttributeValue ( sSetAttributeValue *inData )
{
bool done = false;
sInt32 siResult = eDSNoErr;
bool bFreePropList = false;
uInt32 pn = 0;
uInt32 pv = 0;
char *pAttrType = nil;
char *pAttrValue = nil;
sNIContextData *pContext = nil;
ni_namelist niNameList;
ni_namelist niValue;
ni_property niProp;
ni_proplist niPropList;
char *authUser = nil;
gNetInfoMutex->Wait();
try
{
pContext = (sNIContextData *)gNINodeRef->GetItemData( inData->fInRecRef );
if ( pContext == nil ) throw( (sInt32)eDSInvalidRecordRef );
void * aNIDomain = RetrieveNIDomain(pContext);
if (aNIDomain != NULL)
{
pAttrType = MapAttrToNetInfoType( inData->fInAttrType->fBufferData );
siResult = ::ni_read( aNIDomain, &pContext->dirID, &niPropList );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
bFreePropList = true;
if ( ( pContext->fEffectiveUID != 0 )
&& ( (pContext->fAuthenticatedUserName == NULL)
|| (strcmp(pContext->fAuthenticatedUserName,"root") != 0) ) )
{
authUser = pContext->fAuthenticatedUserName;
if ( ( authUser == NULL ) && (strcmp(pAttrType,"picture") == 0) )
{
authUser = GetUserNameForUID( pContext->fEffectiveUID, aNIDomain );
}
ni_index niIndex;
siResult = NiLib2::ValidateDir( authUser, &niPropList );
if ( siResult != NI_OK )
{
niIndex = ::ni_proplist_match( niPropList, pAttrType, NULL );
siResult = NiLib2::ValidateName( authUser, &niPropList, niIndex );
}
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
}
siResult = eDSAttributeNotFound;
pAttrValue = NormalizeNIString( inData->fInAttrValueEntry->fAttributeValueData.fBufferData, pAttrType );
for ( pn = 0; pn < (niPropList.ni_proplist_len) && (done == false); pn++ )
{
niProp = niPropList.ni_proplist_val[ pn ];
if ( (pAttrType != nil) && (::strcmp( niProp.nip_name, pAttrType ) == 0) )
{
niValue = niProp.nip_val;
for ( pv = 0; (pv < niValue.ni_namelist_len) && (done == false); pv++ )
{
uInt32 crcVal = CalcCRC( niValue.ni_namelist_val[ pv ] );
if ( crcVal == inData->fInAttrValueEntry->fAttributeValueID )
{
if ( (pAttrType != nil) && (strcmp(pAttrType,"authentication_authority") == 0) )
{
ni_namelist niValues;
ni_namelist niValuesGUID;
NI_INIT( &niValues );
NI_INIT( &niValuesGUID );
siResult = ni_lookupprop( aNIDomain, &pContext->dirID, "authentication_authority", &niValues );
if ( (siResult == eDSNoErr) && (niValues.ni_namelist_len > 0) && (niValues.ni_namelist_val[0] != nil))
{
if ( strcasestr(niValues.ni_namelist_val[0], kDSValueAuthAuthorityShadowHash) != nil )
{
if ( ( strcasestr(pAttrValue, kDSValueAuthAuthorityShadowHash) == nil ) &&
( strcasestr(pAttrValue, kDSTagAuthAuthorityDisabledUser) == nil ) )
{
siResult = ni_lookupprop( aNIDomain, &pContext->dirID, "generateduid", &niValuesGUID );
if ( (siResult == eDSNoErr) && (niValuesGUID.ni_namelist_len > 0) && (niValuesGUID.ni_namelist_val[0] != nil))
{
RemoveShadowHash( pContext->fRecName, niValuesGUID.ni_namelist_val[0], true );
}
if (niValuesGUID.ni_namelist_len > 0)
{
ni_namelist_free(&niValuesGUID);
}
}
}
}
if (niValues.ni_namelist_len > 0)
{
ni_namelist_free(&niValues);
}
}
NI_INIT( &niNameList );
::ni_namelist_insert( &niNameList, niValue.ni_namelist_val[ pv ], NI_INDEX_NULL );
siResult = NiLib2::DestroyDirVal( aNIDomain, &pContext->dirID, pAttrType, niNameList );
siResult = NiLib2::InsertDirVal( aNIDomain, &pContext->dirID, pAttrType, pAttrValue, pv );
siResult = MapNetInfoErrors( siResult );
if (siResult == eDSNoErr)
{
pContext->bDidWriteOperation = true;
}
::ni_namelist_free( &niNameList );
done = true;
break;
}
}
}
}
}
else
{
throw( (sInt32)eDSInvalidSession );
}
}
catch( sInt32 err )
{
siResult = err;
}
if (authUser != nil)
{
if (pContext != nil)
{
if (pContext->fAuthenticatedUserName == nil)
{
free(authUser);
authUser = nil;
}
}
}
DSDelete( pAttrType );
if ( pAttrValue != inData->fInAttrValueEntry->fAttributeValueData.fBufferData )
{
DSFreeString( pAttrValue );
}
if (bFreePropList)
{
::ni_proplist_free( &niPropList );
}
gNetInfoMutex->Signal();
return( siResult );
}
sInt32 CNiPlugIn::SetAttributeValues ( sSetAttributeValues *inData )
{
bool bWasShadowHash = false;
bool bIsShadowHash = false;
sInt32 siResult = eDSNoErr;
bool bFreePropList = false;
uInt32 pn = 0;
uInt32 pv = 0;
char *pAttrType = nil;
uInt32 valCount = 0;
char *attrValue = nil;
uInt32 attrLength = 0;
tDataNodePtr valuePtr = nil;
sNIContextData *pContext = nil;
ni_namelist niNameList;
ni_namelist niValue;
ni_property niProp;
ni_proplist niPropList;
char *authUser = nil;
gNetInfoMutex->Wait();
try
{
pContext = (sNIContextData *)gNINodeRef->GetItemData( inData->fInRecRef );
if ( pContext == nil ) throw( (sInt32)eDSInvalidRecordRef );
if ( inData->fInAttrType == nil ) throw( (sInt32)eDSNullAttributeType );
void * aNIDomain = RetrieveNIDomain(pContext);
if (aNIDomain != NULL)
{
pAttrType = MapAttrToNetInfoType( inData->fInAttrType->fBufferData );
siResult = ::ni_read( aNIDomain, &pContext->dirID, &niPropList );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
bFreePropList = true;
if ( ( pContext->fEffectiveUID != 0 )
&& ( (pContext->fAuthenticatedUserName == NULL)
|| (strcmp(pContext->fAuthenticatedUserName,"root") != 0) ) )
{
authUser = pContext->fAuthenticatedUserName;
if ( ( authUser == NULL ) && (strcmp(pAttrType,"picture") == 0) )
{
authUser = GetUserNameForUID( pContext->fEffectiveUID, aNIDomain );
}
ni_index niIndex;
siResult = NiLib2::ValidateDir( authUser, &niPropList );
if ( siResult != NI_OK )
{
niIndex = ::ni_proplist_match( niPropList, pAttrType, NULL );
siResult = NiLib2::ValidateName( authUser, &niPropList, niIndex );
}
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
}
valCount = inData->fInAttrValueList->fDataNodeCount;
niNameList.ni_namelist_len = valCount;
niNameList.ni_namelist_val = (ni_name*) calloc(valCount + 1, sizeof(ni_name*) );
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);
niNameList.ni_namelist_val[i] = attrValue;
attrValue = nil;
}
if (valuePtr != NULL)
{
dsDataBufferDeallocatePriv(valuePtr);
valuePtr = NULL;
}
} NormalizeNINameList(&niNameList, pAttrType);
if ( strcmp(pAttrType,"authentication_authority") == 0 )
{
pn = ni_proplist_match(niPropList, pAttrType, NULL);
if (pn != NI_INDEX_NULL) {
niProp = niPropList.ni_proplist_val[ pn ];
niValue = niProp.nip_val;
for ( pv = 0; pv < niValue.ni_namelist_len && niValue.ni_namelist_val[pv]; pv++ )
{
if (strcasestr(niValue.ni_namelist_val[pv], kDSValueAuthAuthorityShadowHash) != nil)
{
bWasShadowHash = true;
break;
}
}
}
if (bWasShadowHash)
{
niValue = niNameList;
for ( pv = 0; pv < niValue.ni_namelist_len; pv++ )
{
if ( strcasestr(niValue.ni_namelist_val[pv], kDSValueAuthAuthorityShadowHash) != nil )
{
bIsShadowHash = true;
break;
}
}
}
}
if (bWasShadowHash && !bIsShadowHash)
{
ni_namelist niValuesGUID;
NI_INIT( &niValuesGUID );
siResult = ni_lookupprop( aNIDomain, &pContext->dirID, "generateduid", &niValuesGUID );
if ( (siResult == eDSNoErr) && (niValuesGUID.ni_namelist_len > 0) && (niValuesGUID.ni_namelist_val[0] != nil))
{
RemoveShadowHash( pContext->fRecName, niValuesGUID.ni_namelist_val[0], true );
}
if (niValuesGUID.ni_namelist_len > 0)
{
ni_namelist_free(&niValuesGUID);
}
}
siResult = NiLib2::CreateDirProp( aNIDomain, &pContext->dirID, pAttrType, niNameList );
siResult = MapNetInfoErrors( siResult );
if (siResult == eDSNoErr)
{
pContext->bDidWriteOperation = true;
}
::ni_namelist_free( &niNameList );
}
else
{
throw( (sInt32)eDSInvalidSession );
}
}
catch( sInt32 err )
{
siResult = err;
}
if (authUser != nil)
{
if (pContext != nil)
{
if (pContext->fAuthenticatedUserName == nil)
{
free(authUser);
authUser = nil;
}
}
}
DSDelete( pAttrType );
if (bFreePropList)
{
::ni_proplist_free( &niPropList );
}
gNetInfoMutex->Signal();
return( siResult );
}
sInt32 CNiPlugIn::DoPlugInCustomCall ( sDoPlugInCustomCall *inData )
{
sInt32 siResult = eDSNoErr;
sNIContextData *pContext = nil;
gNetInfoMutex->Wait();
try
{
if ( inData == nil ) throw( (sInt32)eMemoryError );
pContext = (sNIContextData *)gNINodeRef->GetItemData( inData->fInNodeRef );
if ( pContext == nil ) throw( (sInt32)eDSInvalidNodeRef );
switch ( inData->fInRequestCode )
{
default:
siResult = eNotHandledByThisNode;
break;
}
}
catch( sInt32 err )
{
siResult = err;
}
gNetInfoMutex->Signal();
return( siResult );
}
sInt32 CNiPlugIn::DoAttributeValueSearch ( sDoAttrValueSearchWithData *inData )
{
sInt32 siResult = eDSNoErr;
bool bAttrInfoOnly = false;
uInt32 uiCount = 0;
uInt32 uiTotal = 0;
CRecTypeList *cpRecTypeList = nil;
CAttributeList *cpAttrTypeList = nil;
CAttributeList *cpPattMatchList = nil;
char *pDS_AttrType = nil;
char *pNI_RecType = nil;
char *pDS_RecType = nil;
sNIContextData *pContext = nil;
sNIContinueData *pContinue = nil;
tDirPatternMatch pattMatch = eDSExact;
tDataList *pTmpDataList = nil;
CBuff *outBuff = nil;
bool bBuffFull = false;
bool separateRecTypes = false;
uInt32 countDownRecTypes = 0;
ni_id niDirID;
ni_entrylist niEntryList;
gNetInfoMutex->Wait();
try
{
if ( inData == nil ) throw( (sInt32)eMemoryError );
pContext = (sNIContextData *)gNINodeRef->GetItemData( inData->fInNodeRef );
if ( pContext == nil ) throw( (sInt32)eDSInvalidNodeRef );
if ( inData->fIOContinueData == nil )
{
pContinue = (sNIContinueData *)::calloc( 1, sizeof( sNIContinueData ) );
gNIContinue->AddItem( pContinue, inData->fInNodeRef );
pContinue->fRecNameIndex = 1;
pContinue->fRecTypeIndex = 1;
pContinue->fAttrIndex = 1;
pContinue->fAllRecIndex = 0;
pContinue->fTotalRecCount = 0;
pContinue->fLimitRecSearch = 0;
if (inData->fOutMatchRecordCount >= 0)
{
pContinue->fLimitRecSearch = inData->fOutMatchRecordCount;
}
}
else
{
pContinue = (sNIContinueData *)inData->fIOContinueData;
if ( gNIContinue->VerifyItem( pContinue ) == false )
{
throw( (sInt32)eDSInvalidContinueData );
}
}
inData->fIOContinueData = nil;
inData->fOutMatchRecordCount = 0;
outBuff = new CBuff;
if ( outBuff == nil ) throw( (sInt32)eMemoryAllocError );
siResult = outBuff->Initialize( inData->fOutDataBuff, true );
if ( siResult != eDSNoErr ) throw( siResult );
siResult = outBuff->SetBuffType( 'StdA' );
if ( siResult != eDSNoErr ) throw( siResult );
cpRecTypeList = new CRecTypeList( inData->fInRecTypeList );
if ( cpRecTypeList == nil ) throw( (sInt32)eDSEmptyRecordTypeList );
if (cpRecTypeList->GetCount() == 0) throw( (sInt32)eDSEmptyRecordTypeList );
char *aStringValue = nil;
if (eDSNoErr == cpRecTypeList->GetAttribute(1, &aStringValue))
{
if (strcmp(aStringValue, kDSStdRecordTypeAll) == 0)
{
delete( cpRecTypeList );
cpRecTypeList = nil;
tDataListPtr newNodeList = dsBuildListFromStrings( 0, kDSStdRecordTypeUsers, kDSStdRecordTypeGroups, kDSStdRecordTypeComputers, nil );
void * aNIDomain = RetrieveNIDomain(pContext);
if (aNIDomain != NULL)
{
NI_INIT( &niDirID );
NI_INIT( &niEntryList );
siResult = ::ni_pathsearch( aNIDomain, &niDirID, "/" );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
siResult = ::ni_list( aNIDomain, &niDirID, "name", &niEntryList );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
if (niEntryList.ni_entrylist_val == NULL)
{
niEntryList.ni_entrylist_len = 0;
}
for ( uInt32 i = 0; i < niEntryList.ni_entrylist_len; i++ )
{
char* dsType = MapNetInfoRecToDSType(niEntryList.ni_entrylist_val[i].names->ni_namelist_val[0]);
if (dsType != NULL)
{
if ( (strncmp(dsType,kDSStdRecordTypePrefix,strlen(kDSStdRecordTypePrefix)) == 0) &&
(strcmp(dsType,kDSStdRecordTypeUsers) != 0) &&
(strcmp(dsType,kDSStdRecordTypeGroups) != 0) &&
(strcmp(dsType,kDSStdRecordTypeComputers) != 0) )
{
dsAppendStringToListAlloc(0, newNodeList, dsType);
}
delete( dsType );
dsType = nil;
}
}
if ( niEntryList.ni_entrylist_len > 0 )
{
ni_entrylist_free(&niEntryList);
}
cpRecTypeList = new CRecTypeList( newNodeList );
if ( cpRecTypeList == nil ) throw( (sInt32)eDSEmptyRecordTypeList );
if (cpRecTypeList->GetCount() == 0) throw( (sInt32)eDSEmptyRecordTypeList );
}
else
{
throw( (sInt32)eDSInvalidSession );
}
} }
countDownRecTypes = cpRecTypeList->GetCount() - pContinue->fRecTypeIndex + 1;
pDS_AttrType = inData->fInAttrType->fBufferData;
if ( pDS_AttrType == nil ) throw( (sInt32)eDSEmptyAttributeType );
cpPattMatchList = new CAttributeList( (char *)(inData->fInPatt2Match->fBufferData) );
if ( cpPattMatchList == nil ) throw( (sInt32)eDSEmptyDataList );
if (cpPattMatchList->GetCount() == 0) throw( (sInt32)eDSEmptyDataList );
if ( inData->fType == kDoAttributeValueSearchWithData )
{
cpAttrTypeList = new CAttributeList( inData->fInAttrTypeRequestList );
if ( cpAttrTypeList == nil ) throw( (sInt32)eDSEmptyAttributeTypeList );
if (cpAttrTypeList->GetCount() == 0) throw( (sInt32)eDSEmptyAttributeTypeList );
bAttrInfoOnly = 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 );
}
}
pattMatch = inData->fInPattMatchType;
siResult = VerifyPatternMatch( pattMatch );
if ( siResult != eDSNoErr ) throw( (sInt32)eDSInvalidPatternMatchType );
while ( (cpRecTypeList->GetAttribute( pContinue->fRecTypeIndex, &pDS_RecType ) == eDSNoErr) &&
(!bBuffFull) && (!separateRecTypes) )
{
pNI_RecType = MapRecToNetInfoType( pDS_RecType );
if ( pNI_RecType != nil )
{
if ( ::strcmp( pDS_AttrType, kDSAttributesAll ) == 0 )
{
siResult = FindAllRecords ( pNI_RecType,
pDS_RecType,
cpPattMatchList,
pattMatch,
cpAttrTypeList,
bAttrInfoOnly,
pContinue,
pContext,
outBuff,
uiCount );
}
else
{
siResult = FindTheseRecords ( pNI_RecType,
pDS_RecType,
pDS_AttrType,
cpPattMatchList,
pattMatch,
cpAttrTypeList,
bAttrInfoOnly,
pContinue,
pContext,
outBuff,
uiCount );
}
if ( siResult == CBuff::kBuffFull )
{
bBuffFull = true;
inData->fIOContinueData = pContinue;
if ( ( uiCount == 0 ) && ( uiTotal == 0 ) )
{
siResult = eDSBufferTooSmall;
break;
}
uiTotal += uiCount;
inData->fOutMatchRecordCount = uiTotal;
outBuff->SetLengthToSize();
siResult = eDSNoErr;
}
else if ( siResult == eDSNoErr )
{
uiTotal += uiCount;
pContinue->fRecNameIndex++;
}
delete( pNI_RecType );
pNI_RecType = nil;
}
if ( !bBuffFull )
{
pDS_RecType = nil;
pContinue->fRecTypeIndex++;
pContinue->fRecNameIndex = 1;
separateRecTypes = true;
inData->fIOContinueData = pContinue;
if ( pContinue->fNIEntryList.ni_entrylist_len > 0 )
{
::ni_entrylist_free(&(pContinue->fNIEntryList));
pContinue->fNIEntryList.ni_entrylist_len = 0;
}
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 ( (inData->fIOContinueData == nil) && (pContinue != nil) )
{
gNIContinue->RemoveItem( pContinue );
pContinue = nil;
}
gNetInfoMutex->Signal();
if ( cpAttrTypeList != nil )
{
delete( cpAttrTypeList );
cpAttrTypeList = nil;
}
if ( cpPattMatchList != nil )
{
delete( cpPattMatchList );
cpPattMatchList = nil;
}
if ( cpRecTypeList != nil )
{
delete( cpRecTypeList );
cpRecTypeList = nil;
}
if ( outBuff != nil )
{
delete( outBuff );
outBuff = nil;
}
if ( pNI_RecType != nil )
{
delete( pNI_RecType );
pNI_RecType = nil;
}
if ( pTmpDataList != nil )
{
(void)::dsDataListDeallocatePriv( pTmpDataList );
free( pTmpDataList );
pTmpDataList = nil;
}
return( siResult );
}
sInt32 CNiPlugIn::DoMultipleAttributeValueSearch ( sDoMultiAttrValueSearchWithData *inData )
{
sInt32 siResult = eDSNoErr;
bool bAttrInfoOnly = false;
uInt32 uiCount = 0;
uInt32 uiTotal = 0;
CRecTypeList *cpRecTypeList = nil;
CAttributeList *cpAttrTypeList = nil;
CAttributeList *cpPattMatchList = nil;
char *pDS_AttrType = nil;
char *pNI_RecType = nil;
char *pDS_RecType = nil;
sNIContextData *pContext = nil;
sNIContinueData *pContinue = nil;
tDirPatternMatch pattMatch = eDSExact;
tDataList *pTmpDataList = nil;
CBuff *outBuff = nil;
bool bBuffFull = false;
bool separateRecTypes = false;
uInt32 countDownRecTypes = 0;
ni_id niDirID;
ni_entrylist niEntryList;
gNetInfoMutex->Wait();
try
{
if ( inData == nil ) throw( (sInt32)eMemoryError );
pContext = (sNIContextData *)gNINodeRef->GetItemData( inData->fInNodeRef );
if ( pContext == nil ) throw( (sInt32)eDSInvalidNodeRef );
if ( inData->fIOContinueData == nil )
{
pContinue = (sNIContinueData *)::calloc( 1, sizeof( sNIContinueData ) );
gNIContinue->AddItem( pContinue, inData->fInNodeRef );
pContinue->fRecNameIndex = 1;
pContinue->fRecTypeIndex = 1;
pContinue->fAttrIndex = 1;
pContinue->fAllRecIndex = 0;
pContinue->fTotalRecCount = 0;
pContinue->fLimitRecSearch = 0;
if (inData->fOutMatchRecordCount >= 0)
{
pContinue->fLimitRecSearch = inData->fOutMatchRecordCount;
}
}
else
{
pContinue = (sNIContinueData *)inData->fIOContinueData;
if ( gNIContinue->VerifyItem( pContinue ) == false )
{
throw( (sInt32)eDSInvalidContinueData );
}
}
inData->fIOContinueData = nil;
inData->fOutMatchRecordCount = 0;
outBuff = new CBuff;
if ( outBuff == nil ) throw( (sInt32)eMemoryAllocError );
siResult = outBuff->Initialize( inData->fOutDataBuff, true );
if ( siResult != eDSNoErr ) throw( siResult );
siResult = outBuff->SetBuffType( 'StdA' );
if ( siResult != eDSNoErr ) throw( siResult );
cpRecTypeList = new CRecTypeList( inData->fInRecTypeList );
if ( cpRecTypeList == nil ) throw( (sInt32)eDSEmptyRecordTypeList );
if (cpRecTypeList->GetCount() == 0) throw( (sInt32)eDSEmptyRecordTypeList );
char *aStringValue = nil;
if (eDSNoErr == cpRecTypeList->GetAttribute(1, &aStringValue))
{
if (strcmp(aStringValue, kDSStdRecordTypeAll) == 0)
{
delete( cpRecTypeList );
cpRecTypeList = nil;
tDataListPtr newNodeList = dsBuildListFromStrings( 0, kDSStdRecordTypeUsers, kDSStdRecordTypeGroups, kDSStdRecordTypeComputers, nil );
void * aNIDomain = RetrieveNIDomain(pContext);
if (aNIDomain != NULL)
{
NI_INIT( &niDirID );
NI_INIT( &niEntryList );
siResult = ::ni_pathsearch( aNIDomain, &niDirID, "/" );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
siResult = ::ni_list( aNIDomain, &niDirID, "name", &niEntryList );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
for ( uInt32 i = 0; i < niEntryList.ni_entrylist_len; i++ )
{
char* dsType = MapNetInfoRecToDSType(niEntryList.ni_entrylist_val[i].names->ni_namelist_val[0]);
if (dsType != NULL)
{
if ( (strncmp(dsType,kDSStdRecordTypePrefix,strlen(kDSStdRecordTypePrefix)) == 0) &&
(strcmp(dsType,kDSStdRecordTypeUsers) != 0) &&
(strcmp(dsType,kDSStdRecordTypeGroups) != 0) &&
(strcmp(dsType,kDSStdRecordTypeComputers) != 0) )
{
dsAppendStringToListAlloc(0, newNodeList, dsType);
}
delete( dsType );
dsType = nil;
}
}
if ( niEntryList.ni_entrylist_len > 0 )
{
ni_entrylist_free(&niEntryList);
}
cpRecTypeList = new CRecTypeList( newNodeList );
if ( cpRecTypeList == nil ) throw( (sInt32)eDSEmptyRecordTypeList );
if (cpRecTypeList->GetCount() == 0) throw( (sInt32)eDSEmptyRecordTypeList );
}
else
{
throw( (sInt32)eDSInvalidSession );
}
} }
countDownRecTypes = cpRecTypeList->GetCount() - pContinue->fRecTypeIndex + 1;
pDS_AttrType = inData->fInAttrType->fBufferData;
if ( pDS_AttrType == nil ) throw( (sInt32)eDSEmptyAttributeType );
cpPattMatchList = new CAttributeList( inData->fInPatterns2MatchList );
if ( cpPattMatchList == nil ) throw( (sInt32)eDSEmptyDataList );
if (cpPattMatchList->GetCount() == 0) throw( (sInt32)eDSEmptyDataList );
if ( inData->fType == kDoMultipleAttributeValueSearchWithData )
{
cpAttrTypeList = new CAttributeList( inData->fInAttrTypeRequestList );
if ( cpAttrTypeList == nil ) throw( (sInt32)eDSEmptyAttributeTypeList );
if (cpAttrTypeList->GetCount() == 0) throw( (sInt32)eDSEmptyAttributeTypeList );
bAttrInfoOnly = 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 );
}
}
pattMatch = inData->fInPattMatchType;
siResult = VerifyPatternMatch( pattMatch );
if ( siResult != eDSNoErr ) throw( (sInt32)eDSInvalidPatternMatchType );
while ( (cpRecTypeList->GetAttribute( pContinue->fRecTypeIndex, &pDS_RecType ) == eDSNoErr) &&
(!bBuffFull) && (!separateRecTypes) )
{
pNI_RecType = MapRecToNetInfoType( pDS_RecType );
if ( pNI_RecType != nil )
{
if ( ::strcmp( pDS_AttrType, kDSAttributesAll ) == 0 )
{
siResult = FindAllRecords ( pNI_RecType,
pDS_RecType,
cpPattMatchList,
pattMatch,
cpAttrTypeList,
bAttrInfoOnly,
pContinue,
pContext,
outBuff,
uiCount );
}
else
{
siResult = FindTheseRecords ( pNI_RecType,
pDS_RecType,
pDS_AttrType,
cpPattMatchList,
pattMatch,
cpAttrTypeList,
bAttrInfoOnly,
pContinue,
pContext,
outBuff,
uiCount );
}
if ( siResult == CBuff::kBuffFull )
{
bBuffFull = true;
inData->fIOContinueData = pContinue;
if ( ( uiCount == 0 ) && ( uiTotal == 0 ) )
{
siResult = eDSBufferTooSmall;
break;
}
uiTotal += uiCount;
inData->fOutMatchRecordCount = uiTotal;
outBuff->SetLengthToSize();
siResult = eDSNoErr;
}
else if ( siResult == eDSNoErr )
{
uiTotal += uiCount;
pContinue->fRecNameIndex++;
}
delete( pNI_RecType );
pNI_RecType = nil;
}
if ( !bBuffFull )
{
pDS_RecType = nil;
pContinue->fRecTypeIndex++;
pContinue->fRecNameIndex = 1;
separateRecTypes = true;
inData->fIOContinueData = pContinue;
if ( pContinue->fNIEntryList.ni_entrylist_len > 0 )
{
::ni_entrylist_free(&(pContinue->fNIEntryList));
pContinue->fNIEntryList.ni_entrylist_len = 0;
}
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 ( (inData->fIOContinueData == nil) && (pContinue != nil) )
{
gNIContinue->RemoveItem( pContinue );
pContinue = nil;
}
gNetInfoMutex->Signal();
if ( cpAttrTypeList != nil )
{
delete( cpAttrTypeList );
cpAttrTypeList = nil;
}
if ( cpRecTypeList != nil )
{
delete( cpRecTypeList );
cpRecTypeList = nil;
}
if ( cpPattMatchList != nil )
{
delete(cpPattMatchList);
cpPattMatchList = nil;
}
if ( outBuff != nil )
{
delete( outBuff );
outBuff = nil;
}
if ( pNI_RecType != nil )
{
delete( pNI_RecType );
pNI_RecType = nil;
}
if ( pTmpDataList != nil )
{
(void)::dsDataListDeallocatePriv( pTmpDataList );
free( pTmpDataList );
pTmpDataList = nil;
}
return( siResult );
}
sInt32 CNiPlugIn:: FindAllRecords ( const char *inNI_RecType,
const char *inDS_RecType,
CAttributeList *inPattMatchList,
tDirPatternMatch inHow,
CAttributeList *inAttrTypeList,
bool inAttrOnly,
sNIContinueData *inContinue,
sNIContextData *inContext,
CBuff *inBuff,
uInt32 &outRecCount )
{
uInt32 pn = 0;
uInt32 pv = 0;
sInt32 siResult = eDSNoErr;
sInt32 siCount = 0;
uInt32 uiSearchFlag = REG_BASIC;
bool bMatches = false;
u_int en2 = 0;
ni_index niIndex = 0;
ni_id niDirID;
ni_entry niEntry;
ni_proplist niPropList;
ni_entrylist niEntryList;
ni_namelist niNameList;
CString csNI_RecName( 128 );
CString csNI_AttrType( 128 );
ni_property niProp;
void *aNIDomain = NULL;
gNetInfoMutex->Wait();
outRecCount = 0;
try
{
NI_INIT( &niDirID );
NI_INIT( &niEntry );
NI_INIT( &niPropList );
NI_INIT( &niNameList );
NI_INIT( &niEntryList );
if ( (inHow >= eDSiExact) && (inHow <= eDSiRegularExpression) )
{
uiSearchFlag = REG_ICASE;
}
aNIDomain = RetrieveNIDomain(inContext);
if (aNIDomain != NULL)
{
siResult = ::ni_pathsearch( aNIDomain, &niDirID, inNI_RecType );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
if ( inContinue->fNIEntryList.ni_entrylist_len == 0 )
{
siResult = ::ni_list( aNIDomain, &niDirID, "name", &(inContinue->fNIEntryList) );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
}
niEntryList = inContinue->fNIEntryList;
for ( en2 = inContinue->fAllRecIndex; (en2 < niEntryList.ni_entrylist_len) &&
(((inContinue->fTotalRecCount) < inContinue->fLimitRecSearch) ||
(inContinue->fLimitRecSearch == 0)); en2++ )
{
niEntry = niEntryList.ni_entrylist_val[ en2 ];
niDirID.nii_object = niEntry.id;
if ( niEntry.names != NULL )
{
siResult = ::ni_read( aNIDomain, &niDirID, &niPropList );
if ( siResult == NI_OK )
{
bMatches = false;
for ( pn = 0; ((pn < niPropList.ni_proplist_len) && (bMatches == false)); pn++ )
{
niProp = niPropList.ni_proplist_val[ pn ];
niNameList = niProp.nip_val;
for ( pv = 0; ((pv < niNameList.ni_namelist_len) && (bMatches == false)); pv++ )
{
bMatches = DoAnyMatch( niNameList.ni_namelist_val[ pv ], inPattMatchList, inHow );
}
}
if ( bMatches == true )
{
fAttrData->Clear();
fRecData->Clear();
fRecData->AppendShort( ::strlen( inDS_RecType ) );
fRecData->AppendString( inDS_RecType );
niIndex = ::ni_proplist_match( niPropList, "name", NULL );
if ( niIndex == NI_INDEX_NULL || niPropList.nipl_val[ niIndex ].nip_val.ninl_len == 0 )
{
fRecData->AppendShort( ::strlen( "*** No Name ***" ) );
fRecData->AppendString( "*** No Name ***" );
}
else
{
fRecData->AppendShort( ::strlen( niPropList.nipl_val[ niIndex ].nip_val.ninl_val[ 0 ] ) );
fRecData->AppendString( niPropList.nipl_val[ niIndex ].nip_val.ninl_val[ 0 ] );
}
siResult = GetTheseAttributes( inAttrTypeList, &niPropList, inAttrOnly, aNIDomain, inContext->fDomainName, inDS_RecType, siCount );
if ( siResult == eDSNoErr )
{
if ( siCount == 0 )
{
fRecData->AppendShort( 0 );
}
else
{
fRecData->AppendShort( siCount );
fRecData->AppendBlock( fAttrData->GetData(), fAttrData->GetLength() );
}
siResult = inBuff->AddData( fRecData->GetData(), fRecData->GetLength() );
if ( siResult == CBuff::kBuffFull )
{
inContinue->fAllRecIndex = en2;
::ni_proplist_free( &niPropList );
break;
}
else if ( siResult == eDSNoErr )
{
outRecCount++;
inContinue->fTotalRecCount++;
}
else
{
inContinue->fAllRecIndex = 0;
::ni_proplist_free( &niPropList );
siResult = eDSInvalidBuffFormat;
break;
}
}
} ::ni_proplist_free( &niPropList );
} } } if ( siResult == eDSNoErr )
{
inContinue->fAllRecIndex = 0;
}
}
else
{
throw( (sInt32)eDSInvalidSession );
}
}
catch( sInt32 err )
{
siResult = err;
}
gNetInfoMutex->Signal();
return( siResult );
}
sInt32 CNiPlugIn::FindTheseRecords ( const char *inNI_RecType,
const char *inDS_RecType,
const char *inDS_AttrType,
CAttributeList *inPattMatchList,
tDirPatternMatch inHow,
CAttributeList *inAttrTypeList,
bool inAttrOnly,
sNIContinueData *inContinue,
sNIContextData *inContext,
CBuff *inBuff,
uInt32 &outRecCount )
{
bool done = false;
bool bMatches = false;
uInt32 i = 0;
sInt32 siCount = 0;
sInt32 siResult = eDSNoErr;
uInt32 uiSearchFlag = REG_BASIC;
ni_status niStatus = NI_OK;
u_int en = 0;
ni_index niIndex = 0;
ni_id niDirID;
ni_entry niEntry;
ni_entrylist niEntryList;
ni_proplist niPropList;
ni_namelist niNameList;
CString csNI_AttrType( 128 );
void *aNIDomain = NULL;
gNetInfoMutex->Wait();
outRecCount = 0;
try
{
NI_INIT( &niDirID );
NI_INIT( &niEntryList );
if ( (inHow >= eDSiExact) && (inHow <= eDSiRegularExpression) )
{
uiSearchFlag = REG_ICASE;
}
aNIDomain = RetrieveNIDomain(inContext);
if (aNIDomain != NULL)
{
while ( !done )
{
NI_INIT( &niDirID );
NI_INIT( &niEntryList );
siResult = ::ni_pathsearch( aNIDomain, &niDirID, inNI_RecType );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
if ( ::strcmp( inDS_AttrType, kDSNAttrRecordName ) == 0 )
{
if ( csNI_AttrType.GetLength() == 0 )
{
csNI_AttrType.Set( "name" );
}
else
{
csNI_AttrType.Set( "realname" );
done = true;
}
}
else
{
char *netInfoType = MapAttrToNetInfoType( inDS_AttrType );
if ( netInfoType != nil )
{
csNI_AttrType.Set( netInfoType );
free( netInfoType );
netInfoType = nil;
}
done = true;
}
if ( (inContinue->fTotalRecCount < inContinue->fLimitRecSearch) || (inContinue->fLimitRecSearch == 0) )
{
niStatus = ::ni_list( aNIDomain, &niDirID, csNI_AttrType.GetData(), &niEntryList );
if ( niStatus == NI_OK )
{
for ( en = inContinue->fAllRecIndex; (en < niEntryList.ni_entrylist_len) &&
(((inContinue->fTotalRecCount) < inContinue->fLimitRecSearch) ||
(inContinue->fLimitRecSearch == 0)); en++ )
{
niEntry = niEntryList.ni_entrylist_val[ en ];
niDirID.nii_object = niEntry.id;
if ( niEntry.names != NULL )
{
niNameList = *niEntry.names;
bMatches = false;
for ( i = 0; ((i < niNameList.ni_namelist_len) && (bMatches == false)); i++ )
{
bMatches = DoAnyMatch( niNameList.ni_namelist_val[ i ], inPattMatchList, inHow );
}
if ( bMatches == true )
{
siResult = ::ni_read( aNIDomain, &niDirID, &niPropList );
if ( siResult == NI_OK )
{
fAttrData->Clear();
fRecData->Clear();
fRecData->AppendShort( ::strlen( inDS_RecType ) );
fRecData->AppendString( inDS_RecType );
niIndex = ::ni_proplist_match( niPropList, "name", NULL );
if ( niIndex == NI_INDEX_NULL || niPropList.nipl_val[ niIndex ].nip_val.ninl_len == 0 )
{
fRecData->AppendShort( ::strlen( "*** No Name ***" ) );
fRecData->AppendString( "*** No Name ***" );
}
else
{
fRecData->AppendShort( ::strlen( niPropList.nipl_val[ niIndex ].nip_val.ninl_val[ 0 ] ) );
fRecData->AppendString( niPropList.nipl_val[ niIndex ].nip_val.ninl_val[ 0 ] );
}
siResult = GetTheseAttributes( inAttrTypeList, &niPropList, inAttrOnly, aNIDomain, inContext->fDomainName, inDS_RecType, siCount );
if ( siResult == eDSNoErr )
{
if ( siCount == 0 )
{
fRecData->AppendShort( 0 );
}
else
{
fRecData->AppendShort( siCount );
fRecData->AppendBlock( fAttrData->GetData(), fAttrData->GetLength() );
}
siResult = inBuff->AddData( fRecData->GetData(), fRecData->GetLength() );
if ( siResult == CBuff::kBuffFull )
{
inContinue->fAllRecIndex = en;
::ni_proplist_free( &niPropList );
if ( siResult != eDSNoErr ) throw( siResult );
}
else if ( siResult == eDSNoErr )
{
outRecCount++;
inContinue->fTotalRecCount++;
}
else
{
inContinue->fAllRecIndex = 0;
::ni_proplist_free( &niPropList );
throw( (sInt32)eDSInvalidBuffFormat );
}
}
::ni_proplist_free( &niPropList );
siResult = eDSNoErr;
}
}
}
}
} if ( niEntryList.ni_entrylist_len > 0 )
{
::ni_entrylist_free(&niEntryList);
niEntryList.ni_entrylist_len = 0;
}
} } inContinue->fAllRecIndex = 0;
}
else
{
throw( (sInt32)eDSInvalidSession );
}
}
catch( sInt32 err )
{
if ( niEntryList.ni_entrylist_len > 0 )
{
::ni_entrylist_free(&niEntryList);
niEntryList.ni_entrylist_len = 0;
}
siResult = err;
}
gNetInfoMutex->Signal();
return( siResult );
}
#pragma mark -
#pragma mark Authentication
#pragma mark -
sInt32 CNiPlugIn::DoAuthentication ( sDoDirNodeAuth *inData )
{
sInt32 siResult = eDSAuthFailed;
sDoDirNodeAuthOnRecordType dataPlus;
dataPlus.fType = inData->fType;
dataPlus.fResult = inData->fResult;
dataPlus.fInNodeRef = inData->fInNodeRef;
dataPlus.fInAuthMethod = inData->fInAuthMethod;
dataPlus.fInDirNodeAuthOnlyFlag = inData->fInDirNodeAuthOnlyFlag;
dataPlus.fInAuthStepData = inData->fInAuthStepData;
dataPlus.fOutAuthStepDataResponse = inData->fOutAuthStepDataResponse;
dataPlus.fIOContinueData = inData->fIOContinueData;
dataPlus.fInRecordType = dsDataBufferAllocatePriv( sizeof(kDSStdRecordTypeUsers) );
if ( dataPlus.fInRecordType == nil )
return eMemoryError;
strcpy( dataPlus.fInRecordType->fBufferData, kDSStdRecordTypeUsers );
dataPlus.fInRecordType->fBufferLength = sizeof(kDSStdRecordTypeUsers) - 1;
siResult = this->DoAuthenticationOnRecordType( &dataPlus );
dsDataBufferDeallocatePriv( dataPlus.fInRecordType );
inData->fType = dataPlus.fType;
inData->fResult = dataPlus.fResult;
inData->fInNodeRef = dataPlus.fInNodeRef;
inData->fInAuthMethod = dataPlus.fInAuthMethod;
inData->fInDirNodeAuthOnlyFlag = dataPlus.fInDirNodeAuthOnlyFlag;
inData->fInAuthStepData = dataPlus.fInAuthStepData;
inData->fOutAuthStepDataResponse = dataPlus.fOutAuthStepDataResponse;
inData->fIOContinueData = dataPlus.fIOContinueData;
return siResult;
}
sInt32 CNiPlugIn::DoAuthenticationOnRecordType ( sDoDirNodeAuthOnRecordType *inData )
{
sInt32 siResult = eDSAuthFailed;
sInt32 siResult2 = eDSAuthFailed;
ni_status niResult = NI_OK;
ni_status niResultGUID = NI_OK;
uInt32 uiAuthMethod = 0;
sNIContextData *pContext = NULL;
sNIContinueData *pContinueData = NULL;
char* userName = NULL;
ni_id niDirID;
ni_namelist niValues;
ni_namelist niValuesGUID;
NetInfoAuthAuthorityHandlerProc handlerProc = NULL;
char *pNIRecType = NULL;
uInt32 settingPolicy = 0;
tDataNodePtr origAuthMethod = NULL;
char *GUIDString = NULL;
char *UserGUIDString = NULL;
void *aNIDomain = NULL;
try
{
pContext = (sNIContextData *)gNINodeRef->GetItemData( inData->fInNodeRef );
if ( pContext == nil ) throw( (sInt32)eDSInvalidNodeRef );
if ( inData->fInAuthStepData == nil ) throw( (sInt32)eDSNullAuthStepData );
if ( inData->fInRecordType == nil ) throw( (sInt32)eDSNullRecType );
if ( inData->fInRecordType->fBufferData == nil ) throw( (sInt32)eDSNullRecType );
pNIRecType = MapRecToNetInfoType( inData->fInRecordType->fBufferData );
if (pNIRecType == nil) throw( (sInt32)eDSAuthFailed );
if ( !(fHashList & kNiPluginHashHasReadConfig) )
{
gNetInfoMutex->Wait();
aNIDomain = RetrieveNIDomain(pContext);
if (aNIDomain != NULL)
{
GetHashSecurityLevelConfig( aNIDomain, &fHashList );
fHashList |= kNiPluginHashHasReadConfig;
}
else
{
gNetInfoMutex->Signal();
throw( (sInt32)eDSInvalidSession );
}
gNetInfoMutex->Signal();
}
sHashList = fHashList;
if ( inData->fIOContinueData != NULL )
{
pContinueData = (sNIContinueData *)inData->fIOContinueData;
if ( gNIContinue->VerifyItem( pContinueData ) == false )
{
throw( (sInt32)eDSInvalidContinueData );
}
if ( pContinueData->fAuthHandlerProc == nil ) throw( (sInt32)eDSInvalidContinueData );
handlerProc = (NetInfoAuthAuthorityHandlerProc)(pContinueData->fAuthHandlerProc);
siResult = (handlerProc)( inData->fInNodeRef, inData->fInAuthMethod, pContext,
&pContinueData, inData->fInAuthStepData,
inData->fOutAuthStepDataResponse,
inData->fInDirNodeAuthOnlyFlag, false,
pContinueData->fAuthAuthorityData, NULL, (const char *)pNIRecType);
}
else
{
if (inData->fInAuthMethod != nil)
{
DBGLOG1( kLogPlugin, "NetInfo PlugIn: Attempting use of authentication method %s", inData->fInAuthMethod->fBufferData );
}
siResult = dsGetAuthMethodEnumValue( inData->fInAuthMethod, &uiAuthMethod );
if ( siResult == eDSNoErr || siResult == eDSAuthMethodNotSupported )
{
if ( uiAuthMethod == kAuthGetPolicy || uiAuthMethod == kAuthSetPolicy )
{
siResult = GetUserNameFromAuthBuffer( inData->fInAuthStepData, 3, &userName );
if ( siResult != eDSNoErr ) throw( siResult );
if ( RecordHasAuthAuthority( userName, (const char *)pNIRecType, pContext, kDSTagAuthAuthorityShadowHash, &niDirID ) == eDSNoErr )
{
UserGUIDString = GetGUIDForRecord( pContext, &niDirID );
if ( uiAuthMethod == kAuthGetPolicy )
{
siResult = DoShadowHashAuth(inData->fInNodeRef, inData->fInAuthMethod, pContext,
&pContinueData,
inData->fInAuthStepData,
inData->fOutAuthStepDataResponse,
inData->fInDirNodeAuthOnlyFlag,
false, NULL, UserGUIDString, (const char *)pNIRecType);
throw( siResult );
}
}
}
if ( uiAuthMethod == kAuthSetGlobalPolicy || uiAuthMethod == kAuthSetPolicy )
{
char *user = NULL;
char *password = NULL;
unsigned int itemCount = 0;
bool authenticatorFieldsHaveData = true;
if ( pContext->fEffectiveUID == 0 )
{
siResult = Get2FromBuffer( inData->fInAuthStepData, NULL, &user, &password, &itemCount );
if ( itemCount >= 2 && user != NULL && user[0] == '\0' && password != NULL && password[0] == '\0' )
authenticatorFieldsHaveData = false;
if ( user != NULL )
free( user );
if ( password != NULL )
free( password );
}
if ( pContext->fEffectiveUID != 0 || authenticatorFieldsHaveData )
{
settingPolicy = uiAuthMethod;
uiAuthMethod = kAuthNativeClearTextOK;
origAuthMethod = inData->fInAuthMethod;
inData->fInAuthMethod = dsDataNodeAllocateString( 0, kDSStdAuthNodeNativeClearTextOK );
if ( inData->fInAuthMethod == NULL )
throw( (sInt32)eMemoryError );
inData->fInDirNodeAuthOnlyFlag = false;
}
else
{
siResult = DoShadowHashAuth(inData->fInNodeRef, inData->fInAuthMethod, pContext,
&pContinueData,
inData->fInAuthStepData,
inData->fOutAuthStepDataResponse,
inData->fInDirNodeAuthOnlyFlag,
false, NULL, UserGUIDString, (const char *)pNIRecType);
throw( siResult );
}
}
else
if ( uiAuthMethod == kAuthSetPasswd )
{
siResult = GetUserNameFromAuthBuffer( inData->fInAuthStepData, 3, &userName );
if ( siResult != eDSNoErr ) throw( siResult );
if ( RecordHasAuthAuthority( userName, (const char *)pNIRecType, pContext, kDSTagAuthAuthorityShadowHash, &niDirID ) == eDSNoErr )
{
GUIDString = GetGUIDForRecord( pContext, &niDirID );
origAuthMethod = inData->fInAuthMethod;
inData->fInAuthMethod = dsDataNodeAllocateString( 0, "dsAuthMethodSetPasswd:dsAuthNodeNativeCanUseClearText" );
if ( inData->fInAuthMethod == NULL )
throw( (sInt32)eMemoryError );
siResult = DoShadowHashAuth(inData->fInNodeRef, inData->fInAuthMethod, pContext,
&pContinueData,
inData->fInAuthStepData,
inData->fOutAuthStepDataResponse,
true,
false, NULL, GUIDString, (const char *)pNIRecType);
if ( siResult != eDSNoErr && siResult != eDSAuthNewPasswordRequired )
throw( siResult );
dsDataBufferDeallocatePriv( inData->fInAuthMethod );
inData->fInAuthMethod = dsDataNodeAllocateString( 0, kDSStdAuthSetPasswdAsRoot );
}
DSFreeString(userName);
}
switch( uiAuthMethod )
{
case kAuthWithAuthorizationRef:
{
AuthorizationRef authRef = 0;
AuthorizationItemSet* resultRightSet = NULL;
if ( inData->fInAuthStepData->fBufferLength < sizeof( AuthorizationExternalForm ) ) throw( (sInt32)eDSInvalidBuffFormat );
siResult = AuthorizationCreateFromExternalForm((AuthorizationExternalForm *)inData->fInAuthStepData->fBufferData,
&authRef);
if (siResult != errAuthorizationSuccess)
{
DBGLOG1( kLogPlugin, "CNiPlugIn: AuthorizationCreateFromExternalForm returned error %d", siResult );
syslog( LOG_ALERT, "AuthorizationCreateFromExternalForm returned error %d", siResult );
throw( (sInt32)eDSPermissionError );
}
AuthorizationItem rights[] = { {"system.preferences", 0, 0, 0} };
AuthorizationItemSet rightSet = { sizeof(rights)/ sizeof(*rights), rights };
siResult = AuthorizationCopyRights(authRef, &rightSet, NULL,
kAuthorizationFlagExtendRights, &resultRightSet);
if (resultRightSet != NULL)
{
AuthorizationFreeItemSet(resultRightSet);
resultRightSet = NULL;
}
if (siResult != errAuthorizationSuccess)
{
DBGLOG1( kLogPlugin, "CNiPlugIn: AuthorizationCopyRights returned error %d", siResult );
syslog( LOG_ALERT, "AuthorizationCopyRights returned error %d", siResult );
throw( (sInt32)eDSPermissionError );
}
if (inData->fInDirNodeAuthOnlyFlag == false)
{
if (pContext->fAuthenticatedUserName != NULL)
{
free(pContext->fAuthenticatedUserName);
}
pContext->fAuthenticatedUserName = strdup("root");
}
AuthorizationFree( authRef, 0 ); siResult = eDSNoErr;
}
break;
case kAuthGetGlobalPolicy:
{
siResult = DoShadowHashAuth(inData->fInNodeRef, inData->fInAuthMethod, pContext,
&pContinueData,
inData->fInAuthStepData,
inData->fOutAuthStepDataResponse,
inData->fInDirNodeAuthOnlyFlag,
false, NULL, NULL, (const char *)pNIRecType);
}
break;
default: {
if ( uiAuthMethod != kAuth2WayRandom )
{
siResult = GetUserNameFromAuthBuffer( inData->fInAuthStepData, 1, &userName );
if ( siResult != eDSNoErr ) throw( siResult );
}
else
{
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 );
}
gNetInfoMutex->Wait();
aNIDomain = RetrieveNIDomain(pContext);
if (aNIDomain != NULL)
{
siResult = IsValidRecordName( userName, (const char *)pNIRecType, aNIDomain, niDirID );
}
else
{
gNetInfoMutex->Signal();
throw( (sInt32)eDSInvalidSession );
}
gNetInfoMutex->Signal();
if ( siResult != eDSNoErr )
{
bool bAdminUserAuthUsed = false;
if ( (pContext->bIsLocal) && !(inData->fInDirNodeAuthOnlyFlag) && (siResult != eDSNoErr) )
{
if (UserIsAdmin(userName, pContext))
{
tDataList *usersNode = nil;
usersNode = FindNodeForSearchPolicyAuthUser(userName);
if (usersNode != nil)
{
tDirReference aDirRef = 0;
sInt32 aResult = eDSNoErr;
tDirNodeReference aNodeRef = 0;
tContextData tContinue = nil;
aResult = dsOpenDirService(&aDirRef);
if (aResult == eDSNoErr)
{
aResult = dsOpenDirNode(aDirRef, usersNode, &aNodeRef);
dsDataListDeallocatePriv(usersNode);
free(usersNode);
usersNode = NULL;
if ( aResult == eDSNoErr)
{
aResult = dsDoDirNodeAuth( aNodeRef, inData->fInAuthMethod, true, inData->fInAuthStepData, inData->fOutAuthStepDataResponse, &tContinue );
if (aResult == eDSNoErr)
{
tDataList *dataList = nil;
dataList = dsAuthBufferGetDataListAllocPriv(inData->fInAuthStepData);
if ( dataList != nil )
{
if ( dsDataListGetNodeCountPriv(dataList) >= 2 )
{
char *pwd = nil;
pwd = dsDataListGetNodeStringPriv(dataList, 2);
if ( pwd != nil )
{
siResult = AuthOpen( pContext, userName, pwd, true );
bAdminUserAuthUsed = true;
bzero(pwd, strlen(pwd));
free(pwd);
pwd = nil;
}
}
dsDataListDeallocatePriv(dataList);
free(dataList);
dataList = NULL;
}
}
dsCloseDirNode(aNodeRef);
aNodeRef = 0;
} dsCloseDirService(aDirRef);
} } } } if (bAdminUserAuthUsed)
{
if ( settingPolicy && siResult == eDSNoErr && UserGUIDString != NULL )
{
uiAuthMethod = settingPolicy;
dsDataBufferDeallocatePriv( inData->fInAuthMethod );
inData->fInAuthMethod = origAuthMethod;
origAuthMethod = NULL;
siResult = DoShadowHashAuth(inData->fInNodeRef, inData->fInAuthMethod, pContext,
&pContinueData,
inData->fInAuthStepData,
inData->fOutAuthStepDataResponse,
inData->fInDirNodeAuthOnlyFlag,
false, NULL, UserGUIDString, (const char *)pNIRecType);
}
throw(siResult);
}
else
{
throw( (sInt32)eDSAuthFailed ); }
}
NI_INIT( &niValuesGUID );
NI_INIT( &niValues );
gNetInfoMutex->Wait();
aNIDomain = RetrieveNIDomain(pContext);
if (aNIDomain != NULL)
{
niResultGUID = ni_lookupprop( aNIDomain, &niDirID,
"generateduid", &niValuesGUID );
niResult = ni_lookupprop( aNIDomain, &niDirID,
"authentication_authority", &niValues );
}
else
{
gNetInfoMutex->Signal();
throw( (sInt32)eDSInvalidSession );
}
gNetInfoMutex->Signal();
if ( (niResult == NI_OK) && (niValues.ni_namelist_len > 0) )
{
unsigned int i = 0;
bool bLoopAll = IsWriteAuthRequest(uiAuthMethod);
bool bIsSecondary = false;
char* aaVersion = NULL;
char* aaTag = NULL;
char* aaData = NULL;
if ( (niResultGUID == NI_OK) && (niValuesGUID.ni_namelist_len > 0) )
{
if (niValuesGUID.ni_namelist_val[0] != nil)
{
GUIDString = strdup(niValuesGUID.ni_namelist_val[0]);
}
gNetInfoMutex->Wait();
ni_namelist_free(&niValuesGUID);
gNetInfoMutex->Signal();
}
siResult = eDSAuthMethodNotSupported;
while ( i < niValues.ni_namelist_len
&& (siResult == eDSAuthMethodNotSupported ||
(bLoopAll && siResult == eDSNoErr)))
{
siResult2 = dsParseAuthAuthority( niValues.ni_namelist_val[i], &aaVersion,
&aaTag, &aaData );
if (siResult2 != eDSNoErr)
{
siResult = eDSAuthFailed;
break;
}
if ( aaTag != NULL && strcasecmp(aaTag, kDSTagAuthAuthorityDisabledUser) == 0 )
{
if ( aaData != NULL )
DSFreeString( aaData );
aaData = strdup( niValues.ni_namelist_val[i] + strlen(aaVersion) + strlen(aaTag) + 2 );
}
handlerProc = GetNetInfoAuthAuthorityHandler( aaTag );
if (handlerProc != NULL)
{
siResult = (handlerProc)(inData->fInNodeRef, inData->fInAuthMethod, pContext,
&pContinueData,
inData->fInAuthStepData,
inData->fOutAuthStepDataResponse,
inData->fInDirNodeAuthOnlyFlag,
bIsSecondary, aaData, GUIDString, (const char *)pNIRecType);
if (siResult == eDSNoErr)
{
if (pContinueData != NULL)
{
pContinueData->fAuthHandlerProc = (void*)handlerProc;
pContinueData->fAuthAuthorityData = aaData;
aaData = NULL;
break;
}
else
{
bIsSecondary = true;
}
}
} else if ( !bIsSecondary )
{
siResult = eDSAuthMethodNotSupported;
}
if (aaVersion != NULL) {
free(aaVersion);
aaVersion = NULL;
}
if (aaTag != NULL) {
free(aaTag);
aaTag = NULL;
}
if (aaData != NULL) {
free(aaData);
aaData = NULL;
}
++i;
}
if (aaVersion != NULL) {
free(aaVersion);
aaVersion = NULL;
}
if (aaTag != NULL) {
free(aaTag);
aaTag = NULL;
}
if (aaData != NULL) {
free(aaData);
aaData = NULL;
}
gNetInfoMutex->Wait();
ni_namelist_free(&niValues);
gNetInfoMutex->Signal();
}
else
{
siResult = DoBasicAuth(inData->fInNodeRef,inData->fInAuthMethod, pContext,
&pContinueData, inData->fInAuthStepData,
inData->fOutAuthStepDataResponse,
inData->fInDirNodeAuthOnlyFlag, false, NULL, NULL, (const char *)pNIRecType);
if (pContinueData != NULL && siResult == eDSNoErr)
{
pContinueData->fAuthHandlerProc = (void*)CNiPlugIn::DoBasicAuth;
}
}
if ( settingPolicy && siResult == eDSNoErr )
{
uiAuthMethod = settingPolicy;
dsDataBufferDeallocatePriv( inData->fInAuthMethod );
inData->fInAuthMethod = origAuthMethod;
origAuthMethod = NULL;
siResult = DoShadowHashAuth(inData->fInNodeRef, inData->fInAuthMethod, pContext,
&pContinueData,
inData->fInAuthStepData,
inData->fOutAuthStepDataResponse,
inData->fInDirNodeAuthOnlyFlag,
false, NULL, UserGUIDString, (const char *)pNIRecType);
}
} }
}
} }
catch( sInt32 err )
{
siResult = err;
}
DSFreeString( GUIDString );
DSFreeString( UserGUIDString );
if ( origAuthMethod != NULL )
{
dsDataBufferDeallocatePriv( origAuthMethod );
origAuthMethod = NULL;
}
if (pNIRecType != NULL)
{
free(pNIRecType);
pNIRecType = nil;
}
DSFreeString( userName );
inData->fResult = siResult;
inData->fIOContinueData = pContinueData;
return( siResult );
}
sInt32 CNiPlugIn::RecordHasAuthAuthority( const char *inRecordName, const char *inRecType, sNIContextData *inContext, const char *inTag, ni_id *outDirID )
{
sInt32 siResult = eDSAuthFailed;
ni_status niResult = NI_OK;
ni_id niDirID;
ni_namelist niValues;
try
{
if ( inContext == nil ) throw( (sInt32)eDSInvalidNodeRef );
if ( inRecType == nil ) throw( (sInt32)eDSNullRecType );
gNetInfoMutex->Wait();
void *aNIDomain = RetrieveNIDomain(inContext);
if (aNIDomain != NULL)
{
siResult = IsValidRecordName( inRecordName, inRecType, aNIDomain, niDirID );
gNetInfoMutex->Signal();
if ( siResult != eDSNoErr ) throw( (sInt32)eDSAuthFailed ); }
else
{
gNetInfoMutex->Signal();
throw( (sInt32)eDSInvalidSession );
}
gNetInfoMutex->Wait();
aNIDomain = RetrieveNIDomain(inContext);
if (aNIDomain != NULL)
{
niResult = ni_lookupprop( aNIDomain, &niDirID, "authentication_authority", &niValues );
}
else
{
gNetInfoMutex->Signal();
throw( (sInt32)eDSInvalidSession );
}
gNetInfoMutex->Signal();
if ( (niResult == NI_OK) && (niValues.ni_namelist_len > 0) )
{
unsigned int i = 0;
char* aaVersion = NULL;
char* aaTag = NULL;
char* aaData = NULL;
sInt32 siResult2;
siResult = eDSAuthMethodNotSupported;
while ( i < niValues.ni_namelist_len && siResult == eDSAuthMethodNotSupported )
{
siResult2 = dsParseAuthAuthority( niValues.ni_namelist_val[i], &aaVersion, &aaTag, &aaData );
if (siResult2 != eDSNoErr)
{
siResult = eDSAuthFailed;
break;
}
if ( strcasecmp(inTag, aaTag) == 0 )
{
siResult = eDSNoErr;
break;
}
else if ( strcasecmp(kDSTagAuthAuthorityDisabledUser, aaTag) == 0 &&
strcasestr(niValues.ni_namelist_val[i], inTag) != NULL )
{
siResult = eDSNoErr;
break;
}
if (aaVersion != NULL) {
free(aaVersion);
aaVersion = NULL;
}
if (aaTag != NULL) {
free(aaTag);
aaTag = NULL;
}
if (aaData != NULL) {
free(aaData);
aaData = NULL;
}
++i;
}
if (aaVersion != NULL) {
free(aaVersion);
aaVersion = NULL;
}
if (aaTag != NULL) {
free(aaTag);
aaTag = NULL;
}
if (aaData != NULL) {
free(aaData);
aaData = NULL;
}
gNetInfoMutex->Wait();
ni_namelist_free(&niValues);
gNetInfoMutex->Signal();
}
}
catch( sInt32 err )
{
siResult = err;
}
if ( outDirID != NULL )
*outDirID = niDirID;
return( siResult );
}
bool CNiPlugIn::IsWriteAuthRequest ( uInt32 uiAuthMethod )
{
switch ( uiAuthMethod )
{
case kAuthSetPasswd:
case kAuthSetPasswdAsRoot:
case kAuthChangePasswd:
case kAuthSetGlobalPolicy:
case kAuthSetPolicy:
return true;
default:
return false;
}
}
#pragma mark -
#pragma mark LocalCachedUser
#pragma mark -
sInt32 CNiPlugIn::DoLocalCachedUserAuth ( tDirNodeReference inNodeRef, tDataNodePtr inAuthMethod,
sNIContextData* inContext,
sNIContinueData** inOutContinueData,
tDataBufferPtr inAuthData, tDataBufferPtr outAuthData,
bool inAuthOnly, bool isSecondary,
const char* inAuthAuthorityData, const char* inGUIDString,
const char* inNativeRecType )
{
sInt32 siResult = eDSAuthFailed;
bool bNetworkNodeReachable = false;
siResult = LocalCachedUserReachable( inNodeRef, inAuthMethod, inContext, inOutContinueData,
inAuthData, outAuthData, inAuthAuthorityData, inGUIDString, inNativeRecType, &bNetworkNodeReachable );
if ( siResult == eDSNoErr )
{
siResult = DoLocalCachedUserAuthPhase2( inNodeRef, inAuthMethod, inContext, inOutContinueData,
inAuthData, outAuthData, inAuthOnly, isSecondary,
inAuthAuthorityData, inGUIDString, inNativeRecType, bNetworkNodeReachable );
}
if (inContext->fLocalCacheNetNode != NULL)
{
dsDataListDeallocatePriv(inContext->fLocalCacheNetNode);
free(inContext->fLocalCacheNetNode);
inContext->fLocalCacheNetNode = NULL;
}
if (inContext->fLocalCacheRef != 0)
{
dsCloseDirService(inContext->fLocalCacheRef);
inContext->fLocalCacheRef = 0;
}
return( siResult );
}
sInt32 CNiPlugIn::LocalCachedUserReachable( tDirNodeReference inNodeRef,
tDataNodePtr inAuthMethod,
sNIContextData* inContext,
sNIContinueData** inOutContinueData,
tDataBufferPtr inAuthData,
tDataBufferPtr outAuthData,
const char* inAuthAuthorityData,
const char* inGUIDString,
const char* inNativeRecType,
bool *inOutNodeReachable )
{
sInt32 siResult = eDSAuthFailed;
uInt32 uiAuthMethod = 0;
char *networkNodename = nil;
char *userRecordName = nil;
char *userGUID = nil;
sInt32 result = eDSNoErr;
tDataBuffer *dataBuffer = nil;
uInt32 nodeCount = 0;
tDirNodeReference aSearchNodeRef = 0;
tDataList *pSearchNode = nil;
tDataList *pSearchNodeList = nil;
tAttributeListRef attrListRef = 0;
tAttributeValueListRef attrValueListRef = 0;
tAttributeValueEntry *pAttrValueEntry = nil;
tAttributeEntry *pAttrEntry = nil;
uInt32 aIndex = 0;
if ( inAuthData == nil ) return( (sInt32)eDSNullAuthStepData );
if ( inContext == nil ) return( (sInt32)eDSInvalidNodeRef );
if ( inOutNodeReachable == nil ) return( (sInt32)eParameterError );
*inOutNodeReachable = false;
DBGLOG( kLogPlugin, "LocalCachedUserReachable::" );
if (inAuthMethod != nil)
DBGLOG1( kLogPlugin, "NetInfo PlugIn: Attempting use of authentication method %s", inAuthMethod->fBufferData );
try
{
siResult = dsGetAuthMethodEnumValue( inAuthMethod, &uiAuthMethod );
if ( siResult == eDSNoErr )
{
siResult = ParseLocalCacheUserData(inAuthAuthorityData, &networkNodename, &userRecordName, &userGUID);
result = dsOpenDirService(&inContext->fLocalCacheRef);
if (result == eDSNoErr)
{
inContext->fLocalCacheNetNode = dsBuildFromPathPriv( networkNodename, "/" );
if ( inContext->fLocalCacheNetNode == nil ) throw( (sInt32)eMemoryError );
dataBuffer = ::dsDataBufferAllocate( inContext->fLocalCacheRef, 1024 );
if ( dataBuffer == nil ) throw( (sInt32)eMemoryError );
if ( strncmp("/Active Directory/", networkNodename, sizeof("/Active Directory/")-1) == 0 )
{
*inOutNodeReachable = true;
siResult = eDSNoErr;
throw( siResult );
}
result = dsFindDirNodes( inContext->fLocalCacheRef, dataBuffer, inContext->fLocalCacheNetNode, eDSiExact, &nodeCount, nil );
if ( (result == eDSNoErr) && (nodeCount == 1) )
{
result = dsFindDirNodes( inContext->fLocalCacheRef, dataBuffer, nil, eDSAuthenticationSearchNodeName, &nodeCount, nil );
if ( ( result == eDSNoErr ) && ( nodeCount == 1 ) )
{
result = dsGetDirNodeName( inContext->fLocalCacheRef, dataBuffer, 1, &pSearchNode );
if ( result == eDSNoErr )
{
result = dsOpenDirNode( inContext->fLocalCacheRef, pSearchNode, &aSearchNodeRef );
if ( pSearchNode != NULL )
{
dsDataListDeallocatePriv( pSearchNode );
free( pSearchNode );
pSearchNode = NULL;
}
if ( result == eDSNoErr )
{
pSearchNodeList = dsBuildFromPathPriv( kDS1AttrSearchPath, "/" );
if ( pSearchNodeList == nil ) throw( (sInt32)eMemoryError );
do
{
nodeCount = 0;
result = dsGetDirNodeInfo( aSearchNodeRef, pSearchNodeList, dataBuffer, false, &nodeCount, &attrListRef, nil );
if (result == eDSBufferTooSmall)
{
uInt32 bufSize = dataBuffer->fBufferSize;
dsDataBufferDeallocatePriv( dataBuffer );
dataBuffer = nil;
dataBuffer = ::dsDataBufferAllocate( inContext->fLocalCacheRef, bufSize * 2 );
}
} while (result == eDSBufferTooSmall);
if ( ( result == eDSNoErr ) && (nodeCount > 0) )
{
result = dsGetAttributeEntry( aSearchNodeRef, dataBuffer, attrListRef, 1, &attrValueListRef, &pAttrEntry );
if ( result != eDSNoErr ) throw( result );
for (aIndex=1; aIndex < (pAttrEntry->fAttributeValueCount+1); aIndex++)
{
result = dsGetAttributeValue( aSearchNodeRef, dataBuffer, aIndex, attrValueListRef, &pAttrValueEntry );
if ( result != eDSNoErr ) throw( result );
if ( pAttrValueEntry->fAttributeValueData.fBufferData == nil ) throw( (sInt32)eMemoryAllocError );
if (strcmp( networkNodename, pAttrValueEntry->fAttributeValueData.fBufferData ) == 0 )
{
char *chPtr = strstr( networkNodename, kstrNetInfoName);
if ( chPtr != nil )
{
tDataList *pNodeNameDL = nil;
pNodeNameDL = ::dsBuildListFromStringsPriv( "NetInfo", "..", nil );
if (pNodeNameDL != nil)
{
sInt32 openResult = eDSNoErr;
tDirNodeReference aNodeRef = 0;
openResult = dsOpenDirNode( inContext->fLocalCacheRef, pNodeNameDL, &aNodeRef );
if ( openResult == eDSNoErr )
{
*inOutNodeReachable = true; dsCloseDirNode(aNodeRef);
aNodeRef = 0;
}
dsDataListDeAllocate( inContext->fLocalCacheRef, pNodeNameDL, false );
free(pNodeNameDL);
pNodeNameDL = nil;
}
}
else
{
*inOutNodeReachable = true; }
dsDeallocAttributeValueEntry(inContext->fLocalCacheRef, pAttrValueEntry);
pAttrValueEntry = nil;
break;
}
dsDeallocAttributeValueEntry(inContext->fLocalCacheRef, pAttrValueEntry);
pAttrValueEntry = nil;
}
dsCloseAttributeList(attrListRef);
dsCloseAttributeValueList(attrValueListRef);
dsDeallocAttributeEntry(inContext->fLocalCacheRef, pAttrEntry);
pAttrEntry = nil;
result = ::dsCloseDirNode(aSearchNodeRef);
aSearchNodeRef = 0;
if ( result != eDSNoErr ) throw( result );
}
}
}
}
}
}
}
}
catch( sInt32 err )
{
siResult = err;
}
DSFreeString( networkNodename );
DSFreeString( userRecordName );
DSFreeString( userGUID );
if ( dataBuffer != nil )
{
dsDataBufferDeallocatePriv( dataBuffer );
dataBuffer = nil;
}
return( siResult );
}
sInt32 CNiPlugIn::DoLocalCachedUserAuthPhase2 ( tDirNodeReference inNodeRef,
tDataNodePtr inAuthMethod,
sNIContextData* inContext,
sNIContinueData** inOutContinueData,
tDataBufferPtr inAuthData,
tDataBufferPtr outAuthData,
bool inAuthOnly,
bool isSecondary,
const char* inAuthAuthorityData,
const char* inGUIDString,
const char* inNativeRecType,
bool inNetNodeReachable )
{
sInt32 siResult = eDSAuthFailed;
uInt32 uiAuthMethod = 0;
sInt32 result = eDSNoErr;
tDirNodeReference aNodeRef = 0;
tDataNode *authMethodPtr = nil;
bool bAuthLocally = false;
sNIContextData *tmpContext = nil;
tDataListPtr dataList = NULL;
char *pUserName = nil;
char *pNewPassword = nil;
unsigned int itemCount = 0;
char *policyStr = NULL;
unsigned long policyStrLen = 0;
try
{
if ( inAuthData == nil ) throw( (sInt32)eDSNullAuthStepData );
if ( inContext == nil ) throw( (sInt32)eDSInvalidNodeRef );
siResult = dsGetAuthMethodEnumValue( inAuthMethod, &uiAuthMethod );
if ( siResult == eDSNoErr )
{
siResult = eDSAuthFailed;
switch( uiAuthMethod )
{
case kAuthSetPasswdAsRoot:
case kAuthWriteSecureHash:
case kAuthReadSecureHash:
case kAuthSecureHash:
siResult = CNiPlugIn::DoShadowHashAuth( inNodeRef,
inAuthMethod,
inContext,
inOutContinueData,
inAuthData,
outAuthData,
inAuthOnly,
isSecondary,
kLocalCachedUserHashList,
inGUIDString,
inNativeRecType );
break;
case kAuthChangePasswd:
if (inNetNodeReachable && inContext->fLocalCacheNetNode != NULL)
{
if ( inContext->fLocalCacheRef != 0 )
result = eDSNoErr;
else
result = dsOpenDirService(&inContext->fLocalCacheRef);
if (result == eDSNoErr)
{
result = dsOpenDirNode(inContext->fLocalCacheRef, inContext->fLocalCacheNetNode, &aNodeRef);
if ( result == eDSNoErr)
{
siResult = dsDoDirNodeAuth( aNodeRef, inAuthMethod, inAuthOnly, inAuthData, outAuthData, nil );
if (siResult == eDSNoErr)
{
siResult = CNiPlugIn::DoShadowHashAuth( inNodeRef,
inAuthMethod,
inContext,
inOutContinueData,
inAuthData,
outAuthData,
inAuthOnly,
isSecondary,
kLocalCachedUserHashList,
inGUIDString,
inNativeRecType );
}
}
}
}
break;
case kAuthNativeClearTextOK:
case kAuthNativeNoClearText:
case kAuthNativeMethod:
bAuthLocally = false;
if (inNetNodeReachable && inContext->fLocalCacheNetNode != NULL)
{
if ( inContext->fLocalCacheRef != 0 )
result = eDSNoErr;
else
result = dsOpenDirService(&inContext->fLocalCacheRef);
if (result == eDSNoErr)
{
result = dsOpenDirNode(inContext->fLocalCacheRef, inContext->fLocalCacheNetNode, &aNodeRef);
if ( result == eDSNoErr)
{
siResult = dsDoDirNodeAuth( aNodeRef, inAuthMethod, true, inAuthData, outAuthData, nil );
if (siResult == eDSNoErr)
{
siResult = CNiPlugIn::DoShadowHashAuth( inNodeRef,
inAuthMethod,
inContext,
inOutContinueData,
inAuthData,
outAuthData,
inAuthOnly,
isSecondary,
kLocalCachedUserHashList,
inGUIDString,
inNativeRecType );
if (siResult != eDSNoErr)
{
DBGLOG( kLogPlugin, "DoLocalCachedUserAuth::Local auth not sync'ed so try to set local password" );
authMethodPtr = dsDataNodeAllocateString( inContext->fLocalCacheRef, kDSStdAuthSetPasswdAsRoot );
if (authMethodPtr == nil ) throw( (sInt32)eMemoryError );
tmpContext = (sNIContextData *) calloc(1, sizeof(sNIContextData));
tmpContext->fDomain = inContext->fDomain;
tmpContext->fDomainName = inContext->fDomainName;
tmpContext->fDomainPath = inContext->fDomainPath;
tmpContext->fRecType = inContext->fRecType;
tmpContext->fRecName = inContext->fRecName;
tmpContext->dirID = inContext->dirID;
tmpContext->offset = inContext->offset;
tmpContext->fDontUseSafeClose = inContext->fDontUseSafeClose;
tmpContext->bDidWriteOperation = inContext->bDidWriteOperation;
tmpContext->fUID = getuid();
tmpContext->fEffectiveUID = geteuid();
tmpContext->fAuthenticatedUserName = inContext->fAuthenticatedUserName;
tmpContext->fPWSRef = inContext->fPWSRef;
tmpContext->fPWSNodeRef = inContext->fPWSNodeRef;
tmpContext->bIsLocal = true;
siResult = CNiPlugIn::DoShadowHashAuth( inNodeRef,
authMethodPtr,
tmpContext,
inOutContinueData,
inAuthData,
outAuthData,
inAuthOnly,
isSecondary,
kLocalCachedUserHashList,
inGUIDString,
inNativeRecType );
free(tmpContext);
tmpContext = nil;
}
}
else if (siResult == eDSCannotAccessSession)
{
DBGLOG( kLogPlugin, "DoLocalCachedUserAuth::Original node failed with eDSCannotAccessSession, authenticate locally" );
bAuthLocally = true;
}
}
else
{
bAuthLocally = true;
}
}
}
else
{
bAuthLocally = true;
}
if (bAuthLocally)
{
siResult = CNiPlugIn::DoShadowHashAuth( inNodeRef,
inAuthMethod,
inContext,
inOutContinueData,
inAuthData,
outAuthData,
inAuthOnly,
isSecondary,
kLocalCachedUserHashList,
inGUIDString,
inNativeRecType );
}
break;
case kAuthSetPolicyAsRoot:
siResult = Get2FromBuffer(inAuthData, &dataList, &pUserName, &pNewPassword, &itemCount );
if ( siResult != eDSNoErr )
throw( siResult );
if ( itemCount != 2 || pNewPassword == NULL || pNewPassword[0] == '\0' )
throw( (sInt32)eDSInvalidBuffFormat );
siResult = SetUserPolicies( inContext, inNativeRecType, pUserName, pNewPassword, NULL );
break;
case kAuthGetPolicy:
if ( outAuthData == nil ) throw( (sInt32)eDSNullAuthStepData );
outAuthData->fBufferLength = 0;
dataList = dsAuthBufferGetDataListAllocPriv(inAuthData);
if ( dataList == nil ) throw( (sInt32)eDSInvalidBuffFormat );
itemCount = dsDataListGetNodeCountPriv(dataList);
if ( itemCount != 3 ) throw( (sInt32)eDSInvalidBuffFormat );
pUserName = dsDataListGetNodeStringPriv(dataList, 3);
if ( pUserName == nil ) throw( (sInt32)eDSInvalidBuffFormat );
if ( strlen(pUserName) < 1 ) throw( (sInt32)eDSInvalidBuffFormat );
siResult = GetUserPolicies( inContext, inNativeRecType, pUserName, NULL, &policyStr );
if ( siResult != 0 ) throw( siResult );
if ( policyStr != NULL )
policyStrLen = strlen( policyStr );
if ( outAuthData->fBufferSize < 4 + policyStrLen )
throw( (sInt32)eDSBufferTooSmall );
outAuthData->fBufferLength = 4 + policyStrLen;
memcpy( outAuthData->fBufferData, &policyStrLen, 4 );
if ( policyStrLen > 0 )
memcpy( outAuthData->fBufferData + 4, policyStr, policyStrLen );
break;
case kAuthSetPolicy:
dataList = dsAuthBufferGetDataListAllocPriv(inAuthData);
if ( dataList == nil ) throw( (sInt32)eDSInvalidBuffFormat );
itemCount = dsDataListGetNodeCountPriv(dataList);
if ( itemCount != 4 ) throw( (sInt32)eDSInvalidBuffFormat );
pUserName = dsDataListGetNodeStringPriv(dataList, 3);
if ( pUserName == nil ) throw( (sInt32)eDSInvalidBuffFormat );
if ( pUserName[0] == '\0' ) throw( (sInt32)eDSInvalidBuffFormat );
pNewPassword = dsDataListGetNodeStringPriv(dataList, 4);
if ( pNewPassword == nil )
throw( (sInt32)eDSInvalidBuffFormat );
if ( pNewPassword[0] == '\0' )
throw( (sInt32)eDSInvalidBuffFormat );
siResult = SetUserPolicies( inContext, inNativeRecType, pUserName, pNewPassword, NULL );
break;
case kAuthSetPasswd:
case kAuthSMB_NT_Key:
case kAuthSMB_LM_Key:
default:
siResult = eDSAuthMethodNotSupported;
break;
}
}
}
catch( sInt32 err )
{
siResult = err;
}
if (authMethodPtr != nil)
{
dsDataBufferDeallocatePriv( authMethodPtr );
authMethodPtr = nil;
}
if (aNodeRef != 0)
{
dsCloseDirNode(aNodeRef);
aNodeRef = 0;
}
if (inContext->fLocalCacheNetNode != NULL)
{
dsDataListDeallocatePriv(inContext->fLocalCacheNetNode);
free(inContext->fLocalCacheNetNode);
inContext->fLocalCacheNetNode = NULL;
}
if (inContext->fLocalCacheRef != 0)
{
dsCloseDirService(inContext->fLocalCacheRef);
inContext->fLocalCacheRef = 0;
}
if (dataList != NULL)
{
dsDataListDeallocatePriv(dataList);
free(dataList);
dataList = NULL;
}
DSFreeString( pUserName );
DSFreePassword( pNewPassword );
DSFreeString( policyStr );
return( siResult );
}
#pragma mark -
#pragma mark DisabledUser
#pragma mark -
sInt32 CNiPlugIn::DoDisabledAuth ( tDirNodeReference inNodeRef, tDataNodePtr inAuthMethod,
sNIContextData* inContext,
sNIContinueData** inOutContinueData,
tDataBufferPtr inAuthData, tDataBufferPtr outAuthData,
bool inAuthOnly, bool isSecondary,
const char* inAuthAuthorityData, const char* inGUIDString,
const char* inNativeRecType )
{
sInt32 siResult = eDSAuthFailed;
uInt32 uiAuthMethod = 0;
bool bNetworkNodeReachable = false;
const char *startOfOrigAuthAuthorityTag = NULL;
char *pUserName = NULL;
tDataListPtr dataList = NULL;
siResult = dsGetAuthMethodEnumValue( inAuthMethod, &uiAuthMethod );
if ( siResult != eDSNoErr )
return siResult;
if ( inAuthAuthorityData != NULL )
{
startOfOrigAuthAuthorityTag = strcasestr( inAuthAuthorityData, kDSValueAuthAuthorityLocalCachedUser );
if ( startOfOrigAuthAuthorityTag != NULL )
{
siResult = LocalCachedUserReachable( inNodeRef, inAuthMethod, inContext, inOutContinueData,
inAuthData, outAuthData,
startOfOrigAuthAuthorityTag + sizeof(kDSValueAuthAuthorityLocalCachedUser) - 1,
inGUIDString, inNativeRecType, &bNetworkNodeReachable );
if ( siResult != eDSNoErr )
return( siResult );
if ( bNetworkNodeReachable )
{
siResult = DoLocalCachedUserAuthPhase2( inNodeRef, inAuthMethod, inContext, inOutContinueData,
inAuthData, outAuthData, inAuthOnly, isSecondary,
startOfOrigAuthAuthorityTag + sizeof(kDSValueAuthAuthorityLocalCachedUser) - 1,
inNativeRecType, inGUIDString, bNetworkNodeReachable );
if ( siResult == eDSNoErr )
{
switch( uiAuthMethod )
{
case kAuthNativeClearTextOK:
case kAuthNativeNoClearText:
case kAuthNativeMethod:
dataList = dsAuthBufferGetDataListAllocPriv( inAuthData );
if ( dataList != NULL )
{
if ( dsDataListGetNodeCountPriv(dataList) >= 1 )
{
pUserName = dsDataListGetNodeStringPriv(dataList, 1);
if ( pUserName != NULL )
{
if ( strlen(pUserName) > 0 )
SetUserAuthAuthorityAsRoot( inContext, inNativeRecType, pUserName, startOfOrigAuthAuthorityTag );
DSFreeString( pUserName );
}
}
dsDataListDeallocatePriv( dataList );
free( dataList );
dataList = NULL;
}
break;
default:
break;
}
}
return siResult;
}
else
{
return( eDSAuthAccountDisabled );
}
}
switch ( uiAuthMethod )
{
case kAuthGetPolicy:
case kAuthGetEffectivePolicy:
case kAuthSetPolicyAsRoot:
case kAuthSetPasswdAsRoot:
siResult = CNiPlugIn::DoShadowHashAuth( inNodeRef, inAuthMethod, inContext, inOutContinueData,
inAuthData, outAuthData, inAuthOnly, isSecondary, inAuthAuthorityData,
inGUIDString, inNativeRecType );
break;
default:
siResult = eDSAuthFailed;
}
}
return siResult;
}
#pragma mark -
#pragma mark Basic
#pragma mark -
sInt32 CNiPlugIn::DoBasicAuth ( tDirNodeReference inNodeRef, tDataNodePtr inAuthMethod,
sNIContextData* inContext,
sNIContinueData** inOutContinueData,
tDataBufferPtr inAuthData, tDataBufferPtr outAuthData,
bool inAuthOnly, bool isSecondary, const char* inAuthAuthorityData,
const char* inGUIDString, const char* inNativeRecType )
{
sInt32 siResult = eDSNoErr;
uInt32 uiAuthMethod = 0;
try
{
if ( inContext == nil ) throw( (sInt32)eDSInvalidNodeRef );
DBGLOG( kLogPlugin, "DoBasicAuth::" );
if (inAuthMethod != nil)
{
DBGLOG1( kLogPlugin, "NetInfo PlugIn: Attempting use of authentication method %s", inAuthMethod->fBufferData );
}
siResult = dsGetAuthMethodEnumValue( inAuthMethod, &uiAuthMethod );
if ( siResult == eDSNoErr )
{
switch( uiAuthMethod )
{
case kAuthGetGlobalPolicy:
case kAuthSetGlobalPolicy:
case kAuthGetPolicy:
case kAuthSetPolicy:
siResult = eDSAuthMethodNotSupported;
break;
case kAuthNativeMethod:
case kAuthNativeNoClearText:
case kAuthNativeClearTextOK:
if ( outAuthData == nil ) throw( (sInt32)eDSNullAuthStepData );
siResult = DoUnixCryptAuth( inContext, inAuthData, inAuthOnly, inNativeRecType );
if ( siResult == eDSNoErr )
{
if ( outAuthData->fBufferSize > ::strlen( kDSStdAuthCrypt ) )
{
::strcpy( outAuthData->fBufferData, kDSStdAuthCrypt );
}
}
else if ( (siResult != eDSAuthFailed) && (siResult != eDSInvalidBuffFormat) )
{
siResult = DoNodeNativeAuth( inContext, inAuthData, inAuthOnly, inNativeRecType );
if ( siResult == eDSNoErr )
{
if ( outAuthData->fBufferSize > ::strlen( kDSStdAuth2WayRandom ) )
{
::strcpy( outAuthData->fBufferData, kDSStdAuth2WayRandom );
}
}
}
break;
case kAuthClearText:
case kAuthCrypt:
siResult = DoUnixCryptAuth( inContext, inAuthData, inAuthOnly, inNativeRecType );
break;
case kAuthSetPasswd:
siResult = DoSetPassword( inContext, inAuthData, inNativeRecType );
break;
case kAuthSetPasswdAsRoot:
siResult = DoSetPasswordAsRoot( inContext, inAuthData, inNativeRecType );
break;
case kAuthChangePasswd:
siResult = DoChangePassword( inContext, inAuthData, isSecondary, inNativeRecType );
break;
#ifdef TIM_CLIENT_PRESENT
case kAuthSMB_NT_Key:
case kAuthSMB_LM_Key:
siResult = DoTimSMBAuth( inContext, inAuthData, uiAuthMethod );
break;
case kAuth2WayRandom:
siResult = DoTimMultiPassAuth( inNodeRef, inAuthMethod, inContext,
inOutContinueData, inAuthData,
outAuthData, inAuthOnly );
break;
case kAuthAPOP:
case kAuthCRAM_MD5:
siResult = ValidateDigest( inContext, inAuthData, uiAuthMethod );
break;
#endif
default:
siResult = eDSAuthFailed;
}
}
}
catch( sInt32 err )
{
siResult = err;
}
return( siResult );
}
sInt32 CNiPlugIn::DoSetPassword ( sNIContextData *inContext, tDataBuffer *inAuthData, const char *inNativeRecType )
{
sInt32 siResult = eDSAuthFailed;
bool bFreePropList = false;
bool bResetCache = false;
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;
ni_proplist niPropList;
#ifdef TIM_CLIENT_PRESENT
TIMHandle *pTimHndl = nil;
#endif
void *aNIDomain = NULL;
gNetInfoMutex->Wait();
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 );
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;
aNIDomain = RetrieveNIDomain(inContext);
if (aNIDomain != NULL)
{
#ifdef TIM_CLIENT_PRESENT
if ( !inContext->bIsLocal && IsTimRunning() )
{
pTimHndl = ::timServerForDomain( aNIDomain );
if ( pTimHndl != nil )
{
siResult = ::timSetPasswordWithTIMHandle( pTimHndl, rootName, rootPwd, userName, userPwd );
timHandleFree( pTimHndl );
if ( siResult != eDSNoErr )
{
}
}
#ifdef DEBUG
if ( siResult != TimStatusOK )
{
DBGLOG1( kLogPlugin, "-- timSetPasswordForUser -- failed with %l.", siResult );
}
#endif
siResult = MapAuthResult( siResult );
}
else
#endif
{
char salt[3];
char hashPwd[ 32 ];
ni_id niDirID;
ni_index niWhere = 0;
ni_namelist niValue;
char *niPwd = nil;
DBGLOG( kLogPlugin, "Attempting UNIX Crypt password change" );
siResult = IsValidRecordName ( rootName, inNativeRecType, aNIDomain, niDirID );
#ifdef DEBUG
if ( siResult != eDSNoErr ) throw( (sInt32)eDSAuthUnknownUser );
#else
if ( siResult != eDSNoErr ) throw( (sInt32)eDSAuthFailed );
#endif
siResult = ::ni_read( aNIDomain, &niDirID, &niPropList );
#ifdef DEBUG
if ( siResult != eDSNoErr ) throw( (sInt32)eDSAuthUnknownUser );
if ( niPropList.ni_proplist_val == nil ) throw( (sInt32)eDSAuthUnknownUser );
#else
if ( siResult != eDSNoErr ) throw( (sInt32)eDSAuthFailed );
if ( niPropList.ni_proplist_val == nil ) throw( (sInt32)eDSAuthFailed );
#endif
bFreePropList = true;
niWhere = ::ni_proplist_match( niPropList, "uid", nil );
if (niWhere == NI_INDEX_NULL) throw( (sInt32)eDSAuthFailed );
siResult = eDSAuthFailed;
niValue = niPropList.ni_proplist_val[ niWhere ].nip_val;
if ( !( ( (niValue.ni_namelist_val[ 0 ] != NULL) && (strcmp( "0", niValue.ni_namelist_val[ 0 ]) == 0) ) ||
(UserIsAdmin(rootName, inContext)) ) )
{
throw( (sInt32)eDSAuthFailed );
}
niWhere = ::ni_proplist_match( niPropList, "passwd", nil );
#ifdef DEBUG
if (niWhere == NI_INDEX_NULL) throw( (sInt32)eDSAuthBadPassword );
siResult = eDSAuthBadPassword;
#else
if (niWhere == NI_INDEX_NULL) throw( (sInt32)eDSAuthFailed );
siResult = eDSAuthFailed;
#endif
niValue = niPropList.ni_proplist_val[ niWhere ].nip_val;
if ((niValue.ni_namelist_len > 0) && (niValue.ni_namelist_val != nil))
{
niPwd = niPropList.ni_proplist_val[ niWhere ].nip_val.ni_namelist_val[ 0 ];
}
else
{
niPwd = (char*)""; }
if (::strcmp(niPwd,"") != 0)
{
salt[ 0 ] = niPwd[0];
salt[ 1 ] = niPwd[1];
salt[ 2 ] = '\0';
bzero(hashPwd, 32);
::strcpy( hashPwd, ::crypt( rootPwd, salt ) );
siResult = eDSAuthFailed;
if ( ::strcmp( hashPwd, niPwd ) == 0 )
{
siResult = eDSNoErr;
}
bzero(hashPwd, 32);
}
else {
if (::strcmp(rootPwd,"") != 0)
{
siResult = eDSNoErr;
}
}
if (siResult == eDSNoErr)
{
if ( inContext->bIsLocal ) {
MigrateToShadowHash(aNIDomain, &niDirID, &niPropList, userName, userPwd, bResetCache);
}
else
{
const char *saltchars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./";
bzero(hashPwd, 32);
if ( ::strlen(userPwd) > 0 )
{
::srandom(getpid() + time(0));
salt[0] = saltchars[random() % 64];
salt[1] = saltchars[random() % 64];
salt[2] = '\0';
::strcpy( hashPwd, ::crypt( userPwd, salt ) );
}
siResult = IsValidRecordName ( userName, inNativeRecType, aNIDomain, niDirID );
#ifdef DEBUG
if ( siResult != eDSNoErr ) throw( (sInt32)eDSAuthUnknownUser );
#else
if ( siResult != eDSNoErr ) throw( (sInt32)eDSAuthFailed );
#endif
::ni_proplist_free( &niPropList );
bFreePropList = false;
siResult = ::ni_read( aNIDomain, &niDirID, &niPropList );
#ifdef DEBUG
if ( siResult != eDSNoErr ) throw( (sInt32)eDSAuthUnknownUser );
#else
if ( siResult != eDSNoErr ) throw( (sInt32)eDSAuthFailed );
#endif
bFreePropList = true;
niWhere = ::ni_proplist_match( niPropList, "passwd", nil );
if ( niWhere != NI_INDEX_NULL )
{
niValue = niPropList.ni_proplist_val[ niWhere ].nip_val;
siResult = NiLib2::DestroyDirVal( aNIDomain, &niDirID, (char*)"passwd", niValue );
}
siResult = NiLib2::InsertDirVal( aNIDomain, &niDirID, (char*)"passwd", hashPwd, 0 );
siResult = MapNetInfoErrors( siResult );
bzero(hashPwd, 32);
}
}
}
}
else
{
throw( (sInt32)eDSInvalidSession );
}
}
catch( sInt32 err )
{
siResult = err;
}
if ( bFreePropList )
{
::ni_proplist_free( &niPropList );
}
gNetInfoMutex->Signal();
if ( bResetCache )
{
gSrvrCntl->HandleMemberDaemonFlushCache();
}
DSFreeString( userName );
DSFreePassword( userPwd );
DSFreeString( rootName );
DSFreePassword( rootPwd );
return( siResult );
}
sInt32 CNiPlugIn::DoSetPasswordAsRoot ( sNIContextData *inContext, tDataBuffer *inAuthData, const char *inNativeRecType )
{
sInt32 siResult = eDSAuthFailed;
bool bFreePropList = false;
bool bResetCache = false;
char *pData = nil;
char *userName = nil;
uInt32 userNameLen = 0;
char *newPasswd = nil;
uInt32 newPwdLen = 0;
uInt32 offset = 0;
uInt32 buffSize = 0;
uInt32 buffLen = 0;
ni_proplist niPropList;
#ifdef TIM_CLIENT_PRESENT
char *pTag = nil;
uInt32 uiCount = 0;
uInt32 i = 0;
sInt32 timResult = eDSAuthFailed;
bool done = false;
TIMHandle *pTimHndl = nil;
Buffer *pUserBuff = nil;
Buffer *pBuffArray = nil;
Buffer *pTmpBuff = nil;
#endif
void *aNIDomain = nil;
gNetInfoMutex->Wait();
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 );
newPasswd = (char *)::calloc( 1, newPwdLen + 1 );
::memcpy( newPasswd, pData, newPwdLen );
pData += newPwdLen;
offset += newPwdLen;
if ( inContext->fEffectiveUID != 0 )
{
if ((inContext->fAuthenticatedUserName == NULL)
|| ((::strcmp(inContext->fAuthenticatedUserName, "root") != 0)
&& (::strcmp(inContext->fAuthenticatedUserName, userName) != 0)))
{
throw( (sInt32)eDSPermissionError );
}
}
aNIDomain = RetrieveNIDomain(inContext);
if (aNIDomain != NULL)
{
#ifdef TIM_CLIENT_PRESENT
if ( !inContext->bIsLocal && IsTimRunning() )
{
pTimHndl = ::timServerForDomain( aNIDomain );
if ( pTimHndl != nil )
{
pUserBuff = ::bufferFromString( userName );
if ( pUserBuff != nil )
{
timResult = ::timGetTagsForUser( pTimHndl, pUserBuff, &pBuffArray );
if ( timResult == TimStatusOK )
{
uiCount = bufferArrayCount( pBuffArray );
while ( (i < uiCount) && !done )
{
pTmpBuff = bufferArrayBufferAtIndex( pBuffArray, i++ );
if ( pTmpBuff != nil )
{
pTag = bufferToString( pTmpBuff );
if ( pTag != nil )
{
timResult = ::timSetPasswordForUserAsRoot( userName, newPasswd, pTag );
#ifdef DEBUG
if ( timResult != TimStatusOK )
{
DBGLOG1( kLogPlugin, "-- timSetPasswordForUserAsRoot -- failed with %l.", timResult );
}
#endif
if ( timResult == TimStatusOK )
{
siResult = eDSNoErr;
done = true;
}
free( pTag );
pTag = nil;
}
::bufferRelease( pTmpBuff );
pTmpBuff = nil;
}
}
}
if ( pBuffArray != nil ) {
::bufferRelease( pBuffArray );
pBuffArray = nil;
}
::bufferRelease( pUserBuff );
pUserBuff = nil;
}
::timHandleFree( pTimHndl );
pTimHndl = nil;
} }
else
#endif
{
char salt[3];
char hashPwd[ 32 ];
ni_id niDirID;
ni_index niWhere = 0;
ni_namelist niValue;
DBGLOG( kLogPlugin, "Attempting UNIX Crypt password change" );
siResult = IsValidRecordName ( userName, inNativeRecType, aNIDomain, niDirID );
#ifdef DEBUG
if ( siResult != eDSNoErr ) throw( (sInt32)eDSAuthUnknownUser );
#else
if ( siResult != eDSNoErr ) throw( (sInt32)eDSAuthFailed );
#endif
siResult = ::ni_read( aNIDomain, &niDirID, &niPropList );
#ifdef DEBUG
if ( siResult != eDSNoErr ) throw( (sInt32)eDSAuthUnknownUser );
#else
if ( siResult != eDSNoErr ) throw( (sInt32)eDSAuthFailed );
#endif
bFreePropList = true;
niWhere = ::ni_proplist_match( niPropList, "passwd", nil );
if (siResult == eDSNoErr)
{
if ( inContext->bIsLocal ) {
MigrateToShadowHash(aNIDomain, &niDirID, &niPropList, userName, newPasswd, bResetCache);
}
else
{
const char *saltchars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./";
bzero(hashPwd, 32);
if ( ::strlen(newPasswd) > 0 )
{
::srandom(getpid() + time(0));
salt[0] = saltchars[random() % 64];
salt[1] = saltchars[random() % 64];
salt[2] = '\0';
::strcpy( hashPwd, ::crypt( newPasswd, salt ) );
}
if ( niWhere != NI_INDEX_NULL )
{
niValue = niPropList.ni_proplist_val[ niWhere ].nip_val;
siResult = NiLib2::DestroyDirVal( aNIDomain, &niDirID, (char*)"passwd", niValue );
}
siResult = NiLib2::InsertDirVal( aNIDomain, &niDirID, (char*)"passwd", hashPwd, 0 );
siResult = MapNetInfoErrors( siResult );
bzero(hashPwd, 32);
}
}
}
}
else
{
throw( (sInt32)eDSInvalidSession );
}
}
catch( sInt32 err )
{
siResult = err;
}
if ( bFreePropList )
{
::ni_proplist_free( &niPropList );
}
gNetInfoMutex->Signal();
if ( bResetCache )
{
gSrvrCntl->HandleMemberDaemonFlushCache();
}
if ( userName != nil )
{
free( userName );
userName = nil;
}
if ( newPasswd != nil )
{
bzero(newPasswd, strlen(newPasswd));
free( newPasswd );
newPasswd = nil;
}
return( siResult );
}
sInt32 CNiPlugIn::DoChangePassword ( sNIContextData *inContext, tDataBuffer *inAuthData,
bool isSecondary, const char *inNativeRecType )
{
sInt32 siResult = eDSAuthFailed;
#ifdef TIM_CLIENT_PRESENT
TIMHandle *timHandle = nil;
#endif
bool bFreePropList = false;
bool bResetCache = false;
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;
void *domain = nil;
ni_proplist niPropList;
gNetInfoMutex->Wait();
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 );
newPwd = (char *)::calloc( 1, newPwdLen + 1 );
::memcpy( newPwd, pData, newPwdLen );
pData += newPwdLen;
offset += newPwdLen;
#ifdef TIM_CLIENT_PRESENT
if ( !inContext->bIsLocal && IsTimRunning() )
{
void* aNIDomain = RetrieveNIDomain(inContext);
if (aNIDomain != NULL)
{
timHandle = ::timServerForDomain( aNIDomain );
if ( timHandle == nil ) throw( (sInt32)eDSAuthFailed );
siResult = ::timSetPasswordWithTIMHandle( timHandle, name, oldPwd, name, newPwd );
#ifdef DEBUG
if ( siResult != TimStatusOK )
{
DBGLOG1( kLogPlugin, "-- timSetPassword -- failed with %l.", siResult );
}
#endif
siResult = MapAuthResult( siResult );
::timHandleFree( timHandle );
timHandle = nil;
}
else
{
siResult = eDSInvalidSession;
}
}
else
#endif
{
char salt[3];
char hashPwd[ 32 ];
ni_id niDirID;
ni_index niWhere = 0;
ni_namelist niValue;
char *niPwd = nil;
ni_status niStatus = NI_OK;
DBGLOG( kLogPlugin, "Attempting UNIX Crypt password change" );
if ( inContext->fDomainPath == nil ) throw( (sInt32)eDSAuthFailed );
niStatus = ::ni_open( nil, inContext->fDomainPath, &domain );
if ( niStatus != 0) throw( (sInt32)eDSAuthFailed );
DBGLOG1( kLogPlugin, "CNiPlugIn::DoChangePassword: <ni_open> opened on the netinfo node %s for changing password", inContext->fDomainPath );
niStatus = ::ni_setuser( domain, name );
niStatus = ::ni_setpassword( domain, oldPwd );
siResult = IsValidRecordName ( name, inNativeRecType, domain, niDirID );
#ifdef DEBUG
if ( siResult != eDSNoErr ) throw( (sInt32)eDSAuthUnknownUser );
#else
if ( siResult != eDSNoErr ) throw( (sInt32)eDSAuthFailed );
#endif
siResult = ::ni_read( domain, &niDirID, &niPropList );
#ifdef DEBUG
if ( siResult != eDSNoErr ) throw( (sInt32)eDSAuthUnknownUser );
if ( niPropList.ni_proplist_val == nil ) throw( (sInt32)eDSAuthUnknownUser );
#else
if ( siResult != eDSNoErr ) throw( (sInt32)eDSAuthFailed );
if ( niPropList.ni_proplist_val == nil ) throw( (sInt32)eDSAuthFailed );
#endif
bFreePropList = true;
niWhere = ::ni_proplist_match( niPropList, "passwd", nil );
#ifdef DEBUG
if (niWhere == NI_INDEX_NULL) throw( (sInt32)eDSAuthBadPassword );
siResult = eDSAuthBadPassword;
#else
if (niWhere == NI_INDEX_NULL) throw( (sInt32)eDSAuthFailed );
siResult = eDSAuthFailed;
#endif
niValue = niPropList.ni_proplist_val[ niWhere ].nip_val;
if ((niValue.ni_namelist_len > 0) && (niValue.ni_namelist_val != nil))
{
niPwd = niPropList.ni_proplist_val[ niWhere ].nip_val.ni_namelist_val[ 0 ];
}
else
{
niPwd = (char*)""; }
siResult = NiLib2::ValidateDir( name, &niPropList );
if ( siResult != NI_OK )
{
siResult = NiLib2::ValidateName( name, &niPropList, niWhere );
}
if ( siResult != eDSNoErr )
{
siResult = MapNetInfoErrors( siResult );
}
else if ( !isSecondary )
{
siResult = eDSAuthFailed;
if (::strcmp(niPwd,"") != 0)
{
salt[ 0 ] = niPwd[0];
salt[ 1 ] = niPwd[1];
salt[ 2 ] = '\0';
bzero(hashPwd, 32);
::strcpy( hashPwd, ::crypt( oldPwd, salt ) );
if ( ::strcmp( hashPwd, niPwd ) == 0 )
{
siResult = eDSNoErr;
}
bzero(hashPwd, 32);
}
else {
if (::strcmp(oldPwd,"") == 0)
{
siResult = eDSNoErr;
}
}
}
if (siResult == eDSNoErr)
{
if ( inContext->bIsLocal ) {
MigrateToShadowHash(domain, &niDirID, &niPropList, name, newPwd, bResetCache);
}
else
{
const char *saltchars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./";
bzero(hashPwd, 32);
if ( ::strlen(newPwd) > 0 )
{
::srandom(getpid() + time(0));
salt[0] = saltchars[random() % 64];
salt[1] = saltchars[random() % 64];
salt[2] = '\0';
::strcpy( hashPwd, ::crypt( newPwd, salt ) );
}
siResult = NiLib2::DestroyDirVal( domain, &niDirID, (char*)"passwd", niValue );
siResult = NiLib2::InsertDirVal( domain, &niDirID, (char*)"passwd", hashPwd, 0 );
siResult = MapNetInfoErrors( siResult );
bzero(hashPwd, 32);
}
}
}
}
catch( sInt32 err )
{
siResult = err;
}
if ( bFreePropList )
{
ni_proplist_free( &niPropList );
}
if ( domain != nil )
{
ni_free( domain );
domain = nil;
}
gNetInfoMutex->Signal();
if ( bResetCache )
{
gSrvrCntl->HandleMemberDaemonFlushCache();
}
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 );
}
#pragma mark -
#pragma mark Shadow Hash
#pragma mark -
sInt32 CNiPlugIn::DoShadowHashAuth ( tDirNodeReference inNodeRef, tDataNodePtr inAuthMethod,
sNIContextData* inContext,
sNIContinueData** inOutContinueData,
tDataBufferPtr inAuthData, tDataBufferPtr outAuthData,
bool inAuthOnly, bool isSecondary,
const char* inAuthAuthorityData, const char* inGUIDString,
const char* inNativeRecType )
{
sInt32 siResult = eDSAuthFailed;
uInt32 uiAuthMethod = 0;
char *pUserName = nil;
char *pNewPassword = nil;
char *pOldPassword = nil;
unsigned char *pNTLMDigest = nil;
unsigned long ntlmDigestLen = 0;
unsigned char *pCramResponse = NULL;
unsigned long cramResponseLen = 0;
char *pSambaName = nil;
char *pDomain = nil;
char *pAdminUser = nil;
char *pAdminPassword = nil;
unsigned char P21[kHashShadowKeyLength] = {0};
unsigned char C8[kHashShadowChallengeLength] = {0};
unsigned char C16[16] = {0};
unsigned char *PeerC16 = NULL;
unsigned char P24[kHashShadowResponseLength] = {0};
unsigned char P24Input[kHashShadowResponseLength] = {0};
unsigned char GeneratedNTLM[EVP_MAX_MD_SIZE] = {0};
char MSCHAP2Response[MS_AUTH_RESPONSE_LENGTH+1] = {0};
tDataListPtr dataList = NULL;
char *path = NULL;
unsigned char hashes[kHashTotalLength] = {0};
unsigned char generatedHashes[kHashTotalLength] = {0};
uInt32 hashLength = kHashTotalLength;
sInt32 hashesLengthFromFile = 0;
tDataNodePtr secureHashNode = NULL;
unsigned char secureHash[kHashSaltedSHA1Length] = {0};
unsigned int itemCount = 0;
char *nativeAttrType = NULL;
char *policyStr = NULL;
struct timespec modDateOfPassword;
struct timeval modDateAssist;
sHashState state;
char *stateFilePath = NULL;
PWGlobalAccessFeatures globalAccess;
unsigned long policyStrLen = 0;
sHashAuthFailed *pHashAuthFailed = nil;
time_t now;
digest_context_t digestContext = {0};
bool bFetchHashFiles = false;
int keySize = 0;
unsigned int userLevelHashList = sHashList;
char *challenge = NULL;
char *apopResponse = NULL;
try
{
if ( inAuthData == nil ) throw( (sInt32)eDSNullAuthStepData );
if ( inContext == nil ) throw( (sInt32)eDSInvalidNodeRef );
bzero( &state, sizeof(state) );
DBGLOG( kLogPlugin, "DoShadowHashAuth::" );
if (inAuthMethod != nil)
{
DBGLOG1( kLogPlugin, "NetInfo PlugIn: Attempting use of authentication method %s", inAuthMethod->fBufferData );
}
siResult = dsGetAuthMethodEnumValue( inAuthMethod, &uiAuthMethod );
if ( siResult == eDSNoErr )
{
if ( inAuthAuthorityData != nil && inAuthAuthorityData[0] != '\0' )
{
siResult = GetHashSecurityLevelForUser( inAuthAuthorityData, &userLevelHashList );
if ( siResult != eDSNoErr )
{
DBGLOG1( kLogPlugin, "DoShadowHashAuth - encountered invalid record hash list: %s", inAuthAuthorityData );
userLevelHashList = sHashList;
siResult = eDSNoErr;
}
}
switch( uiAuthMethod )
{
case kAuthDIGEST_MD5:
siResult = UnpackDigestBuffer( inAuthData, &pUserName, &digestContext );
bFetchHashFiles = (siResult == eDSNoErr);
break;
case kAuthCRAM_MD5:
if ( (userLevelHashList & kNiPluginHashCRAM_MD5) == 0 )
throw( (sInt32)eDSAuthFailed );
siResult = UnpackCramBuffer( inAuthData, &pUserName, &challenge, &pCramResponse, &cramResponseLen );
bFetchHashFiles = (siResult == eDSNoErr);
break;
case kAuthAPOP:
if ( (userLevelHashList & kNiPluginHashRecoverable) == 0 )
throw( (sInt32)eDSAuthFailed );
siResult = UnpackAPOPBuffer( inAuthData, &pUserName, &challenge, &apopResponse );
bFetchHashFiles = (siResult == eDSNoErr);
break;
case kAuthSMB_NT_Key:
if ( (userLevelHashList & kNiPluginHashNT) == 0 )
throw( (sInt32)eDSAuthFailed );
siResult = UnpackSambaBuffer( inAuthData, &pUserName, C8, P24Input );
bFetchHashFiles = (siResult == eDSNoErr);
break;
case kAuthSMB_LM_Key:
if ( (userLevelHashList & kNiPluginHashLM) == 0 )
throw( (sInt32)eDSAuthFailed );
siResult = UnpackSambaBuffer( inAuthData, &pUserName, C8, P24Input );
bFetchHashFiles = (siResult == eDSNoErr);
break;
case kAuthNTLMv2:
if ( (userLevelHashList & kNiPluginHashNT) == 0 )
throw( (sInt32)eDSAuthFailed );
siResult = UnpackNTLMv2Buffer( inAuthData, &pUserName, C8, &pNTLMDigest, &ntlmDigestLen, &pSambaName, &pDomain );
bFetchHashFiles = (siResult == eDSNoErr);
break;
case kAuthMSCHAP2:
if ( (userLevelHashList & kNiPluginHashNT) == 0 )
throw( (sInt32)eDSAuthFailed );
if ( outAuthData == NULL )
throw( (sInt32)eDSNullAuthStepData );
if ( outAuthData->fBufferSize < 4 + MS_AUTH_RESPONSE_LENGTH )
throw( (sInt32)eDSBufferTooSmall );
siResult = UnpackMSCHAPv2Buffer( inAuthData, &pUserName, C16, &PeerC16, &pNTLMDigest, &ntlmDigestLen, &pSambaName );
bFetchHashFiles = (siResult == eDSNoErr);
break;
case kAuthVPN_PPTPMasterKeys:
if ( outAuthData == NULL )
throw( (sInt32)eDSNullAuthStepData );
siResult = UnpackMPPEKeyBuffer( inAuthData, &pUserName, P24Input, &keySize );
if ( outAuthData->fBufferSize < (unsigned long)(8 + keySize*2) )
throw( (sInt32)eDSBufferTooSmall );
bFetchHashFiles = (siResult == eDSNoErr);
break;
case kAuthSecureHash:
if ( (userLevelHashList & kNiPluginHashSaltedSHA1) == 0 )
throw( (sInt32)eDSAuthFailed );
dataList = dsAuthBufferGetDataListAllocPriv(inAuthData);
if ( dataList == nil ) throw( (sInt32)eDSInvalidBuffFormat );
if ( dsDataListGetNodeCountPriv(dataList) != 2 ) throw( (sInt32)eDSInvalidBuffFormat );
pUserName = dsDataListGetNodeStringPriv(dataList, 1);
if ( pUserName == nil ) throw( (sInt32)eDSInvalidBuffFormat );
if ( strlen(pUserName) < 1 ) throw( (sInt32)eDSInvalidBuffFormat );
siResult = dsDataListGetNodePriv(dataList, 2, &secureHashNode);
if ( secureHashNode == nil ) throw( (sInt32)eDSInvalidBuffFormat );
if ( secureHashNode->fBufferLength != kHashSaltedSHA1Length ) throw( (sInt32)eDSInvalidBuffFormat);
if ( siResult != eDSNoErr ) throw( (sInt32)eDSInvalidBuffFormat );
memmove(secureHash, ((tDataBufferPriv*)secureHashNode)->fBufferData, secureHashNode->fBufferLength);
bFetchHashFiles = true;
break;
case kAuthWriteSecureHash:
dataList = dsAuthBufferGetDataListAllocPriv(inAuthData);
if ( dataList == nil ) throw( (sInt32)eDSInvalidBuffFormat );
if ( dsDataListGetNodeCountPriv(dataList) != 2 ) throw( (sInt32)eDSInvalidBuffFormat );
pUserName = dsDataListGetNodeStringPriv(dataList, 1);
if ( pUserName == nil ) throw( (sInt32)eDSInvalidBuffFormat );
if ( strlen(pUserName) < 1 ) throw( (sInt32)eDSInvalidBuffFormat );
siResult = dsDataListGetNodePriv(dataList, 2, &secureHashNode);
if ( secureHashNode == nil ) throw( (sInt32)eDSInvalidBuffFormat );
if ( secureHashNode->fBufferLength != kHashSaltedSHA1Length ) throw( (sInt32)eDSInvalidBuffFormat);
if ( siResult != eDSNoErr ) throw( (sInt32)eDSInvalidBuffFormat );
memmove(secureHash, ((tDataBufferPriv*)secureHashNode)->fBufferData, secureHashNode->fBufferLength);
break;
case kAuthReadSecureHash:
if ( outAuthData == nil ) throw( (sInt32)eDSNullAuthStepData );
dataList = dsAuthBufferGetDataListAllocPriv(inAuthData);
if ( dataList == nil ) throw( (sInt32)eDSInvalidBuffFormat );
if ( dsDataListGetNodeCountPriv(dataList) != 1 ) throw( (sInt32)eDSInvalidBuffFormat );
pUserName = dsDataListGetNodeStringPriv(dataList, 1);
if ( pUserName == nil ) throw( (sInt32)eDSInvalidBuffFormat );
if ( strlen(pUserName) < 1 ) throw( (sInt32)eDSInvalidBuffFormat );
break;
case kAuthSetPasswd:
siResult = Get2FromBuffer( inAuthData, &dataList, &pUserName, &pNewPassword, &itemCount );
if ( siResult == eDSNoErr )
{
if ( itemCount != 4 )
throw( (sInt32)eDSInvalidBuffFormat );
bFetchHashFiles = true;
siResult = GetUserPolicies( inContext, inNativeRecType, pUserName, NULL, &policyStr );
}
break;
case kAuthSetPasswdAsRoot:
siResult = Get2FromBuffer(inAuthData, &dataList, &pUserName, &pNewPassword, &itemCount );
if ( siResult == eDSNoErr )
{
if ( itemCount != 2 && itemCount != 4)
throw( (sInt32)eDSInvalidBuffFormat );
}
break;
case kAuthSetPolicyAsRoot:
siResult = Get2FromBuffer(inAuthData, &dataList, &pUserName, &pNewPassword, &itemCount );
if ( siResult != eDSNoErr )
throw( siResult );
if ( itemCount != 2 || pNewPassword == NULL || pNewPassword[0] == '\0' )
throw( (sInt32)eDSInvalidBuffFormat );
siResult = ReadStateFile(pUserName, inGUIDString, &modDateOfPassword, &path, &stateFilePath, &state, &hashesLengthFromFile);
break;
case kAuthChangePasswd:
siResult = Get2FromBuffer(inAuthData, &dataList, &pUserName, &pOldPassword, &itemCount );
if ( siResult != eDSNoErr )
throw( siResult );
if ( itemCount != 3 )
throw( (sInt32)eDSInvalidBuffFormat );
pNewPassword = dsDataListGetNodeStringPriv(dataList, 3);
if ( pNewPassword == nil ) throw( (sInt32)eDSInvalidBuffFormat );
bFetchHashFiles = true;
if ( siResult == eDSNoErr )
siResult = GetUserPolicies( inContext, inNativeRecType, pUserName, NULL, &policyStr );
break;
case kAuthSetShadowHashWindows:
case kAuthSetShadowHashSecure:
case kAuthNativeClearTextOK:
case kAuthNativeNoClearText:
siResult = Get2FromBuffer(inAuthData, &dataList, &pUserName, &pOldPassword, &itemCount );
if ( siResult == eDSNoErr )
{
bFetchHashFiles = true;
siResult = GetUserPolicies( inContext, inNativeRecType, pUserName, NULL, &policyStr );
}
break;
case kAuthSetPasswdCheckAdmin:
{
char *pUserToChangeName = NULL;
bool modifyingSelf;
dataList = dsAuthBufferGetDataListAllocPriv(inAuthData);
if ( dataList == nil ) throw( (sInt32)eDSInvalidBuffFormat );
itemCount = dsDataListGetNodeCountPriv(dataList);
if ( itemCount != 4 ) throw( (sInt32)eDSInvalidBuffFormat );
pUserName = dsDataListGetNodeStringPriv(dataList, 3);
if ( pUserName == nil ) throw( (sInt32)eDSInvalidBuffFormat );
if ( strlen(pUserName) < 1 ) throw( (sInt32)eDSInvalidBuffFormat );
pOldPassword = dsDataListGetNodeStringPriv(dataList, 4);
if ( pOldPassword == nil )
throw( (sInt32)eDSInvalidBuffFormat );
if ( strlen(pOldPassword) < 1 )
throw( (sInt32)eDSInvalidBuffFormat );
pUserToChangeName = dsDataListGetNodeStringPriv(dataList, 1);
if ( pUserToChangeName == nil ) throw( (sInt32)eDSInvalidBuffFormat );
if ( strlen(pUserToChangeName) < 1 ) throw( (sInt32)eDSInvalidBuffFormat );
modifyingSelf = (pUserToChangeName != NULL) && (pUserName != NULL) && (strcmp(pUserToChangeName, pUserName) == 0);
if ( !modifyingSelf && !UserIsAdmin(pUserName,inContext) )
throw( (sInt32)eDSPermissionError );
bFetchHashFiles = true;
siResult = GetUserPolicies( inContext, inNativeRecType, pUserName, NULL, &policyStr );
}
break;
case kAuthGetPolicy:
if ( outAuthData == nil ) throw( (sInt32)eDSNullAuthStepData );
outAuthData->fBufferLength = 0;
dataList = dsAuthBufferGetDataListAllocPriv(inAuthData);
if ( dataList == nil ) throw( (sInt32)eDSInvalidBuffFormat );
itemCount = dsDataListGetNodeCountPriv(dataList);
if ( itemCount != 3 ) throw( (sInt32)eDSInvalidBuffFormat );
pUserName = dsDataListGetNodeStringPriv(dataList, 3);
if ( pUserName == nil ) throw( (sInt32)eDSInvalidBuffFormat );
if ( strlen(pUserName) < 1 ) throw( (sInt32)eDSInvalidBuffFormat );
siResult = ReadStateFile(pUserName, inGUIDString, &modDateOfPassword, &path, &stateFilePath, &state, &hashesLengthFromFile);
DSFreeString( stateFilePath ); break;
case kAuthSetPolicy:
dataList = dsAuthBufferGetDataListAllocPriv(inAuthData);
if ( dataList == nil ) throw( (sInt32)eDSInvalidBuffFormat );
itemCount = dsDataListGetNodeCountPriv(dataList);
if ( itemCount != 4 ) throw( (sInt32)eDSInvalidBuffFormat );
pUserName = dsDataListGetNodeStringPriv(dataList, 3);
if ( pUserName == nil ) throw( (sInt32)eDSInvalidBuffFormat );
if ( pUserName[0] == '\0' ) throw( (sInt32)eDSInvalidBuffFormat );
pNewPassword = dsDataListGetNodeStringPriv(dataList, 4);
if ( pNewPassword == nil )
throw( (sInt32)eDSInvalidBuffFormat );
if ( pNewPassword[0] == '\0' )
throw( (sInt32)eDSInvalidBuffFormat );
siResult = ReadStateFile(pUserName, inGUIDString, &modDateOfPassword, &path, &stateFilePath, &state, &hashesLengthFromFile);
break;
case kAuthGetGlobalPolicy:
if ( outAuthData == nil )
throw( (sInt32)eDSNullAuthStepData );
outAuthData->fBufferLength = 0;
siResult = GetShadowHashGlobalPolicies( inContext, &globalAccess );
if ( siResult != eDSNoErr )
throw( siResult );
{
char policies[2048];
PWGlobalAccessFeaturesToString( &globalAccess, policies );
policyStrLen = strlen( policies );
if ( outAuthData->fBufferSize < 4 + policyStrLen )
throw( (sInt32)eDSBufferTooSmall );
outAuthData->fBufferLength = 4 + policyStrLen;
memcpy( outAuthData->fBufferData, &policyStrLen, 4 );
memcpy( outAuthData->fBufferData + 4, policies, policyStrLen );
}
if ( outAuthData->fBufferLength == 0 )
throw( (sInt32)eDSEmptyAttribute );
break;
case kAuthSetGlobalPolicy:
GetShadowHashGlobalPolicies( inContext, &globalAccess );
dataList = dsAuthBufferGetDataListAllocPriv(inAuthData);
if ( dataList == nil ) throw( (sInt32)eDSInvalidBuffFormat );
pNewPassword = dsDataListGetNodeStringPriv(dataList, 3);
if ( pNewPassword == nil )
throw( (sInt32)eDSInvalidBuffFormat );
if ( strlen(pNewPassword) < 1 )
throw( (sInt32)eDSInvalidBuffFormat );
StringToPWGlobalAccessFeatures( pNewPassword, &globalAccess );
siResult = SetShadowHashGlobalPolicies( inContext, &globalAccess );
break;
default:
break;
}
if ( bFetchHashFiles )
{
siResult = ReadShadowHashAndStateFiles(pUserName, inGUIDString, hashes, &modDateOfPassword, &path, &stateFilePath, &state, &hashesLengthFromFile);
}
if ((siResult != eDSNoErr) && !(isSecondary && (uiAuthMethod == kAuthChangePasswd)))
{
throw( siResult );
}
switch( uiAuthMethod )
{
case kAuthGetGlobalPolicy:
case kAuthSetGlobalPolicy:
break;
case kAuthSetPolicy:
case kAuthSetPolicyAsRoot:
siResult = SetUserPolicies( inContext, inNativeRecType, pUserName, pNewPassword, &state );
break;
case kAuthGetPolicy:
siResult = GetUserPolicies( inContext, inNativeRecType, pUserName, &state, &policyStr );
if ( siResult != 0 ) throw( siResult );
if ( policyStr != NULL )
{
policyStrLen = strlen( policyStr );
if ( outAuthData->fBufferSize < 4 + policyStrLen )
throw( (sInt32)eDSBufferTooSmall );
outAuthData->fBufferLength = 4 + policyStrLen;
memcpy( outAuthData->fBufferData, &policyStrLen, 4 );
if ( policyStrLen > 0 )
strcpy( outAuthData->fBufferData + 4, policyStr );
}
break;
case kAuthDIGEST_MD5:
{
char *mutualDigest;
unsigned int mutualDigestLen;
unsigned long passwordLength;
siResult = UnobfuscateRecoverablePassword( hashes + kHashOffsetToRecoverable, (unsigned char **)&pOldPassword, &passwordLength );
if ( siResult == eDSNoErr )
{
siResult = digest_verify( &digestContext, pOldPassword, passwordLength, &mutualDigest, &mutualDigestLen );
switch( siResult )
{
case SASL_OK: siResult = eDSNoErr; break;
case SASL_NOMEM: siResult = eMemoryError; break;
default: siResult = eDSAuthFailed;
}
}
if ( siResult == eDSNoErr )
{
outAuthData->fBufferLength = 4 + digestContext.out_buf_len;
memcpy( outAuthData->fBufferData, &digestContext.out_buf_len, 4 );
if ( digestContext.out_buf_len > 0 )
memcpy( outAuthData->fBufferData + 4, digestContext.out_buf, digestContext.out_buf_len );
}
}
break;
case kAuthCRAM_MD5:
siResult = CRAM_MD5( hashes + kHashOffsetToCramMD5, challenge, pCramResponse );
break;
case kAuthAPOP:
{
unsigned long passwordLength;
siResult = UnobfuscateRecoverablePassword( hashes + kHashOffsetToRecoverable, (unsigned char **)&pOldPassword, &passwordLength );
if ( siResult == eDSNoErr )
siResult = Verify_APOP( pUserName, (unsigned char *)pOldPassword, passwordLength, challenge, apopResponse );
}
break;
case kAuthSMB_NT_Key:
memmove(P21, hashes, kHashShadowOneLength);
CalculateP24(P21, C8, P24);
if (memcmp(P24,P24Input,kHashShadowResponseLength) == 0)
{
siResult = eDSNoErr;
}
else
{
siResult = eDSAuthFailed;
}
break;
case kAuthSMB_LM_Key:
memmove(P21, hashes + kHashOffsetToLM, kHashShadowOneLength);
CalculateP24(P21, C8, P24);
if (memcmp(P24,P24Input,kHashShadowResponseLength) == 0)
{
siResult = eDSNoErr;
}
else
{
siResult = eDSAuthFailed;
}
break;
case kAuthNTLMv2:
if ( NTLMv2(GeneratedNTLM, hashes, pSambaName, pDomain, C8, pNTLMDigest + kShadowHashNTLMv2Length, ntlmDigestLen - kShadowHashNTLMv2Length) == 0 )
{
if ( memcmp(GeneratedNTLM, pNTLMDigest, kShadowHashNTLMv2Length) == 0 )
{
siResult = eDSNoErr;
}
else
{
siResult = eDSAuthFailed;
}
}
break;
case kAuthMSCHAP2:
siResult = MSCHAPv2( C16, PeerC16, pNTLMDigest, pSambaName, hashes, MSCHAP2Response );
if ( siResult == eDSNoErr )
{
outAuthData->fBufferLength = 4 + MS_AUTH_RESPONSE_LENGTH;
ntlmDigestLen = MS_AUTH_RESPONSE_LENGTH;
memcpy( outAuthData->fBufferData, &ntlmDigestLen, 4 );
memcpy( outAuthData->fBufferData + 4, MSCHAP2Response, MS_AUTH_RESPONSE_LENGTH );
}
break;
case kAuthVPN_PPTPMasterKeys:
if ( inContext->fEffectiveUID == 0 )
{
unsigned char sendKey[SHA_DIGEST_LENGTH];
unsigned char receiveKey[SHA_DIGEST_LENGTH];
CalculatePPTPSessionKeys( hashes, P24Input, keySize, sendKey, receiveKey );
ntlmDigestLen = keySize;
memcpy( outAuthData->fBufferData, &ntlmDigestLen, 4 );
memcpy( outAuthData->fBufferData + 4, sendKey, ntlmDigestLen );
memcpy( outAuthData->fBufferData + 4 + ntlmDigestLen, &ntlmDigestLen, 4 );
memcpy( outAuthData->fBufferData + 4 + ntlmDigestLen + 4, receiveKey, ntlmDigestLen );
outAuthData->fBufferLength = 8 + keySize*2;
}
else
{
siResult = eDSPermissionError;
}
break;
case kAuthSecureHash:
if ( secureHashNode->fBufferLength == kHashSaltedSHA1Length )
{
if (memcmp(secureHash, hashes + kHashOffsetToSaltedSHA1, kHashSaltedSHA1Length) == 0)
{
siResult = eDSNoErr;
}
else
{
siResult = eDSAuthFailed;
}
}
else
{
siResult = eDSAuthFailed;
}
break;
case kAuthWriteSecureHash:
if ( inContext->fEffectiveUID != 0 )
{
throw( (sInt32)eDSPermissionError );
}
memmove(generatedHashes + kHashOffsetToSaltedSHA1, secureHash, kHashSaltedSHA1Length);
siResult = WriteShadowHash(pUserName, inGUIDString, generatedHashes);
break;
case kAuthReadSecureHash:
if ( inContext->fEffectiveUID != 0 )
{
throw( (sInt32)eDSPermissionError );
}
siResult = ReadShadowHashAndStateFiles(pUserName, inGUIDString, hashes, &modDateOfPassword, &path, &stateFilePath, &state, &hashesLengthFromFile);
if (siResult == eDSNoErr)
{
if ( outAuthData->fBufferSize >= kHashSaltedSHA1Length )
{
memmove( outAuthData->fBufferData, hashes + kHashOffsetToSaltedSHA1, kHashSaltedSHA1Length );
outAuthData->fBufferLength = kHashSaltedSHA1Length;
}
else
{
throw( (sInt32)eDSInvalidBuffFormat );
}
}
break;
case kAuthSetShadowHashWindows:
case kAuthSetShadowHashSecure:
case kAuthNativeClearTextOK:
case kAuthNativeNoClearText:
case kAuthSetPasswdCheckAdmin:
if (hashesLengthFromFile == (kHashShadowBothLength + kHashSecureLength))
{
GenerateShadowHashes( pOldPassword,
strlen(pOldPassword),
kNiPluginHashSHA1 | kNiPluginHashNT | kNiPluginHashLM,
hashes + kHashOffsetToSaltedSHA1,
generatedHashes,
&hashLength );
}
else
{
GenerateShadowHashes( pOldPassword,
strlen(pOldPassword),
userLevelHashList,
hashes + kHashOffsetToSaltedSHA1,
generatedHashes,
&hashLength );
}
if ( NIHashesEqual( hashes, generatedHashes ) )
{
siResult = eDSNoErr;
if ( hashesLengthFromFile < kHashTotalLength)
{
GenerateShadowHashes( pOldPassword,
strlen(pOldPassword),
userLevelHashList,
hashes + kHashOffsetToSaltedSHA1,
generatedHashes,
&hashLength );
siResult = WriteShadowHash( pUserName, inGUIDString, generatedHashes );
}
else if ( memcmp(hashes, generatedHashes, kHashTotalLength) != 0 )
{
siResult = WriteShadowHash( pUserName, inGUIDString, generatedHashes );
}
if (uiAuthMethod == kAuthSetShadowHashWindows)
{
CFMutableArrayRef myHashTypeArray = NULL;
bool needToChange = false;
long convertResult = pwsf_ShadowHashDataToArray( inAuthAuthorityData, &myHashTypeArray );
if (myHashTypeArray == NULL)
{
myHashTypeArray = CFArrayCreateMutable( kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks );
}
if (userLevelHashList & kNiPluginHashCRAM_MD5)
{
CFStringRef cram_md5_cfString = CFStringCreateWithCString( NULL, kNIHashNameCRAM_MD5, kCFStringEncodingUTF8 );
CFIndex locTag = CFArrayGetFirstIndexOfValue(myHashTypeArray, CFRangeMake(0,CFArrayGetCount(myHashTypeArray)), cram_md5_cfString);
if (locTag == kCFNotFound)
{
CFArrayAppendValue(myHashTypeArray, cram_md5_cfString);
needToChange = true;
}
CFRelease(cram_md5_cfString);
}
if (userLevelHashList & kNiPluginHashRecoverable)
{
CFStringRef recoverable_cfString = CFStringCreateWithCString( NULL, kNIHashNameRecoverable, kCFStringEncodingUTF8 );
CFIndex locTag = CFArrayGetFirstIndexOfValue(myHashTypeArray, CFRangeMake(0,CFArrayGetCount(myHashTypeArray)), recoverable_cfString);
if (locTag == kCFNotFound)
{
CFArrayAppendValue(myHashTypeArray, recoverable_cfString);
needToChange = true;
}
CFRelease(recoverable_cfString);
}
if (userLevelHashList & kNiPluginHashSecurityTeamFavorite)
{
CFStringRef team_fav_cfString = CFStringCreateWithCString( NULL, kNIHashNameSecure, kCFStringEncodingUTF8 );
CFIndex locTag = CFArrayGetFirstIndexOfValue(myHashTypeArray, CFRangeMake(0,CFArrayGetCount(myHashTypeArray)), team_fav_cfString);
if (locTag == kCFNotFound)
{
CFArrayAppendValue(myHashTypeArray, team_fav_cfString);
needToChange = true;
}
CFRelease(team_fav_cfString);
}
CFStringRef salted_sha1_cfString = CFStringCreateWithCString( NULL, kNIHashNameSHA1, kCFStringEncodingUTF8 );
CFIndex locTag = CFArrayGetFirstIndexOfValue(myHashTypeArray, CFRangeMake(0,CFArrayGetCount(myHashTypeArray)), salted_sha1_cfString);
if (locTag == kCFNotFound)
{
CFArrayAppendValue(myHashTypeArray, salted_sha1_cfString);
needToChange = true;
}
CFStringRef smb_nt_cfString = CFStringCreateWithCString( NULL, kNIHashNameNT, kCFStringEncodingUTF8 );
locTag = CFArrayGetFirstIndexOfValue(myHashTypeArray, CFRangeMake(0,CFArrayGetCount(myHashTypeArray)), smb_nt_cfString);
if (locTag == kCFNotFound)
{
CFArrayAppendValue(myHashTypeArray, smb_nt_cfString);
needToChange = true;
}
CFStringRef smb_lm_cfString = CFStringCreateWithCString( NULL, kNIHashNameLM, kCFStringEncodingUTF8 );;
locTag = CFArrayGetFirstIndexOfValue(myHashTypeArray, CFRangeMake(0,CFArrayGetCount(myHashTypeArray)), smb_lm_cfString);
if (locTag == kCFNotFound)
{
CFArrayAppendValue(myHashTypeArray, smb_lm_cfString);
needToChange = true;
}
if (needToChange)
{
char *newAuthAuthority = nil;
newAuthAuthority = pwsf_ShadowHashArrayToData( myHashTypeArray, &convertResult );
if (newAuthAuthority != nil)
{
char * fullAuthAuthority = (char *) calloc(1, 1 + strlen(kDSValueAuthAuthorityShadowHash) + strlen(newAuthAuthority));
strcpy(fullAuthAuthority, kDSValueAuthAuthorityShadowHash);
strcat(fullAuthAuthority, newAuthAuthority);
siResult = SetUserAuthAuthorityAsRoot(inContext, "users", pUserName, fullAuthAuthority);
if ( siResult == eDSNoErr )
{
siResult = GetHashSecurityLevelForUser( newAuthAuthority, &userLevelHashList );
if ( siResult != eDSNoErr )
{
DBGLOG1( kLogPlugin, "DoShadowHashAuth - encountered invalid record hash list: %s", fullAuthAuthority );
userLevelHashList = sHashList;
siResult = eDSNoErr;
}
GenerateShadowHashes( pOldPassword,
strlen(pOldPassword),
userLevelHashList,
hashes + kHashOffsetToSaltedSHA1,
generatedHashes,
&hashLength );
siResult = WriteShadowHash( pUserName, inGUIDString, generatedHashes );
}
DSFreeString(newAuthAuthority);
DSFreeString(fullAuthAuthority);
}
}
CFRelease(myHashTypeArray);
CFRelease(smb_nt_cfString);
CFRelease(smb_lm_cfString);
CFRelease(salted_sha1_cfString);
}
else if (uiAuthMethod == kAuthSetShadowHashSecure)
{
CFMutableArrayRef myHashTypeArray = NULL;
bool needToChange = false;
long convertResult = pwsf_ShadowHashDataToArray( inAuthAuthorityData, &myHashTypeArray );
if (myHashTypeArray == NULL)
{
myHashTypeArray = CFArrayCreateMutable( kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks );
}
if (userLevelHashList & kNiPluginHashCRAM_MD5)
{
CFStringRef cram_md5_cfString = CFStringCreateWithCString( NULL, kNIHashNameCRAM_MD5, kCFStringEncodingUTF8 );
CFIndex locTag = CFArrayGetFirstIndexOfValue(myHashTypeArray, CFRangeMake(0,CFArrayGetCount(myHashTypeArray)), cram_md5_cfString);
if (locTag == kCFNotFound)
{
CFArrayAppendValue(myHashTypeArray, cram_md5_cfString);
needToChange = true;
}
CFRelease(cram_md5_cfString);
}
if (userLevelHashList & kNiPluginHashRecoverable)
{
CFStringRef recoverable_cfString = CFStringCreateWithCString( NULL, kNIHashNameRecoverable, kCFStringEncodingUTF8 );
CFIndex locTag = CFArrayGetFirstIndexOfValue(myHashTypeArray, CFRangeMake(0,CFArrayGetCount(myHashTypeArray)), recoverable_cfString);
if (locTag == kCFNotFound)
{
CFArrayAppendValue(myHashTypeArray, recoverable_cfString);
needToChange = true;
}
CFRelease(recoverable_cfString);
}
if (userLevelHashList & kNiPluginHashSecurityTeamFavorite)
{
CFStringRef team_fav_cfString = CFStringCreateWithCString( NULL, kNIHashNameSecure, kCFStringEncodingUTF8 );
CFIndex locTag = CFArrayGetFirstIndexOfValue(myHashTypeArray, CFRangeMake(0,CFArrayGetCount(myHashTypeArray)), team_fav_cfString);
if (locTag == kCFNotFound)
{
CFArrayAppendValue(myHashTypeArray, team_fav_cfString);
needToChange = true;
}
CFRelease(team_fav_cfString);
}
CFStringRef salted_sha1_cfString = CFStringCreateWithCString( NULL, kNIHashNameSHA1, kCFStringEncodingUTF8 );
CFIndex locTag = CFArrayGetFirstIndexOfValue(myHashTypeArray, CFRangeMake(0,CFArrayGetCount(myHashTypeArray)), salted_sha1_cfString);
if (locTag == kCFNotFound)
{
CFArrayAppendValue(myHashTypeArray, salted_sha1_cfString);
needToChange = true;
}
CFStringRef smb_nt_cfString = CFStringCreateWithCString( NULL, kNIHashNameNT, kCFStringEncodingUTF8 );
locTag = CFArrayGetFirstIndexOfValue(myHashTypeArray, CFRangeMake(0,CFArrayGetCount(myHashTypeArray)), smb_nt_cfString);
if (locTag != kCFNotFound)
{
CFArrayRemoveValueAtIndex(myHashTypeArray, locTag);
needToChange = true;
}
CFStringRef smb_lm_cfString = CFStringCreateWithCString( NULL, kNIHashNameLM, kCFStringEncodingUTF8 );;
locTag = CFArrayGetFirstIndexOfValue(myHashTypeArray, CFRangeMake(0,CFArrayGetCount(myHashTypeArray)), smb_lm_cfString);
if (locTag != kCFNotFound)
{
CFArrayRemoveValueAtIndex(myHashTypeArray, locTag);
needToChange = true;
}
if (needToChange)
{
char *newAuthAuthority = nil;
newAuthAuthority = pwsf_ShadowHashArrayToData( myHashTypeArray, &convertResult );
if (newAuthAuthority != nil)
{
char * fullAuthAuthority = (char *) calloc(1, 1 + strlen(kDSValueAuthAuthorityShadowHash) + strlen(newAuthAuthority));
strcpy(fullAuthAuthority, kDSValueAuthAuthorityShadowHash);
strcat(fullAuthAuthority, newAuthAuthority);
siResult = SetUserAuthAuthorityAsRoot(inContext, "users", pUserName, fullAuthAuthority);
if ( siResult == eDSNoErr )
{
siResult = GetHashSecurityLevelForUser( newAuthAuthority, &userLevelHashList );
if ( siResult != eDSNoErr )
{
DBGLOG1( kLogPlugin, "DoShadowHashAuth - encountered invalid record hash list: %s", fullAuthAuthority );
userLevelHashList = sHashList;
siResult = eDSNoErr;
}
GenerateShadowHashes( pOldPassword,
strlen(pOldPassword),
userLevelHashList,
hashes + kHashOffsetToSaltedSHA1,
generatedHashes,
&hashLength );
siResult = WriteShadowHash( pUserName, inGUIDString, generatedHashes );
}
DSFreeString(newAuthAuthority);
DSFreeString(fullAuthAuthority);
}
}
CFRelease(myHashTypeArray);
CFRelease(smb_nt_cfString);
CFRelease(smb_lm_cfString);
CFRelease(salted_sha1_cfString);
}
else
{
if (inAuthOnly == false)
{
siResult = AuthOpen( inContext, pUserName, pOldPassword );
}
}
}
else
{
siResult = eDSAuthFailed;
}
break;
case kAuthSetPasswd:
GetShadowHashGlobalPolicies( inContext, &globalAccess );
siResult = eDSNoErr;
if ( ! UserIsAdmin(pUserName, inContext) )
{
if (! (inContext->fAuthenticatedUserName && pUserName && (::strcmp(inContext->fAuthenticatedUserName, pUserName) == 0)) )
{
siResult = eDSPermissionError;
}
else
{
siResult = NIPasswordOkForPolicies( policyStr, &globalAccess, pUserName, pNewPassword );
if ( siResult == eDSAuthPasswordTooShort &&
globalAccess.minChars == 0 &&
pNewPassword != NULL &&
*pNewPassword == '\0' &&
((policyStr == NULL) || strstr(policyStr, "minChars=0") != NULL) )
{
siResult = eDSNoErr;
}
}
}
if ( siResult == eDSNoErr )
{
bzero(generatedHashes, kHashTotalLength);
GenerateShadowHashes(pNewPassword, strlen(pNewPassword), userLevelHashList, NULL, generatedHashes, &hashLength );
siResult = WriteShadowHash(pUserName, inGUIDString, generatedHashes);
if ( siResult == eDSNoErr )
{
state.newPasswordRequired = 0;
time( &now );
gmtime_r( &now, &state.modDateOfPassword );
gettimeofday( &modDateAssist, NULL );
TIMEVAL_TO_TIMESPEC( &modDateAssist, &modDateOfPassword );
}
}
break;
case kAuthSetPasswdAsRoot:
{
bool modifyingSelf = inContext->fAuthenticatedUserName && pUserName && (::strcmp(inContext->fAuthenticatedUserName, pUserName) == 0);
bool notAdmin = ( (inContext->fAuthenticatedUserName != NULL) && (! UserIsAdmin(inContext->fAuthenticatedUserName, inContext)) );
if ( inContext->fEffectiveUID != 0 )
{
if ( (inContext->fAuthenticatedUserName == NULL) ||
(notAdmin && (!modifyingSelf)) )
{
throw( (sInt32)eDSPermissionError );
}
}
GetShadowHashGlobalPolicies( inContext, &globalAccess );
siResult = eDSNoErr;
if ( modifyingSelf && notAdmin )
{
siResult = NIPasswordOkForPolicies( policyStr, &globalAccess, pUserName, pNewPassword );
if ( siResult == eDSAuthPasswordTooShort &&
globalAccess.minChars == 0 &&
pNewPassword != NULL &&
*pNewPassword == '\0' &&
((policyStr == NULL) || strstr(policyStr, "minChars=0") != NULL) )
{
siResult = eDSNoErr;
}
}
if ( siResult == eDSNoErr )
{
GenerateShadowHashes(pNewPassword, strlen(pNewPassword), userLevelHashList, NULL, generatedHashes, &hashLength );
siResult = WriteShadowHash(pUserName, inGUIDString, generatedHashes);
if ( siResult == eDSNoErr )
{
state.newPasswordRequired = 0;
time( &now );
gmtime_r( &now, &state.modDateOfPassword );
gettimeofday( &modDateAssist, NULL );
TIMEVAL_TO_TIMESPEC( &modDateAssist, &modDateOfPassword );
}
}
}
break;
case kAuthChangePasswd:
GenerateShadowHashes( pOldPassword,
strlen(pOldPassword),
userLevelHashList,
hashes + kHashOffsetToSaltedSHA1,
generatedHashes,
&hashLength );
if ( NIHashesEqual( hashes, generatedHashes ) || isSecondary )
{
bool notAdmin = ( (pUserName != NULL) && (! UserIsAdmin(pUserName, inContext)) );
GetShadowHashGlobalPolicies( inContext, &globalAccess );
if ( notAdmin )
{
siResult = NIPasswordOkForPolicies( policyStr, &globalAccess, pUserName, pNewPassword );
if ( siResult == eDSAuthPasswordTooShort &&
globalAccess.minChars == 0 &&
pNewPassword != NULL &&
*pNewPassword == '\0' &&
((policyStr == NULL) || strstr(policyStr, "minChars=0") != NULL) )
{
siResult = eDSNoErr;
}
}
if ( siResult == eDSNoErr )
{
bzero(generatedHashes, kHashTotalLength);
GenerateShadowHashes(pNewPassword, strlen(pNewPassword), userLevelHashList, NULL, generatedHashes, &hashLength );
siResult = WriteShadowHash(pUserName, inGUIDString, generatedHashes);
state.newPasswordRequired = 0;
time( &now );
gmtime_r( &now, &state.modDateOfPassword );
gettimeofday( &modDateAssist, NULL );
TIMEVAL_TO_TIMESPEC( &modDateAssist, &modDateOfPassword );
}
}
else
{
siResult = eDSAuthFailed;
}
break;
default:
siResult = eDSAuthMethodNotSupported;
break;
}
if ( (pUserName != NULL) && (! UserIsAdmin(pUserName, inContext)) )
{
if ( siResult == eDSNoErr &&
uiAuthMethod != kAuthGetPolicy && uiAuthMethod != kAuthGetGlobalPolicy &&
uiAuthMethod != kAuthSetPolicy && uiAuthMethod != kAuthSetGlobalPolicy )
{
GetShadowHashGlobalPolicies( inContext, &globalAccess );
siResult = NITestPolicies( policyStr, &globalAccess, &state, &modDateOfPassword, path );
if ( siResult == eDSNoErr )
{
state.failedLoginAttempts = 0;
}
else
if ( state.disabled == 1 )
{
SetUserAAtoDisabled( inContext, inNativeRecType, pUserName );
}
}
else
if ( siResult == eDSAuthFailed )
{
state.failedLoginAttempts++;
GetShadowHashGlobalPolicies( inContext, &globalAccess );
NITestPolicies( policyStr, &globalAccess, &state, &modDateOfPassword, path );
if ( state.disabled == 1 )
{
SetUserAAtoDisabled( inContext, inNativeRecType, pUserName );
}
}
}
if ( siResult == eDSNoErr || siResult == eDSAuthNewPasswordRequired )
{
time( &now );
gmtime_r( &now, &(state.lastLoginDate) );
}
switch( uiAuthMethod )
{
case kAuthSMB_NT_Key:
case kAuthSMB_LM_Key:
case kAuthSecureHash:
case kAuthNativeClearTextOK:
case kAuthNativeNoClearText:
case kAuthSetPasswd:
case kAuthSetPasswdAsRoot:
case kAuthChangePasswd:
if ( (siResult == eDSAuthFailed) && (gDelayFailedLocalAuthReturnsDeltaInSeconds != 0) )
{
gHashAuthFailedMapLock->Wait();
string aUserName(pUserName);
HashAuthFailedMapI aHashAuthFailedMapI = gHashAuthFailedMap.find(aUserName);
if (aHashAuthFailedMapI == gHashAuthFailedMap.end())
{
pHashAuthFailed = (sHashAuthFailed *)calloc(1, sizeof(sHashAuthFailed));
pHashAuthFailed->nowTime = dsTimestamp();
pHashAuthFailed->lastTime = pHashAuthFailed->nowTime;
pHashAuthFailed->failCount = 1;
gHashAuthFailedMap[aUserName] = pHashAuthFailed;
gHashAuthFailedMapLock->Signal();
}
else
{
pHashAuthFailed = aHashAuthFailedMapI->second;
pHashAuthFailed->lastTime = pHashAuthFailed->nowTime;
pHashAuthFailed->nowTime = dsTimestamp();
pHashAuthFailed->failCount++;
if ( pHashAuthFailed->failCount > 5 )
{
if (pHashAuthFailed->failCount == 6)
{
syslog(LOG_ALERT,"Failed Authentication return is being delayed due to over five recent auth failures for username: %s.", pUserName);
}
if ( (pHashAuthFailed->nowTime - pHashAuthFailed->lastTime)/USEC_PER_SEC > 10*gDelayFailedLocalAuthReturnsDeltaInSeconds*(pHashAuthFailed->failCount - 5) )
{
gHashAuthFailedMap.erase(aUserName);
free(pHashAuthFailed);
pHashAuthFailed = nil;
gHashAuthFailedMapLock->Signal();
}
else
{
struct mach_timebase_info timeBaseInfo;
mach_timebase_info( &timeBaseInfo );
uint64_t delay = gDelayFailedLocalAuthReturnsDeltaInSeconds * (pHashAuthFailed->failCount - 5) * (((uint64_t)NSEC_PER_SEC * (uint64_t)timeBaseInfo.denom) / (uint64_t)timeBaseInfo.numer);
gHashAuthFailedMapLock->Signal(); mach_wait_until( mach_absolute_time() + delay );
}
}
else
{
gHashAuthFailedMapLock->Signal();
}
}
}
break;
default:
break;
}
}
}
catch( sInt32 err )
{
siResult = err;
}
if ( stateFilePath != NULL )
{
WriteHashStateFile( stateFilePath, &state );
DSFreeString( stateFilePath );
}
DSFreeString( path );
DSFreeString( policyStr );
if ( nativeAttrType != NULL )
{
delete nativeAttrType;
nativeAttrType = NULL;
}
if (dataList != NULL)
{
dsDataListDeallocatePriv(dataList);
free(dataList);
dataList = NULL;
}
DSFreeString( pUserName );
if ( pNewPassword != nil )
{
bzero(pNewPassword, strlen(pNewPassword));
free( pNewPassword );
pNewPassword = nil;
}
if ( pOldPassword != nil )
{
bzero(pOldPassword, strlen(pOldPassword));
free( pOldPassword );
pOldPassword = nil;
}
DSFree( pNTLMDigest );
DSFreeString( pSambaName );
DSFreeString( pDomain );
DSFreeString( pAdminUser );
if ( pAdminPassword != nil )
{
bzero(pAdminPassword, strlen(pAdminPassword));
free( pAdminPassword );
pAdminPassword = nil;
}
digest_dispose( &digestContext );
DSFreeString( challenge );
DSFreeString( apopResponse );
DSFree( pCramResponse );
bzero(P21, kHashShadowKeyLength);
bzero(C8, kHashShadowChallengeLength);
bzero(P24, kHashShadowResponseLength);
bzero(P24Input, kHashShadowResponseLength);
bzero(hashes, kHashTotalLength);
bzero(generatedHashes, kHashTotalLength);
bzero(secureHash, kHashSecureLength);
return( siResult );
}
sInt32 CNiPlugIn::GetUserPolicies( sNIContextData *inContext, const char *inNativeRecType, const char *inUsername, sHashState *inState, char **outPolicyStr )
{
sInt32 error = eDSNoErr;
ni_status niResult = NI_OK;
char *nativeAttrType = NULL;
char *internalPolicyStr = NULL;
ni_id niDirID;
ni_namelist niValues;
long length = 0;
try
{
if ( outPolicyStr == NULL )
return eParameterError;
*outPolicyStr = NULL;
gNetInfoMutex->Wait();
void *aNIDomain = RetrieveNIDomain(inContext);
if (aNIDomain != NULL)
{
error = IsValidRecordName( inUsername, inNativeRecType, aNIDomain, niDirID );
if ( error != eDSNoErr )
{
gNetInfoMutex->Signal();
throw( (sInt32)eDSAuthUnknownUser );
}
nativeAttrType = MapAttrToNetInfoType( kDS1AttrPasswordPolicyOptions );
if ( nativeAttrType == NULL )
{
gNetInfoMutex->Signal();
throw( (sInt32)eDSInvalidAttributeType );
}
niResult = ni_lookupprop( aNIDomain, &niDirID, nativeAttrType, &niValues );
}
else
{
gNetInfoMutex->Signal();
throw( (sInt32)eDSInvalidSession );
}
gNetInfoMutex->Signal();
if ( niResult == NI_OK && niValues.ni_namelist_len > 0 )
{
ConvertXMLPolicyToSpaceDelimited( niValues.ni_namelist_val[0], &internalPolicyStr );
gNetInfoMutex->Wait();
ni_namelist_free( &niValues );
gNetInfoMutex->Signal();
}
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( sInt32 catchErr )
{
error = catchErr;
}
if ( nativeAttrType != NULL )
delete nativeAttrType;
return error;
}
sInt32 CNiPlugIn::SetUserPolicies(
sNIContextData *inContext,
const char *inNativeRecType,
const char *inUsername,
const char *inPolicyStr,
sHashState *inOutHashState )
{
sInt32 siResult = eDSAuthFailed;
ni_id niDirID;
ni_index niWhere = 0;
ni_namelist niValue;
ni_proplist niPropList;
bool bFreePropList = false;
char *nativeAttrType = NULL;
char *currentPolicyStr = NULL;
char *newPassRequiredStr = NULL;
PWAccessFeatures access;
gNetInfoMutex->Wait();
try
{
if ( inContext == nil || inPolicyStr == nil || inUsername == nil )
throw( (sInt32)eDSAuthFailed );
if ( (inContext->fEffectiveUID != 0) && (!UserIsAdmin(inContext->fAuthenticatedUserName, inContext)) )
throw( (sInt32)eDSPermissionError );
if ( inOutHashState != NULL && (newPassRequiredStr = strstr(inPolicyStr, kPWPolicyStr_newPasswordRequired)) != NULL )
{
newPassRequiredStr += sizeof(kPWPolicyStr_newPasswordRequired) - 1;
if ( (*newPassRequiredStr == '=') &&
(*(newPassRequiredStr + 1) == '0' || *(newPassRequiredStr + 1) == '1') )
{
inOutHashState->newPasswordRequired = *(newPassRequiredStr + 1) - '0';
}
}
GetUserPolicies( inContext, inNativeRecType, inUsername, NULL, ¤tPolicyStr );
void *aNIDomain = RetrieveNIDomain(inContext);
if (aNIDomain != NULL)
{
niDirID = inContext->dirID;
nativeAttrType = MapAttrToNetInfoType( kDS1AttrPasswordPolicyOptions );
if ( nativeAttrType == NULL )
throw( (sInt32)eDSInvalidAttributeType );
siResult = IsValidRecordName( inUsername, inNativeRecType, aNIDomain, niDirID );
if ( siResult != eDSNoErr )
throw( (sInt32)eDSAuthFailed );
siResult = ::ni_read( aNIDomain, &niDirID, &niPropList );
if ( siResult != eDSNoErr ) throw( (sInt32)eDSAuthFailed );
if ( niPropList.ni_proplist_val == nil ) throw( (sInt32)eDSAuthFailed );
bFreePropList = true;
niWhere = ::ni_proplist_match( niPropList, nativeAttrType, nil );
if (niWhere != NI_INDEX_NULL)
{
niValue = niPropList.ni_proplist_val[niWhere].nip_val;
if ( ( inContext->fEffectiveUID != 0 )
&& ( (inContext->fAuthenticatedUserName == NULL)
|| (strcmp(inContext->fAuthenticatedUserName,"root") != 0) ) )
{
siResult = NiLib2::ValidateDir( inContext->fAuthenticatedUserName, &niPropList );
if ( siResult != NI_OK )
siResult = NiLib2::ValidateName( "root", &niPropList, niWhere );
}
}
if ( siResult != eDSNoErr )
siResult = MapNetInfoErrors( siResult );
if ( siResult == eDSNoErr )
{
char *xmlDataStr;
char policyStr[2048];
GetDefaultUserPolicies( &access );
if ( currentPolicyStr != NULL )
StringToPWAccessFeatures( currentPolicyStr, &access );
StringToPWAccessFeatures( inPolicyStr, &access );
PWAccessFeaturesToStringWithoutStateInfo( &access, policyStr );
if ( ConvertSpaceDelimitedPolicyToXML( policyStr, &xmlDataStr ) == 0 )
{
siResult = NiLib2::DestroyDirVal( aNIDomain, &niDirID, (char*)nativeAttrType, niValue );
siResult = NiLib2::InsertDirVal( aNIDomain, &niDirID, (char*)nativeAttrType, xmlDataStr, 0 );
siResult = MapNetInfoErrors( siResult );
free( xmlDataStr );
}
}
}
else
{
throw( (sInt32)eDSInvalidSession );
}
}
catch( sInt32 err )
{
siResult = err;
}
gNetInfoMutex->Signal();
if ( bFreePropList )
::ni_proplist_free( &niPropList );
if ( nativeAttrType != NULL )
delete nativeAttrType;
if ( currentPolicyStr != NULL )
free( currentPolicyStr );
return( siResult );
}
sInt32 CNiPlugIn::SetUserAAtoDisabled( sNIContextData *inContext, const char *inNativeRecType, const char *inUsername )
{
sInt32 siResult = eDSAuthFailed;
ni_id niDirID;
ni_index niWhere = 0;
ni_namelist niValue;
ni_proplist niPropList;
bool bFreePropList = false;
char *nativeAttrType = NULL;
char *currentPolicyStr = NULL;
char *curAAString = NULL;
char *aaString = NULL;
gNetInfoMutex->Wait();
try
{
if ( inContext == nil )
throw( (sInt32)eDSAuthFailed );
void *aNIDomain = RetrieveNIDomain(inContext);
if (aNIDomain != NULL)
{
niDirID = inContext->dirID;
nativeAttrType = MapAttrToNetInfoType( kDSNAttrAuthenticationAuthority );
if ( nativeAttrType == NULL )
throw( (sInt32)eDSInvalidAttributeType );
siResult = IsValidRecordName( inUsername, inNativeRecType, aNIDomain, niDirID );
if ( siResult != eDSNoErr )
throw( (sInt32)eDSAuthFailed );
siResult = ::ni_read( aNIDomain, &niDirID, &niPropList );
if ( siResult != eDSNoErr ) throw( (sInt32)eDSAuthFailed );
if ( niPropList.ni_proplist_val == nil ) throw( (sInt32)eDSAuthFailed );
bFreePropList = true;
niWhere = ::ni_proplist_match( niPropList, nativeAttrType, nil );
if (niWhere != NI_INDEX_NULL)
{
niValue = niPropList.ni_proplist_val[niWhere].nip_val;
if ((niValue.ni_namelist_len > 0) && (niValue.ni_namelist_val != nil))
curAAString = niValue.ni_namelist_val[0];
siResult = NiLib2::ValidateDir( inContext->fAuthenticatedUserName, &niPropList );
if ( siResult != NI_OK )
siResult = NiLib2::ValidateName( "root", &niPropList, niWhere );
}
if ( siResult != eDSNoErr )
siResult = MapNetInfoErrors( siResult );
if ( siResult == eDSNoErr )
{
siResult = NiLib2::DestroyDirVal( aNIDomain, &niDirID, (char*)nativeAttrType, niValue );
if ( curAAString != NULL )
{
aaString = (char *) malloc( strlen(curAAString) + sizeof(kDSValueAuthAuthorityDisabledUser) );
strcpy( aaString, kDSValueAuthAuthorityDisabledUser );
strcat( aaString, curAAString );
}
else
{
aaString = strdup( kDSValueAuthAuthorityDisabledUser";ShadowHash;" );
}
siResult = NiLib2::InsertDirVal( aNIDomain, &niDirID, (char*)nativeAttrType, aaString, 0 );
siResult = MapNetInfoErrors( siResult );
}
}
else
{
throw( (sInt32)eDSInvalidSession );
}
}
catch( sInt32 err )
{
siResult = err;
}
gNetInfoMutex->Signal();
if ( bFreePropList )
::ni_proplist_free( &niPropList );
DSFreeString( aaString );
if ( nativeAttrType != NULL )
delete nativeAttrType;
if ( currentPolicyStr != NULL )
free( currentPolicyStr );
return( siResult );
}
sInt32 CNiPlugIn::SetUserAuthAuthorityAsRoot( sNIContextData *inContext, const char *inNativeRecType, const char *inUsername, const char *inAuthAuthority )
{
sInt32 siResult = eDSAuthFailed;
ni_id niDirID;
ni_index niWhere = 0;
ni_namelist niValue;
ni_proplist niPropList;
char *nativeAttrType = NULL;
gNetInfoMutex->Wait();
try
{
if ( ( inContext == nil ) || (inAuthAuthority == nil) )
throw( (sInt32)eDSAuthFailed );
void *aNIDomain = RetrieveNIDomain(inContext);
if (aNIDomain != NULL)
{
niDirID = inContext->dirID;
nativeAttrType = MapAttrToNetInfoType( kDSNAttrAuthenticationAuthority );
if ( nativeAttrType == NULL )
throw( (sInt32)eDSInvalidAttributeType );
siResult = IsValidRecordName( inUsername, inNativeRecType, aNIDomain, niDirID );
if ( siResult != eDSNoErr )
throw( (sInt32)eDSAuthFailed );
siResult = ::ni_read( aNIDomain, &niDirID, &niPropList );
if ( siResult != eDSNoErr ) throw( (sInt32)eDSAuthFailed );
if ( niPropList.ni_proplist_val == nil ) throw( (sInt32)eDSAuthFailed );
if (siResult == eDSNoErr)
{
niWhere = ::ni_proplist_match( niPropList, nativeAttrType, nil );
if (niWhere != NI_INDEX_NULL)
{
niValue = niPropList.ni_proplist_val[niWhere].nip_val;
}
}
else
{
siResult = MapNetInfoErrors( siResult );
}
if ( siResult == eDSNoErr )
{
siResult = NiLib2::DestroyDirVal( aNIDomain, &niDirID, (char*)nativeAttrType, niValue );
siResult = NiLib2::InsertDirVal( aNIDomain, &niDirID, (char*)nativeAttrType, (char *)inAuthAuthority, 0 );
siResult = MapNetInfoErrors( siResult );
}
}
else
{
throw( (sInt32)eDSInvalidSession );
}
}
catch( sInt32 err )
{
siResult = err;
}
gNetInfoMutex->Signal();
if ( nativeAttrType != NULL )
delete nativeAttrType;
return( siResult );
}
sInt32 CNiPlugIn::ReadShadowHash (
const char *inUserName,
const char *inGUIDString,
unsigned char outHashes[kHashTotalLength],
struct timespec *outModTime,
char **outUserHashPath,
sInt32 *outHashDataLen,
bool readHashes )
{
sInt32 siResult = eDSAuthFailed;
char *path = NULL;
char hexHashes[kHashTotalHexLength + 1] = { 0 };
sInt32 readBytes = 0;
uInt32 outBytes = 0;
CFile *hashFile = nil;
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 != nil)
{
pathSize = sizeof(kShadowHashDirPath) + strlen(inGUIDString) + 1;
}
else
{
pathSize = sizeof(kShadowHashDirPath) + strlen(inUserName) + 1;
}
path = (char*)::calloc(pathSize, 1);
if ( path != NULL )
{
if (inGUIDString != nil)
{
strcpy( path, kShadowHashDirPath );
strcat( path, inGUIDString );
}
else
{
strcpy( path, kShadowHashDirPath );
strcat( path, inUserName );
}
try {
hashFile = new CFile(path, false);
} catch ( ... ) {
}
if (hashFile != nil && hashFile->is_open())
{
if ( outModTime != NULL )
hashFile->ModDate( outModTime );
if ( readHashes )
{
bzero( hexHashes, sizeof(hexHashes) );
readBytes = hashFile->ReadBlock( hexHashes, kHashTotalHexLength );
delete(hashFile);
hashFile = nil;
if ( readBytes < kHashShadowBothHexLength ) throw( (sInt32)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 != nil)
{
delete(hashFile);
hashFile = nil;
}
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 = nil;
if ( readBytes != kHashShadowBothHexLength ) throw( (sInt32)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 != nil)
{
delete(hashFile);
hashFile = nil;
}
bzero(hexHashes, kHashTotalHexLength);
if ( outHashDataLen != NULL )
*outHashDataLen = outBytes;
return( siResult );
}
sInt32 CNiPlugIn::WriteShadowHash ( const char *inUserName, const char *inGUIDString, unsigned char inHashes[kHashTotalLength] )
{
sInt32 result = eDSAuthFailed;
char *path = NULL;
char hexHashes[kHashTotalHexLength] = { 0 };
sInt32 siResult = eDSNoErr;
struct stat statResult;
CFile *hashFile = nil;
try
{
RemoveShadowHash( inUserName, nil, false );
if (inGUIDString != nil)
{
path = (char*)::calloc(1, strlen(kShadowHashDirPath) + strlen(inGUIDString) + 1);
}
else
{
path = (char*)::calloc(strlen(kShadowHashDirPath) + strlen(inUserName) + 1, 1);
}
if ( path != NULL )
{
if (inGUIDString != nil)
{
sprintf(path, "%s%s", kShadowHashDirPath, inGUIDString);
}
else
{
sprintf(path, "%s%s", kShadowHashDirPath, inUserName);
}
siResult = stat( "/var/db/shadow/hash", &statResult );
if (siResult != eDSNoErr)
{
siResult = ::stat( "/var/db/shadow", &statResult );
if (siResult != eDSNoErr)
{
::mkdir( "/var/db/shadow", 0700 );
::chmod( "/var/db/shadow", 0700 );
}
siResult = ::stat( "/var/db/shadow/hash", &statResult );
if (siResult != eDSNoErr)
{
::mkdir( "/var/db/shadow/hash", 0700 );
::chmod( "/var/db/shadow/hash", 0700 );
}
}
hashFile = new CFile(path, true);
if (hashFile->is_open())
{
BinaryToHexConversion( inHashes, kHashTotalLength, hexHashes );
hashFile->seekp( 0 ); hashFile->write( hexHashes, kHashTotalHexLength );
chmod( path, 0600 ); delete(hashFile);
hashFile = nil;
result = eDSNoErr;
}
}
}
catch( ... )
{
result = eDSAuthFailed;
}
if ( path != NULL ) {
free( path );
path = NULL;
}
if (hashFile != nil)
{
delete(hashFile);
hashFile = nil;
}
bzero(hexHashes, kHashTotalHexLength);
return( result );
}
void CNiPlugIn::RemoveShadowHash ( const char *inUserName, const char *inGUIDString, bool bShadowToo )
{
char *path = NULL;
char hexHashes[kHashTotalHexLength] = { 0 };
bool bRemovePath = false;
CFile *hashFile = nil;
try
{
if (bShadowToo) {
if (inGUIDString != nil)
{
path = (char*)::calloc(1, strlen(kShadowHashDirPath) + strlen(inGUIDString) + 1);
}
else
{
path = (char*)::calloc(strlen(kShadowHashDirPath) + strlen(inUserName) + 1, 1);
}
if ( path != NULL )
{
if (inGUIDString != nil)
{
sprintf(path, "%s%s", kShadowHashDirPath, inGUIDString);
}
else
{
sprintf(path, "%s%s", kShadowHashDirPath, inUserName);
}
try
{
hashFile = new CFile(path, false);
if (hashFile->is_open())
{
hashFile->seekp( 0 ); hashFile->write( hexHashes, kHashTotalHexLength );
delete(hashFile);
hashFile = nil;
bRemovePath = true;
}
if (bRemovePath)
{
unlink(path);
}
}
catch( ... )
{
}
free( path );
path = NULL;
}
}
if (hashFile != nil)
{
delete(hashFile);
hashFile = nil;
}
bRemovePath = false;
if (inUserName != nil)
{
path = (char*)::calloc(sizeof(kShadowHashOldDirPath) + strlen(inUserName) + 1, 1);
}
if ( path != NULL )
{
sprintf(path, "%s%s", kShadowHashOldDirPath, inUserName);
hashFile = new CFile(path, false);
if (hashFile->is_open())
{
hashFile->seekp( 0 ); hashFile->write( hexHashes, kHashShadowBothHexLength );
delete(hashFile);
hashFile = nil;
bRemovePath = true;
}
if (bRemovePath)
{
unlink(path);
}
free( path );
path = NULL;
}
}
catch( ... )
{
}
if ( path != NULL ) {
free( path );
path = NULL;
}
if (hashFile != nil)
{
delete(hashFile);
hashFile = nil;
}
bzero(hexHashes, kHashTotalHexLength);
return;
}
sInt32 CNiPlugIn::ReadShadowHashAndStateFiles(
const char *inUserName,
const char *inGUIDString,
unsigned char outHashes[kHashTotalLength],
struct timespec *outModTime,
char **outUserHashPath,
char **outStateFilePath,
sHashState *inOutHashState,
sInt32 *outHashDataLen )
{
if ( outStateFilePath == NULL || outUserHashPath == NULL )
return eParameterError;
*outStateFilePath = NULL;
sInt32 siResult = ReadShadowHash( inUserName, inGUIDString, outHashes, outModTime, outUserHashPath, outHashDataLen );
if ( siResult == eDSNoErr )
siResult = NIGetStateFilePath( *outUserHashPath, outStateFilePath );
if ( siResult == eDSNoErr && inOutHashState != NULL )
{
siResult = ReadHashStateFile( *outStateFilePath, inOutHashState );
if (siResult != eDSNoErr)
{
siResult = eDSNoErr;
}
}
return siResult;
}
sInt32 CNiPlugIn::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;
sInt32 siResult = ReadShadowHash( inUserName, inGUIDString, hashes, outModTime, outUserHashPath, outHashDataLen, false );
if ( siResult == eDSNoErr )
siResult = NIGetStateFilePath( *outUserHashPath, outStateFilePath );
if ( siResult == eDSNoErr && inOutHashState != NULL )
{
siResult = ReadHashStateFile( *outStateFilePath, inOutHashState );
if (siResult != eDSNoErr)
{
siResult = eDSNoErr;
}
}
return siResult;
}
sInt32 CNiPlugIn::MigrateToShadowHash( void *inDomain, ni_id *inNIDirID, ni_proplist *inNIPropList, const char *inUserName, const char *inPassword, bool &outResetCache )
{
sInt32 siResult = eDSAuthFailed;
unsigned char generatedHashes[kHashTotalLength] = {0};
ni_namelist niAttribute;
ni_namelist niValues;
ni_index niWhere = NI_INDEX_NULL;
unsigned long hashTotalLength = 0;
niWhere = ::ni_proplist_match( *inNIPropList, "generateduid", nil );
char* GUIDString = nil; if (niWhere != NI_INDEX_NULL)
{
if ((inNIPropList->ni_proplist_val[ niWhere ].nip_val.ni_namelist_len > 0)
&& (inNIPropList->ni_proplist_val[ niWhere ].nip_val.ni_namelist_val != nil))
{
GUIDString = inNIPropList->ni_proplist_val[ niWhere ].nip_val.ni_namelist_val[ 0 ];
}
}
if (GUIDString == nil)
{
CFUUIDRef myUUID;
CFStringRef myUUIDString;
char genUIDValue[100];
memset( genUIDValue, 0, 100 );
myUUID = CFUUIDCreate(kCFAllocatorDefault);
myUUIDString = CFUUIDCreateString(kCFAllocatorDefault, myUUID);
CFStringGetCString(myUUIDString, genUIDValue, 100, kCFStringEncodingASCII);
CFRelease(myUUID);
CFRelease(myUUIDString);
GUIDString = strdup(genUIDValue);
NI_INIT( &niValues );
::ni_namelist_insert( &niValues, GUIDString, NI_INDEX_NULL );
siResult = DoAddAttribute( inDomain, inNIDirID, "generateduid", niValues );
outResetCache = true;
::ni_namelist_free( &niValues );
}
GenerateShadowHashes(inPassword, strlen(inPassword), sHashList, NULL, generatedHashes, &hashTotalLength );
siResult = WriteShadowHash(inUserName, GUIDString, generatedHashes);
if (siResult == eDSNoErr)
{
NI_INIT( &niAttribute );
::ni_namelist_insert( &niAttribute, "authentication_authority", NI_INDEX_NULL );
siResult = NiLib2::DestroyDirProp( inDomain, inNIDirID, niAttribute );
siResult = MapNetInfoErrors( siResult );
::ni_namelist_free( &niAttribute );
NI_INIT( &niAttribute );
::ni_namelist_insert( &niAttribute, "passwd", NI_INDEX_NULL );
siResult = NiLib2::DestroyDirProp( inDomain, inNIDirID, niAttribute );
siResult = MapNetInfoErrors( siResult );
::ni_namelist_free( &niAttribute );
NI_INIT( &niValues );
::ni_namelist_insert( &niValues, kDSValueAuthAuthorityShadowHash, NI_INDEX_NULL );
siResult = DoAddAttribute( inDomain, inNIDirID, "authentication_authority", niValues );
::ni_namelist_free( &niValues );
NI_INIT( &niValues );
::ni_namelist_insert( &niValues, kDSValueNonCryptPasswordMarker, NI_INDEX_NULL );
siResult = DoAddAttribute( inDomain, inNIDirID, "passwd", niValues );
::ni_namelist_free( &niValues );
}
return(siResult);
}
#pragma mark -
#pragma mark Password Server
#pragma mark -
sInt32 CNiPlugIn::PWSetReplicaData( sNIContextData *inContext, const char *inAuthorityData )
{
sInt32 error = eDSNoErr;
ni_status niResult = NI_OK;
bool bFoundWithHash = false;
long replicaListLen = 0;
char *rsaKeyPtr = NULL;
char *nativeRecType = NULL;
char *nativeAttrType = NULL;
tDataBufferPtr replicaBuffer = NULL;
tDataBufferPtr replyBuffer = NULL;
ni_id niDirID;
ni_namelist niValues;
char recordName[64];
char hashStr[34];
nativeRecType = MapRecToNetInfoType( kDSStdRecordTypeConfig );
if ( nativeRecType == NULL )
return eDSInvalidRecordType;
try
{
nativeAttrType = MapAttrToNetInfoType( kDS1AttrPasswordServerList );
if ( nativeAttrType == NULL )
throw( (sInt32)eDSInvalidAttributeType );
gNetInfoMutex->Wait();
void *aNIDomain = RetrieveNIDomain(inContext);
if (aNIDomain != NULL)
{
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 = IsValidRecordName( recordName, nativeRecType, aNIDomain, niDirID );
if ( error == eDSNoErr )
bFoundWithHash = true;
}
if ( ! bFoundWithHash )
{
error = IsValidRecordName( "passwordserver", nativeRecType, aNIDomain, niDirID );
if ( error != eDSNoErr )
throw( error );
}
niResult = ni_lookupprop( aNIDomain, &niDirID, nativeAttrType, &niValues );
}
else
{
gNetInfoMutex->Signal();
throw( (sInt32)eDSInvalidSession );
}
gNetInfoMutex->Signal();
if ( niResult != NI_OK ) throw( (sInt32)eDSAuthFailed );
if ( niValues.ni_namelist_len >= 1 )
{
replicaListLen = strlen( niValues.ni_namelist_val[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, niValues.ni_namelist_val[0], replicaListLen );
error = dsDoPlugInCustomCall( inContext->fPWSNodeRef, 1, replicaBuffer, replyBuffer );
::dsDataBufferDeallocatePriv( replicaBuffer );
::dsDataBufferDeallocatePriv( replyBuffer );
}
if ( nativeAttrType != NULL )
delete nativeAttrType;
gNetInfoMutex->Wait();
if (niValues.ni_namelist_len > 0)
{
ni_namelist_free( &niValues );
}
gNetInfoMutex->Signal();
}
catch( sInt32 catchErr )
{
error = catchErr;
}
if ( nativeRecType != NULL )
delete nativeRecType;
return error;
}
sInt32 CNiPlugIn::DoPasswordServerAuth ( tDirNodeReference inNodeRef, tDataNodePtr inAuthMethod,
sNIContextData* inContext,
sNIContinueData** inOutContinueData,
tDataBufferPtr inAuthData, tDataBufferPtr outAuthData,
bool inAuthOnly, bool isSecondary, const char* inAuthAuthorityData,
const char* inGUIDString, const char* inNativeRecType )
{
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 *password = NULL;
sNIContinueData *pContinue = NULL;
tContextData continueData = NULL;
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, "DoPasswordServerAuth::" );
if (inAuthMethod != nil)
{
DBGLOG1( kLogPlugin, "NetInfo PlugIn: Attempting use of authentication method %s", inAuthMethod->fBufferData );
}
error = dsGetAuthMethodEnumValue( inAuthMethod, &authMethod );
if ( error != eDSNoErr && error != eDSAuthMethodNotSupported )
throw( error );
switch( authMethod )
{
case kAuth2WayRandom:
if ( inOutContinueData == nil )
throw( (sInt32)eDSNullParameter );
if ( *inOutContinueData == nil )
{
pContinue = (sNIContinueData *)::calloc( 1, sizeof( sNIContinueData ) );
if ( pContinue == nil )
throw( (sInt32)eMemoryError );
gNIContinue->AddItem( pContinue, inNodeRef );
*inOutContinueData = pContinue;
authDataBuff = ::dsDataBufferAllocatePriv( uidStrLen + 1 );
if ( authDataBuff == nil ) throw ( (sInt32)eMemoryError );
strcpy( authDataBuff->fBufferData, uidStr );
authDataBuff->fBufferLength = uidStrLen;
}
else
{
pContinue = *inOutContinueData;
if ( gNIContinue->VerifyItem( pContinue ) == false )
throw( (sInt32)eDSInvalidContinueData );
authDataBuff = inAuthData;
}
break;
case kAuthSetPasswd:
case kAuthSetPolicy:
{
ni_id niDirID;
ni_namelist niValues;
ni_status niResult = NI_OK;
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 );
gNetInfoMutex->Wait();
void * aNIDomain = RetrieveNIDomain(inContext);
if (aNIDomain != NULL)
{
error = IsValidRecordName ( userName, inNativeRecType, aNIDomain, niDirID );
if ( error != eDSNoErr )
{
gNetInfoMutex->Signal();
throw( (sInt32)eDSAuthFailed );
}
niResult = ni_lookupprop( aNIDomain, &niDirID,
"authentication_authority", &niValues );
}
else
{
gNetInfoMutex->Signal();
throw( (sInt32)eDSInvalidSession );
}
gNetInfoMutex->Signal();
if (niResult != NI_OK) throw( (sInt32)eDSAuthFailed );
lookupResult = eDSAuthFailed;
for ( idx = 0; idx < niValues.ni_namelist_len && lookupResult == eDSAuthFailed; idx++ )
{
error = dsParseAuthAuthority( niValues.ni_namelist_val[idx], &aaVersion, &aaTag, &aaData );
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;
}
}
if (aaVersion != NULL) {
free(aaVersion);
aaVersion = NULL;
}
if (aaTag != NULL) {
free(aaTag);
aaTag = NULL;
}
if (lookupResult != eDSNoErr && aaData != NULL) {
free(aaData);
aaData = NULL;
}
}
gNetInfoMutex->Wait();
if (niValues.ni_namelist_len > 0)
{
ni_namelist_free(&niValues);
}
gNetInfoMutex->Signal();
if ( lookupResult != eDSNoErr ) throw( (sInt32)eDSAuthFailed );
error = RepackBufferForPWServer(inAuthData, uidStr, 1, &authDataBuffTemp );
if ( error != eDSNoErr ) throw( error );
error = RepackBufferForPWServer(authDataBuffTemp, aaData, 3, &authDataBuff );
if (aaData != NULL) {
free(aaData);
aaData = NULL;
}
if ( error != eDSNoErr ) throw( error );
}
break;
case kAuthClearText:
case kAuthNativeClearTextOK:
case kAuthNativeNoClearText:
case kAuthCrypt:
{
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( error );
}
if ( pContinue )
continueData = pContinue->fPassPlugContinueData;
result = dsDoDirNodeAuth( inContext->fPWSNodeRef, inAuthMethod, inAuthOnly,
authDataBuff, outAuthData, &continueData );
if ( result == eDSAuthNoAuthServerFound || result == eDSAuthServerError )
{
result = PWSetReplicaData( inContext, uidStr );
if ( result == eDSNoErr )
result = dsDoDirNodeAuth( inContext->fPWSNodeRef, inAuthMethod, inAuthOnly,
authDataBuff, outAuthData, &continueData );
}
if ( pContinue )
{
pContinue->fPassPlugContinueData = continueData;
if ( continueData == NULL )
{
gNIContinue->RemoveItem( pContinue );
if ( inOutContinueData == nil )
throw( (sInt32)eDSNullParameter );
*inOutContinueData = nil;
}
}
if ( (result == eDSNoErr) && (inAuthOnly == false) && (userName != NULL) && (password != NULL) )
{
result = AuthOpen( inContext, userName, password );
}
}
}
catch(sInt32 err )
{
result = err;
}
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 ( authDataBuff )
dsDataBufferDeallocatePriv( authDataBuff );
if ( authDataBuffTemp )
dsDataBufferDeallocatePriv( authDataBuffTemp );
return( result );
}
#pragma mark -
#pragma mark TIM
#pragma mark -
sInt32 CNiPlugIn::DoTimSMBAuth ( sNIContextData *inContext, tDataBuffer *inAuthData,
uInt32 inWhichOne )
{
sInt32 siResult = eDSAuthFailed;
#ifdef TIM_CLIENT_PRESENT
TIMHandle *timHandle = nil;
char *pData = nil;
char *pUserName = nil;
uInt32 userNameLen = 0;
char *pC8 = nil;
uInt32 c8Len = 0;
char *pP24 = nil;
uInt32 p24Len = 0;
uInt32 offset = 0;
uInt32 buffSize = 0;
uInt32 buffLen = 0;
gNetInfoMutex->Wait();
if ( !IsTimRunning() )
{
gNetInfoMutex->Signal();
return( eDSAuthMethodNotSupported );
}
try
{
if ( inAuthData == nil ) throw( (sInt32)eDSNullAuthStepData );
if ( inContext == nil ) throw( (sInt32)eDSNullParameter );
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( &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 );
pUserName = (char *)::calloc( 1, userNameLen + 1 );
::memcpy( pUserName, pData, userNameLen );
pData += userNameLen;
offset += userNameLen;
if (offset + sizeof( unsigned long ) > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &c8Len, pData, sizeof( unsigned long ) );
pData += sizeof( unsigned long );
offset += sizeof( unsigned long );
if (offset + c8Len > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
pC8 = (char *)::calloc( 1, c8Len + 1 );
::memcpy( pC8, pData, c8Len );
pData += c8Len;
offset += c8Len;
if (offset + sizeof( unsigned long ) > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &p24Len, pData, sizeof( unsigned long ) );
pData += sizeof( unsigned long );
offset += sizeof( unsigned long );
if (offset + p24Len > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
pP24 = (char *)::calloc( 1, p24Len + 1 );
::memcpy( pP24, pData, p24Len );
pData += p24Len;
offset += p24Len;
void * aNIDomain = RetrieveNIDomain(inContext);
if (aNIDomain != NULL)
{
timHandle = timServerForDomain( aNIDomain );
if ( timHandle == nil ) throw( (sInt32)eDSAuthFailed );
switch ( inWhichOne )
{
case kAuthSMB_NT_Key:
siResult = ::timAuthenticateSMBNTKeyWithTIMHandle( timHandle, pUserName, pC8, pP24 );
break;
case kAuthSMB_LM_Key:
siResult = ::timAuthenticateSMBLMKeyWithTIMHandle( timHandle, pUserName, pC8, pP24 );
break;
}
timHandleFree( timHandle );
timHandle = nil;
}
else
{
throw( (sInt32)eDSInvalidSession );
}
#ifdef DEBUG
if ( siResult != TimStatusOK )
{
DBGLOG2( kLogPlugin, "-- timAuthenticateSMBLMKey -- failed with %l for key %l.", siResult, inWhichOne );
}
#endif
siResult = MapAuthResult( siResult );
}
catch( sInt32 err )
{
siResult = err;
}
gNetInfoMutex->Signal();
if ( pUserName != nil )
{
free( pUserName );
pUserName = nil;
}
if ( pC8 != nil )
{
bzero(pC8, c8Len);
free( pC8 );
pC8 = nil;
}
if ( pP24 != nil )
{
bzero(pP24, p24Len);
free( pP24 );
pP24 = nil;
}
#endif
return( siResult );
}
sInt32 CNiPlugIn::DoTimMultiPassAuth ( tDirNodeReference inNodeRef, tDataNodePtr inAuthMethod,
sNIContextData *inContext, sNIContinueData** inOutContinueData,
tDataBufferPtr inAuthData, tDataBufferPtr outAuthData,
bool inAuthOnly )
{
sInt32 siResult = eDSAuthFailed;
#ifdef TIM_CLIENT_PRESENT
tDataBuffer *authData = nil;
tDataBuffer *outData = nil;
TIMHandle *authHndl = nil;
Buffer *pAuthBuff = nil;
Buffer *pAuthOutBuff = nil;
CString *pAuthStr = nil;
sNIContinueData *pContinue = nil;
gNetInfoMutex->Wait(); if ( !IsTimRunning() )
{
gNetInfoMutex->Signal();
return( eDSAuthMethodNotSupported );
}
try
{
if ( inContext == nil ) throw( (sInt32)eDSNullDataBuff );
if ( inAuthData == nil ) throw( (sInt32)eDSNullAuthStepData );
if ( outAuthData == nil ) throw( (sInt32)eDSNullAuthStepData );
if ( inOutContinueData == nil ) throw( (sInt32)eDSNullParameter );
if ( *inOutContinueData == nil )
{
pContinue = (sNIContinueData *)::calloc( 1, sizeof( sNIContinueData ) );
gNIContinue->AddItem( pContinue, inNodeRef );
}
else
{
pContinue = *inOutContinueData;
if ( gNIContinue->VerifyItem( pContinue ) == false )
{
throw( (sInt32)eDSInvalidContinueData );
}
}
void * aNIDomain = RetrieveNIDomain(inContext);
if (aNIDomain != NULL)
{
if ( pContinue->fAuthPass == 0 )
{
pAuthStr = GetAuthString( inAuthMethod );
if ( pAuthStr == nil ) throw( (sInt32)eDSAuthMethodNotSupported );
authHndl = ::timServerForDomain( aNIDomain );
if ( authHndl == nil ) throw( (sInt32)eDSAuthNoAuthServerFound );
pAuthBuff = ::bufferFromString( pAuthStr->GetData() );
siResult = ::timSessionStart( authHndl, 0, pAuthBuff);
::bufferRelease( pAuthBuff );
pAuthBuff = nil;
if ( siResult != eDSNoErr ) throw( siResult );
pContinue->fAuthHndl = authHndl;
delete( pAuthStr );
pAuthStr = nil;
}
else
{
if ( *inOutContinueData == NULL )
{
throw( (sInt32)eDSInvalidContext );
}
}
pContinue->fAuthPass++;
authData = inAuthData;
outData = outAuthData;
authHndl = (TIMHandle *)pContinue->fAuthHndl;
pAuthBuff = ::bufferFromData( authData->fBufferData, authData->fBufferLength );
siResult = ::timSessionStep( authHndl, pAuthBuff, &pAuthOutBuff );
::bufferRelease( pAuthBuff );
pAuthBuff = nil;
if ( (siResult != TimStatusOK) && (siResult != TimStatusContinue) )
{
::bufferRelease( pAuthOutBuff );
pAuthOutBuff = nil;
::timSessionEnd( authHndl );
authHndl = nil;
gNIContinue->RemoveItem( pContinue );
*inOutContinueData = nil;
if ( siResult != eDSNoErr ) throw( siResult );
}
if ( ::bufferLength( pAuthOutBuff ) <= outData->fBufferSize )
{
::memcpy( outData->fBufferData, pAuthOutBuff->data, pAuthOutBuff->length );
outData->fBufferLength = pAuthOutBuff->length;
::bufferRelease( pAuthOutBuff );
if ( siResult == TimStatusOK )
{
::timSessionEnd( authHndl );
authHndl = nil;
gNIContinue->RemoveItem( pContinue );
*inOutContinueData = nil;
}
else if ( siResult == TimStatusContinue )
{
pContinue->fAuthHndl = authHndl;
*inOutContinueData = pContinue;
siResult = eDSNoErr;
}
}
}
else
{
throw( (sInt32)eDSInvalidSession );
}
}
catch( sInt32 err )
{
siResult = err;
if ( siResult > -14000 )
{
#ifdef DEBUG
switch ( siResult )
{
case TimStatusUserUnknown:
siResult = eDSAuthUnknownUser;
break;
case TimStatusInvalidName:
siResult = eDSAuthInvalidUserName;
break;
case TimStatusUnrecoverablePassword:
siResult = eDSAuthCannotRecoverPasswd;
break;
case TimStatusAuthenticationFailed:
siResult = eDSAuthFailed;
break;
default:
DBGLOG1( kLogPlugin, "Authentication Server Error = %d.", siResult);
siResult = eDSAuthServerError;
break;
}
if ( siResult != TimStatusOK )
{
DBGLOG1( kLogPlugin, "-- DoMultiPassAuth -- failed with %l.", siResult );
}
#else
siResult = eDSAuthFailed;
#endif
}
}
gNetInfoMutex->Signal();
#endif
return( siResult );
}
bool CNiPlugIn::IsTimRunning()
{
bool bTimRunning = false;
#ifdef TIM_CLIENT_PRESENT
TIMHandle* timHandle = NULL;
ni_status niStatus = NI_OK;
void* domain = NULL;
Buffer *tagBuffer;
int timSessionStatus;
if ( time(nil) < gCheckTimAgainTime )
{
return gTimIsRunning;
}
gNetInfoMutex->Wait();
gTimIsRunning = false;
gCheckTimAgainTime = time( nil) + 60;
niStatus = netinfo_open( NULL, ".", &domain, 10 );
if (niStatus == NI_OK)
{
timHandle = ::timServerForDomain( domain );
if (timHandle != NULL)
{
tagBuffer = bufferFromString("local");
timHandleSetTag(timHandle, tagBuffer);
bufferRelease(tagBuffer);
tagBuffer = bufferFromString("Status NetInfo Domain");
timSessionStatus = timSessionStart(timHandle, TimOpUtility, tagBuffer);
bufferRelease(tagBuffer);
if (timSessionStatus == TimStatusOK)
{
timSessionStatus = timSessionStep(timHandle, NULL, &tagBuffer);
bufferRelease(tagBuffer);
if (timSessionStatus == TimStatusOK)
{
bTimRunning = true;
gTimIsRunning = true;
}
timSessionEnd(timHandle);
}
::timHandleFree( timHandle );
timHandle = NULL;
}
}
gNetInfoMutex->Signal();
#endif
return bTimRunning;
}
#pragma mark -
#pragma mark Other Auth Routines
#pragma mark -
sInt32 CNiPlugIn::DoNodeNativeAuth ( sNIContextData *inContext, tDataBuffer *inAuthData, bool inAuthOnly, const char *inNativeRecType )
{
sInt32 siResult = eDSAuthFailed;
#ifdef TIM_CLIENT_PRESENT
TIMHandle *timHandle = nil;
char *pathStr = nil;
char *pData = nil;
char *userName = nil;
uInt32 nameLen = 0;
char *pwd = nil;
uInt32 pwdLen = 0;
gNetInfoMutex->Wait();
if ( !IsTimRunning() )
{
gNetInfoMutex->Signal();
return( eDSAuthMethodNotSupported );
}
try
{
if ( inAuthData != nil )
{
pData = inAuthData->fBufferData;
if ( pData != nil )
{
{
::memcpy( &nameLen, pData, sizeof( unsigned long ) );
if ( nameLen != 0 )
{
userName = (char *)::calloc( 1, nameLen + 1 );
pData += sizeof( unsigned long );
::memcpy( userName, pData, nameLen );
pData += nameLen;
::memcpy( &pwdLen, pData, sizeof( unsigned long ) );
if ( pwdLen != 0 )
{
pwd = (char *)::calloc( 1, pwdLen + 1 );
pData += sizeof( unsigned long );
::memcpy( pwd, pData, pwdLen );
pData += pwdLen;
DBGLOG( kLogPlugin, "Attempting Auth Server Node Native Authentication." );
void * aNIDomain = RetrieveNIDomain(inContext);
if (aNIDomain != NULL)
{
timHandle = timServerForDomain( aNIDomain );
if ( timHandle == nil ) throw( (sInt32)eDSAuthFailed );
siResult = ::timAuthenticate2WayRandomWithTIMHandle( timHandle, userName, pwd );
timHandleFree( timHandle );
timHandle = nil;
}
else
{
throw( (sInt32)eDSInvalidSession );
}
#ifdef DEBUG
if ( siResult != TimStatusOK )
{
DBGLOG1( kLogPlugin, "-- timAuthenticate2WayRandom -- failed with %l.", siResult );
}
#endif
siResult = MapAuthResult( siResult );
if ( (siResult == eDSNoErr) && (inAuthOnly == false) )
{
siResult = AuthOpen( inContext, userName, pwd );
}
bzero(pwd, pwdLen);
free( pwd );
pwd = nil;
}
else
{
#ifdef DEBUG
siResult = eDSAuthInBuffFormatError;
#else
siResult = eDSAuthFailed;
#endif
}
free( userName );
userName = nil;
}
else
{
#ifdef DEBUG
siResult = eDSAuthInBuffFormatError;
#else
siResult = eDSAuthFailed;
#endif
}
}
}
else
{
siResult = eDSNullDataBuff;
}
}
else
{
siResult = eDSNullDataBuff;
}
}
catch( sInt32 err )
{
DBGLOG1( kLogPlugin, "2 way random authentication error %l.", err );
siResult = err;
}
gNetInfoMutex->Signal();
if ( pathStr != nil )
{
free( pathStr );
pathStr = nil;
}
#endif
return( siResult );
}
sInt32 CNiPlugIn::DoUnixCryptAuth ( sNIContextData *inContext, tDataBuffer *inAuthData, bool inAuthOnly, const char *inNativeRecType )
{
sInt32 siResult = eDSAuthFailed;
bool bFreePropList = false;
bool bResetCache = false;
ni_index niWhere = 0;
char *pData = nil;
char *niPwd = nil;
char *name = nil;
uInt32 nameLen = 0;
char *pwd = nil;
uInt32 pwdLen = 0;
uInt32 offset = 0;
uInt32 buffSize = 0;
uInt32 buffLen = 0;
char salt[ 9 ];
char hashPwd[ 32 ];
ni_id niDirID;
ni_proplist niPropList;
gNetInfoMutex->Wait();
try
{
#ifdef DEBUG
if ( inAuthData == nil ) throw( (sInt32)eDSAuthParameterError );
#else
if ( inAuthData == nil ) throw( (sInt32)eDSAuthFailed );
#endif
pData = inAuthData->fBufferData;
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 ) );
pData += sizeof( unsigned long );
offset += sizeof( unsigned long );
#ifdef DEBUG
if (nameLen == 0) throw( (sInt32)eDSAuthUnknownUser );
if (nameLen > 256) throw( (sInt32)eDSInvalidBuffFormat );
if (offset + nameLen > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
#else
if (nameLen == 0) throw( (sInt32)eDSAuthFailed );
if (nameLen > 256) throw( (sInt32)eDSAuthFailed );
if (offset + nameLen > buffLen) throw( (sInt32)eDSAuthFailed );
#endif
name = (char *)::calloc( nameLen + 1, sizeof( char ) );
::memcpy( name, pData, nameLen );
pData += nameLen;
offset += nameLen;
DBGLOG( kLogPlugin, "Attempting UNIX Crypt authentication" );
void * aNIDomain = RetrieveNIDomain(inContext);
if (aNIDomain != NULL)
{
siResult = IsValidRecordName ( name, inNativeRecType, aNIDomain, niDirID );
#ifdef DEBUG
if ( siResult != eDSNoErr ) throw( (sInt32)eDSAuthUnknownUser );
#else
if ( siResult != eDSNoErr ) throw( (sInt32)eDSAuthFailed );
#endif
siResult = ::ni_read( aNIDomain, &niDirID, &niPropList );
#ifdef DEBUG
if ( siResult != eDSNoErr ) throw( (sInt32)eDSAuthUnknownUser );
if ( niPropList.ni_proplist_val == nil ) throw( (sInt32)eDSAuthUnknownUser );
#else
if ( siResult != eDSNoErr ) throw( (sInt32)eDSAuthFailed );
if ( niPropList.ni_proplist_val == nil ) throw( (sInt32)eDSAuthFailed );
#endif
bFreePropList = true;
niWhere = ::ni_proplist_match( niPropList, "passwd", nil );
#ifdef DEBUG
if (niWhere == NI_INDEX_NULL) throw( (sInt32)eDSAuthBadPassword );
siResult = eDSAuthBadPassword;
#else
if (niWhere == NI_INDEX_NULL) throw( (sInt32)eDSAuthFailed );
siResult = eDSAuthFailed;
#endif
if ((niPropList.ni_proplist_val[ niWhere ].nip_val.ni_namelist_len > 0)
&& (niPropList.ni_proplist_val[ niWhere ].nip_val.ni_namelist_val != nil))
{
niPwd = niPropList.ni_proplist_val[ niWhere ].nip_val.ni_namelist_val[ 0 ];
}
else
{
niPwd = (char*)""; }
#ifdef DEBUG
if (offset + sizeof( unsigned long ) > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
#else
if (offset + sizeof( unsigned long ) > buffLen) throw( (sInt32)eDSAuthFailed );
#endif
::memcpy( &pwdLen, pData, sizeof( unsigned long ) );
pData += sizeof( unsigned long );
offset += sizeof( unsigned long );
#ifdef DEBUG
if (offset + pwdLen > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
if (pwdLen > 256) throw( (sInt32)eDSAuthFailed );
#else
if (offset + pwdLen > buffLen) throw( (sInt32)eDSAuthFailed );
if (pwdLen > 256) throw( (sInt32)eDSAuthFailed );
#endif
pwd = (char *)::calloc( pwdLen + 1, sizeof( char ) );
::memcpy( pwd, pData, pwdLen );
if (::strcmp(niPwd,"") != 0)
{
salt[ 0 ] = niPwd[0];
salt[ 1 ] = niPwd[1];
salt[ 2 ] = '\0';
::memset( hashPwd, 0, 32 );
::strcpy( hashPwd, ::crypt( pwd, salt ) );
siResult = eDSAuthFailed;
if ( ::strcmp( hashPwd, niPwd ) == 0 )
{
siResult = eDSNoErr;
}
bzero(hashPwd, 32);
}
else {
if ( ::strcmp(pwd,"") == 0 )
{
siResult = eDSNoErr;
}
}
if (siResult == eDSNoErr)
{
if ( inContext->bIsLocal && (strlen(pwd) < 8) ) {
MigrateToShadowHash(aNIDomain, &niDirID, &niPropList, name, pwd, bResetCache);
}
if (inAuthOnly == false)
{
siResult = AuthOpen( inContext, name, pwd );
}
}
}
else
{
#ifdef DEBUG
siResult = eDSInvalidSession;
#else
siResult = eDSAuthFailed;
#endif
}
}
catch( sInt32 err )
{
DBGLOG1( kLogPlugin, "Crypt authentication error %l", err );
siResult = err;
}
if ( bFreePropList )
{
::ni_proplist_free( &niPropList );
}
gNetInfoMutex->Signal();
if ( bResetCache )
{
gSrvrCntl->HandleMemberDaemonFlushCache();
}
if ( name != nil )
{
free( name );
name = nil;
}
if ( pwd != nil )
{
bzero(pwd, strlen(pwd));
free( pwd );
pwd = nil;
}
return( siResult );
}
sInt32 CNiPlugIn::ValidateDigest ( sNIContextData *inContext, tDataBuffer *inAuthData, uInt32 inAuthMethod )
{
sInt32 siResult = eDSAuthFailed;
#ifdef TIM_CLIENT_PRESENT
TIMHandle *pTimHndl = nil;
char *pathStr = nil;
char *pData = nil;
char *pUserName = nil;
uInt32 nameLen = 0;
char *pChallenge = nil;
uInt32 chalLen = 0;
char *pResponse = nil;
uInt32 respLen = 0;
sInt32 siBuffErr = 0;
#ifdef DEBUG
siBuffErr = eDSAuthInBuffFormatError;
#else
siBuffErr = eDSAuthFailed;
#endif
gNetInfoMutex->Wait();
if ( !IsTimRunning() )
{
gNetInfoMutex->Signal();
return( eDSAuthMethodNotSupported );
}
try
{
if ( inAuthData != nil )
{
pData = inAuthData->fBufferData;
if ( pData != nil )
{
::memcpy( &nameLen, pData, sizeof( unsigned long ) );
if ( nameLen != 0 )
{
pUserName = (char *)::calloc( 1, nameLen + 1 );
pData += sizeof( unsigned long );
::memcpy( pUserName, pData, nameLen );
pData += nameLen;
::memcpy( &chalLen, pData, sizeof( unsigned long ) );
if ( chalLen != 0 )
{
pChallenge = (char *)::calloc( 1, chalLen + 1 );
pData += sizeof( unsigned long );
::memcpy( pChallenge, pData, chalLen );
pData += chalLen;
::memcpy( &respLen, pData, sizeof( unsigned long ) );
if ( respLen != 0 )
{
pResponse = (char *)::calloc( 1, respLen + 1 );
pData += sizeof( unsigned long );
::memcpy( pResponse, pData, respLen );
pData += respLen;
DBGLOG( kLogPlugin, "Attempting Auth ValidateDigest." );
void * aNIDomain = RetrieveNIDomain(inContext);
if (aNIDomain != NULL)
{
pTimHndl = ::timServerForDomain( aNIDomain );
if ( pTimHndl == nil ) throw( (sInt32)eDSAuthFailed );
if ( inAuthMethod == kAuthAPOP )
{
siResult = ::timAuthenticateAPOPWithTIMHandle( pTimHndl, pUserName, pChallenge, pResponse );
}
else if ( inAuthMethod == kAuthCRAM_MD5 )
{
siResult = ::timAuthenticateCRAM_MD5WithTIMHandle( pTimHndl, pUserName, pChallenge, pResponse );
}
else
{
siResult = TimStatusServiceUnavailable;
}
timHandleFree( pTimHndl );
pTimHndl = nil;
}
else
{
throw( (sInt32)eDSInvalidSession );
}
#ifdef DEBUG
if ( siResult != TimStatusOK )
{
DBGLOG1( kLogPlugin, "-- timAuthenticateCRAM_MD5WithTIMHandle -- failed with %l.", siResult );
}
#endif
siResult = MapAuthResult( siResult );
bzero(pResponse, strlen(pResponse));
free( pResponse );
pResponse = nil;
}
else
{
siResult = siBuffErr;
}
bzero(pChallenge, strlen(pChallenge));
free( pChallenge );
pChallenge = nil;
}
else
{
siResult = siBuffErr;
}
free( pUserName );
pUserName = nil;
}
else
{
siResult = siBuffErr;
}
}
else
{
siResult = eDSNullDataBuff;
}
}
else
{
siResult = eDSNullDataBuff;
}
}
catch( sInt32 err )
{
DBGLOG1( kLogPlugin, "2 way random authentication error %l.", err );
siResult = err;
}
gNetInfoMutex->Signal();
if ( pathStr != nil )
{
free( pathStr );
pathStr = nil;
}
#endif
return( siResult );
}
sInt32 CNiPlugIn::AuthOpen ( sNIContextData *inContext, const char * inUserName,
const char * inPassword, bool bIsEffectiveRoot )
{
sInt32 siResult = eDSAuthFailed;
void *domain = nil;
gNetInfoMutex->Wait();
try
{
if ( inContext == nil ) throw( (sInt32)eDSAuthFailed );
if ( inUserName == nil ) throw( (sInt32)eDSAuthFailed );
if ( inPassword == nil ) throw( (sInt32)eDSAuthFailed );
if ( inContext->fDomainPath == nil ) throw( (sInt32)eDSAuthFailed );
siResult = ::ni_open( nil, inContext->fDomainPath, &domain );
if ( siResult != eDSNoErr ) throw( (sInt32)eDSAuthFailed );
DBGLOG1( kLogPlugin, "CNiPlugIn::AuthOpen: <ni_open> opened for auth the netinfo node %s", inContext->fDomainPath );
if (!bIsEffectiveRoot)
{
siResult = ::ni_setuser( domain, inUserName );
if ( siResult != eDSNoErr ) throw( (sInt32)eDSAuthFailed );
siResult = ::ni_setpassword( domain, inPassword );
if ( siResult != eDSNoErr ) throw( (sInt32)eDSAuthFailed );
}
if ( siResult == NI_OK )
{
if ( inContext->fDontUseSafeClose )
{
::ni_free(inContext->fDomain);
}
else if (inContext->fDomainName != nil)
{
CNetInfoPlugin::SafeClose( inContext->fDomainName );
}
inContext->fDomain = domain;
inContext->fDontUseSafeClose = true;
if ( inContext->fAuthenticatedUserName != NULL )
{
free( inContext->fAuthenticatedUserName );
}
if (UserIsAdminInDomain(inUserName, domain))
{
inContext->fAuthenticatedUserName = strdup( "root" );
}
else
{
inContext->fAuthenticatedUserName = strdup( inUserName );
}
}
}
catch( sInt32 err )
{
if ( domain != nil )
{
::ni_free(domain);
domain = nil;
}
siResult = err;
}
gNetInfoMutex->Signal();
return siResult;
}
#pragma mark -
#pragma mark Support Routines
#pragma mark -
sInt32 CNiPlugIn::VerifyPatternMatch ( const tDirPatternMatch inPatternMatch )
{
sInt32 siResult = eDSNoErr;
switch ( inPatternMatch )
{
case eDSExact:
case eDSStartsWith:
case eDSEndsWith:
case eDSContains:
case eDSLessThan:
case eDSGreaterThan:
case eDSLessEqual:
case eDSGreaterEqual:
case eDSiExact:
case eDSiStartsWith:
case eDSiEndsWith:
case eDSiContains:
case eDSiLessThan:
case eDSiGreaterThan:
case eDSiLessEqual:
case eDSiGreaterEqual:
case eDSAnyMatch:
siResult = eDSNoErr;
break;
default:
siResult = eDSInvalidPatternMatchType;
break;
}
return( siResult );
}
CString* CNiPlugIn::GetAuthTypeStr ( const char *inNativeAuthStr )
{
CString *pOutString = nil;
if ( inNativeAuthStr == nil )
{
return( nil );
}
pOutString = new CString( 128 );
if ( pOutString == nil )
{
return( nil );
}
#ifdef TIM_CLIENT_PRESENT
if ( ::strcmp( inNativeAuthStr, AppleStandardCleartext ) == 0 )
{
pOutString->Set( kDSStdAuthClearText );
}
else if ( ::strcmp( inNativeAuthStr, AppleStandardTwoWay ) == 0 )
{
pOutString->Set( kDSStdAuth2WayRandom );
}
else if ( ::strcmp( inNativeAuthStr, AppleStandardSMBNTKey ) == 0 )
{
pOutString->Set( kDSStdAuthSMB_NT_Key );
}
else if ( ::strcmp( inNativeAuthStr, AppleStandardSMBLMKey ) == 0 )
{
pOutString->Set( kDSStdAuthSMB_LM_Key );
}
else
#endif
{
pOutString->Set( kDSNativeAuthMethodPrefix );
pOutString->Append( inNativeAuthStr );
}
return( pOutString );
}
CString* CNiPlugIn::GetAuthString ( tDataNode *inData )
{
CString *pOutString = nil;
#ifdef TIM_CLIENT_PRESENT
char *p = nil;
uInt32 uiNativeLen = 0;
uInt32 uiStrLen = 0;
if ( inData == nil )
{
return( nil );
}
pOutString = new CString( 128 );
if ( pOutString == nil )
{
return( nil );
}
p = (char *)inData->fBufferData;
if ( ::strcmp( p, kDSStdAuthClearText ) == 0 )
{
pOutString->Set( AppleStandardCleartext );
}
else if ( (::strcmp( p, kDSStdAuthNodeNativeClearTextOK ) == 0) ||
(::strcmp( p, kDSStdAuthNodeNativeNoClearText) == 0 ) )
{
pOutString->Set( AppleStandardTwoWay );
}
else if ( ::strcmp( p, kDSStdAuth2WayRandom ) == 0 )
{
pOutString->Set( AppleStandardTwoWay );
}
else if ( ::strcmp( p, kDSStdAuthSetPasswd ) == 0 )
{
pOutString->Set( AppleStandardSetPassword );
}
else if ( ::strcmp( p, kDSStdAuthChangePasswd ) == 0 )
{
pOutString->Set( AppleSetPasswordV2 );
}
else if ( ::strcmp( p, kDSStdAuthSetPasswdAsRoot ) == 0 )
{
pOutString->Set( AppleSetPasswordV2 );
}
else if ( ::strcmp( p, kDSStdAuthSMB_NT_Key ) == 0 )
{
pOutString->Set( AppleStandardSMBNTKey );
}
else if ( ::strcmp( p, kDSStdAuthSMB_LM_Key ) == 0 )
{
pOutString->Set( AppleStandardSMBLMKey );
}
else
{
uiStrLen = ::strlen( p );
uiNativeLen = sizeof( kDSNativeAuthMethodPrefix ) - 1;
if ( ::strncmp( p, kDSNativeAuthMethodPrefix, uiNativeLen ) == 0 )
{
if ( uiStrLen > uiNativeLen )
{
uiStrLen = uiStrLen - uiNativeLen;
pOutString->Set( p + uiNativeLen );
}
}
else
{
delete( pOutString );
pOutString = nil;
}
}
#endif
return( pOutString );
}
sInt32 CNiPlugIn::MapAuthResult ( sInt32 inAuthErr )
{
sInt32 siResult = eUndefinedError;
switch ( inAuthErr )
{
#ifdef TIM_CLIENT_PRESENT
case TimStatusOK:
siResult = eDSNoErr;
break;
#ifdef DEBUG
case TimStatusContinue:
siResult = eDSContinue;
break;
case TimStatusServerTimeout:
siResult = eDSServerTimeout;
break;
case TimStatusInvalidHandle:
siResult = eDSInvalidHandle;
break;
case TimStatusSendFailed:
siResult = eDSSendFailed;
break;
case TimStatusReceiveFailed:
siResult = eDSReceiveFailed;
break;
case TimStatusBadPacket:
siResult = eDSBadPacket;
break;
case TimStatusInvalidTag:
siResult = eDSInvalidTag;
break;
case TimStatusInvalidSession:
siResult = eDSInvalidSession;
break;
case TimStatusInvalidName:
siResult = eDSInvalidName;
break;
case TimStatusUserUnknown:
siResult = eDSUserUnknown;
break;
case TimStatusUnrecoverablePassword:
siResult = eDSUnrecoverablePassword;
break;
case TimStatusAuthenticationFailed:
siResult = eDSAuthenticationFailed;
break;
case TimStatusBogusServer:
siResult = eDSBogusServer;
break;
case TimStatusOperationFailed:
siResult = eDSOperationFailed;
break;
case TimStatusNotAuthorized:
siResult = eDSNotAuthorized;
break;
case TimStatusNetInfoError:
siResult = eDSNetInfoError;
break;
case TimStatusContactMaster:
siResult = eDSContactMaster;
break;
case TimStatusServiceUnavailable:
siResult = eDSServiceUnavailable;
break;
#endif
#endif
default:
siResult = eDSAuthFailed;
break;
}
return( siResult );
}
void CNiPlugIn::MakeGood( char *inStr, char *outStr )
{
uInt32 uiI = 0;
uInt32 uiJ = 0;
if ( (inStr != nil) && (outStr != nil) )
{
while ( inStr[ uiI ] != '\0' )
{
if ( (inStr[ uiI ] == '\\') && (inStr[ uiI + 1 ] == '/') )
{
uiI++;
}
outStr[ uiJ ] = inStr[ uiI ];
uiI++;
uiJ++;
}
outStr[ uiJ ] = '\0';
}
}
sNIContextData* CNiPlugIn::MakeContextData ( void )
{
sNIContextData *pOut = nil;
pOut = (sNIContextData *) ::calloc( 1, sizeof( sNIContextData) );
pOut->fUID = (uid_t)-2;
pOut->fEffectiveUID = (uid_t)-2;
pOut->bIsLocal = false;
return( pOut );
}
sInt32 CNiPlugIn::CleanContextData ( sNIContextData *inContext )
{
sInt32 siResult = eDSNoErr;
if ( inContext == nil )
{
siResult = eDSBadContextData;
}
else
{
if (inContext->fDomain != nil)
{
if ( inContext->fDontUseSafeClose )
{
gNetInfoMutex->Wait();
::ni_free(inContext->fDomain);
gNetInfoMutex->Signal();
inContext->fDomain = nil;
}
}
else if (inContext->fDomainName != nil)
{
CNetInfoPlugin::SafeClose( inContext->fDomainName );
}
DSFreeString(inContext->fDomainName);
DSFreeString(inContext->fDomainPath);
DSFreeString(inContext->fRecType);
DSFreeString(inContext->fRecName);
DSFreeString(inContext->fAuthenticatedUserName);
inContext->offset = 0;
inContext->fDontUseSafeClose = false;
inContext->bIsLocal = false;
inContext->bDidWriteOperation = false;
if ( inContext->fPWSNodeRef != 0 ) {
dsCloseDirNode(inContext->fPWSNodeRef);
inContext->fPWSNodeRef = 0;
}
if ( inContext->fPWSRef != 0 ) {
dsCloseDirService(inContext->fPWSRef);
inContext->fPWSRef = 0;
}
if (inContext->fLocalCacheNetNode != NULL)
{
dsDataListDeallocatePriv(inContext->fLocalCacheNetNode);
free(inContext->fLocalCacheNetNode);
inContext->fLocalCacheNetNode = NULL;
}
if (inContext->fLocalCacheRef != 0)
{
dsCloseDirService(inContext->fLocalCacheRef);
inContext->fLocalCacheRef = 0;
}
}
return( siResult );
}
bool CNiPlugIn::DoAnyMatch ( const char *inString,
CAttributeList *inPattMatchList,
tDirPatternMatch inHow )
{
bool bOutResult = false;
CFMutableStringRef strRef = CFStringCreateMutable(NULL, 0);
CFMutableStringRef patRef = NULL;
CFRange range;
if ( (inString == nil) || (inPattMatchList == nil) || (strRef == nil) )
{
return( false );
}
if (inPattMatchList->GetCount() < 1)
{
return( false );
}
CFStringAppendCString( strRef, inString, kCFStringEncodingUTF8 );
for (uInt32 idx = 1; idx <= inPattMatchList->GetCount(); idx++)
{
char *aStringValue = nil;
if ( eDSNoErr == inPattMatchList->GetAttribute(idx, &aStringValue) )
{
patRef = CFStringCreateMutable(NULL, 0);
CFStringAppendCString( patRef, aStringValue, kCFStringEncodingUTF8 );
if ( (inHow >= eDSiExact) && (inHow <= eDSiRegularExpression) )
{
CFStringUppercase( strRef, NULL );
CFStringUppercase( patRef, NULL );
}
switch ( inHow )
{
case eDSExact:
case eDSiExact:
{
if ( CFStringCompare( strRef, patRef, 0 ) == kCFCompareEqualTo )
{
bOutResult = true;
}
}
break;
case eDSStartsWith:
case eDSiStartsWith:
{
if ( CFStringHasPrefix( strRef, patRef ) )
{
bOutResult = true;
}
}
break;
case eDSEndsWith:
case eDSiEndsWith:
{
if ( CFStringHasSuffix( strRef, patRef ) )
{
bOutResult = true;
}
}
break;
case eDSContains:
case eDSiContains:
{
range = CFStringFind( strRef, patRef, 0 );
if ( range.location != kCFNotFound )
{
bOutResult = true;
}
}
break;
case eDSLessThan:
case eDSiLessThan:
{
if ( CFStringCompare( strRef, patRef, 0 ) == kCFCompareLessThan )
{
bOutResult = true;
}
}
break;
case eDSGreaterThan:
case eDSiGreaterThan:
{
if ( CFStringCompare( strRef, patRef, 0 ) == kCFCompareGreaterThan )
{
bOutResult = true;
}
}
break;
case eDSLessEqual:
case eDSiLessEqual:
{
if ( CFStringCompare( strRef, patRef, 0 ) != kCFCompareGreaterThan )
{
bOutResult = true;
}
}
break;
case eDSGreaterEqual:
case eDSiGreaterEqual:
{
if ( CFStringCompare( strRef, patRef, 0 ) != kCFCompareLessThan )
{
bOutResult = true;
}
}
break;
default:
break;
}
CFRelease( patRef );
patRef = nil;
if (bOutResult)
{
break;
}
}
}
CFRelease( strRef );
strRef = nil;
return( bOutResult );
}
char* CNiPlugIn:: BuildRegExp ( const char *inString )
{
char *outRegExp = nil;
unsigned long i = 0;
unsigned long j = 0;
unsigned long inLength = 0;
if (inString == nil)
{
return( outRegExp );
}
outRegExp = (char *) calloc( 1, 1 + 2*strlen(inString) );
j = 0;
inLength = strlen(inString);
for (i=0; i< inLength; i++)
{
if ( (isascii(inString[i])) && ( (inString[i]) != '(' ) && ( (inString[i]) != ')' ) && ( (inString[i]) != '{' ) && ( (inString[i]) != '}' ) )
{
if (isalnum(inString[i]) || isspace(inString[i]) || (inString[i]) == '_' || (inString[i]) == '-')
{
memcpy(outRegExp+j,&inString[i],1);
j++;
}
else
{
memcpy(outRegExp+j,"\\",1);
j++;
memcpy(outRegExp+j,& inString[i],1);
j++;
}
}
else
{
memcpy(outRegExp+j,".",1);
j++;
}
}
return( outRegExp );
}
char* CNiPlugIn:: BuildMultiRegExp ( CAttributeList *inPattMatchList )
{
char *outRegExp = nil;
char **regExpStrs = nil;
unsigned long i = 0;
unsigned long j = 0;
unsigned long inLength = 0;
uInt32 lenOfStrs = 0;
char *loopString = nil;
uInt32 partCount = 0;
uInt32 idx = 0;
if ( (inPattMatchList == nil) || (inPattMatchList->GetCount() < 1) )
{
return( outRegExp );
}
if (inPattMatchList->GetCount() == 1)
{
char *aStringValue = nil;
if (inPattMatchList->GetAttribute(1, &aStringValue) == eDSNoErr)
{
return(BuildRegExp(aStringValue));
}
else
{
return(nil);
}
}
partCount = inPattMatchList->GetCount();
regExpStrs = (char **)calloc( partCount + 1, sizeof(char *) );
for (idx = 0; idx < partCount; idx++)
{
if ( eDSNoErr == inPattMatchList->GetAttribute(idx+1, &loopString) )
{
inLength = strlen(loopString);
regExpStrs[idx] = (char *) calloc( 1, 1 + 2*inLength );
j = 0;
for (i=0; i< inLength; i++)
{
if ( (isascii(loopString[i])) && ( (loopString[i]) != '(' ) && ( (loopString[i]) != ')' ) && ( (loopString[i]) != '{' ) && ( (loopString[i]) != '}' ) )
{
if (isalnum(loopString[i]) || isspace(loopString[i]) || (loopString[i]) == '_' || (loopString[i]) == '-')
{
memcpy(regExpStrs[idx]+j,&loopString[i],1);
j++;
}
else
{
memcpy(regExpStrs[idx]+j,"\\",1);
j++;
memcpy(regExpStrs[idx]+j,& loopString[i],1);
j++;
}
}
else
{
memcpy(regExpStrs[idx]+j,".",1);
j++;
}
}
lenOfStrs += strlen(regExpStrs[idx]);
}
}
outRegExp = (char *)calloc(1, lenOfStrs + partCount);
strcpy(outRegExp,regExpStrs[0]);
free(regExpStrs[0]);
for (idx = 1; idx < partCount; idx++)
{
strcat(outRegExp,"|");
strcat(outRegExp,regExpStrs[idx]);
free(regExpStrs[idx]);
}
free(regExpStrs);
return( outRegExp );
}
void CNiPlugIn::ContinueDeallocProc ( void* inContinueData )
{
sNIContinueData *pContinue = (sNIContinueData *)inContinueData;
if ( pContinue != nil )
{
if ( pContinue->fDataBuff != nil )
{
::dsDataBufferDeallocatePriv( pContinue->fDataBuff );
pContinue->fDataBuff = nil;
}
if ( pContinue->fNIEntryList.ni_entrylist_len > 0 )
{
::ni_entrylist_free(&(pContinue->fNIEntryList));
pContinue->fNIEntryList.ni_entrylist_len = 0;
}
free( pContinue );
pContinue = nil;
}
}
void CNiPlugIn::ContextDeallocProc ( void* inContextData )
{
sNIContextData *pContext = (sNIContextData *) inContextData;
if ( pContext != nil )
{
CleanContextData( pContext );
free( pContext );
pContext = nil;
}
}
sInt32 CNiPlugIn::IsValidRealname ( char *inRealname,
void *inDomain,
char **outRecName )
{
sInt32 siResult = eDSInvalidRecordName;
ni_id niDirID;
ni_status niStatus = NI_OK;
char *normalizedRealname = nil;
char *inConstRegExpRecName = nil;
ni_entrylist niEntryList;
u_int en = 0;
ni_entry niEntry;
ni_proplist niPropList;
ni_index niIndex = 0;
ni_index niIndexComp = 0;
gNetInfoMutex->Wait();
NI_INIT( &niDirID );
NI_INIT( &niEntry );
NI_INIT( &niPropList );
NI_INIT( &niEntryList );
niStatus = ::ni_pathsearch( inDomain, &niDirID, "/users" );
if ( niStatus == NI_OK )
{
normalizedRealname = NormalizeNIString(inRealname, "realname");
inConstRegExpRecName = BuildRegExp(normalizedRealname);
niStatus = ::ni_search( inDomain, &niDirID, (char *)"realname", inConstRegExpRecName, REG_ICASE, &niEntryList );
DSFreeString(inConstRegExpRecName);
if ( niStatus == NI_OK )
{
for ( en = 0; en < niEntryList.ni_entrylist_len; en++ )
{
niEntry = niEntryList.ni_entrylist_val[ en ];
niDirID.nii_object = niEntry.id;
niStatus = ::ni_read( inDomain, &niDirID, &niPropList );
if ( niStatus == NI_OK )
{
niIndex = ::ni_proplist_match( niPropList, "realname", NULL );
if ( niIndex != NI_INDEX_NULL )
{
if (DoesThisMatch( (const char*)(niPropList.nipl_val[ niIndex ].nip_val.ninl_val[ 0 ]),
(const char*)normalizedRealname, eDSExact ))
{
niIndexComp = ::ni_proplist_match( niPropList, "name", NULL );
if ( niIndexComp != NI_INDEX_NULL )
{
*outRecName = (char *) calloc( 1, 1 + strlen(niPropList.nipl_val[ niIndexComp ].nip_val.ninl_val[ 0 ]) );
strcpy(*outRecName,niPropList.nipl_val[ niIndexComp ].nip_val.ninl_val[ 0 ]);
siResult = eDSNoErr;
::ni_proplist_free( &niPropList );
break;
}
}
} ::ni_proplist_free( &niPropList );
}
}
if (niEntryList.ni_entrylist_len > 0)
{
::ni_entrylist_free( &niEntryList );
niEntryList.ni_entrylist_len = 0;
}
} if ( normalizedRealname != inRealname )
{
DSFreeString( normalizedRealname );
}
}
gNetInfoMutex->Signal();
return( siResult );
}
char* CNiPlugIn::GetUserNameForUID ( uid_t inUserID,
void *inDomain )
{
ni_id niDirID;
ni_status niStatus = NI_OK;
ni_proplist niPropList;
ni_entry niEntry;
ni_entrylist niEntryList;
ni_namelist niValues;
char idStr[ 64 ] = { 0 };
u_int en = 0;
char* userName = NULL;
if ( inDomain == NULL ) {
return NULL;
}
gNetInfoMutex->Wait();
NI_INIT( &niDirID );
NI_INIT( &niEntry );
NI_INIT( &niPropList );
NI_INIT( &niEntryList );
NI_INIT( &niValues );
niStatus = ::ni_pathsearch( inDomain, &niDirID, "/users" );
if (niStatus == NI_OK) {
snprintf( idStr, 64, "%d", inUserID );
niStatus = ni_search( inDomain, &niDirID, "uid", idStr, REG_BASIC, &niEntryList );
if ( niStatus == NI_OK )
{
for ( en = 0; en < niEntryList.ni_entrylist_len; en++ )
{
niEntry = niEntryList.ni_entrylist_val[ en ];
niDirID.nii_object = niEntry.id;
niStatus = ni_lookupprop( inDomain, &niDirID, "name", &niValues );
if ( niStatus == NI_OK )
{
if (niValues.ni_namelist_len > 0)
{
if (niValues.ni_namelist_val[0] != NULL)
{
userName = strdup( niValues.ni_namelist_val[0] );
ni_namelist_free( &niValues );
break;
}
ni_namelist_free( &niValues );
}
}
}
} if ( niEntryList.ni_entrylist_len > 0 )
{
::ni_entrylist_free(&niEntryList);
niEntryList.ni_entrylist_len = 0;
}
}
gNetInfoMutex->Signal();
return userName;
}
NetInfoAuthAuthorityHandlerProc CNiPlugIn::GetNetInfoAuthAuthorityHandler ( const char* inTag )
{
if (inTag == NULL)
{
return NULL;
}
for (unsigned int i = 0; i < kNetInfoAuthAuthorityHandlerProcs; ++i)
{
if (strcasecmp(inTag,sNetInfoAuthAuthorityHandlerProcs[i].fTag) == 0)
{
return sNetInfoAuthAuthorityHandlerProcs[i].fHandler;
}
}
return NULL;
}
tDataList* CNiPlugIn::FindNodeForSearchPolicyAuthUser ( const char *userName )
{
sInt32 siResult = eDSNoErr;
sInt32 returnVal = -3;
unsigned long nodeCount = 0;
unsigned long recCount = 0;
tContextData context = NULL;
tDataListPtr nodeName = NULL;
tDataListPtr recName = NULL;
tDataListPtr recType = NULL;
tDataListPtr attrTypes = NULL;
tDataBufferPtr dataBuff = NULL;
tRecordEntry *pRecEntry = nil;
tAttributeListRef attrListRef = 0;
tAttributeValueListRef valueRef = 0;
tAttributeEntry *pAttrEntry = nil;
tAttributeValueEntry *pValueEntry = nil;
tDirReference aDSRef = 0;
tDirNodeReference aSearchNodeRef = 0;
try
{
siResult = dsOpenDirService( &aDSRef );
if ( siResult != eDSNoErr ) throw( siResult );
dataBuff = dsDataBufferAllocate( aDSRef, 2048 );
if ( dataBuff == nil ) throw( eMemoryAllocError );
siResult = dsFindDirNodes( aDSRef, dataBuff, nil,
eDSAuthenticationSearchNodeName, &nodeCount, &context );
if ( siResult != eDSNoErr ) throw( siResult );
siResult = dsGetDirNodeName( aDSRef, dataBuff, 1, &nodeName );
if ( siResult != eDSNoErr ) throw( siResult );
siResult = dsOpenDirNode( aDSRef, nodeName, &aSearchNodeRef );
if ( siResult != eDSNoErr ) throw( siResult );
if ( nodeName != NULL )
{
dsDataListDeallocate( aDSRef, nodeName );
free( nodeName );
nodeName = NULL;
}
recName = dsBuildListFromStrings( aDSRef, userName, NULL );
recType = dsBuildListFromStrings( aDSRef, kDSStdRecordTypeUsers, NULL );
attrTypes = dsBuildListFromStrings( aDSRef, kDSNAttrMetaNodeLocation, NULL );
recCount = 1; do
{
siResult = dsGetRecordList( aSearchNodeRef, dataBuff, recName, eDSExact, recType,
attrTypes, false, &recCount, &context);
if (siResult == eDSBufferTooSmall)
{
uInt32 bufSize = dataBuff->fBufferSize;
dsDataBufferDeallocatePriv( dataBuff );
dataBuff = nil;
dataBuff = ::dsDataBufferAllocate( aDSRef, bufSize * 2 );
}
} while ( (siResult == eDSBufferTooSmall) || ( (siResult == eDSNoErr) && (recCount == 0) && (context != nil) ) );
if ( (siResult == eDSNoErr) && (recCount > 0) )
{
siResult = ::dsGetRecordEntry( aSearchNodeRef, dataBuff, 1, &attrListRef, &pRecEntry );
if ( (siResult == eDSNoErr) && (pRecEntry != nil) )
{
for (unsigned int i = 1; i <= pRecEntry->fRecordAttributeCount; i++)
{
siResult = ::dsGetAttributeEntry( aSearchNodeRef, dataBuff, attrListRef, i, &valueRef, &pAttrEntry );
if ( ( siResult == eDSNoErr ) && ( pAttrEntry->fAttributeValueCount > 0 ) )
{
siResult = ::dsGetAttributeValue( aSearchNodeRef, dataBuff, 1, valueRef, &pValueEntry );
if ( ::strcmp( pAttrEntry->fAttributeSignature.fBufferData, kDSNAttrMetaNodeLocation ) == 0 )
{
nodeName = dsBuildFromPath( aDSRef, pValueEntry->fAttributeValueData.fBufferData, "/" );
}
if ( pValueEntry != NULL )
{
dsDeallocAttributeValueEntry( aDSRef, pValueEntry );
pValueEntry = NULL;
}
}
dsCloseAttributeValueList(valueRef);
if (pAttrEntry != nil)
{
dsDeallocAttributeEntry(aDSRef, pAttrEntry);
pAttrEntry = nil;
}
} } dsCloseAttributeList(attrListRef);
if (pRecEntry != nil)
{
dsDeallocRecordEntry(aDSRef, pRecEntry);
pRecEntry = nil;
}
} }
catch( sInt32 err )
{
returnVal = err;
}
if ( recName != NULL )
{
dsDataListDeallocate( aDSRef, recName );
free( recName );
recName = NULL;
}
if ( recType != NULL )
{
dsDataListDeallocate( aDSRef, recType );
free( recType );
recType = NULL;
}
if ( attrTypes != NULL )
{
dsDataListDeallocate( aDSRef, attrTypes );
free( attrTypes );
attrTypes = NULL;
}
if ( dataBuff != NULL )
{
dsDataBufferDeAllocate( aDSRef, dataBuff );
dataBuff = NULL;
}
if ( aSearchNodeRef != 0 )
{
dsCloseDirNode( aSearchNodeRef );
aSearchNodeRef = 0;
}
if ( aDSRef != 0 )
{
dsCloseDirService( aDSRef );
aDSRef = 0;
}
return nodeName;
}
sInt32 CNiPlugIn::GetSubNodes ( sNIContextData *inContext, set<string> & nodeNames )
{
sInt32 siResult = 0;
sInt32 entryListCnt = 0;
sInt32 entryListLen = 0;
sInt32 nameListCnt = 0;
sInt32 nameListlen = 0;
ni_status niStatus = NI_OK;
bool isLocal = false;
char *name = nil;
char *p = nil;
ni_namelist *nameList = nil;
ni_id machines;
ni_id niDirID;
ni_entrylist niEntryList;
char *domName = nil;
char *tempName = nil;
bool bNodeServes = false;
uInt32 pv = 0;
char *aNIDomainName = nil;
do
{
NI_INIT( &niDirID );
gNetInfoMutex->Wait();
void *aNIDomain = RetrieveNIDomain(inContext);
if (aNIDomain != NULL)
{
if (inContext->fDomainName != nil)
{
aNIDomainName = strdup(inContext->fDomainName);
}
do
{
NI_INIT( &machines );
siResult = ni_pathsearch( aNIDomain, &machines, "/machines" );
if ( siResult != eDSNoErr )
{
break;
}
NI_INIT( &niEntryList );
niStatus = ni_list( aNIDomain, &machines, "serves", &niEntryList );
if ( niStatus != NI_OK )
{
break;
}
}
while (false);
}
else
{
niStatus = (ni_status)eDSInvalidSession;
}
gNetInfoMutex->Signal();
if ( niStatus != 0 ) break;
entryListLen = niEntryList.ni_entrylist_len;
for ( entryListCnt = 0; entryListCnt < entryListLen; entryListCnt++ )
{
bNodeServes = false;
nameList = niEntryList.ni_entrylist_val[ entryListCnt ].names;
if (nameList != NULL)
{
for ( pv = 0; pv < nameList->ni_namelist_len; pv++ )
{
if (nil == strstr(nameList->ni_namelist_val[ pv ],"/local"))
{
bNodeServes = true;
break;
}
}
}
if (!bNodeServes)
{
continue;
}
if ( nameList == nil || nameList->ni_namelist_len == 0 )
{
continue;
}
nameListlen = nameList->ni_namelist_len;
for ( nameListCnt = 0; nameListCnt < nameListlen; nameListCnt++ )
{
name = nameList->ni_namelist_val[ nameListCnt ];
if ( ::strncmp( name, "./", 2 ) == 0
|| ::strncmp( name, "../", 3 ) == 0 )
{
continue;
}
isLocal = ::strstr( name, "/local" ) != nil;
p = strchr( name, '/' );
if ( p == nil )
{
continue;
}
*p = '\0';
if (domName != nil)
{
free(domName);
domName = nil;
}
if (aNIDomainName != nil)
{
domName = (char *)calloc(1, strlen(aNIDomainName) + 1 + strlen(name) + 1);
strcpy(domName, aNIDomainName);
if (strlen(domName) > 1)
{
strcat(domName,"/");
}
strcat(domName,name);
if (isLocal == false)
{
string aString(domName);
nodeNames.insert(aString);
}
}
}
if (tempName != nil)
{
free(tempName);
tempName = nil;
}
if (domName != nil)
{
free(domName);
domName = nil;
}
}
ni_entrylist_free(&niEntryList);
}
while (false);
return( siResult );
}