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.

3790 lines
102 KiB

  1. /*++
  2. Copyright (c) 1997-2001 Microsoft Corporation
  3. Module Name:
  4. driver.c
  5. Abstract:
  6. This module contains the DriverEntry and other initialization
  7. code for the IPSEC module of the Tcpip transport.
  8. Author:
  9. Sanjay Anand (SanjayAn) 2-January-1997
  10. ChunYe
  11. Environment:
  12. Kernel mode
  13. Revision History:
  14. --*/
  15. #include "precomp.h"
  16. #ifdef RUN_WPP
  17. #include "driver.tmh"
  18. #endif
  19. #ifdef ALLOC_PRAGMA
  20. #pragma alloc_text(INIT, DriverEntry)
  21. #pragma alloc_text(INIT, IPSecGeneralInit)
  22. #pragma alloc_text(PAGE, IPSecBindToIP)
  23. #pragma alloc_text(PAGE, IPSecUnbindFromIP)
  24. #pragma alloc_text(PAGE, IPSecFreeConfig)
  25. #pragma alloc_text(PAGE, IPSecInitMdlPool)
  26. #pragma alloc_text(PAGE, AllocateCacheStructures)
  27. #pragma alloc_text(PAGE, FreeExistingCache)
  28. #pragma alloc_text(PAGE, FreePatternDbase)
  29. #pragma alloc_text(PAGE, OpenRegKey)
  30. #pragma alloc_text(PAGE, GetRegDWORDValue)
  31. #pragma alloc_text(PAGE, IPSecCryptoInitialize)
  32. #pragma alloc_text(PAGE, IPSecCryptoDeinitialize)
  33. #endif
  34. NTSTATUS
  35. DriverEntry(
  36. IN PDRIVER_OBJECT DriverObject,
  37. IN PUNICODE_STRING RegistryPath
  38. )
  39. /*++
  40. Routine Description:
  41. This routine performs initialization of the IPSEC module.
  42. It creates the device object for the transport
  43. provider and performs other driver initialization.
  44. Arguments:
  45. DriverObject - Pointer to driver object created by the system.
  46. RegistryPath - The name of IPSEC's node in the registry.
  47. Return Value:
  48. The function value is the final status from the initialization operation.
  49. --*/
  50. {
  51. PDEVICE_OBJECT deviceObject = NULL;
  52. WCHAR deviceNameBuffer[] = DD_IPSEC_DEVICE_NAME;
  53. WCHAR symbolicLinkBuffer[] = DD_IPSEC_SYM_NAME;
  54. UNICODE_STRING symbolicLinkName;
  55. UNICODE_STRING deviceNameUnicodeString;
  56. NTSTATUS status;
  57. NTSTATUS status1;
  58. //DbgBreakPoint();
  59. // WPP tracing
  60. //
  61. WPP_INIT_TRACING(DriverObject, RegistryPath);
  62. IPSEC_DEBUG(LL_A, DBF_LOAD, ("Entering DriverEntry"));
  63. //
  64. // Init g_ipsec structure and read reg keys.
  65. //
  66. IPSecZeroMemory(&g_ipsec, sizeof(g_ipsec));
  67. //
  68. // Create the device - do we need a device at all?
  69. //
  70. // Setup the handlers.
  71. //
  72. //
  73. // Initialize the driver object with this driver's entry points.
  74. //
  75. g_ipsec.IPSecDriverObject = DriverObject;
  76. IPSecReadRegistry();
  77. DriverObject->MajorFunction [IRP_MJ_CREATE] =
  78. DriverObject->MajorFunction [IRP_MJ_CLOSE] =
  79. DriverObject->MajorFunction [IRP_MJ_CLEANUP] =
  80. DriverObject->MajorFunction [IRP_MJ_INTERNAL_DEVICE_CONTROL] =
  81. DriverObject->MajorFunction [IRP_MJ_DEVICE_CONTROL] = IPSecDispatch;
  82. DriverObject->DriverUnload = IPSecUnload;
  83. RtlInitUnicodeString (&deviceNameUnicodeString, deviceNameBuffer);
  84. status = IoCreateDevice(
  85. DriverObject,
  86. 0, // DeviceExtensionSize
  87. &deviceNameUnicodeString, // DeviceName
  88. FILE_DEVICE_NETWORK, // DeviceType
  89. FILE_DEVICE_SECURE_OPEN, // DeviceCharacteristics
  90. FALSE, // Exclusive
  91. &deviceObject); // *DeviceObject
  92. if (!NT_SUCCESS (status)) {
  93. IPSEC_DEBUG(LL_A, DBF_LOAD, ("Failed to create device: %lx", status));
  94. LOG_EVENT(
  95. DriverObject,
  96. EVENT_IPSEC_CREATE_DEVICE_FAILED,
  97. 1,
  98. 1,
  99. &deviceNameUnicodeString.Buffer,
  100. 0,
  101. NULL);
  102. goto err;
  103. }
  104. deviceObject->Flags |= DO_BUFFERED_IO;
  105. IPSecDevice = deviceObject;
  106. RtlInitUnicodeString (&symbolicLinkName, symbolicLinkBuffer);
  107. status = IoCreateSymbolicLink(&symbolicLinkName, &deviceNameUnicodeString);
  108. if (!NT_SUCCESS (status)) {
  109. IPSEC_DEBUG(LL_A, DBF_LOAD, ("Failed to create symbolic link: %lx", status));
  110. LOG_EVENT(
  111. DriverObject,
  112. EVENT_IPSEC_CREATE_DEVICE_FAILED,
  113. 2,
  114. 1,
  115. &deviceNameUnicodeString.Buffer,
  116. 0,
  117. NULL);
  118. IoDeleteDevice(DriverObject->DeviceObject);
  119. goto err;
  120. }
  121. //
  122. // General structs init here.
  123. // Allocates the SA Table etc.
  124. //
  125. status = IPSecGeneralInit();
  126. if (!NT_SUCCESS (status)) {
  127. IPSEC_DEBUG(LL_A, DBF_LOAD, ("Failed to init general structs: %lx", status));
  128. //
  129. // Free the general structs and SA Table etc.
  130. //
  131. status1 = IPSecGeneralFree();
  132. if (!NT_SUCCESS (status1)) {
  133. IPSEC_DEBUG(LL_A, DBF_LOAD, ("Failed to free config: %lx", status1));
  134. }
  135. LOG_EVENT(
  136. DriverObject,
  137. EVENT_IPSEC_NO_RESOURCES_FOR_INIT,
  138. 1,
  139. 0,
  140. NULL,
  141. 0,
  142. NULL);
  143. IoDeleteSymbolicLink(&symbolicLinkName);
  144. IoDeleteDevice(DriverObject->DeviceObject);
  145. goto err;
  146. }
  147. //
  148. // Wait for TCP/IP to load and call IOCTL_IPSEC_SET_TCPIP_STATUS where we
  149. // would finish the initialization.
  150. //
  151. status = STATUS_SUCCESS;
  152. IPSEC_DEBUG(LL_A, DBF_LOAD, ("Exiting DriverEntry; SUCCESS"));
  153. err:
  154. return status;
  155. }
  156. VOID
  157. IPSecUnload(
  158. IN PDRIVER_OBJECT DriverObject
  159. )
  160. /*++
  161. Routine Description:
  162. Called when the driver is unloaded.
  163. Arguments:
  164. DriverObject
  165. Return Value:
  166. None
  167. --*/
  168. {
  169. UNICODE_STRING IPSecLinkName;
  170. KIRQL OldIrq;
  171. KIRQL kIrql;
  172. NTSTATUS status;
  173. INT class;
  174. IPSEC_DEBUG(LL_A, DBF_LOAD, ("Entering IPSecUnload"));
  175. //
  176. // Set IPSEC_DRIVER_UNLOADING bit.
  177. //
  178. IPSEC_DRIVER_UNLOADING() = TRUE;
  179. AcquireWriteLock(&g_ipsec.SADBLock,&kIrql);
  180. if (g_ipsec.BootStatefulHT){
  181. IPSecFreeMemory(g_ipsec.BootStatefulHT);
  182. g_ipsec.BootStatefulHT = NULL;
  183. }
  184. if (g_ipsec.BootBufferPool){
  185. IPSecFreeMemory(g_ipsec.BootBufferPool);
  186. g_ipsec.BootBufferPool = NULL;
  187. }
  188. if (g_ipsec.BootExemptList){
  189. IPSecFreeMemory(g_ipsec.BootExemptList);
  190. g_ipsec.BootExemptList = NULL;
  191. }
  192. ReleaseWriteLock(&g_ipsec.SADBLock, kIrql);
  193. //
  194. // Stop the reaper timer.
  195. //
  196. IPSecStopTimer(&g_ipsec.ReaperTimer);
  197. //
  198. // Stop the EventLog timer.
  199. //
  200. IPSecStopTimer(&g_ipsec.EventLogTimer);
  201. //
  202. // Complete the Acquire Irp with error status
  203. //
  204. if (g_ipsec.AcquireInfo.Irp) {
  205. IPSEC_DEBUG(LL_A, DBF_ACQUIRE, ("Unload: Completing Irp.."));
  206. if (g_ipsec.AcquireInfo.InMe) {
  207. IoAcquireCancelSpinLock(&g_ipsec.AcquireInfo.Irp->CancelIrql);
  208. IPSecAcquireIrpCancel(NULL, g_ipsec.AcquireInfo.Irp);
  209. }
  210. }
  211. //
  212. // Stop timers for all SAs (of all states)
  213. //
  214. IPSecStopSATimers();
  215. if (g_ipsec.ShimFunctions.pCleanupRoutine) {
  216. (g_ipsec.ShimFunctions.pCleanupRoutine)();
  217. }
  218. //
  219. // Wait for all timers to clear before going further
  220. //
  221. while (IPSEC_GET_VALUE(g_ipsec.NumTimers) != 0) {
  222. IPSEC_DELAY_EXECUTION();
  223. }
  224. //
  225. // Cleanup any larval SAs
  226. //
  227. AcquireWriteLock(&g_ipsec.SADBLock, &kIrql);
  228. ACQUIRE_LOCK(&g_ipsec.AcquireInfo.Lock, &OldIrq);
  229. IPSecFlushLarvalSAList();
  230. IPSecFlushSAExpirations();
  231. RELEASE_LOCK(&g_ipsec.AcquireInfo.Lock, OldIrq);
  232. ReleaseWriteLock(&g_ipsec.SADBLock, kIrql);
  233. //
  234. // Free the SA Table.
  235. //
  236. status = IPSecFreeConfig();
  237. if (!NT_SUCCESS (status)) {
  238. IPSEC_DEBUG(LL_A, DBF_LOAD, ("Failed to free config: %lx", status));
  239. }
  240. //
  241. // Free the MDL pools and run down all buffered packets.
  242. //
  243. status = IPSecQuiesce();
  244. if (!NT_SUCCESS (status)) {
  245. IPSEC_DEBUG(LL_A, DBF_LOAD, ("Failed to reach quiescent state: %lx", status));
  246. }
  247. AcquireWriteLock(&g_ipsec.SADBLock, &kIrql);
  248. ASSERT (gpParserIfEntry == NULL);
  249. FlushAllParserEntries();
  250. ReleaseWriteLock(&g_ipsec.SADBLock, kIrql);
  251. //
  252. // Destroy timer structures
  253. //
  254. ACQUIRE_LOCK(&g_ipsec.TimerLock, &kIrql);
  255. for (class = 0; class < IPSEC_CLASS_MAX; class++) {
  256. ASSERT(g_ipsec.TimerList[class].TimerCount == 0);
  257. IPSecFreeMemory(g_ipsec.TimerList[class].pTimers);
  258. }
  259. RELEASE_LOCK(&g_ipsec.TimerLock, kIrql);
  260. IPSecCryptoDeinitialize();
  261. #if GPC
  262. IPSecGpcDeinitialize();
  263. #endif
  264. RtlInitUnicodeString(&IPSecLinkName, DD_IPSEC_SYM_NAME);
  265. IoDeleteSymbolicLink(&IPSecLinkName);
  266. WPP_CLEANUP(DriverObject);
  267. IoDeleteDevice(DriverObject->DeviceObject);
  268. IPSEC_DEBUG(LL_A, DBF_LOAD, ("Exiting IPSecUnload"));
  269. }
  270. NTSTATUS
  271. IPSecDispatch(
  272. IN PDEVICE_OBJECT DeviceObject,
  273. IN PIRP Irp
  274. )
  275. /*++
  276. Routine Description:
  277. Dispatch Routine for the driver. Gets the current irp stack location, validates
  278. the parameters and routes the calls
  279. Arguments:
  280. DeviceObject
  281. Irp
  282. Return Value:
  283. Status as returned by the worker functions
  284. --*/
  285. {
  286. PIO_STACK_LOCATION irpStack;
  287. PVOID pvIoBuffer;
  288. LONG inputBufferLength;
  289. LONG outputBufferLength;
  290. ULONG ioControlCode;
  291. NTSTATUS status = STATUS_SUCCESS;
  292. LONG dwSize = 0;
  293. PAGED_CODE();
  294. IPSEC_DEBUG(LL_A, DBF_IOCTL, ("Entering IPSecDispath"));
  295. Irp->IoStatus.Status = status;
  296. Irp->IoStatus.Information = 0;
  297. //
  298. // Get a pointer to the current location in the Irp. This is where
  299. // the function codes and parameters are located.
  300. //
  301. irpStack = IoGetCurrentIrpStackLocation(Irp);
  302. //
  303. // Get the pointer to the input/output buffer and its length.
  304. //
  305. pvIoBuffer = Irp->AssociatedIrp.SystemBuffer;
  306. inputBufferLength = irpStack->Parameters.DeviceIoControl.InputBufferLength;
  307. outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
  308. switch (irpStack->MajorFunction) {
  309. case IRP_MJ_CREATE: {
  310. IPSEC_DEBUG(LL_A, DBF_IOCTL, ("IRP_MJ_CREATE"));
  311. break;
  312. }
  313. case IRP_MJ_CLOSE: {
  314. IPSEC_DEBUG(LL_A, DBF_IOCTL, ("IRP_MJ_CLOSE"));
  315. break;
  316. }
  317. case IRP_MJ_DEVICE_CONTROL: {
  318. ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
  319. IPSEC_DEBUG(LL_A, DBF_IOCTL, ("IRP_MJ_DEVICE_CONTROL: %lx", ioControlCode));
  320. if (ioControlCode != IOCTL_IPSEC_SET_TCPIP_STATUS) {
  321. if (IPSEC_DRIVER_IS_INACTIVE()) {
  322. status = STATUS_INVALID_DEVICE_STATE;
  323. break;
  324. }
  325. if (!IPSecCryptoInitialize()) {
  326. status = STATUS_CRYPTO_SYSTEM_INVALID;
  327. break;
  328. }
  329. }
  330. IPSEC_INCREMENT(g_ipsec.NumIoctls);
  331. switch (ioControlCode) {
  332. case IOCTL_IPSEC_ADD_FILTER: {
  333. PIPSEC_ADD_FILTER pAddFilter = (PIPSEC_ADD_FILTER)pvIoBuffer;
  334. IPSEC_DEBUG(LL_A, DBF_IOCTL, ("IOCTL_IPSEC_ADD_FILTER"));
  335. dwSize = sizeof(IPSEC_ADD_FILTER);
  336. if (inputBufferLength < dwSize) {
  337. status = STATUS_BUFFER_TOO_SMALL;
  338. break;
  339. }
  340. //
  341. // Check the size of the entry
  342. //
  343. if (pAddFilter->NumEntries == 0) {
  344. status = STATUS_SUCCESS;
  345. } else {
  346. dwSize = FIELD_OFFSET(IPSEC_ADD_FILTER, pInfo[0]) +
  347. pAddFilter->NumEntries * sizeof(IPSEC_FILTER_INFO);
  348. if (dwSize < FIELD_OFFSET(IPSEC_ADD_FILTER, pInfo[0]) ||
  349. inputBufferLength < dwSize) {
  350. status = STATUS_BUFFER_TOO_SMALL;
  351. IPSEC_DEBUG(LL_A, DBF_IOCTL, ("returning: %lx", status));
  352. break;
  353. }
  354. status = IPSecAddFilter(pAddFilter);
  355. }
  356. break;
  357. }
  358. case IOCTL_IPSEC_DELETE_FILTER: {
  359. PIPSEC_DELETE_FILTER pDelFilter = (PIPSEC_DELETE_FILTER)pvIoBuffer;
  360. IPSEC_DEBUG(LL_A, DBF_IOCTL, ("IOCTL_IPSEC_DELETE_FILTER"));
  361. dwSize = sizeof(IPSEC_DELETE_FILTER);
  362. if (inputBufferLength < dwSize) {
  363. status = STATUS_BUFFER_TOO_SMALL;
  364. break;
  365. }
  366. //
  367. // Check the size of the entry
  368. //
  369. if (pDelFilter->NumEntries == 0) {
  370. status = STATUS_SUCCESS;
  371. } else {
  372. dwSize = FIELD_OFFSET(IPSEC_DELETE_FILTER, pInfo[0]) +
  373. pDelFilter->NumEntries * sizeof(IPSEC_FILTER_INFO);
  374. if (dwSize < FIELD_OFFSET(IPSEC_DELETE_FILTER, pInfo[0]) ||
  375. inputBufferLength < dwSize) {
  376. status = STATUS_BUFFER_TOO_SMALL;
  377. break;
  378. }
  379. status = IPSecDeleteFilter(pDelFilter);
  380. }
  381. break;
  382. }
  383. case IOCTL_IPSEC_ENUM_SAS: {
  384. IPSEC_DEBUG(LL_A, DBF_IOCTL, ("IOCTL_IPSEC_ENUM_SAS"));
  385. dwSize = sizeof(IPSEC_ENUM_SAS);
  386. //
  387. // Output/Input in the same buffer at MdlAddress
  388. //
  389. // This functions accesses Irp->MdlAddress
  390. // and checks if it is NULL too.
  391. status = IPSecEnumSAs(Irp, &dwSize);
  392. break;
  393. }
  394. case IOCTL_IPSEC_ENUM_FILTERS: {
  395. IPSEC_DEBUG(LL_A, DBF_IOCTL, ("IOCTL_IPSEC_ENUM_FILTERS"));
  396. dwSize = sizeof(IPSEC_ENUM_FILTERS);
  397. //
  398. // Output/Input in the same buffer at MdlAddress
  399. //
  400. // This functions accesses Irp->MdlAddress
  401. // and checks if it is NULL too.
  402. status = IPSecEnumFilters(Irp, &dwSize);
  403. break;
  404. }
  405. case IOCTL_IPSEC_QUERY_STATS: {
  406. //
  407. // The minimum size is without any Keys
  408. //
  409. IPSEC_DEBUG(LL_A, DBF_IOCTL, ("IOCTL_IPSEC_QUERY_STATS"));
  410. dwSize = sizeof(IPSEC_QUERY_STATS);
  411. if (outputBufferLength < dwSize) {
  412. status = STATUS_BUFFER_TOO_SMALL;
  413. break;
  414. }
  415. *((PIPSEC_QUERY_STATS)pvIoBuffer) = g_ipsec.Statistics;
  416. status = STATUS_SUCCESS;
  417. break;
  418. }
  419. case IOCTL_IPSEC_ADD_SA: {
  420. //
  421. // Adds the SA to the relevant database.
  422. // Typically used to add outbound SAs to the DB.
  423. //
  424. IPSEC_DEBUG(LL_A, DBF_IOCTL, ("IOCTL_IPSEC_ADD_SA"));
  425. //
  426. // The minimum size is without any Keys
  427. //
  428. dwSize = IPSEC_ADD_SA_NO_KEY_SIZE;
  429. if (inputBufferLength < dwSize) {
  430. status = STATUS_BUFFER_TOO_SMALL;
  431. break;
  432. }
  433. status = IPSecAddSA((PIPSEC_ADD_SA)pvIoBuffer, inputBufferLength);
  434. ASSERT(status != STATUS_PENDING);
  435. if (outputBufferLength >= sizeof(NTSTATUS)) {
  436. (*(NTSTATUS *)pvIoBuffer) = status;
  437. dwSize = sizeof(NTSTATUS);
  438. } else {
  439. dwSize = 0;
  440. }
  441. status = STATUS_SUCCESS;
  442. break;
  443. }
  444. case IOCTL_IPSEC_UPDATE_SA: {
  445. //
  446. // This completes the negotiation kicked off via the Acquire.
  447. //
  448. // Adds the SA to the relevant database.
  449. // Typically used to complete inbound SA acquisitions.
  450. //
  451. IPSEC_DEBUG(LL_A, DBF_IOCTL, ("IOCTL_IPSEC_UPDATE_SA"));
  452. //
  453. // The minimum size is without any Keys
  454. //
  455. dwSize = IPSEC_UPDATE_SA_NO_KEY_SIZE;
  456. if (inputBufferLength < dwSize) {
  457. status = STATUS_BUFFER_TOO_SMALL;
  458. break;
  459. }
  460. status = IPSecUpdateSA((PIPSEC_UPDATE_SA)pvIoBuffer, inputBufferLength);
  461. ASSERT(status != STATUS_PENDING);
  462. if (outputBufferLength >= sizeof(NTSTATUS)) {
  463. (*(NTSTATUS *)pvIoBuffer)=status;
  464. dwSize = sizeof(NTSTATUS);
  465. } else {
  466. dwSize = 0;
  467. }
  468. status = STATUS_SUCCESS;
  469. break;
  470. }
  471. case IOCTL_IPSEC_EXPIRE_SA: {
  472. //
  473. // Deref the particular SA - delete when ref cnt drops to 0.
  474. //
  475. IPSEC_DEBUG(LL_A, DBF_IOCTL, ("IOCTL_IPSEC_EXPIRE_SA"));
  476. dwSize = sizeof(IPSEC_EXPIRE_SA);
  477. if (inputBufferLength < dwSize) {
  478. status = STATUS_BUFFER_TOO_SMALL;
  479. break;
  480. }
  481. status = IPSecExpireSA((PIPSEC_EXPIRE_SA)pvIoBuffer);
  482. break;
  483. }
  484. case IOCTL_IPSEC_GET_SPI: {
  485. //
  486. // returns the SPI for an inbound SA
  487. //
  488. IPSEC_DEBUG(LL_A, DBF_IOCTL, ("IOCTL_IPSEC_GET_SPI"));
  489. dwSize = sizeof(IPSEC_GET_SPI);
  490. if (outputBufferLength < dwSize) {
  491. status = STATUS_BUFFER_TOO_SMALL;
  492. break;
  493. }
  494. status = IPSecGetSPI((PIPSEC_GET_SPI)pvIoBuffer);
  495. break;
  496. }
  497. case IOCTL_IPSEC_POST_FOR_ACQUIRE_SA: {
  498. //
  499. // The SAAPI client posts a request that we complete when
  500. // an SA needs to be initialized or updated (due to
  501. // re-key).
  502. // We keep the Irp around until we need an SA to be
  503. // negotiated.
  504. //
  505. IPSEC_DEBUG(LL_A, DBF_IOCTL, ("IPSEC_POST_FOR_ACQUIRE_SA"));
  506. dwSize = sizeof(IPSEC_POST_FOR_ACQUIRE_SA);
  507. if (outputBufferLength < dwSize) {
  508. IPSEC_DEBUG(LL_A, DBF_IOCTL, ("IPSEC_POST_FOR_ACQUIRE_SA: bad size: dwSize: %lx, input: %lx",
  509. dwSize, inputBufferLength));
  510. status = STATUS_BUFFER_TOO_SMALL;
  511. break;
  512. }
  513. Irp->IoStatus.Status = STATUS_PENDING;
  514. status = IPSecHandleAcquireRequest( Irp,
  515. (PIPSEC_POST_FOR_ACQUIRE_SA)pvIoBuffer);
  516. if (status == STATUS_PENDING) {
  517. IPSEC_DECREMENT(g_ipsec.NumIoctls);
  518. return status;
  519. }
  520. break;
  521. }
  522. case IOCTL_IPSEC_QUERY_EXPORT: {
  523. //
  524. // Queries whether the driver is built for export. Used by the IPSEC components
  525. // to decide what key lengths to use for encryption.
  526. //
  527. IPSEC_DEBUG(LL_A, DBF_IOCTL, ("IPSEC_QUERY_EXPORT"));
  528. dwSize = sizeof(IPSEC_QUERY_EXPORT);
  529. if (outputBufferLength < dwSize) {
  530. IPSEC_DEBUG(LL_A, DBF_IOCTL, ("IPSEC_QUERY_EXPORT: bad size: dwSize: %lx, input: %lx",
  531. dwSize, inputBufferLength));
  532. status = STATUS_BUFFER_TOO_SMALL;
  533. break;
  534. }
  535. ((PIPSEC_QUERY_EXPORT)pvIoBuffer)->Export = FALSE;
  536. status = STATUS_SUCCESS;
  537. break;
  538. }
  539. case IOCTL_IPSEC_QUERY_SPI: {
  540. IPSEC_DEBUG(LL_A, DBF_IOCTL, ("Entered Query SPI"));
  541. dwSize = sizeof(IPSEC_QUERY_SPI);
  542. if (inputBufferLength < dwSize) {
  543. IPSEC_DEBUG(LL_A, DBF_IOCTL, ("IPSEC_QUERY_SPI: bad size: dwSize: %lx, input: %lx",
  544. dwSize, inputBufferLength));
  545. status = STATUS_BUFFER_TOO_SMALL;
  546. break;
  547. }
  548. status = IPSecQuerySpi((PIPSEC_QUERY_SPI)pvIoBuffer);
  549. break;
  550. }
  551. case IOCTL_IPSEC_DELETE_SA: {
  552. IPSEC_DEBUG(LL_A, DBF_IOCTL, ("Entered Delete SA"));
  553. dwSize = sizeof(IPSEC_DELETE_SA);
  554. if (inputBufferLength < dwSize) {
  555. IPSEC_DEBUG(LL_A, DBF_IOCTL, ("IPSEC_DELETE_SA: bad size: dwSize: %lx, input: %lx",
  556. dwSize, inputBufferLength));
  557. status = STATUS_BUFFER_TOO_SMALL;
  558. break;
  559. }
  560. status = IPSecDeleteSA((PIPSEC_DELETE_SA)pvIoBuffer);
  561. break;
  562. }
  563. case IOCTL_IPSEC_SET_OPERATION_MODE: {
  564. OPERATION_MODE LastMode = g_ipsec.OperationMode;
  565. IPSEC_DEBUG(LL_A, DBF_IOCTL, ("Entered Set Operation Mode"));
  566. dwSize = sizeof(IPSEC_SET_OPERATION_MODE);
  567. if (inputBufferLength < dwSize) {
  568. IPSEC_DEBUG(LL_A, DBF_IOCTL, ("IPSEC_SET_OPERATION_MODE: bad size: dwSize: %lx, input: %lx",
  569. dwSize, inputBufferLength));
  570. status = STATUS_BUFFER_TOO_SMALL;
  571. break;
  572. }
  573. status = IPSecSetOperationMode((PIPSEC_SET_OPERATION_MODE)pvIoBuffer);
  574. if (IPSEC_BOOTTIME_STATEFUL_MODE == LastMode)
  575. {
  576. LARGE_INTEGER CurTime;
  577. LARGE_INTEGER Delta;
  578. NdisGetCurrentSystemTime(&CurTime);
  579. IPSecCleanupBoottimeStatefulStructs();
  580. Delta = RtlLargeIntegerSubtract(CurTime,g_ipsec.StartTimeDelta);
  581. IPSEC_DEBUG(LL_A,DBF_BOOTTIME,("Delta %d %d",Delta.HighPart,Delta.LowPart));
  582. }
  583. break;
  584. }
  585. case IOCTL_IPSEC_GET_OPERATION_MODE: {
  586. OPERATION_MODE CurrentMode = g_ipsec.OperationMode;
  587. dwSize = sizeof(IPSEC_GET_OPERATION_MODE);
  588. if (outputBufferLength< dwSize) {
  589. IPSEC_DEBUG(LL_A, DBF_IOCTL, ("IPSEC_SET_OPERATION_MODE: bad size: dwSize: %lx, input: %lx",
  590. dwSize, inputBufferLength));
  591. status = STATUS_BUFFER_TOO_SMALL;
  592. break;
  593. }
  594. ((PIPSEC_SET_OPERATION_MODE)pvIoBuffer)->OperationMode = CurrentMode;
  595. break;
  596. }
  597. case IOCTL_IPSEC_SET_DIAGNOSTIC_MODE: {
  598. DWORD Mode;
  599. DWORD LogInterval;
  600. // Initialize the return status
  601. status = STATUS_SUCCESS;
  602. dwSize = sizeof (IPSEC_SET_DIAGNOSTIC_MODE);
  603. // Check Input Buffer Length
  604. if (inputBufferLength < dwSize) {
  605. IPSEC_DEBUG(LL_A, DBF_IOCTL, ("IPSEC_SET_DIAGNOSTIC_MODE : bad size: dwSize : %lx, input %lx",
  606. dwSize, inputBufferLength));
  607. status = STATUS_BUFFER_TOO_SMALL;
  608. break;
  609. }
  610. // Get the input Parameters
  611. Mode = ((PIPSEC_SET_DIAGNOSTIC_MODE)pvIoBuffer)->Mode;
  612. LogInterval = ((PIPSEC_SET_DIAGNOSTIC_MODE)pvIoBuffer)->LogInterval;
  613. // Validate the diagnostic mode : Fail IOCTL if invalid
  614. if (Mode > IPSEC_DIAGNOSTIC_MAX ){
  615. status = STATUS_INVALID_PARAMETER;
  616. break;
  617. }
  618. // Set the Diagnostic Mode
  619. g_ipsec.DiagnosticMode = Mode;
  620. // If LogInterval = 0 then dont change log interval
  621. if ( IPSEC_NOCHANGE_LOG_INTERVAL == LogInterval){
  622. break;
  623. }
  624. // Default to MIN and MAX limits
  625. if (IPSEC_MIN_LOG_INTERVAL > LogInterval ){
  626. LogInterval = IPSEC_MIN_LOG_INTERVAL;
  627. }
  628. if (IPSEC_MAX_LOG_INTERVAL < LogInterval ){
  629. LogInterval = IPSEC_MAX_LOG_INTERVAL;
  630. }
  631. // Set the Log Interval
  632. g_ipsec.LogInterval = LogInterval;
  633. break;
  634. }
  635. case IOCTL_IPSEC_SET_TCPIP_STATUS: {
  636. IPSEC_DEBUG(LL_A, DBF_IOCTL, ("Entered Set Tcpip Status"));
  637. if (Irp->RequestorMode != KernelMode) {
  638. status = STATUS_ACCESS_DENIED;
  639. break;
  640. }
  641. dwSize = sizeof(IPSEC_SET_TCPIP_STATUS);
  642. if (inputBufferLength < dwSize) {
  643. IPSEC_DEBUG(LL_A, DBF_IOCTL, ("IPSEC_SET_TCPIP_STATUS: bad size: dwSize: %lx, input: %lx",
  644. dwSize, inputBufferLength));
  645. status = STATUS_BUFFER_TOO_SMALL;
  646. break;
  647. }
  648. status = IPSecSetTcpipStatus((PIPSEC_SET_TCPIP_STATUS)pvIoBuffer);
  649. break;
  650. }
  651. case IOCTL_IPSEC_REGISTER_PROTOCOL: {
  652. dwSize = sizeof(IPSEC_REGISTER_PROTOCOL);
  653. if (inputBufferLength < dwSize) {
  654. status = STATUS_BUFFER_TOO_SMALL;
  655. break;
  656. }
  657. status = IPSecRegisterProtocols(
  658. (PIPSEC_REGISTER_PROTOCOL) pvIoBuffer
  659. );
  660. break;
  661. }
  662. default: {
  663. status = STATUS_INVALID_PARAMETER;
  664. break;
  665. }
  666. }
  667. IPSEC_DECREMENT(g_ipsec.NumIoctls);
  668. break ;
  669. }
  670. default: {
  671. IPSEC_DEBUG(LL_A, DBF_IOCTL, ("IPSEC: unknown IRP_MJ_XXX: %lx", irpStack->MajorFunction));
  672. status = STATUS_INVALID_PARAMETER;
  673. break;
  674. }
  675. }
  676. ASSERT(status != STATUS_PENDING);
  677. ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
  678. Irp->IoStatus.Status = status;
  679. Irp->IoStatus.Information = MIN(dwSize, outputBufferLength);
  680. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  681. IPSEC_DEBUG(LL_A, DBF_IOCTL, ("Exiting IPSecDispath"));
  682. return status;
  683. }
  684. NTSTATUS
  685. IPSecBindToIP()
  686. /*++
  687. Routine Description:
  688. This bind exchanges a number of entrypoints with IP so that
  689. - packets relevant to IPSEC can be handed over from the IP driver.
  690. - buffered packets can be flushed.
  691. - SA Table indices can be plumbed.
  692. - ....
  693. Arguments:
  694. NONE
  695. Return Value:
  696. The function value is the final status from the bind operation.
  697. --*/
  698. {
  699. NTSTATUS status;
  700. IPSEC_FUNCTIONS ipsecFns;
  701. PAGED_CODE();
  702. IPSEC_DEBUG(LL_A, DBF_LOAD, ("Entering IPSecBindToIP"));
  703. ipsecFns.Version = IP_IPSEC_BIND_VERSION;
  704. ipsecFns.IPSecHandler = IPSecHandlePacket;
  705. ipsecFns.IPSecQStatus = IPSecQueryStatus;
  706. ipsecFns.IPSecSendCmplt = IPSecSendComplete;
  707. ipsecFns.IPSecNdisStatus = IPSecNdisStatus;
  708. ipsecFns.IPSecRcvFWPacket = IPSecRcvFWPacket;
  709. status = TCPIP_SET_IPSEC(&ipsecFns);
  710. if (status != IP_SUCCESS) {
  711. IPSEC_DEBUG(LL_A, DBF_LOAD, ("Failed to bind to IP: %lx", status));
  712. } else {
  713. IPSEC_DRIVER_BOUND() = TRUE;
  714. IPSEC_DRIVER_SEND_BOUND() = TRUE;
  715. }
  716. IPSEC_DEBUG(LL_A, DBF_LOAD, ("Exiting IPSecBindToIP"));
  717. return status;
  718. }
  719. NTSTATUS
  720. IPSecUnbindFromIP()
  721. /*++
  722. Routine Description:
  723. This unbinds from the Filter Driver
  724. Arguments:
  725. NONE
  726. Return Value:
  727. The function value is the final status from the bind operation.
  728. --*/
  729. {
  730. NTSTATUS status;
  731. IPSEC_FUNCTIONS ipsecFns={0};
  732. PAGED_CODE();
  733. IPSEC_DEBUG(LL_A, DBF_LOAD, ("Entering IPSecUnbindFromIP"));
  734. ipsecFns.Version = IP_IPSEC_BIND_VERSION;
  735. status = TCPIP_UNSET_IPSEC(&ipsecFns);
  736. if (status != IP_SUCCESS) {
  737. IPSEC_DEBUG(LL_A, DBF_LOAD, ("Failed to bind to IP: %lx", status));
  738. } else {
  739. IPSEC_DRIVER_BOUND() = FALSE;
  740. }
  741. IPSEC_DEBUG(LL_A, DBF_LOAD, ("Exiting IPSecUnbindFromIP"));
  742. return status;
  743. }
  744. NTSTATUS
  745. IPSecUnbindSendFromIP()
  746. /*++
  747. Routine Description:
  748. Unbinds just the send handler from IP
  749. Arguments:
  750. NONE
  751. Return Value:
  752. The function value is the final status from the bind operation.
  753. --*/
  754. {
  755. NTSTATUS status;
  756. IPSEC_FUNCTIONS ipsecFns={0};
  757. PAGED_CODE();
  758. IPSEC_DEBUG(LL_A, DBF_LOAD, ("Entering IPSecUnbindSendFromIP"));
  759. ipsecFns.Version = IP_IPSEC_BIND_VERSION;
  760. status = TCPIP_UNSET_IPSEC_SEND(&ipsecFns);
  761. if (status != IP_SUCCESS) {
  762. IPSEC_DEBUG(LL_A, DBF_LOAD, ("Failed to bind to IP: %lx", status));
  763. } else {
  764. IPSEC_DRIVER_SEND_BOUND() = FALSE;
  765. }
  766. IPSEC_DEBUG(LL_A, DBF_LOAD, ("Exiting IPSecUnbindSendFromIP"));
  767. return status;
  768. }
  769. NTSTATUS
  770. OpenRegKey(
  771. PHANDLE HandlePtr,
  772. PWCHAR KeyName
  773. )
  774. /*++
  775. Routine Description:
  776. Opens a Registry key and returns a handle to it.
  777. Arguments:
  778. HandlePtr - The varible into which to write the opened handle.
  779. KeyName - The name of the Registry key to open.
  780. Return Value:
  781. STATUS_SUCCESS or an appropriate failure code.
  782. --*/
  783. {
  784. NTSTATUS Status;
  785. OBJECT_ATTRIBUTES ObjectAttributes;
  786. UNICODE_STRING UKeyName;
  787. PAGED_CODE();
  788. RtlInitUnicodeString(&UKeyName, KeyName);
  789. memset(&ObjectAttributes, 0, sizeof(OBJECT_ATTRIBUTES));
  790. InitializeObjectAttributes(&ObjectAttributes,
  791. &UKeyName,
  792. OBJ_CASE_INSENSITIVE,
  793. NULL,
  794. NULL);
  795. Status = ZwOpenKey(HandlePtr,
  796. KEY_READ,
  797. &ObjectAttributes);
  798. return Status;
  799. }
  800. NTSTATUS
  801. GetRegDWORDValue(
  802. HANDLE KeyHandle,
  803. PWCHAR ValueName,
  804. PULONG ValueData
  805. )
  806. /*++
  807. Routine Description:
  808. Reads a REG_DWORD value from the registry into the supplied variable.
  809. Arguments:
  810. KeyHandle - Open handle to the parent key of the value to read.
  811. ValueName - The name of the value to read.
  812. ValueData - The variable into which to read the data.
  813. Return Value:
  814. STATUS_SUCCESS or an appropriate failure code.
  815. --*/
  816. {
  817. NTSTATUS status;
  818. ULONG resultLength;
  819. PKEY_VALUE_FULL_INFORMATION keyValueFullInformation;
  820. UCHAR keybuf[WORK_BUFFER_SIZE];
  821. UNICODE_STRING UValueName;
  822. PAGED_CODE();
  823. RtlInitUnicodeString(&UValueName, ValueName);
  824. keyValueFullInformation = (PKEY_VALUE_FULL_INFORMATION)keybuf;
  825. RtlZeroMemory(keyValueFullInformation, sizeof(keyValueFullInformation));
  826. status = ZwQueryValueKey(KeyHandle,
  827. &UValueName,
  828. KeyValueFullInformation,
  829. keyValueFullInformation,
  830. WORK_BUFFER_SIZE,
  831. &resultLength);
  832. if (NT_SUCCESS(status)) {
  833. if (keyValueFullInformation->Type != REG_DWORD) {
  834. status = STATUS_INVALID_PARAMETER_MIX;
  835. } else {
  836. *ValueData = *((ULONG UNALIGNED *)((PCHAR)keyValueFullInformation +
  837. keyValueFullInformation->DataOffset));
  838. }
  839. }
  840. return status;
  841. }
  842. NTSTATUS
  843. GetRegStringValue(
  844. HANDLE KeyHandle,
  845. PWCHAR ValueName,
  846. PKEY_VALUE_PARTIAL_INFORMATION *ValueData,
  847. PUSHORT ValueSize
  848. )
  849. /*++
  850. Routine Description:
  851. Reads a REG_*_SZ string value from the Registry into the supplied
  852. key value buffer. If the buffer string buffer is not large enough,
  853. it is reallocated.
  854. Arguments:
  855. KeyHandle - Open handle to the parent key of the value to read.
  856. ValueName - The name of the value to read.
  857. ValueData - Destination for the read data.
  858. ValueSize - Size of the ValueData buffer. Updated on output.
  859. Return Value:
  860. STATUS_SUCCESS or an appropriate failure code.
  861. --*/
  862. {
  863. NTSTATUS status;
  864. ULONG resultLength;
  865. UNICODE_STRING UValueName;
  866. PAGED_CODE();
  867. RtlInitUnicodeString(&UValueName, ValueName);
  868. status = ZwQueryValueKey(
  869. KeyHandle,
  870. &UValueName,
  871. KeyValuePartialInformation,
  872. *ValueData,
  873. (ULONG) *ValueSize,
  874. &resultLength
  875. );
  876. if ( (status == STATUS_BUFFER_OVERFLOW) ||
  877. (status == STATUS_BUFFER_TOO_SMALL)
  878. )
  879. {
  880. PVOID temp;
  881. //
  882. // Free the old buffer and allocate a new one of the
  883. // appropriate size.
  884. //
  885. ASSERT(resultLength > (ULONG) *ValueSize);
  886. if (resultLength <= 0xFFFF) {
  887. temp = IPSecAllocateMemory(resultLength, IPSEC_TAG_IOCTL);
  888. if (temp != NULL) {
  889. if (*ValueData != NULL) {
  890. IPSecFreeMemory(*ValueData);
  891. }
  892. *ValueData = temp;
  893. *ValueSize = (USHORT) resultLength;
  894. status = ZwQueryValueKey(KeyHandle,
  895. &UValueName,
  896. KeyValuePartialInformation,
  897. *ValueData,
  898. *ValueSize,
  899. &resultLength
  900. );
  901. ASSERT( (status != STATUS_BUFFER_OVERFLOW) &&
  902. (status != STATUS_BUFFER_TOO_SMALL)
  903. );
  904. }
  905. else {
  906. status = STATUS_INSUFFICIENT_RESOURCES;
  907. }
  908. }
  909. else {
  910. status = STATUS_BUFFER_TOO_SMALL;
  911. }
  912. }
  913. return status;
  914. }
  915. NTSTATUS
  916. GetRegBinaryValue(
  917. HANDLE KeyHandle,
  918. PWCHAR ValueName,
  919. PKEY_VALUE_PARTIAL_INFORMATION *ValueData,
  920. PUSHORT ValueSize
  921. )
  922. /*++
  923. Routine Description:
  924. Reads a binary from the Registry into the supplied
  925. key value buffer. If the buffer is not large enough,
  926. it is reallocated.
  927. Arguments:
  928. KeyHandle - Open handle to the parent key of the value to read.
  929. ValueName - The name of the value to read.
  930. ValueData - Destination for the read data.
  931. ValueSize - Size of the ValueData buffer. Updated on output.
  932. Return Value:
  933. STATUS_SUCCESS or an appropriate failure code.
  934. --*/
  935. {
  936. NTSTATUS status;
  937. ULONG resultLength;
  938. UNICODE_STRING UValueName;
  939. PAGED_CODE();
  940. RtlInitUnicodeString(&UValueName, ValueName);
  941. status = ZwQueryValueKey(
  942. KeyHandle,
  943. &UValueName,
  944. KeyValuePartialInformation,
  945. *ValueData,
  946. (ULONG) *ValueSize,
  947. &resultLength
  948. );
  949. if ( (status == STATUS_BUFFER_OVERFLOW) ||
  950. (status == STATUS_BUFFER_TOO_SMALL)
  951. )
  952. {
  953. PVOID temp;
  954. //
  955. // Free the old buffer and allocate a new one of the
  956. // appropriate size.
  957. //
  958. ASSERT(resultLength > (ULONG) *ValueSize);
  959. if (resultLength <= 0xFFFF) {
  960. temp = IPSecAllocateMemory(resultLength, IPSEC_TAG_IOCTL);
  961. if (temp != NULL) {
  962. if (*ValueData != NULL) {
  963. IPSecFreeMemory(*ValueData);
  964. }
  965. *ValueData = temp;
  966. *ValueSize = (USHORT) resultLength;
  967. status = ZwQueryValueKey(KeyHandle,
  968. &UValueName,
  969. KeyValuePartialInformation,
  970. *ValueData,
  971. *ValueSize,
  972. &resultLength
  973. );
  974. ASSERT( (status != STATUS_BUFFER_OVERFLOW) &&
  975. (status != STATUS_BUFFER_TOO_SMALL)
  976. );
  977. }
  978. else {
  979. status = STATUS_INSUFFICIENT_RESOURCES;
  980. }
  981. }
  982. else {
  983. status = STATUS_BUFFER_TOO_SMALL;
  984. }
  985. }
  986. return status;
  987. }
  988. NTSTATUS
  989. GetRegMultiSZValue(
  990. HANDLE KeyHandle,
  991. PWCHAR ValueName,
  992. PUNICODE_STRING ValueData
  993. )
  994. /*++
  995. Routine Description:
  996. Reads a REG_MULTI_SZ string value from the Registry into the supplied
  997. Unicode string. If the Unicode string buffer is not large enough,
  998. it is reallocated.
  999. Arguments:
  1000. KeyHandle - Open handle to the parent key of the value to read.
  1001. ValueName - The name of the value to read.
  1002. ValueData - Destination Unicode string for the value data.
  1003. Return Value:
  1004. STATUS_SUCCESS or an appropriate failure code.
  1005. --*/
  1006. {
  1007. NTSTATUS status;
  1008. ULONG resultLength;
  1009. PKEY_VALUE_PARTIAL_INFORMATION keyValuePartialInformation;
  1010. UNICODE_STRING UValueName;
  1011. PAGED_CODE();
  1012. ValueData->Length = 0;
  1013. status = GetRegStringValue(
  1014. KeyHandle,
  1015. ValueName,
  1016. (PKEY_VALUE_PARTIAL_INFORMATION *) &(ValueData->Buffer),
  1017. &(ValueData->MaximumLength)
  1018. );
  1019. if (NT_SUCCESS(status)) {
  1020. keyValuePartialInformation =
  1021. (PKEY_VALUE_PARTIAL_INFORMATION) ValueData->Buffer;
  1022. if (keyValuePartialInformation->Type == REG_MULTI_SZ) {
  1023. ValueData->Length = (USHORT)
  1024. keyValuePartialInformation->DataLength;
  1025. RtlCopyMemory(
  1026. ValueData->Buffer,
  1027. &(keyValuePartialInformation->Data),
  1028. ValueData->Length
  1029. );
  1030. }
  1031. else {
  1032. status = STATUS_INVALID_PARAMETER_MIX;
  1033. }
  1034. }
  1035. return status;
  1036. } // GetRegMultiSZValue
  1037. VOID
  1038. IPSecReadRegistry()
  1039. /*++
  1040. Routine Description:
  1041. Reads config info from registry into g_ipsec
  1042. Arguments:
  1043. Return Value:
  1044. status of the read.
  1045. --*/
  1046. {
  1047. NTSTATUS status;
  1048. HANDLE hRegKey;
  1049. WCHAR IPSecParametersRegistryKey[] = IPSEC_REG_KEY;
  1050. BOOLEAN isAs = MmIsThisAnNtAsSystem();
  1051. g_ipsec.EnableOffload = IPSEC_DEFAULT_ENABLE_OFFLOAD;
  1052. g_ipsec.DefaultSAIdleTime = IPSEC_DEFAULT_SA_IDLE_TIME;
  1053. g_ipsec.LogInterval = IPSEC_DEFAULT_LOG_INTERVAL;
  1054. g_ipsec.EventQueueSize = IPSEC_DEFAULT_EVENT_QUEUE_SIZE;
  1055. g_ipsec.RekeyTime = IPSEC_DEFAULT_REKEY;
  1056. g_ipsec.NoDefaultExempt = IPSEC_DEFAULT_NO_DEFAULT_EXEMPT;
  1057. g_ipsec.OperationMode = IPSEC_BLOCK_MODE;
  1058. g_ipsec.DiagnosticMode = IPSEC_DEFAULT_ENABLE_DIAGNOSTICS;
  1059. if (isAs) {
  1060. g_ipsec.CacheSize = IPSEC_DEFAULT_AS_CACHE_SIZE;
  1061. g_ipsec.SAHashSize = IPSEC_DEFAULT_AS_SA_HASH_SIZE;
  1062. } else {
  1063. g_ipsec.CacheSize = IPSEC_DEFAULT_CACHE_SIZE;
  1064. g_ipsec.SAHashSize = IPSEC_DEFAULT_SA_HASH_SIZE;
  1065. }
  1066. status = OpenRegKey(&hRegKey,
  1067. IPSecParametersRegistryKey);
  1068. if (NT_SUCCESS(status)) {
  1069. //
  1070. // Expected configuration values. We use reasonable defaults if they
  1071. // aren't available for some reason.
  1072. //
  1073. IPSecRegReadDword( hRegKey,
  1074. IPSEC_REG_PARAM_ENABLE_OFFLOAD,
  1075. &g_ipsec.EnableOffload,
  1076. IPSEC_DEFAULT_ENABLE_OFFLOAD,
  1077. IPSEC_MAX_ENABLE_OFFLOAD,
  1078. IPSEC_MIN_ENABLE_OFFLOAD);
  1079. IPSecRegReadDword( hRegKey,
  1080. IPSEC_REG_PARAM_SA_IDLE_TIME,
  1081. &g_ipsec.DefaultSAIdleTime,
  1082. IPSEC_DEFAULT_SA_IDLE_TIME,
  1083. IPSEC_MAX_SA_IDLE_TIME,
  1084. IPSEC_MIN_SA_IDLE_TIME);
  1085. IPSecRegReadDword( hRegKey,
  1086. IPSEC_REG_PARAM_EVENT_QUEUE_SIZE,
  1087. &g_ipsec.EventQueueSize,
  1088. IPSEC_DEFAULT_EVENT_QUEUE_SIZE,
  1089. IPSEC_MAX_EVENT_QUEUE_SIZE,
  1090. IPSEC_MIN_EVENT_QUEUE_SIZE);
  1091. IPSecRegReadDword( hRegKey,
  1092. IPSEC_REG_PARAM_LOG_INTERVAL,
  1093. &g_ipsec.LogInterval,
  1094. IPSEC_DEFAULT_LOG_INTERVAL,
  1095. IPSEC_MAX_LOG_INTERVAL,
  1096. IPSEC_MIN_LOG_INTERVAL);
  1097. IPSecRegReadDword( hRegKey,
  1098. IPSEC_REG_PARAM_REKEY_TIME,
  1099. &g_ipsec.RekeyTime,
  1100. IPSEC_DEFAULT_REKEY,
  1101. IPSEC_MAX_REKEY,
  1102. IPSEC_MIN_REKEY);
  1103. IPSecRegReadDword( hRegKey,
  1104. IPSEC_REG_PARAM_CACHE_SIZE,
  1105. &g_ipsec.CacheSize,
  1106. isAs? IPSEC_DEFAULT_AS_CACHE_SIZE:
  1107. IPSEC_DEFAULT_CACHE_SIZE,
  1108. IPSEC_MAX_CACHE_SIZE,
  1109. IPSEC_MIN_CACHE_SIZE);
  1110. IPSecRegReadDword( hRegKey,
  1111. IPSEC_REG_PARAM_SA_HASH_SIZE,
  1112. &g_ipsec.SAHashSize,
  1113. isAs? IPSEC_DEFAULT_AS_SA_HASH_SIZE:
  1114. IPSEC_DEFAULT_SA_HASH_SIZE,
  1115. IPSEC_MAX_SA_HASH_SIZE,
  1116. IPSEC_MIN_SA_HASH_SIZE);
  1117. IPSecRegReadDword( hRegKey,
  1118. IPSEC_REG_PARAM_NO_DEFAULT_EXEMPT,
  1119. &g_ipsec.NoDefaultExempt,
  1120. IPSEC_DEFAULT_NO_DEFAULT_EXEMPT,
  1121. IPSEC_MAX_NO_DEFAULT_EXEMPT,
  1122. IPSEC_MIN_NO_DEFAULT_EXEMPT);
  1123. IPSecRegReadDword( hRegKey,
  1124. IPSEC_REG_PARAM_ENABLE_DIAGNOSTICS,
  1125. &g_ipsec.DiagnosticMode,
  1126. IPSEC_DEFAULT_ENABLE_DIAGNOSTICS,
  1127. IPSEC_MAX_ENABLE_DIAGNOSTICS,
  1128. IPSEC_MIN_ENABLE_DIAGNOSTICS);
  1129. IPSecRegReadDwordEx( hRegKey,
  1130. IPSEC_REG_PARAM_OPERATION_MODE,
  1131. &(ULONG)g_ipsec.OperationMode,
  1132. IPSEC_OPERATION_MODE_MAX-1, // Max valid value
  1133. 0, //Min valid value
  1134. IPSEC_BYPASS_MODE,//Key not exist
  1135. IPSEC_BLOCK_MODE, // Error in reading the key
  1136. IPSEC_BLOCK_MODE);// Key value out of range
  1137. IPSecRegReadDwordEx(hRegKey,
  1138. IPSEC_REG_PARAM_DFLT_FWDING_BEHAVIOR,
  1139. &(ULONG)g_ipsec.DefaultForwardingBehavior,
  1140. IPSEC_FORWARD_MAX-1,//Max valid
  1141. 0,
  1142. IPSEC_FORWARD_BLOCK,//Key not exist
  1143. IPSEC_FORWARD_BLOCK,// Error in reading
  1144. IPSEC_FORWARD_BLOCK);//Value out of range
  1145. ZwClose(hRegKey);
  1146. }
  1147. g_ipsec.CacheHalfSize = g_ipsec.CacheSize / 2;
  1148. //
  1149. // Init SAIdleTime for low memory reaper
  1150. //
  1151. IPSEC_CONVERT_SECS_TO_100NS(g_ipsec.SAIdleTime, g_ipsec.DefaultSAIdleTime);
  1152. if (IS_DRIVER_BLOCK() || IS_DRIVER_BOOTSTATEFUL()) {
  1153. // Make sure SPD will be starting
  1154. ULONG SPDStart=0;
  1155. WCHAR SPDParametersRegistryKey[] = SPD_REG_KEY;
  1156. status = OpenRegKey(&hRegKey,
  1157. SPDParametersRegistryKey);
  1158. if (NT_SUCCESS(status)) {
  1159. IPSecRegReadDword( hRegKey,
  1160. SPD_REG_PARAM_START,
  1161. &SPDStart,
  1162. 0,
  1163. 4,
  1164. 0);
  1165. if (SPDStart != 2) {
  1166. g_ipsec.OperationMode = IPSEC_BYPASS_MODE;
  1167. }
  1168. ZwClose(hRegKey);
  1169. } else {
  1170. g_ipsec.OperationMode = IPSEC_BYPASS_MODE;
  1171. }
  1172. }
  1173. IPSEC_DEBUG(LL_A,DBF_BOOTTIME,("IPSEC BOOT MODE %d\n",g_ipsec.OperationMode));
  1174. //
  1175. // Log the boot mode to the system event log
  1176. //
  1177. IPSecLogBootOperationMode();
  1178. }
  1179. NTSTATUS IPSecConvertRegExemptPolicy(
  1180. PKEY_VALUE_PARTIAL_INFORMATION pKeyData,
  1181. PIPSEC_EXEMPT_ENTRY *pBootExemptList,
  1182. ULONG *pBootExemptListSize
  1183. )
  1184. {
  1185. ULONG i;
  1186. LONG DataLeft = pKeyData->DataLength;
  1187. PIPSEC_EXEMPT_ENTRY pCurEntry;
  1188. ULONG TotalEntries=0;
  1189. ULONG CurIndex=0;
  1190. pCurEntry = (PIPSEC_EXEMPT_ENTRY)&(pKeyData->Data[0]);
  1191. while (DataLeft >= (LONG)sizeof(IPSEC_EXEMPT_ENTRY)) {
  1192. if ((pCurEntry->Type == EXEMPT_TYPE_PDP) &&
  1193. ((pCurEntry->Direction == EXEMPT_DIRECTION_INBOUND) ||
  1194. (pCurEntry->Direction == EXEMPT_DIRECTION_OUTBOUND)) &&
  1195. (pCurEntry->Size == sizeof(IPSEC_EXEMPT_ENTRY))) {
  1196. TotalEntries++;
  1197. }
  1198. DataLeft -= pCurEntry->Size;
  1199. if (pCurEntry->Size == 0) {
  1200. break;
  1201. }
  1202. pCurEntry = (PIPSEC_EXEMPT_ENTRY) ((PBYTE)pCurEntry + pCurEntry->Size);
  1203. }
  1204. if (0 != TotalEntries ){
  1205. *pBootExemptList = (PIPSEC_EXEMPT_ENTRY)IPSecAllocateMemory(TotalEntries * sizeof(IPSEC_EXEMPT_ENTRY),
  1206. IPSEC_TAG_INIT);
  1207. }
  1208. else {
  1209. *pBootExemptList = NULL;
  1210. *pBootExemptListSize=0;
  1211. return STATUS_SUCCESS;
  1212. }
  1213. if (*pBootExemptList == NULL) {
  1214. *pBootExemptListSize=0;
  1215. return STATUS_INSUFFICIENT_RESOURCES;
  1216. }
  1217. pCurEntry = (PIPSEC_EXEMPT_ENTRY)&(pKeyData->Data[0]);
  1218. DataLeft = pKeyData->DataLength;
  1219. while (DataLeft >= (LONG)sizeof(IPSEC_EXEMPT_ENTRY)) {
  1220. if ((pCurEntry->Type == EXEMPT_TYPE_PDP) &&
  1221. ((pCurEntry->Direction == EXEMPT_DIRECTION_INBOUND) ||
  1222. (pCurEntry->Direction == EXEMPT_DIRECTION_OUTBOUND)) &&
  1223. (pCurEntry->Size == sizeof(IPSEC_EXEMPT_ENTRY))){
  1224. RtlCopyMemory(&((*pBootExemptList)[CurIndex]),pCurEntry,sizeof(IPSEC_EXEMPT_ENTRY));
  1225. IPSEC_DEBUG(LL_A,DBF_BOOTTIME,("RegSrcPort %x : RegDstPort %x",
  1226. (*pBootExemptList)[CurIndex].DestPort,(*pBootExemptList)[CurIndex].SrcPort));
  1227. (*pBootExemptList)[CurIndex].DestPort = NET_SHORT((*pBootExemptList)[CurIndex].DestPort);
  1228. (*pBootExemptList)[CurIndex].SrcPort = NET_SHORT((*pBootExemptList)[CurIndex].SrcPort);
  1229. IPSEC_DEBUG(LL_A,DBF_BOOTTIME,("Post swap RegSrcPort %x : RegDstPort %x",
  1230. (*pBootExemptList)[CurIndex].DestPort,(*pBootExemptList)[CurIndex].SrcPort));
  1231. CurIndex++;
  1232. }
  1233. DataLeft -= pCurEntry->Size;
  1234. if (pCurEntry->Size == 0) {
  1235. break;
  1236. }
  1237. pCurEntry = (PIPSEC_EXEMPT_ENTRY) ((PBYTE)pCurEntry + pCurEntry->Size);
  1238. }
  1239. *pBootExemptListSize = TotalEntries;
  1240. return STATUS_SUCCESS;
  1241. }
  1242. NTSTATUS IPSecReadExemptPolicy()
  1243. {
  1244. WCHAR IPSecParametersRegistryKey[] = IPSEC_REG_KEY;
  1245. HANDLE hRegKey = NULL;
  1246. USHORT BlobSize=0;
  1247. NTSTATUS Status;
  1248. PKEY_VALUE_PARTIAL_INFORMATION pKeyData=NULL;
  1249. Status = OpenRegKey(&hRegKey,
  1250. IPSecParametersRegistryKey);
  1251. if (!NT_SUCCESS(Status)) {
  1252. goto err;
  1253. }
  1254. Status = GetRegBinaryValue(hRegKey,
  1255. IPSEC_REG_PARAM_EXEMPT_LIST,
  1256. &pKeyData,
  1257. &BlobSize);
  1258. if (!NT_SUCCESS(Status)) {
  1259. goto err;
  1260. }
  1261. if (pKeyData->Type != REG_BINARY) {
  1262. Status = STATUS_INVALID_PARAMETER;
  1263. goto err;
  1264. }
  1265. Status = IPSecConvertRegExemptPolicy(pKeyData,
  1266. &g_ipsec.BootExemptList,
  1267. &g_ipsec.BootExemptListSize);
  1268. if (!NT_SUCCESS(Status)) {
  1269. goto err;
  1270. }
  1271. err:
  1272. if (hRegKey) {
  1273. ZwClose(hRegKey);
  1274. }
  1275. if (pKeyData) {
  1276. IPSecFreeMemory(pKeyData);
  1277. }
  1278. return Status;
  1279. }
  1280. NTSTATUS
  1281. IPSecGeneralInit()
  1282. /*++
  1283. Routine Description:
  1284. General structures are initialized here.
  1285. Arguments:
  1286. None
  1287. Return Value:
  1288. --*/
  1289. {
  1290. PSA_TABLE_ENTRY pSA;
  1291. LONG i;
  1292. NTSTATUS status = STATUS_SUCCESS;
  1293. PAGED_CODE();
  1294. IPSEC_DEBUG(LL_A, DBF_LOAD, ("Entering IPSecGeneralInit"));
  1295. NdisGetCurrentSystemTime(&g_ipsec.StartTimeDelta);
  1296. IPSEC_DEBUG(LL_A,DBF_LOAD, ("Entering IPSecGeneralInit\n"));
  1297. //
  1298. // Initialize our counters
  1299. //
  1300. g_ipsec.dwPacketsOnWrongSA = 0;
  1301. //
  1302. // init the acquireinfo struct
  1303. //
  1304. InitializeListHead(&g_ipsec.AcquireInfo.PendingAcquires);
  1305. InitializeListHead(&g_ipsec.AcquireInfo.PendingNotifies);
  1306. InitializeListHead(&g_ipsec.LarvalSAList);
  1307. INIT_LOCK(&g_ipsec.LarvalListLock);
  1308. INIT_LOCK(&g_ipsec.AcquireInfo.Lock);
  1309. //
  1310. // Set up the hashes/tables
  1311. //
  1312. InitializeMRSWLock(&g_ipsec.SADBLock);
  1313. InitializeMRSWLock(&g_ipsec.SPIListLock);
  1314. g_ipsec.IPProtInfo.pi_xmitdone = IPSecProtocolSendComplete;
  1315. g_ipsec.IPProtInfo.pi_protocol = PROTOCOL_ESP;
  1316. //
  1317. // init filter linked lists
  1318. //
  1319. for (i = MIN_FILTER; i <= MAX_FILTER; i++) {
  1320. InitializeListHead(&g_ipsec.FilterList[i]);
  1321. }
  1322. //
  1323. // SAs in a hash table, hashed by <SPI, Dest addr>
  1324. //
  1325. g_ipsec.pSADb = IPSecAllocateMemory(g_ipsec.SAHashSize * sizeof(SA_HASH), IPSEC_TAG_INIT);
  1326. if (!g_ipsec.pSADb) {
  1327. IPSEC_DEBUG(LL_A, DBF_LOAD, ("Failed to alloc SADb hash"));
  1328. return STATUS_INSUFFICIENT_RESOURCES;
  1329. }
  1330. IPSecInitFlag |= INIT_SA_DATABASE;
  1331. IPSecZeroMemory(g_ipsec.pSADb, g_ipsec.SAHashSize * sizeof(SA_HASH));
  1332. for (i = 0; i < g_ipsec.SAHashSize; i++) {
  1333. PSA_HASH Entry = &g_ipsec.pSADb[i];
  1334. InitializeListHead(&Entry->SAList);
  1335. }
  1336. //
  1337. // Initialize the MDL pools.
  1338. //
  1339. status = IPSecInitMdlPool();
  1340. if (!NT_SUCCESS (status)) {
  1341. IPSEC_DEBUG(LL_A, DBF_LOAD, ("Failed to alloc MDL pools"));
  1342. return STATUS_INSUFFICIENT_RESOURCES;
  1343. }
  1344. IPSecInitFlag |= INIT_MDL_POOLS;
  1345. //
  1346. // Initialize the cache structures.
  1347. //
  1348. if (!AllocateCacheStructures()) {
  1349. IPSEC_DEBUG(LL_A, DBF_LOAD, ("Failed to alloc cache structs"));
  1350. return STATUS_INSUFFICIENT_RESOURCES;
  1351. }
  1352. IPSecInitFlag |= INIT_CACHE_STRUCT;
  1353. //
  1354. // Allocate EventQueue memory.
  1355. //
  1356. g_ipsec.IPSecLogMemory = IPSecAllocateMemory( g_ipsec.EventQueueSize * sizeof(IPSEC_EVENT_CTX),
  1357. IPSEC_TAG_EVT_QUEUE);
  1358. if (!g_ipsec.IPSecLogMemory) {
  1359. return STATUS_INSUFFICIENT_RESOURCES;
  1360. }
  1361. IPSecInitFlag |= INIT_DEBUG_MEMORY;
  1362. g_ipsec.IPSecLogMemoryLoc = &g_ipsec.IPSecLogMemory[0];
  1363. g_ipsec.IPSecLogMemoryEnd = &g_ipsec.IPSecLogMemory[g_ipsec.EventQueueSize * sizeof(IPSEC_EVENT_CTX)];
  1364. //
  1365. // Init the timer stuff.
  1366. //
  1367. if (!IPSecInitTimer()) {
  1368. IPSEC_DEBUG(LL_A, DBF_LOAD, ("Failed to init timer"));
  1369. return STATUS_INSUFFICIENT_RESOURCES;
  1370. }
  1371. IPSecInitFlag |= INIT_TIMERS;
  1372. #if GPC
  1373. status = IPSecGpcInitialize();
  1374. if (status != STATUS_SUCCESS) {
  1375. IPSEC_DEBUG(LL_A, DBF_LOAD, ("Failed to register GPC clients"));
  1376. }
  1377. #endif
  1378. //
  1379. // Arm the reaper timer
  1380. //
  1381. IPSEC_DEBUG(LL_A, DBF_LOAD, ("Starting ReaperTimer"));
  1382. IPSecStartTimer(&g_ipsec.ReaperTimer,
  1383. IPSecReaper,
  1384. IPSEC_REAPER_TIME,
  1385. (PVOID)NULL);
  1386. //
  1387. // Start EventLog timer
  1388. //
  1389. IPSEC_DEBUG(LL_A, DBF_LOAD, ("Starting EventLogTimer"));
  1390. IPSecStartTimer(&g_ipsec.EventLogTimer,
  1391. IPSecFlushEventLog,
  1392. g_ipsec.LogInterval,
  1393. (PVOID)NULL);
  1394. IPSEC_DEBUG(LL_A, DBF_LOAD, ("Exiting IPSecGeneralInit"));
  1395. status = NsInitializeShim(IPSecDevice,
  1396. &g_ipsec.ShimFunctions);
  1397. if (status != STATUS_SUCCESS) {
  1398. IPSEC_DEBUG(LL_A, DBF_LOAD, ("Failed to init natshim"));
  1399. return status;
  1400. }
  1401. status = IPSecReadExemptPolicy();
  1402. if (!NT_SUCCESS (status)) {
  1403. IPSEC_DEBUG(LL_A,DBF_LOAD, ("Failed to read exempt policy\n"));
  1404. status = STATUS_SUCCESS;
  1405. }
  1406. //
  1407. // Initialize the boot data structures
  1408. //
  1409. g_ipsec.BootBufferPool = NULL;
  1410. g_ipsec.BootStatefulHT = NULL;
  1411. if (IPSEC_BOOTTIME_STATEFUL_MODE == g_ipsec.OperationMode){
  1412. //
  1413. // Allocate the boot time stateful exemption hash table
  1414. //
  1415. g_ipsec.BootStatefulHT = (PIPSEC_STATEFUL_HASH_TABLE)IPSecAllocateMemory(sizeof(IPSEC_STATEFUL_HASH_TABLE),
  1416. IPSEC_TAG_STATEFUL_HT);
  1417. if(g_ipsec.BootStatefulHT == NULL){
  1418. status = STATUS_INSUFFICIENT_RESOURCES;
  1419. goto exit;
  1420. }
  1421. //
  1422. // Allocate the memory pool for hash table entries
  1423. //
  1424. g_ipsec.BootBufferPool = (PIPSEC_HASH_BUFFER_POOL)IPSecAllocateMemory(sizeof(IPSEC_HASH_BUFFER_POOL),IPSEC_TAG_HASH_POOL);
  1425. if(g_ipsec.BootBufferPool == NULL){
  1426. status = STATUS_INSUFFICIENT_RESOURCES;
  1427. goto exit;
  1428. }
  1429. for (i=0;i<IPSEC_STATEFUL_HASH_TABLE_SIZE;i++){
  1430. InitializeListHead(&(g_ipsec.BootStatefulHT->Entry[i]));
  1431. }
  1432. RtlZeroMemory(g_ipsec.BootBufferPool,sizeof(IPSEC_HASH_BUFFER_POOL));
  1433. }
  1434. return STATUS_SUCCESS;
  1435. exit:
  1436. return status;
  1437. }
  1438. NTSTATUS
  1439. IPSecGeneralFree()
  1440. /*++
  1441. Routine Description:
  1442. Free general structures if IPSecGeneralInit fails.
  1443. Arguments:
  1444. None
  1445. Return Value:
  1446. --*/
  1447. {
  1448. INT index;
  1449. KIRQL kIrql;
  1450. //
  1451. // Free SA database.
  1452. //
  1453. if (IPSecInitFlag & INIT_SA_DATABASE) {
  1454. if (g_ipsec.pSADb) {
  1455. IPSecFreeMemory(g_ipsec.pSADb);
  1456. }
  1457. }
  1458. //
  1459. // Free MDL pool.
  1460. //
  1461. if (IPSecInitFlag & INIT_MDL_POOLS) {
  1462. IPSecDeinitMdlPool();
  1463. }
  1464. //
  1465. // Free cache struct.
  1466. //
  1467. if (IPSecInitFlag & INIT_CACHE_STRUCT) {
  1468. FreeExistingCache();
  1469. }
  1470. //
  1471. // Free EventQueue memory.
  1472. //
  1473. if (IPSecInitFlag & INIT_DEBUG_MEMORY) {
  1474. if (g_ipsec.IPSecLogMemory) {
  1475. IPSecFreeMemory(g_ipsec.IPSecLogMemory);
  1476. }
  1477. }
  1478. //
  1479. // Free timers allocated.
  1480. //
  1481. if (IPSecInitFlag & INIT_TIMERS) {
  1482. for (index = 0; index < IPSEC_CLASS_MAX; index++) {
  1483. IPSecFreeMemory(g_ipsec.TimerList[index].pTimers);
  1484. }
  1485. }
  1486. AcquireWriteLock(&g_ipsec.SADBLock,&kIrql);
  1487. if (g_ipsec.BootStatefulHT){
  1488. IPSecFreeMemory(g_ipsec.BootStatefulHT);
  1489. g_ipsec.BootStatefulHT = NULL;
  1490. }
  1491. if (g_ipsec.BootBufferPool){
  1492. IPSecFreeMemory(g_ipsec.BootBufferPool);
  1493. g_ipsec.BootBufferPool = NULL;
  1494. }
  1495. if (g_ipsec.BootExemptList){
  1496. IPSecFreeMemory(g_ipsec.BootExemptList);
  1497. g_ipsec.BootExemptList = NULL;
  1498. }
  1499. ReleaseWriteLock(&g_ipsec.SADBLock, kIrql);
  1500. return STATUS_SUCCESS;
  1501. }
  1502. NTSTATUS
  1503. IPSecFreeConfig()
  1504. /*++
  1505. Routine Description:
  1506. Free the SA table etc.
  1507. Arguments:
  1508. None
  1509. Return Value:
  1510. --*/
  1511. {
  1512. IPSEC_DEBUG(LL_A, DBF_LOAD, ("Entering IPSecFreeConfig"));
  1513. PAGED_CODE();
  1514. FreeExistingCache();
  1515. FreePatternDbase();
  1516. if (g_ipsec.IPSecLogMemory) {
  1517. IPSecFreeMemory(g_ipsec.IPSecLogMemory);
  1518. }
  1519. IPSEC_DEBUG(LL_A, DBF_LOAD, ("Exiting IPSecFreeConfig"));
  1520. return STATUS_SUCCESS;
  1521. }
  1522. NTSTATUS
  1523. IPSecInitMdlPool()
  1524. /*++
  1525. Routine Description:
  1526. Create the MDL pool for AH and ESP headers.
  1527. Arguments:
  1528. None
  1529. Return Value:
  1530. --*/
  1531. {
  1532. PAGED_CODE();
  1533. IPSEC_DEBUG(LL_A, DBF_LOAD, ("Entering IPSecInitMdlPool"));
  1534. g_ipsec.IPSecSmallBufferSize = IPSEC_SMALL_BUFFER_SIZE;
  1535. g_ipsec.IPSecLargeBufferSize = IPSEC_LARGE_BUFFER_SIZE;
  1536. g_ipsec.IPSecSendCompleteCtxSize = sizeof(IPSEC_SEND_COMPLETE_CONTEXT);
  1537. g_ipsec.IPSecSmallBufferListDepth = IPSEC_LIST_DEPTH;
  1538. g_ipsec.IPSecLargeBufferListDepth = IPSEC_LIST_DEPTH;
  1539. g_ipsec.IPSecSendCompleteCtxDepth = IPSEC_LIST_DEPTH;
  1540. g_ipsec.IPSecCacheLineSize = IPSEC_CACHE_LINE_SIZE;
  1541. //
  1542. // Initialize the lookaside lists.
  1543. //
  1544. g_ipsec.IPSecLookasideLists = IPSecAllocateMemory(
  1545. sizeof(*g_ipsec.IPSecLookasideLists),
  1546. IPSEC_TAG_LOOKASIDE_LISTS);
  1547. if (g_ipsec.IPSecLookasideLists == NULL) {
  1548. return STATUS_INSUFFICIENT_RESOURCES;
  1549. }
  1550. //
  1551. // Initialize the IPSEC buffer lookaside lists.
  1552. //
  1553. ExInitializeNPagedLookasideList(&g_ipsec.IPSecLookasideLists->LargeBufferList,
  1554. IPSecAllocateBufferPool,
  1555. NULL,
  1556. 0,
  1557. g_ipsec.IPSecLargeBufferSize,
  1558. IPSEC_TAG_BUFFER_POOL,
  1559. (USHORT)g_ipsec.IPSecLargeBufferListDepth);
  1560. ExInitializeNPagedLookasideList(&g_ipsec.IPSecLookasideLists->SmallBufferList,
  1561. IPSecAllocateBufferPool,
  1562. NULL,
  1563. 0,
  1564. g_ipsec.IPSecSmallBufferSize,
  1565. IPSEC_TAG_BUFFER_POOL,
  1566. (USHORT)g_ipsec.IPSecSmallBufferListDepth);
  1567. ExInitializeNPagedLookasideList(&g_ipsec.IPSecLookasideLists->SendCompleteCtxList,
  1568. NULL,
  1569. NULL,
  1570. 0,
  1571. g_ipsec.IPSecSendCompleteCtxSize,
  1572. IPSEC_TAG_SEND_COMPLETE,
  1573. (USHORT)g_ipsec.IPSecSendCompleteCtxDepth);
  1574. IPSEC_DEBUG(LL_A, DBF_LOAD, ("Exiting IPSecInitMdlPool"));
  1575. return STATUS_SUCCESS;
  1576. }
  1577. VOID
  1578. IPSecDeinitMdlPool()
  1579. /*++
  1580. Routine Description:
  1581. Free the MDL pool for AH and ESP headers.
  1582. Arguments:
  1583. None
  1584. Return Value:
  1585. --*/
  1586. {
  1587. PAGED_CODE();
  1588. IPSEC_DEBUG(LL_A, DBF_LOAD, ("Entering IPSecDeinitMdlPool"));
  1589. //
  1590. // Destroy the lookaside lists.
  1591. //
  1592. if (g_ipsec.IPSecLookasideLists != NULL) {
  1593. ExDeleteNPagedLookasideList(&g_ipsec.IPSecLookasideLists->LargeBufferList);
  1594. ExDeleteNPagedLookasideList(&g_ipsec.IPSecLookasideLists->SmallBufferList);
  1595. ExDeleteNPagedLookasideList(&g_ipsec.IPSecLookasideLists->SendCompleteCtxList);
  1596. IPSecFreeMemory(g_ipsec.IPSecLookasideLists);
  1597. }
  1598. IPSEC_DEBUG(LL_A, DBF_LOAD, ("Exiting IPSecDeinitMdlPool"));
  1599. }
  1600. NTSTATUS
  1601. IPSecQuiesce()
  1602. /*++
  1603. Routine Description:
  1604. Destroy MDL pools and run down all driver activity
  1605. Arguments:
  1606. None
  1607. Return Value:
  1608. --*/
  1609. {
  1610. IPSEC_DEBUG(LL_A, DBF_LOAD, ("Entering IPSecQuiesce"));
  1611. IPSecDeinitMdlPool();
  1612. IPSEC_DEBUG(LL_A, DBF_LOAD, ("Exiting IPSecQuiesce"));
  1613. return STATUS_SUCCESS;
  1614. }
  1615. BOOLEAN
  1616. AllocateCacheStructures()
  1617. /*++
  1618. Routine Description:
  1619. Allocates the necessary memory for cache (which is an array of pointers to
  1620. cache entries)
  1621. Allocates necessary number of cache entries (but doesnt initialize them)
  1622. Allocates a small number of entries and puts them on the free list (doesnt
  1623. initialize these either)
  1624. Arguments:
  1625. None
  1626. Return Value:
  1627. True if the function completely succeeds, else FALSE. If FALSE, it is upto
  1628. the CALLER to do a rollback and clear any allocated memory
  1629. --*/
  1630. {
  1631. ULONG i;
  1632. PAGED_CODE();
  1633. g_ipsec.ppCache = IPSecAllocateMemory(g_ipsec.CacheSize * sizeof(PFILTER_CACHE), IPSEC_TAG_INIT);
  1634. if (!g_ipsec.ppCache) {
  1635. IPSEC_DEBUG(LL_A, DBF_LOAD, ("Couldnt allocate memory for Input Cache"));
  1636. return FALSE;
  1637. }
  1638. IPSecZeroMemory(g_ipsec.ppCache, g_ipsec.CacheSize * sizeof(PFILTER_CACHE));
  1639. for (i = 0; i < g_ipsec.CacheSize; i++) {
  1640. PFILTER_CACHE pTemp1;
  1641. pTemp1 = IPSecAllocateMemory(sizeof(FILTER_CACHE), IPSEC_TAG_INIT);
  1642. if (!pTemp1) {
  1643. FreeExistingCache();
  1644. return FALSE;
  1645. }
  1646. IPSecZeroMemory(pTemp1, sizeof(FILTER_CACHE));
  1647. g_ipsec.ppCache[i] = pTemp1;
  1648. }
  1649. return TRUE;
  1650. }
  1651. VOID
  1652. FreeExistingCache()
  1653. /*++
  1654. Routine Description
  1655. Frees all the cache entries, free entries and cache pointer array
  1656. Arguments
  1657. None
  1658. Return Value
  1659. None
  1660. --*/
  1661. {
  1662. ULONG i;
  1663. PAGED_CODE();
  1664. IPSEC_DEBUG(LL_A, DBF_LOAD, ("Freeing existing cache..."));
  1665. IPSecResetCacheTable();
  1666. if (g_ipsec.ppCache) {
  1667. for (i = 0; i < g_ipsec.CacheSize; i++) {
  1668. if (g_ipsec.ppCache[i]) {
  1669. ExFreePool(g_ipsec.ppCache[i]);
  1670. }
  1671. }
  1672. ExFreePool(g_ipsec.ppCache);
  1673. g_ipsec.ppCache = NULL;
  1674. }
  1675. }
  1676. VOID
  1677. FreePatternDbase()
  1678. /*++
  1679. Routine Description
  1680. Frees all filters and SAs.
  1681. Arguments
  1682. None
  1683. Return Value
  1684. None
  1685. --*/
  1686. {
  1687. PLIST_ENTRY pEntry;
  1688. PFILTER pFilter;
  1689. PSA_TABLE_ENTRY pSA;
  1690. LONG i, j;
  1691. PAGED_CODE();
  1692. //
  1693. // Free all masked filters and associated (outbound) SAs
  1694. //
  1695. for (i = MIN_FILTER; i <= MAX_FILTER; i++) {
  1696. while (!IsListEmpty(&g_ipsec.FilterList[i])) {
  1697. pEntry = RemoveHeadList(&g_ipsec.FilterList[i]);
  1698. pFilter = CONTAINING_RECORD(pEntry,
  1699. FILTER,
  1700. MaskedLinkage);
  1701. IPSEC_DEBUG(LL_A, DBF_LOAD, ("Freeing filter: %p", pFilter));
  1702. //
  1703. // Free each SA under it.
  1704. //
  1705. for (j = 0; j < pFilter->SAChainSize; j++) {
  1706. while (!IsListEmpty(&pFilter->SAChain[j])) {
  1707. pEntry = RemoveHeadList(&pFilter->SAChain[j]);
  1708. pSA = CONTAINING_RECORD(pEntry,
  1709. SA_TABLE_ENTRY,
  1710. sa_FilterLinkage);
  1711. IPSEC_DEBUG(LL_A, DBF_LOAD, ("Freeing SA: %p", pSA));
  1712. //
  1713. // Remove SA from miniport if plumbed
  1714. //
  1715. if (pSA->sa_Flags & FLAGS_SA_HW_PLUMBED) {
  1716. IPSecDelHWSA(pSA);
  1717. }
  1718. //
  1719. // Also remove the inbound SAs from their SPI list
  1720. // so we dont double free them below.
  1721. //
  1722. IPSecRemoveSPIEntry(pSA);
  1723. //
  1724. // Stop the timer if armed and deref SA.
  1725. //
  1726. IPSecStopTimerDerefSA(pSA);
  1727. }
  1728. }
  1729. #if GPC
  1730. IPSecUninstallGpcFilter(pFilter);
  1731. #endif
  1732. IPSecFreeFilter(pFilter);
  1733. }
  1734. }
  1735. //
  1736. // Free all SAs under the SPI hashes.
  1737. //
  1738. for (i = 0; i < g_ipsec.SAHashSize; i++) {
  1739. PSA_HASH pHash = &g_ipsec.pSADb[i];
  1740. while (!IsListEmpty(&pHash->SAList)) {
  1741. pEntry = RemoveHeadList(&pHash->SAList);
  1742. pSA = CONTAINING_RECORD(pEntry,
  1743. SA_TABLE_ENTRY,
  1744. sa_SPILinkage);
  1745. IPSEC_DEBUG(LL_A, DBF_LOAD, ("Freeing SA: %p", pSA));
  1746. if (pSA->sa_Flags & FLAGS_SA_HW_PLUMBED) {
  1747. IPSecDelHWSA(pSA);
  1748. }
  1749. IPSecStopTimerDerefSA(pSA);
  1750. }
  1751. }
  1752. IPSecFreeMemory(g_ipsec.pSADb);
  1753. IPSEC_DEBUG(LL_A, DBF_LOAD, ("Freed filters/SAs"));
  1754. }
  1755. SIZE_T
  1756. IPSecCalculateBufferSize(
  1757. IN SIZE_T BufferDataSize
  1758. )
  1759. /*++
  1760. Routine Description:
  1761. Determines the size of an AFD buffer structure given the amount of
  1762. data that the buffer contains.
  1763. Arguments:
  1764. BufferDataSize - data length of the buffer.
  1765. AddressSize - length of address structure for the buffer.
  1766. Return Value:
  1767. Number of bytes needed for an IPSEC_LA_BUFFER structure for data of
  1768. this size.
  1769. --*/
  1770. {
  1771. SIZE_T mdlSize;
  1772. SIZE_T bufferSize;
  1773. ASSERT(BufferDataSize != 0);
  1774. ASSERT(g_ipsec.IPSecCacheLineSize < 100);
  1775. //
  1776. // Determine the sizes of the various components of an IPSEC_LA_BUFFER
  1777. // structure. Note that these are all worst-case calculations--
  1778. // actual sizes of the MDL and the buffer may be smaller.
  1779. //
  1780. bufferSize = BufferDataSize + g_ipsec.IPSecCacheLineSize;
  1781. mdlSize = MmSizeOfMdl( (PVOID)(PAGE_SIZE-1), bufferSize );
  1782. return ((sizeof(IPSEC_LA_BUFFER) + mdlSize + bufferSize + 3) & ~3);
  1783. }
  1784. VOID
  1785. IPSecInitializeBuffer(
  1786. IN PIPSEC_LA_BUFFER IPSecBuffer,
  1787. IN SIZE_T BufferDataSize
  1788. )
  1789. /*++
  1790. Routine Description:
  1791. Initializes an IPSec buffer. Sets up fields in the actual IPSEC_LA_BUFFER
  1792. structure and initializes the MDL associated with the buffer. This routine
  1793. assumes that the caller has properly allocated sufficient space for all this.
  1794. Arguments:
  1795. IPSecBuffer - points to the IPSEC_LA_BUFFER structure to initialize.
  1796. BufferDataSize - the size of the data buffer that goes along with the
  1797. buffer structure.
  1798. Return Value:
  1799. None
  1800. --*/
  1801. {
  1802. SIZE_T mdlSize;
  1803. //
  1804. // Set up the MDL pointer but don't build it yet. We have to wait
  1805. // until after the data buffer is built to build the MDL.
  1806. //
  1807. mdlSize = MmSizeOfMdl( (PVOID)(PAGE_SIZE-1), BufferDataSize );
  1808. IPSecBuffer->Mdl = (PMDL)&IPSecBuffer->Data[0];
  1809. IPSEC_DEBUG(LL_A, DBF_POOL, ("IPSecBuffer: %p, MDL: %p", IPSecBuffer, IPSecBuffer->Mdl));
  1810. //
  1811. // Set up the data buffer pointer and length. Note that the buffer
  1812. // MUST begin on a cache line boundary so that we can use the fast
  1813. // copy routines like RtlCopyMemory on the buffer.
  1814. //
  1815. IPSecBuffer->Buffer = (PVOID)
  1816. (((ULONG_PTR)((PCHAR)IPSecBuffer->Mdl + mdlSize) +
  1817. g_ipsec.IPSecCacheLineSize - 1 ) & ~((ULONG_PTR)(g_ipsec.IPSecCacheLineSize - 1)));
  1818. IPSecBuffer->BufferLength = (ULONG)BufferDataSize; // Sundown - FIX
  1819. //
  1820. // Now build the MDL and set up a pointer to the MDL in the IRP.
  1821. //
  1822. MmInitializeMdl( IPSecBuffer->Mdl, IPSecBuffer->Buffer, BufferDataSize );
  1823. MmBuildMdlForNonPagedPool( IPSecBuffer->Mdl );
  1824. }
  1825. PVOID
  1826. IPSecAllocateBufferPool(
  1827. IN POOL_TYPE PoolType,
  1828. IN SIZE_T NumberOfBytes,
  1829. IN ULONG Tag
  1830. )
  1831. /*++
  1832. Routine Description:
  1833. Used by the lookaside list allocation function to allocate a new
  1834. IPSec buffer structure. The returned structure will be fully
  1835. initialized.
  1836. Arguments:
  1837. PoolType - passed to ExAllocatePoolWithTag.
  1838. NumberOfBytes - the number of bytes required for the data buffer
  1839. portion of the IPSec buffer.
  1840. Tag - passed to ExAllocatePoolWithTag.
  1841. Return Value:
  1842. PVOID - a fully initialized PIPSEC_LA_BUFFER, or NULL if the allocation
  1843. attempt fails.
  1844. --*/
  1845. {
  1846. PIPSEC_LA_BUFFER IPSecBuffer;
  1847. SIZE_T bytesRequired;
  1848. //
  1849. // The requested length must be the same as one of the standard
  1850. // IPSec buffer sizes.
  1851. //
  1852. ASSERT( NumberOfBytes == g_ipsec.IPSecSmallBufferSize ||
  1853. NumberOfBytes == g_ipsec.IPSecLargeBufferSize );
  1854. //
  1855. // Determine how much data we'll actually need for the buffer.
  1856. //
  1857. bytesRequired = IPSecCalculateBufferSize(NumberOfBytes);
  1858. //
  1859. // Get nonpaged pool for the buffer.
  1860. //
  1861. IPSecBuffer = IPSecAllocateMemory( bytesRequired, Tag );
  1862. if ( IPSecBuffer == NULL ) {
  1863. return NULL;
  1864. }
  1865. //
  1866. // Initialize the buffer and return a pointer to it.
  1867. //
  1868. IPSecInitializeBuffer( IPSecBuffer, NumberOfBytes );
  1869. return IPSecBuffer;
  1870. }
  1871. PIPSEC_LA_BUFFER
  1872. IPSecGetBuffer(
  1873. IN CLONG BufferDataSize,
  1874. IN ULONG Tag
  1875. )
  1876. /*++
  1877. Routine Description:
  1878. Obtains a buffer of the appropriate size for the caller. Uses
  1879. the preallocated buffers if possible, or else allocates a new buffer
  1880. structure if required.
  1881. Arguments:
  1882. BufferDataSize - the size of the data buffer that goes along with the
  1883. buffer structure.
  1884. Return Value:
  1885. PIPSEC_LA_BUFFER - a pointer to an IPSEC_LA_BUFFER structure, or NULL if one
  1886. was not available or could not be allocated.
  1887. --*/
  1888. {
  1889. PIPSEC_LA_BUFFER IPSecBuffer;
  1890. SIZE_T bufferSize;
  1891. PLIST_ENTRY listEntry;
  1892. PNPAGED_LOOKASIDE_LIST lookasideList;
  1893. //
  1894. // If possible, allocate the buffer from one of the lookaside lists.
  1895. //
  1896. if (BufferDataSize <= g_ipsec.IPSecLargeBufferSize) {
  1897. if ( BufferDataSize <= g_ipsec.IPSecSmallBufferSize ) {
  1898. lookasideList = &g_ipsec.IPSecLookasideLists->SmallBufferList;
  1899. BufferDataSize = g_ipsec.IPSecSmallBufferSize;
  1900. } else {
  1901. lookasideList = &g_ipsec.IPSecLookasideLists->LargeBufferList;
  1902. BufferDataSize = g_ipsec.IPSecLargeBufferSize;
  1903. }
  1904. IPSecBuffer = ExAllocateFromNPagedLookasideList( lookasideList );
  1905. if (!IPSecBuffer) {
  1906. return NULL;
  1907. }
  1908. IPSecBuffer->Tag = Tag;
  1909. return IPSecBuffer;
  1910. }
  1911. //
  1912. // Couldn't find an appropriate buffer that was preallocated.
  1913. // Allocate one manually. If the buffer size requested was
  1914. // zero bytes, give them four bytes. This is because some of
  1915. // the routines like MmSizeOfMdl() cannot handle getting passed
  1916. // in a length of zero.
  1917. //
  1918. // !!! It would be good to ROUND_TO_PAGES for this allocation
  1919. // if appropriate, then use entire buffer size.
  1920. //
  1921. if ( BufferDataSize == 0 ) {
  1922. BufferDataSize = sizeof(ULONG);
  1923. }
  1924. bufferSize = IPSecCalculateBufferSize(BufferDataSize);
  1925. IPSecBuffer = IPSecAllocateMemory(bufferSize, IPSEC_TAG_BUFFER_POOL);
  1926. if ( IPSecBuffer == NULL ) {
  1927. return NULL;
  1928. }
  1929. //
  1930. // Initialize the IPSec buffer structure and return it.
  1931. //
  1932. IPSecInitializeBuffer(IPSecBuffer, BufferDataSize);
  1933. IPSecBuffer->Tag = Tag;
  1934. return IPSecBuffer;
  1935. }
  1936. VOID
  1937. IPSecReturnBuffer (
  1938. IN PIPSEC_LA_BUFFER IPSecBuffer
  1939. )
  1940. /*++
  1941. Routine Description:
  1942. Returns an IPSec buffer to the appropriate global list, or frees
  1943. it if necessary.
  1944. Arguments:
  1945. IPSecBufferHeader - points to the IPSec_BUFFER_HEADER structure to return or free.
  1946. Return Value:
  1947. None
  1948. --*/
  1949. {
  1950. PNPAGED_LOOKASIDE_LIST lookasideList;
  1951. //
  1952. // If appropriate, return the buffer to one of the IPSec buffer
  1953. // lookaside lists.
  1954. //
  1955. if (IPSecBuffer->BufferLength <= g_ipsec.IPSecLargeBufferSize) {
  1956. if (IPSecBuffer->BufferLength==g_ipsec.IPSecSmallBufferSize) {
  1957. lookasideList = &g_ipsec.IPSecLookasideLists->SmallBufferList;
  1958. } else {
  1959. ASSERT (IPSecBuffer->BufferLength==g_ipsec.IPSecLargeBufferSize);
  1960. lookasideList = &g_ipsec.IPSecLookasideLists->LargeBufferList;
  1961. }
  1962. ExFreeToNPagedLookasideList( lookasideList, IPSecBuffer );
  1963. return;
  1964. }
  1965. IPSecFreeMemory(IPSecBuffer);
  1966. }
  1967. NTSTATUS
  1968. IPSecWriteEvent(
  1969. PDRIVER_OBJECT IPSecDriverObject,
  1970. IN ULONG EventCode,
  1971. IN NTSTATUS NtStatusCode,
  1972. IN ULONG OffloadStatus,
  1973. IN ULONG ExtraStatus1,
  1974. IN ULONG ExtraStatus2,
  1975. IN PVOID RawDataBuffer,
  1976. IN USHORT RawDataLength,
  1977. IN USHORT NumberOfInsertionStrings,
  1978. ...
  1979. )
  1980. #define LAST_NAMED_ARGUMENT NumberOfInsertionStrings
  1981. /*++
  1982. Routine Description:
  1983. This function allocates an I/O error log record, fills it in and writes it
  1984. to the I/O error log.
  1985. Arguments:
  1986. Return Value:
  1987. None.
  1988. --*/
  1989. {
  1990. PIO_ERROR_LOG_PACKET ErrorLogEntry;
  1991. va_list ParmPtr; // Pointer to stack parms.
  1992. PCHAR DumpData;
  1993. LONG Length;
  1994. ULONG i, SizeOfRawData, RemainingSpace, TotalErrorLogEntryLength;
  1995. ULONG SizeOfStringData = 0;
  1996. PWSTR StringOffset, InsertionString;
  1997. if (NumberOfInsertionStrings != 0)
  1998. {
  1999. va_start (ParmPtr, LAST_NAMED_ARGUMENT);
  2000. for (i = 0; i < NumberOfInsertionStrings; i += 1)
  2001. {
  2002. InsertionString = va_arg (ParmPtr, PWSTR);
  2003. Length = wcslen (InsertionString);
  2004. while ((Length > 0) && (InsertionString[Length-1] == L' '))
  2005. {
  2006. Length--;
  2007. }
  2008. SizeOfStringData += (Length + 1) * sizeof(WCHAR);
  2009. }
  2010. }
  2011. //
  2012. // Ideally we want the packet to hold the servername and ExtraInformation.
  2013. // Usually the ExtraInformation gets truncated.
  2014. //
  2015. TotalErrorLogEntryLength = min (RawDataLength + sizeof(IO_ERROR_LOG_PACKET) + 1 + SizeOfStringData,
  2016. ERROR_LOG_MAXIMUM_SIZE);
  2017. RemainingSpace = TotalErrorLogEntryLength - FIELD_OFFSET(IO_ERROR_LOG_PACKET, DumpData);
  2018. if (RemainingSpace > SizeOfStringData)
  2019. {
  2020. SizeOfRawData = RemainingSpace - SizeOfStringData;
  2021. }
  2022. else
  2023. {
  2024. SizeOfStringData = RemainingSpace;
  2025. SizeOfRawData = 0;
  2026. }
  2027. ErrorLogEntry = IoAllocateErrorLogEntry (IPSecDriverObject, (UCHAR) TotalErrorLogEntryLength);
  2028. if (ErrorLogEntry == NULL)
  2029. {
  2030. return(STATUS_INSUFFICIENT_RESOURCES);
  2031. }
  2032. //
  2033. // Fill in the error log entry
  2034. //
  2035. ErrorLogEntry->ErrorCode = EventCode;
  2036. ErrorLogEntry->UniqueErrorValue = OffloadStatus;
  2037. ErrorLogEntry->FinalStatus = NtStatusCode;
  2038. ErrorLogEntry->MajorFunctionCode = 0;
  2039. ErrorLogEntry->RetryCount = 0;
  2040. ErrorLogEntry->IoControlCode = 0;
  2041. ErrorLogEntry->DeviceOffset.LowPart = ExtraStatus1;
  2042. ErrorLogEntry->DeviceOffset.HighPart = ExtraStatus2;
  2043. ErrorLogEntry->DumpDataSize = 0;
  2044. ErrorLogEntry->NumberOfStrings = 0;
  2045. ErrorLogEntry->SequenceNumber = 0;
  2046. ErrorLogEntry->StringOffset = (USHORT) (ROUND_UP_COUNT (FIELD_OFFSET(IO_ERROR_LOG_PACKET, DumpData)
  2047. + SizeOfRawData, ALIGN_WORD));
  2048. //
  2049. // Append the dump data. This information is typically an SMB header.
  2050. //
  2051. if ((RawDataBuffer) && (SizeOfRawData))
  2052. {
  2053. DumpData = (PCHAR) ErrorLogEntry->DumpData;
  2054. Length = min (RawDataLength, (USHORT)SizeOfRawData);
  2055. RtlCopyMemory (DumpData, RawDataBuffer, Length);
  2056. ErrorLogEntry->DumpDataSize = (USHORT)Length;
  2057. }
  2058. //
  2059. // Add the debug informatuion strings
  2060. //
  2061. if (NumberOfInsertionStrings)
  2062. {
  2063. StringOffset = (PWSTR) ((PCHAR)ErrorLogEntry + ErrorLogEntry->StringOffset);
  2064. //
  2065. // Set up ParmPtr to point to first of the caller's parameters.
  2066. //
  2067. va_start(ParmPtr, LAST_NAMED_ARGUMENT);
  2068. for (i = 0 ; i < NumberOfInsertionStrings ; i+= 1)
  2069. {
  2070. InsertionString = va_arg(ParmPtr, PWSTR);
  2071. Length = wcslen(InsertionString);
  2072. while ( (Length > 0) && (InsertionString[Length-1] == L' '))
  2073. {
  2074. Length--;
  2075. }
  2076. if (((Length + 1) * sizeof(WCHAR)) > SizeOfStringData)
  2077. {
  2078. Length = (SizeOfStringData/sizeof(WCHAR)) - 1;
  2079. }
  2080. if (Length > 0)
  2081. {
  2082. RtlCopyMemory (StringOffset, InsertionString, Length*sizeof(WCHAR));
  2083. StringOffset += Length;
  2084. *StringOffset++ = L'\0';
  2085. SizeOfStringData -= (Length + 1) * sizeof(WCHAR);
  2086. ErrorLogEntry->NumberOfStrings += 1;
  2087. }
  2088. }
  2089. }
  2090. IoWriteErrorLogEntry(ErrorLogEntry);
  2091. return(STATUS_SUCCESS);
  2092. }
  2093. VOID
  2094. IPSecLogEvents(
  2095. IN PVOID Context
  2096. )
  2097. /*++
  2098. Routine Description:
  2099. Dumps events from the circular buffer to the eventlog when the
  2100. circular buffer overflows.
  2101. Arguments:
  2102. Context - unused.
  2103. Return Value:
  2104. None
  2105. --*/
  2106. {
  2107. PIPSEC_LOG_EVENT pLogEvent;
  2108. LONG LogSize;
  2109. PUCHAR pLog;
  2110. pLogEvent = (PIPSEC_LOG_EVENT)Context;
  2111. LogSize = 0;
  2112. pLog = (PUCHAR)pLogEvent + FIELD_OFFSET(IPSEC_LOG_EVENT, pLog[0]);
  2113. while (LogSize < pLogEvent->LogSize) {
  2114. PIPSEC_EVENT_CTX ctx = (PIPSEC_EVENT_CTX)pLog;
  2115. if (ctx->EventCode == EVENT_IPSEC_DROP_PACKET_INBOUND ||
  2116. ctx->EventCode == EVENT_IPSEC_DROP_PACKET_OUTBOUND) {
  2117. WCHAR IPAddrBufferS[(sizeof(IPAddr) * 4) + 1];
  2118. WCHAR IPAddrBufferD[(sizeof(IPAddr) * 4) + 1];
  2119. WCHAR IPProtocolBuffer[(sizeof(IPAddr) * 4) + 1];
  2120. WCHAR IPSPortBuffer[(sizeof(IPAddr) * 4) + 1];
  2121. WCHAR IPDPortBuffer[(sizeof(IPAddr) * 4) + 1];
  2122. PWCHAR stringlist[5];
  2123. IPHeader UNALIGNED *pIPH;
  2124. USHORT SrcPort=0;
  2125. USHORT DestPort=0;
  2126. ULONG HeaderLen;
  2127. pIPH = (IPHeader UNALIGNED *)ctx->pPacket;
  2128. HeaderLen=(pIPH->iph_verlen & (UCHAR)~IP_VER_FLAG) << 2;
  2129. IPSecIPAddrToUnicodeString( pIPH->iph_src,
  2130. IPAddrBufferS);
  2131. IPSecIPAddrToUnicodeString( pIPH->iph_dest,
  2132. IPAddrBufferD);
  2133. IPSecCountToUnicodeString ( pIPH->iph_protocol,
  2134. IPProtocolBuffer);
  2135. if (pIPH->iph_protocol == PROTOCOL_TCP ||
  2136. pIPH->iph_protocol == PROTOCOL_UDP) {
  2137. RtlCopyMemory(&SrcPort,&ctx->pPacket[HeaderLen],sizeof(USHORT));
  2138. RtlCopyMemory(&DestPort,&ctx->pPacket[HeaderLen+sizeof(USHORT)],sizeof(USHORT));
  2139. }
  2140. IPSecCountToUnicodeString ( NET_SHORT(SrcPort),
  2141. IPSPortBuffer);
  2142. IPSecCountToUnicodeString ( NET_SHORT(DestPort),
  2143. IPDPortBuffer);
  2144. IPSecWriteEvent(
  2145. g_ipsec.IPSecDriverObject,
  2146. ctx->EventCode,
  2147. ctx->DropStatus.IPSecStatus,
  2148. ctx->DropStatus.OffloadStatus,
  2149. ctx->DropStatus.Flags,
  2150. 0,
  2151. ctx->pPacket,
  2152. (USHORT)ctx->PacketSize,
  2153. 5,
  2154. IPAddrBufferS,
  2155. IPAddrBufferD,
  2156. IPProtocolBuffer,
  2157. IPSPortBuffer,
  2158. IPDPortBuffer);
  2159. } else if (ctx->Addr && ctx->EventCount > 0) {
  2160. WCHAR IPAddrBuffer[(sizeof(IPAddr) * 4) + 1];
  2161. WCHAR CountBuffer[MAX_COUNT_STRING_LEN + 1];
  2162. PWCHAR stringList[2];
  2163. IPSecIPAddrToUnicodeString( ctx->Addr,
  2164. IPAddrBuffer);
  2165. IPSecCountToUnicodeString( ctx->EventCount,
  2166. CountBuffer);
  2167. stringList[0] = CountBuffer;
  2168. stringList[1] = IPAddrBuffer;
  2169. LOG_EVENT(
  2170. g_ipsec.IPSecDriverObject,
  2171. ctx->EventCode,
  2172. ctx->UniqueEventValue,
  2173. 2,
  2174. stringList,
  2175. 0,
  2176. NULL);
  2177. } else if (ctx->Addr) {
  2178. WCHAR IPAddrBuffer[(sizeof(IPAddr) * 4) + 1];
  2179. PWCHAR stringList[1];
  2180. IPSecIPAddrToUnicodeString( ctx->Addr,
  2181. IPAddrBuffer);
  2182. stringList[0] = IPAddrBuffer;
  2183. LOG_EVENT(
  2184. g_ipsec.IPSecDriverObject,
  2185. ctx->EventCode,
  2186. ctx->UniqueEventValue,
  2187. 1,
  2188. stringList,
  2189. 0,
  2190. NULL);
  2191. } else {
  2192. LOG_EVENT(
  2193. g_ipsec.IPSecDriverObject,
  2194. ctx->EventCode,
  2195. ctx->UniqueEventValue,
  2196. 0,
  2197. NULL,
  2198. 0,
  2199. NULL);
  2200. }
  2201. if (ctx->pPacket) {
  2202. IPSecFreeLogBuffer(ctx->pPacket);
  2203. ctx->pPacket=NULL;
  2204. }
  2205. pLog += sizeof(IPSEC_EVENT_CTX);
  2206. LogSize += sizeof(IPSEC_EVENT_CTX);
  2207. }
  2208. IPSecFreeMemory(pLogEvent);
  2209. IPSEC_DECREMENT(g_ipsec.NumWorkers);
  2210. }
  2211. VOID
  2212. IPSecBufferEvent(
  2213. IN IPAddr Addr,
  2214. IN ULONG EventCode,
  2215. IN ULONG UniqueEventValue,
  2216. IN BOOLEAN fBufferEvent
  2217. )
  2218. /*++
  2219. Routine Description:
  2220. Buffers events in a circular buffer; dumps them to the eventlog when the
  2221. circular buffer overflows.
  2222. Arguments:
  2223. Addr - [OPTIONAL] the source IP addr of the offending peer.
  2224. EventCode - Identifies the error message.
  2225. UniqueEventValue - Identifies this instance of a given error message.
  2226. Return Value:
  2227. None
  2228. --*/
  2229. {
  2230. KIRQL kIrql;
  2231. if (!(g_ipsec.DiagnosticMode & IPSEC_DIAGNOSTIC_ENABLE_LOG)) {
  2232. return;
  2233. }
  2234. ACQUIRE_LOCK(&g_ipsec.EventLogLock, &kIrql);
  2235. if (fBufferEvent) {
  2236. PIPSEC_EVENT_CTX ctx;
  2237. g_ipsec.IPSecBufferedEvents++;
  2238. ctx = (PIPSEC_EVENT_CTX)g_ipsec.IPSecLogMemoryLoc;
  2239. ctx--;
  2240. while (ctx >= (PIPSEC_EVENT_CTX)g_ipsec.IPSecLogMemory) {
  2241. if (ctx->Addr == Addr &&
  2242. ctx->EventCode == EventCode &&
  2243. ctx->UniqueEventValue == UniqueEventValue) {
  2244. //
  2245. // Found a duplicate; update count and exit.
  2246. //
  2247. ctx->EventCount++;
  2248. if (g_ipsec.IPSecBufferedEvents >= g_ipsec.EventQueueSize) {
  2249. goto logit;
  2250. }
  2251. RELEASE_LOCK(&g_ipsec.EventLogLock, kIrql);
  2252. return;
  2253. }
  2254. ctx--;
  2255. }
  2256. }
  2257. ((PIPSEC_EVENT_CTX)g_ipsec.IPSecLogMemoryLoc)->Addr = Addr;
  2258. ((PIPSEC_EVENT_CTX)g_ipsec.IPSecLogMemoryLoc)->EventCode = EventCode;
  2259. ((PIPSEC_EVENT_CTX)g_ipsec.IPSecLogMemoryLoc)->UniqueEventValue = UniqueEventValue;
  2260. ((PIPSEC_EVENT_CTX)g_ipsec.IPSecLogMemoryLoc)->pPacket=NULL;
  2261. ((PIPSEC_EVENT_CTX)g_ipsec.IPSecLogMemoryLoc)->PacketSize=0;
  2262. if (fBufferEvent) {
  2263. ((PIPSEC_EVENT_CTX)g_ipsec.IPSecLogMemoryLoc)->EventCount = 1;
  2264. } else {
  2265. ((PIPSEC_EVENT_CTX)g_ipsec.IPSecLogMemoryLoc)->EventCount = 0;
  2266. }
  2267. g_ipsec.IPSecLogMemoryLoc += sizeof(IPSEC_EVENT_CTX);
  2268. logit:
  2269. if (!fBufferEvent ||
  2270. g_ipsec.IPSecLogMemoryLoc >= g_ipsec.IPSecLogMemoryEnd ||
  2271. g_ipsec.IPSecBufferedEvents >= g_ipsec.EventQueueSize) {
  2272. //
  2273. // Flush the logs.
  2274. //
  2275. IPSecQueueLogEvent();
  2276. }
  2277. RELEASE_LOCK(&g_ipsec.EventLogLock, kIrql);
  2278. }
  2279. NTSTATUS
  2280. CopyOutboundPacketToBuffer(
  2281. IN PUCHAR pIPHeader,
  2282. IN PVOID pData,
  2283. OUT PUCHAR * pPacket,
  2284. OUT ULONG * PacketSize
  2285. )
  2286. {
  2287. PNDIS_BUFFER pTemp;
  2288. ULONG Length;
  2289. ULONG dataLength=0;
  2290. IPHeader UNALIGNED *pIPH;
  2291. ULONG HeaderLen=0;
  2292. PUCHAR pBuffer;
  2293. ULONG CopyPos=0;
  2294. PUCHAR pPacketData;
  2295. pIPH = (IPHeader UNALIGNED *)pIPHeader;
  2296. pTemp = (PNDIS_BUFFER)pData;
  2297. while (pTemp) {
  2298. pBuffer = NULL;
  2299. Length = 0;
  2300. NdisQueryBufferSafe(pTemp,
  2301. &pBuffer,
  2302. &Length,
  2303. NormalPagePriority);
  2304. if (!pBuffer) {
  2305. return STATUS_UNSUCCESSFUL;
  2306. }
  2307. dataLength += Length;
  2308. pTemp = NDIS_BUFFER_LINKAGE(pTemp);
  2309. }
  2310. HeaderLen=(pIPH->iph_verlen & (UCHAR)~IP_VER_FLAG) << 2;
  2311. dataLength += HeaderLen;
  2312. if (dataLength > IPSEC_LOG_PACKET_SIZE) {
  2313. dataLength = IPSEC_LOG_PACKET_SIZE;
  2314. }
  2315. if (dataLength < sizeof(IPHeader)) {
  2316. // doesn't even have a full ip header
  2317. return STATUS_UNSUCCESSFUL;
  2318. }
  2319. if ((pIPH->iph_protocol == PROTOCOL_TCP) ||
  2320. (pIPH->iph_protocol == PROTOCOL_UDP)) {
  2321. if (dataLength - HeaderLen < 8) {
  2322. // not enough room for ports
  2323. return STATUS_UNSUCCESSFUL;
  2324. }
  2325. }
  2326. *pPacket = IPSecAllocateLogBuffer(dataLength);
  2327. if (! (*pPacket)) {
  2328. return STATUS_UNSUCCESSFUL;
  2329. }
  2330. *PacketSize=dataLength;
  2331. pTemp = (PNDIS_BUFFER)pData;
  2332. CopyPos=0;
  2333. while (pTemp && CopyPos < dataLength) {
  2334. IPSecQueryNdisBuf(pTemp,&pPacketData,&Length);
  2335. if (CopyPos + Length > dataLength) {
  2336. Length = (dataLength - CopyPos);
  2337. }
  2338. RtlCopyMemory(*pPacket+CopyPos,pPacketData,Length);
  2339. CopyPos += Length;
  2340. pTemp = NDIS_BUFFER_LINKAGE(pTemp);
  2341. }
  2342. return STATUS_SUCCESS;
  2343. }
  2344. //
  2345. // pData is data after IPHeader, IPRcvBuf.
  2346. //
  2347. NTSTATUS
  2348. CopyInboundPacketToBuffer(
  2349. IN PUCHAR pIPHeader,
  2350. IN PVOID pData,
  2351. OUT PUCHAR * pPacket,
  2352. OUT ULONG * PacketSize
  2353. )
  2354. {
  2355. IPRcvBuf *pTemp;
  2356. ULONG Length;
  2357. ULONG dataLength=0;
  2358. IPHeader UNALIGNED *pIPH;
  2359. ULONG HeaderLen=0;
  2360. PUCHAR pBuffer;
  2361. ULONG CopyPos=0;
  2362. PUCHAR pPacketData;
  2363. pIPH = (IPHeader UNALIGNED *)pIPHeader;
  2364. pTemp = (IPRcvBuf*)pData;
  2365. while (pTemp) {
  2366. pBuffer = NULL;
  2367. Length = 0;
  2368. IPSecQueryRcvBuf(pTemp,
  2369. &pBuffer,
  2370. &Length);
  2371. if (!pBuffer) {
  2372. return STATUS_UNSUCCESSFUL;
  2373. }
  2374. dataLength += Length;
  2375. pTemp = IPSEC_BUFFER_LINKAGE(pTemp);
  2376. }
  2377. HeaderLen=(pIPH->iph_verlen & (UCHAR)~IP_VER_FLAG) << 2;
  2378. dataLength += HeaderLen;
  2379. if (dataLength > IPSEC_LOG_PACKET_SIZE) {
  2380. dataLength = IPSEC_LOG_PACKET_SIZE;
  2381. }
  2382. // Sanity check length
  2383. if (dataLength < sizeof(IPHeader)) {
  2384. // doesn't even have a full ip header
  2385. return STATUS_UNSUCCESSFUL;
  2386. }
  2387. if ((pIPH->iph_protocol == PROTOCOL_TCP) ||
  2388. (pIPH->iph_protocol == PROTOCOL_UDP)) {
  2389. if (dataLength - HeaderLen < 8) {
  2390. // not enough room for ports
  2391. return STATUS_UNSUCCESSFUL;
  2392. }
  2393. }
  2394. *pPacket = IPSecAllocateLogBuffer(dataLength);
  2395. if (! (*pPacket)) {
  2396. return STATUS_UNSUCCESSFUL;
  2397. }
  2398. *PacketSize=dataLength;
  2399. pTemp = (IPRcvBuf*)pData;
  2400. RtlCopyMemory(*pPacket,pIPH,HeaderLen);
  2401. CopyPos=HeaderLen;
  2402. while (pTemp && CopyPos < dataLength) {
  2403. IPSecQueryRcvBuf(pTemp,&pPacketData,&Length);
  2404. if (CopyPos + Length > dataLength) {
  2405. Length = (dataLength - CopyPos);
  2406. }
  2407. RtlCopyMemory(*pPacket+CopyPos,pPacketData,Length);
  2408. CopyPos += Length;
  2409. pTemp = IPSEC_BUFFER_LINKAGE(pTemp);
  2410. }
  2411. return STATUS_SUCCESS;
  2412. }
  2413. VOID
  2414. IPSecBufferPacketDrop(
  2415. IN PUCHAR pIPHeader,
  2416. IN PVOID pData,
  2417. IN OUT PULONG pIpsecFlags,
  2418. IN PIPSEC_DROP_STATUS pDropStatus
  2419. )
  2420. /*++
  2421. Routine Description:
  2422. Buffers events in a circular buffer; dumps them to the eventlog when the
  2423. circular buffer overflows.
  2424. Arguments:
  2425. EventCode - Identifies the error message.
  2426. Return Value:
  2427. None
  2428. --*/
  2429. {
  2430. KIRQL kIrql;
  2431. PIPSEC_EVENT_CTX ctx;
  2432. IPHeader UNALIGNED *pIPH;
  2433. PNDIS_BUFFER pTemp;
  2434. PUCHAR pPacket=NULL;
  2435. ULONG PacketSize=0;
  2436. ULONG Status;
  2437. BOOL bLockHeld=FALSE;
  2438. pIPH = (IPHeader UNALIGNED *)pIPHeader;
  2439. if (*pIpsecFlags & IPSEC_FLAG_INCOMING) {
  2440. if (!(g_ipsec.DiagnosticMode & IPSEC_DIAGNOSTIC_INBOUND)) {
  2441. // Don't log
  2442. goto out;
  2443. }
  2444. Status=CopyInboundPacketToBuffer(pIPHeader,
  2445. pData,
  2446. &pPacket,
  2447. &PacketSize);
  2448. } else {
  2449. if (!(g_ipsec.DiagnosticMode & IPSEC_DIAGNOSTIC_OUTBOUND)) {
  2450. //Don't log
  2451. goto out;
  2452. }
  2453. Status=CopyOutboundPacketToBuffer(pIPHeader,
  2454. pData,
  2455. &pPacket,
  2456. &PacketSize);
  2457. }
  2458. if (Status != STATUS_SUCCESS) {
  2459. goto out;
  2460. }
  2461. ACQUIRE_LOCK(&g_ipsec.EventLogLock, &kIrql);
  2462. bLockHeld=TRUE;
  2463. g_ipsec.IPSecBufferedEvents++;
  2464. ctx = (PIPSEC_EVENT_CTX)g_ipsec.IPSecLogMemoryLoc;
  2465. ctx--;
  2466. ((PIPSEC_EVENT_CTX)g_ipsec.IPSecLogMemoryLoc)->Addr=pIPH->iph_src;
  2467. if (*pIpsecFlags & IPSEC_FLAG_INCOMING) {
  2468. ((PIPSEC_EVENT_CTX)g_ipsec.IPSecLogMemoryLoc)->EventCode = EVENT_IPSEC_DROP_PACKET_INBOUND;
  2469. } else {
  2470. ((PIPSEC_EVENT_CTX)g_ipsec.IPSecLogMemoryLoc)->EventCode = EVENT_IPSEC_DROP_PACKET_OUTBOUND;
  2471. }
  2472. ((PIPSEC_EVENT_CTX)g_ipsec.IPSecLogMemoryLoc)->EventCount = 1;
  2473. ((PIPSEC_EVENT_CTX)g_ipsec.IPSecLogMemoryLoc)->pPacket = pPacket;
  2474. ((PIPSEC_EVENT_CTX)g_ipsec.IPSecLogMemoryLoc)->PacketSize = PacketSize;
  2475. if (pDropStatus) {
  2476. RtlCopyMemory(&(((PIPSEC_EVENT_CTX)g_ipsec.IPSecLogMemoryLoc)->DropStatus),
  2477. pDropStatus,sizeof(IPSEC_DROP_STATUS));
  2478. } else {
  2479. RtlZeroMemory(&(((PIPSEC_EVENT_CTX)g_ipsec.IPSecLogMemoryLoc)->DropStatus),
  2480. sizeof(IPSEC_DROP_STATUS));
  2481. }
  2482. g_ipsec.IPSecLogMemoryLoc += sizeof(IPSEC_EVENT_CTX);
  2483. if (g_ipsec.IPSecLogMemoryLoc >= g_ipsec.IPSecLogMemoryEnd ||
  2484. g_ipsec.IPSecBufferedEvents >= g_ipsec.EventQueueSize) {
  2485. //
  2486. // Flush the logs.
  2487. //
  2488. IPSecQueueLogEvent();
  2489. }
  2490. out:
  2491. if (bLockHeld) {
  2492. RELEASE_LOCK(&g_ipsec.EventLogLock, kIrql);
  2493. }
  2494. }
  2495. VOID
  2496. IPSecQueueLogEvent(
  2497. VOID
  2498. )
  2499. /*++
  2500. Routine Description:
  2501. Copies the LogMemory to a temporary buffer and schedule an event to
  2502. flush logs.
  2503. Arguments:
  2504. None
  2505. Return Value:
  2506. None
  2507. Notes:
  2508. Called with EventLogLock held.
  2509. --*/
  2510. {
  2511. PIPSEC_LOG_EVENT pLogEvent;
  2512. LONG LogSize;
  2513. PUCHAR pLog;
  2514. LogSize = (LONG)(g_ipsec.IPSecLogMemoryLoc - g_ipsec.IPSecLogMemory);
  2515. //
  2516. // Reset the log memory so we can record again.
  2517. //
  2518. g_ipsec.IPSecLogMemoryLoc = g_ipsec.IPSecLogMemory;
  2519. g_ipsec.IPSecBufferedEvents = 0;
  2520. if (LogSize <= 0) {
  2521. ASSERT(FALSE);
  2522. return;
  2523. }
  2524. pLogEvent = IPSecAllocateMemory(LogSize + FIELD_OFFSET(IPSEC_LOG_EVENT, pLog[0]),
  2525. IPSEC_TAG_EVT_QUEUE);
  2526. if (!pLogEvent) {
  2527. return;
  2528. }
  2529. pLogEvent->LogSize = LogSize;
  2530. pLog = (PUCHAR)pLogEvent + FIELD_OFFSET(IPSEC_LOG_EVENT, pLog[0]);
  2531. RtlCopyMemory(pLog, g_ipsec.IPSecLogMemory, LogSize);
  2532. //
  2533. // Queue work item to dump these into the eventlog.
  2534. //
  2535. ExInitializeWorkItem(&pLogEvent->LogQueueItem, IPSecLogEvents, pLogEvent);
  2536. ExQueueWorkItem(&pLogEvent->LogQueueItem, DelayedWorkQueue);
  2537. IPSEC_INCREMENT(g_ipsec.NumWorkers);
  2538. }
  2539. #if FIPS
  2540. BOOLEAN
  2541. IPSecFipsInitialize(
  2542. VOID
  2543. )
  2544. /*++
  2545. Routine Description:
  2546. Initialize the FIPS library table.
  2547. Arguments:
  2548. Called at PASSIVE level.
  2549. Return Value:
  2550. TRUE/FALSE.
  2551. --*/
  2552. {
  2553. UNICODE_STRING DeviceName;
  2554. PDEVICE_OBJECT pFipsDeviceObject = NULL;
  2555. PIRP pIrp;
  2556. IO_STATUS_BLOCK StatusBlock;
  2557. KEVENT Event;
  2558. NTSTATUS status;
  2559. PAGED_CODE();
  2560. //
  2561. // Return success if FIPS already initialized.
  2562. //
  2563. if (IPSEC_DRIVER_INIT_FIPS()) {
  2564. return TRUE;
  2565. }
  2566. RtlInitUnicodeString(&DeviceName, FIPS_DEVICE_NAME);
  2567. //
  2568. // Get the file and device objects for FIPS.
  2569. //
  2570. status = IoGetDeviceObjectPointer( &DeviceName,
  2571. FILE_ALL_ACCESS,
  2572. &g_ipsec.FipsFileObject,
  2573. &pFipsDeviceObject);
  2574. if (!NT_SUCCESS(status)) {
  2575. g_ipsec.FipsFileObject = NULL;
  2576. return FALSE;
  2577. }
  2578. //
  2579. // Build the request to send to FIPS to get library table.
  2580. //
  2581. KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
  2582. pIrp = IoBuildDeviceIoControlRequest( IOCTL_FIPS_GET_FUNCTION_TABLE,
  2583. pFipsDeviceObject,
  2584. NULL,
  2585. 0,
  2586. &g_ipsec.FipsFunctionTable,
  2587. sizeof(FIPS_FUNCTION_TABLE),
  2588. FALSE,
  2589. &Event,
  2590. &StatusBlock);
  2591. if (pIrp == NULL) {
  2592. IPSEC_DEBUG(LL_A, DBF_LOAD, ("IoBuildDeviceIoControlRequest IOCTL_FIPS_GET_FUNCTION_TABLE failed."));
  2593. ObDereferenceObject(g_ipsec.FipsFileObject);
  2594. g_ipsec.FipsFileObject = NULL;
  2595. return FALSE;
  2596. }
  2597. status = IoCallDriver(pFipsDeviceObject, pIrp);
  2598. if (status == STATUS_PENDING) {
  2599. status = KeWaitForSingleObject( &Event,
  2600. Executive,
  2601. KernelMode,
  2602. FALSE,
  2603. NULL);
  2604. if (status == STATUS_SUCCESS) {
  2605. status = StatusBlock.Status;
  2606. }
  2607. }
  2608. if (status != STATUS_SUCCESS) {
  2609. IPSEC_DEBUG(LL_A, DBF_LOAD, ("IoCallDriver: IOCTL_FIPS_GET_FUNCTION_TABLE failed %#x", status));
  2610. ObDereferenceObject(g_ipsec.FipsFileObject);
  2611. g_ipsec.FipsFileObject = NULL;
  2612. return FALSE;
  2613. }
  2614. IPSEC_DRIVER_INIT_FIPS() = TRUE;
  2615. return TRUE;
  2616. }
  2617. #endif
  2618. BOOLEAN
  2619. IPSecCryptoInitialize(
  2620. VOID
  2621. )
  2622. /*++
  2623. Routine Description:
  2624. Initialize RNG and FIPS library table.
  2625. Arguments:
  2626. None
  2627. Return Value:
  2628. TRUE/FALSE
  2629. --*/
  2630. {
  2631. PAGED_CODE();
  2632. if (IPSEC_DRIVER_INIT_CRYPTO()) {
  2633. return TRUE;
  2634. }
  2635. #if FIPS
  2636. //
  2637. // Init the FIPS crypto library.
  2638. //
  2639. if (!IPSecFipsInitialize()) {
  2640. return FALSE;
  2641. }
  2642. #endif
  2643. //
  2644. // Init the RC4 key for RNG.
  2645. //
  2646. if (!IPSEC_DRIVER_INIT_RNG()) {
  2647. InitializeRNG(NULL);
  2648. if (!IPSecInitRandom()) {
  2649. ShutdownRNG(NULL);
  2650. return FALSE;
  2651. }
  2652. IPSEC_DRIVER_INIT_RNG() = TRUE;
  2653. }
  2654. IPSEC_DRIVER_INIT_CRYPTO() = TRUE;
  2655. return TRUE;
  2656. }
  2657. BOOLEAN
  2658. IPSecCryptoDeinitialize(
  2659. VOID
  2660. )
  2661. /*++
  2662. Routine Description:
  2663. Deinitialize RNG and dereference FipsFileObject.
  2664. Arguments:
  2665. None
  2666. Return Value:
  2667. TRUE/FALSE
  2668. --*/
  2669. {
  2670. PAGED_CODE();
  2671. //
  2672. // Don't forget to shutdown RNG or we will leak memory.
  2673. //
  2674. if (IPSEC_DRIVER_INIT_RNG()) {
  2675. ShutdownRNG(NULL);
  2676. }
  2677. #if FIPS
  2678. //
  2679. // Dereference FipsFileObject.
  2680. //
  2681. if (g_ipsec.FipsFileObject) {
  2682. ObDereferenceObject(g_ipsec.FipsFileObject);
  2683. }
  2684. #endif
  2685. return TRUE;
  2686. }
  2687. NTSTATUS
  2688. IPSecRegisterProtocols(
  2689. PIPSEC_REGISTER_PROTOCOL pIpsecRegisterProtocol
  2690. )
  2691. {
  2692. KIRQL kIrql = 0;
  2693. if (pIpsecRegisterProtocol->RegisterProtocol == IPSEC_REGISTER_PROTOCOLS) {
  2694. if (!IPSEC_GET_VALUE(gdwInitEsp)) {
  2695. if (TCPIP_REGISTER_PROTOCOL(
  2696. PROTOCOL_ESP,
  2697. NULL,
  2698. NULL,
  2699. IPSecESPStatus,
  2700. NULL,
  2701. NULL,
  2702. NULL
  2703. )) {
  2704. IPSEC_SET_VALUE(gdwInitEsp, 1);
  2705. }
  2706. else {
  2707. ASSERT(FALSE);
  2708. return (STATUS_INSUFFICIENT_RESOURCES);
  2709. }
  2710. }
  2711. if (!IPSEC_GET_VALUE(gdwInitAh)) {
  2712. if (TCPIP_REGISTER_PROTOCOL(
  2713. PROTOCOL_AH,
  2714. NULL,
  2715. NULL,
  2716. IPSecAHStatus,
  2717. NULL,
  2718. NULL,
  2719. NULL
  2720. )) {
  2721. IPSEC_SET_VALUE(gdwInitAh, 1);
  2722. }
  2723. else {
  2724. ASSERT(FALSE);
  2725. TCPIP_DEREGISTER_PROTOCOL(PROTOCOL_ESP);
  2726. IPSEC_SET_VALUE(gdwInitEsp, 0);
  2727. return (STATUS_INSUFFICIENT_RESOURCES);
  2728. }
  2729. }
  2730. }
  2731. else if (pIpsecRegisterProtocol->RegisterProtocol == IPSEC_DEREGISTER_PROTOCOLS) {
  2732. if (IPSEC_GET_VALUE(gdwInitEsp)) {
  2733. TCPIP_DEREGISTER_PROTOCOL(PROTOCOL_ESP);
  2734. IPSEC_SET_VALUE(gdwInitEsp, 0);
  2735. }
  2736. if (IPSEC_GET_VALUE(gdwInitAh)) {
  2737. TCPIP_DEREGISTER_PROTOCOL(PROTOCOL_AH);
  2738. IPSEC_SET_VALUE(gdwInitAh, 0);
  2739. }
  2740. AcquireWriteLock(&g_ipsec.SADBLock, &kIrql);
  2741. ASSERT (gpParserIfEntry == NULL);
  2742. FlushAllParserEntries();
  2743. ReleaseWriteLock(&g_ipsec.SADBLock, kIrql);
  2744. }
  2745. else {
  2746. return (STATUS_INVALID_PARAMETER);
  2747. }
  2748. return (STATUS_SUCCESS);
  2749. }
  2750. VOID IPSecCleanupBoottimeStatefulStructs(VOID)
  2751. {
  2752. KIRQL kIrql;
  2753. IPSEC_DEBUG(LL_A,DBF_BOOTTIME,
  2754. ("Number of connections %d",
  2755. g_ipsec.BootBufferPool->ulEntriesUsed));
  2756. AcquireWriteLock(&g_ipsec.SADBLock,&kIrql);
  2757. //Release memory used for the boottime stateful
  2758. //mode operation
  2759. if (g_ipsec.BootStatefulHT){
  2760. IPSecFreeMemory(g_ipsec.BootStatefulHT);
  2761. g_ipsec.BootStatefulHT = NULL;
  2762. }
  2763. if (g_ipsec.BootBufferPool){
  2764. IPSecFreeMemory(g_ipsec.BootBufferPool);
  2765. g_ipsec.BootBufferPool = NULL;
  2766. }
  2767. //Let the exemptlist hang around
  2768. //We will use it only if someone
  2769. //moves us back into block mode.
  2770. //We dont expect it to be too big
  2771. //anyway.
  2772. ReleaseWriteLock(&g_ipsec.SADBLock, kIrql);
  2773. }
  2774. VOID IPSecLogBootOperationMode(VOID)
  2775. {
  2776. NDIS_STATUS status;
  2777. switch (g_ipsec.OperationMode){
  2778. case IPSEC_BOOTTIME_STATEFUL_MODE:
  2779. status= LOG_EVENT(
  2780. g_ipsec.IPSecDriverObject,
  2781. EVENT_IPSEC_BOOT_STATEFUL_MODE,
  2782. 1,
  2783. 0,
  2784. NULL,
  2785. 0,
  2786. NULL);
  2787. break;
  2788. case IPSEC_BYPASS_MODE:
  2789. case IPSEC_SECURE_MODE:
  2790. status = LOG_EVENT(
  2791. g_ipsec.IPSecDriverObject,
  2792. EVENT_IPSEC_BOOT_BYPASS_MODE,
  2793. 1,
  2794. 0,
  2795. NULL,
  2796. 0,
  2797. NULL);
  2798. break;
  2799. case IPSEC_BLOCK_MODE:
  2800. status = LOG_EVENT(
  2801. g_ipsec.IPSecDriverObject,
  2802. EVENT_IPSEC_BOOT_BLOCK_MODE,
  2803. 1,
  2804. 0,
  2805. NULL,
  2806. 0,
  2807. NULL);
  2808. break;
  2809. default:
  2810. break;
  2811. }
  2812. IPSEC_DEBUG(LL_A,DBF_BOOTTIME,("Boot Operation Mode = %d\n",g_ipsec.OperationMode));
  2813. }
  2814. VOID IPSecLogChangeOperationMode(VOID)
  2815. {
  2816. switch (g_ipsec.OperationMode){
  2817. case IPSEC_BLOCK_MODE:
  2818. LOG_EVENT(
  2819. g_ipsec.IPSecDriverObject,
  2820. EVENT_IPSEC_SET_BLOCK_MODE,
  2821. 1,
  2822. 0,
  2823. NULL,
  2824. 0,
  2825. NULL);
  2826. break;
  2827. case IPSEC_SECURE_MODE:
  2828. LOG_EVENT(
  2829. g_ipsec.IPSecDriverObject,
  2830. EVENT_IPSEC_SET_SECURE_MODE,
  2831. 1,
  2832. 0,
  2833. NULL,
  2834. 0,
  2835. NULL);
  2836. break;
  2837. case IPSEC_BYPASS_MODE:
  2838. LOG_EVENT(
  2839. g_ipsec.IPSecDriverObject,
  2840. EVENT_IPSEC_SET_BYPASS_MODE,
  2841. 1,
  2842. 0,
  2843. NULL,
  2844. 0,
  2845. NULL);
  2846. break;
  2847. default:
  2848. break;
  2849. }
  2850. }