You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
841 lines
21 KiB
841 lines
21 KiB
/*++
|
|
|
|
Copyright (c) 1999-2002 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
seutil.c
|
|
|
|
Abstract:
|
|
|
|
This module implements general security utilities, and
|
|
dispatch routines for security IRPs.
|
|
|
|
Author:
|
|
|
|
Keith Moore (keithmo) 25-Mar-1999
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
|
|
#include "precomp.h"
|
|
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text( PAGE, UlAssignSecurity )
|
|
#pragma alloc_text( PAGE, UlDeassignSecurity )
|
|
#pragma alloc_text( PAGE, UlSetSecurity )
|
|
#pragma alloc_text( PAGE, UlQuerySecurity )
|
|
#pragma alloc_text( PAGE, UlAccessCheck )
|
|
#pragma alloc_text( PAGE, UlSetSecurityDispatch )
|
|
#pragma alloc_text( PAGE, UlQuerySecurityDispatch )
|
|
#pragma alloc_text( PAGE, UlThreadAdminCheck )
|
|
#pragma alloc_text( PAGE, UlCreateSecurityDescriptor )
|
|
#pragma alloc_text( PAGE, UlCleanupSecurityDescriptor )
|
|
#pragma alloc_test( PAGE, UlMapGenericMask )
|
|
#endif // ALLOC_PRAGMA
|
|
#if 0
|
|
#endif
|
|
|
|
|
|
//
|
|
// Public functions.
|
|
//
|
|
|
|
/***************************************************************************++
|
|
|
|
Routine Description:
|
|
|
|
Assigns a new security descriptor.
|
|
|
|
Arguments:
|
|
|
|
pSecurityDescriptor - Supplies a pointer to the current security
|
|
descriptor pointer. The current security descriptor pointer
|
|
will be updated with the new security descriptor.
|
|
|
|
pAccessState - Supplies the ACCESS_STATE structure containing
|
|
the state of an access in progress.
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS - Completion status.
|
|
|
|
--***************************************************************************/
|
|
NTSTATUS
|
|
UlAssignSecurity(
|
|
IN OUT PSECURITY_DESCRIPTOR *pSecurityDescriptor,
|
|
IN PACCESS_STATE pAccessState
|
|
)
|
|
{
|
|
NTSTATUS status;
|
|
|
|
//
|
|
// Sanity check.
|
|
//
|
|
|
|
PAGED_CODE();
|
|
|
|
ASSERT( pSecurityDescriptor != NULL );
|
|
ASSERT( pAccessState != NULL );
|
|
|
|
//
|
|
// Assign the security descriptor.
|
|
//
|
|
|
|
SeLockSubjectContext( &pAccessState->SubjectSecurityContext );
|
|
|
|
status = SeAssignSecurity(
|
|
NULL, // ParentDescriptor
|
|
pAccessState->SecurityDescriptor,
|
|
pSecurityDescriptor,
|
|
FALSE, // IsDirectoryObject
|
|
&pAccessState->SubjectSecurityContext,
|
|
IoGetFileObjectGenericMapping(),
|
|
PagedPool
|
|
);
|
|
|
|
SeUnlockSubjectContext( &pAccessState->SubjectSecurityContext );
|
|
|
|
return status;
|
|
|
|
} // UlAssignSecurity
|
|
|
|
|
|
/***************************************************************************++
|
|
|
|
Routine Description:
|
|
|
|
Deletes a security descriptor.
|
|
|
|
Arguments:
|
|
|
|
pSecurityDescriptor - Supplies a pointer to the current security
|
|
descriptor pointer. The current security descriptor pointer
|
|
will be deleted.
|
|
|
|
--***************************************************************************/
|
|
VOID
|
|
UlDeassignSecurity(
|
|
IN OUT PSECURITY_DESCRIPTOR *pSecurityDescriptor
|
|
)
|
|
{
|
|
//
|
|
// Sanity check.
|
|
//
|
|
|
|
PAGED_CODE();
|
|
|
|
ASSERT( pSecurityDescriptor != NULL );
|
|
|
|
//
|
|
// If there's a security descriptor present, free it.
|
|
//
|
|
|
|
if (*pSecurityDescriptor != NULL)
|
|
{
|
|
SeDeassignSecurity( pSecurityDescriptor );
|
|
}
|
|
|
|
} // UlDeassignSecurity
|
|
|
|
|
|
/***************************************************************************++
|
|
|
|
Routine Description:
|
|
|
|
Sets a new security descriptor.
|
|
|
|
Arguments:
|
|
|
|
pSecurityDescriptor - Supplies a pointer to the current security
|
|
descriptor pointer. The current security descriptor will be
|
|
updated with the new security information.
|
|
|
|
pSecurityInformation - Indicates which security information is
|
|
to be applied to the object.
|
|
|
|
pNewSecurityDescriptor - Pointer to the new security descriptor
|
|
to be applied to the object.
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS - Completion status.
|
|
|
|
--***************************************************************************/
|
|
NTSTATUS
|
|
UlSetSecurity(
|
|
IN OUT PSECURITY_DESCRIPTOR *ppSecurityDescriptor,
|
|
IN PSECURITY_INFORMATION pSecurityInformation,
|
|
IN PSECURITY_DESCRIPTOR pNewSecurityDescriptor
|
|
)
|
|
{
|
|
NTSTATUS status;
|
|
PSECURITY_DESCRIPTOR pOldSecurityDescriptor;
|
|
SECURITY_SUBJECT_CONTEXT securitySubjectContext;
|
|
|
|
PAGED_CODE();
|
|
|
|
pOldSecurityDescriptor = *ppSecurityDescriptor;
|
|
|
|
SeCaptureSubjectContext(&securitySubjectContext);
|
|
SeLockSubjectContext(&securitySubjectContext);
|
|
|
|
status = SeSetSecurityDescriptorInfo(
|
|
NULL,
|
|
pSecurityInformation,
|
|
pNewSecurityDescriptor,
|
|
ppSecurityDescriptor,
|
|
PagedPool,
|
|
IoGetFileObjectGenericMapping()
|
|
);
|
|
|
|
SeUnlockSubjectContext(&securitySubjectContext);
|
|
SeReleaseSubjectContext(&securitySubjectContext);
|
|
|
|
if (NT_SUCCESS(status))
|
|
{
|
|
SeDeassignSecurity(&pOldSecurityDescriptor);
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
/***************************************************************************++
|
|
|
|
Routine Description:
|
|
|
|
Query for security descriptor information for an object.
|
|
|
|
Arguments:
|
|
|
|
pSecurityInformation - specifies what information is being queried.
|
|
|
|
pSecurityDescriptor - Supplies a pointer to the security descriptor
|
|
to be filled in.
|
|
|
|
pLength - Address of variable containing length of the above security
|
|
descriptor buffer. Upon return, this will contain the length needed
|
|
to store the requested information.
|
|
|
|
ppSecurityDescriptor - Address of a pointer to the objects security
|
|
descriptor.
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS - Completion status.
|
|
|
|
--***************************************************************************/
|
|
NTSTATUS
|
|
UlQuerySecurity(
|
|
IN PSECURITY_INFORMATION pSecurityInformation,
|
|
OUT PSECURITY_DESCRIPTOR pSecurityDescriptor,
|
|
IN OUT PULONG pLength,
|
|
IN PSECURITY_DESCRIPTOR *ppSecurityDescriptor
|
|
)
|
|
{
|
|
NTSTATUS status;
|
|
SECURITY_SUBJECT_CONTEXT securitySubjectContext;
|
|
|
|
PAGED_CODE();
|
|
|
|
SeCaptureSubjectContext(&securitySubjectContext);
|
|
SeLockSubjectContext(&securitySubjectContext);
|
|
|
|
status = SeQuerySecurityDescriptorInfo(
|
|
pSecurityInformation,
|
|
pSecurityDescriptor,
|
|
pLength,
|
|
ppSecurityDescriptor
|
|
);
|
|
|
|
SeUnlockSubjectContext(&securitySubjectContext);
|
|
SeReleaseSubjectContext(&securitySubjectContext);
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
/***************************************************************************++
|
|
|
|
Routine Description:
|
|
|
|
Determines if a user has access to the specified resource.
|
|
|
|
Arguments:
|
|
|
|
pSecurityDescriptor - Supplies the security descriptor protecting
|
|
the resource.
|
|
|
|
pAccessState - Supplies the ACCESS_STATE structure containing
|
|
the state of an access in progress.
|
|
|
|
DesiredAccess - Supplies an access mask describing the user's
|
|
desired access to the resource. This mask is assumed to not
|
|
contain generic access types.
|
|
|
|
RequestorMode - Supplies the processor mode by which the access is
|
|
being requested.
|
|
|
|
pObjectName - Supplies the name of the object being referenced.
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS - Completion status.
|
|
|
|
--***************************************************************************/
|
|
NTSTATUS
|
|
UlAccessCheck(
|
|
IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
|
|
IN PACCESS_STATE pAccessState,
|
|
IN ACCESS_MASK DesiredAccess,
|
|
IN KPROCESSOR_MODE RequestorMode,
|
|
IN PCWSTR pObjectName
|
|
)
|
|
{
|
|
NTSTATUS status, aaStatus;
|
|
BOOLEAN accessGranted;
|
|
PPRIVILEGE_SET pPrivileges = NULL;
|
|
ACCESS_MASK grantedAccess;
|
|
UNICODE_STRING objectName;
|
|
UNICODE_STRING typeName;
|
|
|
|
//
|
|
// Sanity check.
|
|
//
|
|
|
|
PAGED_CODE();
|
|
|
|
ASSERT( pSecurityDescriptor != NULL );
|
|
ASSERT( pAccessState != NULL );
|
|
|
|
//
|
|
// Perform the access check.
|
|
//
|
|
|
|
SeLockSubjectContext( &pAccessState->SubjectSecurityContext );
|
|
|
|
accessGranted = SeAccessCheck(
|
|
pSecurityDescriptor,
|
|
&pAccessState->SubjectSecurityContext,
|
|
TRUE, // SubjectContextLocked
|
|
DesiredAccess,
|
|
0, // PreviouslyGrantedAccess
|
|
&pPrivileges,
|
|
IoGetFileObjectGenericMapping(),
|
|
RequestorMode,
|
|
&grantedAccess,
|
|
&status
|
|
);
|
|
|
|
if (pPrivileges != NULL)
|
|
{
|
|
SeAppendPrivileges( pAccessState, pPrivileges );
|
|
SeFreePrivileges( pPrivileges );
|
|
}
|
|
|
|
if (accessGranted)
|
|
{
|
|
pAccessState->PreviouslyGrantedAccess |= grantedAccess;
|
|
pAccessState->RemainingDesiredAccess &= ~(grantedAccess | MAXIMUM_ALLOWED);
|
|
}
|
|
|
|
aaStatus = UlInitUnicodeStringEx( &typeName, L"Ul" );
|
|
|
|
if ( NT_SUCCESS(aaStatus) )
|
|
{
|
|
aaStatus = UlInitUnicodeStringEx( &objectName, pObjectName );
|
|
|
|
if ( NT_SUCCESS(aaStatus) )
|
|
{
|
|
SeOpenObjectAuditAlarm(
|
|
&typeName,
|
|
NULL, // Object
|
|
&objectName,
|
|
pSecurityDescriptor,
|
|
pAccessState,
|
|
FALSE, // ObjectCreated
|
|
accessGranted,
|
|
RequestorMode,
|
|
&pAccessState->GenerateOnClose
|
|
);
|
|
}
|
|
}
|
|
|
|
SeUnlockSubjectContext( &pAccessState->SubjectSecurityContext );
|
|
|
|
if (accessGranted)
|
|
{
|
|
status = STATUS_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// SeAccessCheck() should have set the completion status.
|
|
//
|
|
|
|
ASSERT( !NT_SUCCESS(status) );
|
|
}
|
|
|
|
return status;
|
|
|
|
} // UlAccessCheck
|
|
|
|
|
|
NTSTATUS
|
|
UlSetSecurityDispatch(
|
|
IN PDEVICE_OBJECT pDeviceObject,
|
|
IN PIRP pIrp
|
|
)
|
|
{
|
|
NTSTATUS status;
|
|
PIO_STACK_LOCATION pIrpSp;
|
|
PFILE_OBJECT pFileObject;
|
|
PUL_APP_POOL_PROCESS pProcess;
|
|
|
|
UNREFERENCED_PARAMETER(pDeviceObject);
|
|
|
|
PAGED_CODE();
|
|
|
|
UL_ENTER_DRIVER( "UlSetSecurityDispatch", pIrp );
|
|
|
|
pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
|
|
pFileObject = pIrpSp->FileObject;
|
|
|
|
//
|
|
// We only allow changing the security descriptor on app
|
|
// pool handles.
|
|
//
|
|
if (!IS_APP_POOL_FO(pFileObject))
|
|
{
|
|
status = STATUS_INVALID_PARAMETER;
|
|
goto complete;
|
|
}
|
|
|
|
pProcess = GET_APP_POOL_PROCESS(pFileObject);
|
|
|
|
status = UlSetSecurity(
|
|
&pProcess->pAppPool->pSecurityDescriptor,
|
|
&pIrpSp->Parameters.SetSecurity.SecurityInformation,
|
|
pIrpSp->Parameters.SetSecurity.SecurityDescriptor
|
|
);
|
|
|
|
complete:
|
|
|
|
pIrp->IoStatus.Status = status;
|
|
|
|
UlCompleteRequest(pIrp, IO_NO_INCREMENT);
|
|
|
|
UL_LEAVE_DRIVER( "UlSetSecurityDispatch" );
|
|
RETURN(status);
|
|
|
|
} // UlSetSecurityDispatch
|
|
|
|
|
|
NTSTATUS
|
|
UlQuerySecurityDispatch(
|
|
IN PDEVICE_OBJECT pDeviceObject,
|
|
IN PIRP pIrp
|
|
)
|
|
{
|
|
NTSTATUS status;
|
|
PIO_STACK_LOCATION pIrpSp;
|
|
PFILE_OBJECT pFileObject;
|
|
PUL_APP_POOL_PROCESS pProcess;
|
|
|
|
UNREFERENCED_PARAMETER(pDeviceObject);
|
|
|
|
PAGED_CODE();
|
|
|
|
UL_ENTER_DRIVER( "UlQuerySecurityDispatch", pIrp );
|
|
|
|
pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
|
|
pFileObject = pIrpSp->FileObject;
|
|
|
|
//
|
|
// We only allow querying the security descriptor on app
|
|
// pool handles.
|
|
//
|
|
if (!IS_APP_POOL_FO(pFileObject))
|
|
{
|
|
status = STATUS_INVALID_PARAMETER;
|
|
goto complete;
|
|
}
|
|
|
|
pProcess = GET_APP_POOL_PROCESS(pFileObject);
|
|
|
|
status = UlQuerySecurity(
|
|
&pIrpSp->Parameters.QuerySecurity.SecurityInformation,
|
|
pIrp->UserBuffer,
|
|
&pIrpSp->Parameters.QuerySecurity.Length,
|
|
&pProcess->pAppPool->pSecurityDescriptor
|
|
);
|
|
|
|
if (pIrp->UserIosb)
|
|
{
|
|
pIrp->UserIosb->Information = pIrpSp->Parameters.QuerySecurity.Length;
|
|
}
|
|
|
|
complete:
|
|
|
|
pIrp->IoStatus.Status = status;
|
|
|
|
UlCompleteRequest(pIrp, IO_NO_INCREMENT);
|
|
|
|
UL_LEAVE_DRIVER( "UlQuerySecurityDispatch" );
|
|
RETURN(status);
|
|
|
|
} // UlQuerySecurityDispatch
|
|
|
|
|
|
/***************************************************************************++
|
|
|
|
Routine Description:
|
|
|
|
Determines if this is a thread with Admin/LocalSystem privileges.
|
|
|
|
Arguments:
|
|
|
|
DesiredAccess - Supplies an access mask describing the user's
|
|
desired access to the resource. This mask is assumed to not
|
|
contain generic access types.
|
|
|
|
RequestorMode - Supplies the processor mode by which the access is
|
|
being requested.
|
|
|
|
pObjectName - Supplies the name of the object being referenced.
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS - Completion status.
|
|
|
|
--***************************************************************************/
|
|
NTSTATUS
|
|
UlThreadAdminCheck(
|
|
IN ACCESS_MASK DesiredAccess,
|
|
IN KPROCESSOR_MODE RequestorMode,
|
|
IN PCWSTR pObjectName
|
|
)
|
|
{
|
|
ACCESS_STATE AccessState;
|
|
AUX_ACCESS_DATA AuxData;
|
|
NTSTATUS Status;
|
|
|
|
Status = SeCreateAccessState(
|
|
&AccessState,
|
|
&AuxData,
|
|
DesiredAccess,
|
|
NULL
|
|
);
|
|
|
|
if(NT_SUCCESS(Status))
|
|
{
|
|
Status = UlAccessCheck(
|
|
g_pAdminAllSystemAll,
|
|
&AccessState,
|
|
DesiredAccess,
|
|
RequestorMode,
|
|
pObjectName
|
|
);
|
|
|
|
SeDeleteAccessState(&AccessState);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
/***************************************************************************++
|
|
|
|
Routine Description:
|
|
|
|
Allocates and initializes a security descriptor with the specified
|
|
attributes.
|
|
|
|
Arguments:
|
|
|
|
pSecurityDescriptor - Supplies a pointer to the security descriptor
|
|
to initialize.
|
|
|
|
pSidMaskPairs - Supplies an array of SID/ACCESS_MASK pairs.
|
|
|
|
NumSidMaskPairs - Supplies the number of SID/ACESS_MASK pairs.
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS - Completion status.
|
|
|
|
--***************************************************************************/
|
|
NTSTATUS
|
|
UlCreateSecurityDescriptor(
|
|
OUT PSECURITY_DESCRIPTOR pSecurityDescriptor,
|
|
IN PSID_MASK_PAIR pSidMaskPairs,
|
|
IN ULONG NumSidMaskPairs
|
|
)
|
|
{
|
|
NTSTATUS status;
|
|
PACL pDacl;
|
|
ULONG daclLength;
|
|
ULONG i;
|
|
|
|
//
|
|
// Sanity check.
|
|
//
|
|
|
|
PAGED_CODE();
|
|
|
|
ASSERT( pSecurityDescriptor != NULL );
|
|
ASSERT( pSidMaskPairs != NULL );
|
|
ASSERT( NumSidMaskPairs > 0 );
|
|
|
|
//
|
|
// Setup locals so we know how to cleanup on exit.
|
|
//
|
|
|
|
pDacl = NULL;
|
|
|
|
//
|
|
// Initialize the security descriptor.
|
|
//
|
|
|
|
status = RtlCreateSecurityDescriptor(
|
|
pSecurityDescriptor, // SecurityDescriptor
|
|
SECURITY_DESCRIPTOR_REVISION // Revision
|
|
);
|
|
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
//
|
|
// Calculate the DACL length.
|
|
//
|
|
|
|
daclLength = sizeof(ACL);
|
|
|
|
for (i = 0 ; i < NumSidMaskPairs ; i++)
|
|
{
|
|
daclLength += sizeof(ACCESS_ALLOWED_ACE);
|
|
daclLength += RtlLengthSid( pSidMaskPairs[i].pSid );
|
|
}
|
|
|
|
//
|
|
// Allocate & initialize the DACL.
|
|
//
|
|
|
|
pDacl = (PACL) UL_ALLOCATE_POOL(
|
|
PagedPool,
|
|
daclLength,
|
|
UL_SECURITY_DATA_POOL_TAG
|
|
);
|
|
|
|
if (pDacl == NULL)
|
|
{
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
goto cleanup;
|
|
}
|
|
|
|
status = RtlCreateAcl(
|
|
pDacl, // Acl
|
|
daclLength, // AclLength
|
|
ACL_REVISION // AclRevision
|
|
);
|
|
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
//
|
|
// Add the necessary access-allowed ACEs to the DACL.
|
|
//
|
|
|
|
for (i = 0 ; i < NumSidMaskPairs ; i++)
|
|
{
|
|
status = RtlAddAccessAllowedAceEx(
|
|
pDacl, // Acl
|
|
ACL_REVISION, // AceRevision
|
|
pSidMaskPairs[i].AceFlags, // Inheritance flags
|
|
pSidMaskPairs[i].AccessMask, // AccessMask
|
|
pSidMaskPairs[i].pSid // Sid
|
|
);
|
|
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Attach the DACL to the security descriptor.
|
|
//
|
|
|
|
status = RtlSetDaclSecurityDescriptor(
|
|
pSecurityDescriptor, // SecurityDescriptor
|
|
TRUE, // DaclPresent
|
|
pDacl, // Dacl
|
|
FALSE // DaclDefaulted
|
|
);
|
|
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
//
|
|
// Success!
|
|
//
|
|
|
|
ASSERT( NT_SUCCESS(status) );
|
|
return STATUS_SUCCESS;
|
|
|
|
cleanup:
|
|
|
|
ASSERT( !NT_SUCCESS(status) );
|
|
|
|
if (pDacl != NULL)
|
|
{
|
|
UL_FREE_POOL(
|
|
pDacl,
|
|
UL_SECURITY_DATA_POOL_TAG
|
|
);
|
|
}
|
|
|
|
return status;
|
|
|
|
} // UlpCreateSecurityDescriptor
|
|
|
|
/***************************************************************************++
|
|
|
|
Routine Description:
|
|
|
|
Frees any resources associated with the security descriptor created
|
|
by UlpCreateSecurityDescriptor().
|
|
|
|
Arguments:
|
|
|
|
pSecurityDescriptor - Supplies the security descriptor to cleanup.
|
|
|
|
--***************************************************************************/
|
|
VOID
|
|
UlCleanupSecurityDescriptor(
|
|
IN PSECURITY_DESCRIPTOR pSecurityDescriptor
|
|
)
|
|
{
|
|
NTSTATUS status;
|
|
PACL pDacl;
|
|
BOOLEAN daclPresent;
|
|
BOOLEAN daclDefaulted;
|
|
|
|
//
|
|
// Sanity check.
|
|
//
|
|
|
|
PAGED_CODE();
|
|
|
|
ASSERT( RtlValidSecurityDescriptor( pSecurityDescriptor ) );
|
|
|
|
//
|
|
// Try to retrieve the DACL from the security descriptor.
|
|
//
|
|
|
|
status = RtlGetDaclSecurityDescriptor(
|
|
pSecurityDescriptor, // SecurityDescriptor
|
|
&daclPresent, // DaclPresent
|
|
&pDacl, // Dacl
|
|
&daclDefaulted // DaclDefaulted
|
|
);
|
|
|
|
if (NT_SUCCESS(status))
|
|
{
|
|
if (daclPresent && (pDacl != NULL))
|
|
{
|
|
UL_FREE_POOL(
|
|
pDacl,
|
|
UL_SECURITY_DATA_POOL_TAG
|
|
);
|
|
}
|
|
}
|
|
|
|
} // UlCleanupSecurityDescriptor
|
|
|
|
|
|
/**************************************************************************++
|
|
|
|
Routine Description:
|
|
|
|
This routine maps the generic access masks of the ACE's present in the
|
|
DACL of the supplied security descriptor.
|
|
|
|
CODEWORK: Get RtlpApplyAclToObject exported.
|
|
|
|
Arguments:
|
|
|
|
pSecurityDescriptor - Supplies security descriptor.
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS.
|
|
|
|
--**************************************************************************/
|
|
NTSTATUS
|
|
UlMapGenericMask(
|
|
PSECURITY_DESCRIPTOR pSecurityDescriptor
|
|
)
|
|
{
|
|
ULONG i;
|
|
PACE_HEADER Ace;
|
|
PACL Dacl;
|
|
NTSTATUS Status;
|
|
BOOLEAN Ignore;
|
|
BOOLEAN DaclPresent = FALSE;
|
|
|
|
//
|
|
// Get the DACL.
|
|
//
|
|
|
|
Status = RtlGetDaclSecurityDescriptor(
|
|
pSecurityDescriptor,
|
|
&DaclPresent,
|
|
&Dacl,
|
|
&Ignore
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
return Status;
|
|
}
|
|
|
|
if (DaclPresent)
|
|
{
|
|
//
|
|
// RtlpApplyAclToObject(Acl, GenericMapping) is cloned below since
|
|
// it is not exported.
|
|
//
|
|
|
|
//
|
|
// Now walk the ACL, mapping each ACE as we go.
|
|
//
|
|
|
|
for (i = 0, Ace = FirstAce(Dacl);
|
|
i < Dacl->AceCount;
|
|
i += 1, Ace = NextAce(Ace))
|
|
{
|
|
if (IsMSAceType(Ace))
|
|
{
|
|
RtlApplyAceToObject(Ace, &g_UrlAccessGenericMapping);
|
|
}
|
|
}
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
//
|
|
// Private functions.
|
|
//
|