summaryrefslogblamecommitdiffstats
path: root/private/utils/aclconv/sidcache.cxx
blob: ca98d8fa887b813240f86a50b27dc9721af40c22 (plain) (tree)


































































































































































































































































































































































                                                                           
/*++

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;
}