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.

562 lines
15 KiB

  1. /*++
  2. Copyright (c) 1998-2000 Microsoft Corporation
  3. Module Name :
  4. rdpdrpnp.c
  5. Abstract:
  6. This module includes routines for handling PnP and IO manager related IRP's
  7. for RDP device redirection.
  8. Don't forget to clean up the device object and the symbol link when
  9. our driver is unloaded.
  10. We should probably not expose a Win32 symbolic link. This might be a
  11. security issue ... If this is the case, then I will have to do a better
  12. job of researching overlapped I/O with NtCreateFile vs. CreateFile.
  13. Need a check in IRP_MJ_CREATE to make sure that we are not being opened
  14. 2x by the same session. This shouldn't be allowed.
  15. We may need to completely lock out access to the IRP queue on a cancel
  16. request.
  17. Where can I safely use PAGEDPOOL instead of NONPAGEDPOOL.
  18. Make sure that we handle opens and all subsequent IRP's from bogus
  19. user-mode apps.
  20. Author:
  21. tadb
  22. Revision History:
  23. --*/
  24. #include "precomp.hxx"
  25. #define TRC_FILE "rdpdrpnp"
  26. #include "trc.h"
  27. #define DRIVER
  28. #include "cfg.h"
  29. #include "pnp.h"
  30. #include "stdarg.h"
  31. #include "stdio.h"
  32. ///////////////////////////////////////////////////////////////////////////////////////
  33. //
  34. // Local Prototypes
  35. //
  36. // This routine is called when the lower level driver completes an IRP.
  37. NTSTATUS RDPDR_DeferIrpCompletion(
  38. IN PDEVICE_OBJECT DeviceObject,
  39. IN PIRP Irp,
  40. IN PVOID Context
  41. );
  42. // Adjust the dacl on the rdpdyn device object
  43. NTSTATUS AdjustSecurityDescriptor(
  44. IN PDEVICE_OBJECT DeviceObject,
  45. IN PSECURITY_DESCRIPTOR SecurityDescriptor,
  46. IN ULONG SecurityDescriptorLength);
  47. //
  48. // Externals. We cannot include ob.h or ntosp.h
  49. // as it causes tons of conflicts.
  50. //
  51. extern "C" {
  52. NTSYSAPI
  53. NTSTATUS
  54. NTAPI
  55. RtlDeleteAce (
  56. PACL Acl,
  57. ULONG AceIndex
  58. );
  59. }
  60. ///////////////////////////////////////////////////////////////////////////////////////
  61. //
  62. // Globals
  63. //
  64. // Unique Port Name Counter defined in rdpdyn.c.
  65. extern ULONG LastPortNumberUsed;
  66. // The Physical Device Object that terminates our DO stack.
  67. extern PDEVICE_OBJECT RDPDYN_PDO;
  68. // Global Registry Path for RDPDR.SYS. This global is defined in rdpdr.c.
  69. extern UNICODE_STRING DrRegistryPath;
  70. // Global Dr admin SD and sd length
  71. extern PSECURITY_DESCRIPTOR DrAdminSecurityDescriptor;
  72. extern ULONG DrSecurityDescriptorLength;
  73. ///////////////////////////////////////////////////////////////////////////////////////
  74. //
  75. // External Prototypes
  76. //
  77. // Just shove the typedefs in for the Power Management functions now because I can't
  78. // get the header conflicts resolved.
  79. NTKERNELAPI VOID PoStartNextPowerIrp(IN PIRP Irp);
  80. NTKERNELAPI NTSTATUS PoCallDriver(IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp);
  81. ///////////////////////////////////////////////////////////////////////////////////////
  82. //
  83. // Internal Prototypes
  84. //
  85. NTSTATUS RDPDRPNP_HandleStartDeviceIRP(
  86. PDEVICE_OBJECT StackDeviceObject,
  87. PIO_STACK_LOCATION IoStackLocation,
  88. IN PIRP Irp
  89. )
  90. /*++
  91. Routine Description:
  92. Handles PnP Start Device IRP's.
  93. Arguments:
  94. DeviceObject - Pointer to the device object for the class device.
  95. Irp - Irp.
  96. Return Value:
  97. The function value is the final status from the operation.
  98. --*/
  99. {
  100. KEVENT event;
  101. NTSTATUS ntStatus;
  102. BEGIN_FN("RDPDRPNP_HandleStartDeviceIRP");
  103. // Initialize this module.
  104. ntStatus = RDPDYN_Initialize();
  105. if (NT_SUCCESS(ntStatus)) {
  106. //
  107. // Set up the IO completion routine because the lower level
  108. // driver needs to handle this IRP before we can continue.
  109. //
  110. KeInitializeEvent(&event, NotificationEvent, FALSE);
  111. IoCopyCurrentIrpStackLocationToNext(Irp);
  112. IoSetCompletionRoutine(Irp,RDPDR_DeferIrpCompletion,&event,TRUE,TRUE,TRUE);
  113. ntStatus = IoCallDriver(StackDeviceObject,Irp);
  114. if (ntStatus == STATUS_PENDING)
  115. {
  116. KeWaitForSingleObject(&event,Suspended,KernelMode,FALSE,NULL);
  117. ntStatus = Irp->IoStatus.Status;
  118. }
  119. }
  120. // Finish the IRP.
  121. Irp->IoStatus.Status = ntStatus;
  122. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  123. return ntStatus;
  124. }
  125. NTSTATUS RDPDRPNP_HandleRemoveDeviceIRP(
  126. IN PDEVICE_OBJECT DeviceObject,
  127. PDEVICE_OBJECT StackDeviceObject,
  128. IN PIRP Irp
  129. )
  130. /*++
  131. Routine Description:
  132. Handles PnP Remove Device IRP's.
  133. Arguments:
  134. DeviceObject - Pointer to the device object for the class device.
  135. Irp - Irp.
  136. Return Value:
  137. The function value is the final status from the operation.
  138. --*/
  139. {
  140. NTSTATUS ntStatus;
  141. UNICODE_STRING symbolicLink;
  142. BEGIN_FN("RDPDRPNP_HandleRemoveDeviceIRP");
  143. //
  144. // Remove the Win32 symbolic link name.
  145. //
  146. RtlInitUnicodeString(&symbolicLink, RDPDRDVMGR_W32DEVICE_PATH_U);
  147. // Delete the existing link ... if it exists.
  148. #if DBG
  149. ntStatus = IoDeleteSymbolicLink(&symbolicLink);
  150. if (ntStatus != STATUS_SUCCESS) {
  151. TRC_ERR((TB, "IoDeleteSymbolicLink failed: %08X", ntStatus));
  152. }
  153. else {
  154. TRC_NRM((TB, "IoDeleteSymbolicLink succeeded"));
  155. }
  156. #else
  157. IoDeleteSymbolicLink(&symbolicLink);
  158. #endif
  159. //
  160. // Call the lower level driver.
  161. //
  162. IoSkipCurrentIrpStackLocation(Irp);
  163. ntStatus = IoCallDriver(StackDeviceObject,Irp);
  164. //
  165. // Detach the FDO from the DO stack.
  166. //
  167. IoDetachDevice(StackDeviceObject);
  168. //
  169. // The device is now about to be deleted4 ... we might need to perform
  170. // some cleanup for the device here before we remove it.
  171. //
  172. //
  173. // Release the FDO.
  174. //
  175. IoDeleteDevice(DeviceObject);
  176. return ntStatus;
  177. }
  178. NTSTATUS RDPDRPNP_PnPAddDevice(
  179. IN PDRIVER_OBJECT DriverObject,
  180. IN PDEVICE_OBJECT PhysicalDeviceObject
  181. )
  182. /*++
  183. Routine Description:
  184. This routine should only be called one time to create the "dr"'s FDO
  185. that sits on top of the PDO for the sole purpose of registering new
  186. device interfaces.
  187. This function is called by PnP to make the "dr" the function driver
  188. for a root dev node that was created on install.
  189. Arguments:
  190. DriverObject - pointer to the driver object for this instance of USBPRINT
  191. PhysicalDeviceObject - pointer to a device object created by the bus
  192. Return Value:
  193. STATUS_SUCCESS if successful,
  194. STATUS_UNSUCCESSFUL otherwise
  195. --*/
  196. {
  197. NTSTATUS ntStatus = STATUS_SUCCESS;
  198. PDEVICE_OBJECT fdo = NULL;
  199. PRDPDYNDEVICE_EXTENSION deviceExtension;
  200. UNICODE_STRING deviceName;
  201. UNICODE_STRING symbolicLink;
  202. BEGIN_FN("RDPDRPNP_PnPAddDevice");
  203. // Initialize the device name.
  204. RtlInitUnicodeString(&deviceName, RDPDRDVMGR_DEVICE_PATH_U);
  205. //
  206. // Create our FDO.
  207. //
  208. ntStatus = IoCreateDevice(DriverObject, sizeof(RDPDYNDEVICE_EXTENSION),
  209. &deviceName, FILE_DEVICE_UNKNOWN, 0, FALSE, &fdo);
  210. if (NT_SUCCESS(ntStatus)) {
  211. //
  212. // Adjust the default security descriptor on our device object
  213. //
  214. TRC_ASSERT(DrAdminSecurityDescriptor != NULL,
  215. (TB, "DrAdminSecurityDescriptor != NULL"));
  216. ntStatus = AdjustSecurityDescriptor(fdo, DrAdminSecurityDescriptor, DrSecurityDescriptorLength);
  217. if (!NT_SUCCESS(ntStatus)) {
  218. TRC_ERR((TB, "AdjustSecurityDescriptor failed: %08X",
  219. ntStatus));
  220. IoDeleteDevice(fdo);
  221. goto cleanup;
  222. }
  223. // We support buffered IO.
  224. fdo->Flags |= DO_BUFFERED_IO;
  225. //
  226. // Add the Win32 symbolic link name.
  227. //
  228. RtlInitUnicodeString(&symbolicLink, RDPDRDVMGR_W32DEVICE_PATH_U);
  229. // Delete the existing link ... in case it exists.
  230. IoDeleteSymbolicLink(&symbolicLink);
  231. // Create the new link.
  232. ntStatus = IoCreateSymbolicLink(&symbolicLink, &deviceName);
  233. if (!NT_SUCCESS(ntStatus)) {
  234. TRC_ERR((TB, "IoCreateSymbolicLink failed: %08X",
  235. ntStatus));
  236. IoDeleteDevice(fdo);
  237. }
  238. else {
  239. //
  240. // Get the device extension.
  241. //
  242. deviceExtension = (PRDPDYNDEVICE_EXTENSION)(fdo->DeviceExtension);
  243. //
  244. // Attach to the PDO after recording the current top of the DO stack.
  245. //
  246. deviceExtension->TopOfStackDeviceObject=IoAttachDeviceToDeviceStack(
  247. fdo,
  248. PhysicalDeviceObject
  249. );
  250. if (deviceExtension->TopOfStackDeviceObject == NULL)
  251. {
  252. TRC_ERR((TB, "IoAttachDeviceToDeviceStack failed"));
  253. IoDeleteDevice(fdo);
  254. }
  255. else
  256. {
  257. // Record the PDO to a global.
  258. RDPDYN_PDO = PhysicalDeviceObject;
  259. // We are done initializing our device.
  260. fdo->Flags &= ~DO_DEVICE_INITIALIZING;
  261. }
  262. }
  263. } // end if creation of FDO succeeded.
  264. cleanup:
  265. return ntStatus;
  266. }
  267. NTSTATUS
  268. AdjustSecurityDescriptor(
  269. IN PDEVICE_OBJECT DeviceObject,
  270. IN PSECURITY_DESCRIPTOR SecurityDescriptor,
  271. IN ULONG SecurityDescriptorLength
  272. )
  273. /*++
  274. Routine Description:
  275. Use the given security descriptor to give system-only access on the given device object
  276. Arguments:
  277. Device Object - Pointer to the device object to be modified
  278. SecurityDescriptor - Pointer to a valid SECURITY_DESCRIPTOR structure
  279. SecurityDescriptorLength - Length of the SecurityDescriptor
  280. Return Value:
  281. NTSTATUS - success/error code.
  282. --*/
  283. {
  284. BEGIN_FN("AdjustSecurityDescriptor");
  285. //
  286. // We set only the Dacl from the SD
  287. //
  288. SECURITY_INFORMATION SecurityInformation = DACL_SECURITY_INFORMATION;
  289. NTSTATUS status;
  290. PACE_HEADER AceHeader = NULL;
  291. PSID AceSid;
  292. PACL Dacl = NULL;
  293. BOOLEAN DaclDefaulted;
  294. BOOLEAN DaclPresent;
  295. DWORD i;
  296. PACL NewDacl = NULL;
  297. SECURITY_DESCRIPTOR NewSD;
  298. if (DeviceObject == NULL ||
  299. SecurityDescriptor == NULL ||
  300. SecurityDescriptorLength == 0) {
  301. return STATUS_INVALID_PARAMETER;
  302. }
  303. //
  304. // Validate the security descriptor
  305. //
  306. if (SeValidSecurityDescriptor(SecurityDescriptorLength, SecurityDescriptor)) {
  307. //
  308. // Obtain the Dacl from the security descriptor
  309. //
  310. status = RtlGetDaclSecurityDescriptor(SecurityDescriptor,
  311. &DaclPresent,
  312. &Dacl,
  313. &DaclDefaulted);
  314. if (!NT_SUCCESS(status)) {
  315. TRC_ERR((TB, "RDPDRPNP:RtlGetDaclSecurityDescriptor failed: %08X",
  316. status));
  317. goto Cleanup;
  318. }
  319. TRC_ASSERT(DaclPresent != FALSE,
  320. (TB, "RDPDRPNP:Dacl not present"));
  321. //
  322. // Make a copy of the Dacl so that we can modify it.
  323. //
  324. NewDacl = (PACL)ExAllocatePoolWithTag(PagedPool, Dacl->AclSize, DR_POOLTAG);
  325. if (NULL == NewDacl) {
  326. status = STATUS_NO_MEMORY;
  327. TRC_ERR((TB, "RDPDRPNP:Can't allocate memory for new dacl: %08X",
  328. status));
  329. goto Cleanup;
  330. }
  331. RtlCopyMemory(NewDacl, Dacl, Dacl->AclSize);
  332. //
  333. // Loop through the DACL, removing any access allowed
  334. // entries that aren't for SYSTEM
  335. //
  336. for (i = 0; i < NewDacl->AceCount; i++) {
  337. //
  338. // Get each ACE.
  339. //
  340. status = RtlGetAce(NewDacl, i, (PVOID*)&AceHeader);
  341. if (NT_SUCCESS(status)) {
  342. if (ACCESS_ALLOWED_ACE_TYPE == AceHeader->AceType) {
  343. AceSid = (PSID) &((ACCESS_ALLOWED_ACE*)AceHeader)->SidStart;
  344. //
  345. // Check if this is system sid.
  346. //
  347. if (!RtlEqualSid(AceSid, SeExports->SeLocalSystemSid)) {
  348. //
  349. // Not a system sid. Delete ace.
  350. //
  351. status = RtlDeleteAce(NewDacl, i);
  352. if (NT_SUCCESS(status)) {
  353. i -= 1;
  354. }
  355. }
  356. }
  357. }
  358. }
  359. TRC_ASSERT(NewDacl->AceCount > 0,
  360. (TB, "RDPDRPNP:AceCount is 0 in the new dacl"));
  361. //
  362. // Create a new security descriptor to hold the new Dacl.
  363. //
  364. status = RtlCreateSecurityDescriptor(&NewSD, SECURITY_DESCRIPTOR_REVISION);
  365. if (!NT_SUCCESS(status)) {
  366. TRC_ERR((TB, "RDPDRPNP:RtlCreateSecurityDescriptor failed: %08X",
  367. status));
  368. goto Cleanup;
  369. }
  370. //
  371. // Place the new Dacl into the new SD
  372. //
  373. status = RtlSetDaclSecurityDescriptor(&NewSD, TRUE, NewDacl, FALSE);
  374. if (!NT_SUCCESS(status)) {
  375. TRC_ERR((TB, "RDPDRPNP:RtlSetDaclSecurityDescriptor failed: %08X",
  376. status));
  377. goto Cleanup;
  378. }
  379. //
  380. // Set the new SD into our device object.
  381. //
  382. status = ObSetSecurityObjectByPointer(
  383. DeviceObject,
  384. SecurityInformation,
  385. &NewSD
  386. );
  387. }
  388. else {
  389. status = STATUS_INVALID_PARAMETER;
  390. TRC_ERR((TB, "RDPDRPNP: Invalid security descriptor",
  391. status));
  392. }
  393. Cleanup:
  394. if (NULL != NewDacl) {
  395. ExFreePool(NewDacl);
  396. }
  397. return status;
  398. }
  399. NTSTATUS
  400. RDPDR_DeferIrpCompletion(
  401. IN PDEVICE_OBJECT DeviceObject,
  402. IN PIRP Irp,
  403. IN PVOID Context
  404. )
  405. /*++
  406. Routine Description:
  407. This routine is called when the lower level driver completes an IRP. It
  408. simply sets an event to true, which allows the blocked thread to finish
  409. whatever processing was pending.
  410. Arguments:
  411. DeviceObject - Pointer to the device object for the class device.
  412. Irp - Irp completed.
  413. Context - Driver defined context.
  414. Return Value:
  415. The function value is the final status from the operation.
  416. --*/
  417. {
  418. PKEVENT event = (PKEVENT)Context;
  419. BEGIN_FN("RDPDR_DeferIrpCompletion");
  420. KeSetEvent(event,
  421. 1,
  422. FALSE);
  423. return STATUS_MORE_PROCESSING_REQUIRED;
  424. }