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.

1663 lines
39 KiB

  1. #include <lsapch2.h>
  2. #pragma hdrstop
  3. #include "adtp.h"
  4. #include "adtgen.h"
  5. #include "adtgenp.h"
  6. //
  7. // These variables describe and protect the list of registered
  8. // event sources.
  9. //
  10. LIST_ENTRY LsapAdtEventSourceList = {0};
  11. RTL_CRITICAL_SECTION LsapAdtEventSourceListLock = {0};
  12. DWORD LsapAdtEventSourceCount = 0;
  13. #define MAX_EVENT_SOURCE_NAME_LENGTH 256
  14. #define LsapAdtLockEventSourceList() RtlEnterCriticalSection(&LsapAdtEventSourceListLock)
  15. #define LsapAdtUnlockEventSourceList() RtlLeaveCriticalSection(&LsapAdtEventSourceListLock)
  16. //
  17. // The number of parameters which need to be prepended internally to an AUDIT_PARAMS so that
  18. // extensible auditing can function properly. The parameters are the pSid, the string "Security",
  19. // the actual source string, and the actual source audit ID.
  20. //
  21. #define EXTENSIBLE_AUDIT_PREPEND_COUNT 4
  22. //
  23. // Our registry key name.
  24. //
  25. #define SECURITY_KEY_NAME L"SYSTEM\\CurrentControlSet\\Services\\EventLog\\Security"
  26. #define DEBUG_AUTHZ 0
  27. #define VERIFY_PID 0x1
  28. NTSTATUS
  29. LsapAdtValidateExtensibleAuditingCaller(
  30. OUT PDWORD pdwCallerProcessId,
  31. IN BOOL bPrivCheck
  32. );
  33. PLSAP_SECURITY_EVENT_SOURCE
  34. LsapAdtLocateSecurityEventSourceByName(
  35. IN PCWSTR szEventSourceName
  36. );
  37. PLSAP_SECURITY_EVENT_SOURCE
  38. LsapAdtLocateSecurityEventSourceByIdentifier(
  39. IN PLUID pIdentifier
  40. );
  41. PLSAP_SECURITY_EVENT_SOURCE
  42. LsapAdtLocateSecurityEventSourceBySource(
  43. IN PLSAP_SECURITY_EVENT_SOURCE pSource
  44. );
  45. LONG
  46. LsapAdtReferenceSecurityEventSource(
  47. IN OUT PLSAP_SECURITY_EVENT_SOURCE pSource
  48. );
  49. LONG
  50. LsapAdtDereferenceSecurityEventSource(
  51. IN OUT PLSAP_SECURITY_EVENT_SOURCE pSource
  52. );
  53. VOID
  54. LsapAdtDeleteSecurityEventSource(
  55. IN OUT PLSAP_SECURITY_EVENT_SOURCE pSource
  56. );
  57. NTSTATUS
  58. LsapAdtCreateSourceAuditParams(
  59. IN DWORD dwFlags,
  60. IN PSID pSid,
  61. IN PLSAP_SECURITY_EVENT_SOURCE pSource,
  62. IN DWORD dwAuditId,
  63. IN PAUDIT_PARAMS pOldParams,
  64. OUT PAUDIT_PARAMS pNewParams
  65. );
  66. NTSTATUS
  67. LsapAdtVerifySecurityEventSource(
  68. IN LPCWSTR szEventSourceName,
  69. IN PUNICODE_STRING pImageName,
  70. IN OUT PDWORD pdwInstalledSourceFlags
  71. );
  72. NTSTATUS
  73. LsapAdtAuditSecuritySource(
  74. IN USHORT AuditEventType,
  75. IN PLSAP_SECURITY_EVENT_SOURCE pEventSource,
  76. IN BOOL bRegistration
  77. );
  78. LONG
  79. LsapAdtReferenceSecurityEventSource(
  80. IN OUT PLSAP_SECURITY_EVENT_SOURCE pSource
  81. )
  82. /**
  83. Routine Description:
  84. Adds one reference to pSource. This assumes that all locks on the source
  85. list are held.
  86. Arguments:
  87. pSource - pointer to LSAP_SECURITY_EVENT_SOURCE.
  88. Return Value:
  89. The number of references remaining on the pSource.
  90. **/
  91. {
  92. LONG l = InterlockedIncrement(&pSource->dwRefCount);
  93. #if DEBUG_AUTHZ
  94. DbgPrint("Source 0x%x +refcount = %d\n", pSource, pSource->dwRefCount);
  95. #endif
  96. return l;
  97. }
  98. LONG
  99. LsapAdtDereferenceSecurityEventSource(
  100. IN OUT PLSAP_SECURITY_EVENT_SOURCE pSource
  101. )
  102. /**
  103. Routine Description:
  104. Removes a reference from pSource and deletes the source if the refcount
  105. has reached 0.
  106. This assumes that all necessary locks are held on the source list, so that
  107. if deletion is necessary no list corruption will result.
  108. Arguments:
  109. pSource - pointer to LSAP_SECURITY_EVENT_SOURCE.
  110. Return Value:
  111. The number of references remaining on the pSource.
  112. **/
  113. {
  114. LONG l = InterlockedDecrement(&pSource->dwRefCount);
  115. #if DEBUG_AUTHZ
  116. DbgPrint("Source 0x%x %S -refcount = %d\n", pSource, pSource->szEventSourceName, pSource->dwRefCount);
  117. #endif
  118. if (l == 0)
  119. {
  120. LsapAdtAuditSecuritySource(
  121. EVENTLOG_AUDIT_SUCCESS,
  122. pSource,
  123. FALSE
  124. );
  125. LsapAdtDeleteSecurityEventSource(pSource);
  126. }
  127. return l;
  128. }
  129. VOID
  130. LsapAdtDeleteSecurityEventSource(
  131. PLSAP_SECURITY_EVENT_SOURCE pSource
  132. )
  133. /**
  134. Routine Description:
  135. Deletes pSource from the global source list. This assumes that
  136. all locks necessary are held.
  137. Arguments:
  138. pSource - pointer to LSAP_SECURITY_EVENT_SOURCE.
  139. Return Value:
  140. None.
  141. **/
  142. {
  143. RemoveEntryList(
  144. &pSource->List
  145. );
  146. #if DEBUG_AUTHZ
  147. DbgPrint("Source 0x%x %S deleted. List size = %d\n", pSource, pSource->szEventSourceName, LsapAdtEventSourceCount);
  148. #endif
  149. LsapFreeLsaHeap(pSource);
  150. ASSERT(LsapAdtEventSourceCount > 0);
  151. LsapAdtEventSourceCount--;
  152. }
  153. NTSTATUS
  154. LsapAdtInitializeExtensibleAuditing(
  155. )
  156. /**
  157. Routine Description:
  158. Initializes necessary data structures for extensible
  159. auditing support.
  160. Arguments:
  161. None.
  162. Return Value:
  163. NTSTATUS.
  164. **/
  165. {
  166. NTSTATUS Status;
  167. InitializeListHead(
  168. &LsapAdtEventSourceList
  169. );
  170. LsapAdtEventSourceCount = 0;
  171. Status = RtlInitializeCriticalSection(
  172. &LsapAdtEventSourceListLock
  173. );
  174. return Status;
  175. }
  176. NTSTATUS
  177. LsapAdtRegisterSecurityEventSource(
  178. IN DWORD dwFlags,
  179. IN PCWSTR szEventSourceName,
  180. OUT SECURITY_SOURCE_HANDLE * phEventSource
  181. )
  182. /**
  183. Routine Description:
  184. This is the routine that allows a client to register a new security
  185. source with the LSA. It adds the source to the global list and returns
  186. a handle to the client for future reference to the new security event
  187. source.
  188. Arguments:
  189. dwFlags - TBD.
  190. szEventSourceName - the name to describe the new source.
  191. phEventSource - pointer to handle which receives the new source allocation.
  192. Return Value:
  193. NTSTATUS.
  194. **/
  195. {
  196. NTSTATUS Status;
  197. DWORD dwCallerProcessId;
  198. BOOL b;
  199. USHORT AuditEventType;
  200. DWORD dwInstalledSourceFlags = 0;
  201. PLSAP_SECURITY_EVENT_SOURCE pEventSource = NULL;
  202. BOOL bLock = FALSE;
  203. DWORD dwNameLength;
  204. HANDLE hProcess = NULL;
  205. UCHAR ProcBuffer[80];
  206. PUNICODE_STRING pProcessName = (PUNICODE_STRING) ProcBuffer;
  207. DWORD dwLength = 0;
  208. if (NULL == szEventSourceName || NULL == phEventSource)
  209. {
  210. return STATUS_INVALID_PARAMETER;
  211. }
  212. dwNameLength = wcslen(szEventSourceName);
  213. if (dwNameLength > MAX_EVENT_SOURCE_NAME_LENGTH || dwNameLength == 0)
  214. {
  215. return STATUS_INVALID_PARAMETER;
  216. }
  217. //
  218. // Make sure the caller has the Audit privilege.
  219. //
  220. Status = LsapAdtValidateExtensibleAuditingCaller(
  221. &dwCallerProcessId,
  222. TRUE
  223. );
  224. if (!NT_SUCCESS(Status))
  225. {
  226. return Status;
  227. }
  228. //
  229. // Make sure this process has the name that was registered.
  230. // Open the process and query the image name.
  231. //
  232. hProcess = OpenProcess(
  233. PROCESS_QUERY_INFORMATION,
  234. FALSE,
  235. dwCallerProcessId
  236. );
  237. if (hProcess == NULL)
  238. {
  239. Status = LsapWinerrorToNtStatus(GetLastError());
  240. goto Cleanup;
  241. }
  242. Status = NtQueryInformationProcess(
  243. hProcess,
  244. ProcessImageFileName,
  245. pProcessName,
  246. sizeof(ProcBuffer),
  247. &dwLength
  248. );
  249. if (Status == STATUS_INFO_LENGTH_MISMATCH)
  250. {
  251. pProcessName = LsapAllocateLsaHeap(dwLength + sizeof(WCHAR));
  252. if (NULL == pProcessName)
  253. {
  254. Status = STATUS_NO_MEMORY;
  255. goto Cleanup;
  256. }
  257. Status = NtQueryInformationProcess(
  258. hProcess,
  259. ProcessImageFileName,
  260. pProcessName,
  261. dwLength,
  262. &dwLength
  263. );
  264. }
  265. if (!NT_SUCCESS(Status))
  266. {
  267. goto Cleanup;
  268. }
  269. LsapAdtSubstituteDriveLetter(pProcessName);
  270. //
  271. // Verify the existence of this source in the registry. The source
  272. // must have been installed in order for it to be registered at
  273. // runtime.
  274. //
  275. Status = LsapAdtVerifySecurityEventSource(
  276. szEventSourceName,
  277. pProcessName,
  278. &dwInstalledSourceFlags
  279. );
  280. if (!NT_SUCCESS(Status))
  281. {
  282. goto Cleanup;
  283. }
  284. //
  285. // Build the LSAP_EVENT_SOURCE. Allocate space for the structure and the embedded name string.
  286. //
  287. pEventSource = LsapAllocateLsaHeap(
  288. sizeof(LSAP_SECURITY_EVENT_SOURCE) + (sizeof(WCHAR) * (dwNameLength + 1))
  289. );
  290. if (NULL == pEventSource)
  291. {
  292. Status = STATUS_NO_MEMORY;
  293. goto Cleanup;
  294. }
  295. RtlZeroMemory(
  296. pEventSource,
  297. sizeof(LSAP_SECURITY_EVENT_SOURCE) + (sizeof(WCHAR) * (dwNameLength + 1))
  298. );
  299. pEventSource->szEventSourceName = (PWSTR)((PUCHAR)pEventSource + sizeof(LSAP_SECURITY_EVENT_SOURCE));
  300. wcsncpy(
  301. pEventSource->szEventSourceName,
  302. szEventSourceName,
  303. dwNameLength
  304. );
  305. pEventSource->dwProcessId = dwCallerProcessId;
  306. b = AllocateLocallyUniqueId(&pEventSource->Identifier);
  307. if (!b)
  308. {
  309. Status = LsapWinerrorToNtStatus(GetLastError());
  310. goto Cleanup;
  311. }
  312. //
  313. // Now make sure no other source has registered with the same name.
  314. // Hold the lock for this operation and the insertion to avoid
  315. // a race condition for registering identical names.
  316. //
  317. Status = LsapAdtLockEventSourceList();
  318. if (!NT_SUCCESS(Status))
  319. {
  320. goto Cleanup;
  321. }
  322. bLock = TRUE;
  323. //
  324. // Don't bother with this check if the installed source flags allows
  325. // multiple instances of the same provider name. If the Locate
  326. // function returns NULL then no source already is registered with
  327. // this name.
  328. //
  329. if ((dwInstalledSourceFlags & AUTHZ_ALLOW_MULTIPLE_SOURCE_INSTANCES) ||
  330. NULL == LsapAdtLocateSecurityEventSourceByName(szEventSourceName))
  331. {
  332. //
  333. // Take out an initial reference on this source.
  334. //
  335. LsapAdtReferenceSecurityEventSource(pEventSource);
  336. //
  337. // Add the entry to the list.
  338. //
  339. LsapAdtEventSourceCount++;
  340. InsertTailList(
  341. &LsapAdtEventSourceList,
  342. &pEventSource->List
  343. );
  344. #if DEBUG_AUTHZ
  345. DbgPrint("Source 0x%x %S created. List size = %d\n", pEventSource, pEventSource->szEventSourceName, LsapAdtEventSourceCount);
  346. #endif
  347. }
  348. else
  349. {
  350. //
  351. // The name is already taken.
  352. //
  353. Status = STATUS_OBJECT_NAME_EXISTS;
  354. goto Cleanup;
  355. }
  356. Cleanup:
  357. if (hProcess)
  358. {
  359. CloseHandle(hProcess);
  360. }
  361. if (pProcessName != NULL && pProcessName != (PUNICODE_STRING) ProcBuffer)
  362. {
  363. LsapFreeLsaHeap(pProcessName);
  364. }
  365. if (bLock)
  366. {
  367. NTSTATUS TempStatus;
  368. TempStatus = LsapAdtUnlockEventSourceList();
  369. ASSERT(NT_SUCCESS(TempStatus));
  370. }
  371. if (NT_SUCCESS(Status))
  372. {
  373. *phEventSource = (SECURITY_SOURCE_HANDLE)pEventSource;
  374. AuditEventType = EVENTLOG_AUDIT_SUCCESS;
  375. }
  376. else
  377. {
  378. AuditEventType = EVENTLOG_AUDIT_FAILURE;
  379. }
  380. //
  381. // Audit the registration.
  382. //
  383. (VOID) LsapAdtAuditSecuritySource(
  384. AuditEventType,
  385. pEventSource,
  386. TRUE
  387. );
  388. if (!NT_SUCCESS(Status))
  389. {
  390. if (pEventSource)
  391. {
  392. LsapFreeLsaHeap(pEventSource);
  393. }
  394. }
  395. return Status;
  396. }
  397. NTSTATUS
  398. LsapAdtReportSecurityEvent(
  399. IN DWORD dwFlags,
  400. IN PLSAP_SECURITY_EVENT_SOURCE pSource,
  401. IN DWORD dwAuditId,
  402. IN PSID pSid,
  403. IN PAUDIT_PARAMS pParams
  404. )
  405. /**
  406. Routine Description:
  407. This routine generates an audit / security event for a registered source.
  408. Arguments:
  409. dwFlags - APF_AuditSuccess, APF_AuditFailure
  410. pSource - pointer to the source which is generating the event.
  411. dwAuditId - the ID of the audit.
  412. pSid - the caller's sid to be placed into the audit.
  413. pParams - the parameters of the audit. Note that extensible auditing
  414. differs from the rest of the system in that the first 2 parameters
  415. are not supposed to be the SID and the string "Security." We prepend
  416. this data to the audit internally. The pParams passed in should contain
  417. only the data of the audit. We take care of all modifications that
  418. are necessary for the eventviewer to properly parse the audit.
  419. Return Value:
  420. NTSTATUS.
  421. **/
  422. {
  423. BOOLEAN bAudit;
  424. UINT AuditEventType;
  425. SE_ADT_OBJECT_TYPE ObjectTypes[MAX_OBJECT_TYPES];
  426. LONG Refs;
  427. NTSTATUS Status = STATUS_SUCCESS;
  428. SE_ADT_PARAMETER_ARRAY SeAuditParameters = {0};
  429. UNICODE_STRING Strings[SE_MAX_AUDIT_PARAM_STRINGS] = {0};
  430. PSE_ADT_OBJECT_TYPE pObjectTypes = ObjectTypes;
  431. AUDIT_PARAMS NewParams = {0};
  432. AUDIT_PARAM ParamArray[SE_MAX_AUDIT_PARAMETERS] = {0};
  433. BOOLEAN bRef = FALSE;
  434. BOOLEAN bLock = FALSE;
  435. if (pParams->Count < 0 || pParams->Count > (SE_MAX_AUDIT_PARAM_STRINGS - EXTENSIBLE_AUDIT_PREPEND_COUNT))
  436. {
  437. return STATUS_INVALID_PARAMETER;
  438. }
  439. if (!RtlValidSid(pSid))
  440. {
  441. return STATUS_INVALID_PARAMETER;
  442. }
  443. Status = LsapAdtLockEventSourceList();
  444. if (!NT_SUCCESS(Status))
  445. {
  446. goto Cleanup;
  447. }
  448. bLock = TRUE;
  449. //
  450. // Make certain that the source is registered.
  451. //
  452. if (LsapAdtLocateSecurityEventSourceBySource(pSource) == NULL)
  453. {
  454. Status = STATUS_INVALID_PARAMETER;
  455. goto Cleanup;
  456. }
  457. else
  458. {
  459. Refs = LsapAdtReferenceSecurityEventSource(pSource);
  460. bRef = TRUE;
  461. //
  462. // There should always be one other reference on a source that is
  463. // generating an audit (the initial reference should still be present).
  464. //
  465. ASSERT(Refs > 1);
  466. }
  467. //
  468. // We have protected the pSource pointer; we can safely unlock the list.
  469. //
  470. (VOID) LsapAdtUnlockEventSourceList();
  471. bLock = FALSE;
  472. if ( pParams->Flags & APF_AuditSuccess )
  473. {
  474. AuditEventType = EVENTLOG_AUDIT_SUCCESS;
  475. }
  476. else
  477. {
  478. AuditEventType = EVENTLOG_AUDIT_FAILURE;
  479. }
  480. //
  481. // Check if auditing is enabled for ObjectAccess and this user. All
  482. // third party audits fall under the policy of the object access category.
  483. //
  484. Status = LsapAdtAuditingEnabledBySid(
  485. AuditCategoryObjectAccess,
  486. pSid,
  487. AuditEventType,
  488. &bAudit
  489. );
  490. if (NT_SUCCESS(Status) && bAudit)
  491. {
  492. //
  493. // Construct a legacy style audit params from the data.
  494. // Utilize the SE_AUDITID_GENERIC_AUDIT_EVENT type to
  495. // allow eventvwr to parse the audit properly.
  496. //
  497. NewParams.Parameters = ParamArray;
  498. Status = LsapAdtCreateSourceAuditParams(
  499. dwFlags,
  500. pSid,
  501. pSource,
  502. dwAuditId,
  503. pParams,
  504. &NewParams
  505. );
  506. if (!NT_SUCCESS(Status))
  507. {
  508. goto Cleanup;
  509. }
  510. SeAuditParameters.Type = (USHORT) AuditEventType;
  511. SeAuditParameters.CategoryId = SE_CATEGID_OBJECT_ACCESS;
  512. SeAuditParameters.AuditId = SE_AUDITID_GENERIC_AUDIT_EVENT;
  513. SeAuditParameters.ParameterCount = NewParams.Count;
  514. //
  515. // Map AUDIT_PARAMS structure to SE_ADT_PARAMETER_ARRAY structure
  516. //
  517. Status = LsapAdtMapAuditParams( &NewParams,
  518. &SeAuditParameters,
  519. (PUNICODE_STRING) Strings,
  520. &pObjectTypes );
  521. if (!NT_SUCCESS(Status))
  522. {
  523. goto Cleanup;
  524. }
  525. //
  526. // write the params to eventlog
  527. //
  528. Status = LsapAdtWriteLog(&SeAuditParameters);
  529. if (!NT_SUCCESS(Status))
  530. {
  531. goto Cleanup;
  532. }
  533. }
  534. else
  535. {
  536. goto Cleanup;
  537. }
  538. Cleanup:
  539. if (bRef)
  540. {
  541. LsapAdtDereferenceSecurityEventSource(pSource);
  542. }
  543. if (bLock)
  544. {
  545. LsapAdtUnlockEventSourceList();
  546. }
  547. if (!NT_SUCCESS(Status))
  548. {
  549. //
  550. // crash on failure if specified by the security policy
  551. //
  552. // But do not crash on documented errors
  553. //
  554. if ( ( Status != STATUS_INVALID_PARAMETER ) &&
  555. ( Status != STATUS_AUDITING_DISABLED ) &&
  556. ( Status != STATUS_NOT_FOUND ) )
  557. {
  558. LsapAuditFailed(Status);
  559. }
  560. }
  561. //
  562. // Free pObjectTypes if we are not using the stack buffer.
  563. //
  564. if (pObjectTypes && (pObjectTypes != ObjectTypes))
  565. {
  566. LsapFreeLsaHeap(pObjectTypes);
  567. }
  568. return Status;
  569. }
  570. NTSTATUS
  571. LsapAdtUnregisterSecurityEventSource(
  572. IN DWORD dwFlags,
  573. IN OUT SECURITY_SOURCE_HANDLE * phEventSource
  574. )
  575. /**
  576. Routine Description:
  577. This frees (dereferences once) the LSAP_EVENT_SOURCE that was created via LsapRegisterSecurityEventSource.
  578. Arguments:
  579. dwFlags - TBD
  580. phEventSource - pointer to a SECURITY_SOURCE_HANDLE (pointer to an event source)
  581. Return Value:
  582. NTSTATUS.
  583. **/
  584. {
  585. NTSTATUS Status;
  586. DWORD dwCallerProcessId;
  587. if (NULL == phEventSource)
  588. {
  589. Status = STATUS_INVALID_PARAMETER;
  590. goto Cleanup;
  591. }
  592. //
  593. // we don't care if the caller has the privilege enabled at this time.
  594. //
  595. Status = LsapAdtValidateExtensibleAuditingCaller(
  596. &dwCallerProcessId,
  597. FALSE
  598. );
  599. if (!NT_SUCCESS(Status))
  600. {
  601. goto Cleanup;
  602. }
  603. Status = LsapAdtRundownSecurityEventSource(
  604. VERIFY_PID,
  605. dwCallerProcessId,
  606. phEventSource
  607. );
  608. Cleanup:
  609. return Status;
  610. }
  611. NTSTATUS
  612. LsapAdtRundownSecurityEventSource(
  613. IN DWORD dwFlags,
  614. IN DWORD dwCallerProcessId,
  615. IN OUT SECURITY_SOURCE_HANDLE * phEventSource
  616. )
  617. /**
  618. Routine Description:
  619. This frees (dereferences once) the LSAP_EVENT_SOURCE that was created via LsapRegisterSecurityEventSource.
  620. Arguments:
  621. dwFlags - VERIFY_PID - verify that the process which installed the source is the
  622. one deleting it.
  623. dwCallerProcessId - the PID of the process which initiated the call.
  624. phEventSource - pointer to a SECURITY_SOURCE_HANDLE (pointer to an event source)
  625. Return Value:
  626. NTSTATUS.
  627. **/
  628. {
  629. NTSTATUS Status;
  630. BOOL bLock = FALSE;
  631. PLSAP_SECURITY_EVENT_SOURCE pEventSource = NULL;
  632. if (NULL == phEventSource)
  633. {
  634. Status = STATUS_INVALID_PARAMETER;
  635. goto Cleanup;
  636. }
  637. pEventSource = (PLSAP_SECURITY_EVENT_SOURCE) *phEventSource;
  638. Status = LsapAdtLockEventSourceList();
  639. if (!NT_SUCCESS(Status))
  640. {
  641. goto Cleanup;
  642. }
  643. bLock = TRUE;
  644. if (LsapAdtLocateSecurityEventSourceBySource(pEventSource))
  645. {
  646. //
  647. // If we are asked to verify the pid then make sure that the current
  648. // process has the same ID as the one who registered the source.
  649. //
  650. if ((dwFlags & VERIFY_PID) && (pEventSource->dwProcessId != dwCallerProcessId))
  651. {
  652. Status = STATUS_ACCESS_DENIED;
  653. goto Cleanup;
  654. }
  655. LsapAdtDereferenceSecurityEventSource(pEventSource);
  656. }
  657. else
  658. {
  659. Status = STATUS_OBJECT_NAME_NOT_FOUND;
  660. goto Cleanup;
  661. }
  662. Cleanup:
  663. if (bLock)
  664. {
  665. NTSTATUS TempStatus;
  666. TempStatus = LsapAdtUnlockEventSourceList();
  667. ASSERT(NT_SUCCESS(TempStatus));
  668. }
  669. if (NT_SUCCESS(Status))
  670. {
  671. *phEventSource = NULL;
  672. }
  673. return Status;
  674. }
  675. PLSAP_SECURITY_EVENT_SOURCE
  676. LsapAdtLocateSecurityEventSourceByName(
  677. IN PCWSTR szEventSourceName
  678. )
  679. /**
  680. Routine Description:
  681. This returns the event source associated with the source name.
  682. The caller is responsible for locking the list.
  683. Arguments:
  684. szEventSourceName - source name to look up.
  685. Return Value:
  686. Either a valid pointer to the source associated with the szEventSourceName, or NULL
  687. if the name is not registered.
  688. **/
  689. {
  690. PLIST_ENTRY pList;
  691. PLSAP_SECURITY_EVENT_SOURCE pListEventSource;
  692. DWORD dwNameLength;
  693. DWORD dwCount = 0;
  694. dwNameLength = wcslen(szEventSourceName);
  695. pList = LsapAdtEventSourceList.Flink;
  696. ASSERT(pList != NULL);
  697. if (pList == NULL)
  698. {
  699. return NULL;
  700. }
  701. while (pList != &LsapAdtEventSourceList)
  702. {
  703. if (dwCount > LsapAdtEventSourceCount)
  704. {
  705. break;
  706. }
  707. pListEventSource = CONTAINING_RECORD(
  708. pList,
  709. LSAP_SECURITY_EVENT_SOURCE,
  710. List
  711. );
  712. if (dwNameLength == wcslen(pListEventSource->szEventSourceName) &&
  713. 0 == wcsncmp(
  714. szEventSourceName,
  715. pListEventSource->szEventSourceName,
  716. dwNameLength
  717. ))
  718. {
  719. return pListEventSource;
  720. }
  721. pList = pList->Flink;
  722. dwCount++;
  723. }
  724. return NULL;
  725. }
  726. PLSAP_SECURITY_EVENT_SOURCE
  727. LsapAdtLocateSecurityEventSourceByIdentifier(
  728. IN PLUID pIdentifier
  729. )
  730. /**
  731. Routine Description:
  732. This returns the event source associated with the source identifier.
  733. The caller is responsible for locking the list.
  734. Arguments:
  735. pIdentifier - pointer to LUID associated with an event source.
  736. Return Value:
  737. A valid pointer if the passed LUID is associated with a source, or NULL if
  738. not.
  739. **/
  740. {
  741. PLIST_ENTRY pList;
  742. PLSAP_SECURITY_EVENT_SOURCE pListEventSource;
  743. DWORD dwCount = 0;
  744. pList = LsapAdtEventSourceList.Flink;
  745. ASSERT(pList != NULL);
  746. if (pList == NULL)
  747. {
  748. return NULL;
  749. }
  750. while (pList != &LsapAdtEventSourceList)
  751. {
  752. if (dwCount > LsapAdtEventSourceCount)
  753. {
  754. break;
  755. }
  756. pListEventSource = CONTAINING_RECORD(
  757. pList,
  758. LSAP_SECURITY_EVENT_SOURCE,
  759. List
  760. );
  761. if (RtlEqualLuid(&pListEventSource->Identifier, pIdentifier))
  762. {
  763. return pListEventSource;
  764. }
  765. pList = pList->Flink;
  766. dwCount++;
  767. }
  768. return NULL;
  769. }
  770. PLSAP_SECURITY_EVENT_SOURCE
  771. LsapAdtLocateSecurityEventSourceBySource(
  772. PLSAP_SECURITY_EVENT_SOURCE pSource
  773. )
  774. /**
  775. Routine Description:
  776. This routine returns either a pointer to the source, or NULL if the
  777. source is not registered.
  778. Arguments:
  779. pSource - a pointer to a source.
  780. Return Value:
  781. Either a valid pointer (which will be equal to the pSource argument) or NULL if
  782. the passed pSource value is not a registered source.
  783. **/
  784. {
  785. PLIST_ENTRY pList;
  786. PLSAP_SECURITY_EVENT_SOURCE pListEventSource;
  787. DWORD dwCount = 0;
  788. pList = LsapAdtEventSourceList.Flink;
  789. ASSERT(pList != NULL);
  790. if (pList == NULL)
  791. {
  792. return NULL;
  793. }
  794. while (pList != &LsapAdtEventSourceList)
  795. {
  796. if (dwCount > LsapAdtEventSourceCount)
  797. {
  798. break;
  799. }
  800. pListEventSource = CONTAINING_RECORD(
  801. pList,
  802. LSAP_SECURITY_EVENT_SOURCE,
  803. List
  804. );
  805. if (pListEventSource == pSource)
  806. {
  807. return pListEventSource;
  808. }
  809. pList = pList->Flink;
  810. dwCount++;
  811. }
  812. return NULL;
  813. }
  814. NTSTATUS
  815. LsapAdtValidateExtensibleAuditingCaller(
  816. IN OUT PDWORD pdwCallerProcessId,
  817. IN BOOL bPrivCheck
  818. )
  819. /**
  820. Routine Description:
  821. This verifies that the caller is on the local box and that
  822. the client also possesses the necessary privilege (SeAuditPrivilege).
  823. Arguments:
  824. pdwCallerProcessId - pointer to DWORD which returns the caller's
  825. PID.
  826. bPrivCheck - boolean indicating if a privilege check should be performed.
  827. Return Value:
  828. NTSTATUS.
  829. **/
  830. {
  831. NTSTATUS Status;
  832. DWORD dwRpcTransportType;
  833. DWORD dwLocalClient;
  834. //
  835. // Find out the transport over which we are receiving this call.
  836. //
  837. Status = I_RpcBindingInqTransportType(
  838. NULL,
  839. &dwRpcTransportType
  840. );
  841. if (RPC_S_OK != Status)
  842. {
  843. Status = I_RpcMapWin32Status(
  844. Status
  845. );
  846. goto Cleanup;
  847. }
  848. //
  849. // If the transport is anything other than LPC, error out.
  850. // We want to support only LPC for audit calls.
  851. //
  852. if (dwRpcTransportType != TRANSPORT_TYPE_LPC)
  853. {
  854. Status = RPC_NT_PROTSEQ_NOT_SUPPORTED;
  855. goto Cleanup;
  856. }
  857. //
  858. // The callers are forced to be local.
  859. //
  860. Status = I_RpcBindingIsClientLocal(
  861. NULL,
  862. &dwLocalClient
  863. );
  864. if (!NT_SUCCESS(Status))
  865. {
  866. goto Cleanup;
  867. }
  868. if (!dwLocalClient)
  869. {
  870. Status = STATUS_INVALID_PARAMETER;
  871. goto Cleanup;
  872. }
  873. //
  874. // Get the PID of the caller.
  875. //
  876. Status = I_RpcBindingInqLocalClientPID(
  877. NULL,
  878. pdwCallerProcessId
  879. );
  880. if (!NT_SUCCESS(Status))
  881. {
  882. goto Cleanup;
  883. }
  884. if (bPrivCheck)
  885. {
  886. //
  887. // Make sure that the caller has audit privilege.
  888. // (LsapAdtCheckAuditPrivilege calls RpcImpersonateClient)
  889. //
  890. Status = LsapAdtCheckAuditPrivilege();
  891. if (!NT_SUCCESS(Status))
  892. {
  893. goto Cleanup;
  894. }
  895. }
  896. Cleanup:
  897. return Status;
  898. }
  899. NTSTATUS
  900. LsapAdtCreateSourceAuditParams(
  901. IN DWORD dwFlags,
  902. IN PSID pSid,
  903. IN PLSAP_SECURITY_EVENT_SOURCE pSource,
  904. IN DWORD dwAuditId,
  905. IN PAUDIT_PARAMS pOldParams,
  906. IN OUT PAUDIT_PARAMS pNewParams
  907. )
  908. /**
  909. Routine Description:
  910. This is an internal routine which constructs an AUDIT_PARAMS for eventlog
  911. to properly display -- with params 0 and 1 being the pSid and the string "Security",
  912. and strings 2 and 3 being the actual source name and the actual source AuditId.
  913. Arguments:
  914. dwFlags - AUTHZ_AUDIT_INSTANCE_INFORMATION - prepends audit with source name, identifier,
  915. and PID.
  916. pSid - the Sid to be displayed in eventlog as the user.
  917. pSource - the source generating the audit.
  918. dwAuditId - the AuditId to be generated.
  919. pOldParams - an AUDIT_PARAMS that contains only the data for the audit as passed from
  920. the client, without any ot the internal (above mentioned) data that eventlog uses
  921. to parse and display the data.
  922. pNewParams - an AUDIT_PARAMS that is suitable for passing to event log.
  923. Return Value:
  924. NTSTATUS.
  925. **/
  926. {
  927. PAUDIT_PARAM pOldParam;
  928. PAUDIT_PARAM pNewParam;
  929. DWORD i;
  930. pNewParams->Count = 0;
  931. pNewParams->Flags = pOldParams->Flags;
  932. pNewParams->Length = pOldParams->Length;
  933. pNewParam = pNewParams->Parameters;
  934. pOldParam = pOldParams->Parameters;
  935. //
  936. // First set up the 4 initial parameters, so that the eventlog can
  937. // digest this audit and present it with the correct source and
  938. // audit id.
  939. //
  940. pNewParam->Type = APT_Sid;
  941. pNewParam->Data0 = (ULONG_PTR) pSid;
  942. pNewParams->Count++;
  943. pNewParam++;
  944. pNewParam->Type = APT_String;
  945. pNewParam->Data0 = (ULONG_PTR) L"Security";
  946. pNewParams->Count++;
  947. pNewParam++;
  948. pNewParam->Type = APT_String;
  949. pNewParam->Data0 = (ULONG_PTR) pSource->szEventSourceName;
  950. pNewParams->Count++;
  951. pNewParam++;
  952. pNewParam->Type = APT_Ulong;
  953. pNewParam->Data0 = (ULONG_PTR) dwAuditId;
  954. pNewParams->Count++;
  955. pNewParam++;
  956. // //
  957. // // Now stick in the LUID identifier as a parameter.
  958. // //
  959. //
  960. // pNewParam->Type = APT_Luid;
  961. // pNewParam->Data0 = (ULONG_PTR) pSource->Identifier;
  962. // pNewParams->Count++;
  963. // pNewParam++;
  964. //
  965. // If the flags specify that the caller would like to have source
  966. // information automatically added to the audit, then do so.
  967. //
  968. if (dwFlags & AUTHZ_AUDIT_INSTANCE_INFORMATION)
  969. {
  970. pNewParam->Type = APT_Luid;
  971. pNewParam->Data0 = (ULONG_PTR) pSource->Identifier.LowPart;
  972. pNewParam->Data1 = (ULONG_PTR) pSource->Identifier.HighPart;
  973. pNewParams->Count++;
  974. pNewParam++;
  975. pNewParam->Type = APT_Ulong;
  976. pNewParam->Data0 = (ULONG_PTR) pSource->dwProcessId;
  977. pNewParams->Count++;
  978. pNewParam++;
  979. }
  980. if ((pNewParams->Count + pOldParams->Count) > SE_MAX_AUDIT_PARAM_STRINGS)
  981. {
  982. return STATUS_INVALID_PARAMETER;
  983. }
  984. for (i = 0; i < pOldParams->Count; i++)
  985. {
  986. *pNewParam = *pOldParam;
  987. pNewParams->Count++;
  988. pNewParam++;
  989. pOldParam++;
  990. }
  991. return STATUS_SUCCESS;
  992. }
  993. NTSTATUS
  994. LsapAdtVerifySecurityEventSource(
  995. IN LPCWSTR szEventSourceName,
  996. IN PUNICODE_STRING pImageName,
  997. IN OUT PDWORD pdwInstalledSourceFlags
  998. )
  999. /**
  1000. Routine Description:
  1001. This verifies that the event source has been properly installed in the registry.
  1002. Arguments:
  1003. pdwInstalledSourceFlags - pointer to a DWORD that returns any flags used when
  1004. installing the event source.
  1005. szEventSourceName - the name of the source to verify.
  1006. Return Value:
  1007. NTSTATUS.
  1008. **/
  1009. {
  1010. DWORD dwType;
  1011. NTSTATUS Status = STATUS_SUCCESS;
  1012. DWORD dwError = ERROR_SUCCESS;
  1013. HKEY hkSecurity = NULL;
  1014. HKEY hkSource = NULL;
  1015. DWORD dwSize = sizeof(DWORD);
  1016. WCHAR NameBuffer[80];
  1017. PWSTR pName = NameBuffer;
  1018. *pdwInstalledSourceFlags = 0;
  1019. dwError = RegOpenKeyEx(
  1020. HKEY_LOCAL_MACHINE,
  1021. SECURITY_KEY_NAME,
  1022. 0,
  1023. KEY_READ,
  1024. &hkSecurity
  1025. );
  1026. if (ERROR_SUCCESS != dwError)
  1027. {
  1028. goto Cleanup;
  1029. }
  1030. dwError = RegOpenKeyEx(
  1031. hkSecurity,
  1032. szEventSourceName,
  1033. 0,
  1034. KEY_READ,
  1035. &hkSource
  1036. );
  1037. if (ERROR_SUCCESS != dwError)
  1038. {
  1039. goto Cleanup;
  1040. }
  1041. dwError = RegQueryValueEx(
  1042. hkSource,
  1043. L"EventSourceFlags",
  1044. NULL,
  1045. &dwType,
  1046. (LPBYTE)pdwInstalledSourceFlags,
  1047. &dwSize
  1048. );
  1049. if (ERROR_SUCCESS != dwError)
  1050. {
  1051. goto Cleanup;
  1052. }
  1053. ASSERT(dwType == REG_DWORD);
  1054. dwSize = sizeof(NameBuffer);
  1055. dwError = RegQueryValueEx(
  1056. hkSource,
  1057. L"ExecutableImagePath",
  1058. NULL,
  1059. &dwType,
  1060. (LPBYTE)pName,
  1061. &dwSize
  1062. );
  1063. if (ERROR_INSUFFICIENT_BUFFER == dwError)
  1064. {
  1065. pName = LsapAllocateLsaHeap(dwSize);
  1066. if (pName == NULL)
  1067. {
  1068. Status = STATUS_NO_MEMORY;
  1069. goto Cleanup;
  1070. }
  1071. dwError = RegQueryValueEx(
  1072. hkSource,
  1073. L"ExecutableImagePath",
  1074. NULL,
  1075. &dwType,
  1076. (LPBYTE)pName,
  1077. &dwSize
  1078. );
  1079. }
  1080. //
  1081. // If an ExecutableImagePath was not specified, then the provider
  1082. // had decided at installation time to not take advantage of the
  1083. // image spoofproof feature. Let the call pass through successfully.
  1084. //
  1085. if (dwError == ERROR_FILE_NOT_FOUND)
  1086. {
  1087. dwError = ERROR_SUCCESS;
  1088. goto Cleanup;
  1089. }
  1090. //
  1091. // Deal with all other errors now.
  1092. //
  1093. if (ERROR_SUCCESS != dwError)
  1094. {
  1095. goto Cleanup;
  1096. }
  1097. ASSERT(dwType == REG_MULTI_SZ);
  1098. //
  1099. // Make sure that the process registered is the same as the calling process.
  1100. //
  1101. if (0 != _wcsnicmp(pName, pImageName->Buffer, pImageName->Length / sizeof(WCHAR)))
  1102. {
  1103. dwError = ERROR_INVALID_PARAMETER;
  1104. goto Cleanup;
  1105. }
  1106. Cleanup:
  1107. if (hkSource)
  1108. {
  1109. RegCloseKey(hkSource);
  1110. }
  1111. if (hkSecurity)
  1112. {
  1113. RegCloseKey(hkSecurity);
  1114. }
  1115. if (dwError != ERROR_SUCCESS)
  1116. {
  1117. Status = LsapWinerrorToNtStatus(dwError);
  1118. }
  1119. if (pName != NameBuffer && pName != NULL)
  1120. {
  1121. LsapFreeLsaHeap(pName);
  1122. }
  1123. return Status;
  1124. }
  1125. NTSTATUS
  1126. LsapAdtAuditSecuritySource(
  1127. IN USHORT AuditEventType,
  1128. IN PLSAP_SECURITY_EVENT_SOURCE pEventSource,
  1129. IN BOOL bRegistration
  1130. )
  1131. /**
  1132. Routine Description:
  1133. This audits the attempt of a client to register a security event source.
  1134. Arguments:
  1135. AuditEventType - either EVENTLOG_AUDIT_SUCCESS or EVENTLOG_AUDIT_FAILURE.
  1136. pEventSource - the source to audit.
  1137. bRegistration - TRUE if this is a registration audit, FALSE if it is
  1138. an unregistration.
  1139. Return Value:
  1140. NTSTATUS.
  1141. **/
  1142. {
  1143. LUID ClientAuthenticationId;
  1144. BOOLEAN bAudit;
  1145. NTSTATUS Status;
  1146. PTOKEN_USER TokenUserInformation = NULL;
  1147. DWORD dwPid = 0;
  1148. LUID Luid = {0};
  1149. SE_ADT_PARAMETER_ARRAY AuditParameters = {0};
  1150. UNICODE_STRING SourceString = {0};
  1151. //
  1152. // If this is a success audit then the pEventSource is complete and
  1153. // we can trust the pointer to dereference its various fields.
  1154. //
  1155. if (AuditEventType == EVENTLOG_AUDIT_SUCCESS)
  1156. {
  1157. Luid = pEventSource->Identifier;
  1158. RtlInitUnicodeString(
  1159. &SourceString,
  1160. pEventSource->szEventSourceName
  1161. );
  1162. dwPid = pEventSource->dwProcessId;
  1163. } else if (pEventSource != NULL)
  1164. {
  1165. Luid = pEventSource->Identifier;
  1166. dwPid = pEventSource->dwProcessId;
  1167. if (pEventSource->szEventSourceName)
  1168. {
  1169. RtlInitUnicodeString(
  1170. &SourceString,
  1171. pEventSource->szEventSourceName
  1172. );
  1173. }
  1174. }
  1175. Status = LsapQueryClientInfo(
  1176. &TokenUserInformation,
  1177. &ClientAuthenticationId
  1178. );
  1179. if (!NT_SUCCESS(Status))
  1180. {
  1181. goto Cleanup;
  1182. }
  1183. Status = LsapAdtAuditingEnabledByLogonId(
  1184. AuditCategoryPolicyChange,
  1185. &ClientAuthenticationId,
  1186. AuditEventType,
  1187. &bAudit
  1188. );
  1189. if (!NT_SUCCESS(Status) || !bAudit)
  1190. {
  1191. goto Cleanup;
  1192. }
  1193. Status = LsapAdtInitParametersArray(
  1194. &AuditParameters,
  1195. SE_CATEGID_POLICY_CHANGE,
  1196. bRegistration ? SE_AUDITID_SECURITY_EVENT_SOURCE_REGISTERED : SE_AUDITID_SECURITY_EVENT_SOURCE_UNREGISTERED,
  1197. AuditEventType,
  1198. 7,
  1199. //
  1200. // User Sid
  1201. //
  1202. SeAdtParmTypeSid, TokenUserInformation->User.Sid,
  1203. //
  1204. // Subsystem name
  1205. //
  1206. SeAdtParmTypeString, &LsapSubsystemName,
  1207. //
  1208. // Primary Authentication information
  1209. //
  1210. SeAdtParmTypeLogonId, LsapSystemLogonId,
  1211. //
  1212. // Clients's Authentication information
  1213. //
  1214. SeAdtParmTypeLogonId, ClientAuthenticationId,
  1215. //
  1216. // Source Name
  1217. //
  1218. SeAdtParmTypeString, &SourceString,
  1219. //
  1220. // PID
  1221. //
  1222. SeAdtParmTypeUlong, dwPid,
  1223. //
  1224. // Identifier
  1225. //
  1226. SeAdtParmTypeLuid, Luid
  1227. );
  1228. if (!NT_SUCCESS(Status))
  1229. {
  1230. goto Cleanup;
  1231. }
  1232. (VOID) LsapAdtWriteLog(&AuditParameters);
  1233. Cleanup:
  1234. if (!NT_SUCCESS(Status))
  1235. {
  1236. LsapAuditFailed(Status);
  1237. }
  1238. if (TokenUserInformation != NULL)
  1239. {
  1240. LsapFreeLsaHeap(TokenUserInformation);
  1241. }
  1242. return Status;
  1243. }