/*++ Copyright (c) 1993 Microsoft Corporation Module Name: sidcache.hxx Abstract: This module contains definitions for the SID_CACHE class, which models a simple cache of SID's for ACLCONV. Author: Bill McJohn (billmc) 06-Nov-1993 Revision History: --*/ #include "ulib.hxx" #include "sidcache.hxx" DEFINE_CONSTRUCTOR( SID_CACHE, OBJECT ); SID_CACHE::~SID_CACHE( ) { Destroy(); } VOID SID_CACHE::Construct( ) /*++ Routine Description: This method is a helper function for object construction. Arguments: None. Return Value: None. --*/ { _NumberOfEntries = 0; _NextSlot = 0; _Cache = NULL; } VOID SID_CACHE::Destroy( ) /*++ Routine Description: This method is a helper function for object destruction. Arguments: None. Return Value: None. --*/ { ULONG i; for( i = 0; i < _NumberOfEntries; i++ ) { if( _Cache[i].Sid ) { FREE( _Cache[i].Sid ); _Cache[i].Sid = NULL; } } _NumberOfEntries = 0; _NextSlot = 0; delete[] _Cache; } BOOLEAN SID_CACHE::Initialize( IN ULONG NumberOfEntries ) /*++ Routine Description: This method initializes the cache--it allocates the array of CACHED_SID's and initializes each one. Arguments: NumberOfEntries -- Supplies the size of the cache. Return Value: TRUE upon successful completion. --*/ { ULONG i; Destroy(); if( NumberOfEntries == 0 ) { return FALSE; } _NumberOfEntries = NumberOfEntries; _NextSlot = 0; if( (_Cache = NEW CACHED_SID[NumberOfEntries]) == NULL ) { Destroy(); return FALSE; } for( i = 0; i < NumberOfEntries; i++ ) { _Cache[i].InUse = FALSE; _Cache[i].Sid = NULL; _Cache[i].SidLength = 0; } return TRUE; } BOOLEAN SID_CACHE::IsNamePresent( IN PCWSTRING Domain, IN PCWSTRING Name, OUT PULONG SidLength ) /*++ Routine Description: This method determines whether a particular account name is in the cache. Arguments: Domain -- Supplies the domain to search. May be NULL, indicating that the client will accept a positive match from any domain. Name -- Supplies the account name. SidLength -- Receives the length of the SID for the specified name. A value of 0 indicates that the name has been previously sought and not found. Return Value: TRUE if a match is found. --*/ { ULONG Index; if( !LocateName( Domain, Name, &Index ) ) { return FALSE; } *SidLength = _Cache[Index].SidLength; return TRUE; } NONVIRTUAL BOOLEAN SID_CACHE::QueryCachedSid( IN PCWSTRING Domain, IN PCWSTRING Name, OUT PSID Sid, IN OUT PULONG SidLength ) /*++ Routine Description: This method fetches a SID from the cache. Arguments: Domain -- Supplies the domain to search. May be NULL, indicating that the client will accept a positive match from any domain. Name -- Supplies the account name. Sid -- Receives the SID. SidLength -- Supplies the length in bytes of the client's buffer; receives the length in bytes of the SID. A length of zero means that the name has previously been searched for and not found. --*/ { ULONG Index; if( !LocateName( Domain, Name, &Index ) ) { return FALSE; } if( *SidLength < _Cache[Index].SidLength ) { return FALSE; } memcpy( Sid, _Cache[Index].Sid, _Cache[Index].SidLength ); *SidLength = _Cache[Index].SidLength; return TRUE; } BOOLEAN SID_CACHE::CacheSid( IN PCWSTRING Domain, IN PCWSTRING Name, IN PSID Sid, IN ULONG SidLength ) /*++ Routine Description: This method adds a SID to the cache. Arguments: Domain -- Supplies the domain in which the name was found. May be NULL if the SID is also NULL, to indicate that the specified account name was not found in any trusted domain. Name -- Supplies the name associated with this SID. Sid -- Supplies the SID. A NULL SID indicates that the user does not exist. SidLength -- Supplies the length in bytes of the SID. --*/ { DebugAssert( _NextSlot < _NumberOfEntries ); _Cache[_NextSlot].InUse = FALSE; if( _Cache[_NextSlot].Sid ) { FREE( _Cache[_NextSlot].Sid ); _Cache[_NextSlot].Sid = NULL; } if( (!Domain && !_Cache[_NextSlot].Domain.Initialize( "" )) || ( Domain && !_Cache[_NextSlot].Domain.Initialize( Domain )) || !_Cache[_NextSlot].Name.Initialize( Name ) ) { return FALSE; } if( !(_Cache[_NextSlot].Sid = (PSID)MALLOC( SidLength )) ) { return FALSE; } memcpy( _Cache[_NextSlot].Sid, Sid, SidLength ); _Cache[_NextSlot].SidLength = SidLength; _Cache[_NextSlot].InUse = TRUE; _NextSlot++; _NextSlot %= _NumberOfEntries; return TRUE; } BOOLEAN SID_CACHE::LocateName( IN PCWSTRING Domain, IN PCWSTRING Name, OUT PULONG Index ) /*++ Routine Description: This method locates a name in the cache. Note that matching rules are different for positive matches (cache entries with a non-NULL SID) and negative matches (entries with a NULL SID). A negative entry only matches if both the domain and account name are identical, whereas a positive entry also matches if the names are equal and the search domain is the empty string. Arguments: Domain -- Supplies the domain to search. May be NULL, indicating that the client will accept a positive match from any domain. Name -- Supplies the account name to find. Index -- Receives the index of the matching cache entry, if found. Return Value: TRUE if a match is found. --*/ { ULONG i; for( i = 0; i < _NumberOfEntries; i++ ) { if( _Cache[i].InUse && !_Cache[i].Name.Strcmp( Name ) ) { if( (Domain && !_Cache[i].Domain.Strcmp( Domain )) || (!Domain && _Cache[i].Domain.QueryChCount() == 0) ) { // It's an exact match--return it. // *Index = i; return TRUE; } // It's not an exact match. If this is a positive // entry (i.e. the SID is non-NULL), and the search // domain is NULL, then this is an acceptable match. // if( _Cache[i].Sid && !Domain ) { *Index = i; return TRUE; } } } return FALSE; }