BOOLEAN FatCheckManageVolumeAccess ( _In_ PIRP_CONTEXT IrpContext, _In_ PACCESS_STATE AccessState, _In_ KPROCESSOR_MODE ProcessorMode ) /*++ Routine Description: This function checks whether the SID described in the input access state has manage volume privilege. Arguments: AccessState - the access state describing the security context to be checked ProcessorMode - the mode this check should occur against Return Value: BOOLEAN - TRUE if privilege is held and FALSE otherwise --*/ { PRIVILEGE_SET PrivilegeSet; PAGED_CODE(); PrivilegeSet.PrivilegeCount = 1; PrivilegeSet.Control = PRIVILEGE_SET_ALL_NECESSARY; PrivilegeSet.Privilege[0].Luid = RtlConvertLongToLuid( SE_MANAGE_VOLUME_PRIVILEGE ); PrivilegeSet.Privilege[0].Attributes = 0; if (SePrivilegeCheck( &PrivilegeSet, &AccessState->SubjectSecurityContext, ProcessorMode )) { return TRUE; } UNREFERENCED_PARAMETER( IrpContext ); return FALSE; }
NTSTATUS KphDispatchCreate( __in PDEVICE_OBJECT DeviceObject, __in PIRP Irp ) { NTSTATUS status = STATUS_SUCCESS; PIO_STACK_LOCATION stackLocation; PIO_SECURITY_CONTEXT securityContext; stackLocation = IoGetCurrentIrpStackLocation(Irp); securityContext = stackLocation->Parameters.Create.SecurityContext; dprintf("Client (PID %Iu) is connecting\n", PsGetCurrentProcessId()); if (KphParameters.SecurityLevel == KphSecurityPrivilegeCheck) { UCHAR requiredPrivilegesBuffer[FIELD_OFFSET(PRIVILEGE_SET, Privilege) + sizeof(LUID_AND_ATTRIBUTES)]; PPRIVILEGE_SET requiredPrivileges; // Check for SeDebugPrivilege. requiredPrivileges = (PPRIVILEGE_SET)requiredPrivilegesBuffer; requiredPrivileges->PrivilegeCount = 1; requiredPrivileges->Control = PRIVILEGE_SET_ALL_NECESSARY; requiredPrivileges->Privilege[0].Luid.LowPart = SE_DEBUG_PRIVILEGE; requiredPrivileges->Privilege[0].Luid.HighPart = 0; requiredPrivileges->Privilege[0].Attributes = 0; if (!SePrivilegeCheck( requiredPrivileges, &securityContext->AccessState->SubjectSecurityContext, Irp->RequestorMode )) { status = STATUS_PRIVILEGE_NOT_HELD; dprintf("Client (PID %Iu) was rejected\n", PsGetCurrentProcessId()); } } Irp->IoStatus.Status = status; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); return status; }
BOOLEAN SeSinglePrivilegeCheck( __in LUID PrivilegeValue, __in KPROCESSOR_MODE PreviousMode ) /*++ Routine Description: This function will check for the passed privilege value in the current context. Arguments: PrivilegeValue - The value of the privilege being checked. Return Value: TRUE - The current subject has the desired privilege. FALSE - The current subject does not have the desired privilege. --*/ { BOOLEAN AccessGranted; PRIVILEGE_SET RequiredPrivileges; SECURITY_SUBJECT_CONTEXT SubjectSecurityContext; PAGED_CODE(); // // Make sure the caller has the privilege to make this // call. // RequiredPrivileges.PrivilegeCount = 1; RequiredPrivileges.Control = PRIVILEGE_SET_ALL_NECESSARY; RequiredPrivileges.Privilege[0].Luid = PrivilegeValue; RequiredPrivileges.Privilege[0].Attributes = 0; SeCaptureSubjectContext( &SubjectSecurityContext ); AccessGranted = SePrivilegeCheck( &RequiredPrivileges, &SubjectSecurityContext, PreviousMode ); if ( PreviousMode != KernelMode ) { SePrivilegedServiceAuditAlarm ( NULL, &SubjectSecurityContext, &RequiredPrivileges, AccessGranted ); } SeReleaseSubjectContext( &SubjectSecurityContext ); return( AccessGranted ); }
BOOLEAN SeCheckPrivilegedObject( __in LUID PrivilegeValue, __in HANDLE ObjectHandle, __in ACCESS_MASK DesiredAccess, __in KPROCESSOR_MODE PreviousMode ) /*++ Routine Description: This function will check for the passed privilege value in the current context, and generate audits as appropriate. Arguments: PrivilegeValue - The value of the privilege being checked. Object - Specifies a pointer to the object being accessed. ObjectHandle - Specifies the object handle being used. DesiredAccess - The desired access mask, if any PreviousMode - The previous processor mode Return Value: TRUE - The current subject has the desired privilege. FALSE - The current subject does not have the desired privilege. --*/ { BOOLEAN AccessGranted; PRIVILEGE_SET RequiredPrivileges; SECURITY_SUBJECT_CONTEXT SubjectSecurityContext; PAGED_CODE(); // // Make sure the caller has the privilege to make this // call. // RequiredPrivileges.PrivilegeCount = 1; RequiredPrivileges.Control = PRIVILEGE_SET_ALL_NECESSARY; RequiredPrivileges.Privilege[0].Luid = PrivilegeValue; RequiredPrivileges.Privilege[0].Attributes = 0; SeCaptureSubjectContext( &SubjectSecurityContext ); AccessGranted = SePrivilegeCheck( &RequiredPrivileges, &SubjectSecurityContext, PreviousMode ); if ( PreviousMode != KernelMode ) { SePrivilegeObjectAuditAlarm( ObjectHandle, &SubjectSecurityContext, DesiredAccess, &RequiredPrivileges, AccessGranted, PreviousMode ); } SeReleaseSubjectContext( &SubjectSecurityContext ); return( AccessGranted ); }
NTSTATUS FatExplicitDeviceAccessGranted ( IN PIRP_CONTEXT IrpContext, IN PDEVICE_OBJECT DeviceObject, IN PACCESS_STATE AccessState, IN KPROCESSOR_MODE ProcessorMode ) /*++ Routine Description: This function asks whether the SID described in the input access state has been granted any explicit access to the given device object. It does this by acquiring a token stripped of its ability to acquire access via the Everyone SID and re-doing the access check. Arguments: DeviceObject - the device whose ACL will be checked AccessState - the access state describing the security context to be checked ProcessorMode - the mode this check should occur against Return Value: NTSTATUS - Indicating whether explicit access was granted. --*/ { NTSTATUS Status; BOOLEAN Result; PACCESS_TOKEN OriginalAccessToken; PACCESS_TOKEN RestrictedAccessToken; PACCESS_TOKEN *EffectiveToken; PRIVILEGE_SET PrivilegeSet; ACCESS_MASK GrantedAccess; // // If the access state indicates that specific access other // than traverse was acquired, either Everyone does have such // access or explicit access was granted. In both cases, we're // happy to let this proceed. // if (AccessState->PreviouslyGrantedAccess & (SPECIFIC_RIGHTS_ALL ^ FILE_TRAVERSE)) { return STATUS_SUCCESS; } // // If the manage volume privilege is held, this also permits access. // PrivilegeSet.PrivilegeCount = 1; PrivilegeSet.Control = PRIVILEGE_SET_ALL_NECESSARY; PrivilegeSet.Privilege[0].Luid = RtlConvertLongToLuid( SE_MANAGE_VOLUME_PRIVILEGE ); PrivilegeSet.Privilege[0].Attributes = 0; if (SePrivilegeCheck( &PrivilegeSet, &AccessState->SubjectSecurityContext, ProcessorMode )) { return STATUS_SUCCESS; } // // Capture the subject context as a prelude to everything below. // SeLockSubjectContext( &AccessState->SubjectSecurityContext ); // // Convert the token in the subject context into one which does not // acquire access through the Everyone SID. // // The logic for deciding which token is effective comes from // SeQuerySubjectContextToken; since there is no natural way // of getting a pointer to it, do it by hand. // if (ARGUMENT_PRESENT( AccessState->SubjectSecurityContext.ClientToken )) { EffectiveToken = &AccessState->SubjectSecurityContext.ClientToken; } else { EffectiveToken = &AccessState->SubjectSecurityContext.PrimaryToken; } OriginalAccessToken = *EffectiveToken; Status = FatCreateRestrictEveryoneToken( OriginalAccessToken, &RestrictedAccessToken ); if (!NT_SUCCESS(Status)) { SeReleaseSubjectContext( &AccessState->SubjectSecurityContext ); return Status; } // // Now see if the resulting context has access to the device through // its explicitly granted access. We swap in our restricted token // for this check as the effective client token. // *EffectiveToken = RestrictedAccessToken; Result = SeAccessCheck( DeviceObject->SecurityDescriptor, &AccessState->SubjectSecurityContext, FALSE, AccessState->OriginalDesiredAccess, 0, NULL, IoGetFileObjectGenericMapping(), ProcessorMode, &GrantedAccess, &Status ); *EffectiveToken = OriginalAccessToken; // // Cleanup and return. // SeUnlockSubjectContext( &AccessState->SubjectSecurityContext ); ObDereferenceObject( RestrictedAccessToken ); return Status; }