|
|
////////////////////////////////////////////////////////////////////////////////
// //
// Microsoft Windows //
// Copyright (C) Microsoft Corporation, 1999. //
// //
// File: seia.cxx //
// //
// Contents: New marta rewrite functions for SetEntriesInAcl //
// //
// History: 4/99 KedarD Created //
// //
////////////////////////////////////////////////////////////////////////////////
#include <aclpch.hxx>
#pragma hdrstop
extern "C" { #include <stdio.h>
#include <permit.h>
#include <dsgetdc.h>
#include <lmapibuf.h>
#include <wmistr.h>
#include <ntprov.hxx>
#include <strings.h>
#include <seopaque.h>
#include <sertlp.h>
#include <accctrl.h>
#include <guidtables.h>
}
////////////////////////////////////////////////////////////////////////////////
// //
// MACRO DEFINITIONS START HERE //
// //
////////////////////////////////////////////////////////////////////////////////
#define MARTA_SID_FOR_NAME \
{ \ ((PKNOWN_ACE) *ppAcl)->Mask = pAccessInfo->Mask; \ AceSize = RtlLengthSid(pAccessInfo->pSid); \ memcpy( \ ((PUCHAR) *ppAcl) + sizeof(ACE_HEADER) + sizeof(ACCESS_MASK), \ (PUCHAR) pAccessInfo->pSid, \ AceSize \ ); \ AceSize += sizeof(ACE_HEADER) + sizeof(ACCESS_MASK); \ }
#define MARTA_SID_FOR_SID \
{ \ ((PKNOWN_ACE) *ppAcl)->Mask = pAccessInfo->Mask; \ AceSize = RtlLengthSid((PSID) pExplicitAccess->Trustee.ptstrName); \ memcpy( \ ((PUCHAR) *ppAcl) + sizeof(ACE_HEADER) + sizeof(ACCESS_MASK), \ (PUCHAR) pExplicitAccess->Trustee.ptstrName, \ AceSize \ ); \ AceSize += sizeof(ACE_HEADER) + sizeof(ACCESS_MASK); \ }
#define MARTA_SID_AND_GUID_FOR_OBJECT_NAME \
{ \ pObjName = (POBJECTS_AND_NAME_W) pExplicitAccess->Trustee.ptstrName;\ ((PKNOWN_OBJECT_ACE) *ppAcl)->Flags = pObjName->ObjectsPresent; \ ((PKNOWN_OBJECT_ACE) *ppAcl)->Mask = pAccessInfo->Mask; \ AceSize = RtlLengthSid(pAccessInfo->pSid); \ memcpy( \ (PUCHAR) RtlObjectAceSid(*ppAcl), \ (PUCHAR) pAccessInfo->pSid, \ AceSize \ ); \ pGuid = RtlObjectAceObjectType(*ppAcl); \ if (NULL != pGuid) \ { \ memcpy( \ (PUCHAR) pGuid, \ (PUCHAR) pAccessInfo->pObjectTypeGuid, \ sizeof(GUID) \ ); \ AceSize += sizeof(GUID); \ } \ pGuid = RtlObjectAceInheritedObjectType(*ppAcl); \ if (NULL != pGuid) \ { \ memcpy( \ (PUCHAR) pGuid, \ (PUCHAR) pAccessInfo->pInheritedObjectTypeGuid, \ sizeof(GUID) \ ); \ AceSize += sizeof(GUID); \ } \ AceSize += sizeof(ACE_HEADER) + sizeof(ACCESS_MASK) + sizeof(ULONG);\ }
#define MARTA_SID_AND_GUID_FOR_OBJECT_SID \
{ \ pObjSid = (POBJECTS_AND_SID) pExplicitAccess->Trustee.ptstrName; \ ((PKNOWN_OBJECT_ACE) *ppAcl)->Flags = pObjSid->ObjectsPresent; \ ((PKNOWN_OBJECT_ACE) *ppAcl)->Mask = pAccessInfo->Mask; \ AceSize = RtlLengthSid(pObjSid->pSid); \ memcpy( \ (PUCHAR) RtlObjectAceSid(*ppAcl), \ (PUCHAR) pObjSid->pSid, \ AceSize \ ); \ pGuid = RtlObjectAceObjectType(*ppAcl); \ if (NULL != pGuid) \ { \ memcpy( \ (PUCHAR) pGuid, \ (PUCHAR) &(pObjSid->ObjectTypeGuid), \ sizeof(GUID) \ ); \ AceSize += sizeof(GUID); \ } \ pGuid = RtlObjectAceInheritedObjectType(*ppAcl); \ if (NULL != pGuid) \ { \ memcpy( \ (PUCHAR) pGuid, \ (PUCHAR) &(pObjSid->InheritedObjectTypeGuid), \ sizeof(GUID) \ ); \ AceSize += sizeof(GUID); \ } \ AceSize += sizeof(ACE_HEADER) + sizeof(ACCESS_MASK) + sizeof(ULONG);\ }
typedef struct _MARTA_ACCESS_INFO { ACCESS_MASK Mask; ULONG Size; PSID pSid; PSID pServerSid; GUID * pObjectTypeGuid; GUID * pInheritedObjectTypeGuid; } MARTA_ACCESS_INFO, *PMARTA_ACCESS_INFO;
////////////////////////////////////////////////////////////////////////////////
// //
// FUNCTION PROTOTYPES START HERE //
// //
////////////////////////////////////////////////////////////////////////////////
DWORD WINAPI AccRewriteSetEntriesInAcl( IN ULONG cCountOfExplicitEntries, IN PEXPLICIT_ACCESS_W pListOfExplicitEntries, IN PACL OldAcl, OUT PACL * pNewAcl );
BOOL MartaIsExplicitAclCanonical( IN PACL pAcl, OUT PULONG pExplicitAceCnt );
DWORD MartaTrusteeSidAndGuidSize( IN PTRUSTEE_W pTrustee, IN BOOL bComputeGuidSize, OUT PSID * ppSid, OUT PULONG pSize, OUT PULONG pGuidCnt OPTIONAL );
DWORD MartaAddExplicitEntryToAcl( IN OUT PUCHAR * ppAcl, IN PEXPLICIT_ACCESS_W pExplicitAccess, IN PMARTA_ACCESS_INFO pAccessInfo );
DWORD MartaGetSidFromName( IN LPWSTR pName, OUT PSID * ppSid );
DWORD MartaGetGuid( IN LPWSTR pObjectName, IN SE_OBJECT_TYPE ObjectType, OUT GUID * pGuid );
DWORD MartaGetExplicitAccessEntrySize( IN PEXPLICIT_ACCESS_W pExplicitAccess, OUT PMARTA_ACCESS_INFO pAccessInfo, OUT PULONG pGuidCnt, OUT PUCHAR pAclRevision );
DWORD MartaCompareAcesAndMarkMasks( IN PUCHAR pAce, IN PACCESS_MASK pAceMask, IN PEXPLICIT_ACCESS_W pExplicitAccess, IN PMARTA_ACCESS_INFO pAccessInfo, IN BOOL bCanonical );
////////////////////////////////////////////////////////////////////////////////
// //
// Function: MartaAddExplicitEntryToAcl //
// //
// Description: Convert an explicit entry into an ace and store it in the //
// acl. Update the acl pointer to the end. //
// //
// Arguments: //
// //
// [IN OUT ppAcl] Acl pointer where the ace should be stored //
// //
// [IN pExplicitAccess] Explicit entry to convert into an ace //
// [IN pAccessInfo] Temp info associated with the explicit entry //
// //
// Returns: ERROR_SUCCESS if the entry could be converted into an ACE //
// Appropriate failure otherwise //
// //
////////////////////////////////////////////////////////////////////////////////
DWORD MartaAddExplicitEntryToAcl( IN OUT PUCHAR * ppAcl, IN PEXPLICIT_ACCESS_W pExplicitAccess, IN PMARTA_ACCESS_INFO pAccessInfo ) { DWORD dwErr = ERROR_SUCCESS; ULONG AceSize = 0; ULONG SidSize = 0; UCHAR AceType = 0; UCHAR AceFlags = 0; PSID pSid = NULL; GUID * pGuid = NULL; POBJECTS_AND_SID pObjSid = NULL; POBJECTS_AND_NAME_W pObjName = NULL;
if (REVOKE_ACCESS == pExplicitAccess->grfAccessMode) { return ERROR_SUCCESS; }
if (FLAG_ON(pExplicitAccess->grfInheritance, INHERITED_ACE)) { return ERROR_SUCCESS; }
if (0 == pAccessInfo->Size) { return ERROR_SUCCESS; }
if (TRUSTEE_IS_IMPERSONATE == pExplicitAccess->Trustee.MultipleTrusteeOperation) { ((PKNOWN_COMPOUND_ACE) *ppAcl)->CompoundAceType = COMPOUND_ACE_IMPERSONATION; ((PKNOWN_COMPOUND_ACE) *ppAcl)->Mask = pAccessInfo->Mask; ((PKNOWN_COMPOUND_ACE) *ppAcl)->Reserved = 0;
AceSize = sizeof(ACE_HEADER) + sizeof(ACCESS_MASK) + sizeof(LONG);
pSid = pAccessInfo->pServerSid ? pAccessInfo->pServerSid : (PSID) pExplicitAccess->Trustee.ptstrName;
SidSize = RtlLengthSid(pSid);
memcpy( ((PUCHAR) *ppAcl) + AceSize, (PUCHAR) pSid, SidSize );
AceSize += SidSize;
pSid = pAccessInfo->pSid ? pAccessInfo->pSid : (PSID) (pExplicitAccess->Trustee.pMultipleTrustee->ptstrName);
SidSize = RtlLengthSid(pSid);
memcpy( ((PUCHAR) *ppAcl) + AceSize, (PUCHAR) pSid, SidSize );
AceSize += SidSize;
CONDITIONAL_ACE_SIZE_ERROR(AceSize);
((PACE_HEADER) *ppAcl)->AceType = ACCESS_ALLOWED_COMPOUND_ACE_TYPE; ((PACE_HEADER) *ppAcl)->AceFlags = (UCHAR) pExplicitAccess->grfInheritance; ((PACE_HEADER) *ppAcl)->AceSize = (USHORT) AceSize; *ppAcl += AceSize;
return ERROR_SUCCESS; }
switch (pExplicitAccess->grfAccessMode) { case GRANT_ACCESS: case SET_ACCESS: AceFlags = (UCHAR) pExplicitAccess->grfInheritance; switch (pExplicitAccess->Trustee.TrusteeForm) { case TRUSTEE_IS_NAME: AceType = ACCESS_ALLOWED_ACE_TYPE; MARTA_SID_FOR_NAME break; case TRUSTEE_IS_SID: AceType = ACCESS_ALLOWED_ACE_TYPE; MARTA_SID_FOR_SID break; case TRUSTEE_IS_OBJECTS_AND_SID: AceType = ACCESS_ALLOWED_OBJECT_ACE_TYPE; MARTA_SID_AND_GUID_FOR_OBJECT_SID break; case TRUSTEE_IS_OBJECTS_AND_NAME: AceType = ACCESS_ALLOWED_OBJECT_ACE_TYPE; MARTA_SID_AND_GUID_FOR_OBJECT_NAME break; default: break; } break; case DENY_ACCESS: AceFlags = (UCHAR) pExplicitAccess->grfInheritance; switch (pExplicitAccess->Trustee.TrusteeForm) { case TRUSTEE_IS_NAME: AceType = ACCESS_DENIED_ACE_TYPE; MARTA_SID_FOR_NAME break; case TRUSTEE_IS_SID: AceType = ACCESS_DENIED_ACE_TYPE; MARTA_SID_FOR_SID break; case TRUSTEE_IS_OBJECTS_AND_SID: AceType = ACCESS_DENIED_OBJECT_ACE_TYPE; MARTA_SID_AND_GUID_FOR_OBJECT_SID break; case TRUSTEE_IS_OBJECTS_AND_NAME: AceType = ACCESS_DENIED_OBJECT_ACE_TYPE; MARTA_SID_AND_GUID_FOR_OBJECT_NAME break; default: break; } break; case SET_AUDIT_SUCCESS: AceFlags = (UCHAR) (pExplicitAccess->grfInheritance | SUCCESSFUL_ACCESS_ACE_FLAG); switch (pExplicitAccess->Trustee.TrusteeForm) { case TRUSTEE_IS_NAME: AceType = SYSTEM_AUDIT_ACE_TYPE; MARTA_SID_FOR_NAME break; case TRUSTEE_IS_SID: AceType = SYSTEM_AUDIT_ACE_TYPE; MARTA_SID_FOR_SID break; case TRUSTEE_IS_OBJECTS_AND_SID: AceType = SYSTEM_AUDIT_OBJECT_ACE_TYPE; MARTA_SID_AND_GUID_FOR_OBJECT_SID break; case TRUSTEE_IS_OBJECTS_AND_NAME: AceType = SYSTEM_AUDIT_OBJECT_ACE_TYPE; MARTA_SID_AND_GUID_FOR_OBJECT_NAME break; default: break; } break; case SET_AUDIT_FAILURE: AceFlags = (UCHAR) (pExplicitAccess->grfInheritance | FAILED_ACCESS_ACE_FLAG); switch (pExplicitAccess->Trustee.TrusteeForm) { case TRUSTEE_IS_NAME: AceType = SYSTEM_AUDIT_ACE_TYPE; MARTA_SID_FOR_NAME break; case TRUSTEE_IS_SID: AceType = SYSTEM_AUDIT_ACE_TYPE; MARTA_SID_FOR_SID break; case TRUSTEE_IS_OBJECTS_AND_SID: AceType = SYSTEM_AUDIT_OBJECT_ACE_TYPE; MARTA_SID_AND_GUID_FOR_OBJECT_SID break; case TRUSTEE_IS_OBJECTS_AND_NAME: AceType = SYSTEM_AUDIT_OBJECT_ACE_TYPE; MARTA_SID_AND_GUID_FOR_OBJECT_NAME break; default: break; } break; case REVOKE_ACCESS: return ERROR_SUCCESS; default: return ERROR_SUCCESS; }
CONDITIONAL_ACE_SIZE_ERROR(AceSize);
((PACE_HEADER) *ppAcl)->AceType = AceType; ((PACE_HEADER) *ppAcl)->AceFlags = AceFlags; ((PACE_HEADER) *ppAcl)->AceSize = (USHORT) AceSize;
*ppAcl += AceSize;
return ERROR_SUCCESS; }
////////////////////////////////////////////////////////////////////////////////
// //
// Function: MartaCompareAcesAndMarkMasks //
// //
// Description: Check if the explicit entry is supposed to make any changes //
// to the ace. If so, store the change into the temp structure //
// assoiciated with the ace. //
// //
// Arguments: //
// //
// [IN pAce] Ace to compare with the explict entry //
// [IN pAceMask] Temp info associated with the ace //
// [IN pExplicitAccess] Explicit entry //
// [IN pAccessInfo] Temp info associated with the explicit entry //
// [IN bCanonical] Whether the acl passed in is canonical //
// //
// Returns: ERROR_SUCCESS if the entry could be converted into an ACE //
// Appropriate failure otherwise //
// //
////////////////////////////////////////////////////////////////////////////////
DWORD MartaCompareAcesAndMarkMasks( IN PUCHAR pAce, IN PACCESS_MASK pAceMask, IN PEXPLICIT_ACCESS_W pExplicitAccess, IN PMARTA_ACCESS_INFO pAccessInfo, IN BOOL bCanonical ) { ULONG SidLength = 0; DWORD ObjectsPresent = 0; GUID * pGuid = NULL; GUID * pObjectTypeGuid = NULL; GUID * pInheritedObjectTypeGuid = NULL; PSID pSid = NULL; POBJECTS_AND_SID pObjSid = NULL; POBJECTS_AND_NAME_W pObjName = NULL; ULONG AuditFlag = FAILED_ACCESS_ACE_FLAG; UCHAR AceFlags = 0;
if (FLAG_ON(pExplicitAccess->grfInheritance, INHERITED_ACE)) { return ERROR_SUCCESS; }
if (TRUSTEE_IS_IMPERSONATE == pExplicitAccess->Trustee.MultipleTrusteeOperation) { if (ACCESS_ALLOWED_COMPOUND_ACE_TYPE != ((PACE_HEADER) pAce)->AceType) { return ERROR_SUCCESS; }
pSid = pAccessInfo->pServerSid ? pAccessInfo->pServerSid : (PSID) pExplicitAccess->Trustee.ptstrName;
if (!RtlEqualSid( pSid, (PSID) &(((PCOMPOUND_ACCESS_ALLOWED_ACE) pAce)->SidStart) )) { return ERROR_SUCCESS; }
SidLength = RtlLengthSid(pSid);
pSid = pAccessInfo->pSid ? pAccessInfo->pSid : (PSID) (pExplicitAccess->Trustee.pMultipleTrustee->ptstrName);
if (!RtlEqualSid( pSid, (PSID) (((PUCHAR) &(((PCOMPOUND_ACCESS_ALLOWED_ACE) pAce)->SidStart)) + SidLength) )) { return ERROR_SUCCESS; } } else { switch (((PACE_HEADER) pAce)->AceType) { case ACCESS_ALLOWED_ACE_TYPE: case ACCESS_DENIED_ACE_TYPE: case SYSTEM_AUDIT_ACE_TYPE: case SYSTEM_ALARM_ACE_TYPE: switch (pExplicitAccess->Trustee.TrusteeForm) { case TRUSTEE_IS_SID: pSid = (PSID) pExplicitAccess->Trustee.ptstrName; break; case TRUSTEE_IS_NAME: pSid = pAccessInfo->pSid; break; default: return ERROR_SUCCESS; }
if (!RtlEqualSid( pSid, (PSID) &(((PKNOWN_ACE) pAce)->SidStart) )) { return ERROR_SUCCESS; }
break; case ACCESS_ALLOWED_COMPOUND_ACE_TYPE: return ERROR_SUCCESS; case ACCESS_ALLOWED_OBJECT_ACE_TYPE: case ACCESS_DENIED_OBJECT_ACE_TYPE: case SYSTEM_AUDIT_OBJECT_ACE_TYPE: case SYSTEM_ALARM_OBJECT_ACE_TYPE:
switch (pExplicitAccess->Trustee.TrusteeForm) { case TRUSTEE_IS_OBJECTS_AND_SID: pObjSid = (POBJECTS_AND_SID) pExplicitAccess->Trustee.ptstrName; ObjectsPresent = pObjSid->ObjectsPresent; pSid = pObjSid->pSid; pObjectTypeGuid = &(pObjSid->ObjectTypeGuid); pInheritedObjectTypeGuid = &(pObjSid->InheritedObjectTypeGuid); break; case TRUSTEE_IS_OBJECTS_AND_NAME: pObjName = (POBJECTS_AND_NAME_W) pExplicitAccess->Trustee.ptstrName; ObjectsPresent = pObjName->ObjectsPresent; pSid = pAccessInfo->pSid; pObjectTypeGuid = pAccessInfo->pObjectTypeGuid; pInheritedObjectTypeGuid = pAccessInfo->pInheritedObjectTypeGuid; break; default: return ERROR_SUCCESS; }
if (ObjectsPresent != ((PKNOWN_OBJECT_ACE) pAce)->Flags) { return ERROR_SUCCESS; }
if (!RtlEqualSid(pSid, RtlObjectAceSid(pAce))) { return ERROR_SUCCESS; }
pGuid = RtlObjectAceObjectType(pAce);
if (NULL != pGuid) { if ((NULL == pObjectTypeGuid) || !RtlpIsEqualGuid(pGuid, pObjectTypeGuid)) { return ERROR_SUCCESS; } }
pGuid = RtlObjectAceInheritedObjectType(pAce);
if (NULL != pGuid) { if ((NULL == pInheritedObjectTypeGuid) || !RtlpIsEqualGuid(pGuid, pInheritedObjectTypeGuid)) { return ERROR_SUCCESS; } }
break; } }
AceFlags = (((PACE_HEADER) pAce)->AceFlags) & VALID_INHERIT_FLAGS;
switch (pExplicitAccess->grfAccessMode) { case REVOKE_ACCESS: switch (((PACE_HEADER) pAce)->AceType) { case ACCESS_ALLOWED_COMPOUND_ACE_TYPE: case ACCESS_ALLOWED_OBJECT_ACE_TYPE: case ACCESS_ALLOWED_ACE_TYPE: case SYSTEM_AUDIT_ACE_TYPE: case SYSTEM_AUDIT_OBJECT_ACE_TYPE: case SYSTEM_ALARM_ACE_TYPE: case SYSTEM_ALARM_OBJECT_ACE_TYPE: *pAceMask = 0; break; default: break; } break; case GRANT_ACCESS: if (pExplicitAccess->grfInheritance != AceFlags) { return ERROR_SUCCESS; }
switch (((PACE_HEADER) pAce)->AceType) { case ACCESS_ALLOWED_COMPOUND_ACE_TYPE: case ACCESS_ALLOWED_OBJECT_ACE_TYPE: case ACCESS_ALLOWED_ACE_TYPE: if (TRUE == bCanonical) { *pAceMask |= pAccessInfo->Mask; pAccessInfo->Size = 0; } break; case ACCESS_DENIED_OBJECT_ACE_TYPE: case ACCESS_DENIED_ACE_TYPE: *pAceMask &= ~pAccessInfo->Mask; break; default: return ERROR_SUCCESS; } break; case DENY_ACCESS: if (pExplicitAccess->grfInheritance != AceFlags) { return ERROR_SUCCESS; }
switch (((PACE_HEADER) pAce)->AceType) { case ACCESS_ALLOWED_COMPOUND_ACE_TYPE: case ACCESS_ALLOWED_OBJECT_ACE_TYPE: case ACCESS_ALLOWED_ACE_TYPE:
//
// Do not delete existing Allow aces!
//
// *pAceMask &= ~pAccessInfo->Mask;
//
break; case ACCESS_DENIED_OBJECT_ACE_TYPE: case ACCESS_DENIED_ACE_TYPE: if (TRUE == bCanonical) { *pAceMask |= pAccessInfo->Mask; pAccessInfo->Size = 0; } break; default: return ERROR_SUCCESS; } break; case SET_ACCESS: switch (((PACE_HEADER) pAce)->AceType) { case ACCESS_ALLOWED_COMPOUND_ACE_TYPE: case ACCESS_ALLOWED_OBJECT_ACE_TYPE: case ACCESS_ALLOWED_ACE_TYPE: case ACCESS_DENIED_OBJECT_ACE_TYPE: case ACCESS_DENIED_ACE_TYPE: *pAceMask = 0; break; default: return ERROR_SUCCESS; } break; case SET_AUDIT_SUCCESS: AuditFlag = SUCCESSFUL_ACCESS_ACE_FLAG; case SET_AUDIT_FAILURE: if (pExplicitAccess->grfInheritance != AceFlags) { return ERROR_SUCCESS; } switch (((PACE_HEADER) pAce)->AceType) { case SYSTEM_AUDIT_ACE_TYPE: case SYSTEM_AUDIT_OBJECT_ACE_TYPE: case SYSTEM_ALARM_ACE_TYPE: case SYSTEM_ALARM_OBJECT_ACE_TYPE: if (!FLAG_ON(((PACE_HEADER) pAce)->AceFlags, AuditFlag)) { return ERROR_SUCCESS; }
*pAceMask |= pAccessInfo->Mask; pAccessInfo->Size = 0; break; default: return ERROR_SUCCESS; } }
return ERROR_SUCCESS; }
////////////////////////////////////////////////////////////////////////////////
// //
// Function: MartaGetExplicitAccessEntrySize //
// //
// Description: Computes the memory size in bytes for the ace for the //
// explicit entry. //
// //
// Arguments: //
// //
// [IN pExplicitAccess] Explicit entry to convert into an ace //
// [IN pAccessInfo] Temp info associated with the explicit entry //
// //
// [IN OUT pGuidCnt] Number of guid-names that have to be convrted //
// to guid structs. //
// //
// Returns: ERROR_SUCCESS if the entry could be converted into an ACE //
// Appropriate failure otherwise //
// //
////////////////////////////////////////////////////////////////////////////////
DWORD MartaGetExplicitAccessEntrySize( IN PEXPLICIT_ACCESS_W pExplicitAccess, OUT PMARTA_ACCESS_INFO pAccessInfo, OUT PULONG pGuidCnt, OUT PUCHAR pAclRevision ) { DWORD dwErr = ERROR_SUCCESS; ULONG SidAndGuidSize = 0;
if (FLAG_ON(pExplicitAccess->grfInheritance, ~VALID_INHERIT_FLAGS)) { return ERROR_INVALID_PARAMETER; }
switch (pExplicitAccess->grfAccessMode) { case REVOKE_ACCESS: case DENY_ACCESS: case GRANT_ACCESS: case SET_ACCESS: case SET_AUDIT_SUCCESS: case SET_AUDIT_FAILURE: break; default: return ERROR_INVALID_PARAMETER; }
if (FLAG_ON(pExplicitAccess->grfInheritance, INHERITED_ACE)) { pAccessInfo->Size = 0; return ERROR_SUCCESS; }
//
// For an impersonate trustee, two sids contribute to the size.
//
if (TRUSTEE_IS_IMPERSONATE == pExplicitAccess->Trustee.MultipleTrusteeOperation) { pAccessInfo->Size = sizeof(ACE_HEADER) + sizeof(ACCESS_MASK) + sizeof(ULONG);
dwErr = MartaTrusteeSidAndGuidSize( &(pExplicitAccess->Trustee), FALSE, &(pAccessInfo->pServerSid), &SidAndGuidSize, NULL );
if (ERROR_SUCCESS != dwErr) { return dwErr; }
pAccessInfo->Size += SidAndGuidSize;
if (NULL == pExplicitAccess->Trustee.pMultipleTrustee) { return ERROR_INVALID_PARAMETER; }
dwErr = MartaTrusteeSidAndGuidSize( pExplicitAccess->Trustee.pMultipleTrustee, FALSE, &(pAccessInfo->pSid), &SidAndGuidSize, NULL );
if (ERROR_SUCCESS != dwErr) { return dwErr; }
pAccessInfo->Size += SidAndGuidSize;
if (*pAclRevision < ACL_REVISION3) { *pAclRevision = ACL_REVISION3; }
return ERROR_SUCCESS; }
//
// For any other type of trustee, compute the space required for the SID as
// well as Guids, if any.
//
switch (pExplicitAccess->Trustee.TrusteeForm) { case TRUSTEE_IS_OBJECTS_AND_SID: case TRUSTEE_IS_OBJECTS_AND_NAME: pAccessInfo->Size = sizeof(ACE_HEADER) + sizeof(ACCESS_MASK) + sizeof(ULONG); *pAclRevision = ACL_REVISION_DS; break; case TRUSTEE_IS_SID: case TRUSTEE_IS_NAME: pAccessInfo->Size = sizeof(ACE_HEADER) + sizeof(ACCESS_MASK); break; default: return ERROR_INVALID_PARAMETER; }
dwErr = MartaTrusteeSidAndGuidSize( &(pExplicitAccess->Trustee), TRUE, &(pAccessInfo->pSid), &SidAndGuidSize, pGuidCnt );
if (ERROR_SUCCESS != dwErr) { return dwErr; }
if (REVOKE_ACCESS == pExplicitAccess->grfAccessMode) { pAccessInfo->Size = 0; } else { pAccessInfo->Size += SidAndGuidSize; }
return ERROR_SUCCESS; }
////////////////////////////////////////////////////////////////////////////////
// //
// Function: MartaIsExplicitAclCanonical //
// //
// Description: Determines whether the explicit part of the acl is canonical. //
// Finds the first explicit allow ace. //
// //
// Arguments: //
// //
// [IN pAcl] Acl //
// [OUT pExplicitAceCnt] To return the first allow explicit ace //
// //
// Returns: TRUE if the acl is canonical //
// FALSE otherwise //
// //
////////////////////////////////////////////////////////////////////////////////
BOOL MartaIsExplicitAclCanonical( IN PACL pAcl, OUT PULONG pExplicitAceCnt ) { USHORT j; USHORT AceCnt; PACE_HEADER pAce;
*pExplicitAceCnt = 0;
if ((NULL == pAcl) || (0 == pAcl->AceCount)) { return TRUE; }
AceCnt = pAcl->AceCount;
pAce = (PACE_HEADER) FirstAce(pAcl); for (j = 0; j < AceCnt; pAce = (PACE_HEADER) NextAce(pAce)) { if (FLAG_ON(pAce->AceFlags, INHERITED_ACE)) { j++; continue; }
if ((ACCESS_ALLOWED_ACE_TYPE == pAce->AceType) || (ACCESS_ALLOWED_OBJECT_ACE_TYPE == pAce->AceType) || (ACCESS_ALLOWED_COMPOUND_ACE_TYPE == pAce->AceType)) { break; }
*pExplicitAceCnt = ++j; }
for (; j < AceCnt; j++, pAce = (PACE_HEADER) NextAce(pAce)) { if (FLAG_ON(pAce->AceFlags, INHERITED_ACE)) { continue; }
if ((ACCESS_DENIED_ACE_TYPE == pAce->AceType) || (ACCESS_DENIED_OBJECT_ACE_TYPE == pAce->AceType)) { return FALSE; } }
return TRUE; }
////////////////////////////////////////////////////////////////////////////////
// //
// Function: MartaTrusteeSidAndGuidSize //
// //
// Description: Compute the size for the Sid(s) and Guid(s) for the trustee. //
// //
// Arguments: //
// //
// [IN pTrustee] Trsutee for which the size has to be computed //
// [IN bComputeGuidSize] Whether Guidsize should be computed //
// //
// [OUT ppSid] To return the Sid if trustee is "named" //
// [OUT pSize] To return the size computed //
// [OUT pGuidCnt] To return the number of guids //
// //
// Returns: ERROR_SUCCESS if Name to Sid resolution passed //
// Appropriate failure otherwise //
// //
////////////////////////////////////////////////////////////////////////////////
DWORD MartaTrusteeSidAndGuidSize( IN PTRUSTEE_W pTrustee, IN BOOL bComputeGuidSize, OUT PSID * ppSid, OUT PULONG pSize, OUT PULONG pGuidCnt OPTIONAL ) { PSID pSid = NULL; SID_NAME_USE SidType = SidTypeUnknown; DWORD dwErr = ERROR_SUCCESS;
switch (pTrustee->TrusteeForm) { case TRUSTEE_IS_SID:
pSid = (PSID) pTrustee->ptstrName;
if ((NULL == pSid) || (!RtlValidSid(pSid))) { return ERROR_INVALID_PARAMETER; }
*pSize = RtlLengthSid(pSid);
break;
case TRUSTEE_IS_OBJECTS_AND_SID:
pSid = ((POBJECTS_AND_SID) pTrustee->ptstrName)->pSid;
if ((NULL == pSid) || (!RtlValidSid(pSid))) { return ERROR_INVALID_PARAMETER; }
*pSize = RtlLengthSid(pSid);
if (TRUE == bComputeGuidSize) { if (FLAG_ON(((POBJECTS_AND_SID) pTrustee->ptstrName)->ObjectsPresent, ACE_OBJECT_TYPE_PRESENT)) { *pSize += sizeof(GUID); }
if (FLAG_ON(((POBJECTS_AND_SID) pTrustee->ptstrName)->ObjectsPresent, ACE_INHERITED_OBJECT_TYPE_PRESENT)) { *pSize += sizeof(GUID); } }
break;
case TRUSTEE_IS_NAME:
dwErr = MartaGetSidFromName(pTrustee->ptstrName, ppSid);
CONDITIONAL_RETURN(dwErr);
*pSize = RtlLengthSid(*ppSid);
break;
case TRUSTEE_IS_OBJECTS_AND_NAME:
dwErr = MartaGetSidFromName( ((POBJECTS_AND_NAME_W) pTrustee->ptstrName)->ptstrName, ppSid );
CONDITIONAL_RETURN(dwErr);
*pSize = RtlLengthSid(*ppSid);
if (TRUE == bComputeGuidSize) { if (FLAG_ON(((POBJECTS_AND_NAME_W) pTrustee->ptstrName)->ObjectsPresent, ACE_OBJECT_TYPE_PRESENT)) { *pSize += sizeof(GUID); (*pGuidCnt)++; }
if (FLAG_ON(((POBJECTS_AND_NAME_W) pTrustee->ptstrName)->ObjectsPresent, ACE_INHERITED_OBJECT_TYPE_PRESENT)) { *pSize += sizeof(GUID); (*pGuidCnt)++; } }
break;
default: return ERROR_NONE_MAPPED;
}
return ERROR_SUCCESS; }
////////////////////////////////////////////////////////////////////////////////
// //
// Function: MartaGetSidFromName //
// //
// Description: Resolves a given Name to Sid. //
// //
// Arguments: //
// //
// [IN pName] Name to be resolved //
// [OUT ppSid] To return the Sid for the trustee //
// //
// Returns: ERROR_SUCCESS if Name to Sid resolution passed //
// Appropriate failure otherwise //
// //
////////////////////////////////////////////////////////////////////////////////
DWORD MartaGetSidFromName( IN LPWSTR pName, OUT PSID * ppSid ) {
#define MARTA_DEFAULT_SID_SIZE 64
#define MARTA_DEFAULT_DOMAIN_SIZE 256
WCHAR DomainBuffer[MARTA_DEFAULT_DOMAIN_SIZE]; ULONG SidSize = MARTA_DEFAULT_SID_SIZE; ULONG DomainSize = MARTA_DEFAULT_DOMAIN_SIZE; LPWSTR Domain = (LPWSTR) DomainBuffer; SID_NAME_USE SidNameUse = SidTypeUnknown; DWORD dwErr = ERROR_SUCCESS;
if (NULL == ppSid) { return ERROR_INVALID_PARAMETER; }
if(0 == _wcsicmp(pName, L"CURRENT_USER")) { HANDLE TokenHandle;
dwErr = GetCurrentToken(&TokenHandle);
if(dwErr != ERROR_SUCCESS) { return dwErr; }
dwErr = AccGetSidFromToken( NULL, TokenHandle, TokenUser, ppSid );
CloseHandle(TokenHandle);
return dwErr; }
*ppSid = (PSID) AccAlloc(SidSize);
if(NULL == *ppSid) { return ERROR_NOT_ENOUGH_MEMORY; }
if(!LookupAccountName( NULL, pName, *ppSid, &SidSize, Domain, &DomainSize, &SidNameUse)) { dwErr = GetLastError();
if(dwErr == ERROR_INSUFFICIENT_BUFFER) { dwErr = ERROR_SUCCESS;
if (SidSize > MARTA_DEFAULT_SID_SIZE) { AccFree(*ppSid);
*ppSid = (PSID) AccAlloc(SidSize);
if (*ppSid == NULL) { dwErr = ERROR_NOT_ENOUGH_MEMORY; goto End; } }
if(DomainSize > MARTA_DEFAULT_DOMAIN_SIZE) { Domain = (LPWSTR) AccAlloc(DomainSize * sizeof(WCHAR));
if (NULL == Domain) { dwErr = ERROR_NOT_ENOUGH_MEMORY; goto End; }
} if(!LookupAccountName( NULL, pName, *ppSid, &SidSize, Domain, &DomainSize, &SidNameUse)) { dwErr = GetLastError(); goto End; } } }
End:
if (Domain != (LPWSTR) DomainBuffer) { AccFree(Domain); }
if (ERROR_SUCCESS != dwErr) { if (NULL != *ppSid) { AccFree(*ppSid); *ppSid = NULL; } } return dwErr; }
////////////////////////////////////////////////////////////////////////////////
// //
// Function: MartaGetGuid //
// //
// Description: Resolves a given Guid Name to a Guid struct. //
// //
// Arguments: //
// //
// [IN pObjectName] Name to be resolved //
// [IN ObjectType] Object type of the name to be resolved //
// [OUT pGuid] To return the guid //
// //
// Returns: ERROR_SUCCESS if Name to guid resolution passed //
// Appropriate failure otherwise //
// //
////////////////////////////////////////////////////////////////////////////////
DWORD MartaGetGuid( IN LPWSTR pObjectName, IN SE_OBJECT_TYPE ObjectType, OUT GUID * pGuid ) { switch (ObjectType) { case SE_DS_OBJECT: case SE_DS_OBJECT_ALL: break; default: return ERROR_INVALID_PARAMETER; }
return MartaConvertNameToGuid[ObjectType]( pObjectName, pGuid ); }
////////////////////////////////////////////////////////////////////////////////
// //
// Function: AccRewriteSetEntriesInAcl //
// //
// Description: Resolves a given Name to Sid. //
// //
// Arguments: //
// //
// [IN cCountOfExplicitEntries] Number of items in list //
// [IN pListOfExplicitEntries] List of entries to be added //
// [IN OldAcl] The old acl to add the entries to //
// [OUT pNewAcl] To return the new acl //
// //
// Returns: ERROR_SUCCESS if everything passed //
// Appropriate failure otherwise //
// //
////////////////////////////////////////////////////////////////////////////////
DWORD WINAPI AccRewriteSetEntriesInAcl( IN ULONG cCountOfExplicitEntries, IN PEXPLICIT_ACCESS_W pListOfExplicitEntries, IN PACL OldAcl, OUT PACL * pNewAcl )
{ PMARTA_ACCESS_INFO pAccessInfo = NULL; PACCESS_MASK pAceMaskInfo = NULL; PACE_HEADER pAce = NULL; GUID * pGuid = NULL; GUID * pCurrentGuid = NULL; POBJECTS_AND_NAME_W pObjName = NULL; PUCHAR pAcl = NULL; USHORT OldAceCnt = 0; USHORT NewAceCnt = 0; ULONG ExplicitAceCnt = 0; ULONG NewAclSize = sizeof(ACL); BOOL bCanonical = TRUE; DWORD dwErr = ERROR_SUCCESS; ULONG i = 0; ULONG j = 0; ULONG GuidCnt = 0; ULONG ObjectsPresent = 0; UCHAR AclRevision = ACL_REVISION;
if ((NULL == pNewAcl) || ((NULL != OldAcl) && (!RtlValidAcl(OldAcl))))
{ return ERROR_INVALID_PARAMETER; }
*pNewAcl = NULL;
//
// If the number of entries to be added is zero then make a copy of the Old
// Acl as it is. Do not try to convert it into Canonical form if it's not.
//
if (0 == cCountOfExplicitEntries) { if (NULL != OldAcl) { *pNewAcl = (PACL) AccAlloc(OldAcl->AclSize);
if (NULL == *pNewAcl) { return ERROR_NOT_ENOUGH_MEMORY; }
memcpy((PUCHAR) *pNewAcl, (PUCHAR) OldAcl, OldAcl->AclSize); } return ERROR_SUCCESS; }
//
// Canonical acls processing will be done as in the past.
// Note: We now support non-canonical acls as well..
//
bCanonical = MartaIsExplicitAclCanonical(OldAcl, &ExplicitAceCnt);
//
// The Mask for all the aces is stored in a pAceMaskInfo and modified as
// dictated by the ExplicitAccess entries.
//
if (NULL != OldAcl) { OldAceCnt = OldAcl->AceCount; NewAclSize = OldAcl->AclSize; NewAceCnt = OldAceCnt;
pAceMaskInfo = (PACCESS_MASK) AccAlloc(sizeof(ACCESS_MASK) * OldAceCnt);
if (NULL == pAceMaskInfo) { dwErr = ERROR_NOT_ENOUGH_MEMORY; goto End; }
AclRevision = OldAcl->AclRevision; }
//
// Note: cCountOfExplicitEntries is non-zero at this point.
//
pAccessInfo = (PMARTA_ACCESS_INFO) AccAlloc(sizeof(MARTA_ACCESS_INFO) * cCountOfExplicitEntries);
if (NULL == pAccessInfo) { dwErr = ERROR_NOT_ENOUGH_MEMORY; goto End; }
//
// Initialize the temp structures for the acl and the explicit entries.
//
pAce = (PACE_HEADER) FirstAce(OldAcl);
for (j = 0; j < OldAceCnt; j++, pAce = (PACE_HEADER) NextAce(pAce)) { pAceMaskInfo[j] = ((PKNOWN_ACE) pAce)->Mask; }
for (i = 0; i < cCountOfExplicitEntries; i++) { pAccessInfo[i].pServerSid = NULL; pAccessInfo[i].pSid = NULL; pAccessInfo[i].pObjectTypeGuid = NULL; pAccessInfo[i].pInheritedObjectTypeGuid = NULL; pAccessInfo[i].Mask = pListOfExplicitEntries[i].grfAccessPermissions; }
//
// Compute the size required to add this explicit entry to the acl.
//
for (i = 0; i < cCountOfExplicitEntries; i++) { dwErr = MartaGetExplicitAccessEntrySize( pListOfExplicitEntries + i, pAccessInfo + i, &GuidCnt, &AclRevision );
CONDITIONAL_EXIT(dwErr, End); }
//
// For TRUSTEE_IS_OBJECTS_AND_NAME, resolve the GuidNames to Guids and store
// them in the temp structure.
//
if (0 != GuidCnt) { pGuid = pCurrentGuid = (GUID *) AccAlloc(sizeof(GUID) * GuidCnt);
if (NULL == pGuid) { dwErr = ERROR_NOT_ENOUGH_MEMORY; goto End; }
for (i = 0; i < cCountOfExplicitEntries; i++) { pObjName = (POBJECTS_AND_NAME_W) pListOfExplicitEntries[i].Trustee.ptstrName; ObjectsPresent = pObjName->ObjectsPresent;
if (FLAG_ON(ObjectsPresent, ACE_OBJECT_TYPE_PRESENT)) { dwErr = MartaGetGuid( pObjName->ObjectTypeName, pObjName->ObjectType, pCurrentGuid );
CONDITIONAL_EXIT(dwErr, End);
pAccessInfo[i].pObjectTypeGuid = pCurrentGuid++; }
if (FLAG_ON(ObjectsPresent, ACE_INHERITED_OBJECT_TYPE_PRESENT)) { dwErr = MartaGetGuid( pObjName->InheritedObjectTypeName, pObjName->ObjectType, pCurrentGuid );
CONDITIONAL_EXIT(dwErr, End);
pAccessInfo[i].pInheritedObjectTypeGuid = pCurrentGuid++; } } }
//
// Compute the effect of explict entries added on the exisiting acl.
// The size of an explicit entry will be set to zero if the entry will be
// absorbed by some existing ace.
// The Mask for an ace will be set to zero if the AceMask flags have been
// nulled out by explicit entries.
//
for (i = 0; i < cCountOfExplicitEntries; i++) { pAce = (PACE_HEADER) FirstAce(OldAcl);
for (j = 0; j < OldAceCnt; j++, pAce = (PACE_HEADER) NextAce(pAce)) { //
// Skip Inherited aces.
//
if (FLAG_ON(pAce->AceFlags, INHERITED_ACE)) { continue; }
dwErr = MartaCompareAcesAndMarkMasks( (PUCHAR) pAce, pAceMaskInfo + j, pListOfExplicitEntries + i, pAccessInfo + i, bCanonical ); CONDITIONAL_EXIT(dwErr, End); } }
//
// Compute the size required for the new acl and the number of aces in it.
//
pAce = (PACE_HEADER) FirstAce(OldAcl);
for (j = 0; j < OldAceCnt; j++, pAce = (PACE_HEADER) NextAce(pAce)) { if (0 == pAceMaskInfo[j]) { NewAclSize -= pAce->AceSize; NewAceCnt--; } }
for (i = 0; i < cCountOfExplicitEntries; i++) { if (0 != pAccessInfo[i].Size) { NewAclSize += pAccessInfo[i].Size; NewAceCnt++; } }
*pNewAcl = (PACL) AccAlloc(NewAclSize);
if (NULL == *pNewAcl) { dwErr = ERROR_NOT_ENOUGH_MEMORY; goto End; }
if (FALSE == InitializeAcl(*pNewAcl, NewAclSize, AclRevision)) { dwErr = GetLastError(); goto End; }
(*pNewAcl)->AceCount = NewAceCnt;
pAcl = ((PUCHAR) *pNewAcl) + sizeof(ACL);
for (i = 0; i < cCountOfExplicitEntries; i++) { //
// Add all the DENY ACES to the ACL.
//
switch (pListOfExplicitEntries[i].grfAccessMode) { case DENY_ACCESS: case SET_AUDIT_SUCCESS: case SET_AUDIT_FAILURE: dwErr = MartaAddExplicitEntryToAcl( &pAcl, pListOfExplicitEntries + i, pAccessInfo + i ); CONDITIONAL_EXIT(dwErr, End); break; default: break; } }
//
// Copy the explicit aces from the OldAcl that have not been invalidated by
// the new Aces added.
// Inherited aces will be copied afterthe explict ones have been copied.
//
pAce = (PACE_HEADER) FirstAce(OldAcl);
for (j = 0; j < ExplicitAceCnt; j++, pAce = (PACE_HEADER) NextAce(pAce)) { if (FLAG_ON(pAce->AceFlags, INHERITED_ACE)) { continue; }
if (0 != pAceMaskInfo[j]) { memcpy((PUCHAR) pAcl, (PUCHAR) pAce, pAce->AceSize);
((PKNOWN_ACE) pAcl)->Mask = pAceMaskInfo[j]; pAcl += pAce->AceSize; } }
//
// Add all the NON-DENY ACES to the ACL.
// DENY aces have already been added.
//
// If the ACL was canonical then follow the old behavior i.e. add the
// remaining explicit entries to the beginning of the "allowed" acl.
// Otherwise, add the ACEs to the end of the explicit part of the ACL.
//
if (FALSE == bCanonical) { for (; j < OldAceCnt; j++, pAce = (PACE_HEADER) NextAce(pAce)) { if (FLAG_ON(pAce->AceFlags, INHERITED_ACE)) { continue; }
if (0 != pAceMaskInfo[j]) { memcpy((PUCHAR) pAcl, (PUCHAR) pAce, pAce->AceSize);
((PKNOWN_ACE) pAcl)->Mask = pAceMaskInfo[j]; pAcl += pAce->AceSize; } }
for (i = 0; i < cCountOfExplicitEntries; i++) { switch (pListOfExplicitEntries[i].grfAccessMode) { case GRANT_ACCESS: case SET_ACCESS: dwErr = MartaAddExplicitEntryToAcl( &pAcl, pListOfExplicitEntries + i, pAccessInfo + i ); CONDITIONAL_EXIT(dwErr, End); break; default: break; } } } else { for (i = 0; i < cCountOfExplicitEntries; i++) { switch (pListOfExplicitEntries[i].grfAccessMode) { case GRANT_ACCESS: case SET_ACCESS: dwErr = MartaAddExplicitEntryToAcl( &pAcl, pListOfExplicitEntries + i, pAccessInfo + i ); CONDITIONAL_EXIT(dwErr, End); break; default: break; } }
for (; j < OldAceCnt; j++, pAce = (PACE_HEADER) NextAce(pAce)) { if (FLAG_ON(pAce->AceFlags, INHERITED_ACE)) { continue; }
if (0 != pAceMaskInfo[j]) { memcpy((PUCHAR) pAcl, (PUCHAR) pAce, pAce->AceSize);
((PKNOWN_ACE) pAcl)->Mask = pAceMaskInfo[j]; pAcl += pAce->AceSize; } } }
//
// Add the inherited aces to the new ACL. This will reorder the ACEs so that
// the EXPLICIT ACEs precede the INHERITED ONES but will not arrange the ACL
// in canonical form if it was not to start with.
//
pAce = (PACE_HEADER) FirstAce(OldAcl);
for (j = 0; j < OldAceCnt; j++, pAce = (PACE_HEADER) NextAce(pAce)) { if (FLAG_ON(pAce->AceFlags, INHERITED_ACE)) { memcpy((PUCHAR) pAcl, (PUCHAR) pAce, pAce->AceSize);
pAcl += pAce->AceSize; } }
End: if (NULL != pAccessInfo) { for (i = 0; i < cCountOfExplicitEntries; i++ ) { if (NULL != pAccessInfo[i].pServerSid) { AccFree(pAccessInfo[i].pServerSid); }
if (NULL != pAccessInfo[i].pSid) { AccFree(pAccessInfo[i].pSid); } } AccFree(pAccessInfo); }
if (NULL != pGuid) { AccFree(pGuid); }
if (NULL != pAceMaskInfo) { AccFree(pAceMaskInfo); }
if (ERROR_SUCCESS != dwErr) { if (NULL != *pNewAcl) { AccFree(*pNewAcl); *pNewAcl = NULL; } }
return dwErr; }
|