/*
* Copyright (c) 2000 - 2003 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
/*!
* @header DSAuthenticate
*/
#import "DSAuthenticate.h"
#import <Security/checkpw.h>
extern BOOL doVerbose;
@implementation DSAuthenticate
- init
{
tDirStatus status = eDSNoErr;
[super init];
_SearchNodeRef = 0;
_dsStat = [[DSStatus sharedInstance] retain];
[self useAuthenticationSearchPath];
[self searchForUsers];
if (doVerbose)
{
printf("---> dsOpenDirService() ........................ ");
fflush(stdout);
}
status = dsOpenDirService(&_DirRef);
if (doVerbose)
{
[_dsStat printOutErrorMessage:"Status" withStatus:status];
}
if (status != eDSNoErr)
{
[[DSException name:@"DSOpenDirServiceErr" reason:@"Cannot open Directory Services." status:status] raise];
[_dsStat release];
}
_MasterUserList = [[NSMutableArray alloc] init];
return self;
}
- (void) dealloc
{
if (_SearchNodeRef != 0)
dsCloseDirNode(_SearchNodeRef);
if (_DirRef != 0)
dsCloseDirService(_DirRef);
if (_MasterUserList != nil)
[_MasterUserList release];
[_dsStat release];
[super dealloc];
}
- (void) reset
{
if (_SearchNodeRef != 0)
{
dsCloseDirNode(_SearchNodeRef);
_SearchNodeRef = 0;
}
[self useAuthenticationSearchPath];
[self searchForUsers];
if (_MasterUserList != nil)
[_MasterUserList release];
_MasterUserList = [[NSMutableArray alloc] init];
}
// ------------------------------------------------------------------
// useAuthenticationSearchPath
//
// Set this object to use the Authentication search node.
// This is the default behavior.
// ------------------------------------------------------------------
- (void)useAuthenticationSearchPath
{
_SearchNodeNameToUse = eDSSearchNodeName;
}
// ------------------------------------------------------------------
// useContactSearchPath
//
// Set this object to use the Contacts search node, instead of
// the Authentication search node.
// ------------------------------------------------------------------
- (void)useContactSearchPath
{
_SearchNodeNameToUse = eDSContactsSearchNodeName;
}
// ------------------------------------------------------------------
// searchForUsers
//
// Set this object to search for users.
// This is the default behavior.
// ------------------------------------------------------------------
- (void)searchForUsers
{
_SearchObjectType = kDSStdRecordTypeUsers;
}
// ------------------------------------------------------------------
// searchForGroups
//
// Set this object to search for groups, instead of users.
// ------------------------------------------------------------------
- (void)searchForGroups
{
_SearchObjectType = kDSStdRecordTypeGroups;
}
// ============================================================================
// Wrapper methods for Directory Service Utility functions
//
// These methods provide wrappers for some DS utility functions.
// Most of the wrapped functions require
// an argument that is a reference to an open Directory server.
// These automatically provide that reference from the class's
// members.
// ------------------------------------------------------------------
// allocateDataBuffer: withNumberOfBlocks: shouldReallocate:
//
// Allocates memory for the passed in tDataBufferPtr. It expects
// an argument with the number of blocks of memory to allocate,
// where the block size is specified in the class's header file.
// The final parameter specifies whether the buffer has previously
// been allocated memory and should thus be deallocated before
// allocating the new amount.
// ------------------------------------------------------------------
- (void)allocateDataBuffer:(tDataBufferPtr*)buffer
withNumberOfBlocks:(unsigned short) numberOfBlocks
shouldReallocate:(BOOL) reAllocate
{
if (reAllocate == YES)
{
tDirStatus status;
status = dsDataBufferDeAllocate(_DirRef, *buffer);
}
*buffer = dsDataBufferAllocate(_DirRef, numberOfBlocks*kBufferBlockSize);
}
// ------------------------------------------------------------------
// deallocateDataBuffer:
//
// Deallocate memory previously allocated to a tDataBuffer.
// ------------------------------------------------------------------
- (tDirStatus)deallocateDataBuffer:(tDataBufferPtr)buffer
{
if (buffer != NULL)
{
tDirStatus status = dsDataBufferDeAllocate(_DirRef, buffer);
return status;
}
else
return eDSNoErr;
}
// ------------------------------------------------------------------
// deallocateDataList:
//
// Deallocate memory previously allocated to a tDataList.
// The memory allocated to the tDataList pointer object
// must also be free'd manually.
// ------------------------------------------------------------------
- (tDirStatus)deallocateDataList:(tDataListPtr)list;
{
if (list != NULL)
{
tDirStatus status = dsDataListDeAllocate(_DirRef, list, TRUE);
free(list);
return status;
}
else
return eDSNoErr;
}
// ------------------------------------------------------------------
// deallocateDataNode:
//
// Deallocate memory previously allocated to a tDataNode.
// ------------------------------------------------------------------
- (tDirStatus)deallocateDataNode:(tDataNodePtr)node;
{
if (node != NULL)
{
tDirStatus status = dsDataNodeDeAllocate(_DirRef, node);
return status;
}
else
return eDSNoErr;
}
// ============================================================================
// Private utility methods for accessing obtaining and opening
// directory nodes.
// ------------------------------------------------------------------
// retrieveLocalNode
//
// Uses dsFindDirNodes to find and return a pointer to a tDataBuffer
// that should only contain one item: the name of the local node.
// ------------------------------------------------------------------
- (tDataBufferPtr) retrieveLocalNode
{
UInt32 count = 0;
tDataBufferPtr buffer = NULL;
tDirStatus status = eDSNoErr;
[self allocateDataBuffer:&buffer withNumberOfBlocks:4 shouldReallocate: NO];
if (doVerbose)
{
printf("---> dsFindDirNodes() for Local Node .......... ");
fflush(stdout);
}
status = dsFindDirNodes(_DirRef, buffer, NULL, eDSLocalNodeNames, &count, NULL);
if (doVerbose)
{
[_dsStat printOutErrorMessage:"Status" withStatus:status];
}
return buffer;
}
// ------------------------------------------------------------------
// retrieveSearchPathNode
//
// Uses dsFindDirNodes to find and return a pointer to a tDataBuffer
// that should only contain one item: the name of the selected search node
// that is identified by the instance variable _SearchNodeNameToUse.
// ------------------------------------------------------------------
- (tDataBufferPtr) retrieveSearchPathNode
{
UInt32 count = 0;
tDataBufferPtr buffer = NULL;
tDirStatus status = eDSNoErr;
[self allocateDataBuffer:&buffer withNumberOfBlocks:4 shouldReallocate: NO];
if (doVerbose)
{
printf("---> dsFindDirNodes() for Search Node .......... ");
fflush(stdout);
}
status = dsFindDirNodes(_DirRef, buffer, NULL, _SearchNodeNameToUse, &count, NULL);
if (doVerbose)
{
[_dsStat printOutErrorMessage:"Status" withStatus:status];
}
return buffer;
}
// ------------------------------------------------------------------
// getNodeNameForBuffer:
//
// Takes a pointer to a tDataBuffer that represents a list of nodes
// and grabs the name of the first item in the buffer.
// It returns the pointer to a tDataList object that
// encapsulates the name of the node.
// ------------------------------------------------------------------
- (tDataListPtr) getNodeNameForBuffer:(tDataBufferPtr)buffer
{
tDataListPtr tdlist = NULL;
tDirStatus status = eDSNoErr;
tdlist = dsDataListAllocate(_DirRef);
status = dsGetDirNodeName(_DirRef, buffer, 1, &tdlist);
return tdlist;
}
// ------------------------------------------------------------------
// openDirNodeWithName:
//
// Takes a pointer to a tDataList that encapsulates the name
// of a directory node, and opens that node. It returns a
// reference to the open node.
// ------------------------------------------------------------------
- (tDirNodeReference)openDirNodeWithName:(tDataListPtr)inNodeName
{
tDirNodeReference fNodeRef = 0;
tDirStatus status = eDSNoErr;
if ( (doVerbose) && (inNodeName != nil) && (inNodeName->fDataListHead->fBufferData != nil) )
{
printf("---> dsOpenDirNode() for node named: fflush(stdout);
}
status = dsOpenDirNode(_DirRef, inNodeName, &fNodeRef);
if (doVerbose)
{
printf("\t");
[_dsStat printOutErrorMessage:"Status" withStatus:status];
}
return fNodeRef;
}
// ============================================================================
// Private methods for performing search functionality in
// Directory Services.
// ------------------------------------------------------------------
// fetchRecordListOnSearchNodeMatchingName:
//
// Peforms a search for the specified inUsername on the search path
// node that is currently referenced by this object, and adds matching
// nodes to this object's master list of found records.
// See also -fetchRecordListOnNode: matchingName:
// ------------------------------------------------------------------
- (tDirStatus)fetchRecordListOnSearchNodeMatchingName:(NSString*)inUsername
{
tDataListPtr nodeName = nil;
tDataBufferPtr nodeBuffer = nil;
tDirNodeReference nodeRef = 0;
tDirStatus status = eDSNoErr;
nodeBuffer = [self retrieveSearchPathNode];
nodeName = [self getNodeNameForBuffer:nodeBuffer];
nodeRef = [self openDirNodeWithName:nodeName];
status = [self fetchRecordListOnNode:nodeRef matchingName:inUsername];
dsCloseDirNode(nodeRef);
[self deallocateDataBuffer:nodeBuffer];
[self deallocateDataList:nodeName];
return status;
}
// ------------------------------------------------------------------
// addBufferToListOfUsers: fromBuffer: inSearchNode:
//
// Convert Buffer user records to collection of NSArray/NSDictionary/NSString.
// Takes the buffer items and creates an NSDictionary for each key
// and its values. Those values are placed into an NSArray.
// Then each record is added to the _MasterUserList NSArray.
// ------------------------------------------------------------------
- (void)addToListOfUsers: (unsigned long)returnCount fromBuffer: (tDataBufferPtr)nodeBuffer inSearchNode:(tDirNodeReference)nodeRefToSearch
{
int i = 0;
int j = 0;
int k = 0;
tAttributeValueListRef valueRef = 0;
tAttributeEntryPtr pAttrEntry = nil;
tAttributeValueEntryPtr pValueEntry = nil;
tAttributeListRef attrListRef = 0;
tRecordEntry *pRecEntry = nil;
NSMutableDictionary *userAttributes = nil;
NSMutableArray *userAttrValues = nil;
NSString *key = nil;
tDirStatus status = eDSNoErr;
for (i =1; i<= returnCount; i++)
{
status =dsGetRecordEntry( nodeRefToSearch, nodeBuffer, i, &attrListRef, &pRecEntry );
userAttributes = [[NSMutableDictionary alloc ] init];
// Iterate over the Attributes keys for the user.
for (j =1; j<=pRecEntry->fRecordAttributeCount; j++)
{
userAttrValues = [[NSMutableArray alloc] init];
status =dsGetAttributeEntry( nodeRefToSearch, nodeBuffer, attrListRef, j, &valueRef, &pAttrEntry );
// Iterate over the values for the current attribute key
for (k =1; k<=pAttrEntry->fAttributeValueCount; k++)
{
status =dsGetAttributeValue( nodeRefToSearch, nodeBuffer, k, valueRef, &pValueEntry );
if (status == eDSNoErr) {
// Next commented out line causes a one-time 14 byte leak, don't understand why.
//[userAttrValues addObject: [NSString stringWithUTF8String:pValueEntry->fAttributeValueData.fBufferData]];
NSString *valueStr = [[NSString alloc] initWithUTF8String:pValueEntry->fAttributeValueData.fBufferData];
[userAttrValues addObject:valueStr];
[valueStr release];
}
// Clean up memory
if (pValueEntry != nil)
{
status = dsDeallocAttributeValueEntry(_DirRef, pValueEntry);
pValueEntry = nil;
}
}
key = [[NSString alloc] initWithCString: pAttrEntry->fAttributeSignature.fBufferData];
[userAttributes setObject: userAttrValues forKey: key];
[key release];
[userAttrValues release];
// Clean up memory
if (pAttrEntry != nil)
{
status = dsDeallocAttributeEntry(_DirRef, pAttrEntry);
pAttrEntry = nil;
}
if (valueRef != 0)
{
status = dsCloseAttributeValueList(valueRef);
valueRef = 0;
}
}
[_MasterUserList addObject: userAttributes];
[userAttributes release];
// Clean up memory
if (pRecEntry != nil)
{
status = dsDeallocRecordEntry(_DirRef, pRecEntry);
pRecEntry = nil;
}
if (attrListRef != 0)
{
status = dsCloseAttributeList(attrListRef);
attrListRef = 0;
}
}
}
// ------------------------------------------------------------------
// fetchRecordListOnNode: matchingName:
//
// Peforms a search for the specified inUsername in the specified
// node reference (presumable a search node), and adds matching
// nodes to this object's master list of found records.
// See also -fetchRecordListOnSearchNodeMatchingName:
// ------------------------------------------------------------------
- (tDirStatus)fetchRecordListOnNode:(tDirNodeReference)nodeRefToSearch matchingName:(NSString*)inUsername
{
tContextData localcontext = 0;
tDataListPtr recName = nil;
tDataListPtr recType = nil;
tDataListPtr attrType = nil;
tDataBufferPtr nodeBuffer = nil;
tDirStatus status = eDSNoErr;
unsigned short blockCount = 1;
UInt32 returnCount = 0;
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
unsigned long matchingUsers = 0;
recName = dsBuildListFromStrings(_DirRef, [inUsername cString], NULL);
recType = dsBuildListFromStrings(_DirRef, _SearchObjectType, NULL);
attrType = dsBuildListFromStrings(_DirRef, kDSNAttrMetaNodeLocation, kDSNAttrRecordName, NULL);
[self allocateDataBuffer: &nodeBuffer withNumberOfBlocks: blockCount shouldReallocate: NO];
do
{
if (doVerbose)
{
printf("---> dsGetRecordList() .... ");
fflush(stdout);
}
// Stuff the record entries into nodeBuffer
status = dsGetRecordList(nodeRefToSearch, nodeBuffer, recName, eDSExact, recType, attrType, false, &returnCount, &localcontext);
if (doVerbose)
{
printf("Count: localcontext == 0 ? "NO" : "YES");
[_dsStat printOutErrorMessage:"Status" withStatus:status];
}
if (status == eDSBufferTooSmall)
{
blockCount++;
}
else if (status == eDSNoErr && returnCount > 0)
{
[self addToListOfUsers: returnCount fromBuffer: nodeBuffer inSearchNode: nodeRefToSearch ];
}
[self allocateDataBuffer: &nodeBuffer withNumberOfBlocks: blockCount shouldReallocate: YES];
} while ( (status == eDSNoErr && localcontext != 0) || (status == eDSBufferTooSmall));
// Do Memory cleanup
if (localcontext != 0)
{
dsReleaseContinueData(nodeRefToSearch, localcontext);
localcontext = 0;
}
[self deallocateDataList:recType];
[self deallocateDataList:recName];
[self deallocateDataList:attrType];
[self deallocateDataBuffer:nodeBuffer];
[pool release];
// If status is not eDSNoErr, and we didn't get any users, raise an exception.
// If we did get users, then it is some non-fatal error. The normal
// print statements will output the status error, but we should not raise
// an exception (which aborts program execution).
// However, if we get a eDSServerTimeout error, then we should raise exception.
matchingUsers = [_MasterUserList count];
if (status != eDSNoErr && (matchingUsers <= 0 || status == eDSServerTimeout))
{
DSException *ex = nil;
ex = [DSException name:@"FetchRecordError" reason:@"Unable to retrieve any records via dsGetRecordList." status:status];
[ex raise];
}
printf("Call to dsGetRecordList returned count = [_dsStat printOutErrorMessage:"Status" withStatus:status];
if (matchingUsers <= 0)
{
printf("No matching users found.\n");
if (checkpw([inUsername cString], "") != CHECKPW_UNKNOWNUSER)
printf("**** checkpw() DISAGREES! ****\n");
}
return status;
}
// ------------------------------------------------------------------
// getAttibute: forRecordNumber
//
// Retrieve the attribute string from the recordNumber'th
// matching record from the recent search in the search path.
// ------------------------------------------------------------------
- (NSString*)getAttribute: (char*)attr forRecordNumber: (unsigned long)recordNumber
{
NSArray *recordValues = nil;
NSString *key = [[NSString alloc] initWithCString: attr];
recordValues = [[_MasterUserList objectAtIndex: recordNumber] objectForKey: key];
[key release];
if (recordValues != nil && [recordValues count] > 0)
{
return [recordValues objectAtIndex:0];
}
else
return nil;
}
// ------------------------------------------------------------------
// nodePathStrForSearchNodeRecordNumber:
//
// Retrieve the username string from the recordNumber'th
// matching record from the recent search in the search path.
// ------------------------------------------------------------------
- (NSString*)usernameForSearchNodeRecordNumber:(unsigned long)recordNumber
{
return [self getAttribute:kDSNAttrRecordName forRecordNumber:recordNumber];
}
// ------------------------------------------------------------------
// nodePathStrForSearchNodeRecordNumber:
//
// Retrieve the node path name string from the recordNumber'th
// matching record from the recent search in the search path.
// ------------------------------------------------------------------
- (NSString*)nodePathStrForSearchNodeRecordNumber:(unsigned long)recordNumber
{
return [self getAttribute:kDSNAttrMetaNodeLocation forRecordNumber:recordNumber];
}
// ============================================================================
// Public methods for accessing the Directory Service functions
// that this class provides.
// ------------------------------------------------------------------
// authenticateInNodePathStr: username: password:
//
// Takes the text string name of a node path and performs an
// authentication check on it for the specified username & passowrd.
// Similar to authOnNodePath: username: password:, except this one
// is optimized for short usernames only. It skips searching the
// node for the user record and just sends checks for authetication
// based on the username specified in the arguments.
// ------------------------------------------------------------------
- (tDirStatus)authenticateInNodePathStr:(NSString*)nodePathStr username:(NSString*)inUsername
password:(NSString*)inPassword
{
tDataListPtr nodePath = nil;
tDirNodeReference userNode = 0;
tDirStatus status = eDSNoErr;
nodePath = dsBuildFromPath(_DirRef, [nodePathStr cString], "/");
if (doVerbose)
{
printf("---> dsOpenDirNode() on node Named: fflush(stdout);
}
status = dsOpenDirNode(_DirRef, nodePath, &userNode);
if (doVerbose)
{
printf("\t");
[_dsStat printOutErrorMessage:"Status" withStatus:status];
}
[self deallocateDataList:nodePath];
if (status == eDSNoErr)
status = [self authenticateInNode:userNode username:inUsername password:inPassword];
dsCloseDirNode(userNode);
return status;
}
// ------------------------------------------------------------------
// authenticateInNode: username: password:
//
// Takes a DirectoryServices node path reference and performs an
// authentication check on it for the specified username & passowrd.
// ------------------------------------------------------------------
- (tDirStatus)authenticateInNode:(tDirNodeReference)userNode username:(NSString*)inUsername
password:(NSString*)inPassword
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
tDataBufferPtr step = NULL;
tDataBufferPtr stepResponse = NULL;
tDataNodePtr authMethod = NULL;
UInt32 length = 0;
UInt32 current = 0;
tDirStatus status = 0;
[self allocateDataBuffer:&step withNumberOfBlocks:4 shouldReallocate: NO];
[self allocateDataBuffer:&stepResponse withNumberOfBlocks:4 shouldReallocate: NO];
authMethod = dsDataNodeAllocateString(_DirRef, kDSStdAuthNodeNativeClearTextOK);
length = strlen( [inUsername UTF8String] );
memcpy( &(step->fBufferData[current]), &length, sizeof(length));
current += sizeof(length);
memcpy( &(step->fBufferData[current]), [inUsername UTF8String], length );
current +=length;
length = strlen( [inPassword UTF8String] );
memcpy( &(step->fBufferData[current]), &length, sizeof(length));
current += sizeof(length);
memcpy( &(step->fBufferData[current]), [inPassword UTF8String], length );
step->fBufferLength = current + length;
if(doVerbose)
{
printf("---> dsDoDirNodeAuth() ......................... ");
fflush(stdout);
}
status = dsDoDirNodeAuth(userNode, authMethod, 1, step, stepResponse, NULL);
if(doVerbose)
{
[_dsStat printOutErrorMessage:"Status" withStatus:status];
}
printf("Username: if(status == eDSNoErr)
printf("Success");
else
[_dsStat printOutErrorMessage:"Error" withStatus:status];
// Clean up allocated memory
//dsCloseDirNode(userNode); // don't close since not opened here
[self deallocateDataNode:authMethod];
[self deallocateDataBuffer:step];
[self deallocateDataBuffer:stepResponse];
[pool release];
return (status);
}
// ------------------------------------------------------------------
// authUserOnLocalNode: password:
//
// Takes the specified username and password and performs an
// authentication check for them on the local NetInfo node.
// ------------------------------------------------------------------
- (tDirStatus)authUserOnLocalNode:(NSString*)inUsername password:(NSString*)inPassword
{
tDataBufferPtr localNodeBuffer = nil;
tDataListPtr localNodeName = nil;
tDirNodeReference localNodeRef = 0;
tDirStatus status = eDSNoErr;
u_long i = 0;
unsigned long matchingUsers = 0;
localNodeBuffer = [self retrieveLocalNode];
localNodeName = [self getNodeNameForBuffer:localNodeBuffer];
[self deallocateDataBuffer:localNodeBuffer];
localNodeRef = [self openDirNodeWithName:localNodeName];
[self deallocateDataList:localNodeName];
[self fetchRecordListOnNode:localNodeRef matchingName:inUsername];
matchingUsers = [_MasterUserList count];
for (i=0; i< matchingUsers; i++)
{
status = [self authenticateInNode:localNodeRef username:[self usernameForSearchNodeRecordNumber:i] password:inPassword];
printf("\n");
}
dsCloseDirNode(localNodeRef);
return status;
}
// ------------------------------------------------------------------
// authOnNodePath: username: password:
//
// Takes the text string name of a node path and performs an
// authentication check on it for the specified username & passowrd.
// Both long and short usernames can be used because it first
// searches the node for the user record. Then it extracts
// the short username and uses that to check authentication.
// ------------------------------------------------------------------
- (tDirStatus)authOnNodePath:(NSString*)nodePathStr username:(NSString*)inUsername password:(NSString*)inPassword
{
tDataListPtr nodePath = NULL;
tDirNodeReference userNode = 0;
tDirStatus status = 0;
int i = 0;
unsigned long matchingUsers = 0;
nodePath = dsBuildFromPath(_DirRef, [nodePathStr cString], "/");
if (doVerbose)
{
printf("---> dsOpenDirNode() on node Named: fflush(stdout);
}
status = dsOpenDirNode(_DirRef, nodePath, &userNode);
if (doVerbose)
{
printf("\t");
[_dsStat printOutErrorMessage:"Status" withStatus:status];
}
[self deallocateDataList:nodePath];
// if we have an eDSNoErr on open, then we can continue...
if( status == eDSNoErr )
{
[self fetchRecordListOnNode:userNode matchingName:inUsername];
matchingUsers = [_MasterUserList count];
for (i=0; i < matchingUsers; i++)
{
status = [self authenticateInNode:userNode username:[self usernameForSearchNodeRecordNumber:i] password:inPassword];
printf("\n");
}
dsCloseDirNode(userNode);
}
return status;
}
// ------------------------------------------------------------------
// authUserOnSearchPath: password:
//
// Finds all nodes in the search path that contain a user by the
// specified name. It then successively performs an authentication
// check on those nodes for the username and password specified.
// ------------------------------------------------------------------
- (tDirStatus)authUserOnSearchPath:(NSString*)inUsername password:(NSString*)inPassword
{
tDataBufferPtr searchNodeBuffer = nil;
tDataListPtr searchNodeName = nil;
tDirStatus status = eDSNoErr;
u_long i = 0;
NSString *nodePathStr = nil;
NSString *realUsername = nil;
int checkpwresult = 1;
char *cpwresultstr = nil;
NSAutoreleasePool *pool = nil;
unsigned long matchingUsers = 0;
NS_DURING
searchNodeBuffer = [self retrieveSearchPathNode];
searchNodeName = [self getNodeNameForBuffer:searchNodeBuffer];
[self deallocateDataBuffer:searchNodeBuffer];
searchNodeBuffer = nil;
_SearchNodeRef = [self openDirNodeWithName:searchNodeName];
[self deallocateDataList:searchNodeName];
searchNodeName = nil;
status = [self fetchRecordListOnNode:_SearchNodeRef matchingName:inUsername];
matchingUsers = [_MasterUserList count];
for (i=0 ; i < matchingUsers; i++)
{
pool = [[NSAutoreleasePool alloc] init];
nodePathStr = [self nodePathStrForSearchNodeRecordNumber:i];
realUsername = [self usernameForSearchNodeRecordNumber:i];
if ([self isMemberOfClass:[DSAuthenticate class]])
{
if (i == 0) //only need to do checkpw once since result will not change
{
checkpwresult = checkpw([realUsername cString], [inPassword cString]);
switch (checkpwresult) {
case CHECKPW_SUCCESS:
cpwresultstr = "Success";
break;
case CHECKPW_UNKNOWNUSER:
cpwresultstr = "Unknown User";
break;
case CHECKPW_BADPASSWORD:
cpwresultstr = "Bad Password";
break;
case CHECKPW_FAILURE:
cpwresultstr = "Failure";
break;
}
printf("\nCall to checkpw(): }
}
printf("\n\npath:
status = [self authenticateInNodePathStr:nodePathStr username:realUsername password:inPassword];
[pool release];
pool = nil;
}
printf("\n");
NS_HANDLER
[self deallocateDataBuffer:searchNodeBuffer];
[self deallocateDataList:searchNodeName];
[localException retain];
[pool release];
[[localException autorelease] raise];
NS_ENDHANDLER
return status;
}
// ------------------------------------------------------------------
// getListOfNodesWithUser:
//
// Searches the entire search path for a user named by the
// parameter. It returns an NSArray of NSStrings of the names
// of the nodes.
// ------------------------------------------------------------------
- (NSArray*)getListOfNodesWithUser:(NSString*)inUsername
{
NSMutableArray *nodePathStringList = [[NSMutableArray alloc] init];
tDataBufferPtr searchNodeBuffer = nil;
tDataListPtr searchNodeName = nil;
u_long i = 0;
unsigned long matchingUsers = 0;
searchNodeBuffer = [self retrieveSearchPathNode];
searchNodeName = [self getNodeNameForBuffer:searchNodeBuffer];
[self deallocateDataBuffer:searchNodeBuffer];
_SearchNodeRef = [self openDirNodeWithName:searchNodeName];
[self deallocateDataList:searchNodeName];
[self fetchRecordListOnNode:_SearchNodeRef matchingName:inUsername];
matchingUsers = [_MasterUserList count];
for (i=0; i < matchingUsers; i++)
[nodePathStringList addObject:[self nodePathStrForSearchNodeRecordNumber:i]];
return (NSArray*)[nodePathStringList autorelease];
}
@end