NTSTATUS FspFsvolSetSecurityPrepare( PIRP Irp, FSP_FSCTL_TRANSACT_REQ *Request) { PAGED_CODE(); NTSTATUS Result; SECURITY_SUBJECT_CONTEXT SecuritySubjectContext; SECURITY_QUALITY_OF_SERVICE SecurityQualityOfService; SECURITY_CLIENT_CONTEXT SecurityClientContext; HANDLE UserModeAccessToken; PEPROCESS Process; /* duplicate the subject context access token into an impersonation token */ SecurityQualityOfService.Length = sizeof SecurityQualityOfService; SecurityQualityOfService.ImpersonationLevel = SecurityIdentification; SecurityQualityOfService.ContextTrackingMode = SECURITY_STATIC_TRACKING; SecurityQualityOfService.EffectiveOnly = FALSE; SeCaptureSubjectContext(&SecuritySubjectContext); SeLockSubjectContext(&SecuritySubjectContext); Result = SeCreateClientSecurityFromSubjectContext(&SecuritySubjectContext, &SecurityQualityOfService, FALSE, &SecurityClientContext); SeUnlockSubjectContext(&SecuritySubjectContext); SeReleaseSubjectContext(&SecuritySubjectContext); if (!NT_SUCCESS(Result)) return Result; ASSERT(TokenImpersonation == SeTokenType(SecurityClientContext.ClientToken)); /* get a user-mode handle to the impersonation token */ Result = ObOpenObjectByPointer(SecurityClientContext.ClientToken, 0, 0, TOKEN_QUERY, *SeTokenObjectType, UserMode, &UserModeAccessToken); SeDeleteClientSecurity(&SecurityClientContext); if (!NT_SUCCESS(Result)) return Result; /* get a pointer to the current process so that we can close the impersonation token later */ Process = PsGetCurrentProcess(); ObReferenceObject(Process); /* send the user-mode handle to the user-mode file system */ FspIopRequestContext(Request, RequestAccessToken) = UserModeAccessToken; FspIopRequestContext(Request, RequestProcess) = Process; Request->Req.SetSecurity.AccessToken = (UINT_PTR)UserModeAccessToken; return STATUS_SUCCESS; }
//保证每一次操作完成。 PDEVICE_OBJECT FileDiskDeleteDevice ( IN PDEVICE_OBJECT DeviceObject ) { PDEVICE_EXTENSION device_extension; PDEVICE_OBJECT next_device_object; PAGED_CODE(); ASSERT(DeviceObject != NULL); device_extension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension; device_extension->terminate_thread = TRUE; KeSetEvent( &device_extension->request_event, (KPRIORITY) 0, FALSE ); KeWaitForSingleObject( device_extension->thread_pointer, Executive, KernelMode, FALSE, NULL ); ObDereferenceObject(device_extension->thread_pointer); if (device_extension->security_client_context != NULL) { SeDeleteClientSecurity(device_extension->security_client_context); ExFreePool(device_extension->security_client_context); } next_device_object = DeviceObject->NextDevice; IoDeleteDevice(DeviceObject); return next_device_object; }
VOID NTAPI LpcpFreePortClientSecurity(IN PLPCP_PORT_OBJECT Port) { /* Check if this is a client port */ if ((Port->Flags & LPCP_PORT_TYPE_MASK) == LPCP_CLIENT_PORT) { /* Check if security is static */ if (!(Port->Flags & LPCP_SECURITY_DYNAMIC)) { /* Check if we have a token */ if (Port->StaticSecurity.ClientToken) { /* Free security */ SeDeleteClientSecurity(&Port->StaticSecurity); } } } }
NTSTATUS NtImpersonateThread( __in HANDLE ServerThreadHandle, __in HANDLE ClientThreadHandle, __in PSECURITY_QUALITY_OF_SERVICE SecurityQos ) /*++ Routine Description: This routine is used to cause the server thread to impersonate the client thread. The impersonation is done according to the specified quality of service parameters. Arguments: ServerThreadHandle - Is a handle to the server thread (the impersonator, or doing the impersonation). This handle must be open for THREAD_IMPERSONATE access. ClientThreadHandle - Is a handle to the Client thread (the impersonatee, or one being impersonated). This handle must be open for THREAD_DIRECT_IMPERSONATION access. SecurityQos - A pointer to security quality of service information indicating what form of impersonation is to be performed. Return Value: STATUS_SUCCESS - Indicates the call completed successfully. --*/ { KPROCESSOR_MODE PreviousMode; NTSTATUS Status; PETHREAD ClientThread, ServerThread; SECURITY_QUALITY_OF_SERVICE CapturedQos; SECURITY_CLIENT_CONTEXT ClientSecurityContext; // // Get previous processor mode and probe and capture arguments if necessary // PreviousMode = KeGetPreviousMode(); try { if (PreviousMode != KernelMode) { ProbeForReadSmallStructure (SecurityQos, sizeof (SECURITY_QUALITY_OF_SERVICE), sizeof (ULONG)); } CapturedQos = *SecurityQos; } except (ExSystemExceptionFilter ()) { return GetExceptionCode (); } // // Reference the client thread, checking for appropriate access. // Status = ObReferenceObjectByHandle (ClientThreadHandle, // Handle THREAD_DIRECT_IMPERSONATION, // DesiredAccess PsThreadType, // ObjectType PreviousMode, // AccessMode &ClientThread, // Object NULL); // GrantedAccess if (!NT_SUCCESS (Status)) { return Status; } // // Reference the client thread, checking for appropriate access. // Status = ObReferenceObjectByHandle (ServerThreadHandle, // Handle THREAD_IMPERSONATE, // DesiredAccess PsThreadType, // ObjectType PreviousMode, // AccessMode &ServerThread, // Object NULL); // GrantedAccess if (!NT_SUCCESS (Status)) { ObDereferenceObject (ClientThread); return Status; } // // Get the client's security context // Status = SeCreateClientSecurity (ClientThread, // ClientThread &CapturedQos, // SecurityQos FALSE, // ServerIsRemote &ClientSecurityContext); // ClientContext if (!NT_SUCCESS (Status)) { ObDereferenceObject (ServerThread); ObDereferenceObject (ClientThread); return Status; } // // Impersonate the client // Status = SeImpersonateClientEx (&ClientSecurityContext, ServerThread); SeDeleteClientSecurity (&ClientSecurityContext); // // Done. // ObDereferenceObject (ServerThread); ObDereferenceObject (ClientThread); return Status ; }
// // Check IOCTL_VFD_OPEN_IMAGE input parameters // NTSTATUS VfdOpenCheck( PDEVICE_EXTENSION DeviceExtension, PVFD_IMAGE_INFO ImageInfo, ULONG InputLength) { // Check media status if (DeviceExtension->FileHandle || DeviceExtension->FileBuffer) { VFDTRACE(VFDWARN, ("[VFD] image already opened.\n")); return STATUS_DEVICE_BUSY; } // Check input parameter length if (InputLength < sizeof(VFD_IMAGE_INFO) || InputLength < sizeof(VFD_IMAGE_INFO) + ImageInfo->NameLength) { return STATUS_INVALID_PARAMETER; } // Check input parameters if (ImageInfo->MediaType == VFD_MEDIA_NONE || ImageInfo->MediaType >= VFD_MEDIA_MAX) { VFDTRACE(VFDWARN, ("[VFD] invalid MediaType - %u.\n", ImageInfo->MediaType)); return STATUS_INVALID_PARAMETER; } if (ImageInfo->DiskType == VFD_DISKTYPE_FILE && ImageInfo->NameLength == 0) { VFDTRACE(VFDWARN, ("[VFD] File name required for VFD_DISKTYPE_FILE.\n")); return STATUS_INVALID_PARAMETER; } // create a security context to match the calling process' context // the driver thread uses this context to impersonate the client // to open the specified image file // if (ImageInfo->DiskType == VFD_DISKTYPE_FILE) { SECURITY_QUALITY_OF_SERVICE sqos; if (DeviceExtension->SecurityContext != NULL) { SeDeleteClientSecurity(DeviceExtension->SecurityContext); } else { DeviceExtension->SecurityContext = (PSECURITY_CLIENT_CONTEXT)ExAllocatePoolWithTag( NonPagedPool, sizeof(SECURITY_CLIENT_CONTEXT), VFD_POOL_TAG); } RtlZeroMemory(&sqos, sizeof(SECURITY_QUALITY_OF_SERVICE)); sqos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE); sqos.ImpersonationLevel = SecurityImpersonation; sqos.ContextTrackingMode = SECURITY_STATIC_TRACKING; sqos.EffectiveOnly = FALSE; SeCreateClientSecurity( PsGetCurrentThread(), &sqos, FALSE, DeviceExtension->SecurityContext); } return STATUS_SUCCESS; }
NTSTATUS FileDiskDeviceControl ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { PDEVICE_EXTENSION device_extension; PIO_STACK_LOCATION io_stack; NTSTATUS status; // 得到设备扩展 device_extension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension; // 得到当前设备栈 io_stack = IoGetCurrentIrpStackLocation(Irp); // 判断如果是还没有加载物理媒质就返回失败。但是 // IOCTL_FILE_DISK_OPEN_FILE是自定义的功能号,专 // 用来加载物理媒质的 if (!device_extension->media_in_device && io_stack->Parameters.DeviceIoControl.IoControlCode != IOCTL_FILE_DISK_OPEN_FILE) { Irp->IoStatus.Status = STATUS_NO_MEDIA_IN_DEVICE; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_NO_MEDIA_IN_DEVICE; } // 根据不同的功能号处理... switch (io_stack->Parameters.DeviceIoControl.IoControlCode) { case IOCTL_FILE_DISK_OPEN_FILE: { SECURITY_QUALITY_OF_SERVICE security_quality_of_service; if (device_extension->media_in_device) { KdPrint(("FileDisk: IOCTL_FILE_DISK_OPEN_FILE: Media already opened\n")); status = STATUS_INVALID_DEVICE_REQUEST; Irp->IoStatus.Information = 0; break; } if (io_stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(OPEN_FILE_INFORMATION)) { status = STATUS_INVALID_PARAMETER; Irp->IoStatus.Information = 0; break; } if (io_stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(OPEN_FILE_INFORMATION) + ((POPEN_FILE_INFORMATION)Irp->AssociatedIrp.SystemBuffer)->FileNameLength - sizeof(UCHAR)) { status = STATUS_INVALID_PARAMETER; Irp->IoStatus.Information = 0; break; } if (device_extension->security_client_context != NULL) { SeDeleteClientSecurity(device_extension->security_client_context); } else { device_extension->security_client_context = ExAllocatePool(NonPagedPool, sizeof(SECURITY_CLIENT_CONTEXT)); } RtlZeroMemory(&security_quality_of_service, sizeof(SECURITY_QUALITY_OF_SERVICE)); security_quality_of_service.Length = sizeof(SECURITY_QUALITY_OF_SERVICE); security_quality_of_service.ImpersonationLevel = SecurityImpersonation; security_quality_of_service.ContextTrackingMode = SECURITY_STATIC_TRACKING; security_quality_of_service.EffectiveOnly = FALSE; SeCreateClientSecurity( PsGetCurrentThread(), &security_quality_of_service, FALSE, device_extension->security_client_context ); IoMarkIrpPending(Irp); ExInterlockedInsertTailList( &device_extension->list_head, &Irp->Tail.Overlay.ListEntry, &device_extension->list_lock ); KeSetEvent( &device_extension->request_event, (KPRIORITY) 0, FALSE ); status = STATUS_PENDING; break; } case IOCTL_FILE_DISK_CLOSE_FILE: { IoMarkIrpPending(Irp); ExInterlockedInsertTailList( &device_extension->list_head, &Irp->Tail.Overlay.ListEntry, &device_extension->list_lock ); KeSetEvent( &device_extension->request_event, (KPRIORITY) 0, FALSE ); status = STATUS_PENDING; break; } case IOCTL_FILE_DISK_QUERY_FILE: { POPEN_FILE_INFORMATION open_file_information; if (io_stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(OPEN_FILE_INFORMATION) + device_extension->file_name.Length - sizeof(UCHAR)) { status = STATUS_BUFFER_TOO_SMALL; Irp->IoStatus.Information = 0; break; } open_file_information = (POPEN_FILE_INFORMATION) Irp->AssociatedIrp.SystemBuffer; open_file_information->FileSize.QuadPart = device_extension->file_size.QuadPart; open_file_information->ReadOnly = device_extension->read_only; open_file_information->FileNameLength = device_extension->file_name.Length; RtlCopyMemory( open_file_information->FileName, device_extension->file_name.Buffer, device_extension->file_name.Length ); status = STATUS_SUCCESS; Irp->IoStatus.Information = sizeof(OPEN_FILE_INFORMATION) + open_file_information->FileNameLength - sizeof(UCHAR); break; } case IOCTL_DISK_CHECK_VERIFY: case IOCTL_CDROM_CHECK_VERIFY: case IOCTL_STORAGE_CHECK_VERIFY: case IOCTL_STORAGE_CHECK_VERIFY2: { status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; break; } case IOCTL_DISK_GET_DRIVE_GEOMETRY: case IOCTL_CDROM_GET_DRIVE_GEOMETRY: { PDISK_GEOMETRY disk_geometry; ULONGLONG length; if (io_stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(DISK_GEOMETRY)) { status = STATUS_BUFFER_TOO_SMALL; Irp->IoStatus.Information = 0; break; } disk_geometry = (PDISK_GEOMETRY) Irp->AssociatedIrp.SystemBuffer; length = device_extension->file_size.QuadPart; disk_geometry->Cylinders.QuadPart = length / SECTOR_SIZE / 32 / 2; disk_geometry->MediaType = FixedMedia; disk_geometry->TracksPerCylinder = 2; disk_geometry->SectorsPerTrack = 32; disk_geometry->BytesPerSector = SECTOR_SIZE; status = STATUS_SUCCESS; Irp->IoStatus.Information = sizeof(DISK_GEOMETRY); break; } case IOCTL_DISK_GET_LENGTH_INFO: { PGET_LENGTH_INFORMATION get_length_information; if (io_stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(GET_LENGTH_INFORMATION)) { status = STATUS_BUFFER_TOO_SMALL; Irp->IoStatus.Information = 0; break; } get_length_information = (PGET_LENGTH_INFORMATION) Irp->AssociatedIrp.SystemBuffer; get_length_information->Length.QuadPart = device_extension->file_size.QuadPart; status = STATUS_SUCCESS; Irp->IoStatus.Information = sizeof(GET_LENGTH_INFORMATION); break; } case IOCTL_DISK_GET_PARTITION_INFO: { PPARTITION_INFORMATION partition_information; ULONGLONG length; if (io_stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(PARTITION_INFORMATION)) { status = STATUS_BUFFER_TOO_SMALL; Irp->IoStatus.Information = 0; break; } partition_information = (PPARTITION_INFORMATION) Irp->AssociatedIrp.SystemBuffer; length = device_extension->file_size.QuadPart; partition_information->StartingOffset.QuadPart = 0; partition_information->PartitionLength.QuadPart = length; partition_information->HiddenSectors = 1; partition_information->PartitionNumber = 0; partition_information->PartitionType = 0; partition_information->BootIndicator = FALSE; partition_information->RecognizedPartition = FALSE; partition_information->RewritePartition = FALSE; status = STATUS_SUCCESS; Irp->IoStatus.Information = sizeof(PARTITION_INFORMATION); break; } case IOCTL_DISK_GET_PARTITION_INFO_EX: { PPARTITION_INFORMATION_EX partition_information_ex; ULONGLONG length; if (io_stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(PARTITION_INFORMATION_EX)) { status = STATUS_BUFFER_TOO_SMALL; Irp->IoStatus.Information = 0; break; } partition_information_ex = (PPARTITION_INFORMATION_EX) Irp->AssociatedIrp.SystemBuffer; length = device_extension->file_size.QuadPart; partition_information_ex->PartitionStyle = PARTITION_STYLE_MBR; partition_information_ex->StartingOffset.QuadPart = 0; partition_information_ex->PartitionLength.QuadPart = length; partition_information_ex->PartitionNumber = 0; partition_information_ex->RewritePartition = FALSE; partition_information_ex->Mbr.PartitionType = 0; partition_information_ex->Mbr.BootIndicator = FALSE; partition_information_ex->Mbr.RecognizedPartition = FALSE; partition_information_ex->Mbr.HiddenSectors = 1; status = STATUS_SUCCESS; Irp->IoStatus.Information = sizeof(PARTITION_INFORMATION_EX); break; } case IOCTL_DISK_IS_WRITABLE: { if (!device_extension->read_only) { status = STATUS_SUCCESS; } else { status = STATUS_MEDIA_WRITE_PROTECTED; } Irp->IoStatus.Information = 0; break; } case IOCTL_DISK_MEDIA_REMOVAL: case IOCTL_STORAGE_MEDIA_REMOVAL: { status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; break; } case IOCTL_CDROM_READ_TOC: { PCDROM_TOC cdrom_toc; if (io_stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(CDROM_TOC)) { status = STATUS_BUFFER_TOO_SMALL; Irp->IoStatus.Information = 0; break; } cdrom_toc = (PCDROM_TOC) Irp->AssociatedIrp.SystemBuffer; RtlZeroMemory(cdrom_toc, sizeof(CDROM_TOC)); cdrom_toc->FirstTrack = 1; cdrom_toc->LastTrack = 1; cdrom_toc->TrackData[0].Control = TOC_DATA_TRACK; status = STATUS_SUCCESS; Irp->IoStatus.Information = sizeof(CDROM_TOC); break; } case IOCTL_DISK_SET_PARTITION_INFO: { if (device_extension->read_only) { status = STATUS_MEDIA_WRITE_PROTECTED; Irp->IoStatus.Information = 0; break; } if (io_stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(SET_PARTITION_INFORMATION)) { status = STATUS_INVALID_PARAMETER; Irp->IoStatus.Information = 0; break; } status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; break; } case IOCTL_DISK_VERIFY: { PVERIFY_INFORMATION verify_information; if (io_stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(VERIFY_INFORMATION)) { status = STATUS_INVALID_PARAMETER; Irp->IoStatus.Information = 0; break; } verify_information = (PVERIFY_INFORMATION) Irp->AssociatedIrp.SystemBuffer; status = STATUS_SUCCESS; Irp->IoStatus.Information = verify_information->Length; break; } default: { KdPrint(( "FileDisk: Unknown IoControlCode %#x\n", io_stack->Parameters.DeviceIoControl.IoControlCode )); status = STATUS_INVALID_DEVICE_REQUEST; Irp->IoStatus.Information = 0; } } if (status != STATUS_PENDING) { Irp->IoStatus.Status = status; IoCompleteRequest(Irp, IO_NO_INCREMENT); } return status; }