|
|
//+-------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1996 - 1996.
//
// File: alsup.cxx
//
// Contents: CAccessList support functions
//
// Classes:
//
// History: 06-Nov-96 MacM Created
//
//--------------------------------------------------------------------
#include <aclpch.hxx>
#pragma hdrstop
#include <alsup.hxx>
#include <netlib.h>
#include <seopaque.h>
#include <sertlp.h>
#include <martaevt.h>
#include <ntprov.hxx>
#include <strings.h>
DWORD InitializeEvents(void);
//+---------------------------------------------------------------------------
//
// Function: GetOrderTypeForAccessEntry
//
// Synopsis: Determines the "order" type of entry given the node
// information
//
// Arguments: [pwszProperty] -- The property this entry is
// associated with
// [pAE] -- The entry to check
// [SeInfo] -- Type of node this is supposed to
// be
//
// Returns: The type of the node. This is a bitmask flag of the types
// ACCLIST_DENIED through ACCLIST_PROP_ALLOWED
//
// Notes:
//
//----------------------------------------------------------------------------
ULONG GetOrderTypeForAccessEntry(IN PWSTR pwszProperty, IN PACTRL_ACCESS_ENTRY pAE, IN SECURITY_INFORMATION SeInfo) { ULONG Type = 0;
//
// First, check the simple cases (like audit or invalid)
//
if(FLAG_ON(SeInfo, DACL_SECURITY_INFORMATION)) { if(FLAG_ON(pAE->fAccessFlags, ACTRL_AUDIT_SUCCESS | ACTRL_AUDIT_FAILURE)) { Type = ACCLIST_AUDIT; } } else { if(!FLAG_ON(pAE->fAccessFlags, ACTRL_AUDIT_SUCCESS | ACTRL_AUDIT_FAILURE) && FLAG_ON(pAE->fAccessFlags, ACTRL_ACCESS_ALLOWED | ACTRL_ACCESS_DENIED)) { Type = ACCLIST_UNKOWN_ENTRY; } else { Type = ACCLIST_AUDIT; } }
if(Type == 0) { if(pwszProperty == NULL && pAE->lpInheritProperty == NULL) { Type = pAE->fAccessFlags == ACTRL_ACCESS_DENIED ? ACCLIST_DENIED : ACCLIST_ALLOWED; } else if(pwszProperty == NULL) { Type = pAE->fAccessFlags == ACTRL_ACCESS_DENIED ? ACCLIST_OBJ_DENIED : ACCLIST_PROP_ALLOWED; } else { Type = pAE->fAccessFlags == ACTRL_ACCESS_DENIED ? ACCLIST_OBJ_DENIED : ACCLIST_OBJ_ALLOWED; }
//
// See if it's inherited. If it is, and we don't have a level
// flag, assume it's level 1 and mark it as such
//
if(FLAG_ON(pAE->Inheritance, INHERITED_ACCESS_ENTRY) && !FLAG_ON(pAE->Inheritance, INHERITED_PARENT | INHERITED_GRANDPARENT)) { pAE->Inheritance |= INHERITED_PARENT; } }
return(Type); }
//+---------------------------------------------------------------------------
//
// Function: OrderListBySid
//
// Synopsis: Orders an acclist_cnode list by sid. The order would be:
// Everyone
// Well known groups
// Groups
// Users
// Anyone else
//
// Arguments: [pList] -- List of the nodes to sort
// [iStart] -- Where to start in the list
// [iLen] -- Number of nodes in the list
//
// Returns: ERROR_SUCCESS -- Success
//
// Notes:
//
//----------------------------------------------------------------------------
ULONG OrderListBySid(IN PACCLIST_CNODE pList, IN ULONG iStart, IN ULONG iLen) { DWORD dwErr = ERROR_SUCCESS;
return(dwErr); }
//
// Local functions
//
//+---------------------------------------------------------------------------
//
// Function: DelAcclistNode
//
// Synopsis: Deletes an ACCLIST_NODE that's kept in the _AccList. This is
// used by the CSList
//
// Arguments: [IN pvNode] -- Node to delete
//
// Returns: VOID
//
//----------------------------------------------------------------------------
void DelAcclistNode(PVOID pvNode) { PACCLIST_NODE pNode = (PACCLIST_NODE)pvNode;
AccFree(pNode->pAccessList); AccFree(pNode->pAuditList); AccFree(pNode->pwszProperty);
AccFree(pNode); }
//+---------------------------------------------------------------------------
//
// Function: DelTrusteeNode
//
// Synopsis: Deletes an TRUSTEE_NODE that's kept in the _TrusteeList.
// This is used by the CSList
//
// Arguments: [IN pvNode] -- Node to delete
//
// Returns: VOID
//
//----------------------------------------------------------------------------
void DelTrusteeNode(PVOID pvNode) { acDebugOut((DEB_TRACE_ACC, "IN DelTrusteeNode\n"));
PTRUSTEE_NODE pNode = (PTRUSTEE_NODE)pvNode;
if(FLAG_ON(pNode->fFlags,TRUSTEE_DELETE_SID)) { AccFree(pNode->pSid); }
if(FLAG_ON(pNode->fFlags,TRUSTEE_DELETE_NAME)) { AccFree(pNode->pwszTrusteeName); AccFree(pNode->pwszDomainName); } else if(FLAG_ON(pNode->fFlags, TRUSTEE_DELETE_DOMAIN)) { AccFree(pNode->pwszDomainName); }
AccFree(pNode);
acDebugOut((DEB_TRACE_ACC, "Out DelTrusteeNode\n")); }
//+---------------------------------------------------------------------------
//
// Function: CompInheritProps
//
// Synopsis: Compare the given property name to the PIPROP_IN_BUFF stuct
//
// Arguments: [IN pvTrustee] -- Trustee to look for
// [IN pvNode2] -- 2nd node to compare
//
// Returns: TRUE -- Nodes equal
// FALSE -- Nodes not equal
//
//----------------------------------------------------------------------------
BOOL CompInheritProps(IN PVOID pvInheritProp, IN PVOID pvNode2) { BOOL fRet = FALSE; PIPROP_IN_BUFF pPIB = (PIPROP_IN_BUFF)pvNode2;
if(pvInheritProp != NULL) { if(_wcsicmp((PWSTR)pvInheritProp, (PWSTR)(pPIB->pwszIProp)) == 0) { fRet = TRUE; } }
return(fRet); }
//+---------------------------------------------------------------------------
//
// Function: CompTrustees
//
// Synopsis: Compare two TRUSTEE_NODES. Used by _TrusteeList.
//
// Arguments: [IN pvTrustee] -- Trustee to look for
// [IN pvNode2] -- 2nd node to compare
//
// Returns: TRUE -- Nodes equal
// FALSE -- Nodes not equal
//
//----------------------------------------------------------------------------
BOOL CompTrustees(IN PVOID pvTrustee, IN PVOID pvTrustee2) { PTRUSTEE pTrustee = (PTRUSTEE)pvTrustee; TRUSTEE_NODE TrusteeNode; BOOL Result = FALSE;
memset( &TrusteeNode, 0, sizeof( TrusteeNode ) ); memcpy( &TrusteeNode.Trustee, pvTrustee2, sizeof( TRUSTEE ) );
Result = CompTrusteeToTrusteeNode(pvTrustee, &TrusteeNode);
if(FLAG_ON(TrusteeNode.fFlags,TRUSTEE_DELETE_SID)) { AccFree(TrusteeNode.pSid); }
if(FLAG_ON(TrusteeNode.fFlags,TRUSTEE_DELETE_NAME)) { AccFree(TrusteeNode.pwszTrusteeName); AccFree(TrusteeNode.pwszDomainName); TrusteeNode.pwszDomainName = NULL; }
if(FLAG_ON(TrusteeNode.fFlags, TRUSTEE_DELETE_DOMAIN)) { AccFree(TrusteeNode.pwszDomainName); }
return(Result); }
//+---------------------------------------------------------------------------
//
// Function: CompTrusteeToTrusteeNode
//
// Synopsis: Compare two trustees for equality
//
// Arguments: [IN pvTrustee] -- Trustee to look for
// [IN pvNode2] -- 2nd node to compare
//
// Returns: TRUE -- Nodes equal
// FALSE -- Nodes not equal
//
//----------------------------------------------------------------------------
BOOL CompTrusteeToTrusteeNode(IN PVOID pvTrustee, IN PVOID pvNode2) { PTRUSTEE pTrustee = (PTRUSTEE)pvTrustee; PTRUSTEE_NODE pNode2 = (PTRUSTEE_NODE)pvNode2;
DWORD dwErr = ERROR_SUCCESS; BOOL fMatch = FALSE; if(pTrustee->MultipleTrusteeOperation == pNode2->Trustee.MultipleTrusteeOperation) { //
// Ok, first compare the base trustee information...
//
if(pTrustee->TrusteeForm != pNode2->Trustee.TrusteeForm) { //
// We don't have matching information, so we'll have to look
// it up.
//
ULONG fOptions = 0;
if(pTrustee->TrusteeForm == TRUSTEE_IS_NAME) { fOptions = TRUSTEE_OPT_NAME; } else { fOptions = TRUSTEE_OPT_SID; }
dwErr = LookupTrusteeNodeInformation(NULL, pNode2, fOptions); }
//
// Now, do the comparrisons
//
if(dwErr == ERROR_SUCCESS) { //
// Now, compare the trustees
//
if(pTrustee->TrusteeForm == TRUSTEE_IS_NAME) { if(_wcsicmp(pTrustee->ptstrName, pNode2->pwszTrusteeName ? pNode2->pwszTrusteeName : pNode2->Trustee.ptstrName) == 0) { fMatch = TRUE; } } else { if(pTrustee->ptstrName == NULL || (pNode2->Trustee.ptstrName == NULL && pNode2->pSid == NULL)) { fMatch = FALSE; } else { fMatch = RtlEqualSid((PSID)(pTrustee->ptstrName), (PSID)(pNode2->pSid ? pNode2->pSid : pNode2->Trustee.ptstrName)); } } }
//
// Now, if that worked, look for the multiple trustee case
//
if(fMatch == TRUE && pTrustee->MultipleTrusteeOperation == TRUSTEE_IS_IMPERSONATE) { fMatch = CompTrusteeToTrusteeNode(pTrustee->pMultipleTrustee, pNode2->pImpersonate); } }
return(fMatch); }
//+---------------------------------------------------------------------------
//
// Function: DoPropertiesMatch
//
// Synopsis: Determines if 2 properties are equal. It takes into account
// the possibility of a NULL property.
//
// Arguments: [IN pwszProp1] -- 1st property to compare
// [IN pwszProp2] -- 2nd property to compare
//
// Returns: TRUE -- Properties are equal
// FALSE -- Properties are not equal
//
//----------------------------------------------------------------------------
BOOL DoPropertiesMatch(IN PWSTR pwszProp1, IN PWSTR pwszProp2) { BOOL fReturn = FALSE;
if(pwszProp1 == NULL || pwszProp2 == NULL) { if(pwszProp1 == pwszProp2) { fReturn = TRUE; } } else { if(_wcsicmp(pwszProp1, pwszProp2) == 0) { fReturn = TRUE; } }
return(fReturn); }
//+---------------------------------------------------------------------------
//
// Function: CompProps
//
// Synopsis: Compare an ACCLIST_NODE to a property
//
// Arguments: [IN pvProp] -- Property string
// [IN pvNode] -- Node to compare
//
// Returns: TRUE -- Nodes equal
// FALSE -- Nodes not equal
//
//----------------------------------------------------------------------------
BOOL CompProps(IN PVOID pvProp, IN PVOID pvNode) { PACCLIST_NODE pAN = (PACCLIST_NODE)pvNode;
return(DoPropertiesMatch((PWSTR)pvProp, pAN->pwszProperty)); }
//+---------------------------------------------------------------------------
//
// Function: CompGuids
//
// Synopsis: Compare an ACCLIST_ATOACCESS structure to a guid
//
// Arguments: [IN pvGuid] -- Guid
// [IN pvNode] -- Node to compare
//
// Returns: TRUE -- Nodes equal
// FALSE -- Nodes not equal
//
//----------------------------------------------------------------------------
BOOL CompGuids(IN PVOID pvGuid, IN PVOID pvNode) { PACCLIST_ATOACCESS pAA = (PACCLIST_ATOACCESS)pvNode; GUID *pGuid = (GUID *)pvGuid;
if(pGuid == NULL && pAA->pGuid == NULL) { return(TRUE); } else if(pGuid == NULL || pAA->pGuid == NULL) { return(FALSE); }
return((BOOL)!memcmp(pGuid, pAA->pGuid, sizeof(GUID))); }
//+---------------------------------------------------------------------------
//
// Function: LookupTrusteeNodeInformation
//
// Synopsis: Looks up the appropriate trustee information. This involves
// either looking up the trustees sid or name, depending on
// the options
//
// Arguments: [pwszServer] -- Name of server to lookup information on
// [pTrusteeNode] -- Trustee to lookup the information
// for
// [fOptions] -- What information to lookup
//
// Returns: ERROR_SUCCESS -- Success
//
// Notes:
//
//----------------------------------------------------------------------------
DWORD LookupTrusteeNodeInformation(IN PWSTR pwszServer, IN PTRUSTEE_NODE pTrusteeNode, IN ULONG fOptions) { DWORD dwErr = ERROR_SUCCESS;
SID_NAME_USE SidType = SidTypeUnknown;
//
// Need to make sure we have the SID
//
if(FLAG_ON(fOptions, TRUSTEE_OPT_SID)) { //
// Make sure we have the sids
//
if(pTrusteeNode->pSid == NULL) { dwErr = AccctrlLookupSid(pwszServer, pTrusteeNode->Trustee.ptstrName, TRUE, &(pTrusteeNode->pSid), &SidType);
if(dwErr == ERROR_SUCCESS) { pTrusteeNode->fFlags |= TRUSTEE_DELETE_SID; } } }
//
// Ok, we need to have the name
//
if(dwErr == ERROR_SUCCESS && FLAG_ON(fOptions, TRUSTEE_OPT_NAME)) { //
// Make sure we have the name
//
if(pTrusteeNode->pwszTrusteeName == NULL) { dwErr = AccctrlLookupName(pwszServer, pTrusteeNode->pSid, TRUE, &(pTrusteeNode->pwszTrusteeName), &SidType); if(dwErr == ERROR_SUCCESS) { pTrusteeNode->fFlags |= TRUSTEE_DELETE_NAME; } } }
//
// Then, take care of our sid type
//
if(dwErr == ERROR_SUCCESS && pTrusteeNode->SidType == SidTypeUnknown) { pTrusteeNode->SidType = SidType;
if(SidType == SidTypeUnknown) { pTrusteeNode->Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN; } else { pTrusteeNode->Trustee.TrusteeType = (TRUSTEE_TYPE)(SidType); } }
return(dwErr); }
//+---------------------------------------------------------------------------
//
// Function: GetATypeForEntry
//
// Synopsis: Determines the type of entry given the node information
//
// Arguments: [pwszProperty] -- The property this entry is
// associated with
// [pAE] -- The entry to check
// [SeInfo] -- Type of node this is supposed to
// be
//
// Returns: The type of the node
//
// Notes:
//
//----------------------------------------------------------------------------
ACC_ACLBLD_TYPE GetATypeForEntry(IN PWSTR pwszProperty, IN PACTRL_ACCESS_ENTRY pAE, IN SECURITY_INFORMATION SeInfo) { ACC_ACLBLD_TYPE AType = AAT_DENIED;
//
// First, check the simple cases (like audit or invalid)
//
if(FLAG_ON(SeInfo, DACL_SECURITY_INFORMATION)) { if(FLAG_ON(pAE->fAccessFlags, ACTRL_AUDIT_SUCCESS | ACTRL_AUDIT_FAILURE)) { AType = AAT_INVALID; } } else { if(!FLAG_ON(pAE->fAccessFlags, ACTRL_AUDIT_SUCCESS | ACTRL_AUDIT_FAILURE) && FLAG_ON(pAE->fAccessFlags, ACTRL_ACCESS_ALLOWED | ACTRL_ACCESS_DENIED)) { AType = AAT_INVALID; } else { AType = AAT_AUDIT; } }
if(AType == 0) { if(pwszProperty == NULL && pAE->lpInheritProperty == NULL) { AType = pAE->fAccessFlags == ACTRL_ACCESS_DENIED ? AAT_DENIED : AAT_ALLOWED; } else if(pwszProperty == NULL) { AType = pAE->fAccessFlags == ACTRL_ACCESS_DENIED ? AAT_OBJ_DENIED : AAT_PROP_ALLOWED; } else { AType = pAE->fAccessFlags == ACTRL_ACCESS_DENIED ? AAT_OBJ_DENIED : AAT_OBJ_ALLOWED; }
//
// See if it's inherited
//
if(FLAG_ON(pAE->Inheritance, INHERITED_ACCESS_ENTRY)) { AType =(ACC_ACLBLD_TYPE) ((ULONG)AType + ((ULONG)AAT_IDENIED - (ULONG)AAT_DENIED)); } }
return(AType); }
//+---------------------------------------------------------------------------
//
// Function: CNodeCompare
//
// Synopsis: Used by CSList class. Used to determine if 2 acclist_cnodes are
// identical, based upon the property
//
// Arguments: [pv1] -- 1st node
// [pv2] -- 2nd node
//
// Returns: 0 on equality
// non-0 otherwise
//
// Notes:
//
//----------------------------------------------------------------------------
int __cdecl CNodeCompare(const void *pv1, const void *pv2) { PACCLIST_CNODE pCN1 = (PACCLIST_CNODE)pv1; PACCLIST_CNODE pCN2 = (PACCLIST_CNODE)pv2;
if(pCN1->pONode->pwszProperty == NULL) { return(-1); }
if(pCN2->pONode->pwszProperty == NULL) { return(1); }
return(_wcsicmp(pCN1->pONode->pwszProperty, pCN2->pONode->pwszProperty)); }
//+---------------------------------------------------------------------------
//
// Function: CompAndMarkCompressNode
//
// Synopsis: Used by CSList class. Used to determine if 2 nodes can be
// compressed into one. If so, the first node has its access
// flag marked with a bit signifying it can be compressed. See
// below for the definition of what it means to be compressible
//
// Arguments: [pvAE] -- New node
// [pvNode] -- Node already existing in list
//
// Returns: 0 on equality
// non-0 otherwise
//
// Notes:
//
//----------------------------------------------------------------------------
BOOL CompAndMarkCompressNode(IN PVOID pvAE, IN PVOID pvNode) { PACTRL_ACCESS_ENTRY pAE1 = (PACTRL_ACCESS_ENTRY)pvAE; PACTRL_ACCESS_ENTRY pAE2 = (PACTRL_ACCESS_ENTRY)pvNode;
//
// We will consider nodes identical iff:
// They match trustee, inheritance, and access flags exactly and the
// inherit property or (along with the rest of the above):
// - Both nodes are inherited and one is marked l1 inherited and the
// other is not marked at all, or neither node is inherited
// and the inheritance is identical or the inheritance is different
// but the access masks are the same
// - fAccessFlags indicates that combining this 2 nodes will still
// yield an audit node.
//
if(CompTrustees(&pAE1->Trustee,&pAE2->Trustee) == TRUE && //
// Check the inheritance
//
(pAE1->Inheritance == pAE2->Inheritance || (pAE1->Inheritance & ~INHERITED_PARENT) == (pAE2->Inheritance & ~INHERITED_PARENT) || (!FLAG_ON(pAE1->Inheritance, INHERITED_ACCESS_ENTRY) && !FLAG_ON(pAE2->Inheritance, INHERITED_ACCESS_ENTRY)&& (pAE1->Inheritance != 0 && pAE2->Inheritance != 0) && (pAE1->Access) == pAE2->Access)) && //
// Check the access
//
(((pAE1->fAccessFlags & ~(ACCLIST_COMPRESS | ~ACCLIST_VALID_TYPE_FLAGS)) == ( pAE2->fAccessFlags & ~~ACCLIST_VALID_TYPE_FLAGS ) || (((((pAE1->fAccessFlags & ~(ACCLIST_COMPRESS | ~ACCLIST_VALID_TYPE_FLAGS)) | (pAE2->fAccessFlags & ~~ACCLIST_VALID_TYPE_FLAGS)) & ~(ACTRL_AUDIT_SUCCESS | ACTRL_AUDIT_FAILURE)) == 0))) && pAE1->Access == pAE2->Access) && //
// Check the properties
//
DoPropertiesMatch(pAE1->lpInheritProperty, pAE2->lpInheritProperty) == TRUE) { pAE1->fAccessFlags |= ACCLIST_COMPRESS; return(TRUE); }
return(FALSE); }
//+---------------------------------------------------------------------------
//
// Function: GetNodeForProperty
//
// Synopsis: This function will lookup the existing list node for the given
// property. If the node doesn't exist, it will be created and
// inserted into the list
//
// Arguments: [List] -- List to examine
// [pwszProperty] -- The property to look for
// [ppNode] -- Where the found or inserted node is
// returned
//
// Returns: ERROR_SUCCESS -- Success
// ERROR_NOT_ENOUGH_MEMORY A memory allocation failed
//
// Notes:
//
//----------------------------------------------------------------------------
DWORD GetNodeForProperty(CSList& List, PWSTR pwszProperty, PACCLIST_NODE *ppNode) { DWORD dwErr = ERROR_SUCCESS;
PACCLIST_NODE pAccNode = (PACCLIST_NODE)List.Find(pwszProperty, CompProps); if(pAccNode == NULL) { //
// Doesn't exist. We'll have to add it...
//
pAccNode = (PACCLIST_NODE)AccAlloc(sizeof(ACCLIST_NODE)); if(pAccNode == NULL) { dwErr = ERROR_NOT_ENOUGH_MEMORY; } else { if(pwszProperty != NULL) { ACC_ALLOC_AND_COPY_STRINGW(pwszProperty, pAccNode->pwszProperty, dwErr); }
if(dwErr == ERROR_SUCCESS) { dwErr = List.Insert((PVOID)pAccNode);
if(dwErr != ERROR_SUCCESS) { AccFree(pAccNode->pwszProperty); AccFree(pAccNode); } } else { AccFree(pAccNode); pAccNode = 0; } } }
*ppNode = pAccNode;
return(dwErr); }
VOID FreeAToAccessStruct(PVOID pv) { ((PACCLIST_ATOACCESS)pv)->AceList.FreeList((FreeFunc)AccFree); AccFree(pv); }
//+---------------------------------------------------------------------------
//
// Function: GetNodeForGuid
//
// Synopsis: Finds the node in the given list based upon the guid. If the
// node doesn't exist, it is inserted
//
// Arguments: [List] -- List to examine
// [pGuid] -- The guid to look for
// [ppNode] -- Where the found or inserted node is
// returned
//
// Returns: ERROR_SUCCESS -- Success
// ERROR_NOT_ENOUGH_MEMORY A memory allocation failed
//
// Notes:
//
//----------------------------------------------------------------------------
DWORD GetNodeForGuid(CSList& List, GUID *pGuid, PACCLIST_ATOACCESS *ppNode) { DWORD dwErr = ERROR_SUCCESS;
List.Init((FreeFunc)FreeAToAccessStruct);
PACCLIST_ATOACCESS pNode = (PACCLIST_ATOACCESS)List.Find(pGuid, CompGuids); if(pNode == NULL) { //
// Doesn't exist. We'll have to add it...
//
pNode = (PACCLIST_ATOACCESS)AccAlloc(sizeof(ACCLIST_ATOACCESS)); if(pNode == NULL) { dwErr = ERROR_NOT_ENOUGH_MEMORY; } else { pNode->AceList.Init((FreeFunc)AccFree);
if(pGuid != NULL) { pNode->pGuid = (GUID *)AccAlloc(sizeof(GUID)); if(pNode->pGuid == NULL) { dwErr = ERROR_NOT_ENOUGH_MEMORY; AccFree(pNode); pNode = 0; } else { memcpy(pNode->pGuid, pGuid, sizeof(GUID)); } }
if(dwErr == ERROR_SUCCESS) { dwErr = List.Insert((PVOID)pNode);
if(dwErr != ERROR_SUCCESS) { AccFree(pNode->pGuid); AccFree(pNode); } } } }
*ppNode = pNode;
return(dwErr); }
//+---------------------------------------------------------------------------
//
// Function: InsertAtoANode
//
// Synopsis: Inserts an access to ace node into the list.
//
// Arguments: [List] -- List to insert in
// [pProperty] -- Property to match
// [pAce] -- Ace to be inserted
// [fInherit] -- Inheritance flags
//
// Returns: ERROR_SUCCESS -- Success
// ERROR_NOT_ENOUGH_MEMORY A memory allocation failed
//
// Notes:
//
//----------------------------------------------------------------------------
DWORD InsertAtoANode(CSList& List, GUID *pProperty, PACE_HEADER pAce, ULONG fInherit) { DWORD dwErr = ERROR_SUCCESS;
PACCLIST_ATOANODE pAANode = (PACCLIST_ATOANODE)AccAlloc(sizeof(ACCLIST_ATOANODE)); if(pAANode == NULL) { dwErr = ERROR_NOT_ENOUGH_MEMORY; } else { pAANode->pAce = pAce; pAANode->fInherit = fInherit;
PACCLIST_ATOACCESS pParent;
dwErr = GetNodeForGuid(List, pProperty, &pParent); if(dwErr == ERROR_SUCCESS) { dwErr = pParent->AceList.Insert((PVOID)pAANode); }
if(dwErr != ERROR_SUCCESS) { AccFree(pAANode); } }
return(dwErr); }
//+---------------------------------------------------------------------------
//
// Function: AceToAccessEntry
//
// Synopsis: Converts an ACE into an access entry
//
// Arguments: [pAce] -- Ace to convert
// [fInheritLevel] -- What inheritance level (effective,
// parent inherit, etc) are we at
// [ObjType] -- Type of object we're dealing with
// [pAE] -- Already existing access entry to
// initialize
//
// Returns: ERROR_SUCCESS -- Success
// ERROR_INVALID_ACL -- A bad ace type was encountered
//
// Notes:
//
//----------------------------------------------------------------------------
DWORD AceToAccessEntry(PACE_HEADER pAce, ULONG fInheritLevel, SE_OBJECT_TYPE ObjType, IN MARTA_KERNEL_TYPE KernelObjectType, PACTRL_ACCESS_ENTRY pAE) { DWORD dwErr = ERROR_SUCCESS;
//
// Go ahead and initialize the node
//
BOOL fIsImpersonate = FALSE; BOOL fIsExtendedAce = FALSE;
//
// Ok, now lets try to figure out what type of ACE this is, so we can
// do the neccessary mapping into the provider rights
//
switch(pAce->AceType) { case ACCESS_ALLOWED_ACE_TYPE: pAE->fAccessFlags = ACTRL_ACCESS_ALLOWED; break;
case ACCESS_ALLOWED_OBJECT_ACE_TYPE: pAE->fAccessFlags = ACTRL_ACCESS_ALLOWED; fIsExtendedAce = TRUE; break;
//
// Currently unsupported
//
case ACCESS_ALLOWED_COMPOUND_ACE_TYPE: pAE->fAccessFlags = ACTRL_ACCESS_ALLOWED; fIsImpersonate = TRUE; dwErr = ERROR_INVALID_ACL; break;
case ACCESS_DENIED_ACE_TYPE: pAE->fAccessFlags = ACTRL_ACCESS_DENIED; break;
case ACCESS_DENIED_OBJECT_ACE_TYPE: pAE->fAccessFlags = ACTRL_ACCESS_DENIED; fIsExtendedAce = TRUE; break;
case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
pAE->fAccessFlags = 0;
if(FLAG_ON(pAce->AceFlags,SUCCESSFUL_ACCESS_ACE_FLAG)) { pAE->fAccessFlags |= ACTRL_AUDIT_SUCCESS; }
if(FLAG_ON(pAce->AceFlags,FAILED_ACCESS_ACE_FLAG)) { pAE->fAccessFlags |= ACTRL_AUDIT_FAILURE; } fIsExtendedAce = TRUE; break;
case SYSTEM_AUDIT_ACE_TYPE:
pAE->fAccessFlags = 0;
if(FLAG_ON(pAce->AceFlags,SUCCESSFUL_ACCESS_ACE_FLAG)) { pAE->fAccessFlags |= ACTRL_AUDIT_SUCCESS; }
if(FLAG_ON(pAce->AceFlags,FAILED_ACCESS_ACE_FLAG)) { pAE->fAccessFlags |= ACTRL_AUDIT_FAILURE; } break;
default: dwErr = ERROR_INVALID_ACL; break;
}
if(dwErr == ERROR_SUCCESS) { //
// Pull what we can from the ace header
//
pAE->Inheritance = (INHERIT_FLAGS)( pAce->AceFlags & VALID_INHERIT_FLAGS ); pAE->Inheritance |= fInheritLevel;
PSID pSid = NULL; ACCESS_MASK AccessMask = 0; if(fIsImpersonate == FALSE) { if(fIsExtendedAce == TRUE) { pSid = RtlObjectAceSid(pAce); AccessMask = ((PKNOWN_OBJECT_ACE)pAce)->Mask; } else { pSid = &((PKNOWN_ACE)pAce)->SidStart; AccessMask = ((PKNOWN_ACE)pAce)->Mask; } } else { if(fIsExtendedAce == TRUE) { dwErr = ERROR_INVALID_ACL; } else { pSid = (PSID)Add2Ptr(&((PCOMPOUND_ACCESS_ALLOWED_ACE)pAce)->SidStart, RtlLengthSid(&((PCOMPOUND_ACCESS_ALLOWED_ACE)pAce)->SidStart)); AccessMask = ((PCOMPOUND_ACCESS_ALLOWED_ACE)pAce)->Mask; } }
//
// Build the trustee
//
pAE->Trustee.pMultipleTrustee = NULL; pAE->Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; pAE->Trustee.TrusteeForm = TRUSTEE_IS_SID; pAE->Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN; pAE->Trustee.ptstrName = (LPWSTR)pSid;
//
// Convert our access
//
AccConvertAccessMaskToActrlAccess(AccessMask, ObjType, KernelObjectType, pAE);
//
// Deal with the inheritance property...
//
if(fIsExtendedAce == TRUE) { PACCESS_ALLOWED_OBJECT_ACE pExAce = (PACCESS_ALLOWED_OBJECT_ACE)pAce;
if(FLAG_ON(pExAce->Flags, ACE_INHERITED_OBJECT_TYPE_PRESENT)) { PWSTR StrUuid; dwErr = UuidToString(RtlObjectAceInheritedObjectType(pAce), &StrUuid );
//
// The calling functions expect a buffer allocated with AccAlloc
//
if(dwErr == ERROR_SUCCESS) { ACC_ALLOC_AND_COPY_STRINGW(StrUuid, (PWSTR)pAE->lpInheritProperty, dwErr); RpcStringFree(&StrUuid); }
} } else { pAE->lpInheritProperty = NULL; }
}
if(dwErr != ERROR_SUCCESS) { if(pAE->lpInheritProperty != NULL) { AccFree((PWSTR)pAE->lpInheritProperty); } }
return(dwErr); }
//+---------------------------------------------------------------------------
//
// Function: ConvertToAutoInheritSD
//
// Synopsis: Determines the inheritance necessary for the current security
// descriptor given the parent security descriptor
//
// Arguments: [IN pCurrentSD] -- The security descriptor to
// update
// [IN pParentSD] -- The parent security descriptor
// [IN fIsContainer] -- Does the Sec. Desc. refer to
// a container?
// [IN pGenericMapping] -- Generic mapping to apply
// [OUT ppNewSD] -- Where the new SD is returned
//
// Returns: ERROR_SUCCESS -- Success
//
// Notes: The returned security descriptor must be freed via a call to
// DestroyPrivateObjectSecurity
//
//----------------------------------------------------------------------------
DWORD ConvertToAutoInheritSD(IN PSECURITY_DESCRIPTOR pParentSD, IN PSECURITY_DESCRIPTOR pCurrentSD, IN BOOL fIsContainer, IN PGENERIC_MAPPING pGenericMapping, OUT PSECURITY_DESCRIPTOR *ppNewSD) { DWORD dwErr = ERROR_SUCCESS; SECURITY_DESCRIPTOR_CONTROL OldControl;
//
// Turn off the inherited bits, so we can always do the
// necessary inheritance checks. This is because we don't know if some
// downlevel process came in and messed with one of our security
// descriptors, and left is in a hosed state
//
OldControl = ((SECURITY_DESCRIPTOR *)pCurrentSD)->Control;
((SECURITY_DESCRIPTOR *)pCurrentSD)->Control &= ~(SE_DACL_AUTO_INHERITED | SE_SACL_AUTO_INHERITED);
#ifdef DBG
if(pParentSD != NULL) { ASSERT(IsValidSecurityDescriptor(pParentSD)); DebugDumpSD("CTAIPOS ParentSD", pParentSD); }
ASSERT(IsValidSecurityDescriptor(pCurrentSD)); DebugDumpSD("CTAIPOS CurrentSD", pCurrentSD); #endif
if(ConvertToAutoInheritPrivateObjectSecurity(pParentSD, pCurrentSD, ppNewSD, NULL, fIsContainer != 0, pGenericMapping) == FALSE) { dwErr = GetLastError(); } #ifdef DBG
else { ASSERT(IsValidSecurityDescriptor(*ppNewSD)); DebugDumpSD("CTAIPOS NewSD", *ppNewSD); } #endif
((SECURITY_DESCRIPTOR *)pCurrentSD)->Control = OldControl;
return(dwErr); }
//+---------------------------------------------------------------------------
//
// Function: MakeSDAbsolute
//
// Synopsis: Allocates a new security descriptor and makes an absolute copy
// of the supplied SD
//
// Arguments: [IN pOriginalSD] -- The security descriptor to
// convert
// [IN SeInfo] -- SD components to care about
// [IN *ppNewSD] -- Where the new SD is returned
// [IN pOwnerToAdd] -- OPTIONAL. Owner SID to add to
// absolute SD.
// [IN pGroupToAdd] -- OPTIONAL. Group SID to add to
// absolute SD.
//
// Returns: ERROR_SUCCESS -- Success
// ERROR_NOT_ENOUGH_MEMORY -- A memory allocation falied
//
// Notes: The returned security descriptor must be freed via a call to
// AccFree
//
//----------------------------------------------------------------------------
DWORD MakeSDAbsolute(IN PSECURITY_DESCRIPTOR pOriginalSD, IN SECURITY_INFORMATION SeInfo, OUT PSECURITY_DESCRIPTOR *ppNewSD, IN PSID pOwnerToAdd, IN PSID pGroupToAdd) { DWORD dwErr = ERROR_SUCCESS;
BOOL fDAclPresent = FALSE; BOOL fSAclPresent = FALSE; BOOL fDAclDef = FALSE, fSAclDef = FALSE; BOOL fOwnerDef = FALSE, fGroupDef = FALSE; PACL pDAcl = NULL, pSAcl = NULL; PSID pOwner = NULL, pGroup = NULL; ULONG cSize = 0;
//
// First, get the info out of the current SD
//
if(FLAG_ON(SeInfo, DACL_SECURITY_INFORMATION)) { if(GetSecurityDescriptorDacl(pOriginalSD, &fDAclPresent, &pDAcl, &fDAclDef) == FALSE) { dwErr = GetLastError(); } else { if(pDAcl != NULL) { cSize += pDAcl->AclSize; } } }
if(dwErr == ERROR_SUCCESS && FLAG_ON(SeInfo, SACL_SECURITY_INFORMATION)) { if(GetSecurityDescriptorSacl(pOriginalSD, &fSAclPresent, &pSAcl, &fSAclDef) == FALSE) { dwErr = GetLastError(); } else { if(pSAcl != NULL) { cSize += pSAcl->AclSize; } } }
if(pOwnerToAdd != NULL) { pOwner = pOwnerToAdd; } else { if(dwErr == ERROR_SUCCESS && FLAG_ON(SeInfo, OWNER_SECURITY_INFORMATION)) { if(GetSecurityDescriptorOwner(pOriginalSD, &pOwner, &fOwnerDef) == FALSE) { dwErr = GetLastError(); } } }
if(pGroupToAdd != NULL) { pGroup = pGroupToAdd; } else { if(dwErr == ERROR_SUCCESS && FLAG_ON(SeInfo, GROUP_SECURITY_INFORMATION)) { if(GetSecurityDescriptorGroup(pOriginalSD, &pGroup, &fGroupDef) == FALSE) { dwErr = GetLastError(); } } }
if(pOwner != NULL) { cSize += RtlLengthSid(pOwner); }
if(pGroup != NULL) { cSize += RtlLengthSid(pGroup); }
if(dwErr == ERROR_SUCCESS) { //
// Allocate the buffer...
//
PBYTE pBuff = (PBYTE)AccAlloc(cSize + sizeof(SECURITY_DESCRIPTOR)); if(pBuff == NULL) { dwErr = ERROR_NOT_ENOUGH_MEMORY; } else { //
// Start copying in the existing items...
//
DWORD cLen; PBYTE pbEndOBuf = pBuff + cSize + sizeof(SECURITY_DESCRIPTOR);
if(pOwner != NULL) { cLen = RtlLengthSid(pOwner); pbEndOBuf -= cLen; RtlCopyMemory(pbEndOBuf, pOwner, cLen); pOwner = (PSID)pbEndOBuf; }
if(pGroup != NULL) { cLen = RtlLengthSid(pGroup); pbEndOBuf -= cLen; RtlCopyMemory(pbEndOBuf, pGroup, cLen); pGroup = (PSID)pbEndOBuf; }
if(pDAcl != NULL) { pbEndOBuf -= pDAcl->AclSize; RtlCopyMemory(pbEndOBuf, pDAcl, pDAcl->AclSize); pDAcl = (PACL)pbEndOBuf; }
if(pSAcl != NULL) { pbEndOBuf -= pSAcl->AclSize; RtlCopyMemory(pbEndOBuf, pSAcl, pSAcl->AclSize); pSAcl = (PACL)pbEndOBuf; }
//
// Ok, now build it...
//
*ppNewSD = (PSECURITY_DESCRIPTOR)pBuff; if(InitializeSecurityDescriptor(*ppNewSD, SECURITY_DESCRIPTOR_REVISION) == FALSE) { dwErr = GetLastError(); }
if(dwErr == ERROR_SUCCESS && fDAclPresent == TRUE) { if(SetSecurityDescriptorDacl(*ppNewSD, TRUE, pDAcl, fDAclDef) == FALSE) { dwErr = GetLastError(); } }
if(dwErr == ERROR_SUCCESS && fSAclPresent == TRUE) { if(SetSecurityDescriptorSacl(*ppNewSD, TRUE, pSAcl, fSAclDef) == FALSE) { dwErr = GetLastError(); } }
if(dwErr == ERROR_SUCCESS && pOwner != NULL)
{ if(SetSecurityDescriptorOwner(*ppNewSD, pOwner, fOwnerDef) == FALSE) { dwErr = GetLastError(); } }
if(dwErr == ERROR_SUCCESS && pGroup != NULL)
{ if(SetSecurityDescriptorGroup(*ppNewSD, pGroup, fGroupDef) == FALSE) { dwErr = GetLastError(); } }
//
// Set the new control bits to look like the old ones (minus the selfrel flag, of
// course...
//
if(dwErr == ERROR_SUCCESS) { RtlpPropagateControlBits((PISECURITY_DESCRIPTOR)*ppNewSD, (PISECURITY_DESCRIPTOR)pOriginalSD, ~SE_SELF_RELATIVE ); }
if(dwErr != ERROR_SUCCESS) { AccFree(*ppNewSD); *ppNewSD = NULL; }
}
}
return(dwErr); }
//+---------------------------------------------------------------------------
//
// Function: EqualSecurityDescriptors
//
// Synopsis: Determines if 2 security descriptors are identical. It does
// this by comparing control fields, owner/group, and sids.
//
// Arguments: [IN pSD1] -- 1st SD to compare
// [IN pSD2] -- 2nd SD to compare
//
// Returns: TRUE -- They are identical
// FALSE -- They are not identical
//
//
//----------------------------------------------------------------------------
BOOL EqualSecurityDescriptors(IN PSECURITY_DESCRIPTOR pSD1, IN PSECURITY_DESCRIPTOR pSD2) { BOOL fRet = TRUE;
SECURITY_DESCRIPTOR *pS1 = (SECURITY_DESCRIPTOR *)pSD1; SECURITY_DESCRIPTOR *pS2 = (SECURITY_DESCRIPTOR *)pSD2;
if(pS1->Control != pS2->Control) { return(FALSE); }
PACL pA1, pA2;
//
// Dacl
//
pA1 = RtlpDaclAddrSecurityDescriptor(pS1); pA2 = RtlpDaclAddrSecurityDescriptor(pS2);
if((pA1 == NULL && pA2 != NULL) || (pA2 == NULL && pA1 != NULL)) { return(FALSE); }
if(pA1 != NULL) { if(!(pA1->AclSize == pA2->AclSize && memcmp(pA1, pA2, pA1->AclSize))) { return(FALSE); } }
//
// Sacl
//
pA1 = RtlpSaclAddrSecurityDescriptor(pS1); pA2 = RtlpSaclAddrSecurityDescriptor(pS2);
if((pA1 == NULL && pA2 != NULL) || (pA2 == NULL && pA1 != NULL)) { return(FALSE); }
if(pA1 != NULL) { if(!(pA1->AclSize == pA2->AclSize && memcmp(pA1, pA2, pA1->AclSize))) { return(FALSE); } }
//
// Group
//
PSID pSid1, pSid2; pSid1 = RtlpGroupAddrSecurityDescriptor(pS1); pSid2 = RtlpGroupAddrSecurityDescriptor(pS2);
if((pSid1 == NULL && pSid2 != NULL) || (pSid2 == NULL && pSid1 != NULL)) { return(FALSE); }
if(pSid1 != NULL) { if(!RtlEqualSid(pSid1, pSid2)) { return(FALSE); } }
//
// Owner
//
pSid1 = RtlpOwnerAddrSecurityDescriptor(pS1); pSid2 = RtlpOwnerAddrSecurityDescriptor(pS2);
if((pSid1 == NULL && pSid2 != NULL) || (pSid2 == NULL && pSid1 != NULL)) { return(FALSE); }
if(pSid1 != NULL) { if(!RtlEqualSid(pSid1, pSid2)) { return(FALSE); } }
acDebugOut((DEB_TRACE, "Nodes 0x%lx and 0x%lx are equal!\n", pSD1, pSD2)); #ifdef DBG
DebugDumpSD("SD1", pSD1); DebugDumpSD("SD2", pSD2); #endif
return(TRUE); }
//+---------------------------------------------------------------------------
//
// Function: InsertPropagationFailureEntry
//
// Synopsis: Adds a propagation failure entry to the list of items
// to be written to the event log
//
// Arguments: [IN LogList] -- Reference to the log list
// [IN ErrorCode] -- Error of propagation
// [IN Protected] -- Flags determining whether the dacl
// or sacl was protected
// [IN pwszPath] -- Path that expierneced the error
//
// Returns: ERROR_SUCCESS -- Success
// ERROR_NOT_ENOUGH_MEMORY -- A memory allocation failed
//
//
//----------------------------------------------------------------------------
DWORD InsertPropagationFailureEntry( IN CSList& LogList, IN ULONG ErrorCode, IN ULONG Protected, IN PWSTR pwszPath) { DWORD dwErr = ERROR_SUCCESS; PACCESS_PROP_LOG_ENTRY pEntry = NULL;
pEntry = (PACCESS_PROP_LOG_ENTRY)AccAlloc(sizeof(ACCESS_PROP_LOG_ENTRY)); if(pEntry == NULL) { dwErr = ERROR_NOT_ENOUGH_MEMORY; } else { ACC_ALLOC_AND_COPY_STRINGW(pwszPath, pEntry->pwszPath, dwErr );
if(pwszPath == NULL) { AccFree(pEntry); dwErr = ERROR_NOT_ENOUGH_MEMORY; } else { pEntry->Protected = Protected; pEntry->Error = ErrorCode; dwErr = LogList.Insert(pEntry);
if(dwErr != ERROR_SUCCESS) { FreePropagationFailureListEntry(pEntry); } } } return(dwErr); }
//+---------------------------------------------------------------------------
//
// Function: FreePropagationFailureListEntry
//
// Synopsis: Frees the propagation failure list
//
// Arguments: [IN LogList] -- Reference to the log list
//
// Returns: VOID
//
//
//----------------------------------------------------------------------------
VOID FreePropagationFailureListEntry(IN PVOID Entry) { PACCESS_PROP_LOG_ENTRY pLogEntry = (PACCESS_PROP_LOG_ENTRY)Entry;
AccFree(pLogEntry->pwszPath); AccFree(pLogEntry); }
//+---------------------------------------------------------------------------
//
// Function: WritePropagationFailureList
//
// Synopsis: Logs the propagation failures to the event log
//
// Arguments: [IN EventType] -- Type of event to log:
// registry or filesystem
// [IN LogList] -- Reference to the log list
// [IN hToken] -- Current process/thread token
//
// Returns: ERROR_SUCCESS -- Success
// ERROR_NOT_ENOUGH_MEMORY -- A memory allocation failed
//
//----------------------------------------------------------------------------
DWORD WritePropagationFailureList(IN ULONG EventType, IN CSList& LogList, IN HANDLE hToken) { DWORD dwErr = ERROR_SUCCESS; HANDLE hEventlog = NULL; TOKEN_USER *UserInfo; ULONG InfoSize, StrCount, i; PSID pSid = NULL; BYTE Buffer[ 7 * sizeof( ULONG ) + sizeof( TOKEN_USER ) ], *pBuff = NULL; WCHAR ErrorNumberBuffer[25]; WCHAR wszErrorBuffer[ 256]; PWSTR pwszStringBuffer = NULL, pwszCurrent; PACCESS_PROP_LOG_ENTRY pLogEntry; ULONG ProtectedValue;
if(LogList.QueryCount() == 0) { return(dwErr); }
//
// Get the user sid
//
if(GetTokenInformation(hToken, TokenUser, (PVOID)&Buffer, sizeof(Buffer), &InfoSize ) == FALSE ) { dwErr = GetLastError();
if(dwErr == ERROR_INSUFFICIENT_BUFFER) { pBuff = (PBYTE)AccAlloc( InfoSize );
if(pBuff == NULL) { dwErr = ERROR_NOT_ENOUGH_MEMORY; } else {
if(GetTokenInformation(hToken, TokenUser, (PVOID)pBuff, InfoSize, &InfoSize ) == FALSE ) { dwErr = GetLastError(); } else { dwErr = ERROR_SUCCESS; } } } } else { pBuff = Buffer; }
if(dwErr == ERROR_SUCCESS) { UserInfo = ( PTOKEN_USER )pBuff; pSid = UserInfo->User.Sid; }
//
// Build the list of paths and associated error codes
// The format of the buffer is [tab][path] [error][cr/lf]
//
if(dwErr == ERROR_SUCCESS) { InfoSize = 1;
LogList.Reset(); pLogEntry = (PACCESS_PROP_LOG_ENTRY)LogList.NextData(); for(; pLogEntry;) { InfoSize += 1 + wcslen( pLogEntry->pwszPath ) + 5;
//
// Determine the size of the buffer for the error message
//
if(pLogEntry->Protected) { switch(pLogEntry->Protected & (SE_DACL_PROTECTED | SE_SACL_PROTECTED)) { case SE_DACL_PROTECTED | SE_SACL_PROTECTED: ProtectedValue = ACCPROV_MARTA_BOTH_PROTECTED; break;
case SE_DACL_PROTECTED: ProtectedValue = ACCPROV_MARTA_DACL_PROTECTED; break;
case SE_SACL_PROTECTED: ProtectedValue = ACCPROV_MARTA_SACL_PROTECTED; break;
default: ProtectedValue = 0; break; }
if (LoadString(ghDll, ProtectedValue, wszErrorBuffer, sizeof( wszErrorBuffer ) / sizeof( WCHAR )) == 0) { dwErr = GetLastError(); break;
} } else { if( FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, pLogEntry->Error, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), wszErrorBuffer, 256, NULL ) == 0 ) { dwErr = GetLastError(); break; }
}
InfoSize += wcslen( wszErrorBuffer ); pLogEntry = (PACCESS_PROP_LOG_ENTRY)LogList.NextData(); }
//
// Now, allocate the buffer
//
if(dwErr == ERROR_SUCCESS) { pwszStringBuffer = (PWSTR)AccAlloc(( InfoSize + 1 ) * sizeof( WCHAR )); if(pwszStringBuffer == NULL) { dwErr = ERROR_NOT_ENOUGH_MEMORY; } else { LogList.Reset(); pwszCurrent = pwszStringBuffer; pLogEntry = (PACCESS_PROP_LOG_ENTRY)LogList.NextData(); for(; pLogEntry;) { if(pLogEntry->Protected == 0 ) { FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, pLogEntry->Error, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), wszErrorBuffer, 256, NULL ); } else { switch( pLogEntry->Protected & (SE_DACL_PROTECTED | SE_SACL_PROTECTED)) { case SE_DACL_PROTECTED | SE_SACL_PROTECTED: ProtectedValue = ACCPROV_MARTA_BOTH_PROTECTED; break;
case SE_DACL_PROTECTED: ProtectedValue = ACCPROV_MARTA_DACL_PROTECTED; break;
case SE_SACL_PROTECTED: ProtectedValue = ACCPROV_MARTA_SACL_PROTECTED; break;
default: ProtectedValue = 0; break; }
LoadString(ghDll, ProtectedValue, wszErrorBuffer, sizeof( wszErrorBuffer ) / sizeof( WCHAR )); } InfoSize = swprintf( pwszCurrent, L"\r\n\t%ws\t\t%ws", pLogEntry->pwszPath, wszErrorBuffer );
pwszCurrent += InfoSize; pLogEntry = (PACCESS_PROP_LOG_ENTRY)LogList.NextData();
} } } }
//
// Write to the event log
//
if(dwErr == ERROR_SUCCESS) { dwErr = InitializeEvents();
if(dwErr == ERROR_SUCCESS) {
hEventlog = RegisterEventSource( NULL, L"AclPropagation" );
if(hEventlog == NULL) {
dwErr = GetLastError(); if(dwErr == RPC_S_UNKNOWN_IF) { acDebugOut(( DEB_ERROR, "Eventlog service not started!\n" )); dwErr = ERROR_SUCCESS;
}
} else { if( ReportEvent(hEventlog, EVENTLOG_INFORMATION_TYPE, CATEGORY_NTMARTA, EventType, pSid, 1, 0, (LPCTSTR *)&pwszStringBuffer, NULL ) == FALSE ) { dwErr = GetLastError();
}
DeregisterEventSource(hEventlog); } } }
if(pBuff != Buffer) { AccFree(pBuff); }
if ((dwErr != ERROR_SUCCESS) && (pwszStringBuffer != NULL)) { AccFree(pwszStringBuffer); }
return(dwErr); }
//+---------------------------------------------------------------------------
//
// Function: InitializeEvents
//
// Synopsis: Sets the registry values to enable NTMARTA to act as an event source
//
// Arguments: void
//
// Returns: ERROR_SUCCESS -- Success
//
//----------------------------------------------------------------------------
DWORD InitializeEvents(void) {
HKEY hKey; DWORD dwErr, disp;
dwErr = RegCreateKeyEx( HKEY_LOCAL_MACHINE, TEXT("System\\CurrentControlSet\\Services\\EventLog\\Application\\AclPropagation"), 0, TEXT(""), REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, &disp); if(dwErr != ERROR_SUCCESS) { return(dwErr); }
if (disp == REG_CREATED_NEW_KEY) { RegSetValueEx( hKey, TEXT("EventMessageFile"), 0, REG_EXPAND_SZ, (PBYTE) TEXT("%SystemRoot%\\system32\\ntmarta.dll"), sizeof(TEXT("%SystemRoot%\\system32\\ntmarta.dll")) );
RegSetValueEx( hKey, TEXT("CategoryMessageFile"), 0, REG_EXPAND_SZ, (PBYTE) TEXT("%SystemRoot%\\system32\\ntmarta.dll"), sizeof(TEXT("%SystemRoot%\\system32\\ntmarta.dll")) );
disp = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE ;
RegSetValueEx( hKey, TEXT("TypesSupported"), 0, REG_DWORD, (PBYTE) &disp, sizeof(DWORD) );
disp = CATEGORY_MAX_CATEGORY - 1; RegSetValueEx( hKey, TEXT("CategoryCount"), 0, REG_DWORD, (PBYTE) &disp, sizeof(DWORD) );
}
RegCloseKey(hKey);
return(dwErr); }
//+---------------------------------------------------------------------------
//
// Function: SetAccessListLookupServer
//
// Synopsis: Sets the name of the server to lookup the names/sids on for
// the given path
//
// Arguments: [IN pwszPath] -- Path to get the server name for
// [IN AccessList] -- Reference to CAccessList class that
// needs the server name
//
// Returns: ERROR_SUCCESS -- Success
//
//----------------------------------------------------------------------------
DWORD SetAccessListLookupServer(IN PWSTR pwszPath, IN CAccessList &AccessList ) { DWORD dwErr = ERROR_SUCCESS; PWSTR pwszServer, pwszSep;
if( pwszPath && IS_UNC_PATH( pwszPath, wcslen( pwszPath ) ) ) { pwszServer = pwszPath + 2; pwszSep = wcschr(pwszServer, L'\\'); if(pwszSep) { *pwszSep = UNICODE_NULL; }
dwErr = AccessList.SetLookupServer(pwszServer);
if(pwszSep) { *pwszSep = L'\\'; } }
return(dwErr); }
|