#include "BSDHeaders.h"
#include "CommandLineUtilities.h"
#include <CoreFoundation/CoreFoundation.h>
#include <Security/Authorization.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <rpc/types.h>
#include <sys/stat.h> // for file and dir stat calls
#include "crypt-md5.h"
#include "ffparser.h"
#ifndef kServerRunLoop
#define kServerRunLoop (eDSPluginCalls)(kHandleNetworkTransition + 1)
#endif
extern "C" int _lookupd_port(int); extern "C" int _lookup_link(mach_port_t, char *, int *);
extern "C" int _lookup_one(mach_port_t, int, char *, int, char **, int *);
extern "C" int _lu_running();
#define kTaskInterval 2
#define kMaxSizeOfParam 1024
static const uInt32 kBuffPad = 16;
int LogHexDump(char *pktPtr, long pktLen);
boolean_t NetworkChangeCallBack(SCDynamicStoreRef session, void *callback_argument);
sInt32 CleanContextData ( sNISContextData *inContext );
sNISContextData* MakeContextData ( void );
CFStringRef NSLNodeValueCopyDesctriptionCallback ( const void *item );
Boolean NSLNodeValueEqualCallback ( const void *value1, const void *value2 );
void NSLNodeHandlerFunction(const void *inKey, const void *inValue, void *inContext);
typedef struct AttrDataContext {
sInt32 count;
CDataBuff* attrDataBuf;
Boolean attrOnly;
char* attrType;
} AttrDataContext;
typedef struct AttrDataMatchContext {
tDirPatternMatch fInPattMatchType;
CFStringRef fInPatt2MatchRef;
CFStringRef fAttributeNameToMatchRef;
Boolean foundAMatch;
} AttrDataMatchContext;
typedef struct ResultMatchContext {
tDirPatternMatch fInPattMatchType;
CFStringRef fInPatt2MatchRef;
CFStringRef fAttributeNameToMatchRef;
CFMutableArrayRef fResultArray;
} ResultMatchContext;
Boolean IsResultOK( tDirPatternMatch patternMatch, CFStringRef resultRecordNameRef, CFStringRef recNameMatchRef );
void AddDictionaryDataToAttrData(const void *key, const void *value, void *context);
void FindAttributeMatch(const void *key, const void *value, void *context);
void FindAllAttributeMatches(const void *key, const void *value, void *context);
pthread_mutex_t gOutstandingSearchesLock = PTHREAD_MUTEX_INITIALIZER;
#define kSkipYPCatOnRecordNamesFilePath "/Library/Preferences/DirectoryService/.DisableNISCatSearchOnRecordNames"
Boolean gSkipYPCatOnRecordNames = false;
#define kSkipYPCatOnDisplayNamesFilePath "/Library/Preferences/DirectoryService/.DisableNISCatSearchOnDisplayNames"
Boolean gDisableDisplayNameLookups = false;
#define kNumLookupTypes 6
#define kMaxNumAgents 6
static const char* kLookupdRecordNames[kNumLookupTypes] = { "lookupd",
"hosts",
"services",
"protocols",
"rpcs",
"networks"
};
static const char* kLookupdRecordLookupOrdersNISEnabled[kNumLookupTypes][kMaxNumAgents+1] = { {"CacheAgent", "NIAgent", "DSAgent", NULL},
{"CacheAgent", "FFAgent", "DNSAgent", "NIAgent", "DSAgent", "NISAgent", NULL},
{"CacheAgent", "FFAgent", "NIAgent", "DSAgent", "NISAgent", NULL},
{"CacheAgent", "FFAgent", "NIAgent", "DSAgent", "NISAgent", NULL},
{"CacheAgent", "FFAgent", "NIAgent", "DSAgent", "NISAgent", NULL},
{"CacheAgent", "FFAgent", "NIAgent", "DSAgent", "NISAgent", NULL}
};
static const char* kLookupdRecordLookupOrdersNISDisabled[kNumLookupTypes][kMaxNumAgents+1] = { {"CacheAgent", "NIAgent", "DSAgent", NULL},
{"CacheAgent", "FFAgent", "DNSAgent", "NIAgent", "DSAgent", NULL},
{"CacheAgent", "FFAgent", "NIAgent", "DSAgent", NULL},
{"CacheAgent", "FFAgent", "NIAgent", "DSAgent", NULL},
{"CacheAgent", "FFAgent", "NIAgent", "DSAgent", NULL},
{"CacheAgent", "FFAgent", "NIAgent", "DSAgent", NULL}
};
#ifdef BUILDING_COMBO_PLUGIN
const char* kFFRecordTypeUsers = "master.passwd";
const char* kFFRecordTypeGroups = "group";
const char* kFFRecordTypeAlias = "aliases";
const char* kFFRecordTypeBootp = "bootptab";
const char* kFFRecordTypeEthernets = "ethers";
const char* kFFRecordTypeHosts = "hosts";
const char* kFFRecordTypeMounts = "fstab";
const char* kFFRecordTypeNetGroups = "netgroups";
const char* kFFRecordTypeNetworks = "networks";
const char* kFFRecordTypePrintService = "printcap";
const char* kFFRecordTypeProtocols = "protocols";
const char* kFFRecordTypeRPC = "rpc";
const char* kFFRecordTypeServices = "services";
const char* kFFRecordTypeBootParams = "bootparams";
#endif
const char* kNISRecordTypeUsers = "passwd.byname";
const char* kNISRecordTypeUsersByUID = "passwd.byuid";
const char* kNISRecordTypeGroups = "group.byname";
const char* kNISRecordTypeGroupByUser = "group.byusr";
const char* kNISRecordTypeGroupsByGID = "group.bygid";
const char* kNISRecordTypeBootParams = "bootparams.byname";
const char* kNISRecordTypeAlias = "mail.aliases";
const char* kNISRecordTypeBootp = "bootptab.byaddr";
const char* kNISRecordTypeEthernets = "ethers.byname";
const char* kNISRecordTypeHosts = "hosts.byname";
const char* kNISRecordTypeMounts = "mounts.byname";
const char* kNISRecordTypeNetGroups = "netgroups";
const char* kNISRecordTypeNetworks = "networks.byname";
const char* kNISRecordTypePrintService = "printcap.byname";
const char* kNISRecordTypeProtocols = "protocols.byname";
const char* kNISRecordTypeRPC = "rpc.byname";
const char* kNISRecordTypeServices = "services.byname";
#define kDefaultDomainFilePath "/Library/Preferences/DirectoryService/nisdomain"
#pragma mark -
NodeData * AllocateNodeData()
{
NodeData *newNode = (NodeData*)calloc( 1, sizeof(NodeData) );
return newNode;
}
void DeallocateNodeData( NodeData *nodeData )
{
if ( nodeData != NULL )
{
if ( nodeData->fNodeName )
::CFRelease( nodeData->fNodeName );
nodeData->fNodeName = NULL;
if ( nodeData->fServicesRefTable )
::CFRelease( nodeData->fServicesRefTable );
nodeData->fServicesRefTable = NULL;
if ( nodeData->fDSName )
{
dsDataListDeallocatePriv( nodeData->fDSName );
free( nodeData->fDSName );
nodeData->fDSName = NULL;
}
free( nodeData );
}
}
const CFStringRef gBundleIdentifier = CFSTR("com.apple.DirectoryService.BSD");
extern "C" {
CFUUIDRef ModuleFactoryUUID = CFUUIDGetConstantUUIDWithBytes ( NULL, \
0xCE, 0x63, 0xBE, 0x32, 0xF5, 0xB6, 0x11, 0xD6, \
0x9D, 0xC0, 0x00, 0x03, 0x93, 0x4F, 0xB0, 0x10 );
}
const char* gProtocolPrefixString = "BSD";
static CDSServerModule* _Creator ( void )
{
DBGLOG( "Creating new BSD Plugin\n" );
return( new BSDPlugin );
}
CDSServerModule::tCreator CDSServerModule::sCreator = _Creator;
BSDPlugin::BSDPlugin( void )
{
DBGLOG( "BSDPlugin::BSDPlugin\n" );
mLocalNodeString = NULL;
mNISMetaNodeLocationRef = NULL;
#ifdef BUILDING_COMBO_PLUGIN
mFFMetaNodeLocationRef = NULL;
#endif
mPublishedNodes = NULL;
mOpenRecordsRef = NULL;
mOpenRefTable = NULL;
mLastTimeCacheReset = 0;
mWeLaunchedYPBind = false;
mLookupdIsAlreadyConfigured = false;
mState = kUnknownState;
mLastTimeOfNetworkTransition = 0;
#ifdef USE_CACHE
mCachedMapsRef = NULL;
#endif
#ifdef BUILDING_COMBO_PLUGIN
mCachedFFRef = NULL;
bzero( mModTimes, sizeof( mModTimes ) );
#endif
mNISServersRef = NULL;
mNISOK = true;
mNISAgentIsConfigured = false;
mRecordTypeUsersByUIDMapNotAvailable = false;
mRecordTypeGroupByUserMapNotAvailable = false;
mRecordTypeGroupsByGIDMapNotAvailable = false;
}
BSDPlugin::~BSDPlugin( void )
{
DBGLOG( "BSDPlugin::~BSDPlugin\n" );
if ( mOpenRecordsRef )
CFRelease( mOpenRecordsRef );
mOpenRecordsRef = NULL;
if ( mLocalNodeString )
free( mLocalNodeString );
mLocalNodeString = NULL;
if ( mNISMetaNodeLocationRef )
CFRelease( mNISMetaNodeLocationRef );
mNISMetaNodeLocationRef = NULL;
#ifdef BUILDING_COMBO_PLUGIN
if ( mFFMetaNodeLocationRef )
CFRelease( mFFMetaNodeLocationRef );
mFFMetaNodeLocationRef = NULL;
#endif
if ( mOpenRefTable )
{
::CFDictionaryRemoveAllValues( mOpenRefTable );
::CFRelease( mOpenRefTable );
mOpenRefTable = NULL;
}
if ( mNISServersRef )
CFRelease( mNISServersRef );
mNISServersRef = NULL;
}
sInt32 BSDPlugin::Validate ( const char *inVersionStr, const uInt32 inSignature )
{
mSignature = inSignature;
return( noErr );
}
sInt32 BSDPlugin::Initialize( void )
{
sInt32 siResult = eDSNoErr;
DBGLOG( "BSDPlugin::Initialize\n" );
CFDictionaryKeyCallBacks keyCallBack;
CFDictionaryValueCallBacks valueCallBack;
valueCallBack.version = 0;
valueCallBack.retain = NULL;
valueCallBack.release = NULL;
valueCallBack.copyDescription = NSLNodeValueCopyDesctriptionCallback;
valueCallBack.equal = NSLNodeValueEqualCallback;
mPublishedNodes = ::CFDictionaryCreateMutable( NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, &valueCallBack);
pthread_mutex_init( &mQueueLock, NULL );
pthread_mutex_init( &mPluginLock, NULL );
#ifdef BUILDING_COMBO_PLUGIN
pthread_mutex_init( &mFFCache, NULL );
#endif
#ifdef USE_CACHE
pthread_mutex_init( &mMapCache, NULL );
#endif
keyCallBack.version = 0;
keyCallBack.retain = NULL;
keyCallBack.release = NULL;
keyCallBack.copyDescription = NULL;
keyCallBack.equal = NULL;
keyCallBack.hash = NULL;
valueCallBack.release = NULL;
valueCallBack.copyDescription = NULL;
valueCallBack.equal = NULL;
mOpenRefTable = ::CFDictionaryCreateMutable( NULL, 0, &keyCallBack, &valueCallBack );
if ( !mOpenRefTable )
DBGLOG("************* mOpenRefTable is NULL ***************\n");
if ( !mOpenRecordsRef )
mOpenRecordsRef = CFDictionaryCreateMutable( NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks );
mLastTimeCheckedServerAvailabilityViaRPC = 0;
#ifdef BUILDING_COMBO_PLUGIN
ResetFFCache();
#endif
#ifdef USE_CACHE
ResetMapCache();
#endif
#ifdef BUILDING_COMBO_PLUGIN
if ( !mFFMetaNodeLocationRef )
{
char buf[1024];
snprintf( buf, sizeof(buf), "%s%s", kProtocolPrefixSlashStr, kFFNodeName );
mFFMetaNodeLocationRef = CFStringCreateWithCString( NULL, buf, kCFStringEncodingUTF8 );
}
#endif
struct stat statResult;
if ( stat( kSkipYPCatOnRecordNamesFilePath, &statResult ) == 0 )
gSkipYPCatOnRecordNames = true;
if ( stat( kSkipYPCatOnDisplayNamesFilePath, &statResult ) == 0 )
gDisableDisplayNameLookups = true;
if ( !siResult )
{
mState = kInitalized | kInactive;
}
else
mState = kFailedToInit;
return siResult;
}
void BSDPlugin::WaitForInit( void )
{
volatile uInt32 uiAttempts = 0;
while ( !(mState & kInitialized) &&
!(mState & kFailedToInit) )
{
if ( uiAttempts++ >= 240 )
{
return;
}
usleep( (uInt32)(50000) );
}
}
sInt32 BSDPlugin::GetNISConfiguration( void )
{
sInt32 siResult = eDSNoErr;
char* resultPtr = CopyResultOfNISLookup( kNISdomainname );
DBGLOG( "BSDPlugin::GetNISConfiguration called\n" );
if ( resultPtr )
{
if ( strcmp( resultPtr, "\n" ) == 0 )
{
DBGLOG( "BSDPlugin::GetNISConfiguration no domain name set, we will check our own configuration\n" );
CFStringRef configDomain = CopyDomainFromFile();
SetDomain( configDomain );
if ( configDomain )
CFRelease( configDomain );
}
else
{
char* eoln = strstr( resultPtr, "\n" );
if ( eoln )
*eoln = '\0';
if ( strcmp( resultPtr, kNoDomainName ) == 0 )
{
DBGLOG( "BSDPlugin::GetNISConfiguration domain name is: %s, don't use.\n", resultPtr );
}
else
{
DBGLOG( "BSDPlugin::GetNISConfiguration domain name is: %s\n", resultPtr );
if ( mLocalNodeString )
free( mLocalNodeString );
mLocalNodeString = (char*)malloc(strlen(resultPtr)+1);
strcpy( mLocalNodeString, resultPtr );
}
}
free( resultPtr );
resultPtr = NULL;
}
else
{
mNISOK = false;
DBGLOG( "BSDPlugin::GetNISConfiguration resultPtr is NULL setting mNISOK to false! \n" );
}
if ( resultPtr )
{
free( resultPtr );
resultPtr = NULL;
}
if ( mLocalNodeString )
{
if ( !NISAvailable() )
mNISOK = false;
}
if ( mNISOK )
SetNISAvailable();
else
SetNISUnavailable();
return siResult;
}
void BSDPlugin::SetNISUnavailable( void )
{
if ( mNISAgentIsConfigured )
{
SaveDefaultLookupdConfigurationWithNISDisabled();
}
}
void BSDPlugin::SetNISAvailable( void )
{
if ( !mNISAgentIsConfigured )
{
SaveDefaultLookupdConfigurationWithNISEnabled();
}
}
sInt32 BSDPlugin::PeriodicTask( void )
{
sInt32 siResult = eDSNoErr;
#ifdef USE_CACHE
if ( mLastTimeCacheReset + kMaxTimeForMapCacheToLive < CFAbsoluteTimeGetCurrent() )
ResetMapCache();
#endif
return( siResult );
}
sInt32 BSDPlugin::ProcessRequest ( void *inData )
{
sInt32 siResult = 0;
WaitForInit();
if ( inData == nil )
{
DBGLOG( "BSDPlugin::ProcessRequest, inData is NULL!\n" );
return( ePlugInDataError );
}
if ( (mState & kFailedToInit) )
{
DBGLOG( "BSDPlugin::ProcessRequest, kFailedToInit!\n" );
return( ePlugInFailedToInitialize );
}
if ( ((sHeader *)inData)->fType == kServerRunLoop )
{
DBGLOG( "BSDPlugin::ProcessRequest, received a RunLoopRef, 0x%x\n", (int)((sHeader *)inData)->fContextData );
return siResult;
}
else if ( ((mState & kInactive) || !(mState & kActive)) )
{
if ( ((sHeader *)inData)->fType == kOpenDirNode )
{
char *pathStr = nil;
char *protocolStr = nil;
tDataListPtr pNodeList = nil;
pNodeList = ((sOpenDirNode *)inData)->fInDirNodeName;
pathStr = dsGetPathFromListPriv( pNodeList, (char *)"/" );
if ( pathStr )
protocolStr = pathStr+1;
if ( protocolStr && GetProtocolPrefixString() && strcmp( protocolStr, GetProtocolPrefixString() ) == 0 )
{
DBGLOG( "BSDPlugin::ProcessRequest (kOpenDirNode), plugin not active, open on (%s) ok\n", protocolStr );
if (pathStr != NULL)
{
free(pathStr);
pathStr = NULL;
}
}
else
{
DBGLOG( "BSDPlugin::ProcessRequest (kOpenDirNode), plugin not active, returning ePlugInNotActive on open (%s)\n", pathStr );
if (pathStr != NULL)
{
free(pathStr);
pathStr = NULL;
}
return( ePlugInNotActive );
}
}
else if ( ((sHeader *)inData)->fType == kCloseDirNode )
{
DBGLOG( "BSDPlugin::ProcessRequest (kCloseDirNode), plugin not active, returning noErr\n" );
}
else if ( ((sHeader *)inData)->fType != kDoPlugInCustomCall )
{
DBGLOG( "BSDPlugin::ProcessRequest (%ld), plugin not active!\n", ((sHeader *)inData)->fType );
return( ePlugInNotActive );
}
}
siResult = HandleRequest( inData );
return( siResult );
}
sInt32 BSDPlugin::SetPluginState ( const uInt32 inState )
{
sInt32 siResult = 0;
WaitForInit();
DBGLOG( "BSDPlugin::SetPluginState(%s):", GetProtocolPrefixString() );
if ( (kActive & inState) && (mState & kInactive) ) {
DBGLOG( "kActive\n" );
if ( mState & kInactive )
mState -= kInactive;
if ( !(mState & kActive) )
mState += kActive;
#ifdef BUILDING_COMBO_PLUGIN
ResetFFCache();
#endif
#ifdef USE_CACHE
ResetMapCache();
#endif
#ifdef BUILDING_COMBO_PLUGIN
AddNode( kFFNodeName );
#endif
siResult = GetNISConfiguration();
if ( siResult == eDSNoErr && mLocalNodeString && mNISOK )
{
AddNode( mLocalNodeString ); }
}
if ( (kInactive & inState) && (mState & kActive) ) {
DBGLOG( "kInactive\n" );
if ( !(mState & kInactive) )
mState += kInactive;
if ( mState & kActive )
mState -= kActive;
#ifdef BUILDING_COMBO_PLUGIN
ResetFFCache();
#endif
#ifdef USE_CACHE
ResetMapCache();
#endif
#ifdef BUILDING_COMBO_PLUGIN
RemoveNode( CFSTR(kFFNodeName) );
#endif
char* oldDomainStr = mLocalNodeString;
mLocalNodeString = NULL;
DBGLOG( "Setting pluginstate to inactive, null out domain and servers\n" );
SetDomain( NULL );
SetNISServers( NULL, oldDomainStr );
if ( oldDomainStr )
{
CFStringRef localNodeStringRef = CFStringCreateWithCString( NULL, oldDomainStr, kCFStringEncodingUTF8 );
RemoveNode( localNodeStringRef );
CFRelease( localNodeStringRef );
free(oldDomainStr);
oldDomainStr = NULL;
}
SetNISUnavailable(); }
return( siResult );
}
#pragma mark -
void BSDPlugin::AddNode( const char* nodeName, Boolean isLocalNode )
{
if ( !nodeName )
return;
NodeData* node = NULL;
CFStringRef nodeRef = CFStringCreateWithCString( NULL, nodeName, kCFStringEncodingUTF8 );
if ( nodeRef )
{
DBGLOG( "BSDPlugin::AddNode called with %s\n", nodeName );
LockPublishedNodes();
if ( ::CFDictionaryContainsKey( mPublishedNodes, nodeRef ) )
node = (NodeData*)::CFDictionaryGetValue( mPublishedNodes, nodeRef );
if ( node )
{
DSUnregisterNode( mSignature, node->fDSName );
::CFDictionaryRemoveValue( mPublishedNodes, node->fNodeName );
DeallocateNodeData( node );
node = NULL;
}
if ( node )
{
node->fTimeStamp = GetCurrentTime(); }
else
{
DBGLOG( "BSDPlugin::AddNode Adding new node %s\n", nodeName );
node = AllocateNodeData();
node->fNodeName = nodeRef;
CFRetain( node->fNodeName );
node->fDSName = dsBuildListFromStringsPriv(GetProtocolPrefixString(), nodeName, nil);
node->fTimeStamp = GetCurrentTime();
node->fServicesRefTable = ::CFDictionaryCreateMutable( NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks );
node->fSignature = mSignature;
if ( node->fDSName )
{
DSRegisterNode( mSignature, node->fDSName, (kDirNodeType) );
}
::CFDictionaryAddValue( mPublishedNodes, nodeRef, node );
}
CFRelease( nodeRef );
if ( mNISMetaNodeLocationRef )
CFRelease( mNISMetaNodeLocationRef );
mNISMetaNodeLocationRef = CFStringCreateMutable( NULL, 0 );
CFStringAppendCString( mNISMetaNodeLocationRef, kProtocolPrefixSlashStr, kCFStringEncodingUTF8 );
CFStringAppendCString( mNISMetaNodeLocationRef, nodeName, kCFStringEncodingUTF8 );
UnlockPublishedNodes();
}
}
void BSDPlugin::RemoveNode( CFStringRef nodeNameRef )
{
NodeData* node = NULL;
DBGLOG( "BSDPlugin::RemoveNode called with" );
if ( getenv("NSLDEBUG") )
CFShow(nodeNameRef);
LockPublishedNodes();
Boolean containsNode = ::CFDictionaryContainsKey( mPublishedNodes, nodeNameRef );
if ( containsNode )
{
node = (NodeData*)::CFDictionaryGetValue( mPublishedNodes, nodeNameRef );
DSUnregisterNode( mSignature, node->fDSName );
::CFDictionaryRemoveValue( mPublishedNodes, node->fNodeName );
DeallocateNodeData( node );
node = NULL;
}
UnlockPublishedNodes();
}
const char* BSDPlugin::GetProtocolPrefixString( void )
{
return gProtocolPrefixString;
}
#pragma mark -
sInt32 BSDPlugin::HandleRequest( void *inData )
{
sInt32 siResult = 0;
sHeader *pMsgHdr = nil;
if ( inData == nil )
{
return( -8088 );
}
try
{
pMsgHdr = (sHeader *)inData;
switch ( pMsgHdr->fType )
{
case kOpenDirNode:
DBGLOG( "BSDPlugin::HandleRequest, type: kOpenDirNode\n" );
siResult = OpenDirNode( (sOpenDirNode *)inData );
break;
case kCloseDirNode:
DBGLOG( "BSDPlugin::HandleRequest, type: kCloseDirNode\n" );
siResult = CloseDirNode( (sCloseDirNode *)inData );
break;
case kGetDirNodeInfo:
DBGLOG( "BSDPlugin::HandleRequest, type: kGetDirNodeInfo\n" );
siResult = GetDirNodeInfo( (sGetDirNodeInfo *)inData );
break;
case kGetRecordList:
DBGLOG( "BSDPlugin::HandleRequest, type: kGetRecordList\n" );
siResult = GetRecordList( (sGetRecordList *)inData );
break;
case kReleaseContinueData:
DBGLOG( "BSDPlugin::HandleRequest, type: kReleaseContinueData\n" );
siResult = ReleaseContinueData( (sNISContinueData*)((sReleaseContinueData*)inData)->fInContinueData );
((sReleaseContinueData*)inData)->fInContinueData = NULL;
break;
case kGetRecordEntry:
DBGLOG( "BSDPlugin::HandleRequest, type: kGetRecordEntry\n" );
siResult = GetRecordEntry( (sGetRecordEntry *)inData );
break;
case kGetAttributeEntry:
DBGLOG( "BSDPlugin::HandleRequest, type: kGetAttributeEntry\n" );
siResult = GetAttributeEntry( (sGetAttributeEntry *)inData );
break;
case kGetAttributeValue:
DBGLOG( "BSDPlugin::HandleRequest, type: kGetAttributeValue\n" );
siResult = GetAttributeValue( (sGetAttributeValue *)inData );
break;
case kOpenRecord:
DBGLOG( "BSDPlugin::HandleRequest, type: kOpenRecord\n" );
siResult = OpenRecord( (sOpenRecord *)inData );
break;
case kGetRecordReferenceInfo:
DBGLOG( "BSDPlugin::HandleRequest, type: kGetRecordReferenceInfo\n" );
siResult = GetRecRefInfo( (sGetRecRefInfo *)inData );
break;
case kGetRecordAttributeInfo:
DBGLOG( "BSDPlugin::HandleRequest, type: kGetRecordAttributeInfo\n" );
siResult = GetRecordAttributeInfo( (sGetRecAttribInfo *)inData );
break;
case kGetRecordAttributeValueByID:
DBGLOG( "BSDPlugin::HandleRequest, type: kGetRecordAttributeValueByID\n" );
siResult = GetRecordAttributeValueByID( (sGetRecordAttributeValueByID *)inData );
break;
case kGetRecordAttributeValueByIndex:
DBGLOG( "BSDPlugin::HandleRequest, type: kGetRecordAttributeValueByIndex\n" );
siResult = GetRecordAttributeValueByIndex( (sGetRecordAttributeValueByIndex *)inData );
break;
case kGetRecordAttributeValueByValue:
DBGLOG( "BSDPlugin::HandleRequest, type: kGetRecordAttributeValueByValue\n" );
siResult = GetRecordAttributeValueByValue( (sGetRecordAttributeValueByValue *)inData );
break;
case kFlushRecord:
DBGLOG( "BSDPlugin::HandleRequest, type: kFlushRecord\n" );
siResult = eDSNoErr;
break;
case kCloseAttributeList:
DBGLOG( "BSDPlugin::HandleRequest, type: kCloseAttributeList\n" );
siResult = eDSNoErr;
break;
case kCloseAttributeValueList:
siResult = eDSNoErr;
break;
case kCloseRecord:
DBGLOG( "BSDPlugin::HandleRequest, type: kCloseRecord\n" );
siResult = CloseRecord( (sCloseRecord*)inData );
break;
case kSetRecordName:
DBGLOG( "BSDPlugin::HandleRequest, we don't handle kSetRecordName yet\n" );
siResult = eNotHandledByThisNode;
break;
case kSetRecordType:
DBGLOG( "BSDPlugin::HandleRequest, we don't handle kSetRecordType yet\n" );
siResult = eNotHandledByThisNode;
break;
case kDeleteRecord:
siResult = eNotHandledByThisNode;
break;
case kCreateRecord:
case kCreateRecordAndOpen:
siResult = eNotHandledByThisNode;
break;
case kAddAttribute:
DBGLOG( "BSDPlugin::HandleRequest, we don't handle kAddAttribute yet\n" );
siResult = eNotHandledByThisNode;
break;
case kRemoveAttribute:
siResult = eNotHandledByThisNode;
break;
case kAddAttributeValue:
siResult = eNotHandledByThisNode;
break;
case kRemoveAttributeValue:
siResult = eNotHandledByThisNode;
break;
case kSetAttributeValue:
siResult = eNotHandledByThisNode;
break;
case kDoDirNodeAuth:
DBGLOG( "BSDPlugin::HandleRequest, type: kDoDirNodeAuth\n" );
siResult = DoAuthentication( (sDoDirNodeAuth*)inData );
break;
case kDoAttributeValueSearch:
case kDoAttributeValueSearchWithData:
siResult = DoAttributeValueSearch( (sDoAttrValueSearch *)inData );
break;
case kDoPlugInCustomCall:
DBGLOG( "BSDPlugin::HandleRequest, type: kDoPlugInCustomCall\n" );
siResult = DoPlugInCustomCall( (sDoPlugInCustomCall *)inData );
break;
case kHandleNetworkTransition:
DBGLOG( "BSDPlugin::HandleRequest, we have some sort of network transition\n" );
siResult = HandleNetworkTransition( (sHeader*)inData );
break;
default:
DBGLOG( "BSDPlugin::HandleRequest, type: %ld\n", pMsgHdr->fType );
siResult = eNotHandledByThisNode;
break;
}
}
catch ( int err )
{
siResult = err;
DBGLOG( "BSDPlugin::HandleRequest, Caught error:%li\n", siResult );
}
pMsgHdr->fResult = siResult;
if ( siResult )
DBGLOG( "BSDPlugin::HandleRequest returning %ld on a request of type %ld\n", siResult, pMsgHdr->fType );
return( siResult );
}
sInt32 BSDPlugin::DoPlugInCustomCall ( sDoPlugInCustomCall *inData )
{
sInt32 siResult = eDSNoErr;
unsigned long aRequest = 0;
unsigned long bufLen = 0;
AuthorizationRef authRef = 0;
AuthorizationItemSet *resultRightSet = NULL;
BSDDirNodeRep* nodeDirRep = NULL;
DBGLOG( "BSDPlugin::DoPlugInCustomCall called\n" );
try
{
if ( inData == nil ) throw( (sInt32)eDSNullParameter );
if ( mOpenRefTable == nil ) throw ( (sInt32)eDSNodeNotFound );
LockPlugin();
nodeDirRep = (BSDDirNodeRep*)::CFDictionaryGetValue( mOpenRefTable, (const void*)inData->fInNodeRef );
if( !nodeDirRep )
{
DBGLOG( "BSDPlugin::DoPlugInCustomCall called but we couldn't find the nodeDirRep!\n" );
UnlockPlugin();
return eDSInvalidNodeRef;
}
if ( nodeDirRep )
{
nodeDirRep->Retain();
UnlockPlugin();
aRequest = inData->fInRequestCode;
if ( aRequest != kReadNISConfigData )
{
if ( inData->fInRequestData == nil ) throw( (sInt32)eDSNullDataBuff );
if ( inData->fInRequestData->fBufferData == nil ) throw( (sInt32)eDSEmptyBuffer );
bufLen = inData->fInRequestData->fBufferLength;
if ( bufLen < sizeof( AuthorizationExternalForm ) ) throw( (sInt32)eDSInvalidBuffFormat );
siResult = AuthorizationCreateFromExternalForm((AuthorizationExternalForm *)inData->fInRequestData->fBufferData,
&authRef);
if (siResult != errAuthorizationSuccess)
{
throw( (sInt32)eDSPermissionError );
}
AuthorizationItem rights[] = { {"system.services.directory.configure", 0, 0, 0} };
AuthorizationItemSet rightSet = { sizeof(rights)/ sizeof(*rights), rights };
siResult = AuthorizationCopyRights(authRef, &rightSet, NULL,
kAuthorizationFlagExtendRights, &resultRightSet);
if (resultRightSet != NULL)
{
AuthorizationFreeItemSet(resultRightSet);
resultRightSet = NULL;
}
if (siResult != errAuthorizationSuccess)
{
throw( (sInt32)eDSPermissionError );
}
}
switch( aRequest )
{
case kReadNISConfigData:
{
DBGLOG( "BSDPlugin::DoPlugInCustomCall kReadNISConfigData\n" );
siResult = FillOutCurrentState( inData );
}
break;
case kWriteNISConfigData:
{
DBGLOG( "BSDPlugin::DoPlugInCustomCall kWriteNISConfigData\n" );
siResult = SaveNewState( inData );
if ( GetNISConfiguration() == eDSNoErr && mLocalNodeString && mNISOK )
{
DBGLOG( "BSDPlugin::DoPlugInCustomCall calling AddNode on %s\n", mLocalNodeString );
AddNode( mLocalNodeString ); }
else
DBGLOG( "BSDPlugin::DoPlugInCustomCall not calling AddNode because %s\n", (mLocalNodeString)?"we have no damain name":"of an error in GetNISConfiguration()" );
#ifdef BUILDING_COMBO_PLUGIN
ResetFFCache();
#endif
#ifdef USE_CACHE
ResetMapCache();
#endif
}
break;
default:
siResult = eDSInvalidReference;
break;
}
}
}
catch ( sInt32 err )
{
siResult = err;
}
if ( nodeDirRep )
nodeDirRep->Release();
if (authRef != 0)
{
AuthorizationFree(authRef, 0);
authRef = 0;
}
return( siResult );
}
sInt32 BSDPlugin::SaveNewState( sDoPlugInCustomCall *inData )
{
sInt32 siResult = eDSNoErr;
sInt32 xmlDataLength = 0;
CFDataRef xmlData = NULL;
CFDictionaryRef newStateRef = NULL;
CFStringRef domainNameRef = NULL;
CFStringRef nisServersRef = NULL;
CFStringRef errorString = NULL;
Boolean needToChangeDomain = false;
CFStringRef localNodeStringRef = NULL;
char* oldDomainStr = NULL;
DBGLOG( "BSDPlugin::SaveNewState called\n" );
xmlDataLength = (sInt32) inData->fInRequestData->fBufferLength - sizeof( AuthorizationExternalForm );
if ( xmlDataLength <= 0 )
return (sInt32)eDSInvalidBuffFormat;
xmlData = CFDataCreate(NULL,(UInt8 *)(inData->fInRequestData->fBufferData + sizeof( AuthorizationExternalForm )), xmlDataLength);
if ( !xmlData )
{
DBGLOG( "BSDPlugin::SaveNewState, couldn't create xmlData from buffer!!\n" );
siResult = (sInt32)eDSInvalidBuffFormat;
}
else
newStateRef = (CFDictionaryRef)CFPropertyListCreateFromXMLData( NULL,
xmlData,
kCFPropertyListImmutable,
&errorString);
if ( newStateRef && CFGetTypeID( newStateRef ) != CFDictionaryGetTypeID() )
{
DBGLOG( "BSDPlugin::SaveNewState, XML Data wasn't a CFDictionary!\n" );
siResult = (sInt32)eDSInvalidBuffFormat;
}
else
{
if ( mLocalNodeString )
localNodeStringRef = CFStringCreateWithCString( NULL, mLocalNodeString, kCFStringEncodingUTF8 );
domainNameRef = (CFStringRef)CFDictionaryGetValue( newStateRef, CFSTR(kDS1AttrLocation) );
if ( domainNameRef && CFGetTypeID( domainNameRef ) == CFStringGetTypeID() )
{
if ( !mLocalNodeString )
needToChangeDomain = true;
else if ( localNodeStringRef && CFStringCompare( domainNameRef, localNodeStringRef, kCFCompareCaseInsensitive ) != kCFCompareEqualTo )
needToChangeDomain = true;
}
else if ( !domainNameRef )
{
DBGLOG( "BSDPlugin::SaveNewState, we received no domain name so we are basically being turned off\n" );
if ( mLocalNodeString )
needToChangeDomain = true;
}
else
{
DBGLOG( "BSDPlugin::SaveNewState, the domain name is of the wrong type! (%ld)\n", CFGetTypeID( domainNameRef ) );
siResult = (sInt32)eDSInvalidBuffFormat;
}
nisServersRef = (CFStringRef)CFDictionaryGetValue( newStateRef, CFSTR(kDSStdRecordTypeServer) );
if ( nisServersRef && CFGetTypeID( nisServersRef ) != CFStringGetTypeID() )
{
DBGLOG( "BSDPlugin::SaveNewState, the list of servers is of the wrong type! (%ld)\n", CFGetTypeID( nisServersRef ) );
siResult = (sInt32)eDSInvalidBuffFormat;
}
}
if ( siResult == eDSNoErr && needToChangeDomain )
{
if ( localNodeStringRef )
RemoveNode( localNodeStringRef );
oldDomainStr = mLocalNodeString;
mLocalNodeString = NULL;
siResult = SetDomain( domainNameRef );
}
if ( siResult == eDSNoErr )
siResult = SetNISServers( nisServersRef, (oldDomainStr)?oldDomainStr:mLocalNodeString );
if ( siResult == eDSNoErr )
SaveDefaultLookupdConfigurationWithNISEnabled();
else
SaveDefaultLookupdConfigurationWithNISDisabled();
if ( localNodeStringRef )
CFRelease( localNodeStringRef );
if ( xmlData )
CFRelease( xmlData );
if ( newStateRef )
CFRelease( newStateRef );
if ( oldDomainStr )
free( oldDomainStr );
return siResult;
}
#pragma mark -
void BSDPlugin::ConfigureLookupdIfNeeded( void )
{
if ( NISAvailable() )
SaveDefaultLookupdConfigurationWithNISEnabled();
else
SaveDefaultLookupdConfigurationWithNISDisabled();
}
void BSDPlugin::SaveDefaultLookupdConfigurationWithNISEnabled( void )
{
SaveDefaultLookupdConfiguration( true );
mNISAgentIsConfigured = true;
}
void BSDPlugin::SaveDefaultLookupdConfigurationWithNISDisabled( void )
{
SaveDefaultLookupdConfiguration( false );
mNISAgentIsConfigured = false;
}
void BSDPlugin::SaveDefaultLookupdConfiguration( Boolean enableNIS )
{
tDirReference dirRef = 0;
tDataListPtr dirNodeName = NULL;
tDirNodeReference dirNodeRef = 0;
tDirStatus status = eDSNoErr;
status = dsOpenDirService( &dirRef );
if ( !status )
{
sInt32 siResult = eDSNoErr;
tDataBuffer *pLocalNodeBuff = nil;
tDataList *pNodePath = nil;
uInt32 uiCount = 0;
tContextData context = NULL;
tDataNodePtr attributeKey = NULL;
tDataNodePtr attributeValue = NULL;
tDataNodePtr recName = NULL;
tDataNodePtr recordType = NULL;
tRecordReference userRecRef = 0;
try
{
pLocalNodeBuff = ::dsDataBufferAllocate( dirRef, 512 );
if ( pLocalNodeBuff == nil ) throw( (sInt32)eMemoryError );
do
{
siResult = dsFindDirNodes( dirRef, pLocalNodeBuff, NULL, eDSLocalNodeNames, &uiCount, &context );
if (siResult == eDSBufferTooSmall)
{
uInt32 bufSize = pLocalNodeBuff->fBufferSize;
dsDataBufferDeallocatePriv( pLocalNodeBuff );
pLocalNodeBuff = nil;
pLocalNodeBuff = ::dsDataBufferAllocatePriv( bufSize * 2 );
}
} while (siResult == eDSBufferTooSmall);
if ( siResult != eDSNoErr ) throw( siResult );
if ( uiCount == 0 )
{
DBGLOG( "BSDPlugin::SaveDefaultLookupdConfiguration:dsFindDirNodes on local returned zero" );
throw( siResult ); }
siResult = dsGetDirNodeName( dirRef, pLocalNodeBuff, 1, &dirNodeName );
if ( siResult != eDSNoErr )
{
DBGLOG( "BSDPlugin::SaveDefaultLookupdConfiguration:dsGetDirNodeName on local returned error %ld", siResult );
throw( siResult );
}
if ( pLocalNodeBuff != nil )
{
::dsDataBufferDeAllocate( dirRef, pLocalNodeBuff );
pLocalNodeBuff = nil;
}
siResult = ::dsOpenDirNode( dirRef, dirNodeName, &dirNodeRef );
if ( siResult != eDSNoErr )
{
DBGLOG( "BSDPlugin::SaveDefaultLookupdConfiguration:dsOpenDirNode on local returned error %ld", siResult );
throw( siResult );
}
::dsDataListDeAllocate( dirRef, dirNodeName, false );
free(dirNodeName);
dirNodeName = nil;
pNodePath = ::dsBuildListFromStringsPriv( kDSNAttrNodePath, nil );
if ( pNodePath == nil ) throw( (sInt32)eMemoryAllocError );
for ( int i=0; i<kNumLookupTypes; i++ )
{
recordType = dsDataNodeAllocateString( dirRef, (i==0)?"dsRecTypeNative:locations":"dsRecTypeNative:locations/lookupd" );
recName = dsDataNodeAllocateString( dirRef, kLookupdRecordNames[i] );
if ( recName == nil ) throw( (sInt32)eMemoryAllocError );
status = dsOpenRecord( dirNodeRef, recordType, recName, &userRecRef );
if ( status == eDSRecordNotFound )
status = dsCreateRecordAndOpen( dirNodeRef, recordType, recName, &userRecRef );
if ( status != eDSNoErr ) throw( status );
attributeKey = dsDataNodeAllocateString( dirNodeRef, "dsAttrTypeNative:LookupOrder" );
if ( attributeKey == nil ) throw( (sInt32)eMemoryAllocError );
siResult = dsRemoveAttribute( userRecRef, attributeKey );
if ( enableNIS )
{
for ( int j=0; kLookupdRecordLookupOrdersNISEnabled[i][j]; j++ )
{
attributeValue = dsDataNodeAllocateString( dirNodeRef, kLookupdRecordLookupOrdersNISEnabled[i][j] );
if ( attributeValue == nil ) throw( (sInt32)eMemoryAllocError );
status = dsAddAttributeValue( userRecRef, attributeKey, attributeValue );
dsDataNodeDeAllocate( dirNodeRef, attributeValue );
attributeValue = NULL;
}
}
else
{
for ( int j=0; kLookupdRecordLookupOrdersNISDisabled[i][j]; j++ )
{
attributeValue = dsDataNodeAllocateString( dirNodeRef, kLookupdRecordLookupOrdersNISDisabled[i][j] );
if ( attributeValue == nil ) throw( (sInt32)eMemoryAllocError );
status = dsAddAttributeValue( userRecRef, attributeKey, attributeValue );
dsDataNodeDeAllocate( dirNodeRef, attributeValue );
attributeValue = NULL;
}
}
dsDataNodeDeAllocate( dirNodeRef, attributeKey );
attributeKey = NULL;
if ( i == 0 )
{
attributeKey = dsDataNodeAllocateString( dirNodeRef, "dsAttrTypeNative:MaxThreads" );
if ( attributeKey == nil ) throw( (sInt32)eMemoryAllocError );
siResult = dsRemoveAttribute( userRecRef, attributeKey ); attributeValue = dsDataNodeAllocateString( dirNodeRef, "64" );
if ( attributeValue == nil ) throw( (sInt32)eMemoryAllocError );
status = dsAddAttributeValue( userRecRef, attributeKey, attributeValue );
dsDataNodeDeAllocate( dirNodeRef, attributeValue );
attributeValue = NULL;
dsDataNodeDeAllocate( dirNodeRef, attributeKey );
attributeKey = NULL;
}
siResult = ::dsFlushRecord( userRecRef );
siResult = ::dsCloseRecord( userRecRef );
userRecRef = 0;
}
}
catch( sInt32 err )
{
DBGLOG( "BSDPlugin::SaveDefaultLookupdConfiguration:dsOpenDirNode caught error %ld", err );
siResult = err;
}
if ( userRecRef != 0 )
{
siResult = ::dsCloseRecord(userRecRef);
userRecRef = 0;
}
if ( dirNodeRef != 0 )
{
dsCloseDirNode(dirNodeRef);
dirNodeRef = 0;
}
if ( dirNodeName != nil )
{
::dsDataListDeAllocate( dirRef, dirNodeName, false );
free(dirNodeName);
dirNodeName = nil;
}
if ( pNodePath != nil )
{
::dsDataListDeAllocate( dirRef, pNodePath, false );
free(pNodePath);
pNodePath = nil;
}
if ( pLocalNodeBuff != nil )
{
::dsDataBufferDeAllocate( dirRef, pLocalNodeBuff );
pLocalNodeBuff = nil;
}
if ( recName )
{
dsDataNodeDeAllocate( dirRef, recName );
recName = NULL;
}
if ( recordType )
{
dsDataNodeDeAllocate( dirRef, recordType );
recordType = NULL;
}
if ( attributeValue )
{
dsDataNodeDeAllocate( dirNodeRef, attributeValue );
attributeValue = NULL;
}
if ( attributeKey )
{
dsDataNodeDeAllocate( dirNodeRef, attributeKey );
attributeKey = NULL;
}
status = dsCloseDirService( dirRef );
}
mLookupdIsAlreadyConfigured = true;
FlushLookupdCache();
}
sInt32 BSDPlugin::FlushLookupdCache ( void )
{
sInt32 siResult = eDSNoErr;
int i = 0;
int proc = 0;
char str[32];
mach_port_t port = MACH_PORT_NULL;
{
DBGLOG( "BSDPlugin::FlushLookupdCache sending lookupd flushcache" );
_lu_running();
port = _lookupd_port(0);
if( port != MACH_PORT_NULL )
{
_lookup_link(port, "_invalidatecache", &proc);
_lookup_one(port, proc, NULL, 0, (char **)&str, &i);
}
}
return(siResult);
}
#pragma mark -
CFStringRef BSDPlugin::CopyDomainFromFile( void )
{
CFStringRef domainToReturn = NULL;
FILE *sourceFP = NULL;
char *eolPtr = NULL;
char buf[kMaxSizeOfParam] = {0,};
LockPlugin();
DBGLOG( "BSDPlugin::CopyDomainFromFile called\n" );
sourceFP = fopen(kDefaultDomainFilePath,"r+");
if ( sourceFP == NULL )
{
DBGLOG( "BSDPlugin::CopyDomainFromFile: no nisdomain file" );
}
else
{
if (fgets(buf,kMaxSizeOfParam,sourceFP) != NULL)
{
eolPtr = strstr( buf, "\n" );
if ( eolPtr )
*eolPtr = '\0';
if ( buf[0] != '\0' )
{
domainToReturn = CFStringCreateWithCString( NULL, buf, kCFStringEncodingASCII );
DBGLOG( "BSDPlugin::CopyDomainFromFile: using domain: [%s]", buf );
}
}
}
if ( sourceFP )
fclose( sourceFP );
UnlockPlugin();
return domainToReturn;
}
void BSDPlugin::SaveDomainToFile( CFStringRef domainNameRef )
{
if ( domainNameRef )
{
FILE *destFP = NULL;
char buf[kMaxSizeOfParam] = {0,};
LockPlugin();
DBGLOG( "BSDPlugin::SaveDomainToFile called\n" );
destFP = fopen(kDefaultDomainFilePath,"w+");
if ( destFP == NULL )
{
DBGLOG( "BSDPlugin::SaveDomainToFile: could not open nisdomain file to write! (%s)", strerror(errno) );
}
else
{
if ( domainNameRef )
{
CFStringGetCString( domainNameRef, buf, sizeof(buf), kCFStringEncodingASCII );
fputs( buf, destFP );
}
fclose( destFP );
}
UnlockPlugin();
}
}
sInt32 BSDPlugin::SetDomain( CFStringRef domainNameRef )
{
sInt32 siResult = eDSNoErr;
if ( domainNameRef )
{
CFIndex len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(domainNameRef), kCFStringEncodingUTF8) + 1;
mLocalNodeString = (char*)malloc(len);
CFStringGetCString( domainNameRef, mLocalNodeString, len, kCFStringEncodingUTF8 );
DBGLOG( "BSDPlugin::SaveNewState, changing our domain to %s\n", mLocalNodeString );
AddNode( mLocalNodeString );
SaveDomainToFile( domainNameRef );
char* resultPtr = CopyResultOfNISLookup( kNISdomainname, (domainNameRef)?mLocalNodeString:kNoDomainName );
if ( resultPtr )
free( resultPtr );
resultPtr = NULL;
}
return siResult;
}
sInt32 BSDPlugin::SetNISServers( CFStringRef nisServersRef, char* oldDomainStr )
{
sInt32 siResult = eDSNoErr;
DBGLOG( "BSDPlugin::SetNISServers called\n" );
if ( oldDomainStr )
{
char * argv[4] = {0};
char serverFilePath[1024];
char* resultPtr = NULL;
Boolean canceled = false;
int callTimedOut = 0;
snprintf( serverFilePath, sizeof( serverFilePath ), "/var/yp/binding/%s.ypservers", oldDomainStr );
DBGLOG( "BSDPlugin::SetNISServers going to delete file at %s\n", serverFilePath );
argv[0] = "/bin/rm";
argv[1] = "-rf";
argv[2] = serverFilePath;
if ( myexecutecommandas( NULL, "/bin/rm", argv, false, 10, &resultPtr, &canceled, getuid(), getgid(), &callTimedOut ) < 0 )
{
DBGLOG( "BSDPlugin::SetNISServers failed to delete ypservers\n" );
}
if ( resultPtr )
{
DBGLOG( "BSDPlugin::SetNISServers rm -rf returned %s\n", resultPtr );
free( resultPtr );
resultPtr = NULL;
}
}
if ( mLocalNodeString )
{
if ( nisServersRef && !CFStringHasPrefix( nisServersRef, CFSTR("\n") ) ) {
if ( mNISServersRef )
CFRelease( mNISServersRef );
mNISServersRef = CFStringCreateArrayBySeparatingStrings( NULL, nisServersRef, CFSTR("\n") );
FILE* fp = NULL;
char name[1024] = {0};
char* resultPtr = NULL;
char* argv[8] = {0};
Boolean canceled = false;
snprintf( name, sizeof(name), "/var/yp/binding/%s.ypservers", mLocalNodeString );
fp = fopen(name,"w+");
if (fp == NULL)
{
int callTimedOut = 0;
DBGLOG( "BSDPlugin::SetNISServers: Could not open config file %s: %s\n", name, strerror(errno) );
DBGLOG( "BSDPlugin::SetNISServers: We will make sure the path exists and try again.\n" );
argv[0] = "/bin/mkdir";
argv[1] = "-p";
argv[2] = "/var/yp/binding/";
if ( myexecutecommandas( NULL, "/bin/mkdir", argv, false, 10, &resultPtr, &canceled, getuid(), getgid(), &callTimedOut ) < 0 )
{
DBGLOG( "BSDPlugin::SetNISServers failed to delete ypservers\n" );
}
if ( resultPtr )
{
DBGLOG( "BSDPlugin::SetNISServers mkdir -p returned %s\n", resultPtr );
free( resultPtr );
resultPtr = NULL;
}
fp = fopen(name,"w+");
}
if ( fp )
{
UInt32 len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(nisServersRef), kCFStringEncodingUTF8) + 1;
char* serverList = (char *)::malloc( len );
if ( serverList )
{
char* listPtr = NULL;
CFStringGetCString( nisServersRef, serverList, len, kCFStringEncodingUTF8 );
listPtr = serverList + strlen(serverList)-1;
while ( listPtr > serverList && isspace(*listPtr) ) {
*listPtr = '\0';
listPtr--;
}
fprintf( fp, "%s\n", serverList );
DBGLOG( "BSDPlugin::SetNISServers saving: %s\n", serverList );
free( serverList );
}
else
DBGLOG( "BSDPlugin::SetNISServers could not allocate memory!\n" );
fclose(fp);
}
else
siResult = ePlugInError;
}
}
mRecordTypeUsersByUIDMapNotAvailable = false;
mRecordTypeGroupByUserMapNotAvailable = false;
mRecordTypeGroupsByGIDMapNotAvailable = false;
return siResult;
}
sInt32 BSDPlugin::FillOutCurrentState( sDoPlugInCustomCall *inData )
{
sInt32 siResult = eDSNoErr;
CFMutableDictionaryRef currentStateRef = CFDictionaryCreateMutable( NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks );
CFStringRef nisServersRef = NULL;
CFStringRef domainNameRef = NULL;
CFRange aRange;
CFDataRef xmlData = NULL;
try
{
if ( !currentStateRef )
throw( eMemoryError );
if ( mLocalNodeString )
{
DBGLOG( "BSDPlugin::FillOutCurrentState: mLocalNodeString is %s\n", mLocalNodeString );
domainNameRef = CFStringCreateWithCString( NULL, mLocalNodeString, kCFStringEncodingUTF8 );
if ( domainNameRef )
CFDictionaryAddValue( currentStateRef, CFSTR(kDS1AttrLocation), domainNameRef );
nisServersRef = CreateListOfServers();
if ( nisServersRef )
CFDictionaryAddValue( currentStateRef, CFSTR(kDSStdRecordTypeServer), nisServersRef );
}
xmlData = CFPropertyListCreateXMLData( kCFAllocatorDefault, currentStateRef );
if (xmlData != 0)
{
aRange.location = 0;
aRange.length = CFDataGetLength(xmlData);
if ( inData->fOutRequestResponse->fBufferSize < (unsigned int)aRange.length ) throw( (sInt32)eDSBufferTooSmall );
CFDataGetBytes( xmlData, aRange, (UInt8*)(inData->fOutRequestResponse->fBufferData) );
inData->fOutRequestResponse->fBufferLength = aRange.length;
}
}
catch ( sInt32 err )
{
DBGLOG( "BSDPlugin::FillOutCurrentState: Caught error: %ld\n", err );
siResult = err;
}
if ( currentStateRef )
CFRelease( currentStateRef );
if ( nisServersRef )
{
if ( mNISServersRef )
CFRelease( mNISServersRef );
mNISServersRef = CFStringCreateArrayBySeparatingStrings( NULL, nisServersRef, CFSTR("\n") );
}
else
mNISServersRef = CFArrayCreate( NULL, NULL, 0, &kCFTypeArrayCallBacks );
if ( domainNameRef )
CFRelease( domainNameRef );
if ( xmlData )
CFRelease( xmlData );
return siResult;
}
Boolean BSDPlugin::NISAvailable( void )
{
DBGLOG( "BSDPlugin::NISAvailable called" );
Boolean nisAvail = ( mNISOK && AreNISServersReachable() );
DBGLOG( "BSDPlugin::NISAvailable called, nisAvail is %s", (nisAvail)?"true":"false" );
if ( !mNISOK && AreNISServersReachable() && mLastTimeCheckedServerAvailabilityViaRPC + kMinTimeBetweenRPCInfoRequests < CFAbsoluteTimeGetCurrent() )
{
DBGLOG( "BSDPlugin::NISAvailable, servers are reachable. Verifying by using RPCInfo..." );
mLastTimeCheckedServerAvailabilityViaRPC = CFAbsoluteTimeGetCurrent();
if ( mNISServersRef && CFArrayGetCount( mNISServersRef ) > 0 )
{
CFIndex curServerIndex = 0;
CFIndex numServers = CFArrayGetCount( mNISServersRef );
CFStringRef curServerName = NULL;
char* curServerCStringName = NULL;
for ( ; curServerIndex < numServers; curServerIndex++ )
{
curServerName = (CFStringRef)CFArrayGetValueAtIndex( mNISServersRef, curServerIndex );
if ( curServerName && CFStringGetLength(curServerName) > 1 ) {
curServerCStringName = (char*)malloc( CFStringGetMaximumSizeForEncoding(CFStringGetLength(curServerName), kCFStringEncodingUTF8) + 1 );
if ( CFStringGetCString( curServerName, curServerCStringName, CFStringGetMaximumSizeForEncoding(CFStringGetLength(curServerName), kCFStringEncodingUTF8) + 1, kCFStringEncodingUTF8 ) )
{
char* resultPtr = CopyResultOfNISLookup( kNISrpcinfo, curServerCStringName );
if ( resultPtr && strstr( resultPtr, "ypbind" ) )
{
DBGLOG( "BSDPlugin::NISAvailable rpcinfo showed server [%s] running ypbind, setting nisAvail to true.\n%s", curServerCStringName, resultPtr );
nisAvail = true;
break; }
else
{
DBGLOG( "BSDPlugin::NISAvailable rpcinfo did not show server [%s] running ypbind\n%s", curServerCStringName, (resultPtr)?resultPtr:"" );
}
if ( resultPtr )
{
free( resultPtr );
resultPtr = NULL;
}
}
if ( curServerCStringName )
{
free( curServerCStringName );
curServerCStringName = NULL;
}
}
}
if ( curServerCStringName )
{
free( curServerCStringName );
curServerCStringName = NULL;
}
}
else
{
DBGLOG( "BSDPlugin::NISAvailable, checking to see if we can find a server dynamically by calling ypwhich" );
char* resultPtr = CopyResultOfNISLookup( kNISypwhich, NULL, NULL );
if ( !resultPtr )
{
DBGLOG( "BSDPlugin::NISAvailable, ypwhich returned no data, call ypbind and try again" );
resultPtr = CopyResultOfNISLookup( kNISbind );
if ( resultPtr )
free( resultPtr );
DBGLOG( "BSDPlugin::NISAvailable, trying ypwhich again" );
resultPtr = CopyResultOfNISLookup( kNISypwhich, NULL, NULL );
}
if ( resultPtr )
{
nisAvail = true; free( resultPtr );
}
}
}
DBGLOG( "BSDPlugin::NISAvailable returning: %s, mNISOK was %s", nisAvail?"true":"false", mNISOK?"true":"false" );
mNISOK = nisAvail;
return nisAvail;
}
Boolean BSDPlugin::AreNISServersReachable( void )
{
SCNetworkReachabilityRef target = NULL;
SCNetworkConnectionFlags flags;
Boolean reachable = false;
DBGLOG( "BSDPlugin::AreNISServersReachable called" );
if ( !mNISServersRef )
{
CFStringRef nisServersRef = CreateListOfServers();
if ( nisServersRef )
mNISServersRef = CFStringCreateArrayBySeparatingStrings( NULL, nisServersRef, CFSTR("\n") );
else
mNISServersRef = CFArrayCreate( NULL, NULL, 0, &kCFTypeArrayCallBacks );
}
if ( mNISServersRef && CFArrayGetCount( mNISServersRef ) > 0 )
{
CFIndex curServerIndex = 0;
CFIndex numServers = CFArrayGetCount( mNISServersRef );
CFStringRef curServerName = NULL;
char* curServerCStringName = NULL;
for ( ; curServerIndex < numServers; curServerIndex++ )
{
curServerName = (CFStringRef)CFArrayGetValueAtIndex( mNISServersRef, curServerIndex );
if ( curServerName && CFStringGetLength(curServerName) > 1 ) {
curServerCStringName = (char*)malloc( CFStringGetMaximumSizeForEncoding(CFStringGetLength(curServerName), kCFStringEncodingUTF8) + 1 );
if ( CFStringGetCString( curServerName, curServerCStringName, CFStringGetMaximumSizeForEncoding(CFStringGetLength(curServerName), kCFStringEncodingUTF8) + 1, kCFStringEncodingUTF8 ) )
{
DBGLOG( "BSDPlugin::AreNISServersReachable calling SCNetworkReachabilityCreateWithName on [%s]", curServerCStringName );
target = SCNetworkReachabilityCreateWithName( NULL, curServerCStringName );
DBGLOG( "BSDPlugin::AreNISServersReachable, SCNetworkReachabilityCreateWithName returned target: 0x%x", target );
if (target == NULL) {
continue;
}
if (!SCNetworkReachabilityGetFlags(target, &flags)) {
continue;
}
if (!(flags & kSCNetworkFlagsReachable)) {
continue;
}
if (flags & kSCNetworkFlagsConnectionRequired) {
continue;
}
reachable = true; break;
}
}
}
if ( curServerCStringName )
free( curServerCStringName );
}
else
{
reachable = true; }
if ( target )
CFRelease( target );
return ( reachable );
}
#pragma mark -
CFStringRef BSDPlugin::CreateListOfServers( void )
{
CFMutableStringRef listRef = NULL;
if ( mLocalNodeString )
{
FILE* fp = NULL;
char name[kMaxSizeOfParam] = {0};
snprintf( name, sizeof(name), "/var/yp/binding/%s.ypservers", mLocalNodeString );
fp = fopen(name,"r");
if (fp == NULL)
{
DBGLOG( "BSDPlugin::CreateListOfServers: Could not open config file %s: %s", name, strerror(errno) );
}
else
{
char buf[kMaxSizeOfParam];
while (fgets(buf,kMaxSizeOfParam,fp) != NULL)
{
if ( !listRef )
listRef = CFStringCreateMutable( NULL, 0 );
if ( listRef )
{
CFStringAppendCString( listRef, buf, kCFStringEncodingUTF8 );
}
else
{
DBGLOG( "BSDPlugin::CreateListOfServers: Could not allocate a CFString!\n" );
}
}
fclose( fp );
}
}
return listRef;
}
Boolean BSDPlugin::IsOurConfigNode( char* path )
{
Boolean result = false;
if ( strcmp( path+1, kConfigNodeName ) == 0 )
result = true;
return result;
}
Boolean BSDPlugin::IsOurDomainNode( char* path )
{
Boolean result = false;
DBGLOG( "BSDPlugin::IsOurDomainNode comparing path: %s to localNode: %s\n", (path)?path:"", (mLocalNodeString)?mLocalNodeString:"" );
if ( mLocalNodeString && strstr( path, mLocalNodeString ) != NULL )
result = true;
return result;
}
#ifdef BUILDING_COMBO_PLUGIN
Boolean BSDPlugin::IsOurFFNode( char* path )
{
Boolean result = false;
DBGLOG( "BSDPlugin::IsOurDomainNode comparing path: %s to FF Node Name: %s\n", (path)?path:"", kFFNodeName );
if ( path && ( strcmp( path, "/BSD/" kFFNodeName ) == 0
|| strcmp( path, "/BSD Configuration Files/" kFFNodeName ) == 0 ))
result = true;
return result;
}
#endif
#pragma mark
sInt32 BSDPlugin::OpenDirNode ( sOpenDirNode *inData )
{
sInt32 siResult = eDSNoErr;
char *nodeName = nil;
char *pathStr = nil;
char *protocolStr = nil;
tDataListPtr pNodeList = nil;
DBGLOG( "BSDPlugin::OpenDirNode %lx\n", inData->fOutNodeRef );
if ( inData != nil )
{
pNodeList = inData->fInDirNodeName;
pathStr = dsGetPathFromListPriv( pNodeList, (char *)"/" );
protocolStr = pathStr + 1;
DBGLOG( "BSDPlugin::OpenDirNode, ProtocolPrefixString is %s, pathStr is %s\n", GetProtocolPrefixString(), pathStr );
if ( IsOurConfigNode(pathStr) || IsOurDomainNode(pathStr)
#ifdef BUILDING_COMBO_PLUGIN
|| IsOurFFNode(pathStr)
#endif
)
{
if ( !IsOurFFNode(pathStr) && !IsOurConfigNode(pathStr) && !NISAvailable() )
{
siResult = eDSOpenNodeFailed;
DBGLOG( "BSDPlugin::OpenDirNode returning eDSOpenNodeFailed due to NIS not being available\n" );
}
else
{
nodeName = new char[1+strlen(protocolStr)];
if ( !nodeName ) throw ( eDSNullNodeName );
::strcpy(nodeName,protocolStr);
if ( nodeName )
{
DBGLOG( "BSDPlugin::OpenDirNode on %s\n", nodeName );
BSDDirNodeRep* newNodeRep = new BSDDirNodeRep( this, (const void*)inData->fOutNodeRef );
if (!newNodeRep) throw ( eDSNullNodeName );
siResult = newNodeRep->Initialize( nodeName, inData->fInUID );
if ( !siResult )
{
LockPlugin();
newNodeRep->Retain();
::CFDictionaryAddValue( mOpenRefTable, (const void*)inData->fOutNodeRef, (const void*)newNodeRep );
UnlockPlugin();
}
delete( nodeName );
nodeName = nil;
}
}
}
else
{
siResult = eNotHandledByThisNode;
}
}
else
{
DBGLOG( "BSDPlugin::OpenDirNode inData is NULL!\n" );
siResult = eDSNullParameter;
}
if (pathStr != NULL)
{
free(pathStr);
pathStr = NULL;
}
return siResult;
}
sInt32 BSDPlugin::CloseDirNode ( sCloseDirNode *inData )
{
sInt32 siResult = eDSNoErr;
DBGLOG( "BSDPlugin::CloseDirNode %lx\n", inData->fInNodeRef );
if ( inData != nil && inData->fInNodeRef && mOpenRefTable )
{
BSDDirNodeRep* nodeRep = NULL;
LockPlugin();
nodeRep = (BSDDirNodeRep*)::CFDictionaryGetValue( mOpenRefTable, (const void*)inData->fInNodeRef );
DBGLOG( "BSDPlugin::CloseDirNode, CFDictionaryGetValue returned nodeRep: 0x%x\n", (int)nodeRep );
if ( nodeRep )
{
::CFDictionaryRemoveValue( mOpenRefTable, (void*)inData->fInNodeRef );
DBGLOG( "BSDPlugin::CloseDirNode, Release nodeRep: 0x%x\n", (int)nodeRep );
nodeRep->Release();
}
else
{
DBGLOG( "BSDPlugin::CloseDirNode, nodeRef not found in our list\n" );
}
UnlockPlugin();
}
return siResult;
}
#pragma mark
sInt32 BSDPlugin::GetDirNodeInfo ( sGetDirNodeInfo *inData )
{
sInt32 siResult = eDSNoErr;
uInt32 uiOffset = 0;
uInt32 uiCntr = 1;
uInt32 uiAttrCnt = 0;
CAttributeList *inAttrList = nil;
char *pAttrName = nil;
CBuff outBuff;
CDataBuff *aRecData = nil;
CDataBuff *aAttrData = nil;
CDataBuff *aTmpData = nil;
char *pData = nil;
sNISContextData *pAttrContext = nil;
BSDDirNodeRep* nodeRep = NULL;
LockPlugin();
try
{
if ( inData == nil ) throw( (sInt32)eMemoryError );
nodeRep = (BSDDirNodeRep*)::CFDictionaryGetValue( mOpenRefTable, (const void*)inData->fInNodeRef );
if ( nodeRep == nil ) throw( (sInt32)eDSBadContextData );
nodeRep->Retain();
inAttrList = new CAttributeList( inData->fInDirNodeInfoTypeList );
if ( inAttrList == nil ) throw( (sInt32)eDSNullNodeInfoTypeList );
if (inAttrList->GetCount() == 0) throw( (sInt32)eDSEmptyNodeInfoTypeList );
siResult = outBuff.Initialize( inData->fOutDataBuff, true );
if ( siResult != eDSNoErr ) throw( siResult );
siResult = outBuff.SetBuffType( 'Gdni' ); if ( siResult != eDSNoErr ) throw( siResult );
aRecData = new CDataBuff();
if ( aRecData == nil ) throw( (sInt32)eMemoryError );
aAttrData = new CDataBuff();
if ( aAttrData == nil ) throw( (sInt32)eMemoryError );
aTmpData = new CDataBuff();
if ( aTmpData == nil ) throw( (sInt32)eMemoryError );
aRecData->AppendShort( ::strlen( "dsAttrTypeStandard:DirectoryNodeInfo" ) );
aRecData->AppendString( (char *)"dsAttrTypeStandard:DirectoryNodeInfo" );
aRecData->AppendShort( ::strlen( "DirectoryNodeInfo" ) );
aRecData->AppendString( (char *)"DirectoryNodeInfo" );
while ( inAttrList->GetAttribute( uiCntr++, &pAttrName ) == eDSNoErr )
{
if ((::strcmp( pAttrName, kDSAttributesAll ) == 0) ||
(::strcmp( pAttrName, kDSNAttrNodePath ) == 0) )
{
aTmpData->Clear();
uiAttrCnt++;
aTmpData->AppendShort( ::strlen( kDSNAttrNodePath ) );
aTmpData->AppendString( kDSNAttrNodePath );
if ( inData->fInAttrInfoOnly == false )
{
aTmpData->AppendShort( 2 );
aTmpData->AppendLong( ::strlen( "BSD" ) );
aTmpData->AppendString( (char *)"BSD" );
char *tmpStr = NULL;
CFStringRef cfNodeName = nodeRep->GetNodeName();
if (cfNodeName != NULL && CFStringCompare(cfNodeName, CFSTR("BSD"), 0) != kCFCompareEqualTo)
{
CFIndex len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(nodeRep->GetNodeName()), kCFStringEncodingUTF8) + 1;
tmpStr = new char[1+len];
CFStringGetCString( nodeRep->GetNodeName(), tmpStr, len, kCFStringEncodingUTF8 );
char *nodePath = ::strdup( tmpStr + 4 );
delete tmpStr;
tmpStr = nodePath;
}
else
{
tmpStr = ::strdup( "Unknown Node Location" );
}
aTmpData->AppendLong( ::strlen( tmpStr ) );
aTmpData->AppendString( tmpStr );
delete( tmpStr );
} else
{
aTmpData->AppendShort( 0 );
}
aAttrData->AppendLong( aTmpData->GetLength() );
aAttrData->AppendBlock( aTmpData->GetData(), aTmpData->GetLength() );
aTmpData->Clear();
}
if ( (::strcmp( pAttrName, kDSAttributesAll ) == 0) ||
(::strcmp( pAttrName, kDS1AttrReadOnlyNode ) == 0) )
{
aTmpData->Clear();
uiAttrCnt++;
aTmpData->AppendShort( ::strlen( kDS1AttrReadOnlyNode ) );
aTmpData->AppendString( kDS1AttrReadOnlyNode );
if ( inData->fInAttrInfoOnly == false )
{
aTmpData->AppendShort( 1 );
aTmpData->AppendLong( ::strlen( "ReadOnly" ) );
aTmpData->AppendString( "ReadOnly" );
}
else
{
aTmpData->AppendShort( 0 );
}
aAttrData->AppendLong( aTmpData->GetLength() );
aAttrData->AppendBlock( aTmpData->GetData(), aTmpData->GetLength() );
aTmpData->Clear();
}
if ( (::strcmp( pAttrName, kDSAttributesAll ) == 0) ||
(::strcmp( pAttrName, kDSNAttrRecordType ) == 0) )
{
aTmpData->Clear();
uiAttrCnt++;
aTmpData->AppendShort( ::strlen( kDSNAttrRecordType ) );
aTmpData->AppendString( kDSNAttrRecordType );
CFStringRef cfNodeName = nodeRep->GetNodeName();
if ( inData->fInAttrInfoOnly == false &&
cfNodeName != NULL && CFStringCompare(cfNodeName, CFSTR("BSD"), 0) != kCFCompareEqualTo )
{
aTmpData->AppendShort( 12 );
aTmpData->AppendLong( ::strlen( kDSStdRecordTypeUsers ) );
aTmpData->AppendString( kDSStdRecordTypeUsers );
aTmpData->AppendLong( ::strlen( kDSStdRecordTypeGroups ) );
aTmpData->AppendString( kDSStdRecordTypeGroups );
aTmpData->AppendLong( ::strlen( kDSStdRecordTypeBootp ) );
aTmpData->AppendString( kDSStdRecordTypeBootp );
aTmpData->AppendLong( ::strlen( kDSStdRecordTypeEthernets ) );
aTmpData->AppendString( kDSStdRecordTypeEthernets );
aTmpData->AppendLong( ::strlen( kDSStdRecordTypeHosts ) );
aTmpData->AppendString( kDSStdRecordTypeHosts );
aTmpData->AppendLong( ::strlen( kDSStdRecordTypeMounts ) );
aTmpData->AppendString( kDSStdRecordTypeMounts );
aTmpData->AppendLong( ::strlen( kDSStdRecordTypeNetGroups ) );
aTmpData->AppendString( kDSStdRecordTypeNetGroups );
aTmpData->AppendLong( ::strlen( kDSStdRecordTypeNetworks ) );
aTmpData->AppendString( kDSStdRecordTypeNetworks );
aTmpData->AppendLong( ::strlen( kDSStdRecordTypePrintService ) );
aTmpData->AppendString( kDSStdRecordTypePrintService );
aTmpData->AppendLong( ::strlen( kDSStdRecordTypeProtocols ) );
aTmpData->AppendString( kDSStdRecordTypeProtocols );
aTmpData->AppendLong( ::strlen( kDSStdRecordTypeRPC ) );
aTmpData->AppendString( kDSStdRecordTypeRPC );
aTmpData->AppendLong( ::strlen( kDSStdRecordTypeServices ) );
aTmpData->AppendString( kDSStdRecordTypeServices );
}
else
{
aTmpData->AppendShort( 0 );
}
aAttrData->AppendLong( aTmpData->GetLength() );
aAttrData->AppendBlock( aTmpData->GetData(), aTmpData->GetLength() );
aTmpData->Clear();
}
if ((::strcmp( pAttrName, kDSAttributesAll ) == 0) ||
(::strcmp( pAttrName, kDSNAttrAuthMethod ) == 0) )
{
aTmpData->Clear();
uiAttrCnt++;
aTmpData->AppendShort( ::strlen( kDSNAttrAuthMethod ) );
aTmpData->AppendString( kDSNAttrAuthMethod );
if ( inData->fInAttrInfoOnly == false )
{
aTmpData->AppendShort( 4 );
aTmpData->AppendLong( ::strlen( kDSStdAuthCrypt ) );
aTmpData->AppendString( kDSStdAuthCrypt );
aTmpData->AppendLong( ::strlen( kDSStdAuthClearText ) );
aTmpData->AppendString( kDSStdAuthClearText );
aTmpData->AppendLong( ::strlen( kDSStdAuthNodeNativeNoClearText ) );
aTmpData->AppendString( kDSStdAuthNodeNativeNoClearText );
aTmpData->AppendLong( ::strlen( kDSStdAuthNodeNativeClearTextOK ) );
aTmpData->AppendString( kDSStdAuthNodeNativeClearTextOK );
} else
{
aTmpData->AppendShort( 0 );
}
aAttrData->AppendLong( aTmpData->GetLength() );
aAttrData->AppendBlock( aTmpData->GetData(), aTmpData->GetLength() );
aTmpData->Clear();
} }
aRecData->AppendShort( uiAttrCnt );
if (uiAttrCnt > 0)
{
aRecData->AppendBlock( aAttrData->GetData(), aAttrData->GetLength() );
}
outBuff.AddData( aRecData->GetData(), aRecData->GetLength() );
inData->fOutAttrInfoCount = uiAttrCnt;
pData = outBuff.GetDataBlock( 1, &uiOffset );
if ( pData != nil )
{
pAttrContext = MakeContextData();
if ( pAttrContext == nil ) throw( (sInt32)eMemoryAllocError );
pAttrContext->offset = uiOffset + 61;
::CFDictionaryAddValue( mOpenRefTable, (const void*)inData->fOutAttrListRef, (const void*)pAttrContext );
}
}
catch( sInt32 err )
{
siResult = err;
}
if ( nodeRep )
nodeRep->Release();
UnlockPlugin();
if ( inAttrList != nil )
{
delete( inAttrList );
inAttrList = nil;
}
if ( aRecData != nil )
{
delete( aRecData );
aRecData = nil;
}
if ( aAttrData != nil )
{
delete( aAttrData );
aAttrData = nil;
}
if ( aTmpData != nil )
{
delete( aTmpData );
aTmpData = nil;
}
return( siResult );
}
#pragma mark
sInt32 BSDPlugin::ReleaseContinueData( sNISContinueData* continueData )
{
sInt32 siResult = eDSNoErr;
if ( continueData )
{
pthread_mutex_lock( &continueData->fLock );
if ( continueData->fResultArrayRef )
{
CFRelease( continueData->fResultArrayRef );
}
continueData->fResultArrayRef = NULL;
pthread_mutex_unlock( &continueData->fLock );
free( continueData );
}
return siResult;
}
#pragma mark
sInt32 BSDPlugin::GetRecRefInfo ( sGetRecRefInfo *inData )
{
sInt32 siResult = eDSNoErr;
uInt32 uiRecSize = 0;
uInt32 uiDataLen = 0;
tRecordEntry *pRecEntry = nil;
CFStringRef cfRefType = 0;
CFStringRef cfRefName = 0;
char *refType = nil;
uInt32 refTypeLen = 0;
uInt32 uiOffset = 0;
char *refName = nil;
uInt32 refNameLen = 0;
if ( inData == NULL ) return eDSNullParameter;
DBGLOG( "BSDPlugin::GetRecRefInfo called on refNum:0x%x\n", (int)inData->fInRecRef );
CFDictionaryRef recordRef = GetRecordFromRecRef( inData->fInRecRef );
if ( !recordRef )
{
DBGLOG( "BSDPlugin::GetRecRefInfo, unknown record\n" );
return eDSInvalidRecordRef;
}
CFPropertyListRef valueResult = (CFPropertyListRef)CFDictionaryGetValue( recordRef, CFSTR( kDSNAttrRecordType ) );
if ( valueResult )
{
if ( CFGetTypeID( valueResult ) == CFStringGetTypeID() )
{
cfRefType = (CFStringRef)valueResult;
}
else if ( CFGetTypeID( valueResult ) == CFArrayGetTypeID() )
{
if ( CFArrayGetCount( (CFArrayRef)valueResult ) > 0 )
{
cfRefType = (CFStringRef)CFArrayGetValueAtIndex( (CFArrayRef)valueResult, 0 );
}
}
}
valueResult = (CFPropertyListRef)CFDictionaryGetValue( recordRef, CFSTR( kDSNAttrRecordName ) );
if ( valueResult )
{
if ( CFGetTypeID( valueResult ) == CFStringGetTypeID() )
{
cfRefName = (CFStringRef)valueResult;
}
else if ( CFGetTypeID( valueResult ) == CFArrayGetTypeID() )
{
if ( CFArrayGetCount( (CFArrayRef)valueResult ) > 0 )
{
cfRefName = (CFStringRef)CFArrayGetValueAtIndex( (CFArrayRef)valueResult, 0 );
}
}
}
if ( cfRefType )
{
uiDataLen = CFStringGetMaximumSizeForEncoding(CFStringGetLength(cfRefType), kCFStringEncodingUTF8) + 1;
refType = (char *)::calloc( uiDataLen, sizeof( char ) );
CFStringGetCString( cfRefType, refType, uiDataLen, kCFStringEncodingUTF8 );
}
else
{
refType = strdup( "Record Type Unknown" );
}
if ( cfRefName )
{
uiDataLen = CFStringGetMaximumSizeForEncoding(CFStringGetLength(cfRefName), kCFStringEncodingUTF8) + 1;
refName = (char *)::calloc( uiDataLen, sizeof( char ) );
CFStringGetCString( cfRefName, refName, uiDataLen, kCFStringEncodingUTF8 );
}
else
{
refName = strdup( "Record Name Unknown" );
}
refTypeLen = ::strlen( refType );
refNameLen = ::strlen( refName );
uiRecSize = sizeof( tRecordEntry ) + refTypeLen + refNameLen + 4 + kBuffPad;
pRecEntry = (tRecordEntry *)::calloc( 1, uiRecSize );
pRecEntry->fRecordNameAndType.fBufferSize = refTypeLen + refNameLen + 4 + kBuffPad;
pRecEntry->fRecordNameAndType.fBufferLength = refTypeLen + refNameLen + 4;
uiOffset = 0;
uInt16 strLen = 0;
strLen = ::strlen( refName );
::memcpy( pRecEntry->fRecordNameAndType.fBufferData + uiOffset, &strLen, 2);
uiOffset += 2;
::memcpy( pRecEntry->fRecordNameAndType.fBufferData + uiOffset, refName, strLen);
uiOffset += strLen;
strLen = ::strlen( refType );
::memcpy( pRecEntry->fRecordNameAndType.fBufferData + uiOffset, &strLen, 2);
uiOffset += 2;
::memcpy( pRecEntry->fRecordNameAndType.fBufferData + uiOffset, refType, strLen);
uiOffset += strLen;
inData->fOutRecInfo = pRecEntry;
if (refType != nil)
{
free( refType );
refType = nil;
}
if (refName != nil)
{
free( refName );
refName = nil;
}
return( siResult );
}
sInt32 BSDPlugin::GetRecordEntry ( sGetRecordEntry *inData )
{
sInt32 siResult = eDSNoErr;
uInt32 uiIndex = 0;
uInt32 uiCount = 0;
uInt32 uiOffset = 0;
uInt32 uberOffset = 0;
char *pData = nil;
tRecordEntryPtr pRecEntry = nil;
sNISContextData *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;
LockPlugin();
try
{
if ( inData == nil ) throw( (sInt32) eDSNullParameter );
if ( inData->fInOutDataBuff == nil ) throw( (sInt32)eDSEmptyBuffer );
if (inData->fInOutDataBuff->fBufferSize == 0) throw( (sInt32)eDSEmptyBuffer );
siResult = inBuff.Initialize( inData->fInOutDataBuff );
if ( siResult != eDSNoErr ) throw( siResult );
siResult = inBuff.GetDataBlockCount( &uiCount );
if ( siResult != eDSNoErr ) throw( siResult );
uiIndex = inData->fInRecEntryIndex;
if ((uiIndex > uiCount) || (uiIndex == 0)) throw( (sInt32)eDSInvalidIndex );
pData = inBuff.GetDataBlock( uiIndex, &uberOffset );
if ( pData == nil ) throw( (sInt32)eDSCorruptBuffer );
buffLen = inBuff.GetDataBlockLength( uiIndex );
pData += 4;
offset = 0;
if (offset + 2 > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &usTypeLen, pData, 2 );
pData += 2;
offset += 2;
pRecType = pData;
pData += usTypeLen;
offset += usTypeLen;
if (offset + 2 > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &usNameLen, pData, 2 );
pData += 2;
offset += 2;
pRecName = pData;
pData += usNameLen;
offset += usNameLen;
if (offset + 2 > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &usAttrCnt, pData, 2 );
pRecEntry = (tRecordEntry *)::calloc( 1, sizeof( tRecordEntry ) + usNameLen + usTypeLen + 4 + kBuffPad );
pRecEntry->fRecordNameAndType.fBufferSize = usNameLen + usTypeLen + 4 + kBuffPad;
pRecEntry->fRecordNameAndType.fBufferLength = usNameLen + usTypeLen + 4;
::memcpy( pRecEntry->fRecordNameAndType.fBufferData, &usNameLen, 2 );
uiOffset += 2;
::memcpy( pRecEntry->fRecordNameAndType.fBufferData + uiOffset, pRecName, usNameLen );
uiOffset += usNameLen;
::memcpy( pRecEntry->fRecordNameAndType.fBufferData + uiOffset, &usTypeLen, 2 );
uiOffset += 2;
::memcpy( pRecEntry->fRecordNameAndType.fBufferData + uiOffset, pRecType, usTypeLen );
pRecEntry->fRecordAttributeCount = usAttrCnt;
pContext = new sNISContextData;
if ( pContext == nil ) throw( (sInt32) eMemoryAllocError );
pContext->offset = uberOffset + offset + 4;
::CFDictionaryAddValue( mOpenRefTable, (const void*)inData->fOutAttrListRef, (const void*)pContext );
inData->fOutRecEntryPtr = pRecEntry;
}
catch ( sInt32 err )
{
siResult = err;
}
UnlockPlugin();
return( siResult );
}
sInt32 BSDPlugin::GetAttributeEntry ( sGetAttributeEntry *inData )
{
sInt32 siResult = eDSNoErr;
uInt16 usAttrTypeLen = 0;
uInt16 usAttrCnt = 0;
uInt32 usAttrLen = 0;
uInt16 usValueCnt = 0;
uInt32 usValueLen = 0;
uInt32 i = 0;
uInt32 uiIndex = 0;
uInt32 uiAttrEntrySize = 0;
uInt32 uiOffset = 0;
uInt32 uiTotalValueSize = 0;
uInt32 offset = 4;
uInt32 buffSize = 0;
uInt32 buffLen = 0;
char *p = nil;
char *pAttrType = nil;
tDataBufferPtr pDataBuff = nil;
tAttributeEntryPtr pAttribInfo = nil;
sNISContextData *pAttrContext = nil;
sNISContextData *pValueContext = nil;
LockPlugin();
try
{
if ( inData == nil ) throw( (sInt32)eMemoryError );
pAttrContext = (sNISContextData *)::CFDictionaryGetValue( mOpenRefTable, (const void*)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 > (sInt32)(buffSize - offset)) 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 > (sInt32)(buffSize - offset)) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &usAttrLen, p, 4 );
p += 4 + usAttrLen;
offset += 4 + usAttrLen;
}
uiOffset = offset;
if (4 > (sInt32)(buffSize - offset)) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &usAttrLen, p, 4 );
p += 4;
offset += 4;
buffLen = offset + usAttrLen;
if (2 > (sInt32)(buffLen - offset)) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &usAttrTypeLen, p, 2 );
pAttrType = p + 2;
p += 2 + usAttrTypeLen;
offset += 2 + usAttrTypeLen;
if (2 > (sInt32)(buffLen - offset)) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &usValueCnt, p, 2 );
p += 2;
offset += 2;
for ( i = 0; i < usValueCnt; i++ )
{
if (4 > (sInt32)(buffLen - offset)) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &usValueLen, p, 4 );
p += 4 + usValueLen;
offset += 4 + usValueLen;
uiTotalValueSize += usValueLen;
}
uiAttrEntrySize = sizeof( tAttributeEntry ) + usAttrTypeLen + kBuffPad;
pAttribInfo = (tAttributeEntry *)::calloc( 1, uiAttrEntrySize );
pAttribInfo->fAttributeValueCount = usValueCnt;
pAttribInfo->fAttributeDataSize = uiTotalValueSize;
pAttribInfo->fAttributeValueMaxSize = 512; pAttribInfo->fAttributeSignature.fBufferSize = usAttrTypeLen + kBuffPad;
pAttribInfo->fAttributeSignature.fBufferLength = usAttrTypeLen;
::memcpy( pAttribInfo->fAttributeSignature.fBufferData, pAttrType, usAttrTypeLen );
pValueContext = MakeContextData();
if ( pValueContext == nil ) throw( (sInt32)eMemoryAllocError );
pValueContext->offset = uiOffset;
::CFDictionaryAddValue( mOpenRefTable, (const void*)inData->fOutAttrValueListRef, (const void*)pValueContext );
inData->fOutAttrInfoPtr = pAttribInfo;
}
catch( sInt32 err )
{
siResult = err;
}
UnlockPlugin();
return( siResult );
}
sInt32 BSDPlugin::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;
sNISContextData *pValueContext = nil;
uInt32 buffSize = 0;
uInt32 buffLen = 0;
uInt32 attrLen = 0;
LockPlugin();
try
{
pValueContext = (sNISContextData *)::CFDictionaryGetValue( mOpenRefTable, (const void*)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 > (sInt32)(buffSize - offset)) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &attrLen, p, 4 );
buffLen = attrLen + pValueContext->offset + 4;
if (buffLen > buffSize) throw( (sInt32)eDSInvalidBuffFormat );
p += 4;
offset += 4;
if (2 > (sInt32)(buffLen - offset)) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &usAttrNameLen, p, 2 );
p += 2 + usAttrNameLen;
offset += 2 + usAttrNameLen;
if (2 > (sInt32)(buffLen - offset)) 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 > (sInt32)(buffLen - offset)) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &usValueLen, p, 4 );
p += 4 + usValueLen;
offset += 4 + usValueLen;
}
if (4 > (sInt32)(buffLen - offset)) 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 ( (sInt32)usValueLen > (sInt32)(buffLen - offset)) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( pAttrValue->fAttributeValueData.fBufferData, p, usValueLen );
pAttrValue->fAttributeValueID = inData->fInAttrValueIndex;
inData->fOutAttrValue = pAttrValue;
}
catch( sInt32 err )
{
siResult = err;
}
UnlockPlugin();
return( siResult );
}
sInt32 BSDPlugin::GetRecordList ( sGetRecordList *inData )
{
sInt32 siResult = eDSNoErr;
char *pRecType = nil;
const char *pNSLRecType = nil;
CAttributeList *cpRecNameList = nil;
CAttributeList *cpRecTypeList = nil;
CBuff *outBuff = nil;
uInt32 countDownRecTypes = 0;
BSDDirNodeRep* nodeDirRep = nil;
sNISContinueData *pContinue = (sNISContinueData*)inData->fIOContinueData;
LockPlugin();
DBGLOG( "BSDPlugin::GetRecordList called\n" );
nodeDirRep = (BSDDirNodeRep*)::CFDictionaryGetValue( mOpenRefTable, (const void*)inData->fInNodeRef );
if( !nodeDirRep )
{
DBGLOG( "BSDPlugin::GetRecordList called but we couldn't find the nodeDirRep!\n" );
UnlockPlugin();
return eDSInvalidNodeRef;
}
nodeDirRep->Retain();
UnlockPlugin();
nodeDirRep->SearchListQueueLock();
try
{
if ( nodeDirRep->IsTopLevelNode() )
{
DBGLOG( "BSDPlugin::GetRecordList, we don't have any records in our top level node.\n" );
inData->fOutRecEntryCount = 0;
inData->fIOContinueData = NULL;
}
else
{
if ( !mLocalNodeString && !nodeDirRep->IsFFNode() )
{
DBGLOG( "BSDPlugin::GetRecordList we have no domain, returning zero results\n" );
inData->fOutRecEntryCount = 0;
inData->fIOContinueData = NULL;
}
else if ( nodeDirRep && !pContinue )
{
DBGLOG( "BSDPlugin::GetRecordList called, lookup hasn't been started yet.\n" );
if( !inData ) throw( eMemoryError );
if( !inData->fInDataBuff) throw( eDSEmptyBuffer );
if( (inData->fInDataBuff->fBufferSize == 0) ) throw( eDSEmptyBuffer );
if( !inData->fInRecNameList ) throw( eDSEmptyRecordNameList );
if( !inData->fInRecTypeList ) throw( eDSEmptyRecordTypeList );
if( !inData->fInAttribTypeList ) throw( eDSEmptyAttributeTypeList );
pContinue = (sNISContinueData *)::calloc( sizeof( sNISContinueData ), sizeof( char ) );
DBGLOG( "BSDPlugin::GetRecordList created a new pContinue: 0x%x\n", (int)pContinue );
pContinue->fRecNameIndex = 1;
pContinue->fAllRecIndex = 0;
pContinue->fTotalRecCount = 0;
pContinue->fRecTypeIndex = 1;
pContinue->fAttrIndex = 1;
pContinue->fLimitRecSearch = 0;
pContinue->fResultArrayRef = CFArrayCreateMutable( NULL, 0, &kCFTypeArrayCallBacks );
pContinue->fSearchComplete = false;
pthread_mutex_init( &pContinue->fLock, NULL );
if (inData->fOutRecEntryCount >= 0)
{
DBGLOG( "BSDPlugin::DoAttributeValueSearch, setting pContinue->fLimitRecSearch to %ld\n", inData->fOutRecEntryCount );
pContinue->fLimitRecSearch = inData->fOutRecEntryCount;
}
inData->fOutRecEntryCount = 0;
cpRecTypeList = new CAttributeList( inData->fInRecTypeList );
if( !cpRecTypeList ) throw( eDSEmptyRecordTypeList );
countDownRecTypes = cpRecTypeList->GetCount();
if( (countDownRecTypes == 0) ) throw( eDSEmptyRecordTypeList );
sInt32 error = eDSNoErr;
nodeDirRep->LookupHasStarted();
cpRecNameList = new CAttributeList( inData->fInRecNameList );
if ( !cpRecNameList ) throw( eMemoryError );
uInt32 numRecNames = cpRecNameList->GetCount();
pthread_mutex_lock( &pContinue->fLock );
for ( uInt16 i=1; i<=countDownRecTypes; i++ )
{
if ( (error = cpRecTypeList->GetAttribute( i, &pRecType )) == eDSNoErr )
{
DBGLOG( "BSDPlugin::GetRecordList, GetAttribute(%d of %ld) returned pRecType: %s\n", i, countDownRecTypes, pRecType );
#ifdef BUILDING_COMBO_PLUGIN
if ( nodeDirRep->IsFFNode() )
pNSLRecType = GetFFTypeFromRecType( pRecType );
else
#endif
pNSLRecType = GetNISTypeFromRecType( pRecType );
if ( pNSLRecType )
{
if ( inData->fInPatternMatch == eDSExact || inData->fInPatternMatch == eDSiExact )
{
char *pRecName = nil;
for ( uInt16 i=1; i<=numRecNames; i++ )
{
if ( (error = cpRecNameList->GetAttribute( i, &pRecName )) == eDSNoErr && pRecName )
{
if ( strcmp( pRecName, "dsRecordsAll" ) == 0 )
DoRecordsLookup( (CFMutableArrayRef)pContinue->fResultArrayRef, nodeDirRep->IsFFNode(), pRecType, pNSLRecType ); else
DoRecordsLookup( (CFMutableArrayRef)pContinue->fResultArrayRef, nodeDirRep->IsFFNode(), pRecType, pNSLRecType, pRecName );
}
}
}
else
DoRecordsLookup( (CFMutableArrayRef)pContinue->fResultArrayRef, nodeDirRep->IsFFNode(), pRecType, pNSLRecType );
}
else
DBGLOG( "BSDPlugin::GetRecordList, we don't have a mapping for type: %s, skipping\n", pRecType );
}
else
{
DBGLOG( "BSDPlugin::GetRecordList, GetAttribute returned error: %li\n", error );
}
}
pthread_mutex_unlock( &pContinue->fLock );
}
if ( nodeDirRep && pContinue )
{
siResult = RetrieveResults( inData->fInNodeRef,
inData->fInDataBuff,
inData->fInPatternMatch,
inData->fInRecNameList,
inData->fInRecTypeList,
inData->fInAttribInfoOnly,
inData->fInAttribTypeList,
&(inData->fOutRecEntryCount),
pContinue );
DBGLOG( "***Sending Back Results, fBufferSize = %ld, fBufferLength = %ld\n", inData->fInDataBuff->fBufferSize, inData->fInDataBuff->fBufferLength );
}
if ( nodeDirRep && pContinue && pContinue->fSearchComplete )
{
DBGLOG( "BSDPlugin::GetRecordList called and pContinue->fSearchComplete, we are done, Releaseing Continue Data (0x%x)\n", (int)pContinue );
ReleaseContinueData ( pContinue );
pContinue = NULL;
}
}
}
catch ( int err )
{
siResult = err;
if ( pContinue )
{
ReleaseContinueData ( pContinue );
pContinue = NULL;
}
DBGLOG( "BSDPlugin::GetRecordList, Caught error:%li\n", siResult );
}
if ( nodeDirRep )
nodeDirRep->Release();
if ( cpRecNameList != nil )
{
delete( cpRecNameList );
cpRecNameList = nil;
}
if ( cpRecTypeList != nil )
{
delete( cpRecTypeList );
cpRecTypeList = nil;
}
if ( outBuff != nil )
{
delete( outBuff );
outBuff = nil;
}
nodeDirRep->SearchListQueueUnlock();
DBGLOG( "BSDPlugin::GetRecordList returning, inData->fOutRecEntryCount: %ld, inData->fIOContinueData: 0x%x\n", inData->fOutRecEntryCount, (int)pContinue );
inData->fIOContinueData = pContinue;
return( siResult );
}
sInt32 BSDPlugin::OpenRecord ( sOpenRecord *inData )
{
tDirStatus siResult = eDSNoErr;
DBGLOG( "BSDPlugin::OpenRecord called on refNum:0x%x for record: %s of type: %s\n", (int)inData->fOutRecRef, (char*)inData->fInRecName->fBufferData, (char*)inData->fInRecType->fBufferData );
const char* pNSLRecType = NULL;
BSDDirNodeRep* nodeDirRep = (BSDDirNodeRep*)::CFDictionaryGetValue( mOpenRefTable, (const void*)inData->fInNodeRef );
if ( !nodeDirRep )
return eDSInvalidDirRef;
#ifdef BUILDING_COMBO_PLUGIN
if ( nodeDirRep->IsFFNode() )
pNSLRecType = GetFFTypeFromRecType( (char*)inData->fInRecType->fBufferData );
else
#endif
pNSLRecType = GetNISTypeFromRecType( (char*)inData->fInRecType->fBufferData );
if ( pNSLRecType )
{
CFMutableDictionaryRef recordResults = CopyRecordLookup( nodeDirRep->IsFFNode(), (const char*)inData->fInRecType->fBufferData, pNSLRecType, (char*)inData->fInRecName->fBufferData );
if ( recordResults )
AddRecordRecRef( inData->fOutRecRef, recordResults );
else
siResult = eDSRecordNotFound;
}
else
{
inData->fOutRecRef = 0;
siResult = eDSInvalidRecordType;
DBGLOG( "BSDPlugin::OpenRecord we don't support that type!\n" );
}
return( siResult );
}
sInt32 BSDPlugin::GetRecordAttributeInfo( sGetRecAttribInfo *inData )
{
tDirStatus siResult = eDSNoErr;
tAttributeEntryPtr pOutAttrEntry = NULL;
uInt32 uiTypeLen = 0;
if ( inData == NULL ) return eDSNullParameter;
DBGLOG( "BSDPlugin::GetRecordAttributeInfo called on refNum:0x%x, for type: %s\n", (int)inData->fInRecRef, (char*)inData->fInAttrType->fBufferData );
CFDictionaryRef recordRef = GetRecordFromRecRef( inData->fInRecRef );
if ( !recordRef )
{
DBGLOG( "BSDPlugin::GetRecordAttributeValueInfo, unknown record\n" );
return eDSInvalidRecordRef;
}
CFStringRef keyRef = CFStringCreateWithCString( NULL, (char*)inData->fInAttrType->fBufferData, kCFStringEncodingUTF8 );
if ( keyRef )
{
CFPropertyListRef valueResult = (CFPropertyListRef)CFDictionaryGetValue( recordRef, keyRef );
if ( valueResult )
{
uiTypeLen = ::strlen( inData->fInAttrType->fBufferData );
pOutAttrEntry = (tAttributeEntry *)::calloc( 1, sizeof( tAttributeEntry ) + uiTypeLen + 1 );
pOutAttrEntry->fAttributeSignature.fBufferSize = uiTypeLen;
pOutAttrEntry->fAttributeSignature.fBufferLength = uiTypeLen;
::memcpy( pOutAttrEntry->fAttributeSignature.fBufferData, inData->fInAttrType->fBufferData, uiTypeLen );
pOutAttrEntry->fAttributeValueMaxSize = 255;
if ( CFGetTypeID( valueResult ) == CFStringGetTypeID() )
{
pOutAttrEntry->fAttributeValueCount = 1;
}
else if ( CFGetTypeID( valueResult ) == CFArrayGetTypeID() )
{
pOutAttrEntry->fAttributeValueCount = CFArrayGetCount( (CFArrayRef)valueResult );
}
inData->fOutAttrInfoPtr = pOutAttrEntry;
}
else
{
DBGLOG( "BSDPlugin::GetRecordAttributeInfo, the value wasn't one we handle (%ld), ignoring\n", (valueResult)?CFGetTypeID( valueResult ):0 );
siResult = eDSAttributeNotFound; }
CFRelease( keyRef );
}
else
{
DBGLOG( "BSDPlugin::GetRecordAttributeInfo, couldn't create a keyRef!\n" );
siResult = eDSInvalidAttributeType;
}
return( siResult );
}
sInt32 BSDPlugin::GetRecordAttributeValueByIndex( sGetRecordAttributeValueByIndex *inData )
{
tDirStatus siResult = eDSNoErr;
tAttributeValueEntryPtr pOutAttrValue = nil;
uInt32 uiDataLen = 0;
if ( inData == NULL ) return eDSNullParameter;
DBGLOG( "BSDPlugin::GetRecordAttributeValueByIndex called on refNum:0x%x, for type: %s, index: %ld\n", (int)inData->fInRecRef, (char*)inData->fInAttrType->fBufferData, inData->fInAttrValueIndex );
CFDictionaryRef recordRef = GetRecordFromRecRef( inData->fInRecRef );
if ( !recordRef )
{
DBGLOG( "BSDPlugin::GetRecordAttributeValueByIndex, unknown record\n" );
return eDSInvalidRecordRef;
}
CFStringRef keyRef = CFStringCreateWithCString( NULL, (char*)inData->fInAttrType->fBufferData, kCFStringEncodingUTF8 );
if ( keyRef )
{
CFStringRef valueStringRef = NULL;
CFPropertyListRef valueResult = (CFPropertyListRef)CFDictionaryGetValue( recordRef, keyRef );
if ( valueResult && CFGetTypeID( valueResult ) == CFStringGetTypeID() )
{
if ( inData->fInAttrValueIndex == 1 )
valueStringRef = (CFStringRef)valueResult;
else
DBGLOG( "BSDPlugin::GetRecordAttributeValueByIndex, they are asking for an index of (%ld) when we only have one value\n", inData->fInAttrValueIndex );
}
else if ( valueResult && CFGetTypeID( valueResult ) == CFArrayGetTypeID() )
{
if ( (CFIndex)inData->fInAttrValueIndex <= CFArrayGetCount( (CFArrayRef)valueResult ) )
valueStringRef = (CFStringRef)CFArrayGetValueAtIndex( (CFArrayRef)valueResult, inData->fInAttrValueIndex-1 );
else
DBGLOG( "BSDPlugin::GetRecordAttributeValueByIndex, they are asking for an index of (%ld) when we only have %ld value(s)\n", inData->fInAttrValueIndex, CFArrayGetCount( (CFArrayRef)valueResult ) );
}
else
DBGLOG( "BSDPlugin::GetRecordAttributeValueByIndex, the value wasn't one we handle (%ld), ignoring\n", (valueResult)?CFGetTypeID( valueResult ):0 );
if ( valueStringRef )
{
uiDataLen = CFStringGetMaximumSizeForEncoding(CFStringGetLength(valueStringRef), kCFStringEncodingUTF8) + 1;
pOutAttrValue = (tAttributeValueEntry *)::calloc( (sizeof( tAttributeValueEntry ) + uiDataLen + kBuffPad), sizeof( char ) );
pOutAttrValue->fAttributeValueID = inData->fInAttrValueIndex; CFStringGetCString( valueStringRef, pOutAttrValue->fAttributeValueData.fBufferData, uiDataLen, kCFStringEncodingUTF8 );
uiDataLen = strlen( pOutAttrValue->fAttributeValueData.fBufferData );
pOutAttrValue->fAttributeValueData.fBufferSize = uiDataLen;
pOutAttrValue->fAttributeValueData.fBufferLength = uiDataLen;
inData->fOutEntryPtr = pOutAttrValue;
DBGLOG( "BSDPlugin::GetRecordAttributeValueByIndex, found the value: %s\n", pOutAttrValue->fAttributeValueData.fBufferData );
}
else
{
DBGLOG( "BSDPlugin::GetRecordAttributeValueByIndex, couldn't find any values with this key!\n" );
siResult = eDSIndexOutOfRange;
}
CFRelease( keyRef );
}
else
{
DBGLOG( "BSDPlugin::GetRecordAttributeValueByIndex, couldn't create a keyRef!\n" );
siResult = eDSInvalidAttributeType;
}
return( siResult );
}
sInt32 BSDPlugin::GetRecordAttributeValueByID( sGetRecordAttributeValueByID *inData )
{
tDirStatus siResult = eDSNoErr;
tAttributeValueEntryPtr pOutAttrValue = nil;
uInt32 uiDataLen = 0;
if ( inData == NULL ) return eDSNullParameter;
DBGLOG( "BSDPlugin::GetRecordAttributeValueByID called on refNum:0x%x, for type: %s, ID: %ld\n", (int)inData->fInRecRef, (char*)inData->fInAttrType->fBufferData, inData->fInValueID );
CFDictionaryRef recordRef = GetRecordFromRecRef( inData->fInRecRef );
if ( !recordRef )
{
DBGLOG( "BSDPlugin::GetRecordAttributeValueByID, unknown record\n" );
return eDSInvalidRecordRef;
}
CFStringRef keyRef = CFStringCreateWithCString( NULL, (char*)inData->fInAttrType->fBufferData, kCFStringEncodingUTF8 );
if ( keyRef )
{
CFStringRef valueStringRef = NULL;
CFPropertyListRef valueResult = (CFPropertyListRef)CFDictionaryGetValue( recordRef, keyRef );
if ( valueResult && CFGetTypeID( valueResult ) == CFStringGetTypeID() )
{
if ( inData->fInValueID == 1 )
valueStringRef = (CFStringRef)valueResult;
else
{
DBGLOG( "BSDPlugin::GetRecordAttributeValueByID, they are asking for an ID of (%ld) when we only have one value\n", inData->fInValueID );
siResult = eDSAttributeValueNotFound;
}
}
else if ( valueResult && CFGetTypeID( valueResult ) == CFArrayGetTypeID() )
{
if ( (CFIndex)inData->fInValueID <= CFArrayGetCount( (CFArrayRef)valueResult ) )
valueStringRef = (CFStringRef)CFArrayGetValueAtIndex( (CFArrayRef)valueResult, inData->fInValueID-1 );
else
{
DBGLOG( "BSDPlugin::GetRecordAttributeValueByID, they are asking for an ID of (%ld) when we only have %ld value(s)\n", inData->fInValueID, CFArrayGetCount( (CFArrayRef)valueResult ) );
siResult = eDSAttributeValueNotFound;
}
}
else
{
DBGLOG( "BSDPlugin::GetRecordAttributeValueByID, the value wasn't one we handle (%ld), ignoring\n", (valueResult)?CFGetTypeID( valueResult ):0 );
siResult = eDSAttributeNotFound;
}
if ( valueStringRef )
{
uiDataLen = CFStringGetMaximumSizeForEncoding(CFStringGetLength(valueStringRef), kCFStringEncodingUTF8) + 1;
pOutAttrValue = (tAttributeValueEntry *)::calloc( (sizeof( tAttributeValueEntry ) + uiDataLen + kBuffPad), sizeof( char ) );
pOutAttrValue->fAttributeValueID = inData->fInValueID; CFStringGetCString( valueStringRef, pOutAttrValue->fAttributeValueData.fBufferData, uiDataLen, kCFStringEncodingUTF8 );
uiDataLen = strlen( pOutAttrValue->fAttributeValueData.fBufferData );
pOutAttrValue->fAttributeValueData.fBufferSize = uiDataLen;
pOutAttrValue->fAttributeValueData.fBufferLength = uiDataLen;
inData->fOutEntryPtr = pOutAttrValue;
DBGLOG( "BSDPlugin::GetRecordAttributeValueByIndex, found the value: %s\n", pOutAttrValue->fAttributeValueData.fBufferData );
}
else
{
DBGLOG( "BSDPlugin::GetRecordAttributeValueByID, couldn't find any values with this key!\n" );
}
CFRelease( keyRef );
}
else
{
DBGLOG( "BSDPlugin::GetRecordAttributeValueByID, couldn't create a keyRef!\n" );
siResult = eDSInvalidAttributeType;
}
return( siResult );
}
sInt32 BSDPlugin::GetRecordAttributeValueByValue( sGetRecordAttributeValueByValue *inData )
{
tDirStatus siResult = eDSNoErr;
tAttributeValueEntryPtr pOutAttrValue = nil;
uInt32 uiDataLen = 0;
CFIndex i = 0;
if ( inData == NULL ) return eDSNullParameter;
DBGLOG( "BSDPlugin::GetRecordAttributeValueByValue called on refNum:0x%x, for type: %s, value: %s\n", (int)inData->fInRecRef, (char*)inData->fInAttrType->fBufferData, (char*)inData->fInAttrValue->fBufferData );
CFDictionaryRef recordRef = GetRecordFromRecRef( inData->fInRecRef );
if ( !recordRef )
{
DBGLOG( "BSDPlugin::GetRecordAttributeValueByValue, unknown record\n" );
return eDSInvalidRecordRef;
}
CFStringRef keyRef = CFStringCreateWithCString( NULL, (char*)inData->fInAttrType->fBufferData, kCFStringEncodingUTF8 );
CFStringRef value = CFStringCreateWithCString( NULL, (char*)inData->fInAttrValue->fBufferData, kCFStringEncodingUTF8 );
if ( keyRef && value )
{
CFStringRef valueStringRef = NULL;
CFPropertyListRef valueResult = (CFPropertyListRef)CFDictionaryGetValue( recordRef, keyRef );
if ( valueResult && CFGetTypeID( valueResult ) == CFStringGetTypeID() )
{
if ( CFStringCompare( value, (CFStringRef)valueResult, 0 ) == kCFCompareEqualTo )
{
valueStringRef = (CFStringRef)valueResult;
i = 0;
}
else
{
siResult = eDSAttributeValueNotFound;
}
}
else if ( valueResult && CFGetTypeID( valueResult ) == CFArrayGetTypeID() )
{
CFIndex count = CFArrayGetCount( (CFArrayRef)valueResult );
for ( i = 0; i < count; i++ )
{
valueStringRef = (CFStringRef)CFArrayGetValueAtIndex( (CFArrayRef)valueResult, i );
if ( CFStringCompare( value, (CFStringRef)valueStringRef, 0 ) == kCFCompareEqualTo )
{
break;
}
}
if ( i == count )
{
siResult = eDSAttributeValueNotFound;
}
}
else
{
DBGLOG( "BSDPlugin::GetRecordAttributeValueByValue, the value wasn't one we handle (%ld), ignoring\n", (valueResult)?CFGetTypeID( valueResult ):0 );
siResult = eDSAttributeNotFound;
}
if ( valueStringRef )
{
uiDataLen = CFStringGetMaximumSizeForEncoding(CFStringGetLength(valueStringRef), kCFStringEncodingUTF8) + 1;
pOutAttrValue = (tAttributeValueEntry *)::calloc( (sizeof( tAttributeValueEntry ) + uiDataLen + kBuffPad), sizeof( char ) );
pOutAttrValue->fAttributeValueID = i + 1; CFStringGetCString( valueStringRef, pOutAttrValue->fAttributeValueData.fBufferData, uiDataLen, kCFStringEncodingUTF8 );
uiDataLen = strlen( pOutAttrValue->fAttributeValueData.fBufferData );
pOutAttrValue->fAttributeValueData.fBufferSize = uiDataLen;
pOutAttrValue->fAttributeValueData.fBufferLength = uiDataLen;
inData->fOutEntryPtr = pOutAttrValue;
DBGLOG( "BSDPlugin::GetRecordAttributeValueByValue, found the value: %s\n", pOutAttrValue->fAttributeValueData.fBufferData );
}
else
{
DBGLOG( "BSDPlugin::GetRecordAttributeValueByValue, couldn't find any values with this key!\n" );
siResult = eDSIndexOutOfRange;
}
}
else if ( keyRef == NULL )
{
DBGLOG( "BSDPlugin::GetRecordAttributeValueByValue, couldn't create a keyRef!\n" );
siResult = eDSInvalidAttributeType;
}
else
{
DBGLOG( "BSDPlugin::GetRecordAttributeValueByValue, couldn't create value!\n" );
siResult = eDSAttributeValueNotFound;
}
DSCFRelease( keyRef );
DSCFRelease( value );
return( siResult );
}
sInt32 BSDPlugin::DoAttributeValueSearch( sDoAttrValueSearch* inData )
{
sInt32 siResult = eDSNoErr;
char *pRecType = nil;
const char* pNSLRecType = nil;
CAttributeList *cpRecNameList = nil;
CAttributeList *cpRecTypeList = nil;
CAttributeList *cpAttrTypeList = nil;
CBuff *outBuff = nil;
uInt32 countDownRecTypes = 0;
BSDDirNodeRep* nodeDirRep = nil;
sNISContinueData *pContinue = (sNISContinueData*)inData->fIOContinueData;
LockPlugin();
DBGLOG( "BSDPlugin::DoAttributeValueSearch called\n" );
nodeDirRep = (BSDDirNodeRep*)::CFDictionaryGetValue( mOpenRefTable, (const void*)inData->fInNodeRef );
if( !nodeDirRep )
{
DBGLOG( "BSDPlugin::DoAttributeValueSearch called but we couldn't find the nodeDirRep!\n" );
UnlockPlugin();
return eDSInvalidNodeRef;
}
nodeDirRep->Retain();
UnlockPlugin();
nodeDirRep->SearchListQueueLock();
try
{
if ( nodeDirRep->IsTopLevelNode() )
{
DBGLOG( "BSDPlugin::DoAttributeValueSearch, we don't have any records in our top level node.\n" );
inData->fOutMatchRecordCount = 0;
inData->fIOContinueData = NULL;
}
else
{
if ( nodeDirRep && !pContinue )
{
DBGLOG( "BSDPlugin::DoAttributeValueSearch called, lookup hasn't been started yet.\n" );
if( !inData ) throw( eMemoryError );
if( !inData->fOutDataBuff) throw( eDSEmptyBuffer );
if( (inData->fOutDataBuff->fBufferSize == 0) ) throw( eDSEmptyBuffer );
if( !inData->fInAttrType ) throw( eDSEmptyAttributeType );
if( !inData->fInPattMatchType ) throw( eDSEmptyPatternMatch );
if( !inData->fInPatt2Match ) throw( eDSEmptyPattern2Match );
if( !inData->fInRecTypeList ) throw( eDSEmptyRecordTypeList );
pContinue = (sNISContinueData *)::calloc( sizeof( sNISContinueData ), sizeof( char ) );
pContinue->fRecNameIndex = 1;
pContinue->fAllRecIndex = 0;
pContinue->fTotalRecCount = 0;
pContinue->fRecTypeIndex = 1;
pContinue->fAttrIndex = 1;
pContinue->fLimitRecSearch = 0;
pContinue->fResultArrayRef = CFArrayCreateMutable( NULL, 0, &kCFTypeArrayCallBacks );
pContinue->fSearchComplete = false;
if (inData->fOutMatchRecordCount >= 0)
{
DBGLOG( "BSDPlugin::DoAttributeValueSearch, setting pContinue->fLimitRecSearch to %ld\n", inData->fOutMatchRecordCount );
pContinue->fLimitRecSearch = inData->fOutMatchRecordCount;
}
inData->fOutMatchRecordCount = 0;
cpRecTypeList = new CAttributeList( inData->fInRecTypeList );
if( !cpRecTypeList ) throw( eDSEmptyRecordTypeList );
countDownRecTypes = cpRecTypeList->GetCount();
if( (countDownRecTypes == 0) ) throw( eDSEmptyRecordTypeList );
sInt32 error = eDSNoErr;
nodeDirRep->LookupHasStarted();
for ( uInt16 i=1; i<=countDownRecTypes; i++ )
{
if ( (error = cpRecTypeList->GetAttribute( i, &pRecType )) == eDSNoErr )
{
DBGLOG( "BSDPlugin::DoAttributeValueSearch, GetAttribute(%d) returned pRecType: %s\n", i, pRecType );
#ifdef BUILDING_COMBO_PLUGIN
if ( nodeDirRep->IsFFNode() )
pNSLRecType = GetFFTypeFromRecType( pRecType );
else
#endif
pNSLRecType = GetNISTypeFromRecType( pRecType );
if ( pNSLRecType )
{
DBGLOG( "BSDPlugin::DoAttributeValueSearch, looking up records of pNSLRecType: %s, matchType: 0x%x and pattern: \"%s\"\n", pNSLRecType, inData->fInPattMatchType, (inData->fInPatt2Match)?inData->fInPatt2Match->fBufferData:"NULL" );
DoRecordsLookup( (CFMutableArrayRef)pContinue->fResultArrayRef, nodeDirRep->IsFFNode(), pRecType, pNSLRecType, NULL, inData->fInPattMatchType, inData->fInPatt2Match, inData->fInAttrType->fBufferData );
}
else
DBGLOG( "BSDPlugin::DoAttributeValueSearch, we don't have a mapping for type: %s, skipping\n", pNSLRecType );
}
else
{
DBGLOG( "BSDPlugin::DoAttributeValueSearch, GetAttribute returned error: %li\n", error );
}
}
}
if ( nodeDirRep && pContinue )
{
tDataList allAttributesWanted;
tDataListPtr attrTypeList = NULL;
bool attrInfoOnly = false;
if (inData->fType == kDoAttributeValueSearchWithData)
{
attrTypeList = ((sDoAttrValueSearchWithData*)inData)->fInAttrTypeRequestList;
attrInfoOnly = ((sDoAttrValueSearchWithData*)inData)->fInAttrInfoOnly;
DBGLOG( "BSDPlugin::DoAttributeValueSearch inData->fType == kDoAttributeValueSearchWithData, inAttrInfoOnly: %d\n", attrInfoOnly );
}
else
{
dsBuildListFromStringsAlloc( inData->fInNodeRef, &allAttributesWanted, kDSAttributesAll, NULL );
attrTypeList = &allAttributesWanted;
}
if ( siResult == eDSNoErr )
{
siResult = RetrieveResults( inData->fInNodeRef,
inData->fOutDataBuff,
eDSAnyMatch,
NULL,
inData->fInRecTypeList,
attrInfoOnly,
attrTypeList,
&(inData->fOutMatchRecordCount),
pContinue );
if ( attrTypeList == &allAttributesWanted )
dsDataListDeallocate( inData->fInNodeRef, attrTypeList );
}
DBGLOG( "***Sending Back Results, fBufferSize = %ld, fBufferLength = %ld\n", inData->fOutDataBuff->fBufferSize, inData->fOutDataBuff->fBufferLength );
}
if ( nodeDirRep && pContinue && pContinue->fSearchComplete )
{
DBGLOG( "BSDPlugin::DoAttributeValueSearch called and pContinue->fSearchComplete, we are done\n" );
ReleaseContinueData ( pContinue );
pContinue = NULL;
}
else
usleep( 100000 ); }
}
catch ( int err )
{
siResult = err;
DBGLOG( "BSDPlugin::DoAttributeValueSearch, Caught error:%li\n", siResult );
}
if ( nodeDirRep )
nodeDirRep->Release();
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;
}
nodeDirRep->SearchListQueueUnlock();
DBGLOG( "BSDPlugin::DoAttributeValueSearch returning, inData->fOutMatchRecordCount: %ld, inData->fIOContinueData: 0x%x\n", inData->fOutMatchRecordCount, (int)pContinue );
inData->fIOContinueData = pContinue;
return( siResult );
}
sInt32 BSDPlugin::CloseRecord ( sCloseRecord *inData )
{
DBGLOG( "BSDPlugin::CloseRecord called on refNum:0x%x\n", (int)inData->fInRecRef );
DeleteRecordRecRef( inData->fInRecRef );
return( eDSNoErr );
}
void BSDPlugin::AddRecordRecRef( tRecordReference recRef, CFDictionaryRef resultRef )
{
if ( resultRef )
{
char recAsString[32] = {0};
sprintf( recAsString, "%ld", recRef );
CFStringRef recAsStringRef = CFStringCreateWithCString( NULL, recAsString, kCFStringEncodingUTF8 );
if ( recAsStringRef )
{
CFDictionarySetValue( mOpenRecordsRef, recAsStringRef, resultRef );
CFRelease( recAsStringRef );
}
}
}
void BSDPlugin::DeleteRecordRecRef( tRecordReference recRef )
{
char recAsString[32] = {0};
sprintf( recAsString, "%ld", recRef );
CFStringRef recAsStringRef = CFStringCreateWithCString( NULL, recAsString, kCFStringEncodingUTF8 );
if ( recAsStringRef )
{
CFDictionaryRemoveValue( mOpenRecordsRef, recAsStringRef );
CFRelease( recAsStringRef );
}
}
CFDictionaryRef BSDPlugin::GetRecordFromRecRef( tRecordReference recRef )
{
CFDictionaryRef resultRef = NULL;
char recAsString[32] = {0};
sprintf( recAsString, "%ld", recRef );
CFStringRef recAsStringRef = CFStringCreateWithCString( NULL, recAsString, kCFStringEncodingUTF8 );
if ( recAsStringRef )
{
resultRef = (CFDictionaryRef)CFDictionaryGetValue( mOpenRecordsRef, recAsStringRef );
CFRelease( recAsStringRef );
}
return resultRef;
}
#pragma mark
sInt32 BSDPlugin::HandleNetworkTransition( sHeader *inData )
{
sInt32 siResult = eDSNoErr;
DBGLOG( "BSDPlugin::HandleNetworkTransition called, setting mNISOK to true\n" );
mNISOK = true; mLastTimeOfNetworkTransition = CFAbsoluteTimeGetCurrent(); mLastTimeCheckedServerAvailabilityViaRPC = 0;
mRecordTypeUsersByUIDMapNotAvailable = false;
mRecordTypeGroupByUserMapNotAvailable = false;
mRecordTypeGroupsByGIDMapNotAvailable = false;
if ( mLocalNodeString )
{
CFStringRef localNodeStringRef = CFStringCreateWithCString( NULL, mLocalNodeString, kCFStringEncodingUTF8 );
RemoveNode( localNodeStringRef );
CFRelease( localNodeStringRef );
free( mLocalNodeString );
}
mLocalNodeString = NULL;
siResult = GetNISConfiguration();
if ( siResult == eDSNoErr && mLocalNodeString )
{
DBGLOG( "BSDPlugin::HandleNetworkTransition calling AddNode on %s\n", mLocalNodeString );
AddNode( mLocalNodeString ); }
else
DBGLOG( "BSDPlugin::HandleNetworkTransition not calling AddNode (siResult:%ld) because %s\n", siResult, (mLocalNodeString)?"we have no damain name":"of an error" );
#ifdef USE_CACHE
ResetMapCache();
#endif
return ( siResult );
}
#ifdef BUILDING_COMBO_PLUGIN
void BSDPlugin::ResetFFCache( void )
{
LockFFCache();
DBGLOG( "BSDPlugin::ResetMapCache called\n" );
if ( mCachedFFRef )
{
CFRelease( mCachedFFRef );
}
mCachedFFRef = CFDictionaryCreateMutable( NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks );
mLastTimeFFCacheReset = CFAbsoluteTimeGetCurrent();
UnlockFFCache();
}
#endif
#ifdef USE_CACHE
void BSDPlugin::ResetMapCache( void )
{
LockMapCache();
DBGLOG( "BSDPlugin::ResetMapCache called\n" );
if ( mCachedMapsRef )
{
CFRelease( mCachedMapsRef );
}
mCachedMapsRef = CFDictionaryCreateMutable( NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks );
mLastTimeCacheReset = CFAbsoluteTimeGetCurrent();
UnlockMapCache();
}
#endif
Boolean BSDPlugin::ResultMatchesRequestRecordNameCriteria( CFDictionaryRef result,
tDirPatternMatch patternMatch,
tDataListPtr inRecordNameList )
{
if ( patternMatch == eDSAnyMatch )
return true;
Boolean resultIsOK = false;
CAttributeList* cpRecNameList = new CAttributeList( inRecordNameList );
CFPropertyListRef valueResult = NULL;
if ( cpRecNameList )
{
sInt32 error = eDSNoErr;
uInt32 numRecNames = cpRecNameList->GetCount();
char *pRecName = nil;
for ( uInt16 i=1; !resultIsOK && i<=numRecNames; i++ )
{
if ( (error = cpRecNameList->GetAttribute( i, &pRecName )) == eDSNoErr )
{
CFStringRef recNameMatchRef = NULL;
if ( pRecName )
DBGLOG( "BSDPlugin::ResultMatchesRequestRecordNameCriteria, request name is: %s\n", pRecName );
else
DBGLOG( "BSDPlugin::ResultMatchesRequestRecordNameCriteria, request name is NULL\n" );
if ( pRecName && strcmp( pRecName, kDSRecordsAll ) == 0 )
{
resultIsOK = true;
break;
}
else if ( pRecName && strcmp( pRecName, kDSRecordsStandardAll ) == 0 )
{
valueResult = (CFPropertyListRef)CFDictionaryGetValue( result, CFSTR(kDSNAttrRecordType) );
if ( valueResult && CFGetTypeID( valueResult ) == CFStringGetTypeID() )
{
resultIsOK = CFStringHasPrefix( (CFStringRef)valueResult, CFSTR(kDSStdRecordTypePrefix) );
}
else if ( valueResult && CFGetTypeID( valueResult ) == CFArrayGetTypeID() )
{
CFIndex arrayCount = CFArrayGetCount( (CFArrayRef)valueResult );
for ( CFIndex i=0; i<arrayCount && !resultIsOK; i++ )
{
CFStringRef resultRecordAttributeRef = (CFStringRef)CFArrayGetValueAtIndex( (CFArrayRef)valueResult, i );
resultIsOK = (resultRecordAttributeRef && CFStringHasPrefix( (CFStringRef)resultRecordAttributeRef, CFSTR(kDSStdRecordTypePrefix) ) );
}
}
}
else if ( pRecName && strcmp( pRecName, kDSRecordsNativeAll ) == 0 )
{
valueResult = (CFPropertyListRef)CFDictionaryGetValue( result, CFSTR(kDSNAttrRecordType) );
if ( valueResult && CFGetTypeID( valueResult ) == CFStringGetTypeID() )
{
resultIsOK = CFStringHasPrefix( (CFStringRef)valueResult, CFSTR(kDSNativeRecordTypePrefix) );
}
else if ( valueResult && CFGetTypeID( valueResult ) == CFArrayGetTypeID() )
{
CFIndex arrayCount = CFArrayGetCount( (CFArrayRef)valueResult );
for ( CFIndex i=0; i<arrayCount && !resultIsOK; i++ )
{
CFStringRef resultRecordAttributeRef = (CFStringRef)CFArrayGetValueAtIndex( (CFArrayRef)valueResult, i );
resultIsOK = (resultRecordAttributeRef && CFStringHasPrefix( (CFStringRef)resultRecordAttributeRef, CFSTR(kDSNativeRecordTypePrefix) ) );
}
}
}
else
{
CFPropertyListRef valueRealNameResult = NULL;
valueResult = (CFPropertyListRef)CFDictionaryGetValue( result, CFSTR(kDSNAttrRecordName) );
valueRealNameResult = (CFPropertyListRef)CFDictionaryGetValue( result, CFSTR(kDS1AttrDistinguishedName) );
if ( !valueResult )
continue;
recNameMatchRef = CFStringCreateWithCString( NULL, pRecName, kCFStringEncodingUTF8 );
if ( recNameMatchRef )
{
if ( CFGetTypeID( valueResult ) == CFStringGetTypeID() )
{
resultIsOK = IsResultOK( patternMatch, (CFStringRef)valueResult, recNameMatchRef );
}
else if ( CFGetTypeID( valueResult ) == CFArrayGetTypeID() )
{
CFIndex arrayCount = CFArrayGetCount( (CFArrayRef)valueResult );
for ( CFIndex i=0; i<arrayCount && !resultIsOK; i++ )
{
CFStringRef resultRecordNameRef = (CFStringRef)CFArrayGetValueAtIndex( (CFArrayRef)valueResult, i );
if ( resultRecordNameRef && CFGetTypeID( resultRecordNameRef ) == CFStringGetTypeID() )
resultIsOK = IsResultOK( patternMatch, resultRecordNameRef, recNameMatchRef );
}
}
if ( !resultIsOK && valueRealNameResult )
{
if ( CFGetTypeID( valueRealNameResult ) == CFStringGetTypeID() )
{
resultIsOK = IsResultOK( patternMatch, (CFStringRef)valueRealNameResult, recNameMatchRef );
}
else if ( CFGetTypeID( valueRealNameResult ) == CFArrayGetTypeID() )
{
CFIndex arrayCount = CFArrayGetCount( (CFArrayRef)valueRealNameResult );
for ( CFIndex i=0; i<arrayCount && !resultIsOK; i++ )
{
CFStringRef resultRecordNameRef = (CFStringRef)CFArrayGetValueAtIndex( (CFArrayRef)valueRealNameResult, i );
if ( resultRecordNameRef && CFGetTypeID( resultRecordNameRef ) == CFStringGetTypeID() )
resultIsOK = IsResultOK( patternMatch, resultRecordNameRef, recNameMatchRef );
}
}
}
CFRelease( recNameMatchRef );
}
}
}
}
delete cpRecNameList;
}
return resultIsOK;
}
sInt32 BSDPlugin::RetrieveResults( tDirNodeReference inNodeRef,
tDataBufferPtr inDataBuff,
tDirPatternMatch inRecordNamePatternMatch,
tDataListPtr inRecordNameList,
tDataListPtr inRecordTypeList,
bool inAttributeInfoOnly,
tDataListPtr inAttributeInfoTypeList,
unsigned long* outRecEntryCount,
sNISContinueData* continueData )
{
sInt32 siResult = eDSNoErr;
CDataBuff* aRecData = nil;
CDataBuff* aAttrData = nil;
CDataBuff* aTempData = nil;
CBuff* outBuff = nil;
if ( !outRecEntryCount || !continueData || !inDataBuff )
return eDSNullParameter;
*outRecEntryCount = 0;
DBGLOG( "BSDPlugin::RetrieveResults called for 0x%x in node %lx\n", (int)continueData, inNodeRef );
if ( inRecordNamePatternMatch != eDSExact
&& inRecordNamePatternMatch != eDSiExact
&& inRecordNamePatternMatch != eDSAnyMatch
&& inRecordNamePatternMatch != eDSStartsWith
&& inRecordNamePatternMatch != eDSiStartsWith
&& inRecordNamePatternMatch != eDSEndsWith
&& inRecordNamePatternMatch != eDSiEndsWith
&& inRecordNamePatternMatch != eDSContains
&& inRecordNamePatternMatch != eDSiContains )
{
DBGLOG( "BSDPlugin::RetrieveResults called with a pattern match we haven't implemented yet: 0x%.4x\n", inRecordNamePatternMatch );
return eNotYetImplemented;
}
pthread_mutex_lock( &continueData->fLock );
if ( (CFIndex)*outRecEntryCount >= CFArrayGetCount(continueData->fResultArrayRef) )
{
DBGLOG( "BSDPlugin::RetrieveResults we're finished, setting fSearchComplete and fOutRecEntryCount to zero\n" );
continueData->fSearchComplete = true;
pthread_mutex_unlock( &continueData->fLock );
return eDSNoErr;
}
try
{
aRecData = new CDataBuff();
if( !aRecData ) throw( eMemoryError );
aAttrData = new CDataBuff();
if( !aAttrData ) throw( eMemoryError );
aTempData = new CDataBuff();
if( !aTempData ) throw( eMemoryError );
outBuff = new CBuff();
if( !outBuff ) throw( eMemoryError );
siResult = outBuff->Initialize( inDataBuff, true );
if( siResult ) throw ( siResult );
siResult = outBuff->GetBuffStatus();
if( siResult ) throw ( siResult );
siResult = outBuff->SetBuffType( kClientSideParsingBuff );
if( siResult ) throw ( siResult );
while ( continueData->fResultArrayRef && CFArrayGetCount(continueData->fResultArrayRef) > 0 && !siResult && (continueData->fTotalRecCount < continueData->fLimitRecSearch || continueData->fLimitRecSearch == 0) )
{
Boolean okToAddResult = false;
DBGLOG( "BSDPlugin::RetrieveResults clearing aAttrData and aRecData\n" );
aAttrData->Clear();
aRecData->Clear();
CFDictionaryRef curResult = (CFDictionaryRef)CFArrayGetValueAtIndex( continueData->fResultArrayRef, CFArrayGetCount(continueData->fResultArrayRef)-1 );
if ( !curResult )
throw( ePlugInDataError );
CFRetain( curResult );
CFArrayRemoveValueAtIndex( continueData->fResultArrayRef, CFArrayGetCount(continueData->fResultArrayRef)-1 );
if ( !ResultMatchesRequestRecordNameCriteria( curResult, inRecordNamePatternMatch, inRecordNameList ) )
{
DBGLOG( "BSDPlugin::RetrieveResults curResult: 0x%x for index: %ld doesn't satisfy Request Criteria, skipping\n", (int)curResult, CFArrayGetCount(continueData->fResultArrayRef)-1 );
CFRelease( curResult );
curResult = NULL;
continue;
}
DBGLOG( "BSDPlugin::RetrieveResults curResult: 0x%x for index: %ld and pattern match: 0x%x\n", (int)curResult, CFArrayGetCount(continueData->fResultArrayRef)+1, (int)inRecordNamePatternMatch );
char tempBuf[1024];
char* recordName = NULL;
CFIndex recordNameLength = 0;
CFStringRef recordNameRef = NULL;
char* recType = NULL;
CFIndex recTypeLength = 0;
CFStringRef recordTypeRef = (CFStringRef)CFDictionaryGetValue( curResult, CFSTR(kDSNAttrRecordType) );
if ( recordTypeRef && CFGetTypeID( recordTypeRef ) == CFArrayGetTypeID() )
{
DBGLOG( "BSDPlugin::RetrieveResults curResult has more than one record type, grabbing the first one\n" );
recordTypeRef = (CFStringRef)CFArrayGetValueAtIndex( (CFArrayRef)recordTypeRef, 0 );
}
if ( recordTypeRef && CFGetTypeID( recordTypeRef ) == CFStringGetTypeID() )
{
recTypeLength = ::CFStringGetMaximumSizeForEncoding( CFStringGetLength(recordTypeRef), kCFStringEncodingUTF8) +1;
if ( recTypeLength > (CFIndex)sizeof(tempBuf) )
recType = (char*)malloc( recTypeLength );
else
recType = tempBuf;
if ( !::CFStringGetCString( recordTypeRef, recType, recTypeLength, kCFStringEncodingUTF8 ) )
{
DBGLOG( "BSDPlugin::RetrieveResults couldn't convert recordTypeRef CFString to char* in UTF8!\n" );
if ( recType != tempBuf )
free( recType );
recType = NULL;
}
}
else if ( recordTypeRef )
{
DBGLOG( "BSDPlugin::RetrieveResults unknown recordTypeRefID: %ld\n", CFGetTypeID( recordTypeRef ) );
}
if ( recType != nil )
{
DBGLOG( "BSDPlugin::RetrieveResults recType=%s\n", recType );
aRecData->AppendShort( ::strlen( recType ) );
aRecData->AppendString( recType );
if ( recType != tempBuf )
free(recType);
recType = NULL;
} else
{
aRecData->AppendShort( ::strlen( "Record Type Unknown" ) );
aRecData->AppendString( "Record Type Unknown" );
}
recordNameRef = (CFStringRef)CFDictionaryGetValue( curResult, CFSTR(kDSNAttrRecordName) );
if ( !recordNameRef )
{
DBGLOG( "BSDPlugin::RetrieveResults record has no name, skipping\n" );
CFRelease( curResult );
curResult = NULL;
continue; }
if ( CFGetTypeID( recordNameRef ) == CFArrayGetTypeID() )
{
recordNameRef = (CFStringRef)CFArrayGetValueAtIndex( (CFArrayRef)recordNameRef, 0 );
}
recordNameLength = ::CFStringGetMaximumSizeForEncoding( CFStringGetLength(recordNameRef), kCFStringEncodingUTF8) +1;
if ( recordNameLength > (CFIndex)sizeof(tempBuf) )
recordName = (char*)malloc( recordNameLength );
else
recordName = tempBuf;
if ( !::CFStringGetCString( recordNameRef, recordName, recordNameLength, kCFStringEncodingUTF8 ) )
{
DBGLOG( "BSDPlugin::RetrieveResults couldn't convert recordNameRef CFString to char* in UTF8!\n" );
recordName[0] = '\0';
}
if ( recordNameRef != nil && recordName[0] != '\0' )
{
DBGLOG( "BSDPlugin::RetrieveResults looking at record: %s\n", recordName );
aRecData->AppendShort( ::strlen( recordName ) );
aRecData->AppendString( recordName );
}
else
{
aRecData->AppendShort( ::strlen( "Record Name Unknown" ) );
aRecData->AppendString( "Record Name Unknown" );
}
if ( recordName != tempBuf )
free( recordName );
recordName = NULL;
AttrDataContext context = {0,aAttrData,inAttributeInfoOnly, NULL};
uInt32 numAttrTypes = 0;
CAttributeList cpAttributeList( inAttributeInfoTypeList );
numAttrTypes = cpAttributeList.GetCount();
DBGLOG( "BSDPlugin::RetrieveResults client looking for %ld attribute(s)\n", numAttrTypes );
if( (numAttrTypes == 0) ) throw( eDSEmptyRecordTypeList );
sInt32 error = eDSNoErr;
char* pAttrType = nil;
for ( uInt32 i=1; i<=numAttrTypes; i++ )
{
if ( (error = cpAttributeList.GetAttribute( i, &pAttrType )) == eDSNoErr )
{
DBGLOG( "BSDPlugin::RetrieveResults looking for attribute type: %s\n", pAttrType );
if ( strcmp( pAttrType, kDSAttributesAll ) == 0 || strcmp( pAttrType, kDSAttributesStandardAll ) == 0 || strcmp( pAttrType, kDSAttributesNativeAll ) == 0 )
{
context.attrType = pAttrType;
::CFDictionaryApplyFunction( curResult, AddDictionaryDataToAttrData, &context );
okToAddResult = true;
break;
}
else
{
CFStringRef keyRef = ::CFStringCreateWithCString( NULL, pAttrType, kCFStringEncodingUTF8 );
CFStringRef valueRef = NULL;
CFTypeRef valueTypeRef = NULL;
CFArrayRef valueArrayRef = NULL;
aTempData->Clear();
if ( ::CFDictionaryContainsKey( curResult, keyRef ) )
valueTypeRef = (CFTypeRef)::CFDictionaryGetValue( curResult, keyRef );
CFRelease( keyRef );
if ( valueTypeRef )
{
if ( CFGetTypeID(valueTypeRef) == CFArrayGetTypeID() )
{
valueArrayRef = (CFArrayRef)valueTypeRef;
CFRetain( valueArrayRef ); }
else
if ( CFGetTypeID(valueTypeRef) == CFStringGetTypeID() )
{
valueRef = (CFStringRef)valueTypeRef;
valueArrayRef = CFArrayCreateMutable( NULL, 1, &kCFTypeArrayCallBacks );
if ( CFStringGetLength( valueRef ) > 0 )
CFArrayAppendValue( (CFMutableArrayRef)valueArrayRef, valueRef );
}
else
DBGLOG( "BSDPlugin::RetrieveResults got unknown value type (%ld), ignore\n", CFGetTypeID(valueTypeRef) );
aTempData->AppendShort( ::strlen( pAttrType ) ); aTempData->AppendString( pAttrType );
if ( valueArrayRef && !inAttributeInfoOnly )
{
char valueTmpBuf[1024];
char* value = NULL;
CFIndex arrayCount = CFArrayGetCount(valueArrayRef);
aTempData->AppendShort( (short)CFArrayGetCount(valueArrayRef) );
for ( CFIndex i=0; i<arrayCount; i++ )
{
valueRef = (CFStringRef)::CFArrayGetValueAtIndex( valueArrayRef, i );
if ( valueRef && ::CFStringGetLength(valueRef) > 0 )
{
CFIndex maxValueEncodedSize = ::CFStringGetMaximumSizeForEncoding(CFStringGetLength(valueRef), kCFStringEncodingUTF8) + 1;
if ( maxValueEncodedSize > (CFIndex)sizeof(valueTmpBuf) )
value = (char*)malloc( maxValueEncodedSize );
else
value = valueTmpBuf;
if ( ::CFStringGetCString( valueRef, value, maxValueEncodedSize, kCFStringEncodingUTF8 ) )
{
aTempData->AppendShort( ::strlen( value ) );
aTempData->AppendString( value );
DBGLOG( "BSDPlugin::RetrieveResults added value: %s\n", value );
}
else
{
DBGLOG( "BSDPlugin::RetrieveResults couldn't make cstr from CFString for value!\n" );
aTempData->AppendShort( 0 );
}
if ( value != valueTmpBuf )
free( value );
value = NULL;
}
else
{
DBGLOG( "BSDPlugin::RetrieveResults no valueRef or its length is 0!\n" );
aTempData->AppendShort( 0 );
}
}
}
else if ( inAttributeInfoOnly )
{
aTempData->AppendShort( 0 ); DBGLOG( "BSDPlugin::RetrieveResults skipping values as the caller only wants attributes\n" );
}
else
{
DBGLOG( "BSDPlugin::RetrieveResults no values for this attribute, skipping!\n" );
if ( valueArrayRef )
{
CFRelease( valueArrayRef ); valueArrayRef = NULL;
}
continue;
}
if ( valueArrayRef )
{
CFRelease( valueArrayRef ); valueArrayRef = NULL;
}
context.count++;
DBGLOG( "BSDPlugin::RetrieveResults adding aTempData to aAttrData, context.count: %d\n", (short)context.count );
aAttrData->AppendShort(aTempData->GetLength());
aAttrData->AppendBlock(aTempData->GetData(), aTempData->GetLength() );
}
}
}
else
{
DBGLOG( "BSDPlugin::RetrieveResults GetAttribute returned error:%li\n", error );
}
}
DBGLOG( "BSDPlugin::RetrieveResults adding aAttrData count %d to aRecData\n", (short)context.count );
aRecData->AppendShort( (short)context.count );
if ( context.count > 0 )
{
aRecData->AppendBlock( aAttrData->GetData(), aAttrData->GetLength() );
}
DBGLOG( "BSDPlugin::RetrieveResults calling outBuff->AddData()\n" );
siResult = outBuff->AddData( aRecData->GetData(), aRecData->GetLength() );
if ( siResult == CBuff::kBuffFull )
{
DBGLOG( "BSDPlugin::RetrieveResults siResult == CBuff::kBuffFull, don't bump the count for next time\n" );
CFArrayAppendValue( continueData->fResultArrayRef, curResult );
UInt32 numDataBlocks = 0;
if ( outBuff->GetDataBlockCount( &numDataBlocks ) != eDSNoErr || numDataBlocks == 0 )
{
siResult = eDSBufferTooSmall; DBGLOG( "BSDPlugin::RetrieveResults siResult == eDSBufferTooSmall, we're done\n" );
}
}
else if ( siResult == eDSNoErr )
{
continueData->fTotalRecCount++;
(*outRecEntryCount)++;
}
else
DBGLOG( "BSDPlugin::RetrieveResults siResult == %ld\n", siResult );
CFRelease( curResult );
curResult = NULL;
}
if ( siResult == CBuff::kBuffFull )
siResult = eDSNoErr;
outBuff->SetLengthToSize();
}
catch ( int err )
{
DBGLOG( "BSDPlugin::RetrieveResults caught err: %d\n", err );
siResult = err;
}
if ( aRecData != nil )
{
delete (aRecData);
aRecData = nil;
}
if ( aTempData != nil )
{
delete (aTempData);
aTempData = nil;
}
if ( aAttrData != nil )
{
delete (aAttrData);
aAttrData = nil;
}
if ( outBuff != nil )
{
delete( outBuff );
outBuff = nil;
}
if ( !continueData->fResultArrayRef || CFArrayGetCount( continueData->fResultArrayRef ) == 0 || (continueData->fTotalRecCount >= continueData->fLimitRecSearch && continueData->fLimitRecSearch > 0) )
{
continueData->fSearchComplete = true;
DBGLOG( "BSDPlugin::RetrieveResults setting fSearchComplete to true\n" );
}
pthread_mutex_unlock( &continueData->fLock );
DBGLOG( "BSDPlugin::RetrieveResults returning siResult: %ld\n", siResult );
return( siResult );
}
#ifdef BUILDING_COMBO_PLUGIN
const char* BSDPlugin::GetFFTypeFromRecType ( char *inRecType )
{
if ( !inRecType )
return NULL;
if ( strcmp( inRecType, kDSStdRecordTypeUsers ) == 0 )
return kFFRecordTypeUsers;
else if ( strcmp( inRecType, kDSStdRecordTypeGroups ) == 0 )
return kFFRecordTypeGroups;
else if ( strcmp( inRecType, kDSStdRecordTypeBootp ) == 0 )
return kFFRecordTypeBootp;
else if ( strcmp( inRecType, kDSStdRecordTypeEthernets ) == 0 )
return kFFRecordTypeEthernets;
else if ( strcmp( inRecType, kDSStdRecordTypeHosts ) == 0 )
return kFFRecordTypeHosts;
else if ( strcmp( inRecType, kDSStdRecordTypeMounts ) == 0 )
return kFFRecordTypeMounts;
else if ( strcmp( inRecType, kDSStdRecordTypeNetGroups ) == 0 )
return kFFRecordTypeNetGroups;
else if ( strcmp( inRecType, kDSStdRecordTypeNetworks ) == 0 )
return kFFRecordTypeNetworks;
else if ( strcmp( inRecType, kDSStdRecordTypePrintService ) == 0 )
return kFFRecordTypePrintService;
else if ( strcmp( inRecType, kDSStdRecordTypeProtocols ) == 0 )
return kFFRecordTypeProtocols;
else if ( strcmp( inRecType, kDSStdRecordTypeRPC ) == 0 )
return kFFRecordTypeRPC;
else if ( strcmp( inRecType, kDSStdRecordTypeServices ) == 0 )
return kFFRecordTypeServices;
else if ( strcmp( inRecType, kDSNAttrBootParams ) == 0 )
return kFFRecordTypeBootParams;
else
return NULL;
}
#endif
const char* BSDPlugin::GetNISTypeFromRecType ( char *inRecType )
{
if ( !inRecType )
return NULL;
if ( strcmp( inRecType, kDSStdRecordTypeUsers ) == 0 )
return kNISRecordTypeUsers;
else if ( strcmp( inRecType, kDSStdRecordTypeGroups ) == 0 )
return kNISRecordTypeGroups;
else if ( strcmp( inRecType, kDSStdRecordTypeBootp ) == 0 )
return kNISRecordTypeBootp;
else if ( strcmp( inRecType, kDSStdRecordTypeEthernets ) == 0 )
return kNISRecordTypeEthernets;
else if ( strcmp( inRecType, kDSStdRecordTypeHosts ) == 0 )
return kNISRecordTypeHosts;
else if ( strcmp( inRecType, kDSStdRecordTypeMounts ) == 0 )
return kNISRecordTypeMounts;
else if ( strcmp( inRecType, kDSStdRecordTypeNetGroups ) == 0 )
return kNISRecordTypeNetGroups;
else if ( strcmp( inRecType, kDSStdRecordTypeNetworks ) == 0 )
return kNISRecordTypeNetworks;
else if ( strcmp( inRecType, kDSStdRecordTypePrintService ) == 0 )
return kNISRecordTypePrintService;
else if ( strcmp( inRecType, kDSStdRecordTypeProtocols ) == 0 )
return kNISRecordTypeProtocols;
else if ( strcmp( inRecType, kDSStdRecordTypeRPC ) == 0 )
return kNISRecordTypeRPC;
else if ( strcmp( inRecType, kDSStdRecordTypeServices ) == 0 )
return kNISRecordTypeServices;
else if ( strcmp( inRecType, kDSNAttrBootParams ) == 0 )
return kNISRecordTypeBootParams;
else
return NULL;
}
#pragma mark -
void BSDPlugin::StartNodeLookup( void )
{
DBGLOG( "BSDPlugin::StartNodeLookup called\n" );
if ( mLocalNodeString )
AddNode( mLocalNodeString ); }
CFMutableDictionaryRef BSDPlugin::CopyRecordLookup( Boolean isFFRecord, const char* recordTypeName, const char* mapName, char* recordName )
{
CFMutableDictionaryRef resultRecordRef = NULL;
DBGLOG( "BSDPlugin::CopyRecordLookup called, recordTypeName: %s, mapName: %s, recordName: %s\n", recordTypeName, mapName, recordName );
CFMutableArrayRef tempArrayRef = CFArrayCreateMutable( NULL, 0, &kCFTypeArrayCallBacks );
if ( tempArrayRef )
{
DoRecordsLookup( tempArrayRef, isFFRecord, recordTypeName, mapName, recordName );
if ( CFArrayGetCount(tempArrayRef) > 0 )
{
resultRecordRef = (CFMutableDictionaryRef)CFArrayGetValueAtIndex( tempArrayRef, 0 );
CFRetain( resultRecordRef );
}
CFRelease( tempArrayRef );
}
return resultRecordRef;
}
#ifdef BUILDING_COMBO_PLUGIN
void BSDPlugin::SetLastModTimeOfFileRead( const char* recordTypeName, time_t modTimeOfFile )
{
if ( !recordTypeName )
{
DBGLOG( "BSDPlugin::SetLastModTimeOfFileRead was passed a recordTypeName of NULL!" );
return;
}
int index = -1;
if ( strcmp( recordTypeName, kFFRecordTypeUsers ) == 0 )
index = 0;
else if ( strcmp( recordTypeName, kFFRecordTypeGroups ) == 0 )
index = 1;
else if ( strcmp( recordTypeName, kFFRecordTypeAlias ) == 0 )
index = 2;
else if ( strcmp( recordTypeName, kFFRecordTypeBootp ) == 0 )
index = 3;
else if ( strcmp( recordTypeName, kFFRecordTypeEthernets ) == 0 )
index = 4;
else if ( strcmp( recordTypeName, kFFRecordTypeHosts ) == 0 )
index = 5;
else if ( strcmp( recordTypeName, kFFRecordTypeMounts ) == 0 )
index = 6;
else if ( strcmp( recordTypeName, kFFRecordTypeNetGroups ) == 0 )
index = 7;
else if ( strcmp( recordTypeName, kFFRecordTypeNetworks ) == 0 )
index = 8;
else if ( strcmp( recordTypeName, kFFRecordTypePrintService ) == 0 )
index = 9;
else if ( strcmp( recordTypeName, kFFRecordTypeProtocols ) == 0 )
index = 10;
else if ( strcmp( recordTypeName, kFFRecordTypeRPC ) == 0 )
index = 11;
else if ( strcmp( recordTypeName, kFFRecordTypeServices ) == 0 )
index = 12;
else if ( strcmp( recordTypeName, kFFRecordTypeBootParams ) == 0 )
index = 13;
if ( index > 0 )
mModTimes[index] = modTimeOfFile;
else
DBGLOG( "BSDPlugin::SetLastModTimeOfFileRead, unknown recordTypeName: %s\n", recordTypeName );
}
time_t BSDPlugin::GetLastModTimeOfFileRead( const char* recordTypeName )
{
if ( !recordTypeName )
return 0;
if ( strcmp( recordTypeName, kFFRecordTypeUsers ) == 0 )
return mModTimes[0];
else if ( strcmp( recordTypeName, kFFRecordTypeGroups ) == 0 )
return mModTimes[1];
else if ( strcmp( recordTypeName, kFFRecordTypeAlias ) == 0 )
return mModTimes[2];
else if ( strcmp( recordTypeName, kFFRecordTypeBootp ) == 0 )
return mModTimes[3];
else if ( strcmp( recordTypeName, kFFRecordTypeEthernets ) == 0 )
return mModTimes[4];
else if ( strcmp( recordTypeName, kFFRecordTypeHosts ) == 0 )
return mModTimes[5];
else if ( strcmp( recordTypeName, kFFRecordTypeMounts ) == 0 )
return mModTimes[6];
else if ( strcmp( recordTypeName, kFFRecordTypeNetGroups ) == 0 )
return mModTimes[7];
else if ( strcmp( recordTypeName, kFFRecordTypeNetworks ) == 0 )
return mModTimes[8];
else if ( strcmp( recordTypeName, kFFRecordTypePrintService ) == 0 )
return mModTimes[9];
else if ( strcmp( recordTypeName, kFFRecordTypeProtocols ) == 0 )
return mModTimes[10];
else if ( strcmp( recordTypeName, kFFRecordTypeRPC ) == 0 )
return mModTimes[11];
else if ( strcmp( recordTypeName, kFFRecordTypeServices ) == 0 )
return mModTimes[12];
else if ( strcmp( recordTypeName, kFFRecordTypeBootParams ) == 0 )
return mModTimes[13];
else
return 0;
}
CFMutableDictionaryRef BSDPlugin::CopyResultOfFFLookup( const char* recordTypeName, CFStringRef recordTypeRef )
{
char filepath[1024] = {0,};
CFMutableDictionaryRef resultDictionaryRef = NULL;
time_t modTimeOfFile = 0;
snprintf( filepath, sizeof(filepath), "%s%s", kFFConfDir, recordTypeName );
struct stat statResult;
if ( stat( filepath, &statResult ) == 0 )
{
DBGLOG( "%s, modtime is: %d, last checked modtime is: %d\n", filepath, statResult.st_mtimespec.tv_sec, GetLastModTimeOfFileRead( recordTypeName ) );
modTimeOfFile = statResult.st_mtimespec.tv_sec;
if ( modTimeOfFile > GetLastModTimeOfFileRead( recordTypeName ) )
{
DBGLOG( "%s has changed, re-read the file\n", filepath );
}
else
{
DBGLOG( "%s hasn't changed, go with cached results if applicable\n", filepath );
if ( mCachedFFRef )
resultDictionaryRef = (CFMutableDictionaryRef)CFDictionaryGetValue( mCachedFFRef, recordTypeRef );
if ( resultDictionaryRef )
CFRetain( resultDictionaryRef );
}
}
else
DBGLOG( "Couldn't stat the file (%s) due to: %s!\n", filepath, strerror(errno) );
if ( resultDictionaryRef == NULL )
{
CFMutableStringRef alternateRecordTypeRef = NULL;
CFMutableDictionaryRef alternateDictionaryRef = CFDictionaryCreateMutable( NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks );
size_t curLen;
FILE* fd;
CFStringRef recordTypeRef = CFStringCreateWithCString( NULL, recordTypeName, kCFStringEncodingASCII );
resultDictionaryRef = CFDictionaryCreateMutable( NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks );
fd = fopen(filepath, "r");
if ( !fd )
{
DBGLOG( "CopyResultOfFFLookup returning NULL as we can't open the file at: (%s)!\n", filepath );
if ( recordTypeRef )
CFRelease( recordTypeRef );
if ( resultDictionaryRef )
CFRelease( resultDictionaryRef );
if ( alternateDictionaryRef )
CFRelease( alternateDictionaryRef );
return NULL;
}
if ( recordTypeRef )
{
alternateRecordTypeRef = CFStringCreateMutableCopy( NULL, 0, recordTypeRef );
CFStringAppend( alternateRecordTypeRef, CFSTR(kAlternateTag) );
char* lnResult = NULL;
char* continuationBuffer = NULL;
char lnBuf[kMaxSizeOfParam] = {0,};
while ( lnResult = fgets( lnBuf, sizeof(lnBuf), fd ) )
{
char* commentPtr = NULL;
if ( lnResult && (lnResult[0] == '#' || lnResult[0] == '\n') )
continue;
curLen = strlen( lnResult );
if ( curLen )
lnResult[curLen-1] = '\0';
commentPtr = strchr( lnResult, '#' );
if ( commentPtr )
{
char* trailingWSPtr = commentPtr;
commentPtr++;
trailingWSPtr--;
while ( isspace( *trailingWSPtr ) )
trailingWSPtr--;
*(++trailingWSPtr) = '\0'; }
if ( continuationBuffer )
{
char* tempBuf = NULL;
size_t lnLen = strlen(lnResult);
size_t conBufLen = strlen(continuationBuffer);
tempBuf = (char*)malloc( lnLen + conBufLen + 1 );
memcpy( tempBuf, continuationBuffer, conBufLen );
memcpy( &tempBuf[conBufLen], lnResult, lnLen );
tempBuf[lnLen + conBufLen] = '\0';
free( continuationBuffer );
continuationBuffer = tempBuf;
lnResult = continuationBuffer;
}
curLen = strlen(lnResult);
if ( curLen > 0 && lnResult[curLen-1] == '\\' ) {
char* oldContBuffer = continuationBuffer;
lnResult[curLen-1] = '\0';
continuationBuffer = (char*)malloc( curLen+1 );
strcpy( continuationBuffer, lnResult );
if ( oldContBuffer )
free(oldContBuffer);
continue; }
if ( lnResult[0] != '\0' )
{
CFMutableDictionaryRef resultRef = CreateFFParseResult( lnResult, recordTypeName );
if ( resultRef )
{
if ( commentPtr && commentPtr[0] != '\0' )
{
CFStringRef commentRef = CFStringCreateWithCString( NULL, commentPtr, kCFStringEncodingUTF8 );
if ( commentRef )
{
CFDictionaryAddValue( resultRef, CFSTR(kDS1AttrComment), commentRef );
CFRelease( commentRef );
}
}
AddResultToDictionaries( CFSTR(kDSNAttrRecordName), resultDictionaryRef, alternateDictionaryRef, resultRef );
CFRelease( resultRef );
}
else
DBGLOG( "BSDPlugin::CopyResultOfFFLookup no result\n" );
}
if ( continuationBuffer )
free( continuationBuffer );
continuationBuffer = NULL;
}
}
if ( recordTypeRef )
{
if ( mCachedFFRef )
{
CFDictionarySetValue( mCachedFFRef, recordTypeRef, resultDictionaryRef );
CFDictionarySetValue( mCachedFFRef, alternateRecordTypeRef, alternateDictionaryRef );
}
CFRelease( recordTypeRef );
if ( alternateRecordTypeRef )
CFRelease( alternateRecordTypeRef );
alternateRecordTypeRef = NULL;
}
if ( alternateDictionaryRef )
CFRelease( alternateDictionaryRef );
alternateDictionaryRef = NULL;
fclose( fd );
DBGLOG( "%s, setting last checked modtime to: %d\n", filepath, modTimeOfFile );
SetLastModTimeOfFileRead( recordTypeName, modTimeOfFile );
if ( modTimeOfFile != GetLastModTimeOfFileRead( recordTypeName ) )
DBGLOG( "setting mod time didn't take!\n" );
}
return resultDictionaryRef;
}
#endif
void BSDPlugin::AddResultToDictionaries( CFStringRef primaryKeyTypeRef, CFMutableDictionaryRef primaryDictRef, CFMutableDictionaryRef alternateDictRef, CFDictionaryRef resultRef )
{
CFStringRef recordPrimaryKey;
CFStringRef recordRealName;
recordPrimaryKey = (CFStringRef)CFDictionaryGetValue(resultRef, primaryKeyTypeRef);
if ( recordPrimaryKey && CFGetTypeID(recordPrimaryKey) == CFArrayGetTypeID() )
{
CFArrayRef recordPrimaryKeyList = (CFArrayRef)recordPrimaryKey;
CFIndex numRecordPrimaryKeys = CFArrayGetCount(recordPrimaryKeyList);
for ( CFIndex i=0; i<numRecordPrimaryKeys; i++ )
{
recordPrimaryKey = (CFStringRef)CFArrayGetValueAtIndex( recordPrimaryKeyList, i );
if ( recordPrimaryKey && CFGetTypeID(recordPrimaryKey) == CFStringGetTypeID() )
{
if ( i==0 )
CFDictionaryAddValue( primaryDictRef, recordPrimaryKey, resultRef ); else
CFDictionaryAddValue( alternateDictRef, recordPrimaryKey, resultRef ); }
}
}
else if ( recordPrimaryKey && CFGetTypeID(recordPrimaryKey) == CFStringGetTypeID())
CFDictionaryAddValue( primaryDictRef, recordPrimaryKey, resultRef );
recordRealName = (CFStringRef)CFDictionaryGetValue(resultRef, CFSTR(kDS1AttrDistinguishedName));
if ( recordRealName && CFGetTypeID(recordRealName) == CFArrayGetTypeID() )
{
CFArrayRef recordRealNameList = (CFArrayRef)recordRealName;
CFIndex numrecordRealNames = CFArrayGetCount(recordRealNameList);
for ( CFIndex i=0; i<numrecordRealNames; i++ )
{
recordRealName = (CFStringRef)CFArrayGetValueAtIndex( recordRealNameList, i );
if ( recordRealName && CFGetTypeID(recordRealName) == CFStringGetTypeID() )
{
CFDictionaryAddValue( alternateDictRef, recordRealName, resultRef ); }
}
}
else if ( recordRealName && CFGetTypeID(recordRealName) == CFStringGetTypeID())
CFDictionaryAddValue( alternateDictRef, recordRealName, resultRef );
}
char* BSDPlugin::CopyResultOfNISLookup( NISLookupType type, const char* recordTypeName, const char* keys )
{
char* resultPtr = NULL;
char* argv[8] = {0};
char* pathArg = NULL;
Boolean canceled = false;
int callTimedOut = 0;
CFAbsoluteTime timeLookupStarted = CFAbsoluteTimeGetCurrent();
DBGLOG( "BSDPlugin::CopyResultOfNISLookup started type: %d, recordTypeName: %s, keys: %s\n", type, (recordTypeName)?recordTypeName:"NULL", (keys)?keys:"NULL" );
switch (type)
{
case kNISypcat:
{
if ( gSkipYPCatOnRecordNames && strcmp( recordTypeName, kNISRecordTypeUsers ) == 0 )
{
DBGLOG( "BSDPlugin::CopyResultOfNISLookup calling kNISypcat, returning NULL since %s exists\n", kSkipYPCatOnRecordNamesFilePath );
return NULL;
}
argv[0] = kNISypcatPath;
argv[1] = "-k";
argv[2] = "-d";
argv[3] = mLocalNodeString;
argv[4] = (char*)recordTypeName;
pathArg = kNISypcatPath;
}
break;
case kNISdomainname:
{
argv[0] = kNISdomainnamePath;
argv[1] = (char*)recordTypeName;
pathArg = kNISdomainnamePath;
}
break;
case kNISrpcinfo:
{
argv[0] = kNISrpcinfoPath;
argv[1] = "-p";
argv[2] = (char*)recordTypeName;
pathArg = kNISrpcinfoPath;
}
break;
case kNISportmap:
{
argv[0] = kNISportmapPath;
pathArg = kNISportmapPath;
}
break;
case kNISbind:
{
argv[0] = kNISbindPath;
pathArg = kNISbindPath;
}
break;
case kNISypwhich:
{
argv[0] = kNISypwhichPath;
pathArg = kNISypwhichPath;
}
break;
case kNISypmatch:
{
argv[0] = kNISypmatchPath;
argv[1] = "-d";
argv[2] = mLocalNodeString;
argv[3] = "-t";
argv[4] = "-k";
argv[5] = (char*)keys;
argv[6] = (char*)recordTypeName;
pathArg = kNISypmatchPath;
}
break;
};
if ( myexecutecommandas( NULL, pathArg, argv, false, (type==kNISypwhich)?2:10, &resultPtr, &canceled, getuid(), getgid(), &callTimedOut ) < 0 )
{
DBGLOG( "BSDPlugin::CopyResultOfNISLookup failed\n" );
}
if ( type == kNISbind && callTimedOut )
{
if ( mLastTimeOfNetworkTransition < timeLookupStarted )
{
syslog( LOG_ALERT, "ypbind failed to locate NIS Server, some services may be unavailable...\n" );
mNISOK = false;
SetNISUnavailable();
}
else
DBGLOG( "BSDPlugin::CopyResultOfNISLookup, ypbind failed to locate NIS Server, ignoring because a NetworkTransition occurred.\n" );
}
DBGLOG( "BSDPlugin::CopyResultOfNISLookup finished type: %d, recordTypeName: %s, keys: %s\n%s%s", type, (recordTypeName)?recordTypeName:"NULL", (keys)?keys:"NULL", (resultPtr)?"resultPtr: \"":"",(resultPtr)?resultPtr:"");
return resultPtr;
}
void BSDPlugin::DoRecordsLookup( CFMutableArrayRef resultArrayRef,
Boolean isFFRecord,
const char* inRecordTypeName,
const char* inMapName,
char* recordName,
tDirPatternMatch inAttributePatternMatch,
tDataNodePtr inAttributePatt2Match,
char* attributeKeyToMatch )
{
CFDictionaryRef cachedResult = NULL;
Boolean doYPCatForResults = true;
const char* mapName = inMapName;
if ( !resultArrayRef )
{
DBGLOG( "BSDPlugin::DoRecordsLookup resultArrayRef passed in is NULL!\n" );
return;
}
if ( isFFRecord )
DBGLOG( "BSDPlugin::DoRecordsLookup param %s lookup\n", (isFFRecord)?"/BSD/local":"NIS" );
if ( mapName )
DBGLOG( "BSDPlugin::DoRecordsLookup param mapName: %s\n", mapName );
if ( recordName )
DBGLOG( "BSDPlugin::DoRecordsLookup param recordName: %s\n", recordName );
if ( inAttributePatt2Match && inAttributePatt2Match->fBufferData )
DBGLOG( "BSDPlugin::DoRecordsLookup param inAttributePatt2Match: %s\n", inAttributePatt2Match->fBufferData );
if ( attributeKeyToMatch )
DBGLOG( "BSDPlugin::DoRecordsLookup param attributeKeyToMatch: %s\n", attributeKeyToMatch );
if ( inAttributePatternMatch != eDSExact
&& inAttributePatternMatch != eDSiExact
&& inAttributePatternMatch != eDSAnyMatch
&& inAttributePatternMatch != eDSStartsWith
&& inAttributePatternMatch != eDSiStartsWith
&& inAttributePatternMatch != eDSEndsWith
&& inAttributePatternMatch != eDSiEndsWith
&& inAttributePatternMatch != eDSContains
&& inAttributePatternMatch != eDSiContains )
{
DBGLOG( "BSDPlugin::DoRecordsLookup called with a pattern match we haven't implemented yet: 0x%.4x\n", inAttributePatternMatch );
throw( eNotYetImplemented );
}
if ( recordName )
{
cachedResult = CopyRecordResult( isFFRecord, inRecordTypeName, mapName, recordName );
if ( cachedResult )
{
if ( RecordIsAMatch( cachedResult, inAttributePatternMatch, inAttributePatt2Match, attributeKeyToMatch ) )
CFArrayAppendValue( resultArrayRef, cachedResult );
else
DBGLOG( "BSDPlugin::DoRecordsLookup RecordIsAMatch returned false\n" );
CFRelease( cachedResult );
}
else
DBGLOG( "BSDPlugin::DoRecordsLookup couldn't find a matching result\n" );
doYPCatForResults = false;
}
else if ( isFFRecord == false && attributeKeyToMatch && (inAttributePatternMatch == eDSiExact || inAttributePatternMatch == eDSExact) &&
( (strcmp(attributeKeyToMatch, kDSNAttrNestedGroups) == 0) || (strcmp(attributeKeyToMatch,kDSNAttrGroupMembers) == 0) ) )
{
DBGLOG("BSDPlugin::DoRecordsLookup skipping a lookup (%s) we know is not supported\n", attributeKeyToMatch );
doYPCatForResults = false;
}
else if ( isFFRecord == false && (inAttributePatternMatch == eDSiExact || inAttributePatternMatch == eDSExact) &&
( ( strcmp(mapName, kNISRecordTypeUsers) == 0 &&
( strcmp(attributeKeyToMatch, kDS1AttrDistinguishedName) == 0 ||
strcmp(attributeKeyToMatch, kDS1AttrUniqueID) == 0
)
) ||
( strcmp(mapName, kNISRecordTypeGroups) == 0 &&
( strcmp(attributeKeyToMatch, kDSNAttrGroupMembership) == 0 ||
strcmp(attributeKeyToMatch, kDSNAttrMember) == 0 ||
strcmp(attributeKeyToMatch, kDS1AttrDistinguishedName) == 0 ||
strcmp(attributeKeyToMatch, kDS1AttrPrimaryGroupID) == 0
)
)
)
)
{
char* resultPtr = NULL;
doYPCatForResults = false;
DBGLOG( "BSDPlugin::DoRecordsLookup we are not FlatFiles and we are looking for User UniqueID or Group PrimaryGroupID we can match instead of ypcat\n" );
if ( strcmp(mapName, kNISRecordTypeUsers) == 0)
{
if ( strcmp(attributeKeyToMatch, kDS1AttrDistinguishedName) == 0 )
{
mapName = kNISRecordTypeUsers;
}
else
if ( strcmp(attributeKeyToMatch, kDS1AttrUniqueID) == 0 )
{
if ( mRecordTypeUsersByUIDMapNotAvailable )
doYPCatForResults = true; else
mapName = kNISRecordTypeUsersByUID;
}
}
else
if ( strcmp(mapName, kNISRecordTypeGroups) == 0)
{
if ( strcmp(attributeKeyToMatch, kDSNAttrGroupMembership) == 0)
{
if ( mRecordTypeGroupByUserMapNotAvailable )
doYPCatForResults = true; else
mapName = kNISRecordTypeGroupByUser;
}
else
if ( strcmp(attributeKeyToMatch, kDSNAttrMember) == 0)
{
if ( mRecordTypeGroupByUserMapNotAvailable )
doYPCatForResults = true; else
mapName = kNISRecordTypeGroupByUser;
}
else
if ( strcmp(attributeKeyToMatch, kDS1AttrPrimaryGroupID) == 0)
{
if ( mRecordTypeGroupsByGIDMapNotAvailable )
doYPCatForResults = true; else
mapName = kNISRecordTypeGroupsByGID;
}
}
if ( mapName )
resultPtr = CopyResultOfNISLookup( kNISypmatch, mapName, inAttributePatt2Match->fBufferData );
else
DBGLOG( "BSDPlugin::DoRecordsLookup had no mapName so no YPMatch lookup was tried" );
if ( resultPtr )
{
if ( strstr( resultPtr, kBindErrorString ) && !mWeLaunchedYPBind )
{
DBGLOG( "BSDPlugin::DoRecordsLookup CopyResultOfNISLookup got an error, implying that ypbind may not be running\n%s", resultPtr );
free( resultPtr );
resultPtr = NULL;
DBGLOG( "BSDPlugin::DoRecordsLookup attempting to launch ypbind\n" );
#ifdef ONLY_TRY_LAUNCHING_YPBIND_ONCE
mWeLaunchedYPBind = true;
#endif
resultPtr = CopyResultOfNISLookup( kNISbind );
if ( resultPtr )
{
free( resultPtr );
resultPtr = NULL;
}
resultPtr = CopyResultOfNISLookup( kNISypmatch, mapName, inAttributePatt2Match->fBufferData );
}
}
if ( resultPtr && strncmp( resultPtr, "No such map", strlen("No such map") ) != 0 && strncmp( resultPtr, "Can't match key", strlen("Can't match key") ) != 0 )
{
char* curPtr = resultPtr;
char* eoln = NULL;
char* key = NULL;
char* value = NULL;
while ( curPtr && curPtr[0] != '\0' )
{
key = curPtr;
eoln = strstr( curPtr, "\n" );
if ( !eoln )
eoln = curPtr + strlen(curPtr);
curPtr = strstr( curPtr, " " );
if ( curPtr && curPtr < eoln )
{
*curPtr = '\0';
curPtr++;
value = curPtr;
curPtr = strstr( curPtr, "\n" ); }
else
curPtr = eoln;
if ( curPtr )
{
curPtr[0] = '\0';
curPtr++;
}
if ( key && value )
{
DBGLOG( "BSDPlugin::DoRecordsLookup key is: %s, value is: %s for mapName: %s\n", key, value, mapName );
CFMutableDictionaryRef resultRef = CreateNISParseResult( value, mapName, key );
if ( resultRef )
{
CFArrayAppendValue( resultArrayRef, resultRef );
CFRelease( resultRef );
}
else
DBGLOG( "BSDPlugin::DoRecordsLookup no result\n" );
}
}
if ( strcmp(mapName, kNISRecordTypeGroupByUser) == 0 && CFArrayGetCount(resultArrayRef) > 0 )
{
CFDictionaryRef nisUserResult = (CFDictionaryRef)CFArrayGetValueAtIndex( resultArrayRef, 0 );
CFRetain(nisUserResult);
CFArrayRemoveAllValues( resultArrayRef );
CFArrayRef groupResultsRef = (CFArrayRef)CFDictionaryGetValue( nisUserResult, CFSTR(kDSNAttrMember) );
CFIndex numResults = CFArrayGetCount(groupResultsRef);
CFIndex curResult = 0;
for ( ; curResult < numResults; curResult++ )
{
char curGroupName[32]; if ( CFStringGetCString( (CFStringRef)CFArrayGetValueAtIndex(groupResultsRef, curResult), curGroupName, sizeof(curGroupName), kCFStringEncodingASCII ) )
DoRecordsLookup( resultArrayRef, isFFRecord, attributeKeyToMatch, kNISRecordTypeGroupsByGID, curGroupName );
}
CFRelease(nisUserResult);
}
}
else
if ( resultPtr && strstr( resultPtr, "No such map" ) )
{
syslog( LOG_ALERT, "BSDPlugin::DoRecordsLookup found a map that is not supported, trying ypcat" );
DBGLOG("BSDPlugin::DoRecordsLookup found a map that is not supported, trying ypcat" );
doYPCatForResults = true;
if (strcmp(mapName, kNISRecordTypeUsers) == 0)
{
mRecordTypeUsersByUIDMapNotAvailable = true;
}
else
if (strcmp(attributeKeyToMatch, kDSNAttrGroupMembership) == 0)
{
mRecordTypeGroupByUserMapNotAvailable = true;
}
else
if (strcmp(attributeKeyToMatch, kDSNAttrMember) == 0)
{
mRecordTypeGroupByUserMapNotAvailable = true;
}
else
if (strcmp(attributeKeyToMatch, kDS1AttrPrimaryGroupID) == 0)
{
mRecordTypeGroupsByGIDMapNotAvailable = true;
}
mapName = inMapName; }
else
{
DBGLOG("BSDPlugin::DoRecordsLookup got an error: %s\n", resultPtr );
}
if ( resultPtr )
free( resultPtr );
resultPtr = NULL;
}
else
if ( gDisableDisplayNameLookups && attributeKeyToMatch && ( (strcmp(attributeKeyToMatch, kDS1AttrDistinguishedName) == 0)
|| (strcmp(mapName, kNISRecordTypeGroups) == 0 && strcmp(attributeKeyToMatch, kDSNAttrNestedGroups) == 0 ) ) )
{
DBGLOG("BSDPlugin::DoRecordsLookup skipping a lookup we know is not supported\n" );
doYPCatForResults = false;
}
if ( doYPCatForResults )
{
cachedResult = CopyMapResults( isFFRecord, mapName );
if ( cachedResult && ( (inAttributePatt2Match && inAttributePatt2Match->fBufferData) || inAttributePatternMatch == eDSAnyMatch ) )
{
CFStringRef patternRef = NULL;
CFStringRef attributeNameToMatchRef = NULL;
if ( inAttributePatt2Match && inAttributePatt2Match->fBufferData )
patternRef = CFStringCreateWithCString( NULL, inAttributePatt2Match->fBufferData, kCFStringEncodingUTF8 );
if ( attributeKeyToMatch )
{
DBGLOG( "BSDPlugin::DoRecordsLookup looking for records with keys (%s) matching (%s)\n", attributeKeyToMatch, ( inAttributePatt2Match && inAttributePatt2Match->fBufferData )?inAttributePatt2Match->fBufferData:"null" );
attributeNameToMatchRef = CFStringCreateWithCString( NULL, attributeKeyToMatch, kCFStringEncodingUTF8 );
}
ResultMatchContext context = { inAttributePatternMatch, patternRef, attributeNameToMatchRef, resultArrayRef };
CFDictionaryApplyFunction( cachedResult, FindAllAttributeMatches, &context );
DBGLOG( "BSDPlugin::DoRecordsLookup FindMatchingResults found %ld matches\n", CFArrayGetCount(resultArrayRef) );
if ( patternRef )
CFRelease( patternRef );
if ( attributeNameToMatchRef )
CFRelease( attributeNameToMatchRef );
}
else
DBGLOG( "BSDPlugin::DoRecordsLookup couldn't find any matching results\n" );
if ( cachedResult )
CFRelease( cachedResult );
}
}
CFDictionaryRef BSDPlugin::CopyMapResults( Boolean isFFRecord, const char* mapName )
{
if ( !mapName )
return NULL;
DBGLOG("BSDPlugin::CopyMapResults on %s for %s\n", (isFFRecord)?"/BSD/local":"NIS", mapName);
CFDictionaryRef results = NULL;
CFMutableDictionaryRef newResult = NULL;
CFMutableDictionaryRef alternateDictionaryRef = NULL;
CFStringRef mapNameRef = CFStringCreateWithCString( NULL, mapName, kCFStringEncodingUTF8 );
CFMutableStringRef alternateRecordTypeRef = NULL;
if ( mapNameRef )
{
alternateRecordTypeRef = CFStringCreateMutableCopy( NULL, 0, mapNameRef );
CFStringAppend( alternateRecordTypeRef, CFSTR(kAlternateTag) );
#ifdef BUILDING_COMBO_PLUGIN
if ( isFFRecord )
{
LockFFCache();
results = CopyResultOfFFLookup( mapName, mapNameRef );
UnlockFFCache();
}
else
#endif
{
#ifdef USE_CACHE
LockMapCache();
results = (CFDictionaryRef)CFDictionaryGetValue( mCachedMapsRef, mapNameRef );
if ( results )
{
CFRetain( results );
DBGLOG( "BSDPlugin::CopyMapResults returning Map cached result\n" );
}
UnlockMapCache();
#endif
}
}
else
DBGLOG("BSDPlugin::CopyMapResults couldn't make a CFStringRef out of mapName: %s\n", mapName );
if ( !results )
{
DBGLOG("BSDPlugin::CopyMapResults no cached entry for map: %s, doing a lookup...\n", mapName );
char* resultPtr = NULL;
newResult = CFDictionaryCreateMutable( NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks );
alternateDictionaryRef = CFDictionaryCreateMutable( NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks );
if ( !isFFRecord )
resultPtr = CopyResultOfNISLookup( kNISypcat, mapName );
if ( resultPtr )
{
if ( strstr( resultPtr, kBindErrorString ) && !mWeLaunchedYPBind )
{
DBGLOG( "BSDPlugin::CopyMapResults got an error, implying that ypbind may not be running\n" );
free( resultPtr );
resultPtr = NULL;
DBGLOG( "BSDPlugin::CopyMapResults attempting to launch ypbind\n" );
#ifdef ONLY_TRY_LAUNCHING_YPBIND_ONCE
mWeLaunchedYPBind = true;
#endif
resultPtr = CopyResultOfNISLookup( kNISbind );
if ( resultPtr )
{
free( resultPtr );
resultPtr = NULL;
}
resultPtr = CopyResultOfNISLookup( kNISypcat, mapName );
}
if ( resultPtr != NULL && (strncmp( resultPtr, "No such map", strlen("No such map") ) == 0 || strncmp( resultPtr, "Can't match key", strlen("Can't match key") ) == 0) )
{
DBGLOG("BSDPlugin::CopyMapResults got an error: %s\n", resultPtr );
free( resultPtr );
resultPtr = NULL;
if ( mapNameRef )
CFRelease( mapNameRef );
if ( alternateRecordTypeRef )
CFRelease( alternateRecordTypeRef );
if ( newResult )
CFRelease( newResult );
if ( alternateDictionaryRef )
CFRelease( alternateDictionaryRef );
return NULL;
}
char* curPtr = resultPtr;
char* eoln = NULL;
char* key = NULL;
char* value = NULL;
while ( curPtr && curPtr[0] != '\0' )
{
key = curPtr;
eoln = strstr( curPtr, "\n" );
if ( !eoln )
eoln = curPtr + strlen(curPtr);
curPtr = strstr( curPtr, " " );
if ( curPtr && curPtr < eoln )
{
*curPtr = '\0';
curPtr++;
value = curPtr;
curPtr = strstr( curPtr, "\n" ); }
else
curPtr = eoln;
if ( curPtr )
{
curPtr[0] = '\0';
curPtr++;
}
if ( key && value )
{
DBGLOG( "BSDPlugin::CopyMapResults key is: %s, value is: %s\n", key, value );
CFMutableDictionaryRef resultRef = CreateNISParseResult( value, mapName, key );
if ( resultRef )
{
AddResultToDictionaries( CFSTR(kDSNAttrRecordName), newResult, alternateDictionaryRef, resultRef );
CFRelease( resultRef );
}
else
DBGLOG( "BSDPlugin::CopyMapResults no result\n" );
}
else
DBGLOG( "BSDPlugin::CopyMapResults key <0x%x> or value <0x%x> is NULL\n", key, value );
}
free( resultPtr );
resultPtr = NULL;
}
results = newResult;
if ( mapNameRef )
{
#ifdef BUILDING_COMBO_PLUGIN
if ( isFFRecord )
{
LockFFCache();
CFDictionarySetValue( mCachedFFRef, mapNameRef, results ); CFDictionarySetValue( mCachedFFRef, alternateRecordTypeRef, alternateDictionaryRef );
UnlockFFCache();
}
else
#endif
{
#ifdef USE_CACHE
LockMapCache();
CFDictionarySetValue( mCachedMapsRef, mapNameRef, results ); CFDictionarySetValue( mCachedMapsRef, alternateRecordTypeRef, alternateDictionaryRef );
UnlockMapCache();
#endif
}
}
else
DBGLOG( "BSDPlugin::CopyMapResults couldn't set the latest cached map in mCachedMapsRef since we couldn't make a mapNameRef!\n" );
if ( alternateDictionaryRef )
CFRelease( alternateDictionaryRef );
alternateDictionaryRef = NULL;
}
if ( mapNameRef )
CFRelease( mapNameRef );
mapNameRef = NULL;
if ( alternateRecordTypeRef )
CFRelease( alternateRecordTypeRef );
alternateRecordTypeRef = NULL;
DBGLOG( "BSDPlugin::CopyMapResults results has %ld members\n", CFDictionaryGetCount(results) );
return results;
}
Boolean BSDPlugin::RecordIsAMatch( CFDictionaryRef recordRef,
tDirPatternMatch inAttributePatternMatch,
tDataNodePtr inAttributePatt2Match,
char* attributeKeyToMatch )
{
Boolean isAMatch = false;
if ( inAttributePatternMatch == eDSAnyMatch )
isAMatch = true;
else if ( inAttributePatt2Match )
{
CFStringRef attrPatternRef = CFStringCreateWithCString( NULL, inAttributePatt2Match->fBufferData, kCFStringEncodingUTF8 );
CFStringRef attrKeyToMatchRef = NULL;
if ( attrPatternRef )
{
if ( attributeKeyToMatch )
attrKeyToMatchRef = CFStringCreateWithCString( NULL, attributeKeyToMatch, kCFStringEncodingUTF8 );
AttrDataMatchContext context = { inAttributePatternMatch, attrPatternRef, attrKeyToMatchRef, false };
CFDictionaryApplyFunction( recordRef, FindAttributeMatch, &context );
if ( context.foundAMatch )
{
isAMatch = true;
}
else
DBGLOG( "BSDPlugin::RecordIsAMatch result didn't have the attribute: %s\n", inAttributePatt2Match->fBufferData );
CFRelease( attrPatternRef );
if ( attrKeyToMatchRef )
CFRelease( attrKeyToMatchRef );
}
else
DBGLOG( "BSDPlugin::RecordIsAMatch couldn't make a UTF8 string out of: %s!\n", inAttributePatt2Match->fBufferData );
}
return isAMatch;
}
CFDictionaryRef BSDPlugin::CopyRecordResult( Boolean isFFRecord, const char* recordType, const char* mapName, char* recordName )
{
if ( !mapName || !recordName )
{
DBGLOG( "BSDPlugin::CopyRecordResult null parameter! mapName: 0x%x, recordName: 0x%x\n", (int)mapName, (int)recordName );
return NULL;
}
CFStringRef recordTypeRef = CFStringCreateWithCString( NULL, recordType, kCFStringEncodingUTF8 );
CFStringRef mapNameRef = CFStringCreateWithCString( NULL, mapName, kCFStringEncodingUTF8 );
CFStringRef recordNameRef = CFStringCreateWithCString( NULL, recordName, kCFStringEncodingUTF8 );
CFDictionaryRef returnRecordRef = NULL;
if ( !recordNameRef || !mapNameRef || !recordTypeRef )
{
DBGLOG( "BSDPlugin::CopyRecordResult couldn't convert to CFStringRef! recordNameRef: 0x%x, mapNameRef: 0x%x, recordTypeRef: 0x%x\n", (int)recordNameRef, (int)mapNameRef, (int)recordTypeRef );
if ( recordTypeRef )
CFRelease( recordTypeRef );
if ( mapNameRef )
CFRelease( mapNameRef );
if ( recordNameRef )
CFRelease( recordNameRef );
return NULL;
}
CFMutableStringRef alternateRecordTypeRef = CFStringCreateMutableCopy( NULL, 0, mapNameRef );
CFStringAppend( alternateRecordTypeRef, CFSTR(kAlternateTag) );
#ifdef BUILDING_COMBO_PLUGIN
if ( isFFRecord )
{
LockFFCache();
CFDictionaryRef cachedFFRef = CopyResultOfFFLookup( mapName, mapNameRef );
if ( cachedFFRef )
{
returnRecordRef = (CFDictionaryRef)CFDictionaryGetValue( cachedFFRef, recordNameRef );
if ( !returnRecordRef )
{
CFRelease( cachedFFRef );
cachedFFRef = (CFDictionaryRef)CFDictionaryGetValue( mCachedFFRef, alternateRecordTypeRef );
if ( cachedFFRef )
{
returnRecordRef = (CFDictionaryRef)CFDictionaryGetValue( cachedFFRef, recordNameRef );
CFRetain( cachedFFRef );
}
}
if ( returnRecordRef )
{
CFRetain( returnRecordRef );
DBGLOG( "BSDPlugin::CopyRecordResult returning cached BSD/local result\n" );
}
CFRelease( cachedFFRef );
}
UnlockFFCache();
}
else
#endif
{
#ifdef USE_CACHE
LockMapCache();
CFDictionaryRef cachedMapRef = (CFDictionaryRef)CFDictionaryGetValue( mCachedMapsRef, mapNameRef );
if ( cachedMapRef )
{
returnRecordRef = (CFDictionaryRef)CFDictionaryGetValue( cachedMapRef, recordNameRef );
if ( !returnRecordRef )
{
cachedMapRef = (CFDictionaryRef)CFDictionaryGetValue( mCachedMapsRef, alternateRecordTypeRef );
if ( cachedMapRef )
returnRecordRef = (CFDictionaryRef)CFDictionaryGetValue( cachedMapRef, recordNameRef );
}
if ( returnRecordRef )
{
CFRetain( returnRecordRef );
DBGLOG( "BSDPlugin::CopyRecordResult returning cached NIS result\n" );
}
}
UnlockMapCache();
#endif
}
if ( !returnRecordRef )
{
char* resultPtr = NULL;
if ( !isFFRecord )
resultPtr = CopyResultOfNISLookup( (recordName)?kNISypmatch:kNISypcat, mapName, recordName );
if ( resultPtr )
{
if ( strstr( resultPtr, kBindErrorString ) && !mWeLaunchedYPBind )
{
DBGLOG( "BSDPlugin::CopyRecordResult got an error, implying that ypbind may not be running\n" );
free( resultPtr );
resultPtr = NULL;
DBGLOG( "BSDPlugin::CopyRecordResult attempting to launch ypbind\n" );
#ifdef ONLY_TRY_LAUNCHING_YPBIND_ONCE
mWeLaunchedYPBind = true;
#endif
resultPtr = CopyResultOfNISLookup( kNISbind );
if ( resultPtr )
{
free( resultPtr );
resultPtr = NULL;
}
resultPtr = CopyResultOfNISLookup( (recordName)?kNISypmatch:kNISypcat, mapName, recordName );
}
if ( !isFFRecord && resultPtr && recordName && strncmp( mapName, kNISRecordTypeUsers, sizeof(kNISRecordTypeUsers) ) == 0 && strstr( resultPtr, "No such key in map" ) != NULL )
{
DBGLOG( "BSDPlugin::CopyRecordResult unable to find user record, try a ypcat call to try long name\n" );
free( resultPtr);
resultPtr = CopyResultOfNISLookup( kNISypcat, mapName );
}
if ( isFFRecord || ( resultPtr && strncmp( resultPtr, "No such map", strlen("No such map") ) != 0 && strncmp( resultPtr, "Can't match key", strlen("Can't match key") ) != 0 ) )
{
char* curPtr = resultPtr;
char* eoln = NULL;
char* value = NULL;
CFMutableDictionaryRef resultDictionaryRef = CFDictionaryCreateMutable( NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks );
CFMutableDictionaryRef alternateDictionaryRef = CFDictionaryCreateMutable( NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks );
CFStringRef resultPrimaryKeyType = CFSTR(kDSNAttrRecordName);
if ( strcmp( mapName, kNISRecordTypeGroupsByGID ) == 0 )
resultPrimaryKeyType = CFSTR(kDS1AttrPrimaryGroupID);
else
if ( strcmp( mapName, kNISRecordTypeUsersByUID ) == 0 )
resultPrimaryKeyType = CFSTR(kDS1AttrUniqueID);
while ( curPtr && curPtr[0] != '\0' )
{
eoln = strstr( curPtr, "\n" );
if ( !eoln )
eoln = curPtr + strlen(curPtr);
curPtr = strstr( curPtr, " " );
if ( curPtr && curPtr < eoln )
{
*curPtr = '\0';
curPtr++;
value = curPtr;
curPtr = strstr( curPtr, "\n" ); }
else
curPtr = eoln;
if ( curPtr )
{
curPtr[0] = '\0';
curPtr++;
}
if ( value )
{
CFMutableDictionaryRef resultRef = CreateNISParseResult( value, mapName );
if ( resultRef )
{
AddResultToDictionaries( resultPrimaryKeyType, resultDictionaryRef, alternateDictionaryRef, resultRef );
CFRelease( resultRef );
}
else
DBGLOG( "BSDPlugin::CopyRecordResult no result\n" );
}
}
#ifdef USE_CACHE
LockMapCache();
CFDictionarySetValue( mCachedMapsRef, recordTypeRef, resultDictionaryRef );
CFDictionarySetValue( mCachedMapsRef, alternateRecordTypeRef, alternateDictionaryRef );
UnlockMapCache();
#endif
returnRecordRef = (CFDictionaryRef)CFDictionaryGetValue( resultDictionaryRef, recordNameRef );
if ( !returnRecordRef )
{
returnRecordRef= (CFDictionaryRef)CFDictionaryGetValue( alternateDictionaryRef, recordNameRef );
}
if ( returnRecordRef )
{
CFRetain( returnRecordRef );
}
if ( resultDictionaryRef )
CFRelease( resultDictionaryRef );
resultDictionaryRef = NULL;
if ( alternateDictionaryRef )
CFRelease( alternateDictionaryRef );
alternateDictionaryRef = NULL;
}
else
{
DBGLOG( "BSDPlugin::CopyRecordResult got an error: %s\n", resultPtr );
}
free( resultPtr );
resultPtr = NULL;
}
else
DBGLOG( "BSDPlugin::CopyRecordResult resultPtr is NULL\n" );
if ( returnRecordRef )
DBGLOG( "BSDPlugin::CopyRecordResult returnRecordRef has %ld members\n", CFDictionaryGetCount(returnRecordRef) );
else
DBGLOG( "BSDPlugin::CopyRecordResult no returnRecordRef\n" );
}
if ( mapNameRef )
CFRelease( mapNameRef );
mapNameRef = NULL;
if ( recordTypeRef )
CFRelease( recordTypeRef );
recordTypeRef = NULL;
if ( alternateRecordTypeRef )
CFRelease( alternateRecordTypeRef );
alternateRecordTypeRef = NULL;
if ( recordNameRef )
CFRelease( recordNameRef );
recordNameRef = NULL;
return returnRecordRef;
}
#ifdef BUILDING_COMBO_PLUGIN
CFMutableDictionaryRef BSDPlugin::CreateFFParseResult(char *data, const char* recordTypeName)
{
if (data == NULL) return NULL;
if (data[0] == '#') return NULL;
CFMutableDictionaryRef returnResult = NULL;
if ( strcmp( recordTypeName, kFFRecordTypeUsers ) == 0 )
returnResult = ff_parse_user_A(data);
else if ( strcmp( recordTypeName, kFFRecordTypeGroups ) == 0 )
returnResult = ff_parse_group(data);
else if ( strcmp( recordTypeName, kFFRecordTypeHosts ) == 0 )
returnResult = ff_parse_host(data);
else if ( strcmp( recordTypeName, kFFRecordTypeNetworks ) == 0 )
returnResult = ff_parse_network(data);
else if ( strcmp( recordTypeName, kFFRecordTypeServices ) == 0 )
returnResult = ff_parse_service(data);
else if ( strcmp( recordTypeName, kFFRecordTypeProtocols ) == 0 )
returnResult = ff_parse_protocol(data);
else if ( strcmp( recordTypeName, kFFRecordTypeRPC ) == 0 )
returnResult = ff_parse_rpc(data);
else if ( strcmp( recordTypeName, kFFRecordTypeMounts ) == 0 )
returnResult = ff_parse_mount(data);
else if ( strcmp( recordTypeName, kFFRecordTypePrintService ) == 0 )
returnResult = ff_parse_printer(data);
else if ( strcmp( recordTypeName, kFFRecordTypeBootParams ) == 0 )
returnResult = ff_parse_bootparam(data);
else if ( strcmp( recordTypeName, kFFRecordTypeBootp ) == 0 )
returnResult = ff_parse_bootp(data);
else if ( strcmp( recordTypeName, kFFRecordTypeAlias ) == 0 )
ff_parse_alias(data);
else if ( strcmp( recordTypeName, kFFRecordTypeEthernets ) == 0 )
returnResult = ff_parse_ethernet(data);
else if ( strcmp( recordTypeName, "netgroup" ) == 0 )
returnResult = ff_parse_netgroup(data);
if ( returnResult && mFFMetaNodeLocationRef )
{
CFDictionarySetValue( returnResult, CFSTR(kDSNAttrMetaNodeLocation), mFFMetaNodeLocationRef );
}
return returnResult;
}
#endif
CFMutableDictionaryRef BSDPlugin::CreateNISParseResult(char *data, const char* recordTypeName, const char* key)
{
if (data == NULL) return NULL;
if (data[0] == '#') return NULL;
CFMutableDictionaryRef returnResult = NULL;
if ( strcmp( recordTypeName, kNISRecordTypeUsers ) == 0 || strcmp( recordTypeName, kNISRecordTypeUsersByUID ) == 0 )
returnResult = ff_parse_user(data);
else if ( strcmp( recordTypeName, kNISRecordTypeGroups ) == 0 || strcmp( recordTypeName, kNISRecordTypeGroupsByGID ) == 0 )
returnResult = ff_parse_group(data);
else if ( strcmp( recordTypeName, kNISRecordTypeGroupByUser ) == 0 )
returnResult = ff_parse_group_by_usr(data, key);
else if ( strcmp( recordTypeName, kNISRecordTypeHosts ) == 0 )
returnResult = ff_parse_host(data);
else if ( strcmp( recordTypeName, kNISRecordTypeNetworks ) == 0 )
returnResult = ff_parse_network(data);
else if ( strcmp( recordTypeName, kNISRecordTypeServices ) == 0 )
returnResult = ff_parse_service(data);
else if ( strcmp( recordTypeName, kNISRecordTypeProtocols ) == 0 )
returnResult = ff_parse_protocol(data);
else if ( strcmp( recordTypeName, kNISRecordTypeRPC ) == 0 )
returnResult = ff_parse_rpc(data);
else if ( strcmp( recordTypeName, kNISRecordTypeMounts ) == 0 )
returnResult = ff_parse_mount(data);
else if ( strcmp( recordTypeName, kNISRecordTypePrintService ) == 0 )
returnResult = ff_parse_printer(data);
else if ( strcmp( recordTypeName, kNISRecordTypeBootParams ) == 0 )
returnResult = ff_parse_bootparam(data);
else if ( strcmp( recordTypeName, kNISRecordTypeBootp ) == 0 )
returnResult = ff_parse_bootp(data);
else if ( strcmp( recordTypeName, kNISRecordTypeAlias ) == 0 )
ff_parse_alias(data);
else if ( strcmp( recordTypeName, kNISRecordTypeEthernets ) == 0 )
returnResult = ff_parse_ethernet(data);
else if ( strcmp( recordTypeName, "netgroup" ) == 0 )
returnResult = ff_parse_netgroup(data);
if ( returnResult && mNISMetaNodeLocationRef )
{
CFDictionarySetValue( returnResult, CFSTR(kDSNAttrMetaNodeLocation), mNISMetaNodeLocationRef );
}
return returnResult;
}
#pragma mark -
sInt32 BSDPlugin::DoAuthentication ( sDoDirNodeAuth *inData )
{
DBGLOG( "BSDPlugin::DoAuthentication fInAuthMethod: %s, fInDirNodeAuthOnlyFlag: %d, fInAuthStepData: %d, fOutAuthStepDataResponse: %d, fIOContinueData: %d\n", (char *)inData->fInAuthMethod->fBufferData, inData->fInDirNodeAuthOnlyFlag, (int)inData->fInAuthStepData, (int)inData->fOutAuthStepDataResponse, (int)inData->fIOContinueData );
BSDDirNodeRep* nodeDirRep = NULL;
sInt32 siResult = eDSAuthFailed;
uInt32 uiAuthMethod = 0;
sNISContinueData *pContinueData = NULL;
char* userName = NULL;
try
{
LockPlugin();
nodeDirRep = (BSDDirNodeRep*)::CFDictionaryGetValue( mOpenRefTable, (const void*)inData->fInNodeRef );
if( !nodeDirRep )
{
DBGLOG( "BSDPlugin::DoAuthentication called but we couldn't find the nodeDirRep!\n" );
UnlockPlugin();
return eDSInvalidNodeRef;
}
nodeDirRep->Retain();
UnlockPlugin();
if ( nodeDirRep == nil ) throw( (sInt32)eDSInvalidNodeRef );
if ( inData->fInAuthStepData == nil ) throw( (sInt32)eDSNullAuthStepData );
if ( inData->fIOContinueData != NULL )
{
pContinueData = (sNISContinueData *)inData->fIOContinueData;
siResult = DoBasicAuth(inData->fInNodeRef, inData->fInAuthMethod, nodeDirRep,
&pContinueData, inData->fInAuthStepData,
inData->fOutAuthStepDataResponse,
inData->fInDirNodeAuthOnlyFlag,
pContinueData->fAuthAuthorityData);
}
else
{
siResult = GetAuthMethod( inData->fInAuthMethod, &uiAuthMethod );
if ( siResult == eDSNoErr )
{
if ( uiAuthMethod != kAuth2WayRandom )
{
siResult = GetUserNameFromAuthBuffer( inData->fInAuthStepData, 1, &userName );
if ( siResult != eDSNoErr ) throw( siResult );
}
else
{
DBGLOG( "BSDPlugin::DoAuthentication we don't support 2 way random!\n" );
siResult = eDSAuthMethodNotSupported;
}
const char* mapName = NULL;
#ifdef BUILDING_COMBO_PLUGIN
if ( nodeDirRep->IsFFNode() )
mapName = GetFFTypeFromRecType( kDSStdRecordTypeUsers );
else
#endif
mapName = GetNISTypeFromRecType( kDSStdRecordTypeUsers );
CFMutableDictionaryRef recordResult = CopyRecordLookup( nodeDirRep->IsFFNode(), kDSStdRecordTypeUsers, mapName, userName );
if ( recordResult )
{
siResult = DoBasicAuth(inData->fInNodeRef,inData->fInAuthMethod, nodeDirRep,
&pContinueData, inData->fInAuthStepData,
inData->fOutAuthStepDataResponse,
inData->fInDirNodeAuthOnlyFlag,NULL);
CFRelease( recordResult );
}
else
{
DBGLOG( "BSDPlugin::DoAuthentication, unknown user!\n" );
siResult = eDSAuthUnknownUser;
}
}
}
}
catch( sInt32 err )
{
siResult = err;
}
if (userName != NULL)
{
free(userName);
userName = NULL;
}
if ( nodeDirRep )
nodeDirRep->Release();
inData->fResult = siResult;
inData->fIOContinueData = pContinueData;
return( siResult );
}
sInt32 BSDPlugin::DoBasicAuth ( tDirNodeReference inNodeRef, tDataNodePtr inAuthMethod,
BSDDirNodeRep* nodeDirRep,
sNISContinueData** inOutContinueData,
tDataBufferPtr inAuthData, tDataBufferPtr outAuthData,
bool inAuthOnly, char* inAuthAuthorityData )
{
sInt32 siResult = eDSNoErr;
uInt32 uiAuthMethod = 0;
DBGLOG( "BSDPlugin::DoBasicAuth\n" );
try
{
if ( nodeDirRep == nil ) throw( (sInt32)eDSInvalidNodeRef );
siResult = GetAuthMethod( inAuthMethod, &uiAuthMethod );
if ( siResult == eDSNoErr )
{
switch( uiAuthMethod )
{
case kAuthNativeMethod:
case kAuthNativeNoClearText:
case kAuthNativeClearTextOK:
if ( outAuthData == nil ) throw( (sInt32)eDSNullAuthStepData );
siResult = DoUnixCryptAuth( nodeDirRep, inAuthData, inAuthOnly );
if ( siResult == eDSNoErr )
{
if ( outAuthData->fBufferSize > ::strlen( kDSStdAuthCrypt ) )
{
::strcpy( outAuthData->fBufferData, kDSStdAuthCrypt );
}
}
break;
case kAuthClearText:
case kAuthCrypt:
siResult = DoUnixCryptAuth( nodeDirRep, inAuthData, inAuthOnly );
break;
default:
siResult = eDSAuthFailed;
}
}
}
catch( sInt32 err )
{
siResult = err;
DBGLOG( "BSDPlugin::DoBasicAuth caught exception: %ld\n", siResult );
}
return( siResult );
}
sInt32 BSDPlugin::DoUnixCryptAuth ( BSDDirNodeRep *nodeDirRep, tDataBuffer *inAuthData, bool inAuthOnly )
{
sInt32 siResult = eDSAuthFailed;
char *pData = nil;
char *nisPwd = 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[ 64 ];
CFMutableDictionaryRef recordResult = NULL;
const char* mapName = NULL;
DBGLOG( "BSDPlugin::DoUnixCryptAuth\n" );
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( "BSDPlugin::DoUnixCryptAuth attempting UNIX Crypt authentication\n" );
#ifdef BUILDING_COMBO_PLUGIN
if ( nodeDirRep->IsFFNode() )
mapName = GetFFTypeFromRecType( kDSStdRecordTypeUsers );
else
#endif
mapName = GetNISTypeFromRecType( kDSStdRecordTypeUsers );
recordResult = CopyRecordLookup( nodeDirRep->IsFFNode(), kDSStdRecordTypeUsers, mapName, name );
if ( !recordResult )
{
DBGLOG( "BSDPlugin::DoUnixCryptAuth, unknown user!\n" );
throw( (sInt32)eDSAuthUnknownUser );
}
CFStringRef nisPwdRef = (CFStringRef)CFDictionaryGetValue( recordResult, CFSTR(kDS1AttrPassword) );
if ( nisPwdRef )
{
CFIndex len = ::CFStringGetMaximumSizeForEncoding(CFStringGetLength(nisPwdRef), kCFStringEncodingUTF8) + 1;
nisPwd = (char*)malloc( len ); CFStringGetCString( nisPwdRef, nisPwd, len, kCFStringEncodingUTF8 );
}
else
{
nisPwd = (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 ( nisPwd[0] != '\0' )
{
siResult = eDSAuthFailed;
::bzero( hashPwd, sizeof(hashPwd) );
if ( strncmp(nisPwd, "$1$", 3) == 0 )
{
::strlcpy( hashPwd, ::crypt_md5(pwd, nisPwd), sizeof(hashPwd) );
}
else
{
salt[ 0 ] = nisPwd[0];
salt[ 1 ] = nisPwd[1];
salt[ 2 ] = '\0';
::strlcpy( hashPwd, ::crypt(pwd, salt), sizeof(hashPwd) );
}
if ( ::strcmp( hashPwd, nisPwd ) == 0 )
{
siResult = eDSNoErr;
}
}
else {
if ( pwd[0] == '\0' )
{
siResult = eDSNoErr;
}
}
}
catch( sInt32 err )
{
DBGLOG( "BSDPlugin::DoUnixCryptAuth Crypt authentication error %ld\n", err );
siResult = err;
}
if ( name != nil )
{
free( name );
name = nil;
}
if ( pwd != nil )
{
free( pwd );
pwd = nil;
}
if ( nisPwd && *nisPwd != '\0' )
free( nisPwd );
if ( recordResult )
{
CFRelease( recordResult );
}
return( siResult );
}
sInt32 BSDPlugin::GetAuthMethod ( tDataNode *inData, uInt32 *outAuthMethod )
{
sInt32 siResult = eDSNoErr;
uInt32 uiNativeLen = 0;
char *p = nil;
if ( inData == nil )
{
*outAuthMethod = kAuthUnknownMethod;
#ifdef DEBUG
return( eDSAuthParameterError );
#else
return( eDSAuthFailed );
#endif
}
p = (char *)inData->fBufferData;
DBGLOG( "BSDPlugin::GetAuthMethod using authentication method %s\n", p );
if ( ::strcmp( p, kDSStdAuthClearText ) == 0 )
{
*outAuthMethod = kAuthClearText;
}
else if ( ::strcmp( p, kDSStdAuthNodeNativeClearTextOK ) == 0 )
{
*outAuthMethod = kAuthNativeClearTextOK;
}
else if ( ::strcmp( p, kDSStdAuthNodeNativeNoClearText ) == 0 )
{
*outAuthMethod = kAuthNativeNoClearText;
}
else if ( ::strcmp( p, kDSStdAuthCrypt ) == 0 )
{
*outAuthMethod = kAuthCrypt;
}
else if ( ::strcmp( p, kDSStdAuthSetPasswd ) == 0 )
{
*outAuthMethod = kAuthSetPasswd;
}
else if ( ::strcmp( p, kDSStdAuthSetPasswdAsRoot ) == 0 )
{
*outAuthMethod = kAuthSetPasswdAsRoot;
}
else if ( ::strcmp( p, kDSStdAuthChangePasswd ) == 0 )
{
*outAuthMethod = kAuthChangePasswd;
}
else
{
uiNativeLen = ::strlen( kDSNativeAuthMethodPrefix );
if ( ::strncmp( p, kDSNativeAuthMethodPrefix, uiNativeLen ) == 0 )
{
*outAuthMethod = kAuthNativeMethod;
}
else
{
*outAuthMethod = kAuthUnknownMethod;
#ifdef DEBUG
siResult = eDSAuthMethodNotSupported;
#else
siResult = eDSAuthFailed;
#endif
}
}
return( siResult );
}
sInt32 BSDPlugin::GetUserNameFromAuthBuffer ( tDataBufferPtr inAuthData, unsigned long inUserNameIndex,
char **outUserName )
{
DBGLOG( "BSDPlugin::GetUserNameFromAuthBuffer\n" );
tDataListPtr dataList = dsAuthBufferGetDataListAllocPriv(inAuthData);
if (dataList != NULL)
{
*outUserName = dsDataListGetNodeStringPriv(dataList, inUserNameIndex);
dsDataListDeallocatePriv(dataList);
free(dataList);
dataList = NULL;
DBGLOG( "BSDPlugin::GetUserNameFromAuthBuffer successfully returning username: %s\n", *outUserName );
return eDSNoErr;
}
return eDSInvalidBuffFormat;
}
sInt32 BSDPlugin::VerifyPatternMatch ( const tDirPatternMatch inPatternMatch )
{
DBGLOG( "BSDPlugin::VerifyPatternMatch\n" );
sInt32 siResult = eDSNoErr;
switch ( inPatternMatch )
{
case eDSExact:
case eDSStartsWith:
case eDSEndsWith:
case eDSContains:
case eDSiExact:
case eDSiStartsWith:
case eDSiEndsWith:
case eDSiContains:
case eDSAnyMatch:
siResult = eDSNoErr;
break;
default:
siResult = eDSInvalidPatternMatchType;
break;
}
return( siResult );
}
#pragma mark
CFStringRef NSLNodeValueCopyDesctriptionCallback ( const void *value )
{
NodeData* nodeData = (NodeData*)value;
return nodeData->fNodeName;
}
Boolean NSLNodeValueEqualCallback ( const void *value1, const void *value2 )
{
NodeData* nodeData1 = (NodeData*)value1;
NodeData* nodeData2 = (NodeData*)value2;
Boolean areEqual = false;
if ( nodeData1 && nodeData2 && nodeData1->fNodeName && nodeData2->fNodeName )
areEqual = ( CFStringCompare( nodeData1->fNodeName, nodeData2->fNodeName, kCFCompareCaseInsensitive ) == kCFCompareEqualTo );
return areEqual;
}
#pragma mark -
sNISContextData* MakeContextData ( void )
{
sNISContextData *pOut = nil;
sInt32 siResult = eDSNoErr;
pOut = (sNISContextData *) calloc(1, sizeof(sNISContextData));
if ( pOut != nil )
{
siResult = CleanContextData(pOut);
}
return( pOut );
}
sInt32 CleanContextData ( sNISContextData *inContext )
{
sInt32 siResult = eDSNoErr;
if ( inContext == nil )
{
siResult = eDSBadContextData;
}
else
{
inContext->offset = 0;
}
return( siResult );
}
UInt32 GetCurrentTime( void ) {
struct timeval curTime;
if ( gettimeofday( &curTime, NULL ) != 0 )
fprintf( stderr, "call to gettimeofday returned error: %s", strerror(errno) );
return curTime.tv_sec;
}
Boolean IsResultOK( tDirPatternMatch patternMatch, CFStringRef resultRecordNameRef, CFStringRef recNameMatchRef )
{
Boolean resultIsOK = false;
if ( patternMatch == eDSAnyMatch )
{
resultIsOK = true;
}
else if ( !resultRecordNameRef || !recNameMatchRef ) {
resultIsOK = false;
}
else if ( patternMatch == eDSExact && CFStringCompare( resultRecordNameRef, recNameMatchRef, 0 ) == kCFCompareEqualTo )
{
resultIsOK = true;
}
else if ( patternMatch >= eDSiExact && CFStringCompare( resultRecordNameRef, recNameMatchRef, kCFCompareCaseInsensitive ) == kCFCompareEqualTo )
{
resultIsOK = true;
}
else if ( patternMatch == eDSStartsWith && CFStringHasPrefix( resultRecordNameRef, recNameMatchRef ) )
{
resultIsOK = true;
}
else if ( patternMatch == eDSEndsWith && CFStringHasSuffix( resultRecordNameRef, recNameMatchRef ) )
{
resultIsOK = true;
}
else if ( patternMatch == eDSContains )
{
CFRange result = CFStringFind( resultRecordNameRef, recNameMatchRef, 0 );
if ( result.length > 0 )
resultIsOK = true;
}
else if ( patternMatch == eDSiContains || patternMatch == eDSiStartsWith || patternMatch == eDSiEndsWith )
{
CFRange result = CFStringFind( resultRecordNameRef, recNameMatchRef, kCFCompareCaseInsensitive );
if ( result.length > 0 )
{
if ( patternMatch == eDSiContains )
{
resultIsOK = true;
}
else if ( patternMatch == eDSiStartsWith && result.location == 0 )
{
resultIsOK = true;
}
else if ( patternMatch == eDSiEndsWith && result.location == CFStringGetLength(resultRecordNameRef) - result.length )
{
resultIsOK = true;
}
}
}
return resultIsOK;
}
void AddDictionaryDataToAttrData(const void *key, const void *value, void *context)
{
CFStringRef keyRef = (CFStringRef)key;
CFTypeRef valueTypeRef = (CFTypeRef)value; CFStringRef valueRef = NULL;
CFArrayRef valueArrayRef = NULL;
char keyBuf[256] = {0};
char* valueBuf = NULL;
CDataBuff* aTmpData = nil;
AttrDataContext* dataContext = (AttrDataContext*)context;
DBGLOG( "AddDictionaryDataToAttrData called with key: 0x%x, value 0x%x\n", (int)key, (int)value );
if ( dataContext->attrType && strcmp( dataContext->attrType, kDSAttributesStandardAll ) == 0 )
{
if ( CFStringHasPrefix( keyRef, CFSTR(kDSAttributesStandardAll) ) )
{
DBGLOG( "AddDictionaryDataToAttrData ignoring type as it isn't a standard attribute\n" );
return;
}
}
else if ( dataContext->attrType && strcmp( dataContext->attrType, kDSAttributesNativeAll ) == 0 )
{
if ( CFStringHasPrefix( keyRef, CFSTR(kDSAttributesNativeAll) ) )
{
DBGLOG( "AddDictionaryDataToAttrData ignoring type as it isn't a native attribute\n" );
return;
}
}
dataContext->count++;
aTmpData = new CDataBuff();
if( !aTmpData ) throw( eMemoryError );
aTmpData->Clear();
if ( valueTypeRef )
{
if ( CFGetTypeID(valueTypeRef) == CFArrayGetTypeID() )
{
valueArrayRef = (CFArrayRef)valueTypeRef;
CFRetain( valueArrayRef ); }
else
if ( CFGetTypeID(valueTypeRef) == CFStringGetTypeID() )
{
valueRef = (CFStringRef)valueTypeRef;
valueArrayRef = CFArrayCreateMutable( NULL, 1, &kCFTypeArrayCallBacks );
if ( CFStringGetLength( valueRef ) > 0 )
CFArrayAppendValue( (CFMutableArrayRef)valueArrayRef, valueRef );
}
else
DBGLOG( "AddDictionaryDataToAttrData, got unknown value type (%ld), ignore\n", CFGetTypeID(valueTypeRef) );
if ( valueArrayRef && ::CFStringGetCString( keyRef, keyBuf, sizeof(keyBuf), kCFStringEncodingUTF8 ) )
{
char valueTmpBuf[1024];
CFIndex arrayCount = CFArrayGetCount(valueArrayRef);
aTmpData->AppendShort( ::strlen( keyBuf ) ); aTmpData->AppendString( keyBuf );
DBGLOG( "AddDictionaryDataToAttrData, adding keyBuf: %s\n", keyBuf );
aTmpData->AppendShort( arrayCount );
for ( CFIndex i=0; i< arrayCount; i++ )
{
valueRef = (CFStringRef)::CFArrayGetValueAtIndex( valueArrayRef, i );
if ( !dataContext->attrOnly && ::CFStringGetLength(valueRef) > 0 )
{
CFIndex maxValueEncodedSize = ::CFStringGetMaximumSizeForEncoding(CFStringGetLength(valueRef), kCFStringEncodingUTF8) + 1;
if ( maxValueEncodedSize > (CFIndex)sizeof(valueTmpBuf) )
valueBuf = (char*)malloc( maxValueEncodedSize );
else
valueBuf = valueTmpBuf;
if ( ::CFStringGetCString( valueRef, valueBuf, maxValueEncodedSize, kCFStringEncodingUTF8 ) )
{
aTmpData->AppendShort( ::strlen( valueBuf ) ); aTmpData->AppendString( valueBuf );
DBGLOG( "AddDictionaryDataToAttrData, adding valueBuf: %s\n", valueBuf );
}
else
{
DBGLOG( "AddDictionaryDataToAttrData, CFStringGetCString couldn't create a string for valueRef!\n" );
if ( getenv( "NSLDEBUG" ) )
::CFShow( valueRef );
}
if ( valueBuf != valueTmpBuf )
free( valueBuf );
valueBuf = NULL;
}
}
dataContext->attrDataBuf->AppendShort( aTmpData->GetLength() );
dataContext->attrDataBuf->AppendBlock( aTmpData->GetData(), aTmpData->GetLength() );
aTmpData->Clear();
delete aTmpData;
}
if ( valueArrayRef )
{
CFRelease( valueArrayRef );
}
}
}
void FindAttributeMatch(const void *key, const void *value, void *context)
{
CFStringRef keyRef = (CFStringRef)key;
CFTypeRef valueRef = (CFTypeRef)value;
CFArrayRef valueArrayRef = NULL;
AttrDataMatchContext* info = (AttrDataMatchContext*)context;
if ( info->foundAMatch )
return;
if ( !valueRef )
return;
if ( info->fAttributeNameToMatchRef && CFStringCompare( keyRef, info->fAttributeNameToMatchRef, kCFCompareCaseInsensitive ) != kCFCompareEqualTo )
{
return;
}
if ( CFGetTypeID(valueRef) == CFArrayGetTypeID() )
{
valueArrayRef = (CFArrayRef)valueRef;
CFRetain( valueArrayRef ); }
else if ( CFGetTypeID(valueRef) == CFStringGetTypeID() )
{
valueArrayRef = CFArrayCreateMutable( NULL, 1, &kCFTypeArrayCallBacks );
CFArrayAppendValue( (CFMutableArrayRef)valueArrayRef, valueRef );
}
else
{
DBGLOG( "FindAttributeMatch, got unknown value type (%ld), ignore\n", CFGetTypeID(valueRef) );
CFShow( valueRef );
}
CFIndex arrayCount = CFArrayGetCount(valueArrayRef);
for ( CFIndex i=0; valueArrayRef && i< arrayCount && !info->foundAMatch; i++ )
{
CFStringRef valueStringRef = (CFStringRef)::CFArrayGetValueAtIndex( valueArrayRef, i );
if ( IsResultOK( info->fInPattMatchType, valueStringRef, info->fInPatt2MatchRef ) )
info->foundAMatch = true;
}
if ( valueArrayRef )
{
CFRelease( valueArrayRef );
}
}
void FindAllAttributeMatches(const void *key, const void *value, void *context)
{
CFTypeRef valueRef = NULL;
CFDictionaryRef resultRef = (CFDictionaryRef)value;
ResultMatchContext* info = (ResultMatchContext*)context;
Boolean recordMatches = false;
if ( info->fInPattMatchType == eDSAnyMatch )
{
recordMatches = true;
}
else if ( resultRef && CFGetTypeID(resultRef) == CFDictionaryGetTypeID() )
{
if ( info->fAttributeNameToMatchRef )
{
CFArrayRef valueArrayRef = NULL;
valueRef = CFDictionaryGetValue( resultRef, info->fAttributeNameToMatchRef );
if (!valueRef)
return;
if ( CFGetTypeID(valueRef) == CFArrayGetTypeID() )
{
valueArrayRef = (CFArrayRef)valueRef;
CFRetain( valueArrayRef ); }
else if ( CFGetTypeID(valueRef) == CFStringGetTypeID() )
{
valueArrayRef = CFArrayCreateMutable( NULL, 1, &kCFTypeArrayCallBacks );
CFArrayAppendValue( (CFMutableArrayRef)valueArrayRef, valueRef );
}
else
{
DBGLOG( "FindAllAttributeMatches, got unknown value type (%ld), ignore\n", CFGetTypeID(valueRef) );
CFShow( valueRef );
}
CFIndex arrayCount = CFArrayGetCount(valueArrayRef);
for ( CFIndex i=0; valueArrayRef && i< arrayCount; i++ )
{
CFStringRef valueStringRef = (CFStringRef)::CFArrayGetValueAtIndex( valueArrayRef, i );
if ( IsResultOK( info->fInPattMatchType, valueStringRef, info->fInPatt2MatchRef ) )
{
recordMatches = true;
break;
}
}
if ( valueArrayRef )
{
CFRelease( valueArrayRef );
}
}
else
{
AttrDataMatchContext context = { info->fInPattMatchType, info->fInPatt2MatchRef, info->fAttributeNameToMatchRef, false };
CFDictionaryApplyFunction( resultRef, FindAttributeMatch, &context );
if ( context.foundAMatch )
recordMatches = true;
}
}
else
DBGLOG( "FindAllAttributeMatches, got unknown value type (%ld), ignore\n", CFGetTypeID(valueRef) );
if ( recordMatches )
CFArrayAppendValue( info->fResultArray, resultRef );
}
#define kOffset 0
#define kHexData 7
#define kASCIIData (kHexData+50)
#define kEOL (kASCIIData+16)
#define kLineLength (kEOL+1)
#define kLineEnding '\n'
#define kBufferTooBig -1
#define kMaxBufSize 10240
#define kMaxPacketLen (((kMaxBufSize - 2)/kLineLength)*16)-15
int LogHexDump(char *pktPtr, long pktLen)
{
static char hexChars[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
register unsigned char *curPtr=NULL; register char *hexPtr=NULL; register char *charPtr=NULL; char *offsetPtr=NULL; unsigned char *p=NULL; short i,j;
char *buf=NULL;
long bufLen;
short numLines;
short numCharsOnLine;
short remainder;
short offset;
if ( pktLen == 0 )
{
DBGLOG( "LogHexDump was passed in a pktLen of zero!\n" );
return noErr; }
if ( pktLen > kMaxPacketLen )
pktLen = kMaxPacketLen;
numLines = (pktLen + 15)/16; remainder = pktLen - (numLines-1)*16;
bufLen = numLines * kLineLength + 2;
if (bufLen > kMaxBufSize)
{
DBGLOG( "LogHexDump kBufferTooBig (%ld), setting to max log size (%d)\n", bufLen, kMaxBufSize );
bufLen = kMaxBufSize;
}
DBGLOG( "Dumping %ld bytes of hex-format data:\n",pktLen );
buf = (char*)malloc(bufLen);
if (!buf)
{
DBGLOG( "LogHexDump return memFullErr\n" );
return(eMemoryAllocError);
}
for (i=0; i<bufLen; i++) buf[i] = ' ';
curPtr = (unsigned char *)pktPtr; offsetPtr = buf; for (j=0; j<numLines; j++) {
hexPtr = offsetPtr+kHexData; charPtr = offsetPtr+kASCIIData;
offset = j*16; p = (unsigned char*)&offset; *(offsetPtr++) = hexChars[(*p>>4)];
*(offsetPtr++) = hexChars[(*p++&0x0F)]; *(offsetPtr++) = hexChars[(*p>>4)];
*(offsetPtr++) = hexChars[(*p&0x0F)];
*offsetPtr = ':';
if (j == numLines-1) numCharsOnLine = remainder;
else numCharsOnLine = 16;
for (i=0; i<numCharsOnLine; i++) {
*(hexPtr++) = hexChars[(*curPtr>>4)];
*(hexPtr++) = hexChars[(*curPtr&0x0F)];
hexPtr++;
if (isprint(*curPtr))
*(charPtr++) = *curPtr;
else *(charPtr++) = '.';
curPtr++; }
*(charPtr++) = kLineEnding; offsetPtr = charPtr; }
*(charPtr++) = kLineEnding;
*charPtr = '\0';
DBGLOG( "%s\n",buf);
free(buf);
return noErr;
}
#if BUILDING_NSLDEBUG
pthread_mutex_t bsdSysLogLock = PTHREAD_MUTEX_INITIALIZER;
void ourLog(const char* format, ...)
{
va_list ap;
pthread_mutex_lock( &bsdSysLogLock );
va_start( ap, format );
newlog( format, ap );
va_end( ap );
pthread_mutex_unlock( &bsdSysLogLock );
}
void newlog(const char* format, va_list ap )
{
char pcMsg[MAXLINE +1];
vsnprintf( pcMsg, MAXLINE, format, ap );
#if LOG_ALWAYS
syslog( LOG_ALERT, "T:[0x%x] %s", pthread_self(), pcMsg );
#else
syslog( LOG_ERR, "T:[0x%x] %s", pthread_self(), pcMsg );
#endif
}
#endif
#if LOG_ALWAYS
int gDebuggingNSL = 1;
#else
int gDebuggingNSL = (getenv("NSLDEBUG") != NULL);
#endif
int IsNSLDebuggingEnabled( void )
{
return gDebuggingNSL;
}