Handling Client Impersonation in UMDF 1.x Drivers
[This topic applies to UMDF 1.x.]
UMDF drivers typically run under the LocalService account and cannot access files or resources that require user credentials, such as protected files or other protected resources. A UMDF driver typically operates on commands and data that flow between a client application and a device. Therefore, most UMDF drivers do not access protected resources.
However, some drivers might require access to a protected resource. For example, a UMDF driver might load firmware into a device from a file that a client application provides. The file might have an access control list (ACL) that prevents unauthorized users from modifying the file and taking control of the device. Unfortunately, this ACL also prevents the UMDF driver from accessing the file.
The framework provides an impersonation capability that allows drivers to impersonate the driver's client and obtain the client's access rights to protected resources.
Both the UMDF driver's installation package and the client application must enable the framework's impersonation capability, as follows:
The INF file of the UMDF driver's installation package must include the UmdfImpersonationLevel directive and set the maximum allowable impersonation level. Impersonation is enabled only if the INF file includes the UmdfImpersonationLevel directive. For more information about setting the impersonation level, see Specifying WDF Directives in INF Files.
The client application must set the allowed impersonation level for each file handle. The application uses the quality of service (QoS) settings in the Microsoft Win32 CreateFile function to set the allowed impersonation level. For more information about these settings, see the dwFlagsAndAttributes parameter of CreateFile in the Windows SDK documentation.
The UMDF driver and framework handle impersonation for an I/O request in the following sequence:
The framework checks the requested impersonation level. If the requested level is greater than the level that the UMDF driver's installation package and the client application allow, the impersonation request fails. Otherwise, the framework impersonates the client and immediately calls the OnImpersonate callback function.
The OnImpersonate callback function must perform only the operations that require the requested impersonation level, such as opening a protected file.
UMDF does not allow a driver's OnImpersonate callback function to call any of the framework's object methods. This ensures that the driver does not expose the impersonation level to other driver callback functions or other drivers.
Note In versions 1.0 through 1.7 of UMDF, IWDFIoRequest::Impersonate grants the highest impersonation level that the client application and INF file allow, even if the impersonation level that the driver requests is lower. In UMFD versions 1.9 and later, the Impersonate method grants only the impersonation level that the driver requests.
When your driver receives a WdfRequestCreate-typed I/O request, the driver might forward the I/O request down the driver stack to a kernel-mode driver. Kernel-mode drivers do not have the impersonation capability that IWDFIoRequest::Impersonate provides to UMDF-based drivers.
Therefore, if you want a kernel-mode driver to receive the client's user credentials (rather the credentials of the driver host process), the driver must set the WDF_REQUEST_SEND_OPTION_IMPERSONATE_CLIENT flag when it calls IWDFIoRequest::Send to send the create request to the I/O target. The Send method returns an error code if the impersonation attempt fails, unless the driver also sets the WDF_REQUEST_SEND_OPTION_IMPERSONATION_IGNORE_FAILURE flag.
The driver does not have to call IWDFIoRequest::Impersonate before it sends the request to the I/O target.
If lower-level drivers also forward the request, the client's impersonation level travels down the driver stack.
To reduce the chance of an "elevation of privilege" attack, you should:
Try to avoid using impersonation.
For example, to avoid using impersonation to open a file that the driver must use, the client application can open the file and use I/O operations to send file contents to the driver.
Use the lowest impersonation level that your driver requires.
Set the impersonation level in your driver's INF file as low as possible. If your driver does not require any impersonation, do not include the UmdfImpersonationLevel directive in the INF file.
Minimize the opportunities for an attacker to exploit your driver.
Your OnImpersonate callback function should contain a small section of code that performs only the operation that requires impersonation. For example, if your driver accesses a protected file, it requires impersonation only when it opens the file handle. It does not require impersonation to read from or write to the file.