Leaked source code of windows server 2003
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.
 
 
 
 
 
 

1014 lines
30 KiB

#include "precomp.h"
typedef ULONG SECURITY_INFORMATION;
NTSTATUS
AddNetConfigOpsAce(IN PACL Dacl,
OUT PACL * DeviceAcl
)
/*++
Routine Description:
This routine builds an ACL which adds the Network Configuration Operators group
to the principals allowed to control the driver.
Arguments:
Dacl - Existing DACL.
DeviceAcl - Output pointer to the new ACL.
Return Value:
STATUS_SUCCESS or an appropriate error code.
--*/
{
PGENERIC_MAPPING GenericMapping;
PSID NetConfigOpsSid = NULL;
ULONG AclLength;
NTSTATUS Status;
ACCESS_MASK AccessMask = GENERIC_ALL;
PACL NewAcl = NULL;
ULONG SidSize;
SID_IDENTIFIER_AUTHORITY sidAuth = SECURITY_NT_AUTHORITY;
PISID ISid;
PACCESS_ALLOWED_ACE AceTemp;
int i;
//
// Enable access to all the globally defined SIDs
//
GenericMapping = IoGetFileObjectGenericMapping();
RtlMapGenericMask(&AccessMask, GenericMapping);
SidSize = RtlLengthRequiredSid(2);
NetConfigOpsSid = (PSID)(ExAllocatePoolWithTag(PagedPool,SidSize, NDIS_TAG_NET_CFG_OPS_ID));
if (NULL == NetConfigOpsSid) {
return STATUS_INSUFFICIENT_RESOURCES;
}
Status = RtlInitializeSid(NetConfigOpsSid, &sidAuth, 2);
if (Status != STATUS_SUCCESS) {
goto clean_up;
}
ISid = (PISID)(NetConfigOpsSid);
ISid->SubAuthority[0] = SECURITY_BUILTIN_DOMAIN_RID;
ISid->SubAuthority[1] = DOMAIN_ALIAS_RID_NETWORK_CONFIGURATION_OPS;
AclLength = Dacl->AclSize;
AclLength += sizeof(ACL) + FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart);
AclLength += RtlLengthSid(NetConfigOpsSid);
NewAcl = ExAllocatePoolWithTag(
PagedPool,
AclLength,
NDIS_TAG_NET_CFG_OPS_ACL
);
if (NewAcl == NULL) {
Status = STATUS_INSUFFICIENT_RESOURCES;
goto clean_up;
}
Status = RtlCreateAcl(NewAcl, AclLength, ACL_REVISION2);
if (!NT_SUCCESS(Status)) {
goto clean_up;
}
for (i = 0; i < Dacl->AceCount; i++) {
Status = RtlGetAce(Dacl, i, &AceTemp);
if (NT_SUCCESS(Status)) {
Status = RtlAddAccessAllowedAce(NewAcl,
ACL_REVISION2,
AceTemp->Mask,
&AceTemp->SidStart);
}
if (!NT_SUCCESS(Status)) {
goto clean_up;
}
}
// Add Net Config Operators Ace
Status = RtlAddAccessAllowedAce(NewAcl,
ACL_REVISION2,
AccessMask,
NetConfigOpsSid);
if (!NT_SUCCESS(Status)) {
goto clean_up;
}
*DeviceAcl = NewAcl;
clean_up:
if (NetConfigOpsSid) {
ExFreePool(NetConfigOpsSid);
}
if (!NT_SUCCESS(Status) && NewAcl) {
ExFreePool(NewAcl);
}
return (Status);
}
NTSTATUS
CreateDeviceDriverSecurityDescriptor(
IN PVOID DeviceOrDriverObject,
IN BOOLEAN AddNetConfigOps,
IN PACL AclToAdd OPTIONAL
)
/*++
Routine Description:
Creates the SD responsible for giving access to different users.
Arguments:
None.
Return Value:
STATUS_SUCCESS or an appropriate error code.
--*/
{
NTSTATUS status;
BOOLEAN memoryAllocated = FALSE;
PSECURITY_DESCRIPTOR sdSecurityDescriptor = NULL;
PACL paclDacl = NULL;
BOOLEAN bHasDacl;
BOOLEAN bDaclDefaulted;
PACL NewAcl = NULL;
//
// Get a pointer to the security descriptor from the driver/device object.
//
status = ObGetObjectSecurity(
DeviceOrDriverObject,
&sdSecurityDescriptor,
&memoryAllocated
);
if (!NT_SUCCESS(status))
{
KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,
"TCP: Unable to get security descriptor, error: %x\n",
status
));
ASSERT(memoryAllocated == FALSE);
return (status);
}
status = RtlGetDaclSecurityDescriptor(sdSecurityDescriptor,
&bHasDacl,
&paclDacl,
&bDaclDefaulted);
if (NT_SUCCESS(status))
{
if (bHasDacl)
{
if (AddNetConfigOps && paclDacl)
{
status = AddNetConfigOpsAce(paclDacl, &NewAcl);
}
else if (AclToAdd)
{
NewAcl = AclToAdd;
}
else
{
return STATUS_UNSUCCESSFUL;
}
ASSERT(NT_SUCCESS(status));
if (NT_SUCCESS(status))
{
PSECURITY_DESCRIPTOR sdSecDesc = NULL;
ULONG ulSecDescSize = 0;
PACL daclAbs = NULL;
ULONG ulDacl = 0;
PACL saclAbs = NULL;
ULONG ulSacl = 0;
PSID Owner = NULL;
ULONG ulOwnerSize = 0;
PSID PrimaryGroup = NULL;
ULONG ulPrimaryGroupSize = 0;
BOOLEAN bOwnerDefault;
BOOLEAN bGroupDefault;
BOOLEAN HasSacl = FALSE;
BOOLEAN SaclDefaulted = FALSE;
SECURITY_INFORMATION secInfo = OWNER_SECURITY_INFORMATION |
GROUP_SECURITY_INFORMATION |
DACL_SECURITY_INFORMATION;
ulSecDescSize = sizeof(SECURITY_DESCRIPTOR) + NewAcl->AclSize;
sdSecDesc = ExAllocatePoolWithTag(PagedPool,
ulSecDescSize,
NDIS_TAG_NET_CFG_SEC_DESC);
if (sdSecDesc)
{
ulDacl = NewAcl->AclSize;
daclAbs = ExAllocatePoolWithTag(PagedPool,
ulDacl,
NDIS_TAG_NET_CFG_DACL);
if (daclAbs)
{
status = RtlGetOwnerSecurityDescriptor(sdSecurityDescriptor,
&Owner,
&bOwnerDefault);
if (NT_SUCCESS(status))
{
ulOwnerSize = RtlLengthSid(Owner);
status = RtlGetGroupSecurityDescriptor(sdSecurityDescriptor,
&PrimaryGroup,
&bGroupDefault);
if (NT_SUCCESS(status))
{
status = RtlGetSaclSecurityDescriptor(sdSecurityDescriptor,
&HasSacl,
&saclAbs,
&SaclDefaulted);
if (NT_SUCCESS(status))
{
if (HasSacl)
{
ulSacl = saclAbs->AclSize;
secInfo |= SACL_SECURITY_INFORMATION;
}
ulPrimaryGroupSize= RtlLengthSid(PrimaryGroup);
status = RtlSelfRelativeToAbsoluteSD(sdSecurityDescriptor,
sdSecDesc,
&ulSecDescSize,
daclAbs,
&ulDacl,
saclAbs,
&ulSacl,
Owner,
&ulOwnerSize,
PrimaryGroup,
&ulPrimaryGroupSize);
if (NT_SUCCESS(status))
{
status = RtlSetDaclSecurityDescriptor(sdSecDesc, TRUE, NewAcl, FALSE);
if (NT_SUCCESS(status))
{
status = ObSetSecurityObjectByPointer(DeviceOrDriverObject, secInfo, sdSecDesc);
}
}
}
}
}
}
if (sdSecDesc)
{
// Since this is a Self-Relative security descriptor, freeing it also frees
// Owner and PrimaryGroup.
ExFreePool(sdSecDesc);
}
if (daclAbs)
{
ExFreePool(daclAbs);
}
}
if ((AclToAdd == NULL) && NewAcl)
{
ExFreePool(NewAcl);
}
}
}
else
{
KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"NDIS: No Dacl: %x\n", status));
}
}
ObReleaseObjectSecurity(
sdSecurityDescriptor,
memoryAllocated
);
return (status);
}
NTSTATUS
ndisBuildDeviceAcl(
OUT PACL *DeviceAcl,
IN BOOLEAN AddNetConfigOps,
IN BOOLEAN AddNetworkService
)
/*++
Routine Description:
This routine builds an ACL which gives Administrators, LocalSystem,
and NetworkService principals full access. All other principals have no access.
Arguments:
DeviceAcl - Output pointer to the new ACL.
Return Value:
STATUS_SUCCESS or an appropriate error code.
--*/
{
NTSTATUS Status;
PGENERIC_MAPPING GenericMapping;
ULONG AclLength;
ACCESS_MASK AccessMask = GENERIC_ALL;
PACL NewAcl;
PSID NetConfigOpsSid = NULL;
ULONG NetConfigOpsSidSize;
SID_IDENTIFIER_AUTHORITY NetConfigOpsSidAuth = SECURITY_NT_AUTHORITY;
PISID ISid;
do
{
//
// Enable access to all the globally defined SIDs
//
GenericMapping = IoGetFileObjectGenericMapping();
RtlMapGenericMask(&AccessMask, GenericMapping );
AclLength = sizeof(ACL) +
FIELD_OFFSET (ACCESS_ALLOWED_ACE, SidStart) +
RtlLengthSid(SeExports->SeAliasAdminsSid);
if (AddNetworkService)
{
AclLength += sizeof(ACL) +
FIELD_OFFSET (ACCESS_ALLOWED_ACE, SidStart) +
RtlLengthSid(SeExports->SeNetworkServiceSid);
}
if (AddNetConfigOps)
{
NetConfigOpsSidSize = RtlLengthRequiredSid(2);
NetConfigOpsSid = (PSID)ALLOC_FROM_POOL(NetConfigOpsSidSize, NDIS_TAG_NET_CFG_OPS_ID);
if (NULL == NetConfigOpsSid)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
Status = RtlInitializeSid(NetConfigOpsSid, &NetConfigOpsSidAuth, 2);
if (Status != STATUS_SUCCESS)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
ISid = (PISID)(NetConfigOpsSid);
ISid->SubAuthority[0] = SECURITY_BUILTIN_DOMAIN_RID;
ISid->SubAuthority[1] = DOMAIN_ALIAS_RID_NETWORK_CONFIGURATION_OPS;
AclLength += RtlLengthSid(NetConfigOpsSid) + FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart);
}
NewAcl = ALLOC_FROM_POOL(AclLength, NDIS_TAG_SECURITY);
if (NewAcl == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
ZeroMemory(NewAcl, AclLength);
Status = RtlCreateAcl(NewAcl, AclLength, ACL_REVISION );
if (!NT_SUCCESS(Status))
{
FREE_POOL(NewAcl);
break;
}
Status = RtlAddAccessAllowedAce (
NewAcl,
ACL_REVISION2,
AccessMask,
SeExports->SeAliasAdminsSid
);
ASSERT(NT_SUCCESS(Status));
if (AddNetworkService)
{
Status = RtlAddAccessAllowedAce(
NewAcl,
ACL_REVISION2,
AccessMask,
SeExports->SeNetworkServiceSid
);
ASSERT(NT_SUCCESS(Status));
}
if (AddNetConfigOps)
{
// Add Net Config Operators Ace
Status = RtlAddAccessAllowedAce(NewAcl,
ACL_REVISION2,
AccessMask,
NetConfigOpsSid);
ASSERT(NT_SUCCESS(Status));
}
*DeviceAcl = NewAcl;
Status = STATUS_SUCCESS;
}while (FALSE);
if (NetConfigOpsSid)
{
ExFreePool(NetConfigOpsSid);
}
return(Status);
}
NTSTATUS
ndisCreateSecurityDescriptor(
IN PDEVICE_OBJECT DeviceObject,
OUT PSECURITY_DESCRIPTOR * pSecurityDescriptor,
IN BOOLEAN AddNetConfigOps,
IN BOOLEAN AddNetworkService
)
/*++
Routine Description:
This routine creates a security descriptor which gives access
only to certain priviliged accounts. This descriptor is used
to access check processes that open a handle to miniport device
objects.
Arguments:
None.
Return Value:
STATUS_SUCCESS or an appropriate error code.
--*/
{
PACL devAcl = NULL;
NTSTATUS Status;
BOOLEAN memoryAllocated = FALSE;
PSECURITY_DESCRIPTOR CurSecurityDescriptor;
PSECURITY_DESCRIPTOR NewSecurityDescriptor;
ULONG CurSecurityDescriptorLength;
CHAR buffer[SECURITY_DESCRIPTOR_MIN_LENGTH];
PSECURITY_DESCRIPTOR localSecurityDescriptor =
(PSECURITY_DESCRIPTOR)buffer;
SECURITY_INFORMATION securityInformation = DACL_SECURITY_INFORMATION;
BOOLEAN bReleaseObjectSecurity = FALSE;
do
{
*pSecurityDescriptor = NULL;
//
// Get a pointer to the security descriptor from the device object.
//
Status = ObGetObjectSecurity(
DeviceObject,
&CurSecurityDescriptor,
&memoryAllocated
);
if (!NT_SUCCESS(Status))
{
ASSERT(memoryAllocated == FALSE);
break;
}
bReleaseObjectSecurity = TRUE;
//
// Build a local security descriptor with an ACL giving only
// certain priviliged accounts.
//
Status = ndisBuildDeviceAcl(&devAcl, AddNetConfigOps, AddNetworkService);
if (!NT_SUCCESS(Status))
{
break;
}
//1 why (VOID)?
(VOID)RtlCreateSecurityDescriptor(
localSecurityDescriptor,
SECURITY_DESCRIPTOR_REVISION
);
(VOID)RtlSetDaclSecurityDescriptor(
localSecurityDescriptor,
TRUE,
devAcl,
FALSE
);
//
// Make a copy of the security descriptor. This copy will be the raw descriptor.
//
CurSecurityDescriptorLength = RtlLengthSecurityDescriptor(
CurSecurityDescriptor
);
NewSecurityDescriptor = ALLOC_FROM_POOL(CurSecurityDescriptorLength, NDIS_TAG_SECURITY);
if (NewSecurityDescriptor == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
RtlMoveMemory(
NewSecurityDescriptor,
CurSecurityDescriptor,
CurSecurityDescriptorLength
);
*pSecurityDescriptor = NewSecurityDescriptor;
//
// Now apply the local descriptor to the raw descriptor.
//
Status = SeSetSecurityDescriptorInfo(
NULL,
&securityInformation,
localSecurityDescriptor,
pSecurityDescriptor,
NonPagedPool,
IoGetFileObjectGenericMapping()
);
if (!NT_SUCCESS(Status))
{
ASSERT(*pSecurityDescriptor == NewSecurityDescriptor);
FREE_POOL(*pSecurityDescriptor);
*pSecurityDescriptor = NULL;
break;
}
if (*pSecurityDescriptor != NewSecurityDescriptor)
{
ExFreePool(NewSecurityDescriptor);
}
Status = STATUS_SUCCESS;
}while (FALSE);
if (bReleaseObjectSecurity)
{
ObReleaseObjectSecurity(
CurSecurityDescriptor,
memoryAllocated
);
}
if (devAcl!=NULL)
{
FREE_POOL(devAcl);
}
return(Status);
}
BOOLEAN
ndisCheckAccess (
PIRP Irp,
PIO_STACK_LOCATION IrpSp,
PNTSTATUS Status,
PSECURITY_DESCRIPTOR SecurityDescriptor
)
/*++
Routine Description:
Compares security context of the endpoint creator to that
of the administrator and local system.
Arguments:
Irp - Pointer to I/O request packet.
IrpSp - pointer to the IO stack location to use for this request.
Status - returns status generated by access check on failure.
Return Value:
TRUE - the creator has admin or local system privilige
FALSE - the creator is just a plain user
--*/
{
BOOLEAN accessGranted;
PACCESS_STATE accessState;
PIO_SECURITY_CONTEXT securityContext;
PPRIVILEGE_SET privileges = NULL;
ACCESS_MASK grantedAccess;
PGENERIC_MAPPING GenericMapping;
ACCESS_MASK AccessMask = GENERIC_ALL;
//
// Enable access to all the globally defined SIDs
//
GenericMapping = IoGetFileObjectGenericMapping();
RtlMapGenericMask( &AccessMask, GenericMapping );
securityContext = IrpSp->Parameters.Create.SecurityContext;
accessState = securityContext->AccessState;
SeLockSubjectContext(&accessState->SubjectSecurityContext);
accessGranted = SeAccessCheck(
SecurityDescriptor,
&accessState->SubjectSecurityContext,
TRUE,
AccessMask,
0,
&privileges,
IoGetFileObjectGenericMapping(),
(KPROCESSOR_MODE)((IrpSp->Flags & SL_FORCE_ACCESS_CHECK)
? UserMode
: Irp->RequestorMode),
&grantedAccess,
Status
);
if (privileges) {
(VOID) SeAppendPrivileges(
accessState,
privileges
);
SeFreePrivileges(privileges);
}
if (accessGranted) {
accessState->PreviouslyGrantedAccess |= grantedAccess;
accessState->RemainingDesiredAccess &= ~( grantedAccess | MAXIMUM_ALLOWED );
ASSERT (NT_SUCCESS (*Status));
}
else {
ASSERT (!NT_SUCCESS (*Status));
}
SeUnlockSubjectContext(&accessState->SubjectSecurityContext);
return accessGranted;
}
NTSTATUS
ndisCreateGenericSD(
PACL Acl,
PCHAR AccessSecurityDescriptor
)
/*++
Routine Description:
Creates the SD responsible for giving access to different users.
Arguments:
None.
Return Value:
STATUS_SUCCESS or an appropriate error code.
--*/
{
PSECURITY_DESCRIPTOR AccessSd;
NTSTATUS Status;
if (Acl == NULL)
return STATUS_UNSUCCESSFUL;
do
{
AccessSd = AccessSecurityDescriptor;
Status = RtlCreateSecurityDescriptor(
AccessSd,
SECURITY_DESCRIPTOR_REVISION1
);
if (!NT_SUCCESS(Status))
{
DbgPrint("RtlCreateSecurityDescriptor failed, Status %lx.\n", Status);
break;
}
Status = RtlSetDaclSecurityDescriptor(
AccessSd,
TRUE, // DaclPresent
Acl,
FALSE // DaclDefaulted
);
if (!NT_SUCCESS(Status))
{
DbgPrint("RtlSetDaclSecurityDescriptor failed, Status %lx.\n", Status);
break;
}
Status = RtlSetOwnerSecurityDescriptor(AccessSd,
SeExports->SeAliasAdminsSid,
FALSE);
if (!NT_SUCCESS(Status))
{
DbgPrint("RtlSetOwnerSecurityDescriptor failed, Status %lx.\n", Status);
break;
}
Status = RtlSetGroupSecurityDescriptor(AccessSd,
SeExports->SeAliasAdminsSid,
FALSE);
if (!NT_SUCCESS(Status))
{
DbgPrint("RtlSetGroupSecurityDescriptor failed, Status %lx.\n", Status);
break;
}
}while (FALSE);
return (Status);
}
PACL
ndisCreateAcl(
BOOLEAN Admins,
BOOLEAN LocalSystem,
BOOLEAN LocalService,
BOOLEAN NetworkService,
BOOLEAN NetConfigOps,
BOOLEAN Users,
ACCESS_MASK AccessMask
)
{
PACL AccessDacl = NULL, pAcl = NULL;
ULONG AclLength = 0;
PSID NetConfigOpsSid = NULL;
ULONG NetConfigOpsSidSize;
SID_IDENTIFIER_AUTHORITY NetConfigOpsSidAuth = SECURITY_NT_AUTHORITY;
PISID ISid;
NTSTATUS Status;
do
{
if (Admins)
{
AclLength += sizeof(ACL) +
FIELD_OFFSET (ACCESS_ALLOWED_ACE, SidStart) +
RtlLengthSid(SeExports->SeAliasAdminsSid);
}
if (LocalSystem)
{
AclLength += sizeof(ACL) +
FIELD_OFFSET (ACCESS_ALLOWED_ACE, SidStart) +
RtlLengthSid(SeExports->SeLocalSystemSid);
}
if (LocalService)
{
AclLength += sizeof(ACL) +
FIELD_OFFSET (ACCESS_ALLOWED_ACE, SidStart) +
RtlLengthSid(SeExports->SeLocalServiceSid);
}
if (NetworkService)
{
AclLength += sizeof(ACL) +
FIELD_OFFSET (ACCESS_ALLOWED_ACE, SidStart) +
RtlLengthSid(SeExports->SeNetworkServiceSid);
}
if (NetConfigOps)
{
NetConfigOpsSidSize = RtlLengthRequiredSid(2);
NetConfigOpsSid = (PSID)ALLOC_FROM_POOL(NetConfigOpsSidSize, NDIS_TAG_NET_CFG_OPS_ID);
if (NULL == NetConfigOpsSid)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
Status = RtlInitializeSid(NetConfigOpsSid, &NetConfigOpsSidAuth, 2);
if (Status != STATUS_SUCCESS)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
ISid = (PISID)(NetConfigOpsSid);
ISid->SubAuthority[0] = SECURITY_BUILTIN_DOMAIN_RID;
ISid->SubAuthority[1] = DOMAIN_ALIAS_RID_NETWORK_CONFIGURATION_OPS;
AclLength += sizeof(ACL) +
FIELD_OFFSET (ACCESS_ALLOWED_ACE, SidStart) +
RtlLengthSid(NetConfigOpsSid);
}
if (Users)
{
AclLength += sizeof(ACL) +
FIELD_OFFSET (ACCESS_ALLOWED_ACE, SidStart) +
RtlLengthSid(SeExports->SeAliasUsersSid);
}
AccessDacl = (PACL)ExAllocatePoolWithTag(PagedPool,
AclLength,
NDIS_TAG_SECURITY);
if (AccessDacl == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
Status = RtlCreateAcl(AccessDacl,
AclLength,
ACL_REVISION2);
if (!NT_SUCCESS(Status))
{
DbgPrint("RtlCreateAcl failed, Status %lx.\n", Status);
break;
}
if (Admins)
{
Status = RtlAddAccessAllowedAce(
AccessDacl,
ACL_REVISION2,
(STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL),
SeExports->SeAliasAdminsSid
);
if (!NT_SUCCESS(Status))
{
DbgPrint("RtlAddAccessAllowedAce failed, Status %lx.\n", Status);
break;
}
}
if (LocalSystem)
{
Status = RtlAddAccessAllowedAce(
AccessDacl,
ACL_REVISION2,
(STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL),
SeExports->SeLocalSystemSid
);
if (!NT_SUCCESS(Status))
{
DbgPrint("RtlAddAccessAllowedAce failed, Status %lx.\n", Status);
break;
}
}
if (LocalService)
{
Status = RtlAddAccessAllowedAce(
AccessDacl,
ACL_REVISION2,
(STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL),
SeExports->SeLocalServiceSid
);
if (!NT_SUCCESS(Status))
{
DbgPrint("RtlAddAccessAllowedAce failed, Status %lx.\n", Status);
break;
}
}
if (NetworkService)
{
Status = RtlAddAccessAllowedAce(
AccessDacl,
ACL_REVISION2,
(STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL),
SeExports->SeNetworkServiceSid
);
if (!NT_SUCCESS(Status))
{
DbgPrint("RtlAddAccessAllowedAce failed, Status %lx.\n", Status);
break;
}
}
if (NetConfigOps)
{
Status = RtlAddAccessAllowedAce(
AccessDacl,
ACL_REVISION2,
(STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL),
NetConfigOpsSid
);
if (!NT_SUCCESS(Status))
{
DbgPrint("RtlAddAccessAllowedAce failed, Status %lx.\n", Status);
break;
}
}
if (Users)
{
Status = RtlAddAccessAllowedAce(
AccessDacl,
ACL_REVISION2,
AccessMask,
SeExports->SeAliasUsersSid
);
if (!NT_SUCCESS(Status))
{
DbgPrint("RtlAddAccessAllowedAce failed, Status %lx.\n", Status);
break;
}
}
pAcl = AccessDacl;
}while (FALSE);
if (pAcl == NULL)
{
if (AccessDacl)
FREE_POOL(AccessDacl);
}
return pAcl;
}