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