Source code of Windows XP (NT5)
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.

1095 lines
32 KiB

  1. // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs)
  2. //
  3. // Copyright (c) 1985-2000 Microsoft Corporation
  4. //
  5. // This file is part of the Microsoft Research IPv6 Network Protocol Stack.
  6. // You should have received a copy of the Microsoft End-User License Agreement
  7. // for this software along with this release; see the file "license.txt".
  8. // If not, please see http://www.research.microsoft.com/msripv6/license.htm,
  9. // or write to Microsoft Research, One Microsoft Way, Redmond, WA 98052-6399.
  10. //
  11. // Abstract:
  12. //
  13. // NT specific routines for loading and configuring the TCP/IPv6 driver.
  14. //
  15. #include <oscfg.h>
  16. #include <ndis.h>
  17. #include <tdi.h>
  18. #include <tdikrnl.h>
  19. #include <tdint.h>
  20. #include <tdistat.h>
  21. #include <tdiinfo.h>
  22. #include <ip6imp.h>
  23. #include <ip6def.h>
  24. #include <ntddip6.h>
  25. #include "queue.h"
  26. #include "transprt.h"
  27. #include "addr.h"
  28. #include "tcp.h"
  29. #include "tcb.h"
  30. #include "tcpconn.h"
  31. #include "tcpcfg.h"
  32. #include <ntddtcp.h>
  33. //
  34. // Global variables.
  35. //
  36. PSECURITY_DESCRIPTOR TcpAdminSecurityDescriptor = NULL;
  37. PDEVICE_OBJECT TCPDeviceObject = NULL;
  38. PDEVICE_OBJECT UDPDeviceObject = NULL;
  39. PDEVICE_OBJECT RawIPDeviceObject = NULL;
  40. extern PDEVICE_OBJECT IPDeviceObject;
  41. HANDLE TCPRegistrationHandle;
  42. HANDLE UDPRegistrationHandle;
  43. HANDLE IPRegistrationHandle;
  44. //
  45. // Set to TRUE when the stack is unloading.
  46. //
  47. int Unloading = FALSE;
  48. //
  49. // External function prototypes.
  50. // REVIEW: These prototypes should be imported via include files.
  51. //
  52. int
  53. TransportLayerInit(void);
  54. void
  55. TransportLayerUnload(void);
  56. NTSTATUS
  57. TCPDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
  58. NTSTATUS
  59. TCPDispatchInternalDeviceControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
  60. NTSTATUS
  61. IPDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
  62. NTSTATUS
  63. IPDriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath);
  64. NTSTATUS
  65. GetRegMultiSZValue(HANDLE KeyHandle, PWCHAR ValueName,
  66. PUNICODE_STRING ValueData);
  67. PWCHAR
  68. EnumRegMultiSz(IN PWCHAR MszString, IN ULONG MszStringLength,
  69. IN ULONG StringIndex);
  70. //
  71. // Local funcion prototypes.
  72. //
  73. NTSTATUS
  74. DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath);
  75. VOID
  76. DriverUnload(IN PDRIVER_OBJECT DriverObject);
  77. void
  78. TLRegisterProtocol(uchar Protocol, void *RcvHandler, void *XmitHandler,
  79. void *StatusHandler, void *RcvCmpltHandler);
  80. uchar
  81. TCPGetConfigInfo(void);
  82. NTSTATUS
  83. TCPInitializeParameter(HANDLE KeyHandle, PWCHAR ValueName, PULONG Value);
  84. BOOLEAN
  85. IsRunningOnPersonal(VOID);
  86. NTSTATUS
  87. TcpBuildDeviceAcl(OUT PACL *DeviceAcl);
  88. NTSTATUS
  89. TcpCreateAdminSecurityDescriptor(VOID);
  90. NTSTATUS
  91. AddNetConfigOpsAce(IN PACL Dacl, OUT PACL *DeviceAcl);
  92. NTSTATUS
  93. CreateDeviceDriverSecurityDescriptor(PVOID DeviceOrDriverObject);
  94. #ifdef ALLOC_PRAGMA
  95. #pragma alloc_text(INIT, DriverEntry)
  96. #pragma alloc_text(INIT, TLRegisterProtocol)
  97. #pragma alloc_text(INIT, TCPGetConfigInfo)
  98. #pragma alloc_text(INIT, TCPInitializeParameter)
  99. #pragma alloc_text(INIT, IsRunningOnPersonal)
  100. #pragma alloc_text(INIT, TcpBuildDeviceAcl)
  101. #pragma alloc_text(INIT, TcpCreateAdminSecurityDescriptor)
  102. #pragma alloc_text(INIT, AddNetConfigOpsAce)
  103. #pragma alloc_text(INIT, CreateDeviceDriverSecurityDescriptor)
  104. #endif // ALLOC_PRAGMA
  105. //
  106. // Main initialization routine for the TCP/IPv6 driver.
  107. //
  108. // This is the driver entry point, called by NT upon loading us.
  109. //
  110. //
  111. NTSTATUS // Returns: final status from the initialization operation.
  112. DriverEntry(
  113. IN PDRIVER_OBJECT DriverObject, // TCP/IPv6 driver object.
  114. IN PUNICODE_STRING RegistryPath) // Path to our info in the registry.
  115. {
  116. NTSTATUS Status;
  117. UNICODE_STRING deviceName;
  118. USHORT i;
  119. int initStatus;
  120. PIO_ERROR_LOG_PACKET entry;
  121. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_STATE,
  122. "Tcpip6: In DriverEntry routine\n"));
  123. //
  124. // Write a log entry, so that PSS will know
  125. // if this driver has been loaded on the machine.
  126. //
  127. entry = IoAllocateErrorLogEntry(DriverObject, sizeof *entry);
  128. if (entry != NULL) {
  129. RtlZeroMemory(entry, sizeof *entry);
  130. entry->ErrorCode = EVENT_TCPIP6_STARTED;
  131. IoWriteErrorLogEntry(entry);
  132. }
  133. #if COUNTING_MALLOC
  134. InitCountingMalloc();
  135. #endif
  136. TdiInitialize();
  137. //
  138. // Initialize network level protocol: IPv6.
  139. //
  140. Status = IPDriverEntry(DriverObject, RegistryPath);
  141. if (!NT_SUCCESS(Status)) {
  142. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INTERNAL_ERROR,
  143. "Tcpip6: IPv6 init failed, status %lx\n", Status));
  144. return(Status);
  145. }
  146. //
  147. // Initialize transport level protocols: TCP, UDP, and RawIP.
  148. //
  149. //
  150. // Create the device objects. IoCreateDevice zeroes the memory
  151. // occupied by the object.
  152. //
  153. RtlInitUnicodeString(&deviceName, DD_TCPV6_DEVICE_NAME);
  154. Status = IoCreateDevice(DriverObject, 0, &deviceName,
  155. FILE_DEVICE_NETWORK,
  156. FILE_DEVICE_SECURE_OPEN,
  157. FALSE, &TCPDeviceObject);
  158. if (!NT_SUCCESS(Status)) {
  159. //
  160. // REVIEW: Write an error log entry here?
  161. //
  162. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_NTOS_ERROR,
  163. "Tcpip6: Failed to create TCP device object, status %lx\n",
  164. Status));
  165. goto init_failed;
  166. }
  167. RtlInitUnicodeString(&deviceName, DD_UDPV6_DEVICE_NAME);
  168. Status = IoCreateDevice(DriverObject, 0, &deviceName,
  169. FILE_DEVICE_NETWORK,
  170. FILE_DEVICE_SECURE_OPEN,
  171. FALSE, &UDPDeviceObject);
  172. if (!NT_SUCCESS(Status)) {
  173. //
  174. // REVIEW: Write an error log entry here?
  175. //
  176. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_NTOS_ERROR,
  177. "Tcpip6: Failed to create UDP device object, status %lx\n",
  178. Status));
  179. goto init_failed;
  180. }
  181. RtlInitUnicodeString(&deviceName, DD_RAW_IPV6_DEVICE_NAME);
  182. Status = IoCreateDevice(DriverObject, 0, &deviceName,
  183. FILE_DEVICE_NETWORK,
  184. FILE_DEVICE_SECURE_OPEN,
  185. FALSE, &RawIPDeviceObject);
  186. if (!NT_SUCCESS(Status)) {
  187. //
  188. // REVIEW: Write an error log entry here?
  189. //
  190. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_NTOS_ERROR,
  191. "Tcpip6: Failed to create Raw IP device object, status %lx\n",
  192. Status));
  193. goto init_failed;
  194. }
  195. //
  196. // Initialize the driver object.
  197. //
  198. DriverObject->DriverUnload = DriverUnload;
  199. DriverObject->FastIoDispatch = NULL;
  200. for (i=0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) {
  201. DriverObject->MajorFunction[i] = TCPDispatch;
  202. }
  203. //
  204. // We special case Internal Device Controls because they are the
  205. // hot path for kernel-mode clients.
  206. //
  207. DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] =
  208. TCPDispatchInternalDeviceControl;
  209. //
  210. // Intialize the device objects.
  211. //
  212. TCPDeviceObject->Flags |= DO_DIRECT_IO;
  213. UDPDeviceObject->Flags |= DO_DIRECT_IO;
  214. RawIPDeviceObject->Flags |= DO_DIRECT_IO;
  215. //
  216. // Change the devices and objects to allow access by
  217. // Network Configuration Operators
  218. //
  219. if (!IsRunningOnPersonal()) {
  220. Status = CreateDeviceDriverSecurityDescriptor(IPDeviceObject);
  221. if (!NT_SUCCESS(Status)) {
  222. goto init_failed;
  223. }
  224. Status = CreateDeviceDriverSecurityDescriptor(TCPDeviceObject);
  225. if (!NT_SUCCESS(Status)) {
  226. goto init_failed;
  227. }
  228. }
  229. //
  230. // Create the security descriptor used for raw socket access checks.
  231. //
  232. Status = TcpCreateAdminSecurityDescriptor();
  233. if (!NT_SUCCESS(Status)) {
  234. goto init_failed;
  235. }
  236. //
  237. // Finally, initialize the stack.
  238. //
  239. initStatus = TransportLayerInit();
  240. if (initStatus == TRUE) {
  241. RtlInitUnicodeString(&deviceName, DD_TCPV6_DEVICE_NAME);
  242. (void)TdiRegisterDeviceObject(&deviceName, &TCPRegistrationHandle);
  243. RtlInitUnicodeString(&deviceName, DD_UDPV6_DEVICE_NAME);
  244. (void)TdiRegisterDeviceObject(&deviceName, &UDPRegistrationHandle);
  245. RtlInitUnicodeString(&deviceName, DD_RAW_IPV6_DEVICE_NAME);
  246. (void)TdiRegisterDeviceObject(&deviceName, &IPRegistrationHandle);
  247. return(STATUS_SUCCESS);
  248. }
  249. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INTERNAL_ERROR,
  250. "Tcpip6: "
  251. "TCP/UDP initialization failed, but IP will be available.\n"));
  252. //
  253. // REVIEW: Write an error log entry here?
  254. //
  255. Status = STATUS_UNSUCCESSFUL;
  256. init_failed:
  257. //
  258. // IP has successfully started, but TCP & UDP failed. Set the
  259. // Dispatch routine to point to IP only, since the TCP and UDP
  260. // devices don't exist.
  261. //
  262. if (TCPDeviceObject != NULL) {
  263. IoDeleteDevice(TCPDeviceObject);
  264. }
  265. if (UDPDeviceObject != NULL) {
  266. IoDeleteDevice(UDPDeviceObject);
  267. }
  268. if (RawIPDeviceObject != NULL) {
  269. IoDeleteDevice(RawIPDeviceObject);
  270. }
  271. for (i=0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) {
  272. DriverObject->MajorFunction[i] = IPDispatch;
  273. }
  274. return(STATUS_SUCCESS);
  275. }
  276. VOID
  277. DriverUnload(
  278. IN PDRIVER_OBJECT DriverObject)
  279. {
  280. UNICODE_STRING WinDeviceName;
  281. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_STATE,
  282. "IPv6: DriverUnload\n"));
  283. //
  284. // Start the shutdown process by noting our change of state.
  285. // This will inhibit our starting new activities.
  286. // REVIEW - Is this actually needed? Possibly other factors
  287. // prevent new entries into the stack.
  288. //
  289. Unloading = TRUE;
  290. //
  291. // Cleanup our modules.
  292. // This will break connections with NDIS and the v4 stack.
  293. //
  294. TransportLayerUnload();
  295. IPUnload();
  296. LanUnload();
  297. //
  298. // Deregister with TDI.
  299. //
  300. (void) TdiDeregisterDeviceObject(TCPRegistrationHandle);
  301. (void) TdiDeregisterDeviceObject(UDPRegistrationHandle);
  302. (void) TdiDeregisterDeviceObject(IPRegistrationHandle);
  303. //
  304. // Delete Win32 symbolic links.
  305. //
  306. RtlInitUnicodeString(&WinDeviceName, L"\\??\\" WIN_IPV6_BASE_DEVICE_NAME);
  307. (void) IoDeleteSymbolicLink(&WinDeviceName);
  308. //
  309. // Delete our device objects.
  310. //
  311. IoDeleteDevice(TCPDeviceObject);
  312. IoDeleteDevice(UDPDeviceObject);
  313. IoDeleteDevice(RawIPDeviceObject);
  314. IoDeleteDevice(IPDeviceObject);
  315. #if COUNTING_MALLOC
  316. DumpCountingMallocStats();
  317. UnloadCountingMalloc();
  318. #endif
  319. }
  320. //
  321. // Interval in milliseconds between keepalive transmissions until a
  322. // response is received.
  323. //
  324. #define DEFAULT_KEEPALIVE_INTERVAL 1000
  325. //
  326. // Time to first keepalive transmission. 2 hours == 7,200,000 milliseconds
  327. //
  328. #define DEFAULT_KEEPALIVE_TIME 7200000
  329. #if 1
  330. //* TCPGetConfigInfo -
  331. //
  332. // Initializes TCP global configuration parameters.
  333. //
  334. uchar // Returns: Zero on failure, nonzero on success.
  335. TCPGetConfigInfo(void)
  336. {
  337. HANDLE keyHandle;
  338. NTSTATUS status;
  339. OBJECT_ATTRIBUTES objectAttributes;
  340. UNICODE_STRING UKeyName;
  341. ULONG maxConnectRexmits = 0;
  342. ULONG maxDataRexmits = 0;
  343. ULONG pptpmaxDataRexmits = 0;
  344. ULONG useRFC1122UrgentPointer = 0;
  345. MM_SYSTEMSIZE systemSize;
  346. //
  347. // Initialize to the defaults in case an error occurs somewhere.
  348. //
  349. AllowUserRawAccess = FALSE;
  350. KAInterval = DEFAULT_KEEPALIVE_INTERVAL;
  351. KeepAliveTime = DEFAULT_KEEPALIVE_TIME;
  352. PMTUDiscovery = TRUE;
  353. PMTUBHDetect = FALSE;
  354. DeadGWDetect = TRUE;
  355. DefaultRcvWin = 0; // Automagically pick a reasonable one.
  356. MaxConnections = DEFAULT_MAX_CONNECTIONS;
  357. maxConnectRexmits = MAX_CONNECT_REXMIT_CNT;
  358. pptpmaxDataRexmits = maxDataRexmits = MAX_REXMIT_CNT;
  359. BSDUrgent = TRUE;
  360. FinWait2TO = FIN_WAIT2_TO;
  361. NTWMaxConnectCount = NTW_MAX_CONNECT_COUNT;
  362. NTWMaxConnectTime = NTW_MAX_CONNECT_TIME;
  363. MaxUserPort = MAX_USER_PORT;
  364. TcbTableSize = ComputeLargerOrEqualPowerOfTwo(DEFAULT_TCB_TABLE_SIZE);
  365. systemSize = MmQuerySystemSize();
  366. if (MmIsThisAnNtAsSystem()) {
  367. switch (systemSize) {
  368. case MmSmallSystem:
  369. MaxConnBlocks = DEFAULT_MAX_CONN_BLOCKS_AS_SMALL;
  370. break;
  371. case MmMediumSystem:
  372. MaxConnBlocks = DEFAULT_MAX_CONN_BLOCKS_AS_MEDIUM;
  373. break;
  374. case MmLargeSystem:
  375. default:
  376. #if defined(_WIN64)
  377. MaxConnBlocks = DEFAULT_MAX_CONN_BLOCKS_AS_LARGE64;
  378. #else
  379. MaxConnBlocks = DEFAULT_MAX_CONN_BLOCKS_AS_LARGE;
  380. #endif
  381. break;
  382. }
  383. } else {
  384. switch (systemSize) {
  385. case MmSmallSystem:
  386. MaxConnBlocks = DEFAULT_MAX_CONN_BLOCKS_WS_SMALL;
  387. break;
  388. case MmMediumSystem:
  389. MaxConnBlocks = DEFAULT_MAX_CONN_BLOCKS_WS_MEDIUM;
  390. break;
  391. case MmLargeSystem:
  392. default:
  393. MaxConnBlocks = DEFAULT_MAX_CONN_BLOCKS_WS_LARGE;
  394. break;
  395. }
  396. }
  397. //
  398. // Read the TCP optional (hidden) registry parameters.
  399. //
  400. RtlInitUnicodeString(&UKeyName,
  401. L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\" TCPIPV6_NAME L"\\Parameters"
  402. );
  403. memset(&objectAttributes, 0, sizeof(OBJECT_ATTRIBUTES));
  404. InitializeObjectAttributes(&objectAttributes, &UKeyName,
  405. OBJ_CASE_INSENSITIVE, NULL, NULL);
  406. status = ZwOpenKey(&keyHandle, KEY_READ, &objectAttributes);
  407. if (NT_SUCCESS(status)) {
  408. TCPInitializeParameter(keyHandle, L"AllowUserRawAccess", &AllowUserRawAccess);
  409. TCPInitializeParameter(keyHandle, L"IsnStoreSize", &ISNStoreSize);
  410. TCPInitializeParameter(keyHandle, L"KeepAliveInterval", &KAInterval);
  411. TCPInitializeParameter(keyHandle, L"KeepAliveTime", &KeepAliveTime);
  412. TCPInitializeParameter(keyHandle, L"EnablePMTUBHDetect",
  413. &PMTUBHDetect);
  414. TCPInitializeParameter(keyHandle, L"TcpWindowSize", &DefaultRcvWin);
  415. TCPInitializeParameter(keyHandle, L"TcpNumConnections",
  416. &MaxConnections);
  417. if (MaxConnections != DEFAULT_MAX_CONNECTIONS) {
  418. uint ConnBlocks =
  419. (MaxConnections + MAX_CONN_PER_BLOCK - 1) / MAX_CONN_PER_BLOCK;
  420. if (ConnBlocks > MaxConnBlocks) {
  421. MaxConnBlocks = ConnBlocks;
  422. }
  423. }
  424. TCPInitializeParameter(keyHandle, L"MaxHashTableSize", &TcbTableSize);
  425. if (TcbTableSize < MIN_TCB_TABLE_SIZE) {
  426. TcbTableSize = MIN_TCB_TABLE_SIZE;
  427. } else if (TcbTableSize > MAX_TCB_TABLE_SIZE) {
  428. TcbTableSize = MAX_TCB_TABLE_SIZE;
  429. } else {
  430. TcbTableSize = ComputeLargerOrEqualPowerOfTwo(TcbTableSize);
  431. }
  432. TCPInitializeParameter(keyHandle, L"TcpMaxConnectRetransmissions",
  433. &maxConnectRexmits);
  434. if (maxConnectRexmits > 255) {
  435. maxConnectRexmits = 255;
  436. }
  437. TCPInitializeParameter(keyHandle, L"TcpMaxDataRetransmissions",
  438. &maxDataRexmits);
  439. if (maxDataRexmits > 255) {
  440. maxDataRexmits = 255;
  441. }
  442. //
  443. // If we fail, then set to same value as maxDataRexmit so that the
  444. // max(pptpmaxDataRexmit,maxDataRexmit) is a decent value
  445. // Need this since TCPInitializeParameter no longer "initializes"
  446. // to a default value.
  447. //
  448. if(TCPInitializeParameter(keyHandle, L"PPTPTcpMaxDataRetransmissions",
  449. &pptpmaxDataRexmits) != STATUS_SUCCESS) {
  450. pptpmaxDataRexmits = maxDataRexmits;
  451. }
  452. if (pptpmaxDataRexmits > 255) {
  453. pptpmaxDataRexmits = 255;
  454. }
  455. TCPInitializeParameter(keyHandle, L"TcpUseRFC1122UrgentPointer",
  456. &useRFC1122UrgentPointer);
  457. if (useRFC1122UrgentPointer) {
  458. BSDUrgent = FALSE;
  459. }
  460. TCPInitializeParameter(keyHandle, L"TcpTimedWaitDelay", &FinWait2TO);
  461. if (FinWait2TO < 30) {
  462. FinWait2TO = 30;
  463. }
  464. if (FinWait2TO > 300) {
  465. FinWait2TO = 300;
  466. }
  467. FinWait2TO = MS_TO_TICKS(FinWait2TO*1000);
  468. NTWMaxConnectTime = MS_TO_TICKS(NTWMaxConnectTime*1000);
  469. TCPInitializeParameter(keyHandle, L"MaxUserPort", &MaxUserPort);
  470. if (MaxUserPort < 5000) {
  471. MaxUserPort = 5000;
  472. }
  473. if (MaxUserPort > 65534) {
  474. MaxUserPort = 65534;
  475. }
  476. //
  477. // Read a few IP optional (hidden) registry parameters that TCP
  478. // cares about.
  479. //
  480. TCPInitializeParameter(keyHandle, L"EnablePMTUDiscovery",
  481. &PMTUDiscovery);
  482. TCPInitializeParameter(keyHandle, L"EnableDeadGWDetect",
  483. &DeadGWDetect);
  484. TCPInitializeParameter(keyHandle, L"SynAttackProtect",
  485. &SynAttackProtect);
  486. ZwClose(keyHandle);
  487. }
  488. MaxConnectRexmitCount = maxConnectRexmits;
  489. //
  490. // Use the greater of the two, hence both values should be valid
  491. //
  492. MaxDataRexmitCount = (maxDataRexmits > pptpmaxDataRexmits ?
  493. maxDataRexmits : pptpmaxDataRexmits);
  494. return(1);
  495. }
  496. #endif
  497. #define WORK_BUFFER_SIZE 256
  498. //* TCPInitializeParameter - Read a value from the registry.
  499. //
  500. // Initializes a ULONG parameter from the registry.
  501. //
  502. NTSTATUS
  503. TCPInitializeParameter(
  504. HANDLE KeyHandle, // An open handle to the registry key for the parameter.
  505. PWCHAR ValueName, // The UNICODE name of the registry value to read.
  506. PULONG Value) // The ULONG into which to put the data.
  507. {
  508. NTSTATUS status;
  509. ULONG resultLength;
  510. PKEY_VALUE_FULL_INFORMATION keyValueFullInformation;
  511. UCHAR keybuf[WORK_BUFFER_SIZE];
  512. UNICODE_STRING UValueName;
  513. RtlInitUnicodeString(&UValueName, ValueName);
  514. keyValueFullInformation = (PKEY_VALUE_FULL_INFORMATION)keybuf;
  515. RtlZeroMemory(keyValueFullInformation, sizeof(keyValueFullInformation));
  516. status = ZwQueryValueKey(KeyHandle, &UValueName, KeyValueFullInformation,
  517. keyValueFullInformation, WORK_BUFFER_SIZE,
  518. &resultLength);
  519. if (status == STATUS_SUCCESS) {
  520. if (keyValueFullInformation->Type == REG_DWORD) {
  521. *Value = *((ULONG UNALIGNED *) ((PCHAR)keyValueFullInformation +
  522. keyValueFullInformation->DataOffset));
  523. }
  524. }
  525. return(status);
  526. }
  527. //* IsRunningOnPersonal - Are we running on the Personal SKU.
  528. //
  529. BOOLEAN
  530. IsRunningOnPersonal(
  531. VOID)
  532. {
  533. OSVERSIONINFOEXW OsVer = {0};
  534. ULONGLONG ConditionMask = 0;
  535. BOOLEAN IsPersonal = TRUE;
  536. OsVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
  537. OsVer.wSuiteMask = VER_SUITE_PERSONAL;
  538. OsVer.wProductType = VER_NT_WORKSTATION;
  539. VER_SET_CONDITION(ConditionMask, VER_PRODUCT_TYPE, VER_EQUAL);
  540. VER_SET_CONDITION(ConditionMask, VER_SUITENAME, VER_AND);
  541. if (RtlVerifyVersionInfo(&OsVer, VER_PRODUCT_TYPE | VER_SUITENAME,
  542. ConditionMask) == STATUS_REVISION_MISMATCH) {
  543. IsPersonal = FALSE;
  544. }
  545. return(IsPersonal);
  546. } // IsRunningOnPersonal
  547. //* TcpBuildDeviceAcl -
  548. //
  549. // (Lifted from AFD - AfdBuildDeviceAcl)
  550. // This routine builds an ACL which gives Administrators and LocalSystem
  551. // principals full access. All other principals have no access.
  552. //
  553. NTSTATUS
  554. TcpBuildDeviceAcl(
  555. OUT PACL *DeviceAcl) // Output pointer to the new ACL.
  556. {
  557. PGENERIC_MAPPING GenericMapping;
  558. PSID AdminsSid;
  559. PSID SystemSid;
  560. PSID NetworkSid;
  561. ULONG AclLength;
  562. NTSTATUS Status;
  563. ACCESS_MASK AccessMask = GENERIC_ALL;
  564. PACL NewAcl;
  565. //
  566. // Enable access to all the globally defined SIDs
  567. //
  568. GenericMapping = IoGetFileObjectGenericMapping();
  569. RtlMapGenericMask(&AccessMask, GenericMapping);
  570. AdminsSid = SeExports->SeAliasAdminsSid;
  571. SystemSid = SeExports->SeLocalSystemSid;
  572. NetworkSid = SeExports->SeNetworkServiceSid;
  573. AclLength = sizeof(ACL) +
  574. 3 * sizeof(ACCESS_ALLOWED_ACE) +
  575. RtlLengthSid(AdminsSid) +
  576. RtlLengthSid(SystemSid) +
  577. RtlLengthSid(NetworkSid) -
  578. 3 * sizeof(ULONG);
  579. NewAcl = ExAllocatePool(NonPagedPool, AclLength);
  580. if (NewAcl == NULL) {
  581. return(STATUS_INSUFFICIENT_RESOURCES);
  582. }
  583. Status = RtlCreateAcl(NewAcl, AclLength, ACL_REVISION);
  584. if (!NT_SUCCESS(Status)) {
  585. ExFreePool(NewAcl);
  586. return(Status);
  587. }
  588. Status = RtlAddAccessAllowedAce(NewAcl,
  589. ACL_REVISION2,
  590. AccessMask,
  591. AdminsSid);
  592. ASSERT(NT_SUCCESS(Status));
  593. Status = RtlAddAccessAllowedAce(NewAcl,
  594. ACL_REVISION2,
  595. AccessMask,
  596. SystemSid);
  597. ASSERT(NT_SUCCESS(Status));
  598. // Add acl for NetworkSid!
  599. Status = RtlAddAccessAllowedAce(NewAcl,
  600. ACL_REVISION2,
  601. AccessMask,
  602. NetworkSid);
  603. ASSERT(NT_SUCCESS(Status));
  604. *DeviceAcl = NewAcl;
  605. return(STATUS_SUCCESS);
  606. } // TcpBuildDeviceAcl
  607. //* TcpCreateAdminSecurityDescriptor -
  608. //
  609. // (Lifted from AFD - AfdCreateAdminSecurityDescriptor)
  610. // This routine creates a security descriptor which gives access
  611. // only to Administrtors and LocalSystem. This descriptor is used
  612. // to access check raw endpoint opens and exclisive access to transport
  613. // addresses.
  614. //
  615. NTSTATUS
  616. TcpCreateAdminSecurityDescriptor(VOID)
  617. {
  618. PACL rawAcl = NULL;
  619. NTSTATUS status;
  620. BOOLEAN memoryAllocated = FALSE;
  621. PSECURITY_DESCRIPTOR tcpSecurityDescriptor;
  622. ULONG tcpSecurityDescriptorLength;
  623. CHAR buffer[SECURITY_DESCRIPTOR_MIN_LENGTH];
  624. PSECURITY_DESCRIPTOR localSecurityDescriptor =
  625. (PSECURITY_DESCRIPTOR) &buffer;
  626. PSECURITY_DESCRIPTOR localTcpAdminSecurityDescriptor;
  627. SECURITY_INFORMATION securityInformation = DACL_SECURITY_INFORMATION;
  628. //
  629. // Get a pointer to the security descriptor from the TCP device object.
  630. //
  631. status = ObGetObjectSecurity(TCPDeviceObject,
  632. &tcpSecurityDescriptor,
  633. &memoryAllocated);
  634. if (!NT_SUCCESS(status)) {
  635. ASSERT(memoryAllocated == FALSE);
  636. return(status);
  637. }
  638. //
  639. // Build a local security descriptor with an ACL giving only
  640. // administrators and system access.
  641. //
  642. status = TcpBuildDeviceAcl(&rawAcl);
  643. if (!NT_SUCCESS(status)) {
  644. goto error_exit;
  645. }
  646. (VOID) RtlCreateSecurityDescriptor(
  647. localSecurityDescriptor,
  648. SECURITY_DESCRIPTOR_REVISION
  649. );
  650. (VOID) RtlSetDaclSecurityDescriptor(
  651. localSecurityDescriptor,
  652. TRUE,
  653. rawAcl,
  654. FALSE
  655. );
  656. //
  657. // Make a copy of the TCP descriptor. This copy will be the raw descriptor.
  658. //
  659. tcpSecurityDescriptorLength = RtlLengthSecurityDescriptor(tcpSecurityDescriptor);
  660. localTcpAdminSecurityDescriptor = ExAllocatePool(PagedPool,
  661. tcpSecurityDescriptorLength);
  662. if (localTcpAdminSecurityDescriptor == NULL) {
  663. goto error_exit;
  664. }
  665. RtlMoveMemory(localTcpAdminSecurityDescriptor,
  666. tcpSecurityDescriptor,
  667. tcpSecurityDescriptorLength);
  668. TcpAdminSecurityDescriptor = localTcpAdminSecurityDescriptor;
  669. //
  670. // Now apply the local descriptor to the raw descriptor.
  671. //
  672. status = SeSetSecurityDescriptorInfo(NULL,
  673. &securityInformation,
  674. localSecurityDescriptor,
  675. &TcpAdminSecurityDescriptor,
  676. PagedPool,
  677. IoGetFileObjectGenericMapping());
  678. if (!NT_SUCCESS(status)) {
  679. ASSERT(TcpAdminSecurityDescriptor == localTcpAdminSecurityDescriptor);
  680. ExFreePool(TcpAdminSecurityDescriptor);
  681. TcpAdminSecurityDescriptor = NULL;
  682. goto error_exit;
  683. }
  684. if (TcpAdminSecurityDescriptor != localTcpAdminSecurityDescriptor) {
  685. ExFreePool(localTcpAdminSecurityDescriptor);
  686. }
  687. status = STATUS_SUCCESS;
  688. error_exit:
  689. ObReleaseObjectSecurity(tcpSecurityDescriptor,
  690. memoryAllocated);
  691. if (rawAcl != NULL) {
  692. ExFreePool(rawAcl);
  693. }
  694. return(status);
  695. }
  696. //* TcpCreateAdminSecurityDescriptor -
  697. //
  698. // This routine builds an ACL which gives adds the Network Configuration
  699. // Operators group to the principals allowed to control the driver.
  700. //
  701. NTSTATUS
  702. AddNetConfigOpsAce(
  703. IN PACL Dacl, // Existing DACL.
  704. OUT PACL *DeviceAcl) // Output pointer to the new ACL.
  705. {
  706. PGENERIC_MAPPING GenericMapping;
  707. PSID AdminsSid = NULL;
  708. PSID SystemSid = NULL;
  709. PSID NetworkSid = NULL;
  710. PSID NetConfigOpsSid = NULL;
  711. ULONG AclLength;
  712. NTSTATUS Status;
  713. ACCESS_MASK AccessMask = GENERIC_ALL;
  714. PACL NewAcl = NULL;
  715. ULONG SidSize;
  716. SID_IDENTIFIER_AUTHORITY sidAuth = SECURITY_NT_AUTHORITY;
  717. PISID ISid;
  718. PACCESS_ALLOWED_ACE AceTemp;
  719. int i;
  720. //
  721. // Enable access to all the globally defined SIDs
  722. //
  723. GenericMapping = IoGetFileObjectGenericMapping();
  724. RtlMapGenericMask(&AccessMask, GenericMapping);
  725. AdminsSid = SeExports->SeAliasAdminsSid;
  726. SystemSid = SeExports->SeLocalSystemSid;
  727. NetworkSid = SeExports->SeNetworkServiceSid;
  728. SidSize = RtlLengthRequiredSid(3);
  729. NetConfigOpsSid = (PSID)(ExAllocatePool(NonPagedPool, SidSize));
  730. if (NULL == NetConfigOpsSid) {
  731. return(STATUS_INSUFFICIENT_RESOURCES);
  732. }
  733. Status = RtlInitializeSid(NetConfigOpsSid, &sidAuth, 2);
  734. if (Status != STATUS_SUCCESS) {
  735. goto clean_up;
  736. }
  737. ISid = (PISID)(NetConfigOpsSid);
  738. ISid->SubAuthority[0] = SECURITY_BUILTIN_DOMAIN_RID;
  739. ISid->SubAuthority[1] = DOMAIN_ALIAS_RID_NETWORK_CONFIGURATION_OPS;
  740. AclLength = Dacl->AclSize;
  741. AclLength += sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) - 2 * sizeof(ULONG);
  742. AclLength += RtlLengthSid(NetConfigOpsSid);
  743. NewAcl = ExAllocatePool(NonPagedPool, AclLength);
  744. if (NewAcl == NULL) {
  745. Status = STATUS_INSUFFICIENT_RESOURCES;
  746. goto clean_up;
  747. }
  748. Status = RtlCreateAcl(NewAcl, AclLength, ACL_REVISION2);
  749. if (!NT_SUCCESS(Status)) {
  750. goto clean_up;
  751. }
  752. for (i = 0; i < Dacl->AceCount; i++) {
  753. Status = RtlGetAce(Dacl, i, &AceTemp);
  754. if (NT_SUCCESS(Status)) {
  755. Status = RtlAddAccessAllowedAce(NewAcl,
  756. ACL_REVISION2,
  757. AceTemp->Mask,
  758. &AceTemp->SidStart);
  759. }
  760. if (!NT_SUCCESS(Status)) {
  761. goto clean_up;
  762. }
  763. }
  764. // Add Net Config Operators Ace
  765. Status = RtlAddAccessAllowedAce(NewAcl,
  766. ACL_REVISION2,
  767. AccessMask,
  768. NetConfigOpsSid);
  769. if (!NT_SUCCESS(Status)) {
  770. goto clean_up;
  771. }
  772. *DeviceAcl = NewAcl;
  773. clean_up:
  774. if (NetConfigOpsSid) {
  775. ExFreePool(NetConfigOpsSid);
  776. }
  777. if (!NT_SUCCESS(Status) && NewAcl) {
  778. ExFreePool(NewAcl);
  779. }
  780. return(Status);
  781. } // AddNetConfigOpsAce
  782. //* CreateDeviceDriverSecurityDescriptor -
  783. //
  784. // Creates the SD responsible for giving access to different users.
  785. //
  786. NTSTATUS
  787. CreateDeviceDriverSecurityDescriptor(
  788. PVOID DeviceOrDriverObject) // Object to which to assign the Access Rights.
  789. {
  790. NTSTATUS status;
  791. BOOLEAN memoryAllocated = FALSE;
  792. PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
  793. ULONG SecurityDescriptorLength;
  794. CHAR buffer[SECURITY_DESCRIPTOR_MIN_LENGTH];
  795. PSECURITY_DESCRIPTOR localSecurityDescriptor =
  796. (PSECURITY_DESCRIPTOR) & buffer;
  797. SECURITY_INFORMATION securityInformation = DACL_SECURITY_INFORMATION;
  798. PACL Dacl = NULL;
  799. BOOLEAN HasDacl = FALSE;
  800. BOOLEAN DaclDefaulted = FALSE;
  801. PACL NewAcl = NULL;
  802. INT i;
  803. //
  804. // Get a pointer to the security descriptor from the driver/device object.
  805. //
  806. status = ObGetObjectSecurity(DeviceOrDriverObject,
  807. &SecurityDescriptor,
  808. &memoryAllocated);
  809. if (!NT_SUCCESS(status)) {
  810. ASSERT(memoryAllocated == FALSE);
  811. return(status);
  812. }
  813. status = RtlGetDaclSecurityDescriptor(SecurityDescriptor, &HasDacl, &Dacl, &DaclDefaulted);
  814. if (NT_SUCCESS(status) && HasDacl)
  815. {
  816. status = AddNetConfigOpsAce(Dacl, &NewAcl);
  817. if (NT_SUCCESS(status)) {
  818. PSECURITY_DESCRIPTOR SecDesc = NULL;
  819. ULONG SecDescSize = 0;
  820. PACL AbsDacl = NULL;
  821. ULONG DaclSize = 0;
  822. PACL AbsSacl = NULL;
  823. ULONG ulSacl = 0;
  824. PSID Owner = NULL;
  825. ULONG OwnerSize = 0;
  826. PSID PrimaryGroup = NULL;
  827. ULONG PrimaryGroupSize = 0;
  828. BOOLEAN OwnerDefault = FALSE;
  829. BOOLEAN GroupDefault = FALSE;
  830. BOOLEAN HasSacl = FALSE;
  831. BOOLEAN SaclDefaulted = FALSE;
  832. SECURITY_INFORMATION secInfo = OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION;
  833. SecDescSize = sizeof(SecDesc) + NewAcl->AclSize;
  834. SecDesc = ExAllocatePool(NonPagedPool, SecDescSize);
  835. if (SecDesc) {
  836. DaclSize = NewAcl->AclSize;
  837. AbsDacl = ExAllocatePool(NonPagedPool, DaclSize);
  838. if (AbsDacl) {
  839. status = RtlGetOwnerSecurityDescriptor(SecurityDescriptor, &Owner, &OwnerDefault);
  840. if (NT_SUCCESS(status)) {
  841. OwnerSize = RtlLengthSid(Owner);
  842. status = RtlGetGroupSecurityDescriptor(SecurityDescriptor, &PrimaryGroup, &GroupDefault);
  843. if (NT_SUCCESS(status)) {
  844. PrimaryGroupSize = RtlLengthSid(PrimaryGroup);
  845. status = RtlGetSaclSecurityDescriptor(SecurityDescriptor, &HasSacl, &AbsSacl, &SaclDefaulted);
  846. if (NT_SUCCESS(status)) {
  847. if (HasSacl) {
  848. ulSacl = AbsSacl->AclSize;
  849. secInfo |= SACL_SECURITY_INFORMATION;
  850. }
  851. status = RtlSelfRelativeToAbsoluteSD(SecurityDescriptor, SecDesc, &SecDescSize, AbsDacl,
  852. &DaclSize, AbsSacl, &ulSacl, Owner, &OwnerSize, PrimaryGroup, &PrimaryGroupSize);
  853. if (NT_SUCCESS(status)) {
  854. status = RtlSetDaclSecurityDescriptor(SecDesc, TRUE, NewAcl, FALSE);
  855. if (NT_SUCCESS(status)) {
  856. status = ObSetSecurityObjectByPointer(DeviceOrDriverObject, secInfo, SecDesc);
  857. }
  858. }
  859. }
  860. }
  861. } else {
  862. status = STATUS_INSUFFICIENT_RESOURCES;
  863. }
  864. } else {
  865. status = STATUS_INSUFFICIENT_RESOURCES;
  866. }
  867. if (SecDesc) {
  868. // Since this is a Self-Relative security descriptor, freeing it also frees
  869. // Owner and PrimaryGroup.
  870. ExFreePool(SecDesc);
  871. }
  872. if (AbsDacl) {
  873. ExFreePool(AbsDacl);
  874. }
  875. }
  876. if (NewAcl) {
  877. ExFreePool(NewAcl);
  878. }
  879. }
  880. }
  881. ObReleaseObjectSecurity(SecurityDescriptor,
  882. memoryAllocated);
  883. return(status);
  884. } // CreateDeviceDriverSecurityDescriptor