#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <pwd.h>
#include <ctype.h>
#include <regex.h>
#include <syslog.h> // for syslog() to log calls
#include <openssl/md5.h>
#include <openssl/sha.h>
#include <Security/Authorization.h>
#include "CNiPlugIn.h"
#include "CNetInfoPlugin.h"
#include "SMBAuth.h"
#include "CBuff.h"
#include "CSharedData.h"
#include "CString.h"
#include "CFile.h"
#include "NiLib2.h"
#include "NiLib3.h"
#include "DSUtils.h"
#include "DirServicesConst.h"
#include "DirServices.h"
#include "DirServicesUtils.h"
#include "ServerModuleLib.h"
#include "CRecTypeList.h"
#include "CRecNameList.h"
#include "SharedConsts.h"
#include "PrivateTypes.h"
#include "CPlugInRef.h"
#include "CContinue.h"
#include "CRCCalc.h"
#include "CDataBuff.h"
#include "CLog.h"
#include "TimConditional.h"
#include "my_ni_pwdomain.h"
#ifdef TIM_CLIENT_PRESENT
#include <TimClient/TimClient.h>
#endif
#define kAttrConsts 130
static const char *sAttrMap[ kAttrConsts ][ 2 ] =
{
{ kDSNAttrRecordName, "name" },
{ kDS1AttrDistinguishedName, "realname" },
{ kDS1AttrPassword, "passwd" },
{ kDS1AttrPasswordPlus, "passwd" }, { kDS1AttrUniqueID, "uid" },
{ kDS1AttrPrimaryGroupID, "gid" },
{ kDS1AttrUserShell, "shell" },
{ kDS1AttrNFSHomeDirectory, "home" },
{ kDSNAttrAuthenticationAuthority, "authentication_authority" },
{ kDSNAttrHomeDirectory, "home_loc" }, { kDS1AttrHomeLocOwner, "home_loc_owner" },
{ kDS1AttrHomeDirectoryQuota, "homedirectoryquota" },
{ kDS1AttrHomeDirectorySoftQuota, "homedirectorysoftquota" },
{ kDS1AttrPicture, "picture" },
{ kDS1AttrAuthenticationHint, "hint" },
{ kDS1AttrRARA, "RARA" },
{ kDS1AttrGeneratedUID, "generateduid" },
{ kDS1AttrRealUserID, "ruid" },
{ kDSNAttrGroupMembership, "users" },
{ kDSNAttrEMailAddress, "mail" },
{ kDS1AttrAlternateDatastoreLocation, "alternatedatastorelocation" },
{ kDSNAttrURL, "URL" },
{ kDSNAttrURLForNSL, "URL" },
{ kDSNAttrMIME, "mime" },
{ kDSNAttrHTML, "htmldata" },
{ kDSNAttrIPAddress, "IP_Address" },
{ kDS1AttrENetAddress, "en_address" },
{ kDSNAttrKeywords, "keywords" },
{ kDSNAttrComputers, "computers" },
{ kDS1AttrMCXFlags, "mcx_flags" },
{ kDS1AttrMCXSettings, "mcx_settings" },
{ kDSNAttrMCXSettings, "mcx_settings" },
{ kDS1AttrCopyTimestamp, "copy_timestamp" },
{ kDS1AttrOriginalNodeName, "original_node_name" },
{ kDS1AttrOriginalNFSHomeDirectory, "original_home" },
{ kDSNAttrOriginalHomeDirectory,"original_home_loc" },
{ kDS1AttrPasswordPolicyOptions,"passwordpolicyoptions" },
{ kDS1AttrPasswordServerList, "passwordserverlist" },
{ kDS1AttrXMLPlist, "XMLPlist" },
{ kDS1AttrDataStamp, "data_stamp" },
{ kDS1AttrPrintServiceInfoText, "PrintServiceInfoText" },
{ kDS1AttrPrintServiceInfoXML, "PrintServiceInfoXML" },
{ kDS1AttrPrintServiceUserData, "appleprintservice" },
{ kDS1AttrNote, "note" },
{ kDS1AttrPrinterLPRHost, "rm" },
{ kDS1AttrPrinterLPRQueue, "rp" },
{ kDS1AttrPrinterType, "ty" },
{ kDS1AttrPrinter1284DeviceID, "1284deviceid" },
{ kDS1AttrPrinterMakeAndModel, "makeandmodel" },
{ kDS1AttrPrinterURI, "uri" },
{ kDSNAttrPrinterXRISupported, "xrisupported" },
{ kDS1AttrVFSType, "vfstype" },
{ kDS1AttrVFSPassNo, "passno" },
{ kDS1AttrVFSDumpFreq, "dump_freq" },
{ kDS1AttrVFSLinkDir, "dir" },
{ kDSNAttrVFSOpts, "opts" },
{ kDS1AttrAliasData, "alias_data" },
{ kDSNAttrPhoneNumber, "phonenumber" },
{ kDSNAttrMember, "users" },
{ kDSNAttrAllNames, "dsAttrTypeStandard:AllNames" },
{ kStandardTargetAlias, "dsAttrTypeStandard:AppleMetaAliasTarget" },
{ kStandardSourceAlias, "dsAttrTypeStandard:AppleMetaAliasSource" },
{ kDSNAttrMetaNodeLocation, "dsAttrTypeStandard:AppleMetaNodeLocation" },
{ kDS1AttrComment, "comment" },
{ kDS1AttrChange, "change" },
{ kDS1AttrExpire, "expire" },
{ kDSNAttrGroup, "groups" },
{ kDS1AttrFirstName, "firstname" },
{ kDS1AttrMiddleName, "middlename" },
{ kDS1AttrLastName, "lastname" },
{ kDSNAttrAreaCode , "areacode" },
{ kDSNAttrAddressLine1, "address1" },
{ kDSNAttrAddressLine2, "address2" },
{ kDSNAttrAddressLine3, "address3" },
{ kDSNAttrCity, "city" },
{ kDSNAttrState, "state" },
{ kDSNAttrPostalCode, "zip" },
{ kDSNAttrOrganizationName, "orgname" },
{ kDS1AttrSetupOccupation, "occupation" },
{ kDSNAttrFaxNumber, "faxnumber" },
{ kDSNAttrMobileNumber, "mobilenumber" },
{ kDSNAttrPagerNumber, "pagernumber" },
{ kDSNAttrPostalAddress, "postaladdress" },
{ kDSNAttrStreet, "street" },
{ kDSNAttrDepartment, "department" },
{ kDSNAttrNickName, "nickname" },
{ kDSNAttrJobTitle, "jobtitle" },
{ kDSNAttrIMHandle, "imhandle" },
{ kDSNAttrBuilding, "building" },
{ kDSNAttrCountry, "country" },
{ kDSNAttrNamePrefix, "nameprefix" },
{ kDSNAttrNameSuffix, "namesuffix" },
{ kDS1AttrSetupLocation, "location" },
{ kDS1AttrSetupAdvertising, "spam" },
{ kDS1AttrSetupAutoRegister, "autoregister" },
{ kDSNAttrKDCAuthKey, "kdcauthkey" },
{ kDS1AttrKDCConfigData, "kdcconfigdata" },
{ kDS1AttrPresetUserIsAdmin, "preset_user_is_admin" },
{ kDS1AttrPasswordServerLocation, "passwordserverlocation" },
{ kDSNAttrBootParams, "bootparams" },
{ kDSNAttrNetGroups, "netgroups" },
{ kDS1AttrSMBRID, "smb_rid" },
{ kDS1AttrSMBGroupRID, "smb_group_rid" },
{ kDS1AttrSMBHomeDrive, "smb_home_drive" },
{ kDS1AttrSMBHome, "smb_home" },
{ kDS1AttrSMBScriptPath, "smb_script_path" },
{ kDS1AttrSMBProfilePath, "smb_profile_path" },
{ kDS1AttrSMBUserWorkstations, "smb_user_workstations" },
{ kDS1AttrSMBAcctFlags, "smb_acctFlags" },
{ kDS1AttrSMBPWDLastSet, "smb_pwd_last_set" },
{ kDS1AttrSMBLogonTime, "smb_logon_time" },
{ kDS1AttrSMBLogoffTime, "smb_logoff_time" },
{ kDS1AttrSMBKickoffTime, "smb_kickoff_time" },
{ kDS1AttrDNSDomain, "domain" },
{ kDS1AttrDNSNameServer, "nameserver" },
{ "dsAttrTypeStandard:NIAutoSwitchToLDAP", "niautoswitchtoldap" },
{ kDS1AttrLocation, "location" },
{ kDS1AttrPort, "port" },
{ kDS1AttrServiceType, "servicetype" },
{ kDSNAttrPGPPublicKey, "pgppublickey" },
{ kDS1AttrInternetAlias, "InetAlias" },
{ kDS1AttrMailAttribute, "applemail" },
{ kDSNAttrNBPEntry, "NBPEntry" },
{ kDSNAttrDNSName, "dnsname" },
{ kDS1AttrAdminStatus, "AdminStatus" },
{ kDS1AttrAdminLimits, "admin_limits" },
{ kDS1AttrCapabilities, "capabilities" },
{ kDSNAttrProtocols, "protocols" },
{ kDS1AttrPwdAgingPolicy, "PwdAgingPolicy" },
{ kDSNAttrRecordAlias, "RecordAlias" } };
#define kRecConsts 44
static const char *sRecMap[ kRecConsts ][ 2 ] =
{
{ kDSStdRecordTypeUsers, "users" },
{ kDSStdRecordTypeUserAliases, "user_aliases" },
{ kDSStdRecordTypeGroups, "groups" },
{ kDSStdRecordTypeGroupAliases, "group_aliases" },
{ kDSStdRecordTypeMachines, "machines" },
{ kDSStdRecordTypeComputers, "computers" },
{ kDSStdRecordTypeComputerLists, "computer_lists" },
{ kDSStdRecordTypePrinters, "printers" },
{ kDSStdRecordTypeHosts, "machines" },
{ kDSStdRecordTypeAliases, "aliases" },
{ kDSStdRecordTypeNetworks, "networks" },
{ kDSStdRecordTypeServer, "servers" },
{ kDSStdRecordTypePasswordServer, "passwordservers" },
{ kDSStdRecordTypeWebServer, "httpservers" },
{ kDSStdRecordTypeFTPServer, "ftpservers" },
{ kDSStdRecordTypeAFPServer, "afpservers" },
{ kDSStdRecordTypeLDAPServer, "ldapservers" },
{ kDSStdRecordTypeSMBServer, "smbservers" },
{ kDSStdRecordTypeQTSServer, "qtsservers" },
{ kDSStdRecordTypeNFS, "mounts" },
{ kDSStdRecordTypeServices, "services" },
{ kDSStdRecordTypePrintService, "PrintService" },
{ kDSStdRecordTypeConfig, "config" },
{ kDSStdUserNamesMeta, "dsRecTypeStandard:MetaUserNames" }, { kDSStdRecordTypeMeta, "dsRecTypeStandard:AppleMetaRecord" },
{ "dsRecTypeStandard:UsreNames", "users" }, { kDSStdRecordTypeAFPUserAliases, "afpuser_aliases" },
{ kDSStdRecordTypeMounts, "mounts" },
{ kDSStdRecordTypePrintServiceUser, "printserviceusers" },
{ kDSStdRecordTypePresetUsers, "presets_users" },
{ kDSStdRecordTypePresetGroups, "presets_groups" },
{ kDSStdRecordTypePresetComputerLists, "presets_computer_lists" },
{ kDSStdRecordTypeHosts, "hosts" },
{ kDSStdRecordTypeProtocols, "protocols" },
{ kDSStdRecordTypeRPC, "rpcs" },
{ kDSStdRecordTypeBootp, "bootp" },
{ kDSStdRecordTypeNetDomains, "netdomains" },
{ kDSStdRecordTypeEthernets, "ethernets" },
{ kDSStdRecordTypeNetGroups, "netgroups" },
{ kDSStdRecordTypeHostServices, "hostservices" },
{ kDSStdRecordTypeAutoServerSetup, "autoserversetup" },
{ kDSStdRecordTypeLocations, "locations" },
{ kDSStdRecordTypeSharePoints, "config/SharePoints" },
{ kDSStdRecordTypePeople, "people" }
};
typedef struct NetInfoAuthAuthorityHandler {
char* fTag;
NetInfoAuthAuthorityHandlerProc fHandler;
} NetInfoAuthAuthorityHandler;
#define kNetInfoAuthAuthorityHandlerProcs 6
static NetInfoAuthAuthorityHandler sNetInfoAuthAuthorityHandlerProcs[ kNetInfoAuthAuthorityHandlerProcs ] =
{
{ kDSTagAuthAuthorityBasic, (NetInfoAuthAuthorityHandlerProc)CNiPlugIn::DoBasicAuth },
{ kDSTagAuthAuthorityLocalWindowsHash, (NetInfoAuthAuthorityHandlerProc)CNiPlugIn::DoShadowHashAuth },
{ kDSTagAuthAuthorityShadowHash, (NetInfoAuthAuthorityHandlerProc)CNiPlugIn::DoShadowHashAuth },
{ kDSTagAuthAuthorityPasswordServer, (NetInfoAuthAuthorityHandlerProc)CNiPlugIn::DoPasswordServerAuth },
{ kDSTagAuthAuthorityDisabledUser, (NetInfoAuthAuthorityHandlerProc)CNiPlugIn::DoDisabledAuth },
{ kDSTagAuthAuthorityLocalCachedUser, (NetInfoAuthAuthorityHandlerProc)CNiPlugIn::DoLocalCachedUserAuth }
};
CPlugInRef *gNINodeRef = nil;
CContinue *gNIContinue = nil;
time_t gCheckTimAgainTime = 0;
bool gTimIsRunning = false;
static const uInt32 kNodeInfoBuffTag = 'NInf';
typedef enum
{
eHasAuthMethod = -7000,
eNoAuthServer = -7001,
eNoAuthMethods = -7002,
eAuthMethodNotFound = -7003
} eAuthValues;
CNiPlugIn::CNiPlugIn ( void )
{
if ( gNINodeRef == nil )
{
gNINodeRef = new CPlugInRef( CNiPlugIn::ContextDeallocProc );
}
if ( gNIContinue == nil )
{
gNIContinue = new CContinue( CNiPlugIn::ContinueDeallocProc );
}
fRecData = new CDataBuff();
fAttrData = new CDataBuff();
fTmpData = new CDataBuff();
}
CNiPlugIn::~CNiPlugIn ( void )
{
if ( fRecData != nil )
{
delete( fRecData );
fRecData = nil;
}
if ( fAttrData != nil )
{
delete( fAttrData );
fAttrData = nil;
}
if ( fTmpData != nil )
{
delete( fTmpData );
fTmpData = nil;
}
}
sInt32 CNiPlugIn::HandleRequest ( void *inData )
{
sInt32 siResult = 0;
sHeader *pMsgHdr = nil;
if ( inData == nil )
{
return( -8088 );
}
pMsgHdr = (sHeader *)inData;
switch ( pMsgHdr->fType )
{
case kReleaseContinueData:
siResult = ReleaseContinueData( (sReleaseContinueData *)inData );
break;
case kOpenDirNode:
siResult = OpenDirNode( (sOpenDirNode *)inData );
break;
case kCloseDirNode:
siResult = CloseDirNode( (sCloseDirNode *)inData );
break;
case kGetDirNodeInfo:
siResult = GetDirNodeInfo( (sGetDirNodeInfo *)inData );
break;
case kGetRecordList:
siResult = GetRecordList( (sGetRecordList *)inData );
break;
case kGetRecordEntry:
siResult = GetRecordEntry( (sGetRecordEntry *)inData );
break;
case kGetAttributeEntry:
siResult = GetAttributeEntry( (sGetAttributeEntry *)inData );
break;
case kGetAttributeValue:
siResult = GetAttributeValue( (sGetAttributeValue *)inData );
break;
case kCloseAttributeList:
siResult = CloseAttributeList( (sCloseAttributeList *)inData );
break;
case kCloseAttributeValueList:
siResult = CloseAttributeValueList( (sCloseAttributeValueList *)inData );
break;
case kOpenRecord:
siResult = OpenRecord( (sOpenRecord *)inData );
break;
case kGetRecordReferenceInfo:
siResult = GetRecRefInfo( (sGetRecRefInfo *)inData );
break;
case kGetRecordAttributeInfo:
siResult = GetRecAttribInfo( (sGetRecAttribInfo *)inData );
break;
case kGetRecordAttributeValueByID:
siResult = GetRecordAttributeValueByID( (sGetRecordAttributeValueByID *)inData );
break;
case kGetRecordAttributeValueByIndex:
siResult = GetRecAttrValueByIndex( (sGetRecordAttributeValueByIndex *)inData );
break;
case kCloseRecord:
siResult = CloseRecord( (sCloseRecord *)inData );
break;
case kSetRecordName:
siResult = SetRecordName( (sSetRecordName *)inData );
break;
case kSetRecordType:
siResult = SetRecordType( (sSetRecordType *)inData );
break;
case kDeleteRecord:
siResult = DeleteRecord( (sDeleteRecord *)inData );
break;
case kCreateRecord:
case kCreateRecordAndOpen:
siResult = CreateRecord( (sCreateRecord *)inData );
break;
case kAddAttribute:
siResult = AddAttribute( (sAddAttribute *)inData );
break;
case kRemoveAttribute:
siResult = RemoveAttribute( (sRemoveAttribute *)inData );
break;
case kAddAttributeValue:
siResult = AddAttributeValue( (sAddAttributeValue *)inData );
break;
case kRemoveAttributeValue:
siResult = RemoveAttributeValue( (sRemoveAttributeValue *)inData );
break;
case kSetAttributeValue:
siResult = SetAttributeValue( (sSetAttributeValue *)inData );
break;
case kDoDirNodeAuth:
siResult = DoAuthentication( (sDoDirNodeAuth *)inData );
break;
case kDoDirNodeAuthOnRecordType:
siResult = DoAuthenticationOnRecordType( (sDoDirNodeAuthOnRecordType *)inData );
break;
case kDoAttributeValueSearch:
case kDoAttributeValueSearchWithData:
siResult = DoAttributeValueSearch( (sDoAttrValueSearchWithData *)inData );
break;
case kDoPlugInCustomCall:
siResult = DoPlugInCustomCall( (sDoPlugInCustomCall *)inData );
break;
case kFlushRecord:
siResult = eDSNoErr;
break;
default:
siResult = eNotHandledByThisNode;
break;
}
pMsgHdr->fResult = siResult;
return( siResult );
}
sInt32 CNiPlugIn::ReleaseContinueData ( sReleaseContinueData *inData )
{
sInt32 siResult = eDSNoErr;
gNetInfoMutex->Wait();
if ( gNIContinue->RemoveItem( inData->fInContinueData ) != eDSNoErr )
{
siResult = eDSInvalidContext;
}
gNetInfoMutex->Signal();
return( siResult );
}
sInt32 CNiPlugIn::OpenDirNode ( sOpenDirNode *inData )
{
sInt32 siResult = eDSNoErr;
char *nameStr = nil;
char *pathStr = nil;
char *domName = nil;
void *domain = nil;
sInt32 timeOutSecs = 3;
sNIContextData *pContext = nil;
ni_id niRootDir;
try
{
nameStr = ::dsGetPathFromListPriv( inData->fInDirNodeName, kstrDelimiter );
if ( nameStr == nil ) throw( (sInt32)eDSNullNodeName );
pathStr = BuildDomainPathFromName( nameStr );
if ( pathStr == nil ) throw( (sInt32)eDSUnknownNodeName );
siResult = CNetInfoPlugin::SafeOpen( pathStr, timeOutSecs, &niRootDir, &domain, &domName );
if ( siResult != eDSNoErr ) throw( siResult );
if (::strcmp(domName,"") == 0)
{
siResult = eDSOpenNodeFailed;
if ( siResult != eDSNoErr ) throw( siResult );
}
pContext = MakeContextData();
if ( pContext == nil ) throw( (sInt32)eMemoryAllocError );
pContext->fDomain = domain;
pContext->fDomainName = domName; pContext->fUID = inData->fInUID;
pContext->fEffectiveUID = inData->fInEffectiveUID;
if (strcmp(pathStr,".") == 0)
{
pContext->bIsLocal = true;
}
gNINodeRef->AddItem( inData->fOutNodeRef, pContext );
}
catch( sInt32 err )
{
siResult = err;
}
if ( pathStr != nil )
{
free( pathStr );
pathStr = nil;
}
if ( nameStr != nil )
{
free( nameStr );
nameStr = nil;
}
return( siResult );
}
sInt32 CNiPlugIn::CloseDirNode ( sCloseDirNode *inData )
{
sInt32 siResult = NI_OK;
sNIContextData *pContext = nil;
try
{
pContext = (sNIContextData *)gNINodeRef->GetItemData( inData->fInNodeRef );
if ( pContext == nil ) throw( (sInt32)eDSInvalidNodeRef );
gNINodeRef->RemoveItem( inData->fInNodeRef );
gNIContinue->RemoveItems( inData->fInNodeRef );
}
catch( sInt32 err )
{
siResult = err;
}
return( siResult );
}
sInt32 CNiPlugIn::GetDirNodeInfo ( sGetDirNodeInfo *inData )
{
sInt32 siResult = eDSNoErr;
uInt32 uiOffset = 0;
#ifdef TIM_CLIENT_PRESENT
sInt32 siTimStatus = eDSNoErr;
TIMHandle *timHndl = nil;
Buffer *pTmp = nil;
Buffer *pTimInfo = nil;
uInt32 timAuthCount = 0;
char *pBuffStr = nil;
CString *pAuthStr = nil;
uInt32 timAuthAvail = 0;
#endif
uInt32 i = 0;
uInt32 authCount = 0;
uInt32 uiCntr = 1;
uInt32 uiAttrCnt = 0;
CAttributeList *inAttrList = nil;
char *pAttrName = nil;
char *pData = nil;
sNIContextData *pContext = nil;
sNIContextData *pAttrContext = nil;
char *niDomNameStr = nil;
tDataList *pNodePath = nil;
tDataNode *pDataNode = nil;
CBuff outBuff;
time_t delayedNI = 0;
gNetInfoMutex->Wait();
try
{
if ( inData == nil ) throw( (sInt32)eMemoryError );
pContext = (sNIContextData *)gNINodeRef->GetItemData( inData->fInNodeRef );
if ( pContext == nil ) throw( (sInt32)eDSInvalidNodeRef );
inAttrList = new CAttributeList( inData->fInDirNodeInfoTypeList );
if ( inAttrList == nil ) throw( (sInt32)eDSNullNodeInfoTypeList );
if (inAttrList->GetCount() == 0) throw( (sInt32)eDSEmptyNodeInfoTypeList );
siResult = outBuff.Initialize( inData->fOutDataBuff, true );
if ( siResult != eDSNoErr ) throw( siResult );
siResult = outBuff.SetBuffType( 'Gdni' ); if ( siResult != eDSNoErr ) throw( siResult );
fRecData->Clear();
fAttrData->Clear();
fRecData->AppendShort( ::strlen( "dsAttrTypeStandard:DirectoryNodeInfo" ) );
fRecData->AppendString( "dsAttrTypeStandard:DirectoryNodeInfo" );
fRecData->AppendShort( ::strlen( "DirectoryNodeInfo" ) );
fRecData->AppendString( "DirectoryNodeInfo" );
while ( inAttrList->GetAttribute( uiCntr++, &pAttrName ) == eDSNoErr )
{
if ( (::strcmp( pAttrName, kDSAttributesAll ) == 0) ||
(::strcmp( pAttrName, kDSNAttrAuthMethod ) == 0) )
{
fTmpData->Clear();
uiAttrCnt++;
fTmpData->AppendShort( ::strlen( kDSNAttrAuthMethod ) );
fTmpData->AppendString( kDSNAttrAuthMethod );
if ( inData->fInAttrInfoOnly == false )
{
#ifdef TIM_CLIENT_PRESENT
if ( IsTimRunning() )
{
authCount = 7;
timHndl = ::timServerForDomain( pContext->fDomain );
if ( timHndl != nil )
{
siTimStatus = ::timGetOperations( timHndl, TimOpAuthentication, &pTimInfo );
if ( siTimStatus == eDSNoErr )
{
timAuthCount = ::bufferArrayCount( pTimInfo );
if ( timAuthCount != 0 )
{
for ( i = 0; i < timAuthCount; i++ )
{
pTmp = ::bufferArrayBufferAtIndex( pTimInfo, i );
if ( pTmp != nil )
{
pBuffStr = ::bufferToString( pTmp );
pAuthStr = GetAuthTypeStr( pBuffStr );
if ( pAuthStr != nil )
{
if (strcmp(kDSStdAuth2WayRandom,pAuthStr->GetData()) == 0)
{
authCount++;
timAuthAvail |= 1;
}
if (strcmp(kDSStdAuthSMB_NT_Key,pAuthStr->GetData()) == 0)
{
authCount++;
timAuthAvail |= 2;
}
if (strcmp(kDSStdAuthSMB_LM_Key,pAuthStr->GetData()) == 0)
{
authCount++;
timAuthAvail |= 4;
}
delete( pAuthStr );
pAuthStr = nil;
}
::bufferRelease( pTmp );
pTmp = nil;
if ( pBuffStr != nil )
{
free( pBuffStr );
pBuffStr = nil;
}
}
}
}
}
if ( pTimInfo != nil )
{
::bufferRelease( pTimInfo );
pTimInfo = nil;
}
::timHandleFree( timHndl );
timHndl = nil;
}
fTmpData->AppendShort( authCount );
if (timAuthAvail & 1)
{
fTmpData->AppendLong( ::strlen( kDSStdAuth2WayRandom ) );
fTmpData->AppendString( kDSStdAuth2WayRandom );
}
if (timAuthAvail & 2)
{
fTmpData->AppendLong( ::strlen( kDSStdAuthSMB_NT_Key ) );
fTmpData->AppendString( kDSStdAuthSMB_NT_Key );
}
if (timAuthAvail & 4)
{
fTmpData->AppendLong( ::strlen( kDSStdAuthSMB_LM_Key ) );
fTmpData->AppendString( kDSStdAuthSMB_LM_Key );
}
}
else #endif
{
authCount = 7;
fTmpData->AppendShort( authCount );
}
fTmpData->AppendLong( ::strlen( kDSStdAuthClearText ) );
fTmpData->AppendString( kDSStdAuthClearText );
fTmpData->AppendLong( ::strlen( kDSStdAuthCrypt ) );
fTmpData->AppendString( kDSStdAuthCrypt );
fTmpData->AppendLong( ::strlen( kDSStdAuthSetPasswd ) );
fTmpData->AppendString( kDSStdAuthSetPasswd );
fTmpData->AppendLong( ::strlen( kDSStdAuthChangePasswd ) );
fTmpData->AppendString( kDSStdAuthChangePasswd );
fTmpData->AppendLong( ::strlen( kDSStdAuthSetPasswdAsRoot ) );
fTmpData->AppendString( kDSStdAuthSetPasswdAsRoot );
fTmpData->AppendLong( ::strlen( kDSStdAuthNodeNativeClearTextOK ) );
fTmpData->AppendString( kDSStdAuthNodeNativeClearTextOK );
fTmpData->AppendLong( ::strlen( kDSStdAuthNodeNativeNoClearText ) );
fTmpData->AppendString( kDSStdAuthNodeNativeNoClearText );
}
else
{
fTmpData->AppendShort( 0 );
}
fAttrData->AppendLong( fTmpData->GetLength() );
fAttrData->AppendBlock( fTmpData->GetData(), fTmpData->GetLength() );
fTmpData->Clear();
}
if ( (::strcmp( pAttrName, kDSAttributesAll ) == 0) ||
(::strcmp( pAttrName, kDS1AttrReadOnlyNode ) == 0) )
{
fTmpData->Clear();
uiAttrCnt++;
fTmpData->AppendShort( ::strlen( kDS1AttrReadOnlyNode ) );
fTmpData->AppendString( kDS1AttrReadOnlyNode );
if ( inData->fInAttrInfoOnly == false )
{
fTmpData->AppendShort( 1 );
fTmpData->AppendLong( ::strlen( "ReadWrite" ) );
fTmpData->AppendString( "ReadWrite" );
}
else
{
fTmpData->AppendShort( 0 );
}
fAttrData->AppendLong( fTmpData->GetLength() );
fAttrData->AppendBlock( fTmpData->GetData(), fTmpData->GetLength() );
fTmpData->Clear();
}
if ( (::strcmp( pAttrName, kDSAttributesAll ) == 0) ||
(::strcmp( pAttrName, kDSNAttrNodePath ) == 0) )
{
delayedNI = time(nil) + 2; siResult = ::my_ni_pwdomain( pContext->fDomain, &niDomNameStr );
if ( delayedNI < time(nil) )
{
if (pContext->fDomainName != nil)
{
syslog(LOG_INFO,"GetDirNodeInfo::Call to my_ni_pwdomain was with argument domain name: %s and lasted %d seconds.", pContext->fDomainName, (uInt32)(2 + time(nil) - delayedNI));
}
else
{
syslog(LOG_INFO,"GetDirNodeInfo::Call to my_ni_pwdomain lasted %d seconds.", (uInt32)(2 + time(nil) - delayedNI));
}
if (niDomNameStr != nil)
{
syslog(LOG_INFO,"GetDirNodeInfo::Call to my_ni_pwdomain returned domain name: %s.", niDomNameStr);
}
}
if ( ( siResult != eDSNoErr ) || (niDomNameStr == nil) )
{
syslog(LOG_INFO,"GetDirNodeInfo::Call to my_ni_pwdomain failed or returned nil name.");
niDomNameStr = (char *) calloc(1,2);
strcpy(niDomNameStr,"/");
}
if (niDomNameStr != nil)
{
fTmpData->Clear();
uiAttrCnt++;
fTmpData->AppendShort( ::strlen( kDSNAttrNodePath ) );
fTmpData->AppendString( kDSNAttrNodePath );
if ( inData->fInAttrInfoOnly == false )
{
if ( ::strcmp( niDomNameStr, "/" ) == 0 )
{
fTmpData->AppendShort( 2 );
fTmpData->AppendLong( ::strlen( kstrNetInfoName ) );
fTmpData->AppendString( kstrNetInfoName );
fTmpData->AppendLong( ::strlen( kstrRootOnly ) );
fTmpData->AppendString( kstrRootOnly );
}
else
{
pNodePath = ::dsBuildFromPathPriv( niDomNameStr, "/" );
if ( pNodePath == nil ) throw( (sInt32)eMemoryAllocError );
fTmpData->AppendShort( ::dsDataListGetNodeCountPriv( pNodePath ) + 2 );
fTmpData->AppendLong( ::strlen( kstrNetInfoName ) );
fTmpData->AppendString( kstrNetInfoName );
fTmpData->AppendLong( ::strlen( kstrRootOnly ) );
fTmpData->AppendString( kstrRootOnly );
i = 1;
while ( ::dsDataListGetNodeAllocPriv( pNodePath, i, &pDataNode ) == eDSNoErr )
{
fTmpData->AppendLong( ::strlen( pDataNode->fBufferData ) );
fTmpData->AppendString( pDataNode->fBufferData );
::dsDataBufferDeallocatePriv( pDataNode );
pDataNode = nil;
i++;
}
::dsDataListDeallocatePriv( pNodePath );
free( pNodePath );
pNodePath = nil;
}
}
else
{
fTmpData->AppendShort( 0 );
}
fAttrData->AppendLong( fTmpData->GetLength() );
fAttrData->AppendBlock( fTmpData->GetData(), fTmpData->GetLength() );
fTmpData->Clear();
free(niDomNameStr);
niDomNameStr = nil;
}
}
}
fRecData->AppendShort( uiAttrCnt );
fRecData->AppendBlock( fAttrData->GetData(), fAttrData->GetLength() );
outBuff.AddData( fRecData->GetData(), fRecData->GetLength() );
inData->fOutAttrInfoCount = uiAttrCnt;
pData = outBuff.GetDataBlock( 1, &uiOffset );
if ( pData != nil )
{
pAttrContext = MakeContextData();
if ( pAttrContext == nil ) throw( (sInt32)eMemoryAllocError );
pAttrContext->offset = uiOffset + 61;
gNINodeRef->AddItem( inData->fOutAttrListRef, pAttrContext );
}
else
{
siResult = eDSBufferTooSmall;
}
}
catch( sInt32 err )
{
siResult = err;
}
gNetInfoMutex->Signal();
if ( inAttrList != nil )
{
delete( inAttrList );
inAttrList = nil;
}
return( siResult );
}
sInt32 CNiPlugIn::GetAttributeEntry ( sGetAttributeEntry *inData )
{
sInt32 siResult = eDSNoErr;
uInt16 usAttrTypeLen = 0;
uInt16 usAttrCnt = 0;
uInt32 usAttrLen = 0;
uInt16 usValueCnt = 0;
uInt32 usValueLen = 0;
uInt32 i = 0;
uInt32 uiIndex = 0;
uInt32 uiAttrEntrySize = 0;
uInt32 uiOffset = 0;
uInt32 uiTotalValueSize = 0;
uInt32 offset = 0;
uInt32 buffSize = 0;
uInt32 buffLen = 0;
char *p = nil;
char *pAttrType = nil;
tDataBuffer *pDataBuff = nil;
tAttributeValueListRef attrValueListRef = 0;
tAttributeEntryPtr pAttribInfo = nil;
sNIContextData *pAttrContext = nil;
sNIContextData *pValueContext = nil;
try
{
if ( inData == nil ) throw( (sInt32)eMemoryError );
pAttrContext = (sNIContextData *)gNINodeRef->GetItemData( inData->fInAttrListRef );
if ( pAttrContext == nil ) throw( (sInt32)eDSBadContextData );
uiIndex = inData->fInAttrInfoIndex;
if (uiIndex == 0) throw( (sInt32)eDSInvalidIndex );
pDataBuff = inData->fInOutDataBuff;
if ( pDataBuff == nil ) throw( (sInt32)eDSNullDataBuff );
buffSize = pDataBuff->fBufferSize;
p = pDataBuff->fBufferData + pAttrContext->offset;
offset = pAttrContext->offset;
if (2 + offset > buffSize) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &usAttrCnt, p, 2 );
if (uiIndex > usAttrCnt) throw( (sInt32)eDSInvalidIndex );
p += 2;
offset += 2;
for ( i = 1; i < uiIndex; i++ )
{
if (4 + offset > buffSize) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &usAttrLen, p, 4 );
p += 4 + usAttrLen;
offset += 4 + usAttrLen;
}
uiOffset = offset;
if (4 + offset > buffSize) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &usAttrLen, p, 4 );
p += 4;
offset += 4;
buffLen = offset + usAttrLen;
if (2 + offset > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &usAttrTypeLen, p, 2 );
pAttrType = p + 2;
p += 2 + usAttrTypeLen;
offset += 2 + usAttrTypeLen;
if (2 + offset > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &usValueCnt, p, 2 );
p += 2;
offset += 2;
for ( i = 0; i < usValueCnt; i++ )
{
if (4 + offset > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &usValueLen, p, 4 );
p += 4 + usValueLen;
offset += 4 + usValueLen;
uiTotalValueSize += usValueLen;
}
uiAttrEntrySize = sizeof( tAttributeEntry ) + usAttrTypeLen + kBuffPad;
pAttribInfo = (tAttributeEntry *)::calloc( 1, uiAttrEntrySize );
pAttribInfo->fAttributeValueCount = usValueCnt;
pAttribInfo->fAttributeDataSize = uiTotalValueSize;
pAttribInfo->fAttributeValueMaxSize = 512; pAttribInfo->fAttributeSignature.fBufferSize = usAttrTypeLen + kBuffPad;
pAttribInfo->fAttributeSignature.fBufferLength = usAttrTypeLen;
::memcpy( pAttribInfo->fAttributeSignature.fBufferData, pAttrType, usAttrTypeLen );
attrValueListRef = inData->fOutAttrValueListRef;
pValueContext = MakeContextData();
if ( pValueContext == nil ) throw( (sInt32)eMemoryAllocError );
pValueContext->offset = uiOffset;
gNINodeRef->AddItem( inData->fOutAttrValueListRef, pValueContext );
inData->fOutAttrInfoPtr = pAttribInfo;
}
catch( sInt32 err )
{
siResult = err;
}
return( siResult );
}
sInt32 CNiPlugIn::GetRecordEntry ( sGetRecordEntry *inData )
{
sInt32 siResult = eDSNoErr;
uInt32 uiIndex = 0;
uInt32 uiCount = 0;
uInt32 uiOffset = 0;
uInt32 uberOffset = 0;
char *pData = nil;
tRecordEntryPtr pRecEntry = nil;
sNIContextData *pContext = nil;
CBuff inBuff;
uInt32 offset = 0;
uInt16 usTypeLen = 0;
char *pRecType = nil;
uInt16 usNameLen = 0;
char *pRecName = nil;
uInt16 usAttrCnt = 0;
uInt32 buffLen = 0;
try
{
if ( inData == nil ) throw( (sInt32)eMemoryError );
if ( inData->fInOutDataBuff == nil ) throw( (sInt32)eDSEmptyBuffer );
if (inData->fInOutDataBuff->fBufferSize == 0) throw( (sInt32)eDSEmptyBuffer );
siResult = inBuff.Initialize( inData->fInOutDataBuff );
if ( siResult != eDSNoErr ) throw( siResult );
siResult = inBuff.GetDataBlockCount( &uiCount );
if ( siResult != eDSNoErr ) throw( siResult );
uiIndex = inData->fInRecEntryIndex;
if ((uiIndex > uiCount) || (uiIndex == 0)) throw( (sInt32)eDSInvalidIndex );
pData = inBuff.GetDataBlock( uiIndex, &uberOffset );
if ( pData == nil ) throw( (sInt32)eDSCorruptBuffer );
buffLen = inBuff.GetDataBlockLength( uiIndex );
pData += 4;
offset = 0;
if (2 + offset > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &usTypeLen, pData, 2 );
pData += 2;
offset += 2;
pRecType = pData;
pData += usTypeLen;
offset += usTypeLen;
if (2 + offset > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &usNameLen, pData, 2 );
pData += 2;
offset += 2;
pRecName = pData;
pData += usNameLen;
offset += usNameLen;
if (2 + offset > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &usAttrCnt, pData, 2 );
pRecEntry = (tRecordEntry *)::calloc( 1, sizeof( tRecordEntry ) + usNameLen + usTypeLen + 4 + kBuffPad );
pRecEntry->fRecordNameAndType.fBufferSize = usNameLen + usTypeLen + 4 + kBuffPad;
pRecEntry->fRecordNameAndType.fBufferLength = usNameLen + usTypeLen + 4;
::memcpy( pRecEntry->fRecordNameAndType.fBufferData, &usNameLen, 2 );
uiOffset += 2;
::memcpy( pRecEntry->fRecordNameAndType.fBufferData + uiOffset, pRecName, usNameLen );
uiOffset += usNameLen;
::memcpy( pRecEntry->fRecordNameAndType.fBufferData + uiOffset, &usTypeLen, 2 );
uiOffset += 2;
::memcpy( pRecEntry->fRecordNameAndType.fBufferData + uiOffset, pRecType, usTypeLen );
pRecEntry->fRecordAttributeCount = usAttrCnt;
pContext = MakeContextData();
if ( pContext == nil ) throw( (sInt32)eMemoryAllocError );
pContext->offset = uberOffset + offset + 4;
gNINodeRef->AddItem( inData->fOutAttrListRef, pContext );
inData->fOutRecEntryPtr = pRecEntry;
}
catch( sInt32 err )
{
siResult = err;
}
return( siResult );
}
sInt32 CNiPlugIn::GetRecordList ( sGetRecordList *inData )
{
sInt32 siResult = eDSNoErr;
uInt32 uiTotal = 0;
uInt32 uiCount = 0;
char *pRecName = nil;
char *pRecType = nil;
char *pNIRecType = nil;
bool bAttribOnly = false;
tDirPatternMatch pattMatch = eDSNoMatch1;
CRecNameList *cpRecNameList = nil;
CRecTypeList *cpRecTypeList = nil;
CAttributeList *cpAttrTypeList = nil;
sNIContextData *pContext = nil;
sNIContinueData *pContinue = nil;
CBuff *outBuff = nil;
bool bBuffFull = false;
bool separateRecTypes = false;
uInt32 countDownRecTypes = 0;
try
{
if ( inData == nil ) throw( (sInt32)eMemoryError );
if ( inData->fInDataBuff == nil ) throw( (sInt32)eDSEmptyBuffer );
if (inData->fInDataBuff->fBufferSize == 0) throw( (sInt32)eDSEmptyBuffer );
if ( inData->fInRecNameList == nil ) throw( (sInt32)eDSEmptyRecordNameList );
if ( inData->fInRecTypeList == nil ) throw( (sInt32)eDSEmptyRecordTypeList );
if ( inData->fInAttribTypeList == nil ) throw( (sInt32)eDSEmptyAttributeTypeList );
pContext = (sNIContextData *)gNINodeRef->GetItemData( inData->fInNodeRef );
if ( pContext == nil ) throw( (sInt32)eDSInvalidNodeRef );
if ( inData->fIOContinueData == nil )
{
pContinue = (sNIContinueData *)::calloc( sizeof( sNIContinueData ), sizeof( char ) );
gNIContinue->AddItem( pContinue, inData->fInNodeRef );
pContinue->fRecNameIndex = 1;
pContinue->fAllRecIndex = 0;
pContinue->fTotalRecCount = 0;
pContinue->fMultiMapIndex = 0;
pContinue->fRecTypeIndex = 1;
pContinue->fAttrIndex = 1;
pContinue->fLimitRecSearch = 0;
if (inData->fOutRecEntryCount >= 0)
{
pContinue->fLimitRecSearch = inData->fOutRecEntryCount;
}
}
else
{
pContinue = (sNIContinueData *)inData->fIOContinueData;
if ( gNIContinue->VerifyItem( pContinue ) == false )
{
throw( (sInt32)eDSInvalidContinueData );
}
}
inData->fIOContinueData = nil;
inData->fOutRecEntryCount = 0;
outBuff = new CBuff();
if ( outBuff == nil ) throw( (sInt32)eMemoryError );
siResult = outBuff->Initialize( inData->fInDataBuff, true );
if ( siResult != eDSNoErr ) throw( siResult );
siResult = outBuff->GetBuffStatus();
if ( siResult != eDSNoErr ) throw( siResult );
siResult = outBuff->SetBuffType( 'StdA' );
if ( siResult != eDSNoErr ) throw( siResult );
cpRecNameList = new CRecNameList( inData->fInRecNameList );
if ( cpRecNameList == nil ) throw( (sInt32)eDSEmptyRecordNameList );
if (cpRecNameList->GetCount() == 0) throw( (sInt32)eDSEmptyRecordNameList );
pattMatch = inData->fInPatternMatch;
siResult = VerifyPatternMatch( pattMatch );
if ( siResult != eDSNoErr ) throw( (sInt32)eDSInvalidPatternMatchType );
cpRecTypeList = new CRecTypeList( inData->fInRecTypeList );
if ( cpRecTypeList == nil ) throw( (sInt32)eDSEmptyRecordTypeList );
if (cpRecTypeList->GetCount() == 0) throw( (sInt32)eDSEmptyRecordTypeList );
countDownRecTypes = cpRecTypeList->GetCount() - pContinue->fRecTypeIndex + 1;
cpAttrTypeList = new CAttributeList( inData->fInAttribTypeList );
if ( cpAttrTypeList == nil ) throw( (sInt32)eDSEmptyAttributeTypeList );
if (cpAttrTypeList->GetCount() == 0) throw( (sInt32)eDSEmptyAttributeTypeList );
bAttribOnly = inData->fInAttribInfoOnly;
while ( ( cpRecTypeList->GetAttribute( pContinue->fRecTypeIndex, &pRecType ) == eDSNoErr ) &&
(!bBuffFull) && (!separateRecTypes) )
{
pNIRecType = MapRecToNetInfoType( pRecType );
if ( pNIRecType != nil )
{
while ( (cpRecNameList->GetAttribute( pContinue->fRecNameIndex, &pRecName ) == eDSNoErr) &&
(siResult == eDSNoErr) && (!bBuffFull) )
{
bBuffFull = false;
if ( ::strcmp( pRecName, kDSRecordsAll ) == 0 )
{
siResult = GetAllRecords( pNIRecType,
cpAttrTypeList,
pContinue,
pContext->fDomain,
pContext->fDomainName,
bAttribOnly,
outBuff,
uiCount );
}
else
{
siResult = GetTheseRecords ( pRecName,
pRecType,
pNIRecType,
pattMatch,
cpAttrTypeList,
pContext->fDomain,
pContext->fDomainName,
bAttribOnly,
outBuff,
pContinue,
uiCount );
}
if ( siResult == CBuff::kBuffFull )
{
bBuffFull = true;
inData->fIOContinueData = pContinue;
if ( ( uiCount == 0 ) && ( uiTotal == 0 ) )
{
throw( (sInt32)eDSBufferTooSmall );
}
uiTotal += uiCount;
inData->fOutRecEntryCount = uiTotal;
outBuff->SetLengthToSize();
siResult = eDSNoErr;
}
else if ( siResult == eDSNoErr )
{
uiTotal += uiCount;
pContinue->fRecNameIndex++;
}
} delete( pNIRecType );
pNIRecType = nil;
}
else
{
siResult = eDSInvalidRecordType;
}
if ( !bBuffFull )
{
pRecType = nil;
pContinue->fRecTypeIndex++;
pContinue->fRecNameIndex = 1;
separateRecTypes = true;
inData->fIOContinueData = pContinue;
if ( pContinue->fNIEntryList.ni_entrylist_len > 0 )
{
::ni_entrylist_free(&(pContinue->fNIEntryList));
pContinue->fNIEntryList.ni_entrylist_len = 0;
}
siResult = eDSNoErr;
countDownRecTypes--;
if ( countDownRecTypes == 0 )
{
inData->fIOContinueData = nil;
}
}
}
if ( (siResult == eDSNoErr) && (!bBuffFull) )
{
if ( uiTotal == 0 )
{
outBuff->ClearBuff();
}
else
{
outBuff->SetLengthToSize();
}
inData->fOutRecEntryCount = uiTotal;
}
}
catch( sInt32 err )
{
siResult = err;
}
if ( (inData->fIOContinueData == nil) && (pContinue != nil) )
{
gNetInfoMutex->Wait();
gNIContinue->RemoveItem( pContinue );
gNetInfoMutex->Signal();
pContinue = nil;
}
if ( cpRecNameList != nil )
{
delete( cpRecNameList );
cpRecNameList = nil;
}
if ( cpRecTypeList != nil )
{
delete( cpRecTypeList );
cpRecTypeList = nil;
}
if ( cpAttrTypeList != nil )
{
delete( cpAttrTypeList );
cpAttrTypeList = nil;
}
if ( outBuff != nil )
{
delete( outBuff );
outBuff = nil;
}
if ( pNIRecType != nil )
{
delete( pNIRecType );
pNIRecType = nil;
}
return( siResult );
}
sInt32 CNiPlugIn::GetAllRecords ( char *inNI_RecType,
CAttributeList *inAttrTypeList,
sNIContinueData *inContinue,
void *inDomain,
char *inDomainName,
bool inAttrOnly,
CBuff *inBuff,
uInt32 &outRecCount )
{
sInt32 siResult = eDSNoErr;
sInt32 siValCnt = 0;
char *pDS_RecType = 0;
u_int en = 0;
ni_index niIndex = 0;
ni_id niDirID;
ni_entry niEntry;
ni_proplist niPropList;
ni_entrylist niEntryList;
gNetInfoMutex->Wait();
try
{
NI_INIT( &niDirID );
NI_INIT( &niEntry );
NI_INIT( &niPropList );
NI_INIT( &niEntryList );
outRecCount = 0;
siResult = ::ni_pathsearch( inDomain, &niDirID, inNI_RecType );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
if ( inContinue->fNIEntryList.ni_entrylist_len == 0 )
{
siResult = ::ni_list( inDomain, &niDirID, "name", &(inContinue->fNIEntryList) );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
}
niEntryList = inContinue->fNIEntryList;
for ( en = inContinue->fAllRecIndex; (en < niEntryList.ni_entrylist_len) &&
(((inContinue->fTotalRecCount) < inContinue->fLimitRecSearch) ||
(inContinue->fLimitRecSearch == 0)); en++ )
{
niEntry = niEntryList.ni_entrylist_val[ en ];
niDirID.nii_object = niEntry.id;
siResult = ::ni_read( inDomain, &niDirID, &niPropList );
if ( siResult == NI_OK )
{
siResult = GetTheseAttributes( inAttrTypeList, &niPropList, inAttrOnly, inDomain, inDomainName, siValCnt );
if ( siResult == eDSNoErr )
{
fRecData->Clear();
pDS_RecType = MapNetInfoRecToDSType( inNI_RecType );
if ( pDS_RecType != nil )
{
fRecData->AppendShort( ::strlen( pDS_RecType ) );
fRecData->AppendString( pDS_RecType );
delete( pDS_RecType );
pDS_RecType = nil;
}
niIndex = ::ni_proplist_match( niPropList, "name", NULL );
if ( niIndex == NI_INDEX_NULL || niPropList.nipl_val[ niIndex ].nip_val.ninl_len == 0 )
{
fRecData->AppendShort( ::strlen( "*** No Name ***" ) );
fRecData->AppendString( "*** No Name ***" );
}
else
{
fRecData->AppendShort( ::strlen( niPropList.nipl_val[ niIndex ].nip_val.ninl_val[ 0 ] ) );
fRecData->AppendString( niPropList.nipl_val[ niIndex ].nip_val.ninl_val[ 0 ] );
}
if ( siValCnt == 0 )
{
fRecData->AppendShort( 0 );
}
else
{
fRecData->AppendShort( siValCnt );
fRecData->AppendBlock( fAttrData->GetData(), fAttrData->GetLength() );
}
siResult = inBuff->AddData( fRecData->GetData(), fRecData->GetLength() );
if ( siResult == CBuff::kBuffFull )
{
inContinue->fAllRecIndex = en;
::ni_proplist_free( &niPropList );
break;
}
else if ( siResult == eDSNoErr )
{
outRecCount++;
inContinue->fTotalRecCount++;
}
else
{
inContinue->fAllRecIndex = 0;
::ni_proplist_free( &niPropList );
siResult = eDSInvalidBuffFormat;
break;
}
}
::ni_proplist_free( &niPropList );
}
}
if ( siResult == eDSNoErr )
{
inContinue->fAllRecIndex = 0;
}
}
catch( sInt32 err )
{
siResult = err;
}
gNetInfoMutex->Signal();
return( siResult );
}
sInt32 CNiPlugIn:: GetTheseRecords ( char *inConstRecName,
char *inConstRecType,
char *inNativeRecType,
tDirPatternMatch inPattMatch,
CAttributeList *inAttrTypeList,
void *inDomain,
char *inDomainName,
bool inAttrOnly,
CBuff *inBuff,
sNIContinueData *inContinue,
uInt32 &outRecCount )
{
sInt32 siResult = eDSNoErr;
sInt32 siCount = 0;
u_int en = 0;
ni_status niStatus = NI_OK;
ni_index niIndex = 0;
ni_index niIndexComp = 0;
ni_id niDirID;
ni_proplist niPropList;
ni_entry niEntry;
ni_entrylist niEntryList;
bool bGetThisOne = true;
char *inConstRegExpRecName = nil;
bool bGotAMatch = false;
gNetInfoMutex->Wait();
try
{
NI_INIT( &niDirID );
NI_INIT( &niEntry );
NI_INIT( &niPropList );
NI_INIT( &niEntryList );
outRecCount = 0;
fRecData->Clear();
if ( (::strcmp( inNativeRecType, "users" ) == 0 ) &&
((inContinue->fMultiMapIndex == 0) || (inContinue->fMultiMapIndex == 2) || (inContinue->fMultiMapIndex == 3)) )
{
niStatus = ::ni_pathsearch( inDomain, &niDirID, "/users" );
if ( niStatus == NI_OK )
{
inConstRegExpRecName = BuildRegExp(inConstRecName);
niStatus = ::ni_search( inDomain, &niDirID, (char *)"name", inConstRegExpRecName, REG_ICASE, &niEntryList );
free(inConstRegExpRecName);
if ( (niStatus == NI_OK) &&
((inContinue->fMultiMapIndex == 0) || (inContinue->fMultiMapIndex == 2)) )
{
for ( en = inContinue->fAllRecIndex; (en < niEntryList.ni_entrylist_len) &&
(((inContinue->fTotalRecCount) < inContinue->fLimitRecSearch) ||
(inContinue->fLimitRecSearch == 0)); en++ )
{
niEntry = niEntryList.ni_entrylist_val[ en ];
niDirID.nii_object = niEntry.id;
niStatus = ::ni_read( inDomain, &niDirID, &niPropList );
if ( niStatus == NI_OK )
{
niIndex = ::ni_proplist_match( niPropList, "name", NULL );
if ( niIndex != NI_INDEX_NULL )
{
bGotAMatch = false;
for ( uInt32 pv = 0; pv < niPropList.nipl_val[ niIndex ].nip_val.ninl_len; pv++ )
{
if ( DoesThisMatch( (const char*)(niPropList.nipl_val[ niIndex ].nip_val.ninl_val[ pv ]),
(const char*)inConstRecName,
inPattMatch ) )
{
bGotAMatch = true;
break;
}
}
if (bGotAMatch)
{
fRecData->AppendShort( ::strlen( inConstRecType ) );
fRecData->AppendString( inConstRecType );
niIndex = ::ni_proplist_match( niPropList, "name", NULL );
if ( niIndex == NI_INDEX_NULL || niPropList.nipl_val[ niIndex ].nip_val.ninl_len == 0 )
{
fRecData->AppendShort( ::strlen( "*** No Name ***" ) );
fRecData->AppendString( "*** No Name ***" );
}
else
{
fRecData->AppendShort( ::strlen( niPropList.nipl_val[ niIndex ].nip_val.ninl_val[ 0 ] ) );
fRecData->AppendString( niPropList.nipl_val[ niIndex ].nip_val.ninl_val[ 0 ] );
}
siResult = GetTheseAttributes( inAttrTypeList, &niPropList, inAttrOnly, inDomain, inDomainName, siCount );
if ( siResult == eDSNoErr )
{
if ( siCount == 0 )
{
fRecData->AppendShort( 0 );
}
else
{
fRecData->AppendShort( siCount );
fRecData->AppendBlock( fAttrData->GetData(), fAttrData->GetLength() );
}
siResult = inBuff->AddData( fRecData->GetData(), fRecData->GetLength() );
fRecData->Clear();
if ( siResult == CBuff::kBuffFull )
{
inContinue->fMultiMapIndex = 2;
inContinue->fAllRecIndex = en;
::ni_proplist_free( &niPropList );
throw( siResult );
}
else if ( siResult == eDSNoErr )
{
inContinue->fMultiMapIndex = 0;
outRecCount++;
inContinue->fTotalRecCount++;
}
else
{
inContinue->fMultiMapIndex = 0;
::ni_proplist_free( &niPropList );
throw( (sInt32)eDSInvalidBuffFormat );
}
} } }
::ni_proplist_free( &niPropList );
}
} }
if (niEntryList.ni_entrylist_len > 0)
{
::ni_entrylist_free( &niEntryList );
niEntryList.ni_entrylist_len = 0;
}
NI_INIT( &niEntryList );
if ( (inContinue->fTotalRecCount < inContinue->fLimitRecSearch) || (inContinue->fLimitRecSearch == 0) )
{
NI_INIT( &niDirID );
niStatus = ::ni_pathsearch( inDomain, &niDirID, "/users" );
if ( niStatus == NI_OK )
{
inConstRegExpRecName = BuildRegExp(inConstRecName);
niStatus = ::ni_search( inDomain, &niDirID, (char *)"realname", inConstRegExpRecName, REG_ICASE, &niEntryList );
free(inConstRegExpRecName);
if ( (niStatus == NI_OK) &&
((inContinue->fMultiMapIndex == 0) || (inContinue->fMultiMapIndex == 3)) )
{
for ( en = inContinue->fAllRecIndex; (en < niEntryList.ni_entrylist_len) &&
(((inContinue->fTotalRecCount) < inContinue->fLimitRecSearch) ||
(inContinue->fLimitRecSearch == 0)); en++ )
{
niEntry = niEntryList.ni_entrylist_val[ en ];
niDirID.nii_object = niEntry.id;
niStatus = ::ni_read( inDomain, &niDirID, &niPropList );
if ( niStatus == NI_OK )
{
niIndex = ::ni_proplist_match( niPropList, "realname", NULL );
if ( niIndex != NI_INDEX_NULL )
{
bGotAMatch = false;
for ( uInt32 pv = 0; pv < niPropList.nipl_val[ niIndex ].nip_val.ninl_len; pv++ )
{
if ( DoesThisMatch( (const char*)(niPropList.nipl_val[ niIndex ].nip_val.ninl_val[ pv ]),
(const char*)inConstRecName,
inPattMatch ) )
{
bGotAMatch = true;
break;
}
}
if (bGotAMatch)
{
bGetThisOne = true;
niIndexComp = ::ni_proplist_match( niPropList, "name", NULL );
if ( niIndexComp != NI_INDEX_NULL )
{
for ( uInt32 pv = 0; pv < niPropList.nipl_val[ niIndexComp ].nip_val.ninl_len; pv++ )
{
if ( DoesThisMatch( (const char*)(niPropList.nipl_val[ niIndexComp ].nip_val.ninl_val[ pv ]),
(const char*)inConstRecName,
inPattMatch ) )
{
bGetThisOne = false;
break;
}
}
}
if (bGetThisOne)
{
fRecData->AppendShort( ::strlen( inConstRecType ) );
fRecData->AppendString( inConstRecType );
niIndex = ::ni_proplist_match( niPropList, "name", NULL );
if ( niIndex == NI_INDEX_NULL || niPropList.nipl_val[ niIndex ].nip_val.ninl_len == 0 )
{
fRecData->AppendShort( ::strlen( "*** No Name ***" ) );
fRecData->AppendString( "*** No Name ***" );
}
else
{
fRecData->AppendShort( ::strlen( niPropList.nipl_val[ niIndex ].nip_val.ninl_val[ 0 ] ) );
fRecData->AppendString( niPropList.nipl_val[ niIndex ].nip_val.ninl_val[ 0 ] );
}
siResult = GetTheseAttributes( inAttrTypeList, &niPropList, inAttrOnly, inDomain, inDomainName, siCount );
if ( siResult == eDSNoErr )
{
if ( siCount == 0 )
{
fRecData->AppendShort( 0 );
}
else
{
fRecData->AppendShort( siCount );
fRecData->AppendBlock( fAttrData->GetData(), fAttrData->GetLength() );
}
siResult = inBuff->AddData( fRecData->GetData(), fRecData->GetLength() );
fRecData->Clear();
if ( siResult == CBuff::kBuffFull )
{
inContinue->fMultiMapIndex = 3;
inContinue->fAllRecIndex = en;
::ni_proplist_free( &niPropList );
if ( siResult != eDSNoErr ) throw( siResult );
}
else if ( siResult == eDSNoErr )
{
inContinue->fMultiMapIndex = 0;
outRecCount++;
inContinue->fTotalRecCount++;
}
else
{
inContinue->fMultiMapIndex = 0;
::ni_proplist_free( &niPropList );
throw( (sInt32)eDSInvalidBuffFormat );
}
}
} } }
::ni_proplist_free( &niPropList );
} } } if ( niEntryList.ni_entrylist_len > 0 )
{
::ni_entrylist_free(&niEntryList);
niEntryList.ni_entrylist_len = 0;
}
} } } }
else if ( (inContinue->fMultiMapIndex == 0) || (inContinue->fMultiMapIndex == 1) )
{
niStatus = ::ni_pathsearch( inDomain, &niDirID, inNativeRecType );
if ( niStatus == NI_OK )
{
inConstRegExpRecName = BuildRegExp(inConstRecName);
if ( (strcmp(inConstRecName,"/") == 0) &&
((inContinue->fMultiMapIndex == 0) || (inContinue->fMultiMapIndex == 1)) )
{
niStatus = ::ni_read( inDomain, &niDirID, &niPropList );
if ( niStatus == NI_OK )
{
fRecData->AppendShort( ::strlen( inConstRecType ) );
fRecData->AppendString( inConstRecType );
fRecData->AppendShort( 1 );
fRecData->AppendString( "/" );
siResult = GetTheseAttributes( inAttrTypeList, &niPropList, inAttrOnly, inDomain, inDomainName, siCount );
if ( siResult == eDSNoErr )
{
if ( siCount == 0 )
{
fRecData->AppendShort( 0 );
}
else
{
fRecData->AppendShort( siCount );
fRecData->AppendBlock( fAttrData->GetData(), fAttrData->GetLength() );
}
siResult = inBuff->AddData( fRecData->GetData(), fRecData->GetLength() );
fRecData->Clear();
if ( siResult == CBuff::kBuffFull )
{
inContinue->fMultiMapIndex = 1;
inContinue->fAllRecIndex = en;
::ni_proplist_free( &niPropList );
if ( siResult != eDSNoErr ) throw( siResult );
}
else if ( siResult == eDSNoErr )
{
inContinue->fMultiMapIndex = 0;
outRecCount++;
inContinue->fTotalRecCount++;
}
else
{
inContinue->fMultiMapIndex = 0;
::ni_proplist_free( &niPropList );
throw( (sInt32)eDSInvalidBuffFormat );
}
} ::ni_proplist_free( &niPropList );
} }
else
{
niStatus = ::ni_search( inDomain, &niDirID, (char *)"name", inConstRegExpRecName, REG_ICASE, &niEntryList );
if ( (niStatus == NI_OK) &&
((inContinue->fMultiMapIndex == 0) || (inContinue->fMultiMapIndex == 1)) )
{
for ( en = inContinue->fAllRecIndex; (en < niEntryList.ni_entrylist_len) &&
(((inContinue->fTotalRecCount) < inContinue->fLimitRecSearch) ||
(inContinue->fLimitRecSearch == 0)); en++ )
{
niEntry = niEntryList.ni_entrylist_val[ en ];
niDirID.nii_object = niEntry.id;
niStatus = ::ni_read( inDomain, &niDirID, &niPropList );
if ( niStatus == NI_OK )
{
niIndex = ::ni_proplist_match( niPropList, "name", NULL );
if ( niIndex != NI_INDEX_NULL )
{
bGotAMatch = false;
for ( uInt32 pv = 0; pv < niPropList.nipl_val[ niIndex ].nip_val.ninl_len; pv++ )
{
if ( DoesThisMatch( (const char*)(niPropList.nipl_val[ niIndex ].nip_val.ninl_val[ pv ]),
(const char*)inConstRecName,
inPattMatch ) )
{
bGotAMatch = true;
break;
}
}
if (bGotAMatch)
{
fRecData->AppendShort( ::strlen( inConstRecType ) );
fRecData->AppendString( inConstRecType );
niIndex = ::ni_proplist_match( niPropList, "name", NULL );
if ( niIndex == NI_INDEX_NULL || niPropList.nipl_val[ niIndex ].nip_val.ninl_len == 0 )
{
fRecData->AppendShort( ::strlen( "*** No Name ***" ) );
fRecData->AppendString( "*** No Name ***" );
}
else
{
fRecData->AppendShort( ::strlen( niPropList.nipl_val[ niIndex ].nip_val.ninl_val[ 0 ] ) );
fRecData->AppendString( niPropList.nipl_val[ niIndex ].nip_val.ninl_val[ 0 ] );
}
siResult = GetTheseAttributes( inAttrTypeList, &niPropList, inAttrOnly, inDomain, inDomainName, siCount );
if ( siResult == eDSNoErr )
{
if ( siCount == 0 )
{
fRecData->AppendShort( 0 );
}
else
{
fRecData->AppendShort( siCount );
fRecData->AppendBlock( fAttrData->GetData(), fAttrData->GetLength() );
}
siResult = inBuff->AddData( fRecData->GetData(), fRecData->GetLength() );
fRecData->Clear();
if ( siResult == CBuff::kBuffFull )
{
inContinue->fMultiMapIndex = 1;
inContinue->fAllRecIndex = en;
::ni_proplist_free( &niPropList );
if ( siResult != eDSNoErr ) throw( siResult );
}
else if ( siResult == eDSNoErr )
{
inContinue->fMultiMapIndex = 0;
outRecCount++;
inContinue->fTotalRecCount++;
}
else
{
inContinue->fMultiMapIndex = 0;
::ni_proplist_free( &niPropList );
throw( (sInt32)eDSInvalidBuffFormat );
}
} } }
::ni_proplist_free( &niPropList );
} }
} if ( niEntryList.ni_entrylist_len > 0 )
{
::ni_entrylist_free(&niEntryList);
niEntryList.ni_entrylist_len = 0;
}
}
free(inConstRegExpRecName);
} }
inContinue->fMultiMapIndex = 0;
inContinue->fAllRecIndex = 0;
}
catch( sInt32 err )
{
if ( niEntryList.ni_entrylist_len > 0 )
{
::ni_entrylist_free(&niEntryList);
niEntryList.ni_entrylist_len = 0;
}
siResult = err;
}
gNetInfoMutex->Signal();
return( siResult );
}
sInt32 CNiPlugIn::GetTheseAttributes ( CAttributeList *inAttrTypeList,
ni_proplist *inPropList,
bool inAttrOnly,
void *inDomain,
char *inDomainName,
sInt32 &outCount )
{
sInt32 siResult = eDSNoErr;
uInt32 pn = 0;
uInt32 pv = 0;
sInt32 attrTypeIndex = 1;
char *pNI_AttrType = nil;
char *pDS_AttrType = nil;
char *pDS_AttrName = nil;
ni_index niIndex = 0;
ni_property niProp;
ni_namelist niNameList;
gNetInfoMutex->Wait();
try
{
outCount = 0;
fAttrData->Clear();
while ( inAttrTypeList->GetAttribute( attrTypeIndex++, &pDS_AttrType ) == eDSNoErr )
{
siResult = eDSNoErr;
pNI_AttrType = MapAttrToNetInfoType( pDS_AttrType );
if ( pNI_AttrType != nil )
{
if ( ::strcmp( kDSNAttrMetaNodeLocation, pNI_AttrType ) == 0 )
{
fTmpData->Clear();
outCount++;
fTmpData->AppendShort( ::strlen( pDS_AttrType ) );
fTmpData->AppendString( pDS_AttrType );
if ( inAttrOnly == false )
{
fTmpData->AppendShort( 1 );
fTmpData->AppendLong( ::strlen( inDomainName ) );
fTmpData->AppendString( inDomainName );
}
else
{
fTmpData->AppendShort( 0 );
}
fAttrData->AppendLong( fTmpData->GetLength() );
fAttrData->AppendBlock( fTmpData->GetData(), fTmpData->GetLength() );
fTmpData->Clear();
}
else
{
if ( ( ::strcmp( kDSAttributesAll, pNI_AttrType ) == 0 ) ||
( ::strcmp( kDSAttributesStandardAll, pNI_AttrType ) == 0 ) )
{
fTmpData->Clear();
outCount++;
fTmpData->AppendShort( ::strlen( kDSNAttrMetaNodeLocation ) );
fTmpData->AppendString( kDSNAttrMetaNodeLocation );
if ( inAttrOnly == false )
{
fTmpData->AppendShort( 1 );
fTmpData->AppendLong( ::strlen( inDomainName ) );
fTmpData->AppendString( inDomainName );
}
else
{
fTmpData->AppendShort( 0 );
}
fAttrData->AppendLong( fTmpData->GetLength() );
fAttrData->AppendBlock( fTmpData->GetData(), fTmpData->GetLength() );
fTmpData->Clear();
for ( pn = 0; pn < inPropList->ni_proplist_len; pn++ )
{
niProp = inPropList->ni_proplist_val[ pn ];
fTmpData->Clear();
pDS_AttrName = MapNetInfoAttrToDSType( niProp.nip_name );
if ( pDS_AttrName != nil )
{
if ( ( ::strncmp(pDS_AttrName,kDSNativeAttrTypePrefix,strlen(kDSNativeAttrTypePrefix)) == 0 ) &&
( ::strcmp( kDSAttributesStandardAll, pNI_AttrType ) == 0 ) )
{
delete( pDS_AttrName );
pDS_AttrName = nil;
continue;
}
else
{
fTmpData->AppendShort( ::strlen( pDS_AttrName ) );
fTmpData->AppendString( pDS_AttrName );
outCount++;
delete( pDS_AttrName );
pDS_AttrName = nil;
if ( inAttrOnly == false )
{
niNameList = niProp.nip_val;
fTmpData->AppendShort( niNameList.ni_namelist_len );
for ( pv = 0; pv < niNameList.ni_namelist_len; pv++ )
{
fTmpData->AppendLong( ::strlen( niNameList.ni_namelist_val[ pv ] ) );
fTmpData->AppendString( niNameList.ni_namelist_val[ pv ] );
}
}
else
{
fTmpData->AppendShort( 0 );
}
fAttrData->AppendLong( fTmpData->GetLength() );
fAttrData->AppendBlock( fTmpData->GetData(), fTmpData->GetLength() );
fTmpData->Clear();
} } }
}
else
{
niIndex = ::ni_proplist_match( *inPropList, pNI_AttrType, NULL );
if ( niIndex != NI_INDEX_NULL )
{
fTmpData->Clear();
outCount++;
fTmpData->AppendShort( ::strlen( pDS_AttrType ) );
fTmpData->AppendString( pDS_AttrType );
if ( inAttrOnly == false )
{
niNameList = inPropList->nipl_val[ niIndex ].nip_val;
fTmpData->AppendShort( niNameList.ni_namelist_len );
for ( pv = 0; pv < niNameList.ni_namelist_len; pv++ )
{
fTmpData->AppendLong( ::strlen( niNameList.ni_namelist_val[ pv ] ) );
fTmpData->AppendString( niNameList.ni_namelist_val[ pv ] );
}
}
else
{
fTmpData->AppendShort( 0 );
}
fAttrData->AppendLong( fTmpData->GetLength() );
fAttrData->AppendBlock( fTmpData->GetData(), fTmpData->GetLength() );
fTmpData->Clear();
}
}
}
delete( pNI_AttrType );
pNI_AttrType = nil;
}
}
}
catch( sInt32 err )
{
siResult = err;
}
gNetInfoMutex->Signal();
return( siResult );
}
sInt32 CNiPlugIn::AddAttribute ( sAddAttribute *inData )
{
sInt32 siResult = eDSNoErr;
tDataNode *pNewAttr = nil;
char *pAttrKey = nil;
tDataNode *pAttrValue = nil;
sNIContextData *pContext = nil;
char *pEmptyValue = (char *)"";
char *pValue = nil;
ni_namelist niValues;
char *authUser = nil;
gNetInfoMutex->Wait();
try
{
pContext = (sNIContextData *)gNINodeRef->GetItemData( inData->fInRecRef );
if ( pContext == nil ) throw( (sInt32)eDSInvalidRecordRef );
pNewAttr = inData->fInNewAttr;
if ( pNewAttr == nil ) throw( (sInt32)eDSNullAttribute );
pAttrKey = MapAttrToNetInfoType( pNewAttr->fBufferData );
if ( pAttrKey == nil ) throw( (sInt32)eDSNullAttribute );
pAttrValue = inData->fInFirstAttrValue;
if ( pAttrValue == nil )
{
pValue = pEmptyValue;
}
else
{
pValue = pAttrValue->fBufferData;
}
if ( ( pContext->fEffectiveUID != 0 )
&& ( (pContext->fAuthenticatedUserName == NULL)
|| (strcmp(pContext->fAuthenticatedUserName,"root") != 0) ) )
{
authUser = pContext->fAuthenticatedUserName;
if ( ( authUser == NULL ) && (strcmp(pAttrKey,"picture") == 0) )
{
authUser = GetUserNameForUID( pContext->fEffectiveUID, pContext->fDomain );
}
ni_proplist niPropList;
siResult = ::ni_read( pContext->fDomain, &pContext->dirID, &niPropList );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
siResult = NiLib2::ValidateDir( authUser, &niPropList );
::ni_proplist_free( &niPropList );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
}
NI_INIT( &niValues );
::ni_namelist_insert( &niValues, pValue, NI_INDEX_NULL );
siResult = DoAddAttribute( pContext->fDomain, &pContext->dirID, pAttrKey, niValues );
::ni_namelist_free( &niValues );
}
catch( sInt32 err )
{
siResult = err;
}
if (authUser != nil)
{
if (pContext != nil)
{
if (pContext->fAuthenticatedUserName == nil)
{
free(authUser);
authUser = nil;
}
}
}
if ( pAttrKey != nil )
{
delete( pAttrKey );
pAttrKey = nil;
}
gNetInfoMutex->Signal();
return( siResult );
}
sInt32 CNiPlugIn::DoAddAttribute ( void *inDomain,
ni_id *inDir,
const ni_name inKey,
ni_namelist inValues )
{
sInt32 siResult = eDSNoErr;
ni_index where = 0;
ni_property niPropList;
ni_namelist niNameList;
gNetInfoMutex->Wait();
try
{
::ni_needwrite( inDomain, 1 );
NI_INIT( &niNameList );
siResult = ::ni_listprops( inDomain, inDir, &niNameList );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
where = ::ni_namelist_match( niNameList, inKey );
::ni_namelist_free( &niNameList );
if ( where == NI_INDEX_NULL )
{
NI_INIT( &niPropList );
niPropList.nip_name = ::ni_name_dup( inKey );
niPropList.nip_val = ::ni_namelist_dup( inValues );
siResult = ::ni_createprop( inDomain, inDir, niPropList, NI_INDEX_NULL );
::ni_prop_free( &niPropList );
}
else
{
siResult = ::ni_writeprop( inDomain, inDir, where, inValues );
}
siResult = MapNetInfoErrors( siResult );
}
catch( sInt32 err )
{
siResult = err;
}
gNetInfoMutex->Signal();
return( siResult );
}
sInt32 CNiPlugIn::GetAttributeValue ( sGetAttributeValue *inData )
{
sInt32 siResult = eDSNoErr;
uInt16 usValueCnt = 0;
uInt32 usValueLen = 0;
uInt16 usAttrNameLen = 0;
uInt32 i = 0;
uInt32 uiIndex = 0;
uInt32 offset = 0;
char *p = nil;
tDataBuffer *pDataBuff = nil;
tAttributeValueEntry *pAttrValue = nil;
sNIContextData *pValueContext = nil;
uInt32 buffSize = 0;
uInt32 buffLen = 0;
uInt32 attrLen = 0;
try
{
pValueContext = (sNIContextData *)gNINodeRef->GetItemData( inData->fInAttrValueListRef );
if ( pValueContext == nil ) throw( (sInt32)eDSBadContextData );
uiIndex = inData->fInAttrValueIndex;
if (uiIndex == 0) throw( (sInt32)eDSInvalidIndex );
pDataBuff = inData->fInOutDataBuff;
if ( pDataBuff == nil ) throw( (sInt32)eDSNullDataBuff );
buffSize = pDataBuff->fBufferSize;
p = pDataBuff->fBufferData + pValueContext->offset;
offset = pValueContext->offset;
if (4 + offset > buffSize) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &attrLen, p, 4 );
buffLen = attrLen + pValueContext->offset + 4;
if (buffLen > buffSize) throw( (sInt32)eDSInvalidBuffFormat );
p += 4;
offset += 4;
if (2 + offset > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &usAttrNameLen, p, 2 );
p += 2 + usAttrNameLen;
offset += 2 + usAttrNameLen;
if (2 + offset > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &usValueCnt, p, 2 );
p += 2;
offset += 2;
if (uiIndex > usValueCnt) throw( (sInt32)eDSInvalidIndex );
for ( i = 1; i < uiIndex; i++ )
{
if (4 + offset > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &usValueLen, p, 4 );
p += 4 + usValueLen;
offset += 4 + usValueLen;
}
if (4 + offset > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &usValueLen, p, 4 );
p += 4;
offset += 4;
pAttrValue = (tAttributeValueEntry *)::calloc( 1, sizeof( tAttributeValueEntry ) + usValueLen + kBuffPad );
pAttrValue->fAttributeValueData.fBufferSize = usValueLen + kBuffPad;
pAttrValue->fAttributeValueData.fBufferLength = usValueLen;
if ( usValueLen + offset > buffLen ) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( pAttrValue->fAttributeValueData.fBufferData, p, usValueLen );
pAttrValue->fAttributeValueID = CalcCRC( pAttrValue->fAttributeValueData.fBufferData );
inData->fOutAttrValue = pAttrValue;
}
catch( sInt32 err )
{
siResult = err;
}
return( siResult );
}
sInt32 CNiPlugIn::GetRecAttribInfo ( sGetRecAttribInfo *inData )
{
bool bFound = false;
sInt32 siResult = eDSNoErr;
ni_status niStatus = NI_OK;
uInt32 uiPv = 0;
uInt32 uiTypeLen = 0;
uInt32 uiDataLen = 0;
tDataNodePtr pAttrType = nil;
char *pNI_AttrType = nil;
tAttributeEntryPtr pOutAttrEntry = nil;
sNIContextData *pContext = nil;
ni_id niDirID;
ni_namelist niNameList; ni_index niIndex;
gNetInfoMutex->Wait();
try
{
pContext = (sNIContextData *)gNINodeRef->GetItemData( inData->fInRecRef );
if ( pContext == nil ) throw( (sInt32)eDSInvalidRecordRef );
pAttrType = inData->fInAttrType;
if ( pAttrType == nil ) throw( (sInt32)eDSEmptyAttributeType );
pNI_AttrType = MapAttrToNetInfoType( pAttrType->fBufferData );
if ( pNI_AttrType == nil ) throw( (sInt32)eDSInvalidAttributeType );
::memcpy( &niDirID, &pContext->dirID, sizeof( ni_id ) );
NI_INIT( &niNameList );
niStatus = ::ni_listprops( pContext->fDomain, &niDirID, &niNameList );
if ( niStatus == NI_OK )
{
niIndex = ::ni_namelist_match( niNameList, pNI_AttrType );
::ni_namelist_free( &niNameList );
if ( niIndex != NI_INDEX_NULL )
{
NI_INIT( &niNameList );
niStatus = ::ni_readprop( pContext->fDomain, &niDirID, niIndex, &niNameList );
if ( niStatus == NI_OK )
{
uiTypeLen = ::strlen( pAttrType->fBufferData );
pOutAttrEntry = (tAttributeEntry *)::calloc( (sizeof( tAttributeEntry ) + uiTypeLen + kBuffPad), sizeof( char ) );
pOutAttrEntry->fAttributeSignature.fBufferSize = uiTypeLen;
pOutAttrEntry->fAttributeSignature.fBufferLength = uiTypeLen;
::memcpy( pOutAttrEntry->fAttributeSignature.fBufferData, pAttrType->fBufferData, uiTypeLen );
pOutAttrEntry->fAttributeValueCount = niNameList.ni_namelist_len;
pOutAttrEntry->fAttributeValueMaxSize = 255;
for ( uiPv = 0; uiPv < niNameList.ni_namelist_len; uiPv++ )
{
uiDataLen += ::strlen( niNameList.ni_namelist_val[ uiPv ] );
}
pOutAttrEntry->fAttributeDataSize = uiDataLen;
inData->fOutAttrInfoPtr = pOutAttrEntry;
bFound = true;
::ni_namelist_free( &niNameList );
}
}
else
{
siResult = eDSAttributeNotFound;
}
}
else
{
siResult = MapNetInfoErrors( niStatus );
}
delete( pNI_AttrType );
pNI_AttrType = nil;
}
catch( sInt32 err )
{
siResult = err;
}
gNetInfoMutex->Signal();
return( siResult );
}
sInt32 CNiPlugIn::GetRecordAttributeValueByID ( sGetRecordAttributeValueByID *inData )
{
bool done = false;
sInt32 siResult = eDSNoErr;
ni_status niStatus = NI_OK;
uInt32 crcVal = 0;
uInt32 uiDataLen = 0;
uInt32 pv = 0;
char *pNI_AttrType = nil;
tAttributeValueEntryPtr pOutAttrValue = nil;
sNIContextData *pContext = nil;
ni_namelist niNameList; ni_index niIndex;
gNetInfoMutex->Wait();
try
{
pContext = (sNIContextData *)gNINodeRef->GetItemData( inData->fInRecRef );
if ( pContext == nil ) throw( (sInt32)eDSInvalidRecordRef );
if ( inData->fInAttrType == nil ) throw( (sInt32)eDSEmptyAttributeType );
pNI_AttrType = MapAttrToNetInfoType( inData->fInAttrType->fBufferData );
if ( pNI_AttrType == nil ) throw( (sInt32)eDSInvalidAttributeType );
NI_INIT( &niNameList );
niStatus = ::ni_listprops( pContext->fDomain, &pContext->dirID, &niNameList );
if ( niStatus == NI_OK )
{
niIndex = ::ni_namelist_match( niNameList, pNI_AttrType );
::ni_namelist_free( &niNameList );
if ( niIndex != NI_INDEX_NULL )
{
NI_INIT( &niNameList );
niStatus = ::ni_readprop( pContext->fDomain, &pContext->dirID, niIndex, &niNameList );
if ( niStatus == NI_OK )
{
for ( pv = 0; (pv < niNameList.ni_namelist_len) && (done == false); pv++ )
{
crcVal = CalcCRC( niNameList.ni_namelist_val[ pv ] );
if ( crcVal == inData->fInValueID )
{
if ( niNameList.ni_namelist_val[ pv ] != nil )
{
uiDataLen = ::strlen( niNameList.ni_namelist_val[ pv ] );
}
else
{
uiDataLen = 0;
}
pOutAttrValue = (tAttributeValueEntry *)::calloc( (sizeof( tAttributeValueEntry ) + uiDataLen + kBuffPad), sizeof( char ) );
pOutAttrValue->fAttributeValueData.fBufferSize = uiDataLen;
pOutAttrValue->fAttributeValueData.fBufferLength = uiDataLen;
if ( niNameList.ni_namelist_val[ pv ] != nil )
{
pOutAttrValue->fAttributeValueID = crcVal;
::memcpy( pOutAttrValue->fAttributeValueData.fBufferData, niNameList.ni_namelist_val[ pv ], uiDataLen );
}
inData->fOutEntryPtr = pOutAttrValue;
done = true;
break;
}
}
::ni_namelist_free( &niNameList );
}
}
else
{
siResult = eDSAttributeNotFound;
}
}
delete( pNI_AttrType );
pNI_AttrType = nil;
}
catch( sInt32 err )
{
siResult = err;
}
gNetInfoMutex->Signal();
return( siResult );
}
sInt32 CNiPlugIn::GetRecAttrValueByIndex ( sGetRecordAttributeValueByIndex *inData )
{
sInt32 siResult = eDSNoErr;
ni_status niStatus = NI_OK;
uInt32 uiDataLen = 0;
uInt32 uiIndex = 0;
char *pNI_AttrType = nil;
tAttributeValueEntryPtr pOutAttrValue = nil;
sNIContextData *pContext = nil;
ni_id niDirID;
ni_namelist niNameList; ni_index niIndex;
gNetInfoMutex->Wait();
try
{
pContext = (sNIContextData *)gNINodeRef->GetItemData( inData->fInRecRef );
if ( pContext == nil ) throw( (sInt32)eDSInvalidRecordRef );
if ( inData->fInAttrType == nil ) throw( (sInt32)eDSEmptyAttributeType );
pNI_AttrType = MapAttrToNetInfoType( inData->fInAttrType->fBufferData );
if ( pNI_AttrType == nil ) throw( (sInt32)eDSInvalidAttributeType );
uiIndex = inData->fInAttrValueIndex;
::memcpy( &niDirID, &pContext->dirID, sizeof( ni_id ) );
NI_INIT( &niNameList );
niStatus = ::ni_listprops( pContext->fDomain, &niDirID, &niNameList );
if ( niStatus == NI_OK )
{
niIndex = ::ni_namelist_match( niNameList, pNI_AttrType );
::ni_namelist_free( &niNameList );
if ( niIndex != NI_INDEX_NULL )
{
NI_INIT( &niNameList );
niStatus = ::ni_readprop( pContext->fDomain, &niDirID, niIndex, &niNameList );
if ( niStatus == NI_OK )
{
if ( niNameList.ni_namelist_len >= uiIndex )
{
if ( niNameList.ni_namelist_val[ uiIndex - 1 ] != nil )
{
uiDataLen = ::strlen( niNameList.ni_namelist_val[ uiIndex - 1 ] );
}
else
{
uiDataLen = 0;
}
pOutAttrValue = (tAttributeValueEntry *)::calloc( 1, sizeof( tAttributeValueEntry ) + uiDataLen + kBuffPad );
pOutAttrValue->fAttributeValueData.fBufferSize = uiDataLen;
pOutAttrValue->fAttributeValueData.fBufferLength = uiDataLen;
if ( niNameList.ni_namelist_val[ uiIndex - 1 ] != nil )
{
pOutAttrValue->fAttributeValueID = CalcCRC( niNameList.ni_namelist_val[ uiIndex - 1 ] );
::memcpy( pOutAttrValue->fAttributeValueData.fBufferData, niNameList.ni_namelist_val[ uiIndex - 1 ], uiDataLen );
}
inData->fOutEntryPtr = pOutAttrValue;
}
else
{
siResult = eDSIndexOutOfRange;
}
::ni_namelist_free( &niNameList );
}
}
else
{
siResult = eDSAttributeNotFound;
}
}
delete( pNI_AttrType );
pNI_AttrType = nil;
}
catch( sInt32 err )
{
siResult = err;
}
gNetInfoMutex->Signal();
return( siResult );
}
sInt32 CNiPlugIn::CreateRecord ( sCreateRecord *inData )
{
volatile sInt32 siResult = eDSNoErr;
tDataNodePtr pRecName = nil;
tDataNodePtr pRecType = nil;
char *pNIRecType = nil;
sNIContextData *pContext = nil;
sNIContextData *pRecContext = nil;
ni_id niDirID;
char *pPath = nil;
char *pRecTypePath = nil;
ni_namelist niValues;
char *authUser = nil;
gNetInfoMutex->Wait();
try
{
pContext = (sNIContextData *)gNINodeRef->GetItemData( inData->fInNodeRef );
if ( pContext == nil ) throw( (sInt32)eDSInvalidNodeRef );
pRecType = inData->fInRecType;
if ( pRecType == nil ) throw( (sInt32)eDSNullRecType );
pRecName = inData->fInRecName;
if ( pRecName == nil ) throw( (sInt32)eDSNullRecName );
pNIRecType = MapRecToNetInfoType( pRecType->fBufferData );
if ( pNIRecType == nil ) throw( (sInt32)eDSInvalidRecordType );
pPath = BuildRecordNamePath( pRecName->fBufferData, pNIRecType );
if ( pPath == nil ) throw( (sInt32)eDSInvalidRecordName );
NI_INIT( &niDirID );
(void)::ni_root( pContext->fDomain, &niDirID );
if ( ( pContext->fEffectiveUID != 0 )
&& ( (pContext->fAuthenticatedUserName == NULL)
|| (strcmp(pContext->fAuthenticatedUserName,"root") != 0) ) )
{
authUser = pContext->fAuthenticatedUserName;
ni_proplist niPropList;
ni_id typeDirID;
pRecTypePath = (char*)calloc( strlen( pNIRecType ) + 2, 1 );
pRecTypePath[0] = '/';
strcpy( pRecTypePath + 1, pNIRecType );
siResult = ::ni_pathsearch( pContext->fDomain, &typeDirID, pRecTypePath);
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
siResult = ::ni_read( pContext->fDomain, &typeDirID, &niPropList );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
siResult = NiLib2::ValidateDir( authUser, &niPropList );
::ni_proplist_free( &niPropList );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
}
siResult = DoCreateRecord( pContext->fDomain, &niDirID, pPath );
if ( siResult != eDSNoErr ) throw( siResult );
if ( (siResult == eDSNoErr) && (strcmp(pNIRecType,"users") == 0) )
{
NI_INIT( &niValues );
::ni_namelist_insert( &niValues, pRecName->fBufferData, NI_INDEX_NULL );
siResult = DoAddAttribute( pContext->fDomain, &niDirID, (const ni_name)"_writers_passwd", niValues );
#ifdef TIM_CLIENT_PRESENT
siResult = DoAddAttribute( pContext->fDomain, &niDirID, (const ni_name)"_writers_tim_password", niValues );
#endif
siResult = DoAddAttribute( pContext->fDomain, &niDirID, (const ni_name)"_writers_picture", niValues );
::ni_namelist_free( &niValues );
}
free(pPath);
pPath = nil;
if ( inData->fInOpen == true )
{
pRecContext = MakeContextData();
if ( pRecContext == nil ) throw( (sInt32)eMemoryAllocError );
pRecContext->fDomain = pContext->fDomain;
::memcpy( &pRecContext->dirID, &niDirID, sizeof( ni_id ) );
pRecContext->fUID = pContext->fUID;
pRecContext->fEffectiveUID = pContext->fEffectiveUID;
if (pContext->fAuthenticatedUserName != NULL)
{
pRecContext->fAuthenticatedUserName = strdup( pContext->fAuthenticatedUserName );
}
pRecContext->fRecType = (char *)::malloc( ::strlen( pRecType->fBufferData ) + 2 );
pRecContext->fRecType[0] = '\0';
::strcpy( pRecContext->fRecType, pRecType->fBufferData );
pRecContext->fRecName = (char *)::malloc( pRecName->fBufferLength + 2 );
pRecContext->fRecName[0] = '\0';
::strcpy( pRecContext->fRecName, pRecName->fBufferData );
gNINodeRef->AddItem( inData->fOutRecRef, pRecContext );
}
}
catch( sInt32 err )
{
siResult = err;
if (pPath != nil)
{
free(pPath);
pPath = nil;
}
}
if (authUser != nil)
{
if (pContext != nil)
{
if (pContext->fAuthenticatedUserName == nil)
{
free(authUser);
authUser = nil;
}
}
}
if ( pRecTypePath != nil )
{
free( pRecTypePath );
pRecTypePath = nil;
}
if ( pNIRecType != nil )
{
delete( pNIRecType );
pNIRecType = nil;
}
gNetInfoMutex->Signal();
return( siResult );
}
sInt32 CNiPlugIn::DoCreateRecord ( void *inDomain, ni_id *inDir, char *inPathName )
{
sInt32 siResult = eDSNoErr;
ni_status niStatus = NI_OK;
sInt32 siCntr1 = 0;
sInt32 siCntr2 = 0;
sInt32 siLen = 0;
bool bSimple = false;
bool bMadeOne = false;
ni_id niTmpDir;
CString csDirName( 128 );
gNetInfoMutex->Wait();
try
{
siCntr1 = 0;
while ( (inPathName[ siCntr1 ] != '\0') && (niStatus == NI_OK) )
{
bSimple = true;
for ( siCntr2 = siCntr1; inPathName[ siCntr2 ] != '\0' && bSimple; siCntr2++ )
{
if ( inPathName[ siCntr2 ] == '\\' && inPathName[ siCntr2 + 1 ] == '/' )
{
if ( inPathName[ siCntr2 + 2 ] == '/' )
{
bSimple = false;
}
siCntr2++;
}
else if ( inPathName[ siCntr2 ] == '/' )
{
bSimple = false;
}
}
siLen = siCntr2 - siCntr1;
if ( !bSimple )
{
siLen--;
}
csDirName.Set( inPathName + siCntr1, siLen );
siCntr1 = siCntr2;
::memcpy( &niTmpDir, inDir, sizeof( ni_id ) );
niStatus = ::ni_pathsearch( inDomain, inDir, csDirName.GetData() );
if ( niStatus == NI_NODIR )
{
::memcpy( inDir, &niTmpDir, sizeof( ni_id ) );
niStatus = DoCreateChild( inDomain, inDir, csDirName.GetData() );
bMadeOne = true;
}
}
if ( niStatus == NI_OK )
{
if ( bMadeOne == false )
{
siResult = eDSRecordAlreadyExists;
}
}
else
{
siResult = MapNetInfoErrors( niStatus );
}
}
catch( sInt32 err )
{
siResult = err;
}
gNetInfoMutex->Signal();
return( siResult );
}
ni_status CNiPlugIn::DoCreateChild ( void *inDomain, ni_id *inDir, const ni_name inDirName )
{
ni_status niStatus = NI_OK;
sInt32 siCntr1 = 0;
sInt32 siCntr2 = 0;
sInt32 siLen = 0;
ni_proplist niPropList;
ni_id niChild;
char *pKey = nil;
char *pValue = nil;
gNetInfoMutex->Wait();
try
{
pKey = (char *)::malloc( 5 );
strcpy( pKey, "name" );
siLen = strlen( inDirName );
pValue = (char *)::malloc( siLen + 1 );
for ( siCntr1 = 0, siCntr2 = 0; siCntr1 < siLen; siCntr1++, siCntr2++ )
{
if ( inDirName[ siCntr1 ] == '\\'
&& ( (inDirName[ siCntr1 + 1 ] == '/') || (inDirName[ siCntr1 + 1 ] == '\\') ) )
{
siCntr1++;
}
pValue[ siCntr2 ] = inDirName[ siCntr1 ];
}
pValue[ siCntr2 ] = '\0';
NI_INIT( &niPropList );
NiLib3::AppendProp( &niPropList, pKey, pValue );
niStatus = ::ni_create( inDomain, inDir, niPropList, &niChild, NI_INDEX_NULL );
if ( niStatus == NI_OK )
{
::memcpy( inDir, &niChild, sizeof( ni_id ) );
}
::ni_proplist_free( &niPropList );
if ( pKey != nil )
{
free( pKey );
pKey = nil;
}
if ( pValue != nil )
{
free( pValue );
pValue = nil;
}
}
catch( sInt32 err )
{
niStatus = (ni_status)err;
}
gNetInfoMutex->Signal();
return( niStatus );
}
sInt32 CNiPlugIn::CloseAttributeList ( sCloseAttributeList *inData )
{
sInt32 siResult = eDSNoErr;
sNIContextData *pContext = nil;
pContext = (sNIContextData *)gNINodeRef->GetItemData( inData->fInAttributeListRef );
if ( pContext != nil )
{
gNINodeRef->RemoveItem( inData->fInAttributeListRef );
}
else
{
siResult = eDSInvalidAttrListRef;
}
return( siResult );
}
sInt32 CNiPlugIn::CloseAttributeValueList ( sCloseAttributeValueList *inData )
{
sInt32 siResult = eDSNoErr;
sNIContextData *pContext = nil;
pContext = (sNIContextData *)gNINodeRef->GetItemData( inData->fInAttributeValueListRef );
if ( pContext != nil )
{
gNINodeRef->RemoveItem( inData->fInAttributeValueListRef );
}
else
{
siResult = eDSInvalidAttrValueRef;
}
return( siResult );
}
sInt32 CNiPlugIn::OpenRecord ( sOpenRecord *inData )
{
sInt32 siResult = eDSNoErr;
tDataNodePtr pRecName = nil;
tDataNodePtr pRecType = nil;
char *pNIRecType = nil;
sNIContextData *pContext = nil;
sNIContextData *pRecContext = nil;
ni_id niDirID;
bool bFoundRealname = false;
char *aRealname = nil;
gNetInfoMutex->Wait();
try
{
pContext = (sNIContextData *)gNINodeRef->GetItemData( inData->fInNodeRef );
if ( pContext == nil ) throw( (sInt32)eDSInvalidNodeRef );
pRecType = inData->fInRecType;
if ( pRecType == nil ) throw( (sInt32)eDSNullRecType );
pRecName = inData->fInRecName;
if ( pRecName == nil ) throw( (sInt32)eDSNullRecName );
pNIRecType = MapRecToNetInfoType( pRecType->fBufferData );
if ( pNIRecType == nil ) throw( (sInt32)eDSInvalidRecordType );
if (pRecName->fBufferLength == 0) throw( (sInt32)eDSEmptyRecordNameList );
if (pRecType->fBufferLength == 0) throw( (sInt32)eDSEmptyRecordTypeList );
NI_INIT( &niDirID );
siResult = IsValidRecordName( pRecName->fBufferData, pNIRecType, pContext->fDomain, niDirID );
if (siResult != eDSNoErr)
{
if (::strcmp(pNIRecType,"users") == 0)
{
siResult = IsValidRealname( pRecName->fBufferData, pContext->fDomain, &aRealname );
if (siResult == eDSNoErr)
{
bFoundRealname = true;
siResult = IsValidRecordName( aRealname, pNIRecType, pContext->fDomain, niDirID );
}
}
if ( siResult != eDSNoErr ) throw( siResult );
}
pRecContext = MakeContextData();
if ( pRecContext == nil ) throw( (sInt32)eMemoryAllocError );
pRecContext->fDomain = pContext->fDomain;
pRecContext->fUID = pContext->fUID;
pRecContext->fEffectiveUID = pContext->fEffectiveUID;
if (pContext->fAuthenticatedUserName != NULL)
{
pRecContext->fAuthenticatedUserName = strdup( pContext->fAuthenticatedUserName );
}
pRecContext->fRecType = (char *)::calloc( 1, ::strlen( pRecType->fBufferData ) + 1 );
::strcpy( pRecContext->fRecType, pRecType->fBufferData );
if (bFoundRealname)
{
if (aRealname != nil)
{
pRecContext->fRecName = aRealname;
}
}
else
{
pRecContext->fRecName = (char *)::calloc( 1, ::strlen( pRecName->fBufferData ) + 1 );
::strcpy( pRecContext->fRecName, pRecName->fBufferData );
}
::memcpy( &pRecContext->dirID, &niDirID, sizeof( ni_id ) );
gNINodeRef->AddItem( inData->fOutRecRef, pRecContext );
}
catch( sInt32 err )
{
if (siResult == eDSInvalidRecordName)
{
siResult = eDSRecordNotFound; }
else
{
siResult = err;
}
}
if ( pNIRecType != nil )
{
delete( pNIRecType );
pNIRecType = nil;
}
gNetInfoMutex->Signal();
return( siResult );
}
sInt32 CNiPlugIn::GetRecRefInfo ( sGetRecRefInfo *inData )
{
sInt32 siResult = eDSNoErr;
uInt32 uiRecSize = 0;
uInt32 uiRecTypeSize = 0;
uInt32 uiRecNameSize = 0;
tRecordEntry *pRecEntry = nil;
sNIContextData *pContext = nil;
gNetInfoMutex->Wait();
try
{
pContext = (sNIContextData *)gNINodeRef->GetItemData( inData->fInRecRef );
if ( pContext == nil ) throw( (sInt32)eDSInvalidRecordRef );
if ( pContext->fRecType != nil )
{
uiRecTypeSize = ::strlen( pContext->fRecType );
}
if ( pContext->fRecName != nil )
{
uiRecNameSize = ::strlen( pContext->fRecName );
}
uiRecSize = sizeof( tRecordEntry ) + uiRecTypeSize + uiRecNameSize + 8;
pRecEntry = (tRecordEntry *)::calloc( 1, uiRecSize );
fRecData->Clear();
fRecData->AppendShort( uiRecNameSize );
fRecData->AppendString( pContext->fRecName );
fRecData->AppendShort( uiRecTypeSize );
fRecData->AppendString( pContext->fRecType );
::memcpy( pRecEntry->fRecordNameAndType.fBufferData, fRecData->GetData(), fRecData->GetLength() );
pRecEntry->fRecordNameAndType.fBufferSize = uiRecTypeSize + uiRecNameSize + 8;
pRecEntry->fRecordNameAndType.fBufferLength = fRecData->GetLength();
inData->fOutRecInfo = pRecEntry;
}
catch( sInt32 err )
{
siResult = err;
}
gNetInfoMutex->Signal();
return( siResult );
}
sInt32 CNiPlugIn::CloseRecord ( sCloseRecord *inData )
{
sInt32 siResult = eDSNoErr;
sNIContextData *pContext = nil;
gNetInfoMutex->Wait();
pContext = (sNIContextData *)gNINodeRef->GetItemData( inData->fInRecRef );
if ( pContext != nil )
{
gNINodeRef->RemoveItem( inData->fInRecRef );
}
else
{
siResult = eDSInvalidRecordRef;
}
gNetInfoMutex->Signal();
return( siResult );
}
sInt32 CNiPlugIn::SetRecordType ( sSetRecordType *inData )
{
sInt32 siResult = eDSNoErr;
tDataNode *pData = nil;
char *pNewType = nil;
char *pNIRecType = nil;
char *pRecTypePath = nil;
sNIContextData *pContext = nil;
char *pPath = nil;
char *authUser = nil;
gNetInfoMutex->Wait();
try
{
pData = inData->fInNewRecType;
if ( pData == nil ) throw( (sInt32)eDSNullRecType );
pNewType = pData->fBufferData;
pContext = (sNIContextData *)gNINodeRef->GetItemData( inData->fInRecRef );
if ( pContext == nil ) throw( (sInt32)eDSInvalidRecordRef );
pNIRecType = MapRecToNetInfoType( pNewType );
if ( pNIRecType == nil ) throw( (sInt32)eDSInvalidRecordType );
pPath = BuildRecordNamePath( pContext->fRecName, pNIRecType );
if ( pPath == nil ) throw( (sInt32)eDSInvalidRecordName );
if ( ( pContext->fEffectiveUID != 0 )
&& ( (pContext->fAuthenticatedUserName == NULL)
|| (strcmp(pContext->fAuthenticatedUserName,"root") != 0) ) )
{
authUser = pContext->fAuthenticatedUserName;
ni_proplist niPropList;
ni_id niDirID;
ni_index tempIndex = NI_INDEX_NULL;
::memcpy( &niDirID, &pContext->dirID, sizeof( ni_id ) );
siResult = ::ni_parent( pContext->fDomain, &niDirID, &tempIndex );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
niDirID.nii_object = tempIndex;
siResult = ::ni_self( pContext->fDomain, &niDirID );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
siResult = ::ni_read( pContext->fDomain, &niDirID, &niPropList );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
siResult = NiLib2::ValidateDir( authUser, &niPropList );
::ni_proplist_free( &niPropList );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
pRecTypePath = (char*)calloc( strlen( pNIRecType ) + 2, 1 );
pRecTypePath[0] = '/';
strcpy( pRecTypePath + 1, pNIRecType );
siResult = ::ni_pathsearch( pContext->fDomain, &niDirID, pRecTypePath );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
siResult = ::ni_read( pContext->fDomain, &niDirID, &niPropList );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
siResult = NiLib2::ValidateDir( authUser, &niPropList );
::ni_proplist_free( &niPropList );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
}
siResult = NiLib2::Copy( pContext->fDomain, &pContext->dirID, pPath, pContext->fDomain, true );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
siResult = NiLib2::Destroy( pContext->fDomain, &pContext->dirID );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
siResult = ::ni_pathsearch( pContext->fDomain, &pContext->dirID, pPath );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
free(pPath);
pPath = nil;
}
catch( sInt32 err )
{
siResult = err;
if (pPath != nil)
{
free(pPath);
pPath = nil;
}
}
if (authUser != nil)
{
if (pContext != nil)
{
if (pContext->fAuthenticatedUserName == nil)
{
free(authUser);
authUser = nil;
}
}
}
if ( pRecTypePath != nil )
{
free( pRecTypePath );
pRecTypePath = nil;
}
gNetInfoMutex->Signal();
return( siResult );
}
sInt32 CNiPlugIn::DeleteRecord ( sDeleteRecord *inData )
{
sInt32 siResult = eDSNoErr;
ni_status niStatus = NI_OK;
sNIContextData *pContext = nil;
char *authUser = nil;
ni_namelist niValuesGUID;
gNetInfoMutex->Wait();
try
{
pContext = (sNIContextData *)gNINodeRef->GetItemData( inData->fInRecRef );
if ( pContext != nil )
{
if ( ( pContext->fEffectiveUID != 0 )
&& ( (pContext->fAuthenticatedUserName == NULL)
|| (strcmp(pContext->fAuthenticatedUserName,"root") != 0) ) )
{
authUser = pContext->fAuthenticatedUserName;
ni_proplist niPropList;
ni_id parentDir;
ni_index tempIndex = NI_INDEX_NULL;
::memcpy( &parentDir, &pContext->dirID, sizeof( ni_id ) );
siResult = ::ni_parent( pContext->fDomain, &parentDir, &tempIndex );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
parentDir.nii_object = tempIndex;
siResult = ::ni_self( pContext->fDomain, &parentDir );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
siResult = ::ni_read( pContext->fDomain, &parentDir, &niPropList );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
siResult = NiLib2::ValidateDir( authUser, &niPropList );
::ni_proplist_free( &niPropList );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
}
{
ni_status niResultGUID = ni_lookupprop( pContext->fDomain, &pContext->dirID,
"generateduid", &niValuesGUID );
char* GUIDString = nil;
if (niResultGUID == NI_OK)
{
if (niValuesGUID.ni_namelist_len > 0)
{
if (niValuesGUID.ni_namelist_val[0] != nil)
{
GUIDString = strdup(niValuesGUID.ni_namelist_val[0]);
}
ni_namelist_free(&niValuesGUID);
}
}
RemoveShadowHash( pContext->fRecName, GUIDString, true );
if (GUIDString != nil)
{
free(GUIDString);
GUIDString = nil;
}
}
niStatus = NiLib2::Destroy( pContext->fDomain, &pContext->dirID );
if ( niStatus == NI_NODIR )
{
siResult = eDSRecordNotFound;
}
else if ( niStatus != NI_OK )
{
siResult = MapNetInfoErrors( niStatus );
}
else
{
gNINodeRef->RemoveItem( inData->fInRecRef );
}
}
else
{
siResult = eDSInvalidRecordRef;
}
}
catch( sInt32 err )
{
siResult = err;
}
if (authUser != nil)
{
if (pContext != nil)
{
if (pContext->fAuthenticatedUserName == nil)
{
free(authUser);
authUser = nil;
}
}
}
gNetInfoMutex->Signal();
return( siResult );
}
sInt32 CNiPlugIn::SetRecordName ( sSetRecordName *inData )
{
sInt32 siResult = eDSNoErr;
bool bFreePropList = false;
uInt32 uiNameLen = 0;
char *pNewName = nil;
sNIContextData *pContext = nil;
ni_proplist niPropList;
ni_index niWhere;
ni_namelist niValues;
ni_namelist niCurrentName;
char *pOldName = nil;
uInt32 pv = 0;
ni_namelist niValue;
ni_property niProp;
ni_namelist niNameList;
bool bDidNotFindValue= true;
char *pNIRecType = nil;
char *authUser = nil;
gNetInfoMutex->Wait();
try
{
pContext = (sNIContextData *)gNINodeRef->GetItemData( inData->fInRecRef );
if ( pContext == nil ) throw( (sInt32)eDSInvalidRecordRef );
::ni_needwrite( pContext->fDomain, 1 );
siResult = ::ni_read( pContext->fDomain, &pContext->dirID, &niPropList );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
bFreePropList = true;
niWhere = ::ni_proplist_match( niPropList, "name", nil );
if (niWhere == NI_INDEX_NULL) throw( (sInt32)ePlugInError );
if ( ( pContext->fEffectiveUID != 0 )
&& ( (pContext->fAuthenticatedUserName == NULL)
|| (strcmp(pContext->fAuthenticatedUserName,"root") != 0) ) )
{
authUser = pContext->fAuthenticatedUserName;
siResult = NiLib2::ValidateDir( authUser, &niPropList );
if ( siResult != NI_OK )
{
siResult = NiLib2::ValidateName( authUser, &niPropList, niWhere );
}
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
}
NI_INIT(&niCurrentName);
siResult = ::ni_readprop(pContext->fDomain, &pContext->dirID, niWhere, &niCurrentName);
pOldName = (char *)::calloc(1, strlen( niCurrentName.ni_namelist_val[ 0 ] ));
strcpy(pOldName, niCurrentName.ni_namelist_val[ 0 ]);
::ni_namelist_free( &niCurrentName );
uiNameLen = ::strlen( inData->fInNewRecName->fBufferData );
if (uiNameLen == 0) throw( (sInt32)eDSNullRecName );
pNewName = (char *)::malloc( uiNameLen );
if ( pNewName == nil ) throw( (sInt32)eMemoryAllocError );
this->MakeGood( inData->fInNewRecName->fBufferData, pNewName );
siResult = ::ni_writename( pContext->fDomain, &pContext->dirID, niWhere, 0, pNewName );
siResult = MapNetInfoErrors( siResult );
if (pContext->fRecType != nil)
{
pNIRecType = MapRecToNetInfoType( pContext->fRecType );
}
if ( (siResult == eDSNoErr) && (pNIRecType != nil) && (::strcmp(pNIRecType,"users") == 0) )
{
niWhere = ::ni_proplist_match( niPropList, "_writers_passwd", nil );
if (niWhere != NI_INDEX_NULL)
{
niProp = niPropList.ni_proplist_val[ niWhere ];
niValue = niProp.nip_val;
for ( pv = 0; pv < niValue.ni_namelist_len; pv++ )
{
if ( strcmp( niValue.ni_namelist_val[ pv ], pOldName ) == 0 )
{
NI_INIT( &niNameList );
::ni_namelist_insert( &niNameList, niValue.ni_namelist_val[ pv ], NI_INDEX_NULL );
siResult = NiLib2::DestroyDirVal( pContext->fDomain, &pContext->dirID, (const ni_name)"_writers_passwd", niNameList );
siResult = NiLib2::InsertDirVal( pContext->fDomain, &pContext->dirID, (const ni_name)"_writers_passwd", pNewName, pv );
siResult = MapNetInfoErrors( siResult );
::ni_namelist_free( &niNameList );
bDidNotFindValue = false;
break;
}
}
if (bDidNotFindValue)
{
siResult = NiLib2::InsertDirVal( pContext->fDomain, &pContext->dirID, (const ni_name)"_writers_passwd", pNewName, niValue.ni_namelist_len );
siResult = MapNetInfoErrors( siResult );
}
}
else
{
NI_INIT( &niValues );
::ni_namelist_insert( &niValues, pNewName, NI_INDEX_NULL );
siResult = DoAddAttribute( pContext->fDomain, &pContext->dirID, (const ni_name)"_writers_passwd", niValues );
::ni_namelist_free( &niValues );
}
niWhere = ::ni_proplist_match( niPropList, "_writers_picture", nil );
if (niWhere != NI_INDEX_NULL)
{
niProp = niPropList.ni_proplist_val[ niWhere ];
niValue = niProp.nip_val;
for ( pv = 0; pv < niValue.ni_namelist_len; pv++ )
{
if ( strcmp( niValue.ni_namelist_val[ pv ], pOldName ) == 0 )
{
NI_INIT( &niNameList );
::ni_namelist_insert( &niNameList, niValue.ni_namelist_val[ pv ], NI_INDEX_NULL );
siResult = NiLib2::DestroyDirVal( pContext->fDomain, &pContext->dirID, (const ni_name)"_writers_picture", niNameList );
siResult = NiLib2::InsertDirVal( pContext->fDomain, &pContext->dirID, (const ni_name)"_writers_picture", pNewName, pv );
siResult = MapNetInfoErrors( siResult );
::ni_namelist_free( &niNameList );
bDidNotFindValue = false;
break;
}
}
if (bDidNotFindValue)
{
siResult = NiLib2::InsertDirVal( pContext->fDomain, &pContext->dirID, (const ni_name)"_writers_picture", pNewName, niValue.ni_namelist_len );
siResult = MapNetInfoErrors( siResult );
}
}
else
{
NI_INIT( &niValues );
::ni_namelist_insert( &niValues, pNewName, NI_INDEX_NULL );
siResult = DoAddAttribute( pContext->fDomain, &pContext->dirID, (const ni_name)"_writers_picture", niValues );
::ni_namelist_free( &niValues );
}
#ifdef TIM_CLIENT_PRESENT
bDidNotFindValue = true;
niWhere = ::ni_proplist_match( niPropList, "_writers_tim_password", nil );
if (niWhere != NI_INDEX_NULL)
{
niProp = niPropList.ni_proplist_val[ niWhere ];
niValue = niProp.nip_val;
for ( pv = 0; pv < niValue.ni_namelist_len; pv++ )
{
if ( strcmp( niValue.ni_namelist_val[ pv ], pOldName ) == 0 )
{
NI_INIT( &niNameList );
::ni_namelist_insert( &niNameList, niValue.ni_namelist_val[ pv ], NI_INDEX_NULL );
siResult = NiLib2::DestroyDirVal( pContext->fDomain, &pContext->dirID, (const ni_name)"_writers_tim_password", niNameList );
siResult = NiLib2::InsertDirVal( pContext->fDomain, &pContext->dirID, (const ni_name)"_writers_tim_password", pNewName, pv );
siResult = MapNetInfoErrors( siResult );
::ni_namelist_free( &niNameList );
bDidNotFindValue = false;
break;
}
}
if (bDidNotFindValue)
{
siResult = NiLib2::InsertDirVal( pContext->fDomain, &pContext->dirID, (const ni_name)"_writers_tim_password", pNewName, niValue.ni_namelist_len );
siResult = MapNetInfoErrors( siResult );
}
}
else
{
NI_INIT( &niValues );
::ni_namelist_insert( &niValues, pNewName, NI_INDEX_NULL );
siResult = DoAddAttribute( pContext->fDomain, &pContext->dirID, (const ni_name)"_writers_tim_password", niValues );
::ni_namelist_free( &niValues );
}
#endif
}
}
catch( sInt32 err )
{
siResult = err;
}
if (authUser != nil)
{
if (pContext != nil)
{
if (pContext->fAuthenticatedUserName == nil)
{
free(authUser);
authUser = nil;
}
}
}
if ( bFreePropList == true )
{
::ni_proplist_free( &niPropList );
}
gNetInfoMutex->Signal();
if ( pNIRecType != nil )
{
free( pNIRecType );
pNIRecType = nil;
}
if ( pNewName != nil )
{
free( pNewName );
pNewName = nil;
}
if ( pOldName != nil )
{
free( pOldName );
pOldName = nil;
}
return( siResult );
}
sInt32 CNiPlugIn::RemoveAttribute ( sRemoveAttribute *inData )
{
sInt32 siResult = eDSNoErr;
char *pAttrType = nil;
sNIContextData *pContext = nil;
ni_namelist niAttribute;
char *authUser = nil;
gNetInfoMutex->Wait();
try
{
pContext = (sNIContextData *)gNINodeRef->GetItemData( inData->fInRecRef );
if ( pContext == nil ) throw( (sInt32)eDSInvalidRecordRef );
pAttrType = MapAttrToNetInfoType( inData->fInAttribute->fBufferData );
if ( pAttrType == nil ) throw( (sInt32)eDSInvalidAttributeType );
if ( ( pContext->fEffectiveUID != 0 )
&& ( (pContext->fAuthenticatedUserName == NULL)
|| (strcmp(pContext->fAuthenticatedUserName,"root") != 0) ) )
{
authUser = pContext->fAuthenticatedUserName;
if ( ( authUser == NULL ) && (strcmp(pAttrType,"picture") == 0) )
{
authUser = GetUserNameForUID( pContext->fEffectiveUID, pContext->fDomain );
}
ni_proplist niPropList;
siResult = ::ni_read( pContext->fDomain, &pContext->dirID, &niPropList );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
siResult = NiLib2::ValidateDir( authUser, &niPropList );
::ni_proplist_free( &niPropList );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
}
if ( (pAttrType != nil) && (strcmp(pAttrType,"authentication_authority") == 0) )
{
ni_namelist niValues;
ni_namelist niValuesGUID;
NI_INIT( &niValues );
NI_INIT( &niValuesGUID );
siResult = ni_lookupprop( pContext->fDomain, &pContext->dirID, "authentication_authority", &niValues );
if ( (siResult == eDSNoErr) && (niValues.ni_namelist_len > 0) && (niValues.ni_namelist_val[0] != nil))
{
if ( strstr(niValues.ni_namelist_val[0], kDSValueAuthAuthorityShadowHash) != nil )
{
siResult = ni_lookupprop( pContext->fDomain, &pContext->dirID, "generateduid", &niValuesGUID );
if ( (siResult == eDSNoErr) && (niValuesGUID.ni_namelist_len > 0) && (niValuesGUID.ni_namelist_val[0] != nil))
{
RemoveShadowHash( pContext->fRecName, niValuesGUID.ni_namelist_val[0], true );
}
if (niValuesGUID.ni_namelist_len > 0)
{
ni_namelist_free(&niValuesGUID);
}
}
}
if (niValues.ni_namelist_len > 0)
{
ni_namelist_free(&niValues);
}
}
NI_INIT( &niAttribute );
::ni_namelist_insert( &niAttribute, pAttrType, NI_INDEX_NULL );
siResult = NiLib2::DestroyDirProp( pContext->fDomain, &pContext->dirID, niAttribute );
siResult = MapNetInfoErrors( siResult );
::ni_namelist_free( &niAttribute );
if ( pAttrType != nil )
{
delete( pAttrType );
pAttrType = nil;
}
}
catch( sInt32 err )
{
siResult = err;
}
if (authUser != nil)
{
if (pContext != nil)
{
if (pContext->fAuthenticatedUserName == nil)
{
free(authUser);
authUser = nil;
}
}
}
gNetInfoMutex->Signal();
return( siResult );
}
sInt32 CNiPlugIn::AddAttributeValue ( sAddAttributeValue *inData )
{
sInt32 siResult = eDSNoErr;
char *pAttrType = nil;
char *pAttrValue = nil;
sNIContextData *pContext = nil;
ni_namelist niNameList;
char *authUser = nil;
gNetInfoMutex->Wait();
try
{
pContext = (sNIContextData *)gNINodeRef->GetItemData( inData->fInRecRef );
if ( pContext == nil ) throw( (sInt32)eDSInvalidRecordRef );
pAttrValue = inData->fInAttrValue->fBufferData;
pAttrType = MapAttrToNetInfoType( inData->fInAttrType->fBufferData );
if ( pAttrType == nil ) throw( (sInt32)eDSInvalidAttributeType );
if ( ( pContext->fEffectiveUID != 0 )
&& ( (pContext->fAuthenticatedUserName == NULL)
|| (strcmp(pContext->fAuthenticatedUserName,"root") != 0) ) )
{
authUser = pContext->fAuthenticatedUserName;
if ( ( authUser == NULL ) && (strcmp(pAttrType,"picture") == 0) )
{
authUser = GetUserNameForUID( pContext->fEffectiveUID, pContext->fDomain );
}
ni_proplist niPropList;
ni_index niIndex;
siResult = ::ni_read( pContext->fDomain, &pContext->dirID, &niPropList );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
siResult = NiLib2::ValidateDir( authUser, &niPropList );
if ( siResult != NI_OK )
{
niIndex = ::ni_proplist_match( niPropList, pAttrType, NULL );
siResult = NiLib2::ValidateName( authUser, &niPropList, niIndex );
}
::ni_proplist_free( &niPropList );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
}
NI_INIT( &niNameList );
::ni_namelist_insert( &niNameList, pAttrValue, NI_INDEX_NULL );
siResult = NiLib2::AppendDirProp( pContext->fDomain, &pContext->dirID, pAttrType, niNameList );
siResult = MapNetInfoErrors( siResult );
::ni_namelist_free( &niNameList );
if ( pAttrType != nil )
{
delete( pAttrType );
pAttrType = nil;
}
}
catch( sInt32 err )
{
siResult = err;
}
if (authUser != nil)
{
if (pContext != nil)
{
if (pContext->fAuthenticatedUserName == nil)
{
free(authUser);
authUser = nil;
}
}
}
gNetInfoMutex->Signal();
return( siResult );
}
sInt32 CNiPlugIn::RemoveAttributeValue ( sRemoveAttributeValue *inData )
{
bool done = false;
sInt32 siResult = eDSNoErr;
bool bFreePropList = false;
uInt32 pn = 0;
uInt32 pv = 0;
char *pAttrType = nil;
sNIContextData *pContext = nil;
ni_namelist niNameList;
ni_namelist niValue;
ni_property niProp;
ni_proplist niPropList;
char *authUser = nil;
gNetInfoMutex->Wait();
try
{
pContext = (sNIContextData *)gNINodeRef->GetItemData( inData->fInRecRef );
if ( pContext == nil ) throw( (sInt32)eDSInvalidRecordRef );
pAttrType = MapAttrToNetInfoType( inData->fInAttrType->fBufferData );
siResult = ::ni_read( pContext->fDomain, &pContext->dirID, &niPropList );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
bFreePropList = true;
if ( ( pContext->fEffectiveUID != 0 )
&& ( (pContext->fAuthenticatedUserName == NULL)
|| (strcmp(pContext->fAuthenticatedUserName,"root") != 0) ) )
{
authUser = pContext->fAuthenticatedUserName;
if ( ( authUser == NULL ) && (strcmp(pAttrType,"picture") == 0) )
{
authUser = GetUserNameForUID( pContext->fEffectiveUID, pContext->fDomain );
}
ni_index niIndex;
siResult = NiLib2::ValidateDir( authUser, &niPropList );
if ( siResult != NI_OK )
{
niIndex = ::ni_proplist_match( niPropList, pAttrType, NULL );
siResult = NiLib2::ValidateName( authUser, &niPropList, niIndex );
}
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
}
siResult = eDSAttributeNotFound;
for ( pn = 0; (pn < niPropList.ni_proplist_len) && (done == false); pn++ )
{
niProp = niPropList.ni_proplist_val[ pn ];
if ( (pAttrType != nil) && (::strcmp( niProp.nip_name, pAttrType ) == 0) )
{
niValue = niProp.nip_val;
for ( pv = 0; (pv < niValue.ni_namelist_len) && (done == false); pv++ )
{
uInt32 crcVal = CalcCRC( niValue.ni_namelist_val[ pv ] );
if ( crcVal == inData->fInAttrValueID )
{
if ( (pAttrType != nil) && (strcmp(pAttrType,"authentication_authority") == 0) )
{
ni_namelist niValues;
ni_namelist niValuesGUID;
NI_INIT( &niValues );
NI_INIT( &niValuesGUID );
siResult = ni_lookupprop( pContext->fDomain, &pContext->dirID, "authentication_authority", &niValues );
if ( (siResult == eDSNoErr) && (niValues.ni_namelist_len > 0) && (niValues.ni_namelist_val[0] != nil))
{
if ( strstr(niValues.ni_namelist_val[0], kDSValueAuthAuthorityShadowHash) != nil )
{
siResult = ni_lookupprop( pContext->fDomain, &pContext->dirID, "generateduid", &niValuesGUID );
if ( (siResult == eDSNoErr) && (niValuesGUID.ni_namelist_len > 0) && (niValuesGUID.ni_namelist_val[0] != nil))
{
RemoveShadowHash( pContext->fRecName, niValuesGUID.ni_namelist_val[0], true );
}
if (niValuesGUID.ni_namelist_len > 0)
{
ni_namelist_free(&niValuesGUID);
}
}
}
if (niValues.ni_namelist_len > 0)
{
ni_namelist_free(&niValues);
}
}
NI_INIT( &niNameList );
::ni_namelist_insert( &niNameList, niValue.ni_namelist_val[ pv ], NI_INDEX_NULL );
siResult = NiLib2::DestroyDirVal( pContext->fDomain, &pContext->dirID, pAttrType, niNameList );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
::ni_namelist_free( &niNameList );
done = true;
break;
}
}
}
}
if ( pAttrType != nil )
{
delete( pAttrType );
pAttrType = nil;
}
}
catch( sInt32 err )
{
siResult = err;
}
if (authUser != nil)
{
if (pContext != nil)
{
if (pContext->fAuthenticatedUserName == nil)
{
free(authUser);
authUser = nil;
}
}
}
if (bFreePropList)
{
::ni_proplist_free( &niPropList );
}
gNetInfoMutex->Signal();
return( siResult );
}
sInt32 CNiPlugIn::SetAttributeValue ( sSetAttributeValue *inData )
{
bool done = false;
sInt32 siResult = eDSNoErr;
bool bFreePropList = false;
uInt32 pn = 0;
uInt32 pv = 0;
char *pAttrType = nil;
char *pAttrValue = nil;
sNIContextData *pContext = nil;
ni_namelist niNameList;
ni_namelist niValue;
ni_property niProp;
ni_proplist niPropList;
char *authUser = nil;
gNetInfoMutex->Wait();
try
{
pContext = (sNIContextData *)gNINodeRef->GetItemData( inData->fInRecRef );
if ( pContext == nil ) throw( (sInt32)eDSInvalidRecordRef );
pAttrType = MapAttrToNetInfoType( inData->fInAttrType->fBufferData );
siResult = ::ni_read( pContext->fDomain, &pContext->dirID, &niPropList );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
bFreePropList = true;
if ( ( pContext->fEffectiveUID != 0 )
&& ( (pContext->fAuthenticatedUserName == NULL)
|| (strcmp(pContext->fAuthenticatedUserName,"root") != 0) ) )
{
authUser = pContext->fAuthenticatedUserName;
if ( ( authUser == NULL ) && (strcmp(pAttrType,"picture") == 0) )
{
authUser = GetUserNameForUID( pContext->fEffectiveUID, pContext->fDomain );
}
ni_index niIndex;
siResult = NiLib2::ValidateDir( authUser, &niPropList );
if ( siResult != NI_OK )
{
niIndex = ::ni_proplist_match( niPropList, pAttrType, NULL );
siResult = NiLib2::ValidateName( authUser, &niPropList, niIndex );
}
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
}
siResult = eDSAttributeNotFound;
for ( pn = 0; pn < (niPropList.ni_proplist_len) && (done == false); pn++ )
{
niProp = niPropList.ni_proplist_val[ pn ];
if ( (pAttrType != nil) && (::strcmp( niProp.nip_name, pAttrType ) == 0) )
{
niValue = niProp.nip_val;
for ( pv = 0; (pv < niValue.ni_namelist_len) && (done == false); pv++ )
{
uInt32 crcVal = CalcCRC( niValue.ni_namelist_val[ pv ] );
if ( crcVal == inData->fInAttrValueEntry->fAttributeValueID )
{
pAttrValue = inData->fInAttrValueEntry->fAttributeValueData.fBufferData;
if ( (pAttrType != nil) && (strcmp(pAttrType,"authentication_authority") == 0) )
{
ni_namelist niValues;
ni_namelist niValuesGUID;
NI_INIT( &niValues );
NI_INIT( &niValuesGUID );
siResult = ni_lookupprop( pContext->fDomain, &pContext->dirID, "authentication_authority", &niValues );
if ( (siResult == eDSNoErr) && (niValues.ni_namelist_len > 0) && (niValues.ni_namelist_val[0] != nil))
{
if ( strstr(niValues.ni_namelist_val[0], kDSValueAuthAuthorityShadowHash) != nil )
{
if ( ( strstr(pAttrValue, kDSValueAuthAuthorityShadowHash) == nil ) &&
( strstr(pAttrValue, kDSTagAuthAuthorityDisabledUser) == nil ) )
{
siResult = ni_lookupprop( pContext->fDomain, &pContext->dirID, "generateduid", &niValuesGUID );
if ( (siResult == eDSNoErr) && (niValuesGUID.ni_namelist_len > 0) && (niValuesGUID.ni_namelist_val[0] != nil))
{
RemoveShadowHash( pContext->fRecName, niValuesGUID.ni_namelist_val[0], true );
}
if (niValuesGUID.ni_namelist_len > 0)
{
ni_namelist_free(&niValuesGUID);
}
}
}
}
if (niValues.ni_namelist_len > 0)
{
ni_namelist_free(&niValues);
}
}
NI_INIT( &niNameList );
::ni_namelist_insert( &niNameList, niValue.ni_namelist_val[ pv ], NI_INDEX_NULL );
siResult = NiLib2::DestroyDirVal( pContext->fDomain, &pContext->dirID, pAttrType, niNameList );
siResult = NiLib2::InsertDirVal( pContext->fDomain, &pContext->dirID, pAttrType, pAttrValue, pv );
siResult = MapNetInfoErrors( siResult );
::ni_namelist_free( &niNameList );
done = true;
break;
}
}
}
}
if ( pAttrType != nil )
{
delete( pAttrType );
pAttrType = nil;
}
}
catch( sInt32 err )
{
siResult = err;
}
if (authUser != nil)
{
if (pContext != nil)
{
if (pContext->fAuthenticatedUserName == nil)
{
free(authUser);
authUser = nil;
}
}
}
if (bFreePropList)
{
::ni_proplist_free( &niPropList );
}
gNetInfoMutex->Signal();
return( siResult );
}
sInt32 CNiPlugIn::DoPlugInCustomCall ( sDoPlugInCustomCall *inData )
{
sInt32 siResult = eDSNoErr;
sNIContextData *pContext = nil;
gNetInfoMutex->Wait();
try
{
if ( inData == nil ) throw( (sInt32)eMemoryError );
pContext = (sNIContextData *)gNINodeRef->GetItemData( inData->fInNodeRef );
if ( pContext == nil ) throw( (sInt32)eDSInvalidNodeRef );
switch ( inData->fInRequestCode )
{
default:
siResult = eNotHandledByThisNode;
break;
}
}
catch( sInt32 err )
{
siResult = err;
}
gNetInfoMutex->Signal();
return( siResult );
}
sInt32 CNiPlugIn::DoAttributeValueSearch ( sDoAttrValueSearchWithData *inData )
{
sInt32 siResult = eDSNoErr;
bool bAttrInfoOnly = false;
uInt32 uiCount = 0;
uInt32 uiTotal = 0;
CRecTypeList *cpRecTypeList = nil;
CAttributeList *cpAttrTypeList = nil;
char *pSearchStr = nil;
char *pDS_AttrType = nil;
char *pNI_RecType = nil;
char *pDS_RecType = nil;
sNIContextData *pContext = nil;
sNIContinueData *pContinue = nil;
tDirPatternMatch pattMatch = eDSExact;
tDataList *pTmpDataList = nil;
CBuff *outBuff = nil;
bool bBuffFull = false;
bool separateRecTypes = false;
uInt32 countDownRecTypes = 0;
gNetInfoMutex->Wait();
try
{
if ( inData == nil ) throw( (sInt32)eMemoryError );
pContext = (sNIContextData *)gNINodeRef->GetItemData( inData->fInNodeRef );
if ( pContext == nil ) throw( (sInt32)eDSInvalidNodeRef );
if ( inData->fIOContinueData == nil )
{
pContinue = (sNIContinueData *)::calloc( 1, sizeof( sNIContinueData ) );
gNIContinue->AddItem( pContinue, inData->fInNodeRef );
pContinue->fRecNameIndex = 1;
pContinue->fRecTypeIndex = 1;
pContinue->fAttrIndex = 1;
pContinue->fAllRecIndex = 0;
pContinue->fTotalRecCount = 0;
pContinue->fLimitRecSearch = 0;
if (inData->fOutMatchRecordCount >= 0)
{
pContinue->fLimitRecSearch = inData->fOutMatchRecordCount;
}
}
else
{
pContinue = (sNIContinueData *)inData->fIOContinueData;
if ( gNIContinue->VerifyItem( pContinue ) == false )
{
throw( (sInt32)eDSInvalidContinueData );
}
}
inData->fIOContinueData = nil;
inData->fOutMatchRecordCount = 0;
outBuff = new CBuff;
if ( outBuff == nil ) throw( (sInt32)eMemoryAllocError );
siResult = outBuff->Initialize( inData->fOutDataBuff, true );
if ( siResult != eDSNoErr ) throw( siResult );
siResult = outBuff->SetBuffType( 'StdA' );
if ( siResult != eDSNoErr ) throw( siResult );
cpRecTypeList = new CRecTypeList( inData->fInRecTypeList );
if ( cpRecTypeList == nil ) throw( (sInt32)eDSEmptyRecordTypeList );
if (cpRecTypeList->GetCount() == 0) throw( (sInt32)eDSEmptyRecordTypeList );
countDownRecTypes = cpRecTypeList->GetCount() - pContinue->fRecTypeIndex + 1;
pDS_AttrType = inData->fInAttrType->fBufferData;
if ( pDS_AttrType == nil ) throw( (sInt32)eDSEmptyAttributeType );
pSearchStr = inData->fInPatt2Match->fBufferData;
if ( pSearchStr == nil ) throw( (sInt32)eDSEmptyPattern2Match );
if ( inData->fType == kDoAttributeValueSearchWithData )
{
cpAttrTypeList = new CAttributeList( inData->fInAttrTypeRequestList );
if ( cpAttrTypeList == nil ) throw( (sInt32)eDSEmptyAttributeTypeList );
if (cpAttrTypeList->GetCount() == 0) throw( (sInt32)eDSEmptyAttributeTypeList );
bAttrInfoOnly = inData->fInAttrInfoOnly;
}
else
{
pTmpDataList = ::dsBuildListFromStringsPriv( kDSAttributesAll, nil );
if ( pTmpDataList != nil )
{
cpAttrTypeList = new CAttributeList( pTmpDataList );
if ( cpAttrTypeList == nil ) throw( (sInt32)eDSEmptyAttributeTypeList );
if (cpAttrTypeList->GetCount() == 0) throw( (sInt32)eDSEmptyAttributeTypeList );
}
}
pattMatch = inData->fInPattMatchType;
siResult = VerifyPatternMatch( pattMatch );
if ( siResult != eDSNoErr ) throw( (sInt32)eDSInvalidPatternMatchType );
while ( (cpRecTypeList->GetAttribute( pContinue->fRecTypeIndex, &pDS_RecType ) == eDSNoErr) &&
(!bBuffFull) && (!separateRecTypes) )
{
pNI_RecType = MapRecToNetInfoType( pDS_RecType );
if ( pNI_RecType != nil )
{
if ( ::strcmp( pDS_AttrType, kDSAttributesAll ) == 0 )
{
siResult = FindAllRecords ( pNI_RecType,
pDS_RecType,
pSearchStr,
pattMatch,
cpAttrTypeList,
bAttrInfoOnly,
pContinue,
pContext->fDomain,
pContext->fDomainName,
outBuff,
uiCount );
}
else
{
siResult = FindTheseRecords ( pNI_RecType,
pDS_RecType,
pDS_AttrType,
pSearchStr,
pattMatch,
cpAttrTypeList,
bAttrInfoOnly,
pContinue,
pContext->fDomain,
pContext->fDomainName,
outBuff,
uiCount );
}
if ( siResult == CBuff::kBuffFull )
{
bBuffFull = true;
inData->fIOContinueData = pContinue;
if ( ( uiCount == 0 ) && ( uiTotal == 0 ) )
{
siResult = eDSBufferTooSmall;
break;
}
uiTotal += uiCount;
inData->fOutMatchRecordCount = uiTotal;
outBuff->SetLengthToSize();
siResult = eDSNoErr;
}
else if ( siResult == eDSNoErr )
{
uiTotal += uiCount;
pContinue->fRecNameIndex++;
}
delete( pNI_RecType );
pNI_RecType = nil;
}
if ( !bBuffFull )
{
pDS_RecType = nil;
pContinue->fRecTypeIndex++;
pContinue->fRecNameIndex = 1;
separateRecTypes = true;
inData->fIOContinueData = pContinue;
if ( pContinue->fNIEntryList.ni_entrylist_len > 0 )
{
::ni_entrylist_free(&(pContinue->fNIEntryList));
pContinue->fNIEntryList.ni_entrylist_len = 0;
}
siResult = eDSNoErr;
countDownRecTypes--;
if ( countDownRecTypes == 0 )
{
inData->fIOContinueData = nil;
}
}
}
if ( (siResult == eDSNoErr) && (!bBuffFull) )
{
if ( uiTotal == 0 )
{
outBuff->ClearBuff();
}
else
{
outBuff->SetLengthToSize();
}
inData->fOutMatchRecordCount = uiTotal;
}
}
catch( sInt32 err )
{
siResult = err;
}
if ( (inData->fIOContinueData == nil) && (pContinue != nil) )
{
gNIContinue->RemoveItem( pContinue );
pContinue = nil;
}
gNetInfoMutex->Signal();
if ( cpAttrTypeList != nil )
{
delete( cpAttrTypeList );
cpAttrTypeList = nil;
}
if ( cpRecTypeList != nil )
{
delete( cpRecTypeList );
cpRecTypeList = nil;
}
if ( outBuff != nil )
{
delete( outBuff );
outBuff = nil;
}
if ( pNI_RecType != nil )
{
delete( pNI_RecType );
pNI_RecType = nil;
}
if ( pTmpDataList != nil )
{
(void)::dsDataListDeallocatePriv( pTmpDataList );
free( pTmpDataList );
pTmpDataList = nil;
}
return( siResult );
}
sInt32 CNiPlugIn:: FindAllRecords ( const char *inNI_RecType,
const char *inDS_RecType,
const char *inPatt2Match,
tDirPatternMatch inHow,
CAttributeList *inAttrTypeList,
bool inAttrOnly,
sNIContinueData *inContinue,
void *inDomain,
char *inDomainName,
CBuff *inBuff,
uInt32 &outRecCount )
{
uInt32 pn = 0;
uInt32 pv = 0;
sInt32 siResult = eDSNoErr;
sInt32 siCount = 0;
uInt32 uiSearchFlag = REG_BASIC;
bool bMatches = false;
u_int en2 = 0;
ni_index niIndex = 0;
ni_id niDirID;
ni_entry niEntry;
ni_proplist niPropList;
ni_entrylist niEntryList;
ni_namelist niNameList;
CString csNI_RecName( 128 );
CString csNI_AttrType( 128 );
ni_property niProp;
gNetInfoMutex->Wait();
outRecCount = 0;
try
{
NI_INIT( &niDirID );
NI_INIT( &niEntry );
NI_INIT( &niPropList );
NI_INIT( &niNameList );
NI_INIT( &niEntryList );
if ( (inHow >= eDSiExact) && (inHow <= eDSiRegularExpression) )
{
uiSearchFlag = REG_ICASE;
}
siResult = ::ni_pathsearch( inDomain, &niDirID, inNI_RecType );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
if ( inContinue->fNIEntryList.ni_entrylist_len == 0 )
{
siResult = ::ni_list( inDomain, &niDirID, "name", &(inContinue->fNIEntryList) );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
}
niEntryList = inContinue->fNIEntryList;
for ( en2 = inContinue->fAllRecIndex; (en2 < niEntryList.ni_entrylist_len) &&
(((inContinue->fTotalRecCount) < inContinue->fLimitRecSearch) ||
(inContinue->fLimitRecSearch == 0)); en2++ )
{
niEntry = niEntryList.ni_entrylist_val[ en2 ];
niDirID.nii_object = niEntry.id;
if ( niEntry.names != NULL )
{
siResult = ::ni_read( inDomain, &niDirID, &niPropList );
if ( siResult == NI_OK )
{
bMatches = false;
for ( pn = 0; ((pn < niPropList.ni_proplist_len) && (bMatches == false)); pn++ )
{
niProp = niPropList.ni_proplist_val[ pn ];
niNameList = niProp.nip_val;
for ( pv = 0; ((pv < niNameList.ni_namelist_len) && (bMatches == false)); pv++ )
{
bMatches = DoesThisMatch( niNameList.ni_namelist_val[ pv ], inPatt2Match, inHow );
}
}
if ( bMatches == true )
{
fAttrData->Clear();
fRecData->Clear();
fRecData->AppendShort( ::strlen( inDS_RecType ) );
fRecData->AppendString( inDS_RecType );
niIndex = ::ni_proplist_match( niPropList, "name", NULL );
if ( niIndex == NI_INDEX_NULL || niPropList.nipl_val[ niIndex ].nip_val.ninl_len == 0 )
{
fRecData->AppendShort( ::strlen( "*** No Name ***" ) );
fRecData->AppendString( "*** No Name ***" );
}
else
{
fRecData->AppendShort( ::strlen( niPropList.nipl_val[ niIndex ].nip_val.ninl_val[ 0 ] ) );
fRecData->AppendString( niPropList.nipl_val[ niIndex ].nip_val.ninl_val[ 0 ] );
}
siResult = GetTheseAttributes( inAttrTypeList, &niPropList, inAttrOnly, inDomain, inDomainName, siCount );
if ( siResult == eDSNoErr )
{
if ( siCount == 0 )
{
fRecData->AppendShort( 0 );
}
else
{
fRecData->AppendShort( siCount );
fRecData->AppendBlock( fAttrData->GetData(), fAttrData->GetLength() );
}
siResult = inBuff->AddData( fRecData->GetData(), fRecData->GetLength() );
if ( siResult == CBuff::kBuffFull )
{
inContinue->fAllRecIndex = en2;
::ni_proplist_free( &niPropList );
break;
}
else if ( siResult == eDSNoErr )
{
outRecCount++;
inContinue->fTotalRecCount++;
}
else
{
inContinue->fAllRecIndex = 0;
::ni_proplist_free( &niPropList );
siResult = eDSInvalidBuffFormat;
break;
}
}
} ::ni_proplist_free( &niPropList );
} } } if ( siResult == eDSNoErr )
{
inContinue->fAllRecIndex = 0;
}
}
catch( sInt32 err )
{
siResult = err;
}
gNetInfoMutex->Signal();
return( siResult );
}
sInt32 CNiPlugIn::FindTheseRecords ( const char *inNI_RecType,
const char *inDS_RecType,
const char *inDS_AttrType,
const char *inPatt2Match,
tDirPatternMatch inHow,
CAttributeList *inAttrTypeList,
bool inAttrOnly,
sNIContinueData *inContinue,
void *inDomain,
char *inDomainName,
CBuff *inBuff,
uInt32 &outRecCount )
{
bool done = false;
bool bMatches = false;
uInt32 i = 0;
sInt32 siCount = 0;
sInt32 siResult = eDSNoErr;
uInt32 uiSearchFlag = REG_BASIC;
ni_status niStatus = NI_OK;
u_int en = 0;
ni_index niIndex = 0;
ni_id niDirID;
ni_entry niEntry;
ni_entrylist niEntryList;
ni_proplist niPropList;
ni_namelist niNameList;
CString csNI_AttrType( 128 );
char * inConstRegExpPatt2Match = nil;
gNetInfoMutex->Wait();
outRecCount = 0;
try
{
if ( (inHow >= eDSiExact) && (inHow <= eDSiRegularExpression) )
{
uiSearchFlag = REG_ICASE;
}
while ( !done )
{
NI_INIT( &niDirID );
NI_INIT( &niEntryList );
siResult = ::ni_pathsearch( inDomain, &niDirID, inNI_RecType );
if ( siResult != eDSNoErr ) throw( MapNetInfoErrors( siResult ) );
if ( ::strcmp( inDS_AttrType, kDSNAttrRecordName ) == 0 )
{
if ( csNI_AttrType.GetLength() == 0 )
{
csNI_AttrType.Set( "name" );
}
else
{
csNI_AttrType.Set( "realname" );
done = true;
}
}
else
{
char *netInfoType = MapAttrToNetInfoType( inDS_AttrType );
if ( netInfoType != nil )
{
csNI_AttrType.Set( netInfoType );
free( netInfoType );
netInfoType = nil;
}
done = true;
}
if ( (inContinue->fTotalRecCount < inContinue->fLimitRecSearch) || (inContinue->fLimitRecSearch == 0) )
{
inConstRegExpPatt2Match = BuildRegExp(inPatt2Match);
niStatus = ::ni_search( inDomain, &niDirID, csNI_AttrType.GetData(), inConstRegExpPatt2Match, uiSearchFlag, &niEntryList );
free(inConstRegExpPatt2Match);
if ( niStatus == NI_OK )
{
for ( en = inContinue->fAllRecIndex; (en < niEntryList.ni_entrylist_len) &&
(((inContinue->fTotalRecCount) < inContinue->fLimitRecSearch) ||
(inContinue->fLimitRecSearch == 0)); en++ )
{
niEntry = niEntryList.ni_entrylist_val[ en ];
niDirID.nii_object = niEntry.id;
if ( niEntry.names != NULL )
{
niNameList = *niEntry.names;
bMatches = false;
for ( i = 0; ((i < niNameList.ni_namelist_len) && (bMatches == false)); i++ )
{
bMatches = DoesThisMatch( niNameList.ni_namelist_val[ i ], inPatt2Match, inHow );
}
if ( bMatches == true )
{
siResult = ::ni_read( inDomain, &niDirID, &niPropList );
if ( siResult == NI_OK )
{
fAttrData->Clear();
fRecData->Clear();
fRecData->AppendShort( ::strlen( inDS_RecType ) );
fRecData->AppendString( inDS_RecType );
niIndex = ::ni_proplist_match( niPropList, "name", NULL );
if ( niIndex == NI_INDEX_NULL || niPropList.nipl_val[ niIndex ].nip_val.ninl_len == 0 )
{
fRecData->AppendShort( ::strlen( "*** No Name ***" ) );
fRecData->AppendString( "*** No Name ***" );
}
else
{
fRecData->AppendShort( ::strlen( niPropList.nipl_val[ niIndex ].nip_val.ninl_val[ 0 ] ) );
fRecData->AppendString( niPropList.nipl_val[ niIndex ].nip_val.ninl_val[ 0 ] );
}
siResult = GetTheseAttributes( inAttrTypeList, &niPropList, inAttrOnly, inDomain, inDomainName, siCount );
if ( siResult == eDSNoErr )
{
if ( siCount == 0 )
{
fRecData->AppendShort( 0 );
}
else
{
fRecData->AppendShort( siCount );
fRecData->AppendBlock( fAttrData->GetData(), fAttrData->GetLength() );
}
siResult = inBuff->AddData( fRecData->GetData(), fRecData->GetLength() );
if ( siResult == CBuff::kBuffFull )
{
inContinue->fAllRecIndex = en;
::ni_proplist_free( &niPropList );
if ( siResult != eDSNoErr ) throw( siResult );
}
else if ( siResult == eDSNoErr )
{
outRecCount++;
inContinue->fTotalRecCount++;
}
else
{
inContinue->fAllRecIndex = 0;
::ni_proplist_free( &niPropList );
throw( (sInt32)eDSInvalidBuffFormat );
}
}
::ni_proplist_free( &niPropList );
siResult = eDSNoErr;
}
}
}
}
} if ( niEntryList.ni_entrylist_len > 0 )
{
::ni_entrylist_free(&niEntryList);
niEntryList.ni_entrylist_len = 0;
}
} } inContinue->fAllRecIndex = 0;
}
catch( sInt32 err )
{
if ( niEntryList.ni_entrylist_len > 0 )
{
::ni_entrylist_free(&niEntryList);
niEntryList.ni_entrylist_len = 0;
}
siResult = err;
}
gNetInfoMutex->Signal();
return( siResult );
}
sInt32 CNiPlugIn::DoAuthentication ( sDoDirNodeAuth *inData )
{
sInt32 siResult = eDSAuthFailed;
ni_status niResult = NI_OK;
ni_status niResultGUID = NI_OK;
uInt32 uiAuthMethod = 0;
sNIContextData *pContext = nil;
sNIContinueData *pContinueData = NULL;
char* userName = NULL;
ni_id niDirID;
ni_namelist niValues;
ni_namelist niValuesGUID;
NetInfoAuthAuthorityHandlerProc handlerProc = NULL;
const char *pNIRecType = "users";
try
{
pContext = (sNIContextData *)gNINodeRef->GetItemData( inData->fInNodeRef );
if ( pContext == nil ) throw( (sInt32)eDSInvalidNodeRef );
if ( inData->fInAuthStepData == nil ) throw( (sInt32)eDSNullAuthStepData );
if ( inData->fIOContinueData != NULL )
{
pContinueData = (sNIContinueData *)inData->fIOContinueData;
if ( gNIContinue->VerifyItem( pContinueData ) == false )
{
throw( (sInt32)eDSInvalidContinueData );
}
if ( pContinueData->fAuthHandlerProc == nil ) throw( (sInt32)eDSInvalidContinueData );
handlerProc = (NetInfoAuthAuthorityHandlerProc)(pContinueData->fAuthHandlerProc);
siResult = (handlerProc)( inData->fInNodeRef, inData->fInAuthMethod, pContext,
&pContinueData, inData->fInAuthStepData,
inData->fOutAuthStepDataResponse,
inData->fInDirNodeAuthOnlyFlag, false,
pContinueData->fAuthAuthorityData, NULL, pNIRecType);
}
else
{
siResult = GetAuthMethod( inData->fInAuthMethod, &uiAuthMethod );
if ( siResult == eDSNoErr || siResult == eDSAuthMethodNotSupported )
{
if ( uiAuthMethod == kAuthWithAuthorizationRef )
{
AuthorizationRef authRef = 0;
AuthorizationItemSet* resultRightSet = NULL;
if ( inData->fInAuthStepData->fBufferLength < sizeof( AuthorizationExternalForm ) ) throw( (sInt32)eDSInvalidBuffFormat );
siResult = AuthorizationCreateFromExternalForm((AuthorizationExternalForm *)inData->fInAuthStepData->fBufferData,
&authRef);
if (siResult != errAuthorizationSuccess)
{
throw( (sInt32)eDSPermissionError );
}
AuthorizationItem rights[] = { {"system.preferences", 0, 0, 0} };
AuthorizationItemSet rightSet = { sizeof(rights)/ sizeof(*rights), rights };
siResult = AuthorizationCopyRights(authRef, &rightSet, NULL,
kAuthorizationFlagExtendRights, &resultRightSet);
if (resultRightSet != NULL)
{
AuthorizationFreeItemSet(resultRightSet);
resultRightSet = NULL;
}
if (siResult != errAuthorizationSuccess)
{
throw( (sInt32)eDSPermissionError );
}
if (inData->fInDirNodeAuthOnlyFlag == false)
{
if (pContext->fAuthenticatedUserName != NULL)
{
free(pContext->fAuthenticatedUserName);
}
pContext->fAuthenticatedUserName = strdup("root");
}
AuthorizationFree( authRef, 0 ); siResult = eDSNoErr;
}
else {
if ( uiAuthMethod != kAuth2WayRandom )
{
siResult = GetUserNameFromAuthBuffer( inData->fInAuthStepData, 1, &userName );
if ( siResult != eDSNoErr ) throw( siResult );
}
else
{
if ( inData->fInAuthStepData->fBufferLength > inData->fInAuthStepData->fBufferSize ) throw( (sInt32)eDSInvalidBuffFormat );
userName = (char*)calloc( inData->fInAuthStepData->fBufferLength + 1, 1 );
strncpy( userName, inData->fInAuthStepData->fBufferData, inData->fInAuthStepData->fBufferLength );
}
siResult = IsValidRecordName ( userName, pNIRecType, pContext->fDomain, niDirID );
if ( siResult != eDSNoErr ) throw( (sInt32)eDSAuthFailed ); gNetInfoMutex->Wait();
niResultGUID = ni_lookupprop( pContext->fDomain, &niDirID,
"generateduid", &niValuesGUID );
niResult = ni_lookupprop( pContext->fDomain, &niDirID,
"authentication_authority", &niValues );
gNetInfoMutex->Signal();
if ( (niResult == NI_OK) && (niValues.ni_namelist_len > 0) )
{
unsigned int i = 0;
bool bLoopAll = IsWriteAuthRequest(uiAuthMethod);
bool bIsSecondary = false;
char* aaVersion = NULL;
char* aaTag = NULL;
char* aaData = NULL;
char* GUIDString = NULL;
if ( (niResultGUID == NI_OK) && (niValuesGUID.ni_namelist_len > 0) )
{
if (niValuesGUID.ni_namelist_val[0] != nil)
{
GUIDString = strdup(niValuesGUID.ni_namelist_val[0]);
}
gNetInfoMutex->Wait();
ni_namelist_free(&niValuesGUID);
gNetInfoMutex->Signal();
}
siResult = eDSAuthMethodNotSupported;
while ( i < niValues.ni_namelist_len
&& (siResult == eDSAuthMethodNotSupported ||
(bLoopAll && siResult == eDSNoErr)))
{
siResult = ParseAuthAuthority( niValues.ni_namelist_val[i], &aaVersion,
&aaTag, &aaData );
if (siResult != eDSNoErr)
{
siResult = eDSAuthFailed;
break;
}
handlerProc = GetNetInfoAuthAuthorityHandler( aaTag );
if (handlerProc != NULL)
{
siResult = (handlerProc)(inData->fInNodeRef, inData->fInAuthMethod, pContext,
&pContinueData,
inData->fInAuthStepData,
inData->fOutAuthStepDataResponse,
inData->fInDirNodeAuthOnlyFlag,
bIsSecondary, aaData, GUIDString, pNIRecType);
if (siResult == eDSNoErr)
{
if (pContinueData != NULL)
{
pContinueData->fAuthHandlerProc = (void*)handlerProc;
pContinueData->fAuthAuthorityData = aaData;
aaData = NULL;
break;
}
else
{
bIsSecondary = true;
}
}
} else
{
siResult = eDSAuthMethodNotSupported;
}
if (aaVersion != NULL) {
free(aaVersion);
aaVersion = NULL;
}
if (aaTag != NULL) {
free(aaTag);
aaTag = NULL;
}
if (aaData != NULL) {
free(aaData);
aaData = NULL;
}
++i;
}
if ( bIsSecondary && siResult == eDSAuthMethodNotSupported )
siResult = eDSNoErr;
if (aaVersion != NULL) {
free(aaVersion);
aaVersion = NULL;
}
if (aaTag != NULL) {
free(aaTag);
aaTag = NULL;
}
if (aaData != NULL) {
free(aaData);
aaData = NULL;
}
if (GUIDString != NULL) {
free(GUIDString);
GUIDString = NULL;
}
gNetInfoMutex->Wait();
ni_namelist_free(&niValues);
gNetInfoMutex->Signal();
}
else
{
siResult = DoBasicAuth(inData->fInNodeRef,inData->fInAuthMethod, pContext,
&pContinueData, inData->fInAuthStepData,
inData->fOutAuthStepDataResponse,
inData->fInDirNodeAuthOnlyFlag, false, NULL, NULL, pNIRecType);
if (pContinueData != NULL && siResult == eDSNoErr)
{
pContinueData->fAuthHandlerProc = (void*)CNiPlugIn::DoBasicAuth;
}
}
} }
} }
catch( sInt32 err )
{
siResult = err;
}
if (userName != NULL)
{
free(userName);
userName = NULL;
}
inData->fResult = siResult;
inData->fIOContinueData = pContinueData;
return( siResult );
}
sInt32 CNiPlugIn::DoAuthenticationOnRecordType ( sDoDirNodeAuthOnRecordType *inData )
{
sInt32 siResult = eDSAuthFailed;
ni_status niResult = NI_OK;
ni_status niResultGUID = NI_OK;
uInt32 uiAuthMethod = 0;
sNIContextData *pContext = nil;
sNIContinueData *pContinueData = NULL;
char* userName = NULL;
ni_id niDirID;
ni_namelist niValues;
ni_namelist niValuesGUID;
NetInfoAuthAuthorityHandlerProc handlerProc = NULL;
char *pNIRecType = nil;
try
{
pContext = (sNIContextData *)gNINodeRef->GetItemData( inData->fInNodeRef );
if ( pContext == nil ) throw( (sInt32)eDSInvalidNodeRef );
if ( inData->fInAuthStepData == nil ) throw( (sInt32)eDSNullAuthStepData );
if ( inData->fInRecordType == nil ) throw( (sInt32)eDSNullRecType );
if ( inData->fInRecordType->fBufferData == nil ) throw( (sInt32)eDSNullRecType );
pNIRecType = MapRecToNetInfoType( inData->fInRecordType->fBufferData );
if (pNIRecType == nil) throw( (sInt32)eDSAuthFailed );
if ( inData->fIOContinueData != NULL )
{
pContinueData = (sNIContinueData *)inData->fIOContinueData;
if ( gNIContinue->VerifyItem( pContinueData ) == false )
{
throw( (sInt32)eDSInvalidContinueData );
}
if ( pContinueData->fAuthHandlerProc == nil ) throw( (sInt32)eDSInvalidContinueData );
handlerProc = (NetInfoAuthAuthorityHandlerProc)(pContinueData->fAuthHandlerProc);
siResult = (handlerProc)( inData->fInNodeRef, inData->fInAuthMethod, pContext,
&pContinueData, inData->fInAuthStepData,
inData->fOutAuthStepDataResponse,
inData->fInDirNodeAuthOnlyFlag, false,
pContinueData->fAuthAuthorityData, NULL, (const char *)pNIRecType);
}
else
{
siResult = GetAuthMethod( inData->fInAuthMethod, &uiAuthMethod );
if ( siResult == eDSNoErr || siResult == eDSAuthMethodNotSupported )
{
if ( uiAuthMethod == kAuthWithAuthorizationRef )
{
AuthorizationRef authRef = 0;
AuthorizationItemSet* resultRightSet = NULL;
if ( inData->fInAuthStepData->fBufferLength < sizeof( AuthorizationExternalForm ) ) throw( (sInt32)eDSInvalidBuffFormat );
siResult = AuthorizationCreateFromExternalForm((AuthorizationExternalForm *)inData->fInAuthStepData->fBufferData,
&authRef);
if (siResult != errAuthorizationSuccess)
{
throw( (sInt32)eDSPermissionError );
}
AuthorizationItem rights[] = { {"system.preferences", 0, 0, 0} };
AuthorizationItemSet rightSet = { sizeof(rights)/ sizeof(*rights), rights };
siResult = AuthorizationCopyRights(authRef, &rightSet, NULL,
kAuthorizationFlagExtendRights, &resultRightSet);
if (resultRightSet != NULL)
{
AuthorizationFreeItemSet(resultRightSet);
resultRightSet = NULL;
}
if (siResult != errAuthorizationSuccess)
{
throw( (sInt32)eDSPermissionError );
}
if (inData->fInDirNodeAuthOnlyFlag == false)
{
if (pContext->fAuthenticatedUserName != NULL)
{
free(pContext->fAuthenticatedUserName);
}
pContext->fAuthenticatedUserName = strdup("root");
}
AuthorizationFree( authRef, 0 ); siResult = eDSNoErr;
}
else {
if ( uiAuthMethod != kAuth2WayRandom )
{
siResult = GetUserNameFromAuthBuffer( inData->fInAuthStepData, 1, &userName );
if ( siResult != eDSNoErr ) throw( siResult );
}
else
{
if ( inData->fInAuthStepData->fBufferLength > inData->fInAuthStepData->fBufferSize ) throw( (sInt32)eDSInvalidBuffFormat );
userName = (char*)calloc( inData->fInAuthStepData->fBufferLength + 1, 1 );
strncpy( userName, inData->fInAuthStepData->fBufferData, inData->fInAuthStepData->fBufferLength );
}
siResult = IsValidRecordName( userName, (const char *)pNIRecType, pContext->fDomain, niDirID );
if ( siResult != eDSNoErr ) throw( (sInt32)eDSAuthFailed );
gNetInfoMutex->Wait();
niResultGUID = ni_lookupprop( pContext->fDomain, &niDirID,
"generateduid", &niValuesGUID );
niResult = ni_lookupprop( pContext->fDomain, &niDirID,
"authentication_authority", &niValues );
gNetInfoMutex->Signal();
if ( (niResult == NI_OK) && (niValues.ni_namelist_len > 0) )
{
unsigned int i = 0;
bool bLoopAll = IsWriteAuthRequest(uiAuthMethod);
bool bIsSecondary = false;
char* aaVersion = NULL;
char* aaTag = NULL;
char* aaData = NULL;
char* GUIDString = NULL;
if ( (niResultGUID == NI_OK) && (niValuesGUID.ni_namelist_len > 0) )
{
if (niValuesGUID.ni_namelist_val[0] != nil)
{
GUIDString = strdup(niValuesGUID.ni_namelist_val[0]);
}
gNetInfoMutex->Wait();
ni_namelist_free(&niValuesGUID);
gNetInfoMutex->Signal();
}
siResult = eDSAuthMethodNotSupported;
while ( i < niValues.ni_namelist_len
&& (siResult == eDSAuthMethodNotSupported ||
(bLoopAll && siResult == eDSNoErr)))
{
siResult = ParseAuthAuthority( niValues.ni_namelist_val[i], &aaVersion,
&aaTag, &aaData );
if (siResult != eDSNoErr)
{
siResult = eDSAuthFailed;
break;
}
handlerProc = GetNetInfoAuthAuthorityHandler( aaTag );
if (handlerProc != NULL)
{
siResult = (handlerProc)(inData->fInNodeRef, inData->fInAuthMethod, pContext,
&pContinueData,
inData->fInAuthStepData,
inData->fOutAuthStepDataResponse,
inData->fInDirNodeAuthOnlyFlag,
bIsSecondary, aaData, GUIDString, (const char *)pNIRecType);
if (siResult == eDSNoErr)
{
if (pContinueData != NULL)
{
pContinueData->fAuthHandlerProc = (void*)handlerProc;
pContinueData->fAuthAuthorityData = aaData;
aaData = NULL;
break;
}
else
{
bIsSecondary = true;
}
}
} else
{
siResult = eDSAuthMethodNotSupported;
}
if (aaVersion != NULL) {
free(aaVersion);
aaVersion = NULL;
}
if (aaTag != NULL) {
free(aaTag);
aaTag = NULL;
}
if (aaData != NULL) {
free(aaData);
aaData = NULL;
}
++i;
}
if (aaVersion != NULL) {
free(aaVersion);
aaVersion = NULL;
}
if (aaTag != NULL) {
free(aaTag);
aaTag = NULL;
}
if (aaData != NULL) {
free(aaData);
aaData = NULL;
}
if (GUIDString != NULL) {
free(GUIDString);
GUIDString = NULL;
}
gNetInfoMutex->Wait();
ni_namelist_free(&niValues);
gNetInfoMutex->Signal();
}
else
{
siResult = DoBasicAuth(inData->fInNodeRef,inData->fInAuthMethod, pContext,
&pContinueData, inData->fInAuthStepData,
inData->fOutAuthStepDataResponse,
inData->fInDirNodeAuthOnlyFlag, false, NULL, NULL, (const char *)pNIRecType);
if (pContinueData != NULL && siResult == eDSNoErr)
{
pContinueData->fAuthHandlerProc = (void*)CNiPlugIn::DoBasicAuth;
}
}
} }
} }
catch( sInt32 err )
{
siResult = err;
}
if (pNIRecType != NULL)
{
free(pNIRecType);
pNIRecType = nil;
}
if (userName != NULL)
{
free(userName);
userName = NULL;
}
inData->fResult = siResult;
inData->fIOContinueData = pContinueData;
return( siResult );
}
bool CNiPlugIn::IsWriteAuthRequest ( uInt32 uiAuthMethod )
{
switch ( uiAuthMethod )
{
case kAuthSetPasswd:
case kAuthSetPasswdAsRoot:
case kAuthChangePasswd:
return true;
default:
return false;
}
}
sInt32 CNiPlugIn::DoBasicAuth ( tDirNodeReference inNodeRef, tDataNodePtr inAuthMethod,
sNIContextData* inContext,
sNIContinueData** inOutContinueData,
tDataBufferPtr inAuthData, tDataBufferPtr outAuthData,
bool inAuthOnly, bool isSecondary, char* inAuthAuthorityData,
char* inGUIDString, const char* inNativeRecType )
{
sInt32 siResult = eDSNoErr;
uInt32 uiAuthMethod = 0;
try
{
if ( inContext == nil ) throw( (sInt32)eDSInvalidNodeRef );
DBGLOG( kLogPlugin, "DoBasicAuth::" );
siResult = GetAuthMethod( inAuthMethod, &uiAuthMethod );
if ( siResult == eDSNoErr )
{
switch( uiAuthMethod )
{
case kAuthSetPolicy:
siResult = eDSAuthMethodNotSupported;
break;
case kAuthNativeMethod:
case kAuthNativeNoClearText:
case kAuthNativeClearTextOK:
if ( outAuthData == nil ) throw( (sInt32)eDSNullAuthStepData );
siResult = DoUnixCryptAuth( inContext, inAuthData, inAuthOnly, inNativeRecType );
if ( siResult == eDSNoErr )
{
if ( outAuthData->fBufferSize > ::strlen( kDSStdAuthCrypt ) )
{
::strcpy( outAuthData->fBufferData, kDSStdAuthCrypt );
}
}
else if ( (siResult != eDSAuthFailed) && (siResult != eDSInvalidBuffFormat) )
{
siResult = DoNodeNativeAuth( inContext, inAuthData, inAuthOnly, inNativeRecType );
if ( siResult == eDSNoErr )
{
if ( outAuthData->fBufferSize > ::strlen( kDSStdAuth2WayRandom ) )
{
::strcpy( outAuthData->fBufferData, kDSStdAuth2WayRandom );
}
}
}
break;
case kAuthClearText:
case kAuthCrypt:
siResult = DoUnixCryptAuth( inContext, inAuthData, inAuthOnly, inNativeRecType );
break;
case kAuthSetPasswd:
siResult = DoSetPassword( inContext, inAuthData, inNativeRecType );
break;
case kAuthSetPasswdAsRoot:
siResult = DoSetPasswordAsRoot( inContext, inAuthData, inNativeRecType );
break;
case kAuthChangePasswd:
siResult = DoChangePassword( inContext, inAuthData, isSecondary, inNativeRecType );
break;
#ifdef TIM_CLIENT_PRESENT
case kAuthSMB_NT_Key:
case kAuthSMB_LM_Key:
siResult = DoTimSMBAuth( inContext, inAuthData, uiAuthMethod );
break;
case kAuth2WayRandom:
siResult = DoTimMultiPassAuth( inNodeRef, inAuthMethod, inContext,
inOutContinueData, inAuthData,
outAuthData, inAuthOnly );
break;
case kAuthAPOP:
case kAuthCRAM_MD5:
siResult = ValidateDigest( inContext, inAuthData, uiAuthMethod );
break;
#endif
default:
siResult = eDSAuthFailed;
}
}
}
catch( sInt32 err )
{
siResult = err;
}
return( siResult );
}
sInt32 CNiPlugIn::DoShadowHashAuth ( tDirNodeReference inNodeRef, tDataNodePtr inAuthMethod,
sNIContextData* inContext,
sNIContinueData** inOutContinueData,
tDataBufferPtr inAuthData, tDataBufferPtr outAuthData,
bool inAuthOnly, bool isSecondary,
char* inAuthAuthorityData, char* inGUIDString,
const char* inNativeRecType )
{
sInt32 siResult = eDSAuthFailed;
uInt32 uiAuthMethod = 0;
char *pUserName = nil;
char *pNewPassword = nil;
char *pOldPassword = nil;
char *pAdminUser = nil;
char *pAdminPassword = nil;
unsigned char P21[kHashShadowKeyLength] = {0};
tDataNodePtr pC8Node = NULL;
unsigned char C8[kHashShadowChallengeLength] = {0};
unsigned char P24[kHashShadowResponseLength] = {0};
unsigned char P24Input[kHashShadowResponseLength] = {0};
tDataNodePtr pP24InputNode = NULL;
tDataListPtr dataList = NULL;
char *path = NULL;
unsigned char hashes[kHashTotalLength] = {0};
unsigned char generatedHashes[kHashTotalLength] = {0};
bool bUseBothHashes = true; uInt32 hashLength = kHashTotalLength;
tDataNodePtr secureHashNode = NULL;
unsigned char secureHash[kHashSecureLength] = {0};
unsigned char secureNULLHash[kHashSecureLength] = {0};
unsigned char shadowNULLHash[kHashShadowBothLength] = {0};
unsigned char digestData[kHashSecureLength] = {0};
SHA_CTX sha_context = {};
SHA_CTX sha_context2 = {};
try
{
if ( inAuthData == nil ) throw( (sInt32)eDSNullAuthStepData );
if ( inContext == nil ) throw( (sInt32)eDSInvalidNodeRef );
DBGLOG( kLogPlugin, "DoShadowHashAuth::" );
siResult = GetAuthMethod( inAuthMethod, &uiAuthMethod );
if ( siResult == eDSNoErr )
{
if (inAuthAuthorityData != nil)
{
if (strcasecmp(inAuthAuthorityData,kDSTagAuthAuthorityBetterHashOnly) == 0)
{
bUseBothHashes = false;
}
}
switch( uiAuthMethod )
{
case kAuthSetPolicy:
siResult = eDSAuthMethodNotSupported;
break;
case kAuthSMB_NT_Key:
case kAuthSMB_LM_Key:
dataList = dsAuthBufferGetDataListAllocPriv(inAuthData);
if ( dataList == nil ) throw( (sInt32)eDSInvalidBuffFormat );
if ( dsDataListGetNodeCountPriv(dataList) != 3 ) throw( (sInt32)eDSInvalidBuffFormat );
pUserName = dsDataListGetNodeStringPriv(dataList, 1);
if ( pUserName == nil ) throw( (sInt32)eDSInvalidBuffFormat );
if ( strlen(pUserName) < 1 ) throw( (sInt32)eDSInvalidBuffFormat );
siResult = dsDataListGetNodePriv(dataList, 2, &pC8Node);
if ( pC8Node == nil ) throw( (sInt32)eDSInvalidBuffFormat );
if ( pC8Node->fBufferLength != kHashShadowChallengeLength ) throw( (sInt32)eDSInvalidBuffFormat);
if ( siResult != eDSNoErr ) throw( (sInt32)eDSInvalidBuffFormat );
memmove(C8, ((tDataBufferPriv*)pC8Node)->fBufferData, kHashShadowChallengeLength);
siResult = dsDataListGetNodePriv(dataList, 3, &pP24InputNode);
if ( pP24InputNode == nil ) throw( (sInt32)eDSInvalidBuffFormat );
if ( pP24InputNode->fBufferLength != kHashShadowResponseLength ) throw( (sInt32)eDSInvalidBuffFormat);
if ( siResult != eDSNoErr ) throw( (sInt32)eDSInvalidBuffFormat );
memmove(P24Input, ((tDataBufferPriv*)pP24InputNode)->fBufferData, kHashShadowResponseLength);
siResult = ReadShadowHash(pUserName, inGUIDString, hashes);
break;
case kAuthSecureHash:
dataList = dsAuthBufferGetDataListAllocPriv(inAuthData);
if ( dataList == nil ) throw( (sInt32)eDSInvalidBuffFormat );
if ( dsDataListGetNodeCountPriv(dataList) != 2 ) throw( (sInt32)eDSInvalidBuffFormat );
pUserName = dsDataListGetNodeStringPriv(dataList, 1);
if ( pUserName == nil ) throw( (sInt32)eDSInvalidBuffFormat );
if ( strlen(pUserName) < 1 ) throw( (sInt32)eDSInvalidBuffFormat );
siResult = dsDataListGetNodePriv(dataList, 2, &secureHashNode);
if ( secureHashNode == nil ) throw( (sInt32)eDSInvalidBuffFormat );
if ( secureHashNode->fBufferLength != kHashSecureLength ) throw( (sInt32)eDSInvalidBuffFormat);
if ( siResult != eDSNoErr ) throw( (sInt32)eDSInvalidBuffFormat );
memmove(secureHash, ((tDataBufferPriv*)secureHashNode)->fBufferData, kHashSecureLength);
siResult = ReadShadowHash(pUserName, inGUIDString, hashes);
break;
case kAuthWriteSecureHash:
dataList = dsAuthBufferGetDataListAllocPriv(inAuthData);
if ( dataList == nil ) throw( (sInt32)eDSInvalidBuffFormat );
if ( dsDataListGetNodeCountPriv(dataList) != 2 ) throw( (sInt32)eDSInvalidBuffFormat );
pUserName = dsDataListGetNodeStringPriv(dataList, 1);
if ( pUserName == nil ) throw( (sInt32)eDSInvalidBuffFormat );
if ( strlen(pUserName) < 1 ) throw( (sInt32)eDSInvalidBuffFormat );
siResult = dsDataListGetNodePriv(dataList, 2, &secureHashNode);
if ( secureHashNode == nil ) throw( (sInt32)eDSInvalidBuffFormat );
if ( secureHashNode->fBufferLength != kHashSecureLength ) throw( (sInt32)eDSInvalidBuffFormat);
if ( siResult != eDSNoErr ) throw( (sInt32)eDSInvalidBuffFormat );
memmove(secureHash, ((tDataBufferPriv*)secureHashNode)->fBufferData, kHashSecureLength);
break;
case kAuthReadSecureHash:
if ( outAuthData == nil ) throw( (sInt32)eDSNullAuthStepData );
dataList = dsAuthBufferGetDataListAllocPriv(inAuthData);
if ( dataList == nil ) throw( (sInt32)eDSInvalidBuffFormat );
if ( dsDataListGetNodeCountPriv(dataList) != 1 ) throw( (sInt32)eDSInvalidBuffFormat );
pUserName = dsDataListGetNodeStringPriv(dataList, 1);
if ( pUserName == nil ) throw( (sInt32)eDSInvalidBuffFormat );
if ( strlen(pUserName) < 1 ) throw( (sInt32)eDSInvalidBuffFormat );
break;
case kAuthSetPasswd:
dataList = dsAuthBufferGetDataListAllocPriv(inAuthData);
if ( dataList == nil ) throw( (sInt32)eDSInvalidBuffFormat );
if ( dsDataListGetNodeCountPriv(dataList) != 4 ) throw( (sInt32)eDSInvalidBuffFormat );
pUserName = dsDataListGetNodeStringPriv(dataList, 1);
if ( pUserName == nil ) throw( (sInt32)eDSInvalidBuffFormat );
if ( strlen(pUserName) < 1 ) throw( (sInt32)eDSInvalidBuffFormat );
pNewPassword = dsDataListGetNodeStringPriv(dataList, 2);
if ( pNewPassword == nil ) throw( (sInt32)eDSInvalidBuffFormat );
pAdminUser = dsDataListGetNodeStringPriv(dataList, 3);
if ( pAdminUser == nil ) throw( (sInt32)eDSInvalidBuffFormat );
pAdminPassword = dsDataListGetNodeStringPriv(dataList, 4);
if ( pAdminPassword == nil ) throw( (sInt32)eDSInvalidBuffFormat );
siResult = ReadShadowHash(pAdminUser, inGUIDString, hashes);
break;
case kAuthSetPasswdAsRoot:
dataList = dsAuthBufferGetDataListAllocPriv(inAuthData);
if ( dataList == nil ) throw( (sInt32)eDSInvalidBuffFormat );
if ( dsDataListGetNodeCountPriv(dataList) != 2 ) throw( (sInt32)eDSInvalidBuffFormat );
pUserName = dsDataListGetNodeStringPriv(dataList, 1);
if ( pUserName == nil ) throw( (sInt32)eDSInvalidBuffFormat );
if ( strlen(pUserName) < 1 ) throw( (sInt32)eDSInvalidBuffFormat );
pNewPassword = dsDataListGetNodeStringPriv(dataList, 2);
if ( pNewPassword == nil ) throw( (sInt32)eDSInvalidBuffFormat );
break;
case kAuthChangePasswd:
dataList = dsAuthBufferGetDataListAllocPriv(inAuthData);
if ( dataList == nil ) throw( (sInt32)eDSInvalidBuffFormat );
if ( dsDataListGetNodeCountPriv(dataList) != 3 ) throw( (sInt32)eDSInvalidBuffFormat );
pUserName = dsDataListGetNodeStringPriv(dataList, 1);
if ( pUserName == nil ) throw( (sInt32)eDSInvalidBuffFormat );
if ( strlen(pUserName) < 1 ) throw( (sInt32)eDSInvalidBuffFormat );
pOldPassword = dsDataListGetNodeStringPriv(dataList, 2);
if ( pOldPassword == nil ) throw( (sInt32)eDSInvalidBuffFormat );
pNewPassword = dsDataListGetNodeStringPriv(dataList, 3);
if ( pNewPassword == nil ) throw( (sInt32)eDSInvalidBuffFormat );
siResult = ReadShadowHash(pUserName, inGUIDString, hashes);
break;
case kAuthNativeClearTextOK:
case kAuthNativeNoClearText:
dataList = dsAuthBufferGetDataListAllocPriv(inAuthData);
if ( dataList == nil ) throw( (sInt32)eDSInvalidBuffFormat );
if ( dsDataListGetNodeCountPriv(dataList) != 2 ) throw( (sInt32)eDSInvalidBuffFormat );
pUserName = dsDataListGetNodeStringPriv(dataList, 1);
if ( pUserName == nil ) throw( (sInt32)eDSInvalidBuffFormat );
if ( strlen(pUserName) < 1 ) throw( (sInt32)eDSInvalidBuffFormat );
pOldPassword = dsDataListGetNodeStringPriv(dataList, 2);
if ( pOldPassword == nil ) throw( (sInt32)eDSInvalidBuffFormat );
siResult = ReadShadowHash(pUserName, inGUIDString, hashes);
break;
default:
break;
}
if ((siResult != eDSNoErr) && !(isSecondary && (uiAuthMethod == kAuthChangePasswd)))
{
throw( siResult );
}
switch( uiAuthMethod )
{
case kAuthSMB_NT_Key:
memmove(P21, hashes, kHashShadowOneLength);
CalculateP24(P21, C8, P24);
if (memcmp(P24,P24Input,kHashShadowResponseLength) == 0)
{
siResult = eDSNoErr;
}
else
{
siResult = eDSAuthFailed;
}
break;
case kAuthSMB_LM_Key:
memmove(P21, hashes+kHashShadowOneLength, kHashShadowOneLength);
CalculateP24(P21, C8, P24);
if (memcmp(P24,P24Input,kHashShadowResponseLength) == 0)
{
siResult = eDSNoErr;
}
else
{
siResult = eDSAuthFailed;
}
break;
case kAuthSecureHash:
if (memcmp(secureHash,hashes+kHashShadowBothLength,kHashSecureLength) == 0)
{
siResult = eDSNoErr;
}
else
{
siResult = eDSAuthFailed;
}
break;
case kAuthWriteSecureHash:
if ( inContext->fEffectiveUID != 0 )
{
throw( (sInt32)eDSPermissionError );
}
memmove(generatedHashes+kHashShadowBothLength, secureHash, kHashSecureLength);
siResult = WriteShadowHash(pUserName, inGUIDString, generatedHashes);
break;
case kAuthReadSecureHash:
if ( inContext->fEffectiveUID != 0 )
{
throw( (sInt32)eDSPermissionError );
}
siResult = ReadShadowHash(pUserName, inGUIDString, hashes);
if (siResult == eDSNoErr)
{
if ( outAuthData->fBufferSize >= kHashSecureLength )
{
memmove( outAuthData->fBufferData, hashes+kHashShadowBothLength, kHashSecureLength );
outAuthData->fBufferLength = kHashSecureLength;
}
else
{
throw( (sInt32)eDSInvalidBuffFormat );
}
}
break;
case kAuthNativeClearTextOK:
case kAuthNativeNoClearText:
CalculateSMBNTHash(pOldPassword,generatedHashes);
hashLength = kHashShadowOneLength;
if (bUseBothHashes)
{
CalculateSMBLANManagerHash(pOldPassword,generatedHashes+kHashShadowOneLength);
hashLength = kHashShadowBothLength;
}
SHA1_Init(&sha_context);
SHA1_Update(&sha_context, (unsigned char *)pOldPassword, strlen(pOldPassword));
SHA1_Final(digestData, &sha_context);
memmove(generatedHashes+kHashShadowBothLength, digestData, kHashSecureLength);
hashLength = kHashTotalLength;
if ( (memcmp(hashes,generatedHashes,hashLength) == 0) ||
( (memcmp(hashes,generatedHashes,kHashShadowBothLength) == 0) &&
(memcmp(hashes+kHashShadowBothLength,secureNULLHash,kHashSecureLength) == 0) ) ||
( (memcmp(hashes+kHashShadowBothLength,generatedHashes+kHashShadowBothLength,kHashSecureLength) == 0) &&
(memcmp(hashes,shadowNULLHash,kHashShadowBothLength) == 0) ) )
{
if ( ( (memcmp(hashes,generatedHashes,kHashShadowBothLength) == 0) &&
(memcmp(hashes+kHashShadowBothLength,secureNULLHash,kHashSecureLength) == 0) ) ||
( (memcmp(hashes+kHashShadowBothLength,generatedHashes+kHashShadowBothLength,kHashSecureLength) == 0) &&
(memcmp(hashes,shadowNULLHash,kHashShadowBothLength) == 0) ) )
{
siResult = eDSNoErr;
siResult = WriteShadowHash(pUserName, inGUIDString, generatedHashes);
}
if (inAuthOnly == false)
{
siResult = AuthOpen( inContext, pUserName, pOldPassword );
}
else
{
siResult = eDSNoErr;
}
}
else
{
siResult = eDSAuthFailed;
}
break;
case kAuthSetPasswd:
CalculateSMBNTHash(pAdminPassword,generatedHashes);
hashLength = kHashShadowOneLength;
if (bUseBothHashes)
{
CalculateSMBLANManagerHash(pAdminPassword,generatedHashes+kHashShadowOneLength);
hashLength = kHashShadowBothLength;
}
SHA1_Init(&sha_context);
SHA1_Update(&sha_context, (unsigned char *)pAdminPassword, strlen(pAdminPassword));
SHA1_Final(digestData, &sha_context);
memmove(generatedHashes+kHashShadowBothLength, digestData, kHashSecureLength);
hashLength = kHashTotalLength;
if ( (memcmp(hashes,generatedHashes,hashLength) == 0) ||
( (memcmp(hashes,generatedHashes,kHashShadowBothLength) == 0) &&
(memcmp(hashes+kHashShadowBothLength,secureNULLHash,kHashSecureLength) == 0) ) ||
( (memcmp(hashes+kHashShadowBothLength,generatedHashes+kHashShadowBothLength,kHashSecureLength) == 0) &&
(memcmp(hashes,shadowNULLHash,kHashShadowBothLength) == 0) ) )
{
if (UserIsAdmin(pAdminUser,inContext->fDomain))
{
siResult = eDSNoErr;
bzero(generatedHashes,kHashTotalLength);
CalculateSMBNTHash(pNewPassword,generatedHashes);
if (bUseBothHashes)
{
CalculateSMBLANManagerHash(pNewPassword,generatedHashes+kHashShadowOneLength);
}
bzero(digestData, kHashSecureLength);
SHA1_Init(&sha_context2);
SHA1_Update(&sha_context2, (unsigned char *)pNewPassword, strlen(pNewPassword));
SHA1_Final(digestData, &sha_context2);
memmove(generatedHashes+kHashShadowBothLength, digestData, kHashSecureLength);
hashLength = kHashTotalLength;
siResult = WriteShadowHash(pUserName, inGUIDString, generatedHashes);
}
else
{
siResult = eDSPermissionError;
}
}
else
{
siResult = eDSAuthFailed;
}
break;
case kAuthSetPasswdAsRoot:
if ( inContext->fEffectiveUID != 0 )
{
if ((inContext->fAuthenticatedUserName == NULL)
|| ((::strcmp(inContext->fAuthenticatedUserName, "root") != 0)
&& (::strcmp(inContext->fAuthenticatedUserName, pUserName) != 0)))
{
throw( (sInt32)eDSPermissionError );
}
}
CalculateSMBNTHash(pNewPassword,generatedHashes);
if (bUseBothHashes)
{
CalculateSMBLANManagerHash(pNewPassword,generatedHashes+kHashShadowOneLength);
}
SHA1_Init(&sha_context);
SHA1_Update(&sha_context, (unsigned char *)pNewPassword, strlen(pNewPassword));
SHA1_Final(digestData, &sha_context);
memmove(generatedHashes+kHashShadowBothLength, digestData, kHashSecureLength);
hashLength = kHashTotalLength;
siResult = WriteShadowHash(pUserName, inGUIDString, generatedHashes);
break;
case kAuthChangePasswd:
CalculateSMBNTHash(pOldPassword,generatedHashes);
hashLength = kHashShadowOneLength;
if (bUseBothHashes)
{
CalculateSMBLANManagerHash(pOldPassword,generatedHashes+kHashShadowOneLength);
hashLength = kHashShadowBothLength;
}
SHA1_Init(&sha_context);
SHA1_Update(&sha_context, (unsigned char *)pOldPassword, strlen(pOldPassword));
SHA1_Final(digestData, &sha_context);
memmove(generatedHashes+kHashShadowBothLength, digestData, kHashSecureLength);
hashLength = kHashTotalLength;
if ( (memcmp(hashes,generatedHashes,hashLength) == 0) ||
( (memcmp(hashes,generatedHashes,kHashShadowBothLength) == 0) &&
(memcmp(hashes+kHashShadowBothLength,secureNULLHash,kHashSecureLength) == 0) ) ||
( (memcmp(hashes+kHashShadowBothLength,generatedHashes+kHashShadowBothLength,kHashSecureLength) == 0) &&
(memcmp(hashes,shadowNULLHash,kHashShadowBothLength) == 0) ) ||
isSecondary )
{
bzero(generatedHashes,kHashTotalLength);
CalculateSMBNTHash(pNewPassword,generatedHashes);
if (bUseBothHashes)
{
CalculateSMBLANManagerHash(pNewPassword,generatedHashes+kHashShadowOneLength);
}
bzero(digestData, kHashSecureLength);
SHA1_Init(&sha_context2);
SHA1_Update(&sha_context2, (unsigned char *)pNewPassword, strlen(pNewPassword));
SHA1_Final(digestData, &sha_context2);
memmove(generatedHashes+kHashShadowBothLength, digestData, kHashSecureLength);
hashLength = kHashTotalLength;
siResult = WriteShadowHash(pUserName, inGUIDString, generatedHashes);
}
else
{
siResult = eDSAuthFailed;
}
break;
default:
siResult = eDSAuthMethodNotSupported;
break;
}
}
}
catch( sInt32 err )
{
siResult = err;
}
if (dataList != NULL)
{
dsDataListDeallocatePriv(dataList);
free(dataList);
dataList = NULL;
}
if ( pUserName != nil )
{
free( pUserName );
pUserName = nil;
}
if ( pNewPassword != nil )
{
free( pNewPassword );
pNewPassword = nil;
}
if ( pOldPassword != nil )
{
free( pOldPassword );
pOldPassword = nil;
}
if ( pAdminUser != nil )
{
free( pAdminUser );
pAdminUser = nil;
}
if ( pAdminPassword != nil )
{
free( pAdminPassword );
pAdminPassword = nil;
}
if (path != NULL)
{
free(path);
path = NULL;
}
return( siResult );
}
sInt32 CNiPlugIn::ReadShadowHash ( const char *inUserName, char *inGUIDString, unsigned char outHashes[kHashTotalLength] )
{
sInt32 siResult = eDSAuthFailed;
char *path = NULL;
char hexHashes[kHashTotalHexLength] = { 0 };
sInt32 readBytes = 0;
uInt32 outBytes = 0;
CFile *hashFile = nil;
try
{
if (inGUIDString != nil)
{
path = (char*)::calloc(1, strlen("/var/db/shadow/hash/") + strlen(inGUIDString) + 1);
}
else
{
path = (char*)::calloc(strlen("/var/db/shadow/hash/") + strlen(inUserName) + 1, 1);
}
if ( path != NULL )
{
if (inGUIDString != nil)
{
sprintf(path, "%s%s", "/var/db/shadow/hash/", inGUIDString);
}
else
{
sprintf(path, "%s%s", "/var/db/shadow/hash/", inUserName);
}
try {
hashFile = new CFile(path, false);
} catch ( ... ) {
}
if (hashFile != nil && hashFile->is_open())
{
readBytes = hashFile->ReadBlock( hexHashes, kHashTotalHexLength );
delete(hashFile);
hashFile = nil;
if ( readBytes < kHashShadowBothHexLength ) throw( (sInt32)eDSAuthFailed );
HexToBinaryConversion( hexHashes, &outBytes, outHashes );
siResult = eDSNoErr;
}
else {
if (hashFile != nil)
{
delete(hashFile);
hashFile = nil;
}
free( path );
path = NULL;
path = (char*)::calloc(strlen("/var/db/samba/hash/") + strlen(inUserName) + 1, 1);
if ( path != NULL )
{
sprintf(path, "%s%s", "/var/db/samba/hash/", inUserName);
try
{
hashFile = new CFile(path, false);
if (hashFile->is_open())
{
readBytes = hashFile->ReadBlock( hexHashes, kHashShadowBothHexLength );
delete(hashFile);
hashFile = nil;
if ( readBytes != kHashShadowBothHexLength ) throw( (sInt32)eDSAuthFailed );
HexToBinaryConversion( hexHashes, &outBytes, outHashes );
siResult = eDSNoErr;
}
}
catch( ... )
{
}
free(path);
path = nil;
}
}
}
}
catch( ... )
{
siResult = eDSAuthFailed;
}
if ( path != NULL )
{
free( path );
path = NULL;
}
if (hashFile != nil)
{
delete(hashFile);
hashFile = nil;
}
return( siResult );
}
sInt32 CNiPlugIn::WriteShadowHash ( const char *inUserName, char *inGUIDString, unsigned char inHashes[kHashTotalLength] )
{
sInt32 result = eDSAuthFailed;
char *path = NULL;
char hexHashes[kHashTotalHexLength] = { 0 };
sInt32 siResult = eDSNoErr;
struct stat statResult;
CFile *hashFile = nil;
try
{
RemoveShadowHash( inUserName, nil, false );
if (inGUIDString != nil)
{
path = (char*)::calloc(1, strlen("/var/db/shadow/hash/") + strlen(inGUIDString) + 1);
}
else
{
path = (char*)::calloc(strlen("/var/db/shadow/hash/") + strlen(inUserName) + 1, 1);
}
if ( path != NULL )
{
if (inGUIDString != nil)
{
sprintf(path, "%s%s", "/var/db/shadow/hash/", inGUIDString);
}
else
{
sprintf(path, "%s%s", "/var/db/shadow/hash/", inUserName);
}
siResult = stat( "/var/db/shadow/hash", &statResult );
if (siResult != eDSNoErr)
{
siResult = ::stat( "/var/db/shadow", &statResult );
if (siResult != eDSNoErr)
{
::mkdir( "/var/db/shadow", 0700 );
::chmod( "/var/db/shadow", 0700 );
}
siResult = ::stat( "/var/db/shadow/hash", &statResult );
if (siResult != eDSNoErr)
{
::mkdir( "/var/db/shadow/hash", 0700 );
::chmod( "/var/db/shadow/hash", 0700 );
}
}
hashFile = new CFile(path, true);
if (hashFile->is_open())
{
BinaryToHexConversion( inHashes, kHashTotalLength, hexHashes );
hashFile->seekp( 0 ); hashFile->write( hexHashes, kHashTotalHexLength );
chmod( path, 0600 ); delete(hashFile);
hashFile = nil;
result = eDSNoErr;
}
}
}
catch( ... )
{
result = eDSAuthFailed;
}
if ( path != NULL ) {
free( path );
path = NULL;
}
if (hashFile != nil)
{
delete(hashFile);
hashFile = nil;
}
return( result );
}
void CNiPlugIn::RemoveShadowHash ( const char *inUserName, char *inGUIDString, bool bShadowToo )
{
char *path = NULL;
char hexHashes[kHashTotalHexLength] = { 0 };
bool bRemovePath = false;
CFile *hashFile = nil;
try
{
if (bShadowToo) {
if (inGUIDString != nil)
{
path = (char*)::calloc(1, strlen("/var/db/shadow/hash/") + strlen(inGUIDString) + 1);
}
else
{
path = (char*)::calloc(strlen("/var/db/shadow/hash/") + strlen(inUserName) + 1, 1);
}
if ( path != NULL )
{
if (inGUIDString != nil)
{
sprintf(path, "%s%s", "/var/db/shadow/hash/", inGUIDString);
}
else
{
sprintf(path, "%s%s", "/var/db/shadow/hash/", inUserName);
}
try
{
hashFile = new CFile(path, false);
if (hashFile->is_open())
{
hashFile->seekp( 0 ); hashFile->write( hexHashes, kHashTotalHexLength );
delete(hashFile);
hashFile = nil;
bRemovePath = true;
}
if (bRemovePath)
{
unlink(path);
}
}
catch( ... )
{
}
free( path );
path = NULL;
}
}
if (hashFile != nil)
{
delete(hashFile);
hashFile = nil;
}
bRemovePath = false;
if (inUserName != nil)
{
path = (char*)::calloc(strlen("/var/db/samba/hash/") + strlen(inUserName) + 1, 1);
}
if ( path != NULL )
{
sprintf(path, "%s%s", "/var/db/samba/hash/", inUserName);
hashFile = new CFile(path, false);
if (hashFile->is_open())
{
hashFile->seekp( 0 ); hashFile->write( hexHashes, kHashShadowBothHexLength );
delete(hashFile);
hashFile = nil;
bRemovePath = true;
}
if (bRemovePath)
{
unlink(path);
}
free( path );
path = NULL;
}
}
catch( ... )
{
}
if ( path != NULL ) {
free( path );
path = NULL;
}
if (hashFile != nil)
{
delete(hashFile);
hashFile = nil;
}
return;
}
sInt32 CNiPlugIn::PWOpenDirNode ( tDirNodeReference fDSRef, char *inNodeName, tDirNodeReference *outNodeRef )
{
sInt32 error = eDSNoErr;
sInt32 error2 = eDSNoErr;
tDataList *pDataList = nil;
pDataList = ::dsBuildFromPathPriv( inNodeName, "/" );
if ( pDataList != nil )
{
error = ::dsOpenDirNode( fDSRef, pDataList, outNodeRef );
error2 = ::dsDataListDeallocatePriv( pDataList );
free( pDataList );
}
return( error );
}
sInt32 CNiPlugIn::PWSetReplicaData( sNIContextData *inContext, const char *inAuthorityData )
{
sInt32 error = eDSNoErr;
ni_status niResult = NI_OK;
bool bFoundWithHash = false;
long replicaListLen = 0;
char *rsaKeyPtr = NULL;
char *nativeRecType = NULL;
char *nativeAttrType = NULL;
tDataBufferPtr replicaBuffer = NULL;
tDataBufferPtr replyBuffer = NULL;
ni_id niDirID;
ni_namelist niValues;
char recordName[64];
char hashStr[34];
nativeRecType = MapRecToNetInfoType( kDSStdRecordTypeConfig );
if ( nativeRecType == NULL )
return eDSInvalidRecordType;
try
{
nativeAttrType = MapAttrToNetInfoType( kDS1AttrPasswordServerList );
if ( nativeAttrType == NULL )
throw( (sInt32)eDSInvalidAttributeType );
rsaKeyPtr = strchr( inAuthorityData, ',' );
if ( rsaKeyPtr != NULL )
{
MD5_CTX ctx;
unsigned char pubKeyHash[MD5_DIGEST_LENGTH];
MD5_Init( &ctx );
rsaKeyPtr++;
MD5_Update( &ctx, rsaKeyPtr, strlen(rsaKeyPtr) );
MD5_Final( pubKeyHash, &ctx );
BinaryToHexConversion( pubKeyHash, MD5_DIGEST_LENGTH, hashStr );
sprintf( recordName, "passwordserver_%s", hashStr );
error = IsValidRecordName( recordName, nativeRecType, inContext->fDomain, niDirID );
if ( error == eDSNoErr )
bFoundWithHash = true;
}
if ( ! bFoundWithHash )
{
error = IsValidRecordName( "passwordserver", nativeRecType, inContext->fDomain, niDirID );
if ( error != eDSNoErr )
throw( error );
}
gNetInfoMutex->Wait();
niResult = ni_lookupprop( inContext->fDomain, &niDirID, nativeAttrType, &niValues );
gNetInfoMutex->Signal();
if ( niResult != NI_OK ) throw( (sInt32)eDSAuthFailed );
if ( niValues.ni_namelist_len >= 1 )
{
replicaListLen = strlen( niValues.ni_namelist_val[0] );
replicaBuffer = ::dsDataBufferAllocatePriv( replicaListLen + 1 );
if ( replicaBuffer == nil ) throw( (sInt32)eMemoryError );
replyBuffer = ::dsDataBufferAllocatePriv( 1 );
if ( replyBuffer == nil ) throw( (sInt32)eMemoryError );
replicaBuffer->fBufferLength = replicaListLen;
memcpy( replicaBuffer->fBufferData, niValues.ni_namelist_val[0], replicaListLen );
error = dsDoPlugInCustomCall( inContext->fPWSNodeRef, 1, replicaBuffer, replyBuffer );
::dsDataBufferDeallocatePriv( replicaBuffer );
::dsDataBufferDeallocatePriv( replyBuffer );
}
if ( nativeAttrType != NULL )
delete nativeAttrType;
gNetInfoMutex->Wait();
if (niValues.ni_namelist_len > 0)
{
ni_namelist_free( &niValues );
}
gNetInfoMutex->Signal();
}
catch( sInt32 catchErr )
{
error = catchErr;
}
if ( nativeRecType != NULL )
delete nativeRecType;
return error;
}
sInt32 CNiPlugIn::RepackBufferForPWServer ( tDataBufferPtr inBuff, const char *inUserID, unsigned long inUserIDNodeNum, tDataBufferPtr *outBuff )
{
sInt32 result = eDSNoErr;
tDataListPtr dataList = NULL;
tDataNodePtr dataNode = NULL;
unsigned long index, nodeCount;
unsigned long uidLen;
if ( !inBuff || !inUserID || !outBuff )
return eDSAuthParameterError;
try
{
uidLen = strlen(inUserID);
*outBuff = ::dsDataBufferAllocatePriv( inBuff->fBufferLength + uidLen + 1 );
if ( *outBuff == nil ) throw( (sInt32)eMemoryError );
(*outBuff)->fBufferLength = 0;
dataList = dsAuthBufferGetDataListAllocPriv(inBuff);
if ( dataList == nil ) throw( (sInt32)eDSInvalidBuffFormat );
nodeCount = dsDataListGetNodeCountPriv(dataList);
if ( nodeCount < 1 ) throw( (sInt32)eDSInvalidBuffFormat );
for ( index = 1; index <= nodeCount; index++ )
{
if ( index == inUserIDNodeNum )
{
memcpy( (*outBuff)->fBufferData + (*outBuff)->fBufferLength, &uidLen, sizeof(unsigned long) );
(*outBuff)->fBufferLength += sizeof(unsigned long);
memcpy( (*outBuff)->fBufferData + (*outBuff)->fBufferLength, inUserID, uidLen );
(*outBuff)->fBufferLength += uidLen;
}
else
{
result = dsDataListGetNodeAllocPriv(dataList, index, &dataNode);
if ( result != eDSNoErr ) throw( (sInt32)eDSInvalidBuffFormat );
memcpy((*outBuff)->fBufferData + (*outBuff)->fBufferLength, &dataNode->fBufferLength, sizeof(unsigned long));
(*outBuff)->fBufferLength += sizeof(unsigned long);
memcpy( (*outBuff)->fBufferData + (*outBuff)->fBufferLength, dataNode->fBufferData, dataNode->fBufferLength );
(*outBuff)->fBufferLength += dataNode->fBufferLength;
dsDataBufferDeallocatePriv(dataNode);
}
}
(void)dsDataListDeallocatePriv(dataList);
free(dataList);
}
catch( sInt32 error )
{
result = error;
}
return result;
}
sInt32 CNiPlugIn::DoLocalCachedUserAuth ( tDirNodeReference inNodeRef, tDataNodePtr inAuthMethod,
sNIContextData* inContext,
sNIContinueData** inOutContinueData,
tDataBufferPtr inAuthData, tDataBufferPtr outAuthData,
bool inAuthOnly, bool isSecondary,
char* inAuthAuthorityData, char* inGUIDString,
const char* inNativeRecType )
{
sInt32 siResult = eDSAuthFailed;
uInt32 uiAuthMethod = 0;
char *networkNodename = nil;
char *userRecordName = nil;
char *userGUID = nil;
tDirReference aDirRef = NULL;
sInt32 result = eDSNoErr;
tDataList *netNode = nil;
tDataBuffer *dataBuffer = nil;
uInt32 nodeCount = 0;
tContextData tContinue = nil;
bool bNetworkNodeReachable = false;
tDirNodeReference aNodeRef = NULL;
tDirNodeReference aSearchNodeRef = NULL;
tDataNode *authMethodPtr = nil;
bool bAuthLocally = false;
sNIContextData *tmpContext = nil;
tDataList *pSearchNode = nil;
tDataList *pSearchNodeList = nil;
tAttributeListRef attrListRef = 0;
tAttributeValueListRef attrValueListRef = 0;
tAttributeValueEntry *pAttrValueEntry = nil;
tAttributeEntry *pAttrEntry = nil;
uInt32 aIndex = 0;
try
{
if ( inAuthData == nil ) throw( (sInt32)eDSNullAuthStepData );
if ( inContext == nil ) throw( (sInt32)eDSInvalidNodeRef );
DBGLOG( kLogPlugin, "DoLocalCachedUserAuth::" );
siResult = GetAuthMethod( inAuthMethod, &uiAuthMethod );
if ( siResult == eDSNoErr )
{
siResult = ParseLocalCacheUserData(inAuthAuthorityData, &networkNodename, &userRecordName, &userGUID);
result = dsOpenDirService(&aDirRef);
if (result == eDSNoErr)
{
netNode = dsBuildFromPathPriv( networkNodename, "/" );
if ( netNode == nil ) throw( (sInt32)eMemoryError );
dataBuffer = ::dsDataBufferAllocate( aDirRef, 1024 );
if ( dataBuffer == nil ) throw( (sInt32)eMemoryError );
result = dsFindDirNodes( aDirRef, dataBuffer, netNode, eDSiExact, &nodeCount, &tContinue );
if ( (result == eDSNoErr) && (nodeCount == 1) )
{
result = dsFindDirNodes( aDirRef, dataBuffer, nil, eDSAuthenticationSearchNodeName, &nodeCount, &tContinue );
if ( ( result == eDSNoErr ) && ( nodeCount == 1 ) )
{
result = dsGetDirNodeName( aDirRef, dataBuffer, 1, &pSearchNode );
if ( result == eDSNoErr )
{
result = dsOpenDirNode( aDirRef, pSearchNode, &aSearchNodeRef );
if ( pSearchNode != NULL )
{
dsDataListDeallocatePriv( pSearchNode );
free( pSearchNode );
pSearchNode = NULL;
}
if ( result == eDSNoErr )
{
pSearchNodeList = dsBuildFromPathPriv( kDS1AttrSearchPath, "/" );
if ( pSearchNodeList == nil ) throw( (sInt32)eMemoryError );
do
{
nodeCount = 0;
result = dsGetDirNodeInfo( aSearchNodeRef, pSearchNodeList, dataBuffer, false, &nodeCount, &attrListRef, nil );
if (result == eDSBufferTooSmall)
{
uInt32 bufSize = dataBuffer->fBufferSize;
dsDataBufferDeallocatePriv( dataBuffer );
dataBuffer = nil;
dataBuffer = ::dsDataBufferAllocate( aDirRef, bufSize * 2 );
}
} while (result == eDSBufferTooSmall);
if ( ( result == eDSNoErr ) && (nodeCount > 0) )
{
result = dsGetAttributeEntry( aSearchNodeRef, dataBuffer, attrListRef, 1, &attrValueListRef, &pAttrEntry );
if ( result != eDSNoErr ) throw( result );
for (aIndex=1; aIndex < (pAttrEntry->fAttributeValueCount+1); aIndex++)
{
result = dsGetAttributeValue( aSearchNodeRef, dataBuffer, aIndex, attrValueListRef, &pAttrValueEntry );
if ( result != eDSNoErr ) throw( result );
if ( pAttrValueEntry->fAttributeValueData.fBufferData == nil ) throw( (sInt32)eMemoryAllocError );
if (strcmp( networkNodename, pAttrValueEntry->fAttributeValueData.fBufferData ) == 0 )
{
bNetworkNodeReachable = true; dsDeallocAttributeValueEntry(aDirRef, pAttrValueEntry);
pAttrValueEntry = nil;
break;
}
dsDeallocAttributeValueEntry(aDirRef, pAttrValueEntry);
pAttrValueEntry = nil;
}
dsCloseAttributeList(attrListRef);
dsCloseAttributeValueList(attrValueListRef);
dsDeallocAttributeEntry(aDirRef, pAttrEntry);
pAttrEntry = nil;
result = ::dsCloseDirNode(aSearchNodeRef);
if ( result != eDSNoErr ) throw( result );
}
}
}
}
}
}
if ( siResult == eDSNoErr )
{
siResult = eDSAuthFailed;
switch( uiAuthMethod )
{
case kAuthSetPasswdAsRoot:
case kAuthWriteSecureHash:
case kAuthReadSecureHash:
case kAuthSecureHash:
siResult = CNiPlugIn::DoShadowHashAuth( inNodeRef,
inAuthMethod,
inContext,
inOutContinueData,
inAuthData,
outAuthData,
inAuthOnly,
isSecondary,
NULL, inGUIDString,
inNativeRecType );
break;
case kAuthChangePasswd:
if (bNetworkNodeReachable)
{
result = dsOpenDirNode(aDirRef, netNode, &aNodeRef);
if ( result == eDSNoErr)
{
siResult = dsDoDirNodeAuth( aNodeRef, inAuthMethod, inAuthOnly, inAuthData, outAuthData, &tContinue );
if (siResult == eDSNoErr)
{
siResult = CNiPlugIn::DoShadowHashAuth( inNodeRef,
inAuthMethod,
inContext,
inOutContinueData,
inAuthData,
outAuthData,
inAuthOnly,
isSecondary,
NULL, inGUIDString,
inNativeRecType );
}
}
}
break;
case kAuthNativeClearTextOK:
case kAuthNativeNoClearText:
case kAuthNativeMethod:
bAuthLocally = false;
if (bNetworkNodeReachable)
{
result = dsOpenDirNode(aDirRef, netNode, &aNodeRef);
if ( result == eDSNoErr)
{
siResult = dsDoDirNodeAuth( aNodeRef, inAuthMethod, true, inAuthData, outAuthData, &tContinue );
if (siResult == eDSNoErr)
{
siResult = CNiPlugIn::DoShadowHashAuth( inNodeRef,
inAuthMethod,
inContext,
inOutContinueData,
inAuthData,
outAuthData,
inAuthOnly,
isSecondary,
NULL, inGUIDString,
inNativeRecType );
if (siResult != eDSNoErr)
{
DBGLOG( kLogPlugin, "DoLocalCachedUserAuth::Local auth not sync'ed so try to set local password" );
authMethodPtr = dsDataNodeAllocateString( aDirRef, kDSStdAuthSetPasswdAsRoot );
if (authMethodPtr == nil ) throw( (sInt32)eMemoryError );
tmpContext = (sNIContextData *) calloc(1, sizeof(sNIContextData));
tmpContext->fDomain = inContext->fDomain;
tmpContext->fDomainName = inContext->fDomainName;
tmpContext->fRecType = inContext->fRecType;
tmpContext->fRecName = inContext->fRecName;
tmpContext->dirID = inContext->dirID;
tmpContext->offset = inContext->offset;
tmpContext->index = inContext->index;
tmpContext->fDontUseSafeClose = inContext->fDontUseSafeClose;
tmpContext->fUID = getuid();
tmpContext->fEffectiveUID = geteuid();
tmpContext->fAuthenticatedUserName = inContext->fAuthenticatedUserName;
tmpContext->fPWSRef = inContext->fPWSRef;
tmpContext->fPWSNodeRef = inContext->fPWSNodeRef;
tmpContext->bIsLocal = true;
siResult = CNiPlugIn::DoShadowHashAuth( inNodeRef,
authMethodPtr,
tmpContext,
inOutContinueData,
inAuthData,
outAuthData,
inAuthOnly,
isSecondary,
NULL, inGUIDString,
inNativeRecType );
free(tmpContext);
tmpContext = nil;
}
}
}
else
{
bAuthLocally = true;
}
}
else
{
bAuthLocally = true;
}
if (bAuthLocally)
{
siResult = CNiPlugIn::DoShadowHashAuth( inNodeRef,
inAuthMethod,
inContext,
inOutContinueData,
inAuthData,
outAuthData,
inAuthOnly,
isSecondary,
NULL, inGUIDString,
inNativeRecType );
}
break;
case kAuthSetPolicy:
case kAuthSetPasswd:
case kAuthSMB_NT_Key:
case kAuthSMB_LM_Key:
default:
siResult = eDSAuthMethodNotSupported;
break;
}
}
}
}
catch( sInt32 err )
{
siResult = err;
}
if (networkNodename != nil)
{
free(networkNodename);
networkNodename = nil;
}
if (userRecordName != nil)
{
free(userRecordName);
userRecordName = nil;
}
if (userGUID != nil)
{
free(userGUID);
userGUID = nil;
}
if ( dataBuffer != nil )
{
dsDataBufferDeallocatePriv( dataBuffer );
dataBuffer = nil;
}
if (netNode != nil)
{
dsDataListDeallocatePriv(netNode);
free(netNode);
netNode = NULL;
}
if (authMethodPtr != nil)
{
dsDataBufferDeallocatePriv( authMethodPtr );
authMethodPtr = nil;
}
if (aNodeRef != NULL)
{
dsCloseDirNode(aNodeRef);
aNodeRef = NULL;
}
if (aDirRef != NULL)
{
dsCloseDirService(aDirRef);
aDirRef = NULL;
}
return( siResult );
}
sInt32 CNiPlugIn::DoDisabledAuth ( tDirNodeReference inNodeRef, tDataNodePtr inAuthMethod,
sNIContextData* inContext,
sNIContinueData** inOutContinueData,
tDataBufferPtr inAuthData, tDataBufferPtr outAuthData,
bool inAuthOnly, bool isSecondary,
char* inAuthAuthorityData, char* inGUIDString,
const char* inNativeRecType )
{
return (sInt32)eDSAuthFailed;
}
sInt32 CNiPlugIn::DoPasswordServerAuth ( tDirNodeReference inNodeRef, tDataNodePtr inAuthMethod,
sNIContextData* inContext,
sNIContinueData** inOutContinueData,
tDataBufferPtr inAuthData, tDataBufferPtr outAuthData,
bool inAuthOnly, bool isSecondary, char* inAuthAuthorityData,
char* inGUIDString, const char* inNativeRecType )
{
sInt32 result = eDSAuthFailed;
sInt32 error;
uInt32 authMethod;
char *serverAddr;
char *uidStr = NULL;
long uidStrLen;
tDataBufferPtr authDataBuff = NULL;
tDataBufferPtr authDataBuffTemp = NULL;
char *nodeName = NULL;
char *userName = NULL;
char *password = NULL;
sNIContinueData *pContinue = NULL;
tContextData continueData = NULL;
if ( !inAuthAuthorityData || *inAuthAuthorityData == '\0' )
return eDSAuthParameterError;
try
{
serverAddr = strchr( inAuthAuthorityData, ':' );
if ( serverAddr )
{
uidStrLen = serverAddr - inAuthAuthorityData;
uidStr = (char *) calloc(1, uidStrLen+1);
if ( uidStr == nil ) throw( (sInt32)eMemoryError );
strncpy( uidStr, inAuthAuthorityData, uidStrLen );
serverAddr++;
DBGLOG( kLogPlugin, "DoPasswordServerAuth::" );
error = GetAuthMethod( inAuthMethod, &authMethod );
if ( error != eDSNoErr && error != eDSAuthMethodNotSupported )
throw( error );
switch( authMethod )
{
case kAuth2WayRandom:
if ( inOutContinueData == nil )
throw( (sInt32)eDSNullParameter );
if ( *inOutContinueData == nil )
{
pContinue = (sNIContinueData *)::calloc( 1, sizeof( sNIContinueData ) );
if ( pContinue == nil )
throw( (sInt32)eMemoryError );
gNIContinue->AddItem( pContinue, inNodeRef );
*inOutContinueData = pContinue;
authDataBuff = ::dsDataBufferAllocatePriv( uidStrLen + 1 );
if ( authDataBuff == nil ) throw ( (sInt32)eMemoryError );
strcpy( authDataBuff->fBufferData, uidStr );
authDataBuff->fBufferLength = uidStrLen;
}
else
{
pContinue = *inOutContinueData;
if ( gNIContinue->VerifyItem( pContinue ) == false )
throw( (sInt32)eDSInvalidContinueData );
authDataBuff = inAuthData;
}
break;
case kAuthSetPasswd:
case kAuthSetPolicy:
{
ni_id niDirID;
ni_namelist niValues;
ni_status niResult = NI_OK;
char* aaVersion = NULL;
char* aaTag = NULL;
char* aaData = NULL;
unsigned int idx;
sInt32 lookupResult;
char* endPtr = NULL;
error = GetUserNameFromAuthBuffer( inAuthData, 3, &userName );
if ( error != eDSNoErr ) throw( error );
error = IsValidRecordName ( userName, inNativeRecType, inContext->fDomain, niDirID );
if ( error != eDSNoErr ) throw( (sInt32)eDSAuthFailed );
gNetInfoMutex->Wait();
niResult = ni_lookupprop( inContext->fDomain, &niDirID,
"authentication_authority", &niValues );
gNetInfoMutex->Signal();
if (niResult != NI_OK) throw( (sInt32)eDSAuthFailed );
lookupResult = eDSAuthFailed;
for ( idx = 0; idx < niValues.ni_namelist_len && lookupResult == eDSAuthFailed; idx++ )
{
error = ParseAuthAuthority( niValues.ni_namelist_val[idx], &aaVersion, &aaTag, &aaData );
if (error != eDSNoErr)
lookupResult = eParameterError;
if ( error == eDSNoErr && strcmp(aaTag, kDSTagAuthAuthorityPasswordServer) == 0 )
{
endPtr = strchr( aaData, ':' );
if ( endPtr == NULL )
{
lookupResult = eParameterError;
}
else
{
*endPtr = '\0';
lookupResult = eDSNoErr;
}
}
if (aaVersion != NULL) {
free(aaVersion);
aaVersion = NULL;
}
if (aaTag != NULL) {
free(aaTag);
aaTag = NULL;
}
if (lookupResult != eDSNoErr && aaData != NULL) {
free(aaData);
aaData = NULL;
}
}
gNetInfoMutex->Wait();
if (niValues.ni_namelist_len > 0)
{
ni_namelist_free(&niValues);
}
gNetInfoMutex->Signal();
if ( lookupResult != eDSNoErr ) throw( (sInt32)eDSAuthFailed );
error = RepackBufferForPWServer(inAuthData, uidStr, 1, &authDataBuffTemp );
if ( error != eDSNoErr ) throw( error );
error = RepackBufferForPWServer(authDataBuffTemp, aaData, 3, &authDataBuff );
if (aaData != NULL) {
free(aaData);
aaData = NULL;
}
if ( error != eDSNoErr ) throw( error );
}
break;
case kAuthClearText:
case kAuthNativeClearTextOK:
case kAuthNativeNoClearText:
case kAuthCrypt:
{
tDataListPtr dataList = dsAuthBufferGetDataListAllocPriv(inAuthData);
if (dataList != NULL)
{
userName = dsDataListGetNodeStringPriv(dataList, 1);
password = dsDataListGetNodeStringPriv(dataList, 2);
dsDataListDeallocatePriv(dataList);
free(dataList);
dataList = NULL;
}
}
default:
error = RepackBufferForPWServer(inAuthData, uidStr, 1, &authDataBuff );
if ( error != eDSNoErr ) throw( error );
}
if ( inContext->fPWSRef == 0 )
{
error = ::dsOpenDirService( &inContext->fPWSRef );
if ( error != eDSNoErr ) throw( error );
}
if ( inContext->fPWSNodeRef == 0 )
{
nodeName = (char *)calloc(1,strlen(serverAddr)+17);
if ( nodeName == nil ) throw ( (sInt32)eMemoryError );
sprintf( nodeName, "/PasswordServer/%s", serverAddr );
error = PWOpenDirNode( inContext->fPWSRef, nodeName, &inContext->fPWSNodeRef );
if ( error != eDSNoErr ) throw( error );
}
if ( pContinue )
continueData = pContinue->fPassPlugContinueData;
result = dsDoDirNodeAuth( inContext->fPWSNodeRef, inAuthMethod, inAuthOnly,
authDataBuff, outAuthData, &continueData );
if ( result == eDSAuthNoAuthServerFound || result == eDSAuthServerError )
{
result = PWSetReplicaData( inContext, uidStr );
if ( result == eDSNoErr )
result = dsDoDirNodeAuth( inContext->fPWSNodeRef, inAuthMethod, inAuthOnly,
authDataBuff, outAuthData, &continueData );
}
if ( pContinue )
{
pContinue->fPassPlugContinueData = continueData;
if ( continueData == NULL )
{
gNIContinue->RemoveItem( pContinue );
if ( inOutContinueData == nil )
throw( (sInt32)eDSNullParameter );
*inOutContinueData = nil;
}
}
if ( (result == eDSNoErr) && (inAuthOnly == false) && (userName != NULL) && (password != NULL) )
{
result = AuthOpen( inContext, userName, password );
}
}
}
catch(sInt32 err )
{
result = err;
}
if ( nodeName )
free( nodeName );
if ( uidStr != NULL )
{
free( uidStr );
uidStr = NULL;
}
if ( userName != NULL )
{
free( userName );
userName = NULL;
}
if ( password != NULL )
{
free( password );
password = NULL;
}
if ( authDataBuff )
dsDataBufferDeallocatePriv( authDataBuff );
if ( authDataBuffTemp )
dsDataBufferDeallocatePriv( authDataBuffTemp );
return( result );
}
sInt32 CNiPlugIn::DoSetPassword ( sNIContextData *inContext, tDataBuffer *inAuthData, const char *inNativeRecType )
{
sInt32 siResult = eDSAuthFailed;
bool bFreePropList = false;
char *pData = nil;
char *userName = nil;
uInt32 userNameLen = 0;
char *userPwd = nil;
uInt32 userPwdLen = 0;
char *rootName = nil;
uInt32 rootNameLen = 0;
char *rootPwd = nil;
uInt32 rootPwdLen = 0;
uInt32 offset = 0;
uInt32 buffSize = 0;
uInt32 buffLen = 0;
ni_proplist niPropList;
#ifdef TIM_CLIENT_PRESENT
TIMHandle *pTimHndl = nil;
#endif
void *domain = nil;
gNetInfoMutex->Wait();
try
{
if ( inContext == nil ) throw( (sInt32)eDSAuthFailed );
if ( inAuthData == nil ) throw( (sInt32)eDSNullAuthStepData );
pData = inAuthData->fBufferData;
buffSize = inAuthData->fBufferSize;
buffLen = inAuthData->fBufferLength;
if ( buffLen > buffSize ) throw( (sInt32)eDSInvalidBuffFormat );
if ( buffLen < 4 * sizeof( unsigned long ) + 2 ) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &userNameLen, pData, sizeof( unsigned long ) );
pData += sizeof( unsigned long );
offset += sizeof( unsigned long );
if (userNameLen == 0) throw( (sInt32)eDSInvalidBuffFormat );
if (offset + userNameLen > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
userName = (char *)::calloc( 1, userNameLen + 1 );
::memcpy( userName, pData, userNameLen );
pData += userNameLen;
offset += userNameLen;
if (offset + sizeof( unsigned long ) > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &userPwdLen, pData, sizeof( unsigned long ) );
pData += sizeof( unsigned long );
offset += sizeof( unsigned long );
if (offset + userPwdLen > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
userPwd = (char *)::calloc( 1, userPwdLen + 1 );
::memcpy( userPwd, pData, userPwdLen );
pData += userPwdLen;
offset += userPwdLen;
if (offset + sizeof( unsigned long ) > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &rootNameLen, pData, sizeof( unsigned long ) );
pData += sizeof( unsigned long );
offset += sizeof( unsigned long );
if (rootNameLen == 0) throw( (sInt32)eDSInvalidBuffFormat );
if (rootNameLen > (buffSize - offset)) throw( (sInt32)eDSInvalidBuffFormat );
rootName = (char *)::calloc( 1, rootNameLen + 1 );
::memcpy( rootName, pData, rootNameLen );
pData += rootNameLen;
offset += rootNameLen;
if (sizeof( unsigned long ) > (buffSize - offset)) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &rootPwdLen, pData, sizeof( unsigned long ) );
pData += sizeof( unsigned long );
offset += sizeof( unsigned long );
if (rootPwdLen > (buffSize - offset)) throw( (sInt32)eDSInvalidBuffFormat );
rootPwd = (char *)::calloc( 1, rootPwdLen + 1 );
::memcpy( rootPwd, pData, rootPwdLen );
pData += rootPwdLen;
offset += rootPwdLen;
#ifdef TIM_CLIENT_PRESENT
if ( IsTimRunning() )
{
pTimHndl = ::timServerForDomain( inContext->fDomain );
if ( pTimHndl != nil )
{
siResult = ::timSetPasswordWithTIMHandle( pTimHndl, rootName, rootPwd, userName, userPwd );
timHandleFree( pTimHndl );
if ( siResult != eDSNoErr )
{
}
}
#ifdef DEBUG
if ( siResult != TimStatusOK )
{
DBGLOG1( kLogPlugin, "-- timSetPasswordForUser -- failed with %l.", siResult );
}
#endif
siResult = MapAuthResult( siResult );
}
else
#endif
{
char salt[3];
char hashPwd[ 32 ];
ni_id niDirID;
ni_index niWhere = 0;
ni_namelist niValue;
char *niPwd = nil;
domain = inContext->fDomain;
DBGLOG( kLogPlugin, "Attempting UNIX Crypt password change" );
siResult = IsValidRecordName ( rootName, inNativeRecType, domain, niDirID );
#ifdef DEBUG
if ( siResult != eDSNoErr ) throw( (sInt32)eDSAuthUnknownUser );
#else
if ( siResult != eDSNoErr ) throw( (sInt32)eDSAuthFailed );
#endif
siResult = ::ni_read( domain, &niDirID, &niPropList );
#ifdef DEBUG
if ( siResult != eDSNoErr ) throw( (sInt32)eDSAuthUnknownUser );
if ( niPropList.ni_proplist_val == nil ) throw( (sInt32)eDSAuthUnknownUser );
#else
if ( siResult != eDSNoErr ) throw( (sInt32)eDSAuthFailed );
if ( niPropList.ni_proplist_val == nil ) throw( (sInt32)eDSAuthFailed );
#endif
bFreePropList = true;
niWhere = ::ni_proplist_match( niPropList, "uid", nil );
if (niWhere == NI_INDEX_NULL) throw( (sInt32)eDSAuthFailed );
siResult = eDSAuthFailed;
niValue = niPropList.ni_proplist_val[ niWhere ].nip_val;
if ( !( ( (niValue.ni_namelist_val[ 0 ] != NULL) && (strcmp( "0", niValue.ni_namelist_val[ 0 ]) == 0) ) ||
(UserIsAdmin(rootName, domain)) ) )
{
throw( (sInt32)eDSAuthFailed );
}
niWhere = ::ni_proplist_match( niPropList, "passwd", nil );
#ifdef DEBUG
if (niWhere == NI_INDEX_NULL) throw( (sInt32)eDSAuthBadPassword );
siResult = eDSAuthBadPassword;
#else
if (niWhere == NI_INDEX_NULL) throw( (sInt32)eDSAuthFailed );
siResult = eDSAuthFailed;
#endif
niValue = niPropList.ni_proplist_val[ niWhere ].nip_val;
if ((niValue.ni_namelist_len > 0) && (niValue.ni_namelist_val != nil))
{
niPwd = niPropList.ni_proplist_val[ niWhere ].nip_val.ni_namelist_val[ 0 ];
}
else
{
niPwd = (char*)""; }
if (::strcmp(niPwd,"") != 0)
{
salt[ 0 ] = niPwd[0];
salt[ 1 ] = niPwd[1];
salt[ 2 ] = '\0';
::memset( hashPwd, 0, 32 );
::strcpy( hashPwd, ::crypt( rootPwd, salt ) );
siResult = eDSAuthFailed;
if ( ::strcmp( hashPwd, niPwd ) == 0 )
{
siResult = eDSNoErr;
}
}
else {
if (::strcmp(rootPwd,"") != 0)
{
siResult = eDSNoErr;
}
}
if (siResult == eDSNoErr)
{
if ( inContext->bIsLocal ) {
MigrateToShadowHash(domain, &niDirID, &niPropList, userName, userPwd);
}
else
{
const char *saltchars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./";
::memset( hashPwd, 0, 32 );
if ( ::strlen(userPwd) > 0 )
{
::srandom(getpid() + time(0));
salt[0] = saltchars[random() % 64];
salt[1] = saltchars[random() % 64];
salt[2] = '\0';
::strcpy( hashPwd, ::crypt( userPwd, salt ) );
}
siResult = IsValidRecordName ( userName, inNativeRecType, domain, niDirID );
#ifdef DEBUG
if ( siResult != eDSNoErr ) throw( (sInt32)eDSAuthUnknownUser );
#else
if ( siResult != eDSNoErr ) throw( (sInt32)eDSAuthFailed );
#endif
::ni_proplist_free( &niPropList );
bFreePropList = false;
siResult = ::ni_read( domain, &niDirID, &niPropList );
#ifdef DEBUG
if ( siResult != eDSNoErr ) throw( (sInt32)eDSAuthUnknownUser );
#else
if ( siResult != eDSNoErr ) throw( (sInt32)eDSAuthFailed );
#endif
bFreePropList = true;
niWhere = ::ni_proplist_match( niPropList, "passwd", nil );
if ( niWhere != NI_INDEX_NULL )
{
niValue = niPropList.ni_proplist_val[ niWhere ].nip_val;
siResult = NiLib2::DestroyDirVal( domain, &niDirID, (char*)"passwd", niValue );
}
siResult = NiLib2::InsertDirVal( domain, &niDirID, (char*)"passwd", hashPwd, 0 );
siResult = MapNetInfoErrors( siResult );
}
}
}
}
catch( sInt32 err )
{
siResult = err;
}
if ( bFreePropList )
{
::ni_proplist_free( &niPropList );
}
gNetInfoMutex->Signal();
if ( userName != nil )
{
free( userName );
userName = nil;
}
if ( userPwd != nil )
{
free( userPwd );
userPwd = nil;
}
if ( rootName != nil )
{
free( rootName );
rootName = nil;
}
if ( rootPwd != nil )
{
free( rootPwd );
rootPwd = nil;
}
return( siResult );
}
sInt32 CNiPlugIn::DoSetPasswordAsRoot ( sNIContextData *inContext, tDataBuffer *inAuthData, const char *inNativeRecType )
{
sInt32 siResult = eDSAuthFailed;
bool bFreePropList = false;
char *pData = nil;
char *userName = nil;
uInt32 userNameLen = 0;
char *newPasswd = nil;
uInt32 newPwdLen = 0;
uInt32 offset = 0;
uInt32 buffSize = 0;
uInt32 buffLen = 0;
ni_proplist niPropList;
#ifdef TIM_CLIENT_PRESENT
char *pTag = nil;
uInt32 uiCount = 0;
uInt32 i = 0;
sInt32 timResult = eDSAuthFailed;
bool done = false;
TIMHandle *pTimHndl = nil;
Buffer *pUserBuff = nil;
Buffer *pBuffArray = nil;
Buffer *pTmpBuff = nil;
#endif
void *domain = nil;
gNetInfoMutex->Wait();
try
{
if ( inContext == nil ) throw( (sInt32)eDSAuthFailed );
if ( inAuthData == nil ) throw( (sInt32)eDSNullAuthStepData );
pData = inAuthData->fBufferData;
buffSize = inAuthData->fBufferSize;
buffLen = inAuthData->fBufferLength;
domain = inContext->fDomain;
if ( buffLen > buffSize ) throw( (sInt32)eDSInvalidBuffFormat );
if ( buffLen < 2 * sizeof( unsigned long ) + 1 ) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &userNameLen, pData, sizeof( unsigned long ) );
pData += sizeof( unsigned long );
offset += sizeof( unsigned long );
if (userNameLen == 0) throw( (sInt32)eDSInvalidBuffFormat );
if (userNameLen > (buffSize - offset)) throw( (sInt32)eDSInvalidBuffFormat );
userName = (char *)::calloc( 1, userNameLen + 1 );
::memcpy( userName, pData, userNameLen );
pData += userNameLen;
offset += userNameLen;
if (offset + sizeof( unsigned long ) > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &newPwdLen, pData, sizeof( unsigned long ) );
pData += sizeof( unsigned long );
offset += sizeof( unsigned long );
if (newPwdLen > (buffSize - offset)) throw( (sInt32)eDSInvalidBuffFormat );
newPasswd = (char *)::calloc( 1, newPwdLen + 1 );
::memcpy( newPasswd, pData, newPwdLen );
pData += newPwdLen;
offset += newPwdLen;
if ( inContext->fEffectiveUID != 0 )
{
if ((inContext->fAuthenticatedUserName == NULL)
|| ((::strcmp(inContext->fAuthenticatedUserName, "root") != 0)
&& (::strcmp(inContext->fAuthenticatedUserName, userName) != 0)))
{
throw( (sInt32)eDSPermissionError );
}
}
#ifdef TIM_CLIENT_PRESENT
if ( IsTimRunning() )
{
pTimHndl = ::timServerForDomain( inContext->fDomain );
if ( pTimHndl != nil )
{
pUserBuff = ::bufferFromString( userName );
if ( pUserBuff != nil )
{
timResult = ::timGetTagsForUser( pTimHndl, pUserBuff, &pBuffArray );
if ( timResult == TimStatusOK )
{
uiCount = bufferArrayCount( pBuffArray );
while ( (i < uiCount) && !done )
{
pTmpBuff = bufferArrayBufferAtIndex( pBuffArray, i++ );
if ( pTmpBuff != nil )
{
pTag = bufferToString( pTmpBuff );
if ( pTag != nil )
{
timResult = ::timSetPasswordForUserAsRoot( userName, newPasswd, pTag );
#ifdef DEBUG
if ( timResult != TimStatusOK )
{
DBGLOG1( kLogPlugin, "-- timSetPasswordForUserAsRoot -- failed with %l.", timResult );
}
#endif
if ( timResult == TimStatusOK )
{
siResult = eDSNoErr;
done = true;
}
free( pTag );
pTag = nil;
}
::bufferRelease( pTmpBuff );
pTmpBuff = nil;
}
}
}
if ( pBuffArray != nil ) {
::bufferRelease( pBuffArray );
pBuffArray = nil;
}
::bufferRelease( pUserBuff );
pUserBuff = nil;
}
::timHandleFree( pTimHndl );
pTimHndl = nil;
} }
else
#endif
{
char salt[3];
char hashPwd[ 32 ];
ni_id niDirID;
ni_index niWhere = 0;
ni_namelist niValue;
DBGLOG( kLogPlugin, "Attempting UNIX Crypt password change" );
siResult = IsValidRecordName ( userName, inNativeRecType, domain, niDirID );
#ifdef DEBUG
if ( siResult != eDSNoErr ) throw( (sInt32)eDSAuthUnknownUser );
#else
if ( siResult != eDSNoErr ) throw( (sInt32)eDSAuthFailed );
#endif
siResult = ::ni_read( domain, &niDirID, &niPropList );
#ifdef DEBUG
if ( siResult != eDSNoErr ) throw( (sInt32)eDSAuthUnknownUser );
#else
if ( siResult != eDSNoErr ) throw( (sInt32)eDSAuthFailed );
#endif
bFreePropList = true;
niWhere = ::ni_proplist_match( niPropList, "passwd", nil );
if (siResult == eDSNoErr)
{
if ( inContext->bIsLocal ) {
MigrateToShadowHash(domain, &niDirID, &niPropList, userName, newPasswd);
}
else
{
const char *saltchars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./";
::memset( hashPwd, 0, 32 );
if ( ::strlen(newPasswd) > 0 )
{
::srandom(getpid() + time(0));
salt[0] = saltchars[random() % 64];
salt[1] = saltchars[random() % 64];
salt[2] = '\0';
::strcpy( hashPwd, ::crypt( newPasswd, salt ) );
}
if ( niWhere != NI_INDEX_NULL )
{
niValue = niPropList.ni_proplist_val[ niWhere ].nip_val;
siResult = NiLib2::DestroyDirVal( domain, &niDirID, (char*)"passwd", niValue );
}
siResult = NiLib2::InsertDirVal( domain, &niDirID, (char*)"passwd", hashPwd, 0 );
siResult = MapNetInfoErrors( siResult );
}
}
}
}
catch( sInt32 err )
{
siResult = err;
}
if ( bFreePropList )
{
::ni_proplist_free( &niPropList );
}
gNetInfoMutex->Signal();
if ( userName != nil )
{
free( userName );
userName = nil;
}
if ( newPasswd != nil )
{
free( newPasswd );
newPasswd = nil;
}
return( siResult );
}
sInt32 CNiPlugIn::DoChangePassword ( sNIContextData *inContext, tDataBuffer *inAuthData,
bool isSecondary, const char *inNativeRecType )
{
sInt32 siResult = eDSAuthFailed;
#ifdef TIM_CLIENT_PRESENT
TIMHandle *timHandle = nil;
#endif
bool bFreePropList = false;
char *pData = nil;
char *name = nil;
uInt32 nameLen = 0;
char *oldPwd = nil;
uInt32 OldPwdLen = 0;
char *newPwd = nil;
uInt32 newPwdLen = 0;
uInt32 offset = 0;
uInt32 buffSize = 0;
uInt32 buffLen = 0;
char *pathStr = nil;
void *domain = nil;
ni_proplist niPropList;
gNetInfoMutex->Wait();
try
{
if ( inContext == nil ) throw( (sInt32)eDSAuthFailed );
if ( inAuthData == nil ) throw( (sInt32)eDSNullAuthStepData );
pData = inAuthData->fBufferData;
buffSize = inAuthData->fBufferSize;
buffLen = inAuthData->fBufferLength;
if ( buffLen > buffSize ) throw( (sInt32)eDSInvalidBuffFormat );
if ( buffLen < 3 * sizeof( unsigned long ) + 1 ) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &nameLen, pData, sizeof( unsigned long ) );
pData += sizeof( unsigned long );
offset += sizeof( unsigned long );
if (nameLen == 0) throw( (sInt32)eDSInvalidBuffFormat );
if (offset + nameLen > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
name = (char *)::calloc( 1, nameLen + 1 );
::memcpy( name, pData, nameLen );
pData += nameLen;
offset += nameLen;
if (offset + sizeof( unsigned long ) > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &OldPwdLen, pData, sizeof( unsigned long ) );
pData += sizeof( unsigned long );
offset += sizeof( unsigned long );
if (offset + OldPwdLen > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
oldPwd = (char *)::calloc( 1, OldPwdLen + 1 );
::memcpy( oldPwd, pData, OldPwdLen );
pData += OldPwdLen;
offset += OldPwdLen;
if (offset + sizeof( unsigned long ) > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &newPwdLen, pData, sizeof( unsigned long ) );
pData += sizeof( unsigned long );
offset += sizeof( unsigned long );
if (offset + newPwdLen > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
newPwd = (char *)::calloc( 1, newPwdLen + 1 );
::memcpy( newPwd, pData, newPwdLen );
pData += newPwdLen;
offset += newPwdLen;
#ifdef TIM_CLIENT_PRESENT
if ( IsTimRunning() )
{
timHandle = ::timServerForDomain( inContext->fDomain );
if ( timHandle == nil ) throw( (sInt32)eDSAuthFailed );
siResult = ::timSetPasswordWithTIMHandle( timHandle, name, oldPwd, name, newPwd );
#ifdef DEBUG
if ( siResult != TimStatusOK )
{
DBGLOG1( kLogPlugin, "-- timSetPassword -- failed with %l.", siResult );
}
#endif
siResult = MapAuthResult( siResult );
::timHandleFree( timHandle );
timHandle = nil;
}
else
#endif
{
char salt[3];
char hashPwd[ 32 ];
ni_id niDirID;
ni_index niWhere = 0;
ni_namelist niValue;
char *niPwd = nil;
ni_status niStatus = NI_OK;
DBGLOG( kLogPlugin, "Attempting UNIX Crypt password change" );
pathStr = BuildDomainPathFromName( inContext->fDomainName );
if ( pathStr == nil ) throw( (sInt32)eDSAuthFailed );
niStatus = ::ni_open( nil, pathStr, &domain );
if ( niStatus != 0) throw( (sInt32)eDSAuthFailed );
niStatus = ::ni_setuser( domain, name );
niStatus = ::ni_setpassword( domain, oldPwd );
siResult = IsValidRecordName ( name, inNativeRecType, domain, niDirID );
#ifdef DEBUG
if ( siResult != eDSNoErr ) throw( (sInt32)eDSAuthUnknownUser );
#else
if ( siResult != eDSNoErr ) throw( (sInt32)eDSAuthFailed );
#endif
siResult = ::ni_read( domain, &niDirID, &niPropList );
#ifdef DEBUG
if ( siResult != eDSNoErr ) throw( (sInt32)eDSAuthUnknownUser );
if ( niPropList.ni_proplist_val == nil ) throw( (sInt32)eDSAuthUnknownUser );
#else
if ( siResult != eDSNoErr ) throw( (sInt32)eDSAuthFailed );
if ( niPropList.ni_proplist_val == nil ) throw( (sInt32)eDSAuthFailed );
#endif
bFreePropList = true;
niWhere = ::ni_proplist_match( niPropList, "passwd", nil );
#ifdef DEBUG
if (niWhere == NI_INDEX_NULL) throw( (sInt32)eDSAuthBadPassword );
siResult = eDSAuthBadPassword;
#else
if (niWhere == NI_INDEX_NULL) throw( (sInt32)eDSAuthFailed );
siResult = eDSAuthFailed;
#endif
niValue = niPropList.ni_proplist_val[ niWhere ].nip_val;
if ((niValue.ni_namelist_len > 0) && (niValue.ni_namelist_val != nil))
{
niPwd = niPropList.ni_proplist_val[ niWhere ].nip_val.ni_namelist_val[ 0 ];
}
else
{
niPwd = (char*)""; }
siResult = NiLib2::ValidateDir( name, &niPropList );
if ( siResult != NI_OK )
{
siResult = NiLib2::ValidateName( name, &niPropList, niWhere );
}
if ( siResult != eDSNoErr )
{
siResult = MapNetInfoErrors( siResult );
}
else if ( !isSecondary )
{
siResult = eDSAuthFailed;
if (::strcmp(niPwd,"") != 0)
{
salt[ 0 ] = niPwd[0];
salt[ 1 ] = niPwd[1];
salt[ 2 ] = '\0';
::memset( hashPwd, 0, 32 );
::strcpy( hashPwd, ::crypt( oldPwd, salt ) );
if ( ::strcmp( hashPwd, niPwd ) == 0 )
{
siResult = eDSNoErr;
}
}
else {
if (::strcmp(oldPwd,"") == 0)
{
siResult = eDSNoErr;
}
}
}
if (siResult == eDSNoErr)
{
if ( inContext->bIsLocal ) {
MigrateToShadowHash(domain, &niDirID, &niPropList, name, newPwd);
}
else
{
const char *saltchars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./";
::memset( hashPwd, 0, 32 );
if ( ::strlen(newPwd) > 0 )
{
::srandom(getpid() + time(0));
salt[0] = saltchars[random() % 64];
salt[1] = saltchars[random() % 64];
salt[2] = '\0';
::strcpy( hashPwd, ::crypt( newPwd, salt ) );
}
siResult = NiLib2::DestroyDirVal( domain, &niDirID, (char*)"passwd", niValue );
siResult = NiLib2::InsertDirVal( domain, &niDirID, (char*)"passwd", hashPwd, 0 );
siResult = MapNetInfoErrors( siResult );
}
}
}
}
catch( sInt32 err )
{
siResult = err;
}
if ( bFreePropList )
{
ni_proplist_free( &niPropList );
}
if ( domain != nil )
{
ni_free( domain );
domain = nil;
}
gNetInfoMutex->Signal();
if ( pathStr != nil )
{
free( pathStr );
pathStr = nil;
}
if ( name != nil )
{
free( name );
name = nil;
}
if ( newPwd != nil )
{
free( newPwd );
newPwd = nil;
}
if ( oldPwd != nil )
{
free( oldPwd );
oldPwd = nil;
}
return( siResult );
}
sInt32 CNiPlugIn::DoTimSMBAuth ( sNIContextData *inContext, tDataBuffer *inAuthData,
uInt32 inWhichOne )
{
sInt32 siResult = eDSAuthFailed;
#ifdef TIM_CLIENT_PRESENT
TIMHandle *timHandle = nil;
char *pData = nil;
char *pUserName = nil;
uInt32 userNameLen = 0;
char *pC8 = nil;
uInt32 c8Len = 0;
char *pP24 = nil;
uInt32 p24Len = 0;
uInt32 offset = 0;
uInt32 buffSize = 0;
uInt32 buffLen = 0;
gNetInfoMutex->Wait();
if ( !IsTimRunning() )
{
gNetInfoMutex->Signal();
return( eDSAuthMethodNotSupported );
}
try
{
if ( inAuthData == nil ) throw( (sInt32)eDSNullAuthStepData );
if ( inContext == nil ) throw( (sInt32)eDSNullParameter );
pData = inAuthData->fBufferData;
buffSize = inAuthData->fBufferSize;
buffLen = inAuthData->fBufferLength;
if ( buffLen > buffSize ) throw( (sInt32)eDSInvalidBuffFormat );
if ( buffLen < 3 * sizeof( unsigned long ) + 1 ) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &userNameLen, pData, sizeof( unsigned long ) );
pData += sizeof( unsigned long );
offset += sizeof( unsigned long );
if (userNameLen == 0) throw( (sInt32)eDSInvalidBuffFormat );
if (offset + userNameLen > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
pUserName = (char *)::calloc( 1, userNameLen + 1 );
::memcpy( pUserName, pData, userNameLen );
pData += userNameLen;
offset += userNameLen;
if (offset + sizeof( unsigned long ) > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &c8Len, pData, sizeof( unsigned long ) );
pData += sizeof( unsigned long );
offset += sizeof( unsigned long );
if (offset + c8Len > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
pC8 = (char *)::calloc( 1, c8Len + 1 );
::memcpy( pC8, pData, c8Len );
pData += c8Len;
offset += c8Len;
if (offset + sizeof( unsigned long ) > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &p24Len, pData, sizeof( unsigned long ) );
pData += sizeof( unsigned long );
offset += sizeof( unsigned long );
if (offset + p24Len > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
pP24 = (char *)::calloc( 1, p24Len + 1 );
::memcpy( pP24, pData, p24Len );
pData += p24Len;
offset += p24Len;
timHandle = timServerForDomain( inContext->fDomain );
if ( timHandle == nil ) throw( (sInt32)eDSAuthFailed );
switch ( inWhichOne )
{
case kAuthSMB_NT_Key:
siResult = ::timAuthenticateSMBNTKeyWithTIMHandle( timHandle, pUserName, pC8, pP24 );
break;
case kAuthSMB_LM_Key:
siResult = ::timAuthenticateSMBLMKeyWithTIMHandle( timHandle, pUserName, pC8, pP24 );
break;
}
timHandleFree( timHandle );
timHandle = nil;
#ifdef DEBUG
if ( siResult != TimStatusOK )
{
DBGLOG2( kLogPlugin, "-- timAuthenticateSMBLMKey -- failed with %l for key %l.", siResult, inWhichOne );
}
#endif
siResult = MapAuthResult( siResult );
}
catch( sInt32 err )
{
siResult = err;
}
gNetInfoMutex->Signal();
if ( pUserName != nil )
{
free( pUserName );
pUserName = nil;
}
if ( pC8 != nil )
{
free( pC8 );
pC8 = nil;
}
if ( pP24 != nil )
{
free( pP24 );
pP24 = nil;
}
#endif
return( siResult );
}
sInt32 CNiPlugIn::DoTimMultiPassAuth ( tDirNodeReference inNodeRef, tDataNodePtr inAuthMethod,
sNIContextData *inContext, sNIContinueData** inOutContinueData,
tDataBufferPtr inAuthData, tDataBufferPtr outAuthData,
bool inAuthOnly )
{
sInt32 siResult = eDSAuthFailed;
#ifdef TIM_CLIENT_PRESENT
tDataBuffer *authData = nil;
tDataBuffer *outData = nil;
TIMHandle *authHndl = nil;
Buffer *pAuthBuff = nil;
Buffer *pAuthOutBuff = nil;
CString *pAuthStr = nil;
sNIContinueData *pContinue = nil;
gNetInfoMutex->Wait(); if ( !IsTimRunning() )
{
gNetInfoMutex->Signal();
return( eDSAuthMethodNotSupported );
}
try
{
if ( inContext == nil ) throw( (sInt32)eDSNullDataBuff );
if ( inAuthData == nil ) throw( (sInt32)eDSNullAuthStepData );
if ( outAuthData == nil ) throw( (sInt32)eDSNullAuthStepData );
if ( inOutContinueData == nil ) throw( (sInt32)eDSNullParameter );
if ( *inOutContinueData == nil )
{
pContinue = (sNIContinueData *)::calloc( 1, sizeof( sNIContinueData ) );
gNIContinue->AddItem( pContinue, inNodeRef );
}
else
{
pContinue = *inOutContinueData;
if ( gNIContinue->VerifyItem( pContinue ) == false )
{
throw( (sInt32)eDSInvalidContinueData );
}
}
if ( pContinue->fAuthPass == 0 )
{
pAuthStr = GetAuthString( inAuthMethod );
if ( pAuthStr == nil ) throw( (sInt32)eDSAuthMethodNotSupported );
authHndl = ::timServerForDomain( inContext->fDomain );
if ( authHndl == nil ) throw( (sInt32)eDSAuthNoAuthServerFound );
pAuthBuff = ::bufferFromString( pAuthStr->GetData() );
siResult = ::timSessionStart( authHndl, 0, pAuthBuff);
::bufferRelease( pAuthBuff );
pAuthBuff = nil;
if ( siResult != eDSNoErr ) throw( siResult );
pContinue->fAuthHndl = authHndl;
delete( pAuthStr );
pAuthStr = nil;
}
else
{
if ( *inOutContinueData == NULL )
{
throw( (sInt32)eDSInvalidContext );
}
}
pContinue->fAuthPass++;
authData = inAuthData;
outData = outAuthData;
authHndl = (TIMHandle *)pContinue->fAuthHndl;
pAuthBuff = ::bufferFromData( authData->fBufferData, authData->fBufferLength );
siResult = ::timSessionStep( authHndl, pAuthBuff, &pAuthOutBuff );
::bufferRelease( pAuthBuff );
pAuthBuff = nil;
if ( (siResult != TimStatusOK) && (siResult != TimStatusContinue) )
{
::bufferRelease( pAuthOutBuff );
pAuthOutBuff = nil;
::timSessionEnd( authHndl );
authHndl = nil;
gNIContinue->RemoveItem( pContinue );
*inOutContinueData = nil;
if ( siResult != eDSNoErr ) throw( siResult );
}
if ( ::bufferLength( pAuthOutBuff ) <= outData->fBufferSize )
{
::memcpy( outData->fBufferData, pAuthOutBuff->data, pAuthOutBuff->length );
outData->fBufferLength = pAuthOutBuff->length;
::bufferRelease( pAuthOutBuff );
if ( siResult == TimStatusOK )
{
::timSessionEnd( authHndl );
authHndl = nil;
gNIContinue->RemoveItem( pContinue );
*inOutContinueData = nil;
}
else if ( siResult == TimStatusContinue )
{
pContinue->fAuthHndl = authHndl;
*inOutContinueData = pContinue;
siResult = eDSNoErr;
}
}
}
catch( sInt32 err )
{
siResult = err;
if ( siResult > -14000 )
{
#ifdef DEBUG
switch ( siResult )
{
case TimStatusUserUnknown:
siResult = eDSAuthUnknownUser;
break;
case TimStatusInvalidName:
siResult = eDSAuthInvalidUserName;
break;
case TimStatusUnrecoverablePassword:
siResult = eDSAuthCannotRecoverPasswd;
break;
case TimStatusAuthenticationFailed:
siResult = eDSAuthFailed;
break;
default:
DBGLOG1( kLogPlugin, "Authentication Server Error = %d.", siResult);
siResult = eDSAuthServerError;
break;
}
if ( siResult != TimStatusOK )
{
DBGLOG1( kLogPlugin, "-- DoMultiPassAuth -- failed with %l.", siResult );
}
#else
siResult = eDSAuthFailed;
#endif
}
}
gNetInfoMutex->Signal();
#endif
return( siResult );
}
sInt32 CNiPlugIn::DoNodeNativeAuth ( sNIContextData *inContext, tDataBuffer *inAuthData, bool inAuthOnly, const char *inNativeRecType )
{
sInt32 siResult = eDSAuthFailed;
#ifdef TIM_CLIENT_PRESENT
TIMHandle *timHandle = nil;
char *pathStr = nil;
char *pData = nil;
char *userName = nil;
uInt32 nameLen = 0;
char *pwd = nil;
uInt32 pwdLen = 0;
gNetInfoMutex->Wait();
if ( !IsTimRunning() )
{
gNetInfoMutex->Signal();
return( eDSAuthMethodNotSupported );
}
try
{
if ( inAuthData != nil )
{
pData = inAuthData->fBufferData;
if ( pData != nil )
{
{
::memcpy( &nameLen, pData, sizeof( unsigned long ) );
if ( nameLen != 0 )
{
userName = (char *)::calloc( 1, nameLen + 1 );
pData += sizeof( unsigned long );
::memcpy( userName, pData, nameLen );
pData += nameLen;
::memcpy( &pwdLen, pData, sizeof( unsigned long ) );
if ( pwdLen != 0 )
{
pwd = (char *)::calloc( 1, pwdLen + 1 );
pData += sizeof( unsigned long );
::memcpy( pwd, pData, pwdLen );
pData += pwdLen;
DBGLOG( kLogPlugin, "Attempting Auth Server Node Native Authentication." );
timHandle = timServerForDomain( inContext->fDomain );
if ( timHandle == nil ) throw( (sInt32)eDSAuthFailed );
siResult = ::timAuthenticate2WayRandomWithTIMHandle( timHandle, userName, pwd );
free( pwd );
pwd = nil;
timHandleFree( timHandle );
timHandle = nil;
#ifdef DEBUG
if ( siResult != TimStatusOK )
{
DBGLOG1( kLogPlugin, "-- timAuthenticate2WayRandom -- failed with %l.", siResult );
}
#endif
siResult = MapAuthResult( siResult );
if ( (siResult == eDSNoErr) && (inAuthOnly == false) )
{
siResult = AuthOpen( inContext, userName, pwd );
}
}
else
{
#ifdef DEBUG
siResult = eDSAuthInBuffFormatError;
#else
siResult = eDSAuthFailed;
#endif
}
free( userName );
userName = nil;
}
else
{
#ifdef DEBUG
siResult = eDSAuthInBuffFormatError;
#else
siResult = eDSAuthFailed;
#endif
}
}
}
else
{
siResult = eDSNullDataBuff;
}
}
else
{
siResult = eDSNullDataBuff;
}
}
catch( sInt32 err )
{
DBGLOG1( kLogPlugin, "2 way random authentication error %l.", err );
siResult = err;
}
gNetInfoMutex->Signal();
if ( pathStr != nil )
{
free( pathStr );
pathStr = nil;
}
#endif
return( siResult );
}
sInt32 CNiPlugIn::DoUnixCryptAuth ( sNIContextData *inContext, tDataBuffer *inAuthData, bool inAuthOnly, const char *inNativeRecType )
{
sInt32 siResult = eDSAuthFailed;
bool bFreePropList = false;
ni_index niWhere = 0;
char *pData = nil;
char *niPwd = nil;
char *name = nil;
uInt32 nameLen = 0;
char *pwd = nil;
uInt32 pwdLen = 0;
uInt32 offset = 0;
uInt32 buffSize = 0;
uInt32 buffLen = 0;
void *domain = nil;
char salt[ 9 ];
char hashPwd[ 32 ];
ni_id niDirID;
ni_proplist niPropList;
gNetInfoMutex->Wait();
try
{
domain = inContext->fDomain;
#ifdef DEBUG
if ( inAuthData == nil ) throw( (sInt32)eDSAuthParameterError );
#else
if ( inAuthData == nil ) throw( (sInt32)eDSAuthFailed );
#endif
pData = inAuthData->fBufferData;
buffSize = inAuthData->fBufferSize;
buffLen = inAuthData->fBufferLength;
if (buffLen > buffSize) throw( (sInt32)eDSInvalidBuffFormat );
if (offset + (2 * sizeof( unsigned long) + 1) > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
::memcpy( &nameLen, pData, sizeof( unsigned long ) );
pData += sizeof( unsigned long );
offset += sizeof( unsigned long );
#ifdef DEBUG
if (nameLen == 0) throw( (sInt32)eDSAuthUnknownUser );
if (nameLen > 256) throw( (sInt32)eDSInvalidBuffFormat );
if (offset + nameLen > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
#else
if (nameLen == 0) throw( (sInt32)eDSAuthFailed );
if (nameLen > 256) throw( (sInt32)eDSAuthFailed );
if (offset + nameLen > buffLen) throw( (sInt32)eDSAuthFailed );
#endif
name = (char *)::calloc( nameLen + 1, sizeof( char ) );
::memcpy( name, pData, nameLen );
pData += nameLen;
offset += nameLen;
DBGLOG( kLogPlugin, "Attempting UNIX Crypt authentication" );
siResult = IsValidRecordName ( name, inNativeRecType, domain, niDirID );
#ifdef DEBUG
if ( siResult != eDSNoErr ) throw( (sInt32)eDSAuthUnknownUser );
#else
if ( siResult != eDSNoErr ) throw( (sInt32)eDSAuthFailed );
#endif
siResult = ::ni_read( domain, &niDirID, &niPropList );
#ifdef DEBUG
if ( siResult != eDSNoErr ) throw( (sInt32)eDSAuthUnknownUser );
if ( niPropList.ni_proplist_val == nil ) throw( (sInt32)eDSAuthUnknownUser );
#else
if ( siResult != eDSNoErr ) throw( (sInt32)eDSAuthFailed );
if ( niPropList.ni_proplist_val == nil ) throw( (sInt32)eDSAuthFailed );
#endif
bFreePropList = true;
niWhere = ::ni_proplist_match( niPropList, "passwd", nil );
#ifdef DEBUG
if (niWhere == NI_INDEX_NULL) throw( (sInt32)eDSAuthBadPassword );
siResult = eDSAuthBadPassword;
#else
if (niWhere == NI_INDEX_NULL) throw( (sInt32)eDSAuthFailed );
siResult = eDSAuthFailed;
#endif
if ((niPropList.ni_proplist_val[ niWhere ].nip_val.ni_namelist_len > 0)
&& (niPropList.ni_proplist_val[ niWhere ].nip_val.ni_namelist_val != nil))
{
niPwd = niPropList.ni_proplist_val[ niWhere ].nip_val.ni_namelist_val[ 0 ];
}
else
{
niPwd = (char*)""; }
#ifdef DEBUG
if (offset + sizeof( unsigned long ) > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
#else
if (offset + sizeof( unsigned long ) > buffLen) throw( (sInt32)eDSAuthFailed );
#endif
::memcpy( &pwdLen, pData, sizeof( unsigned long ) );
pData += sizeof( unsigned long );
offset += sizeof( unsigned long );
#ifdef DEBUG
if (offset + pwdLen > buffLen) throw( (sInt32)eDSInvalidBuffFormat );
if (pwdLen > 256) throw( (sInt32)eDSAuthFailed );
#else
if (offset + pwdLen > buffLen) throw( (sInt32)eDSAuthFailed );
if (pwdLen > 256) throw( (sInt32)eDSAuthFailed );
#endif
pwd = (char *)::calloc( pwdLen + 1, sizeof( char ) );
::memcpy( pwd, pData, pwdLen );
if (::strcmp(niPwd,"") != 0)
{
salt[ 0 ] = niPwd[0];
salt[ 1 ] = niPwd[1];
salt[ 2 ] = '\0';
::memset( hashPwd, 0, 32 );
::strcpy( hashPwd, ::crypt( pwd, salt ) );
siResult = eDSAuthFailed;
if ( ::strcmp( hashPwd, niPwd ) == 0 )
{
siResult = eDSNoErr;
}
}
else {
if ( ::strcmp(pwd,"") == 0 )
{
siResult = eDSNoErr;
}
}
if (siResult == eDSNoErr)
{
if ( inContext->bIsLocal && (strlen(pwd) < 8) ) {
MigrateToShadowHash(domain, &niDirID, &niPropList, name, pwd);
}
if (inAuthOnly == false)
{
siResult = AuthOpen( inContext, name, pwd );
}
}
}
catch( sInt32 err )
{
DBGLOG1( kLogPlugin, "Crypt authentication error %l", err );
siResult = err;
}
if ( bFreePropList )
{
::ni_proplist_free( &niPropList );
}
gNetInfoMutex->Signal();
if ( name != nil )
{
free( name );
name = nil;
}
if ( pwd != nil )
{
free( pwd );
pwd = nil;
}
return( siResult );
}
sInt32 CNiPlugIn::MigrateToShadowHash( void *inDomain, ni_id *inNIDirID, ni_proplist *inNIPropList, const char *inUserName, const char *inPassword )
{
sInt32 siResult = eDSAuthFailed;
unsigned char generatedHashes[kHashTotalLength] = {0};
SHA_CTX sha_context = {};
unsigned char digestData[kHashSecureLength] = {0};
ni_namelist niAttribute;
ni_namelist niValues;
ni_index niWhere = NI_INDEX_NULL;
niWhere = ::ni_proplist_match( *inNIPropList, "generateduid", nil );
char* GUIDString = nil; if (niWhere != NI_INDEX_NULL)
{
if ((inNIPropList->ni_proplist_val[ niWhere ].nip_val.ni_namelist_len > 0)
&& (inNIPropList->ni_proplist_val[ niWhere ].nip_val.ni_namelist_val != nil))
{
GUIDString = inNIPropList->ni_proplist_val[ niWhere ].nip_val.ni_namelist_val[ 0 ];
}
}
if (GUIDString == nil)
{
CFUUIDRef myUUID;
CFStringRef myUUIDString;
char genUIDValue[100];
memset( genUIDValue, 0, 100 );
myUUID = CFUUIDCreate(kCFAllocatorDefault);
myUUIDString = CFUUIDCreateString(kCFAllocatorDefault, myUUID);
CFStringGetCString(myUUIDString, genUIDValue, 100, kCFStringEncodingASCII);
CFRelease(myUUID);
CFRelease(myUUIDString);
GUIDString = strdup(genUIDValue);
NI_INIT( &niValues );
::ni_namelist_insert( &niValues, GUIDString, NI_INDEX_NULL );
siResult = DoAddAttribute( inDomain, inNIDirID, "generateduid", niValues );
::ni_namelist_free( &niValues );
}
CalculateSMBNTHash(inPassword,generatedHashes);
CalculateSMBLANManagerHash(inPassword,generatedHashes+kHashShadowOneLength);
SHA1_Init(&sha_context);
SHA1_Update(&sha_context, (unsigned char *)inPassword, strlen(inPassword));
SHA1_Final(digestData, &sha_context);
memmove(generatedHashes+kHashShadowBothLength, digestData, kHashSecureLength);
siResult = WriteShadowHash(inUserName, GUIDString, generatedHashes);
if (siResult == eDSNoErr)
{
NI_INIT( &niAttribute );
::ni_namelist_insert( &niAttribute, "authentication_authority", NI_INDEX_NULL );
siResult = NiLib2::DestroyDirProp( inDomain, inNIDirID, niAttribute );
siResult = MapNetInfoErrors( siResult );
::ni_namelist_free( &niAttribute );
NI_INIT( &niAttribute );
::ni_namelist_insert( &niAttribute, "passwd", NI_INDEX_NULL );
siResult = NiLib2::DestroyDirProp( inDomain, inNIDirID, niAttribute );
siResult = MapNetInfoErrors( siResult );
::ni_namelist_free( &niAttribute );
NI_INIT( &niValues );
::ni_namelist_insert( &niValues, kDSValueAuthAuthorityShadowHash, NI_INDEX_NULL );
siResult = DoAddAttribute( inDomain, inNIDirID, "authentication_authority", niValues );
::ni_namelist_free( &niValues );
NI_INIT( &niValues );
::ni_namelist_insert( &niValues, kDSValueNonCryptPasswordMarker, NI_INDEX_NULL );
siResult = DoAddAttribute( inDomain, inNIDirID, "passwd", niValues );
::ni_namelist_free( &niValues );
}
return(siResult);
}
sInt32 CNiPlugIn::ValidateDigest ( sNIContextData *inContext, tDataBuffer *inAuthData, uInt32 inAuthMethod )
{
sInt32 siResult = eDSAuthFailed;
#ifdef TIM_CLIENT_PRESENT
TIMHandle *pTimHndl = nil;
char *pathStr = nil;
char *pData = nil;
char *pUserName = nil;
uInt32 nameLen = 0;
char *pChallenge = nil;
uInt32 chalLen = 0;
char *pResponse = nil;
uInt32 respLen = 0;
sInt32 siBuffErr = 0;
#ifdef DEBUG
siBuffErr = eDSAuthInBuffFormatError;
#else
siBuffErr = eDSAuthFailed;
#endif
gNetInfoMutex->Wait();
if ( !IsTimRunning() )
{
gNetInfoMutex->Signal();
return( eDSAuthMethodNotSupported );
}
try
{
if ( inAuthData != nil )
{
pData = inAuthData->fBufferData;
if ( pData != nil )
{
::memcpy( &nameLen, pData, sizeof( unsigned long ) );
if ( nameLen != 0 )
{
pUserName = (char *)::calloc( 1, nameLen + 1 );
pData += sizeof( unsigned long );
::memcpy( pUserName, pData, nameLen );
pData += nameLen;
::memcpy( &chalLen, pData, sizeof( unsigned long ) );
if ( chalLen != 0 )
{
pChallenge = (char *)::calloc( 1, chalLen + 1 );
pData += sizeof( unsigned long );
::memcpy( pChallenge, pData, chalLen );
pData += chalLen;
::memcpy( &respLen, pData, sizeof( unsigned long ) );
if ( respLen != 0 )
{
pResponse = (char *)::calloc( 1, respLen + 1 );
pData += sizeof( unsigned long );
::memcpy( pResponse, pData, respLen );
pData += respLen;
DBGLOG( kLogPlugin, "Attempting Auth ValidateDigest." );
pTimHndl = ::timServerForDomain( inContext->fDomain );
if ( pTimHndl == nil ) throw( (sInt32)eDSAuthFailed );
if ( inAuthMethod == kAuthAPOP )
{
siResult = ::timAuthenticateAPOPWithTIMHandle( pTimHndl, pUserName, pChallenge, pResponse );
}
else if ( inAuthMethod == kAuthCRAM_MD5 )
{
siResult = ::timAuthenticateCRAM_MD5WithTIMHandle( pTimHndl, pUserName, pChallenge, pResponse );
}
else
{
siResult = TimStatusServiceUnavailable;
}
free( pResponse );
pResponse = nil;
timHandleFree( pTimHndl );
pTimHndl = nil;
#ifdef DEBUG
if ( siResult != TimStatusOK )
{
DBGLOG1( kLogPlugin, "-- timAuthenticateCRAM_MD5WithTIMHandle -- failed with %l.", siResult );
}
#endif
siResult = MapAuthResult( siResult );
free( pResponse );
pResponse = nil;
}
else
{
siResult = siBuffErr;
}
free( pChallenge );
pChallenge = nil;
}
else
{
siResult = siBuffErr;
}
free( pUserName );
pUserName = nil;
}
else
{
siResult = siBuffErr;
}
}
else
{
siResult = eDSNullDataBuff;
}
}
else
{
siResult = eDSNullDataBuff;
}
}
catch( sInt32 err )
{
DBGLOG1( kLogPlugin, "2 way random authentication error %l.", err );
siResult = err;
}
gNetInfoMutex->Signal();
if ( pathStr != nil )
{
free( pathStr );
pathStr = nil;
}
#endif
return( siResult );
}
sInt32 CNiPlugIn::AuthOpen ( sNIContextData *inContext, const char * inUserName,
const char * inPassword )
{
sInt32 siResult = eDSAuthFailed;
void *domain = nil;
char *pathStr = nil;
gNetInfoMutex->Wait();
try
{
if ( inContext == nil ) throw( (sInt32)eDSAuthFailed );
if ( inUserName == nil ) throw( (sInt32)eDSAuthFailed );
if ( inPassword == nil ) throw( (sInt32)eDSAuthFailed );
pathStr = BuildDomainPathFromName( inContext->fDomainName );
if ( pathStr == nil ) throw( (sInt32)eDSAuthFailed );
siResult = ::ni_open( nil, pathStr, &domain );
if ( siResult != eDSNoErr ) throw( (sInt32)eDSAuthFailed );
siResult = ::ni_setuser( domain, inUserName );
if ( siResult != eDSNoErr ) throw( (sInt32)eDSAuthFailed );
siResult = ::ni_setpassword( domain, inPassword );
if ( siResult != eDSNoErr ) throw( (sInt32)eDSAuthFailed );
if ( siResult == NI_OK )
{
if ( inContext->fDontUseSafeClose )
{
::ni_free(inContext->fDomain);
}
else if (inContext->fDomainName != nil)
{
CNetInfoPlugin::SafeClose( inContext->fDomainName );
}
inContext->fDomain = domain;
inContext->fDontUseSafeClose = true;
if ( inContext->fAuthenticatedUserName != NULL )
{
free( inContext->fAuthenticatedUserName );
}
if (UserIsAdmin(inUserName, domain)) {
inContext->fAuthenticatedUserName = strdup( "root" );
} else {
inContext->fAuthenticatedUserName = strdup( inUserName );
}
}
}
catch( sInt32 err )
{
if ( domain != nil )
{
::ni_free(domain);
domain = nil;
}
siResult = err;
}
gNetInfoMutex->Signal();
return siResult;
}
sInt32 CNiPlugIn::VerifyPatternMatch ( const tDirPatternMatch inPatternMatch )
{
sInt32 siResult = eDSNoErr;
switch ( inPatternMatch )
{
case eDSExact:
case eDSStartsWith:
case eDSEndsWith:
case eDSContains:
case eDSLessThan:
case eDSGreaterThan:
case eDSLessEqual:
case eDSGreaterEqual:
case eDSiExact:
case eDSiStartsWith:
case eDSiEndsWith:
case eDSiContains:
case eDSiLessThan:
case eDSiGreaterThan:
case eDSiLessEqual:
case eDSiGreaterEqual:
case eDSAnyMatch:
siResult = eDSNoErr;
break;
default:
siResult = eDSInvalidPatternMatchType;
break;
}
return( siResult );
}
char* CNiPlugIn::MapAttrToNetInfoType ( const char *inAttrType )
{
char *outResult = nil;
uInt32 uiStrLen = 0;
uInt32 uiNativeLen = ::strlen( kDSNativeAttrTypePrefix );
uInt32 uiStdLen = ::strlen( kDSStdAttrTypePrefix );
if ( inAttrType != nil )
{
uiStrLen = ::strlen( inAttrType );
if ( ::strncmp( inAttrType, kDSNativeAttrTypePrefix, uiNativeLen ) == 0 )
{
if ( uiStrLen > uiNativeLen )
{
uiStrLen = uiStrLen - uiNativeLen;
outResult = new char[ uiStrLen + 1 ];
::strcpy( outResult, inAttrType + uiNativeLen );
}
}
else if ( ::strncmp( inAttrType, kDSStdAttrTypePrefix, uiStdLen ) == 0 )
{
for ( int i = 0; i < kAttrConsts; i++ )
{
if ( ::strcmp( inAttrType, sAttrMap[ i ][ 0 ] ) == 0 )
{
outResult = new char[ ::strlen( sAttrMap[ i ][ 1 ] ) + 1 ];
::strcpy( outResult, sAttrMap[ i ][ 1 ] );
break;
}
}
}
else if ( ::strcmp( inAttrType, kDSAttributesAll ) == 0 )
{
outResult = new char[ ::strlen( kDSAttributesAll ) + 1 ];
::strcpy( outResult, kDSAttributesAll );
}
else if ( ::strcmp( inAttrType, kDSAttributesStandardAll ) == 0 )
{
outResult = new char[ ::strlen( kDSAttributesStandardAll ) + 1 ];
::strcpy( outResult, kDSAttributesStandardAll );
}
}
return( outResult );
}
char* CNiPlugIn::MapNetInfoAttrToDSType ( const char *inAttrType )
{
char *outResult = nil;
if ( inAttrType != nil )
{
for ( int i = 0; i < kAttrConsts; i++ )
{
if ( ::strcmp( inAttrType, sAttrMap[ i ][ 1 ] ) == 0 )
{
outResult = new char[ ::strlen( sAttrMap[ i ][ 0 ] ) + 1 ];
::strcpy( outResult, sAttrMap[ i ][ 0 ] );
break;
}
}
if ( outResult == nil )
{
outResult = new char[ ::strlen( kDSNativeAttrTypePrefix ) + ::strlen( inAttrType ) + 1 ];
::strcpy( outResult, kDSNativeAttrTypePrefix );
::strcat( outResult, inAttrType );
}
}
return( outResult );
}
char* CNiPlugIn::MapRecToNetInfoType ( const char *inRecType )
{
char *outResult = nil;
uInt32 uiStrLen = 0;
uInt32 uiNativeLen = ::strlen( kDSNativeRecordTypePrefix );
uInt32 uiStdLen = ::strlen( kDSStdRecordTypePrefix );
if ( inRecType != nil )
{
uiStrLen = ::strlen( inRecType );
if ( ::strncmp( inRecType, kDSNativeRecordTypePrefix, uiNativeLen ) == 0 )
{
if ( uiStrLen > uiNativeLen )
{
uiStrLen = uiStrLen - uiNativeLen;
outResult = new char[ uiStrLen + 2 ];
::strcpy( outResult, inRecType + uiNativeLen );
}
}
else if ( ::strncmp( inRecType, kDSStdRecordTypePrefix, uiStdLen ) == 0 )
{
for ( int i = 0; i < kRecConsts; i++ )
{
if ( ::strcmp( inRecType, sRecMap[ i ][ 0 ] ) == 0 )
{
outResult = new char[ ::strlen( sRecMap[ i ][ 1 ] ) + 1 ];
::strcpy( outResult, sRecMap[ i ][ 1 ] );
break;
}
}
}
}
return( outResult );
}
char* CNiPlugIn::MapNetInfoRecToDSType ( const char *inRecType )
{
char *outResult = nil;
if ( inRecType != nil )
{
for ( int i = 0; i < kRecConsts; i++ )
{
if ( ::strcmp( inRecType, sRecMap[ i ][ 1 ] ) == 0 )
{
outResult = new char[ ::strlen( sRecMap[ i ][ 0 ] ) + 1 ];
::strcpy( outResult, sRecMap[ i ][ 0 ] );
break;
}
}
if ( outResult == nil )
{
outResult = new char[ ::strlen( kDSNativeRecordTypePrefix ) + ::strlen( inRecType ) + 1 ];
::strcpy( outResult, kDSNativeRecordTypePrefix );
::strcat( outResult, inRecType );
}
}
return( outResult );
}
CString* CNiPlugIn::GetAuthTypeStr ( const char *inNativeAuthStr )
{
CString *pOutString = nil;
if ( inNativeAuthStr == nil )
{
return( nil );
}
pOutString = new CString( 128 );
if ( pOutString == nil )
{
return( nil );
}
#ifdef TIM_CLIENT_PRESENT
if ( ::strcmp( inNativeAuthStr, AppleStandardCleartext ) == 0 )
{
pOutString->Set( kDSStdAuthClearText );
}
else if ( ::strcmp( inNativeAuthStr, AppleStandardTwoWay ) == 0 )
{
pOutString->Set( kDSStdAuth2WayRandom );
}
else if ( ::strcmp( inNativeAuthStr, AppleStandardSMBNTKey ) == 0 )
{
pOutString->Set( kDSStdAuthSMB_NT_Key );
}
else if ( ::strcmp( inNativeAuthStr, AppleStandardSMBLMKey ) == 0 )
{
pOutString->Set( kDSStdAuthSMB_LM_Key );
}
else
#endif
{
pOutString->Set( kDSNativeAuthMethodPrefix );
pOutString->Append( inNativeAuthStr );
}
return( pOutString );
}
CString* CNiPlugIn::GetAuthString ( tDataNode *inData )
{
CString *pOutString = nil;
#ifdef TIM_CLIENT_PRESENT
char *p = nil;
uInt32 uiNativeLen = 0;
uInt32 uiStrLen = 0;
if ( inData == nil )
{
return( nil );
}
pOutString = new CString( 128 );
if ( pOutString == nil )
{
return( nil );
}
p = (char *)inData->fBufferData;
if ( ::strcmp( p, kDSStdAuthClearText ) == 0 )
{
pOutString->Set( AppleStandardCleartext );
}
else if ( (::strcmp( p, kDSStdAuthNodeNativeClearTextOK ) == 0) ||
(::strcmp( p, kDSStdAuthNodeNativeNoClearText) == 0 ) )
{
pOutString->Set( AppleStandardTwoWay );
}
else if ( ::strcmp( p, kDSStdAuth2WayRandom ) == 0 )
{
pOutString->Set( AppleStandardTwoWay );
}
else if ( ::strcmp( p, kDSStdAuthSetPasswd ) == 0 )
{
pOutString->Set( AppleStandardSetPassword );
}
else if ( ::strcmp( p, kDSStdAuthChangePasswd ) == 0 )
{
pOutString->Set( AppleSetPasswordV2 );
}
else if ( ::strcmp( p, kDSStdAuthSetPasswdAsRoot ) == 0 )
{
pOutString->Set( AppleSetPasswordV2 );
}
else if ( ::strcmp( p, kDSStdAuthSMB_NT_Key ) == 0 )
{
pOutString->Set( AppleStandardSMBNTKey );
}
else if ( ::strcmp( p, kDSStdAuthSMB_LM_Key ) == 0 )
{
pOutString->Set( AppleStandardSMBLMKey );
}
else
{
uiStrLen = ::strlen( p );
uiNativeLen = ::strlen( kDSNativeAuthMethodPrefix );
if ( ::strncmp( p, kDSNativeAuthMethodPrefix, uiNativeLen ) == 0 )
{
if ( uiStrLen > uiNativeLen )
{
uiStrLen = uiStrLen - uiNativeLen;
pOutString->Set( p + uiNativeLen );
}
}
else
{
delete( pOutString );
pOutString = nil;
}
}
#endif
return( pOutString );
}
sInt32 CNiPlugIn::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;
DBGLOG1( kLogPlugin, "Using authentication method %s.", 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, kDSStdAuth2WayRandom ) == 0 )
{
*outAuthMethod = kAuth2WayRandom;
}
else if ( ::strcmp( p, kDSStdAuth2WayRandomChangePasswd ) == 0 )
{
*outAuthMethod = kAuth2WayRandomChangePass;
}
else if ( ::strcmp( p, kDSStdAuthSMB_NT_Key ) == 0 )
{
*outAuthMethod = kAuthSMB_NT_Key;
}
else if ( ::strcmp( p, kDSStdAuthSMB_LM_Key ) == 0 )
{
*outAuthMethod = kAuthSMB_LM_Key;
}
else if ( ::strcmp( p, kDSStdAuthSecureHash ) == 0 )
{
*outAuthMethod = kAuthSecureHash;
}
else if ( ::strcmp( p, kDSStdAuthReadSecureHash ) == 0 )
{
*outAuthMethod = kAuthReadSecureHash;
}
else if ( ::strcmp( p, kDSStdAuthWriteSecureHash ) == 0 )
{
*outAuthMethod = kAuthWriteSecureHash;
}
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 if ( ::strcmp( p, kDSStdAuthAPOP ) == 0 )
{
*outAuthMethod = kAuthAPOP;
}
else if ( ::strcmp( p, kDSStdAuthCRAM_MD5 ) == 0 )
{
*outAuthMethod = kAuthCRAM_MD5;
}
else if ( ::strcmp( p, kDSStdAuthSetPolicy ) == 0 )
{
*outAuthMethod = kAuthSetPolicy;
}
else if ( ::strcmp( p, kDSStdAuthWithAuthorizationRef ) == 0 )
{
*outAuthMethod = kAuthWithAuthorizationRef;
}
else
{
uiNativeLen = ::strlen( kDSNativeAuthMethodPrefix );
if ( ::strncmp( p, kDSNativeAuthMethodPrefix, uiNativeLen ) == 0 )
{
*outAuthMethod = kAuthNativeMethod;
}
else
{
*outAuthMethod = kAuthUnknownMethod;
siResult = eDSAuthMethodNotSupported;
}
}
return( siResult );
}
sInt32 CNiPlugIn::IsValidRecordName ( const char *inRecName,
const char *inRecType,
void *inDomain,
ni_id &outDirID )
{
sInt32 siResult = eDSInvalidRecordName;
char *pData = nil;
ni_status niStatus = NI_OK;
gNetInfoMutex->Wait();
try
{
if ( inDomain == nil ) throw( (sInt32)eDSInvalidDomain );
if ( inRecName == nil ) throw( (sInt32)eDSInvalidRecordName );
if ( inRecType == nil ) throw( (sInt32)eDSInvalidRecordType );
pData = BuildRecordNamePath( inRecName, inRecType );
if ( pData != nil )
{
niStatus = ::ni_pathsearch( inDomain, &outDirID, pData );
if ( niStatus == NI_OK )
{
siResult = eDSNoErr;
}
free( pData );
}
}
catch( sInt32 err )
{
siResult = err;
}
gNetInfoMutex->Signal();
return( siResult );
}
char *CNiPlugIn:: BuildRecordNamePath ( const char *inRecName,
const char *inRecType )
{
const char *pData = nil;
CString csPath( 128 );
char *outPath = nil;
uInt32 recNameLen = 0;
uInt32 nativeLen = 0;
uInt32 stdLen = 0;
try
{
if ( inRecName == nil ) throw( (sInt32)eDSInvalidRecordName );
if ( inRecType == nil ) throw( (sInt32)eDSInvalidRecordType );
recNameLen = ::strlen( inRecName );
nativeLen = ::strlen( kDSNativeAttrTypePrefix );
stdLen = ::strlen( kDSStdAttrTypePrefix );
if ( ::strncmp( inRecName, kDSNativeAttrTypePrefix, nativeLen ) == 0 )
{
if ( recNameLen > nativeLen )
{
pData = inRecName + nativeLen;
}
}
else if ( ::strncmp( inRecName, kDSStdAttrTypePrefix, stdLen ) == 0 )
{
if ( recNameLen > stdLen )
{
pData = inRecName + stdLen;
}
}
else
{
pData = inRecName;
}
if ( pData != nil )
{
if ( (::strstr( pData, "/" ) != nil) || (::strstr( pData, "\\" ) != nil) )
{
csPath.Set( "/" );
csPath.Append( inRecType );
csPath.Append( "/" );
while(pData[0] != '\0')
{
if (pData[0] == '/')
{
csPath.Append( "\\/" );
}
else if (pData[0] == '\\')
{
csPath.Append( "\\\\" );
}
else
{
csPath.Append( pData[0] );
}
pData++;
}
}
else
{
csPath.Set( "/" );
csPath.Append( inRecType );
csPath.Append( "/" );
csPath.Append( pData );
}
if (strcmp(csPath.GetData(),"///\\/") == 0)
{
outPath = (char *)::calloc( 2, sizeof(char));
if ( outPath == nil ) throw( (sInt32)eMemoryError );
strcpy(outPath,"/");
}
else
{
outPath = (char *)::calloc( csPath.GetLength() + 1, sizeof(char));
if ( outPath == nil ) throw( (sInt32)eMemoryError );
strcpy(outPath,csPath.GetData());
}
}
}
catch( sInt32 err )
{
if (outPath != nil)
{
free(outPath);
outPath = nil;
}
}
return( outPath );
}
bool CNiPlugIn::IsTimRunning()
{
bool bTimRunning = false;
#ifdef TIM_CLIENT_PRESENT
TIMHandle* timHandle = NULL;
ni_status niStatus = NI_OK;
void* domain = NULL;
Buffer *tagBuffer;
int timSessionStatus;
if ( time(nil) < gCheckTimAgainTime )
{
return gTimIsRunning;
}
gNetInfoMutex->Wait();
gTimIsRunning = false;
gCheckTimAgainTime = time( nil) + 60;
niStatus = ::ni_open( NULL, ".", &domain );
if (niStatus == NI_OK)
{
timHandle = ::timServerForDomain( domain );
if (timHandle != NULL)
{
tagBuffer = bufferFromString("local");
timHandleSetTag(timHandle, tagBuffer);
bufferRelease(tagBuffer);
tagBuffer = bufferFromString("Status NetInfo Domain");
timSessionStatus = timSessionStart(timHandle, TimOpUtility, tagBuffer);
bufferRelease(tagBuffer);
if (timSessionStatus == TimStatusOK)
{
timSessionStatus = timSessionStep(timHandle, NULL, &tagBuffer);
bufferRelease(tagBuffer);
if (timSessionStatus == TimStatusOK)
{
bTimRunning = true;
gTimIsRunning = true;
}
timSessionEnd(timHandle);
}
::timHandleFree( timHandle );
timHandle = NULL;
}
ni_free(domain);
domain = NULL;
}
gNetInfoMutex->Signal();
#endif
return bTimRunning;
}
sInt32 CNiPlugIn::MapAuthResult ( sInt32 inAuthErr )
{
sInt32 siResult = eUndefinedError;
switch ( inAuthErr )
{
#ifdef TIM_CLIENT_PRESENT
case TimStatusOK:
siResult = eDSNoErr;
break;
#ifdef DEBUG
case TimStatusContinue:
siResult = eDSContinue;
break;
case TimStatusServerTimeout:
siResult = eDSServerTimeout;
break;
case TimStatusInvalidHandle:
siResult = eDSInvalidHandle;
break;
case TimStatusSendFailed:
siResult = eDSSendFailed;
break;
case TimStatusReceiveFailed:
siResult = eDSReceiveFailed;
break;
case TimStatusBadPacket:
siResult = eDSBadPacket;
break;
case TimStatusInvalidTag:
siResult = eDSInvalidTag;
break;
case TimStatusInvalidSession:
siResult = eDSInvalidSession;
break;
case TimStatusInvalidName:
siResult = eDSInvalidName;
break;
case TimStatusUserUnknown:
siResult = eDSUserUnknown;
break;
case TimStatusUnrecoverablePassword:
siResult = eDSUnrecoverablePassword;
break;
case TimStatusAuthenticationFailed:
siResult = eDSAuthenticationFailed;
break;
case TimStatusBogusServer:
siResult = eDSBogusServer;
break;
case TimStatusOperationFailed:
siResult = eDSOperationFailed;
break;
case TimStatusNotAuthorized:
siResult = eDSNotAuthorized;
break;
case TimStatusNetInfoError:
siResult = eDSNetInfoError;
break;
case TimStatusContactMaster:
siResult = eDSContactMaster;
break;
case TimStatusServiceUnavailable:
siResult = eDSServiceUnavailable;
break;
#endif
#endif
default:
siResult = eDSAuthFailed;
break;
}
return( siResult );
}
sInt32 CNiPlugIn::MapNetInfoErrors ( sInt32 inNiError )
{
sInt32 siOutError = 0;
switch ( inNiError )
{
case NI_OK:
siOutError = eDSNoErr;
break;
case NI_BADID:
siOutError = eUnknownPlugIn;
break;
case NI_STALE:
siOutError = eUnknownPlugIn;
break;
case NI_NOSPACE:
siOutError = eUnknownPlugIn;
break;
case NI_PERM:
siOutError = eDSPermissionError;
break;
case NI_NODIR:
siOutError = eDSInvalidRecordName;
break;
case NI_NOPROP:
siOutError = eUnknownPlugIn;
break;
case NI_NONAME:
siOutError = eUnknownPlugIn;
break;
case NI_NOTEMPTY:
siOutError = eUnknownPlugIn;
break;
case NI_UNRELATED:
siOutError = eUnknownPlugIn;
break;
case NI_SERIAL:
siOutError = eUnknownPlugIn;
break;
case NI_NETROOT:
siOutError = eUnknownPlugIn;
break;
case NI_NORESPONSE:
siOutError = eUnknownPlugIn;
break;
case NI_RDONLY:
siOutError = eDSReadOnly;
break;
case NI_SYSTEMERR:
siOutError = eUnknownPlugIn;
break;
case NI_ALIVE:
siOutError = eUnknownPlugIn;
break;
case NI_NOTMASTER:
siOutError = eUnknownPlugIn;
break;
case NI_CANTFINDADDRESS:
siOutError = eUnknownPlugIn;
break;
case NI_DUPTAG:
siOutError = eUnknownPlugIn;
break;
case NI_NOTAG:
siOutError = eUnknownPlugIn;
break;
case NI_AUTHERROR:
siOutError = eUnknownPlugIn;
break;
case NI_NOUSER:
siOutError = eUnknownPlugIn;
break;
case NI_MASTERBUSY:
siOutError = eUnknownPlugIn;
break;
case NI_INVALIDDOMAIN:
siOutError = eDSInvalidDomain;
break;
case NI_BADOP:
siOutError = eUnknownPlugIn;
break;
case NI_FAILED:
siOutError = eUnknownPlugIn;
break;
default:
siOutError = eUnknownPlugIn;
break;
}
return( siOutError );
}
uInt32 CNiPlugIn::CalcCRC ( const char *inStr )
{
const char *p = inStr;
sInt32 siI = 0;
sInt32 siStrLen = 0;
uInt32 uiCRC = 0xFFFFFFFF;
CRCCalc aCRCCalc;
if ( inStr != nil )
{
siStrLen = ::strlen( inStr );
for ( siI = 0; siI < siStrLen; ++siI )
{
uiCRC = aCRCCalc.UPDC32( *p, uiCRC );
p++;
}
}
return( uiCRC );
}
void CNiPlugIn::MakeGood( char *inStr, char *outStr )
{
uInt32 uiI = 0;
uInt32 uiJ = 0;
if ( (inStr != nil) && (outStr != nil) )
{
while ( inStr[ uiI ] != '\0' )
{
if ( (inStr[ uiI ] == '\\') && (inStr[ uiI + 1 ] == '/') )
{
uiI++;
}
outStr[ uiJ ] = inStr[ uiI ];
uiI++;
uiJ++;
}
outStr[ uiJ ] = '\0';
}
}
sNIContextData* CNiPlugIn::MakeContextData ( void )
{
sNIContextData *pOut = nil;
pOut = (sNIContextData *) ::calloc( 1, sizeof( sNIContextData) );
pOut->fUID = (uid_t)-2;
pOut->fEffectiveUID = (uid_t)-2;
pOut->bIsLocal = false;
return( pOut );
}
sInt32 CNiPlugIn::CleanContextData ( sNIContextData *inContext )
{
sInt32 siResult = eDSNoErr;
if ( inContext == nil )
{
siResult = eDSBadContextData;
}
else
{
if (inContext->fDomain != nil)
{
if ( inContext->fDontUseSafeClose )
{
gNetInfoMutex->Wait();
::ni_free(inContext->fDomain);
gNetInfoMutex->Signal();
inContext->fDomain = nil;
}
else if (inContext->fDomainName != nil)
{
CNetInfoPlugin::SafeClose( inContext->fDomainName );
inContext->fDomain = nil;
}
}
if (inContext->fDomainName != nil)
{
free(inContext->fDomainName);
inContext->fDomainName = nil;
}
if (inContext->fRecType != nil)
{
free(inContext->fRecType);
inContext->fRecType = nil;
}
if (inContext->fRecName != nil)
{
free(inContext->fRecName);
inContext->fRecName = nil;
}
if (inContext->fAuthenticatedUserName != NULL)
{
free(inContext->fAuthenticatedUserName);
inContext->fAuthenticatedUserName = NULL;
}
inContext->offset = 0;
inContext->index = 0;
inContext->fDontUseSafeClose = false;
inContext->bIsLocal = false;
if ( inContext->fPWSNodeRef != 0 )
dsCloseDirNode(inContext->fPWSNodeRef);
if ( inContext->fPWSRef != 0 )
dsCloseDirService(inContext->fPWSRef);
}
return( siResult );
}
bool CNiPlugIn::DoesThisMatch ( const char *inString,
const char *inPatt,
tDirPatternMatch inHow )
{
bool bOutResult = false;
CFMutableStringRef strRef = CFStringCreateMutable(NULL, 0);
CFMutableStringRef patRef = CFStringCreateMutable(NULL, 0);
CFRange range;
if ( (inString == nil) || (inPatt == nil) || (strRef == nil) || (patRef == nil) )
{
return( false );
}
CFStringAppendCString( strRef, inString, kCFStringEncodingUTF8 );
CFStringAppendCString( patRef, inPatt, kCFStringEncodingUTF8 );
if ( (inHow >= eDSiExact) && (inHow <= eDSiRegularExpression) )
{
CFStringUppercase( strRef, NULL );
CFStringUppercase( patRef, NULL );
}
switch ( inHow )
{
case eDSExact:
case eDSiExact:
{
if ( CFStringCompare( strRef, patRef, 0 ) == kCFCompareEqualTo )
{
bOutResult = true;
}
}
break;
case eDSStartsWith:
case eDSiStartsWith:
{
if ( CFStringHasPrefix( strRef, patRef ) )
{
bOutResult = true;
}
}
break;
case eDSEndsWith:
case eDSiEndsWith:
{
if ( CFStringHasSuffix( strRef, patRef ) )
{
bOutResult = true;
}
}
break;
case eDSContains:
case eDSiContains:
{
range = CFStringFind( strRef, patRef, 0 );
if ( range.location != kCFNotFound )
{
bOutResult = true;
}
}
break;
case eDSLessThan:
case eDSiLessThan:
{
if ( CFStringCompare( strRef, patRef, 0 ) == kCFCompareLessThan )
{
bOutResult = true;
}
}
break;
case eDSGreaterThan:
case eDSiGreaterThan:
{
if ( CFStringCompare( strRef, patRef, 0 ) == kCFCompareGreaterThan )
{
bOutResult = true;
}
}
break;
case eDSLessEqual:
case eDSiLessEqual:
{
if ( CFStringCompare( strRef, patRef, 0 ) != kCFCompareGreaterThan )
{
bOutResult = true;
}
}
break;
case eDSGreaterEqual:
case eDSiGreaterEqual:
{
if ( CFStringCompare( strRef, patRef, 0 ) != kCFCompareLessThan )
{
bOutResult = true;
}
}
break;
default:
break;
}
CFRelease( strRef );
strRef = nil;
CFRelease( patRef );
patRef = nil;
return( bOutResult );
}
char* CNiPlugIn:: BuildRegExp ( const char *inString )
{
char *outRegExp = nil;
unsigned long i = 0;
unsigned long j = 0;
unsigned long inLength = 0;
if (inString == nil)
{
return( outRegExp );
}
outRegExp = (char *) calloc( 1, 1 + 2*strlen(inString) );
j = 0;
inLength = strlen(inString);
for (i=0; i< inLength; i++)
{
if ( (isascii(inString[i])) && ( (inString[i]) != '(' ) && ( (inString[i]) != ')' ) )
{
if (isalnum(inString[i]) || isspace(inString[i]) || (inString[i]) == '_' || (inString[i]) == '-')
{
memcpy(outRegExp+j,&inString[i],1);
j++;
}
else
{
memcpy(outRegExp+j,"\\",1);
j++;
memcpy(outRegExp+j,& inString[i],1);
j++;
}
}
else
{
memcpy(outRegExp+j,".",1);
j++;
}
}
return( outRegExp );
}
void CNiPlugIn::ContinueDeallocProc ( void* inContinueData )
{
sNIContinueData *pContinue = (sNIContinueData *)inContinueData;
if ( pContinue != nil )
{
if ( pContinue->fAliasList != nil )
{
::dsDataListDeallocatePriv( pContinue->fAliasList );
free( pContinue->fAliasList );
pContinue->fAliasList = nil;
}
if ( pContinue->fAliasAttribute != nil )
{
::dsDataListDeallocatePriv( pContinue->fAliasAttribute );
free( pContinue->fAliasAttribute );
pContinue->fAliasAttribute = nil;
}
if ( pContinue->fDataBuff != nil )
{
::dsDataBufferDeallocatePriv( pContinue->fDataBuff );
pContinue->fDataBuff = nil;
}
if ( pContinue->fNIEntryList.ni_entrylist_len > 0 )
{
::ni_entrylist_free(&(pContinue->fNIEntryList));
pContinue->fNIEntryList.ni_entrylist_len = 0;
}
free( pContinue );
pContinue = nil;
}
}
void CNiPlugIn::ContextDeallocProc ( void* inContextData )
{
sNIContextData *pContext = (sNIContextData *) inContextData;
if ( pContext != nil )
{
CleanContextData( pContext );
free( pContext );
pContext = nil;
}
}
char* CNiPlugIn::BuildDomainPathFromName( char* inDomainName )
{
CString csPathStr( 128 );
char *pathStr = nil;
if ( inDomainName == NULL )
return NULL;
if (::strncmp( inDomainName, kstrRootName, ::strlen( kstrRootName ) ) != 0)
{
return nil;
}
if ( (::strcmp( inDomainName, kstrLocalDomain ) == 0) ||
(::strcmp( inDomainName + ::strlen( kstrRootNodeName ), kstrLocalDot ) == 0) ||
(::strcmp( inDomainName, kstrDefaultLocalNodeName ) == 0 ) )
{
csPathStr.Set( "." );
}
else if ( (::strcmp( inDomainName, kstrRootName ) == 0) ||
(::strcmp( inDomainName, kstrPrefixName ) == 0) ||
(::strcmp( inDomainName, kstrRootNodeName ) == 0) )
{
csPathStr.Set( kstrDelimiter );
}
else if ( ::strcmp( inDomainName, kstrParentDomain ) == 0 )
{
csPathStr.Set( ".." );
}
else
{
csPathStr.Set( inDomainName + 13 ); }
pathStr = (char *)::calloc( csPathStr.GetLength() + 1, sizeof( char ) );
strcpy( pathStr, csPathStr.GetData());
return pathStr;
}
sInt32 CNiPlugIn::IsValidRealname ( char *inRealname,
void *inDomain,
char **outRecName )
{
sInt32 siResult = eDSInvalidRecordName;
ni_id niDirID;
ni_status niStatus = NI_OK;
char *inConstRegExpRecName = nil;
ni_entrylist niEntryList;
u_int en = 0;
ni_entry niEntry;
ni_proplist niPropList;
ni_index niIndex = 0;
ni_index niIndexComp = 0;
gNetInfoMutex->Wait();
NI_INIT( &niDirID );
NI_INIT( &niEntry );
NI_INIT( &niPropList );
NI_INIT( &niEntryList );
niStatus = ::ni_pathsearch( inDomain, &niDirID, "/users" );
if ( niStatus == NI_OK )
{
inConstRegExpRecName = BuildRegExp(inRealname);
niStatus = ::ni_search( inDomain, &niDirID, (char *)"realname", inConstRegExpRecName, REG_ICASE, &niEntryList );
free(inConstRegExpRecName);
if ( niStatus == NI_OK )
{
for ( en = 0; en < niEntryList.ni_entrylist_len; en++ )
{
niEntry = niEntryList.ni_entrylist_val[ en ];
niDirID.nii_object = niEntry.id;
niStatus = ::ni_read( inDomain, &niDirID, &niPropList );
if ( niStatus == NI_OK )
{
niIndex = ::ni_proplist_match( niPropList, "realname", NULL );
if ( niIndex != NI_INDEX_NULL )
{
if (DoesThisMatch( (const char*)(niPropList.nipl_val[ niIndex ].nip_val.ninl_val[ 0 ]),
(const char*)inRealname, eDSExact ))
{
niIndexComp = ::ni_proplist_match( niPropList, "name", NULL );
if ( niIndexComp != NI_INDEX_NULL )
{
*outRecName = (char *) calloc( 1, 1 + strlen(niPropList.nipl_val[ niIndexComp ].nip_val.ninl_val[ 0 ]) );
strcpy(*outRecName,niPropList.nipl_val[ niIndexComp ].nip_val.ninl_val[ 0 ]);
siResult = eDSNoErr;
::ni_proplist_free( &niPropList );
break;
}
}
} ::ni_proplist_free( &niPropList );
}
}
if (niEntryList.ni_entrylist_len > 0)
{
::ni_entrylist_free( &niEntryList );
niEntryList.ni_entrylist_len = 0;
}
}
}
gNetInfoMutex->Signal();
return( siResult );
}
bool CNiPlugIn::UserIsAdmin ( const char *inUserName,
void *inDomain )
{
ni_id niDirID;
ni_status niStatus = NI_OK;
ni_proplist niPropList;
ni_index niIndex = 0;
bool isAdmin = false;
if ( inUserName == NULL || inDomain == NULL ) {
return false;
}
gNetInfoMutex->Wait();
niStatus = ::ni_pathsearch( inDomain, &niDirID, "/groups/admin" );
if (niStatus == NI_OK) {
niStatus = ::ni_read( inDomain, &niDirID, &niPropList );
if (niStatus == NI_OK) {
niIndex = ::ni_proplist_match( niPropList, "users", nil );
if (niIndex != NI_INDEX_NULL) {
niIndex = ni_namelist_match(niPropList.nipl_val[niIndex].nip_val,inUserName);
isAdmin = (niIndex != NI_INDEX_NULL);
}
::ni_proplist_free( &niPropList );
}
}
gNetInfoMutex->Signal();
return isAdmin;
}
char* CNiPlugIn::GetUserNameForUID ( uid_t inUserID,
void *inDomain )
{
ni_id niDirID;
ni_status niStatus = NI_OK;
ni_proplist niPropList;
ni_entry niEntry;
ni_entrylist niEntryList;
ni_namelist niValues;
char idStr[ 64 ] = { 0 };
u_int en = 0;
char* userName = NULL;
if ( inDomain == NULL ) {
return NULL;
}
gNetInfoMutex->Wait();
NI_INIT( &niDirID );
NI_INIT( &niEntry );
NI_INIT( &niPropList );
NI_INIT( &niEntryList );
NI_INIT( &niValues );
niStatus = ::ni_pathsearch( inDomain, &niDirID, "/users" );
if (niStatus == NI_OK) {
snprintf( idStr, 64, "%d", inUserID );
niStatus = ni_search( inDomain, &niDirID, "uid", idStr, REG_BASIC, &niEntryList );
if ( niStatus == NI_OK )
{
for ( en = 0; en < niEntryList.ni_entrylist_len; en++ )
{
niEntry = niEntryList.ni_entrylist_val[ en ];
niDirID.nii_object = niEntry.id;
niStatus = ni_lookupprop( inDomain, &niDirID, "name", &niValues );
if ( niStatus == NI_OK )
{
if (niValues.ni_namelist_len > 0)
{
if (niValues.ni_namelist_val[0] != NULL)
{
userName = strdup( niValues.ni_namelist_val[0] );
ni_namelist_free( &niValues );
break;
}
ni_namelist_free( &niValues );
}
}
}
} if ( niEntryList.ni_entrylist_len > 0 )
{
::ni_entrylist_free(&niEntryList);
niEntryList.ni_entrylist_len = 0;
}
}
gNetInfoMutex->Signal();
return userName;
}
sInt32 CNiPlugIn::GetUserNameFromAuthBuffer ( tDataBufferPtr inAuthData, unsigned long inUserNameIndex,
char **outUserName )
{
tDataListPtr dataList = dsAuthBufferGetDataListAllocPriv(inAuthData);
if (dataList != NULL)
{
*outUserName = dsDataListGetNodeStringPriv(dataList, inUserNameIndex);
dsDataListDeallocatePriv(dataList);
free(dataList);
dataList = NULL;
return eDSNoErr;
}
return eDSInvalidBuffFormat;
}
NetInfoAuthAuthorityHandlerProc CNiPlugIn::GetNetInfoAuthAuthorityHandler ( const char* inTag )
{
if (inTag == NULL)
{
return NULL;
}
for (unsigned int i = 0; i < kNetInfoAuthAuthorityHandlerProcs; ++i)
{
if (strcasecmp(inTag,sNetInfoAuthAuthorityHandlerProcs[i].fTag) == 0)
{
return sNetInfoAuthAuthorityHandlerProcs[i].fHandler;
}
}
return NULL;
}
sInt32 CNiPlugIn::ParseAuthAuthority ( const char * inAuthAuthority,
char ** outVersion,
char ** outAuthTag,
char ** outAuthData )
{
char* authAuthority = NULL;
char* current = NULL;
char* tempPtr = NULL;
sInt32 result = eDSAuthFailed;
if ( inAuthAuthority == NULL || outVersion == NULL
|| outAuthTag == NULL || outAuthData == NULL )
{
return eDSAuthFailed;
}
authAuthority = strdup(inAuthAuthority);
if (authAuthority == NULL)
{
return eDSAuthFailed;
}
current = authAuthority;
do {
tempPtr = strsep(¤t, ";");
if (tempPtr == NULL) break;
*outVersion = strdup(tempPtr);
tempPtr = strsep(¤t, ";");
if (tempPtr == NULL) break;
*outAuthTag = strdup(tempPtr);
tempPtr = strsep(¤t, ";");
if (tempPtr == NULL) break;
*outAuthData = strdup(tempPtr);
result = eDSNoErr;
} while (false);
free(authAuthority);
authAuthority = NULL;
if (result != eDSNoErr)
{
if (*outVersion != NULL)
{
free(*outVersion);
*outVersion = NULL;
}
if (*outAuthTag != NULL)
{
free(*outAuthTag);
*outAuthTag = NULL;
}
if (*outAuthData != NULL)
{
free(*outAuthData);
*outAuthData = NULL;
}
}
return result;
}
sInt32 CNiPlugIn::ParseLocalCacheUserData ( const char *inAuthData,
char **outNodeName,
char **outRecordName,
char **outGUID )
{
char* authData = NULL;
char* current = NULL;
char* tempPtr = NULL;
sInt32 result = eDSAuthFailed;
if ( inAuthData == NULL )
{
return (sInt32)eDSEmptyBuffer;
}
if ( outNodeName == NULL )
{
return (sInt32)eDSEmptyNodeName;
}
if ( outRecordName == NULL )
{
return (sInt32)eDSEmptyRecordName;
}
if ( outGUID == NULL )
{
return (sInt32)eDSEmptyParameter;
}
authData = strdup(inAuthData);
if (authData == NULL)
{
return eDSAuthFailed;
}
current = authData;
do {
tempPtr = strsep(¤t, ":");
if (tempPtr == NULL)
{
result = eDSEmptyNodeName;
break;
}
*outNodeName = strdup(tempPtr);
tempPtr = strsep(¤t, ":");
if (tempPtr == NULL)
{
result = eDSEmptyRecordName;
break;
}
*outRecordName = strdup(tempPtr);
tempPtr = strsep(¤t, ":");
if (tempPtr == NULL)
{
result = eDSEmptyParameter;
break;
}
*outGUID = strdup(tempPtr);
result = eDSNoErr;
} while (false);
free(authData);
authData = NULL;
if (result != eDSNoErr)
{
if (*outNodeName != NULL)
{
free(*outNodeName);
*outNodeName = NULL;
}
if (*outRecordName != NULL)
{
free(*outRecordName);
*outRecordName = NULL;
}
if (*outGUID != NULL)
{
free(*outGUID);
*outGUID = NULL;
}
}
return result;
}