Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1215 lines
33 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. elfsec.c
  5. Author:
  6. Dan Hinsley (danhi) 28-Mar-1992
  7. Environment:
  8. Calls NT native APIs.
  9. Revision History:
  10. 27-Oct-1993 danl
  11. Make Eventlog service a DLL and attach it to services.exe.
  12. Removed functions that create well-known SIDs. This information
  13. is now passed into the Elfmain as a Global data structure containing
  14. all well-known SIDs.
  15. 28-Mar-1992 danhi
  16. created - based on scsec.c in svcctrl by ritaw
  17. 03-Mar-1995 markbl
  18. Added guest & anonymous logon log access restriction feature.
  19. 18-Mar-2001 a-jyotig
  20. Added clean up code to ElfpAccessCheckAndAudit to reset the
  21. g_lNumSecurityWriters to 0 in case of any error
  22. --*/
  23. #include <eventp.h>
  24. #include <elfcfg.h>
  25. #include <Psapi.h>
  26. #define PRIVILEGE_BUF_SIZE 512
  27. extern long g_lNumSecurityWriters;
  28. BOOL g_bGetClientProc = FALSE;
  29. //-------------------------------------------------------------------//
  30. // //
  31. // Local function prototypes //
  32. // //
  33. //-------------------------------------------------------------------//
  34. NTSTATUS
  35. ElfpGetPrivilege(
  36. IN DWORD numPrivileges,
  37. IN PULONG pulPrivileges
  38. );
  39. NTSTATUS
  40. ElfpReleasePrivilege(
  41. VOID
  42. );
  43. //-------------------------------------------------------------------//
  44. // //
  45. // Structure that describes the mapping of generic access rights to //
  46. // object specific access rights for a LogFile object. //
  47. // //
  48. //-------------------------------------------------------------------//
  49. static GENERIC_MAPPING LogFileObjectMapping = {
  50. STANDARD_RIGHTS_READ | // Generic read
  51. ELF_LOGFILE_READ,
  52. STANDARD_RIGHTS_WRITE | // Generic write
  53. ELF_LOGFILE_WRITE,
  54. STANDARD_RIGHTS_EXECUTE | // Generic execute
  55. ELF_LOGFILE_START |
  56. ELF_LOGFILE_STOP |
  57. ELF_LOGFILE_CONFIGURE,
  58. ELF_LOGFILE_ALL_ACCESS // Generic all
  59. };
  60. //-------------------------------------------------------------------//
  61. // //
  62. // Functions //
  63. // //
  64. //-------------------------------------------------------------------//
  65. NTSTATUS
  66. ElfpCreateLogFileObject(
  67. PLOGFILE LogFile,
  68. DWORD Type,
  69. ULONG GuestAccessRestriction
  70. )
  71. /*++
  72. Routine Description:
  73. This function creates the security descriptor which represents
  74. an active log file.
  75. Arguments:
  76. LogFile - pointer the the LOGFILE structure for this logfile
  77. Return Value:
  78. --*/
  79. {
  80. NTSTATUS Status;
  81. DWORD NumberOfAcesToUse;
  82. #define ELF_LOGFILE_OBJECT_ACES 12 // Number of ACEs in this DACL
  83. RTL_ACE_DATA AceData[ELF_LOGFILE_OBJECT_ACES] = {
  84. {ACCESS_DENIED_ACE_TYPE, 0, 0,
  85. ELF_LOGFILE_ALL_ACCESS, &AnonymousLogonSid},
  86. {ACCESS_DENIED_ACE_TYPE, 0, 0,
  87. ELF_LOGFILE_ALL_ACCESS, &(ElfGlobalData->AliasGuestsSid)},
  88. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  89. ELF_LOGFILE_ALL_ACCESS, &(ElfGlobalData->LocalSystemSid)},
  90. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  91. ELF_LOGFILE_READ | ELF_LOGFILE_CLEAR, &(ElfGlobalData->AliasAdminsSid)},
  92. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  93. ELF_LOGFILE_BACKUP, &(ElfGlobalData->AliasBackupOpsSid)},
  94. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  95. ELF_LOGFILE_READ | ELF_LOGFILE_CLEAR, &(ElfGlobalData->AliasSystemOpsSid)},
  96. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  97. ELF_LOGFILE_READ, &(ElfGlobalData->WorldSid)},
  98. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  99. ELF_LOGFILE_WRITE, &(ElfGlobalData->AliasAdminsSid)},
  100. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  101. ELF_LOGFILE_WRITE, &(ElfGlobalData->LocalServiceSid)},
  102. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  103. ELF_LOGFILE_WRITE, &(ElfGlobalData->NetworkServiceSid)},
  104. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  105. ELF_LOGFILE_WRITE, &(ElfGlobalData->AliasSystemOpsSid)},
  106. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  107. ELF_LOGFILE_WRITE, &(ElfGlobalData->WorldSid)}
  108. };
  109. PRTL_ACE_DATA pAceData = NULL;
  110. //
  111. // NON_SECURE logfiles let anyone read/write to them, secure ones
  112. // only let admins/local system do this. so for secure files we just
  113. // don't use the last ACE
  114. //
  115. // Adjust the ACL start based on the passed GuestAccessRestriction flag.
  116. // The first two aces deny all log access to guests and/or anonymous
  117. // logons. The flag, GuestAccessRestriction, indicates that these two
  118. // deny access aces should be applied. Note that the deny aces and the
  119. // GuestAccessRestriction flag are not applicable to the security log,
  120. // since users and anonymous logons, by default, do not have access.
  121. //
  122. switch (Type)
  123. {
  124. case ELF_LOGFILE_SECURITY:
  125. ELF_LOG0(TRACE,
  126. "ElfpCreateLogFileObject: Creating security Logfile\n");
  127. pAceData = AceData + 2; // Deny ACEs *not* applicable
  128. NumberOfAcesToUse = 3;
  129. break;
  130. case ELF_LOGFILE_SYSTEM:
  131. ELF_LOG1(TRACE,
  132. "ElfpCreateLogFileObject: Creating System Logfile -- "
  133. "Guest access = %d\n", GuestAccessRestriction);
  134. if (GuestAccessRestriction == ELF_GUEST_ACCESS_RESTRICTED)
  135. {
  136. pAceData = AceData; // Deny ACEs *applicable*
  137. NumberOfAcesToUse = 10;
  138. }
  139. else
  140. {
  141. pAceData = AceData + 2; // Deny ACEs *not* applicable
  142. NumberOfAcesToUse = 8;
  143. }
  144. break;
  145. case ELF_LOGFILE_APPLICATION:
  146. ELF_LOG1(TRACE,
  147. "ElfpCreateLogFileObject: Creating Application Logfile -- "
  148. "Guest access = %d\n", GuestAccessRestriction);
  149. if (GuestAccessRestriction == ELF_GUEST_ACCESS_RESTRICTED)
  150. {
  151. pAceData = AceData; // Deny ACEs *applicable*
  152. NumberOfAcesToUse = 12;
  153. }
  154. else
  155. {
  156. pAceData = AceData + 2; // Deny ACEs *not* applicable
  157. NumberOfAcesToUse = 10;
  158. }
  159. break;
  160. default:
  161. //
  162. // We got an unknown type -- this should never happen
  163. //
  164. ELF_LOG1(ERROR,
  165. "ElfpCreateLogFileObject: Invalid Type %#x\n",
  166. Type);
  167. ASSERT(FALSE);
  168. return STATUS_INVALID_LEVEL;
  169. }
  170. Status = RtlCreateUserSecurityObject(
  171. pAceData,
  172. NumberOfAcesToUse,
  173. NULL, // Owner
  174. NULL, // Group
  175. TRUE, // IsDirectoryObject
  176. &LogFileObjectMapping,
  177. &LogFile->Sd);
  178. if (!NT_SUCCESS(Status))
  179. {
  180. ELF_LOG1(ERROR,
  181. "ElfpCreateLogFileObject: RtlCreateUserSecurityObject failed %#x\n",
  182. Status);
  183. }
  184. return Status;
  185. }
  186. VOID
  187. ElfpDeleteLogFileObject(
  188. PLOGFILE LogFile
  189. )
  190. /*++
  191. Routine Description:
  192. This function deletes the self-relative security descriptor which
  193. represents an eventlog logfile object.
  194. Arguments:
  195. LogFile - pointer the the LOGFILE structure for this logfile
  196. Return Value:
  197. None.
  198. --*/
  199. {
  200. RtlDeleteSecurityObject(&LogFile->Sd);
  201. }
  202. NTSTATUS
  203. ElfpVerifyThatCallerIsLSASS(
  204. )
  205. /*++
  206. Routine Description:
  207. This is called if the someone is trying to register themselves as an
  208. event source for the security log. Only local copy of lsass.exe is
  209. allowed to do that.
  210. Return Value:
  211. NT status mapped to Win32 errors.
  212. --*/
  213. {
  214. UINT LocalFlag;
  215. long lCnt;
  216. ULONG pid;
  217. HANDLE hProcess;
  218. DWORD dwNumChar;
  219. WCHAR wModulePath[MAX_PATH + 1];
  220. WCHAR wLsassPath[MAX_PATH + 1];
  221. RPC_STATUS RpcStatus;
  222. // first of all, only local calls are valid
  223. RpcStatus = I_RpcBindingIsClientLocal(
  224. 0, // Active RPC call we are servicing
  225. &LocalFlag
  226. );
  227. if( RpcStatus != RPC_S_OK )
  228. {
  229. ELF_LOG1(ERROR,
  230. "ElfpVerifyThatCallerIsLSASS: I_RpcBindingIsClientLocal failed %d\n",
  231. RpcStatus);
  232. return I_RpcMapWin32Status(RpcStatus);
  233. }
  234. if(LocalFlag == 0)
  235. {
  236. ELF_LOG1(ERROR,
  237. "ElfpVerifyThatCallerIsLSASS: Non local connect tried to get write access to security %d\n", 5);
  238. return E_ACCESSDENIED; // access denied
  239. }
  240. // Get the process id
  241. RpcStatus = I_RpcBindingInqLocalClientPID(NULL, &pid );
  242. if( RpcStatus != RPC_S_OK )
  243. {
  244. ELF_LOG1(ERROR,
  245. "ElfpVerifyThatCallerIsLSASS: I_RpcBindingInqLocalClientPID failed %d\n",
  246. RpcStatus);
  247. return I_RpcMapWin32Status(RpcStatus);
  248. }
  249. // Get the process
  250. hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);
  251. if(hProcess == NULL)
  252. return E_ACCESSDENIED;
  253. // Get the module name of whoever is calling us.
  254. dwNumChar = GetModuleFileNameExW(hProcess, NULL, wModulePath, MAX_PATH);
  255. CloseHandle(hProcess);
  256. if(dwNumChar == 0)
  257. return E_ACCESSDENIED;
  258. dwNumChar = GetWindowsDirectoryW(wLsassPath, MAX_PATH);
  259. if(dwNumChar == 0)
  260. return GetLastError();
  261. if(dwNumChar > MAX_PATH - 19)
  262. return E_ACCESSDENIED; // should never happen
  263. lstrcatW(wLsassPath, L"\\system32\\lsass.exe");
  264. if(lstrcmpiW(wLsassPath, wModulePath))
  265. {
  266. ELF_LOG1(ERROR,
  267. "ElfpVerifyThatCallerIsLSASS: Non lsass process connect tried to get write access to security, returning %d\n", 5);
  268. return E_ACCESSDENIED; // access denied
  269. }
  270. // One last check is to make sure that this access is granted only once
  271. lCnt = InterlockedIncrement(&g_lNumSecurityWriters);
  272. if(lCnt == 1)
  273. return 0; // all is well!
  274. else
  275. {
  276. InterlockedDecrement(&g_lNumSecurityWriters);
  277. ELF_LOG1(ERROR,
  278. "ElfpVerifyThatCallerIsLSASS: tried to get a second security write handle, returnin %d\n", 5);
  279. return E_ACCESSDENIED; // access denied
  280. }
  281. }
  282. void DumpClientProc()
  283. /*++
  284. Routine Description:
  285. This dumps the client's process id and is used for debugging purposes.
  286. --*/
  287. {
  288. ULONG pid;
  289. RPC_STATUS RpcStatus;
  290. // Get the process id
  291. RpcStatus = I_RpcBindingInqLocalClientPID(NULL, &pid );
  292. if( RpcStatus != RPC_S_OK )
  293. {
  294. ELF_LOG1(ERROR,
  295. "DumpClientProc: I_RpcBindingInqLocalClientPID failed %d\n",
  296. RpcStatus);
  297. return;
  298. }
  299. else
  300. ELF_LOG1(TRACE, "DumpClientProc: The client proc is %d\n", pid);
  301. return;
  302. }
  303. NTSTATUS
  304. ElfpAccessCheckAndAudit(
  305. IN LPWSTR SubsystemName,
  306. IN LPWSTR ObjectTypeName,
  307. IN LPWSTR ObjectName,
  308. IN OUT IELF_HANDLE ContextHandle,
  309. IN PSECURITY_DESCRIPTOR SecurityDescriptor,
  310. IN ACCESS_MASK DesiredAccess,
  311. IN PGENERIC_MAPPING GenericMapping,
  312. IN BOOL ForSecurityLog
  313. )
  314. /*++
  315. Routine Description:
  316. This function impersonates the caller so that it can perform access
  317. validation using NtAccessCheckAndAuditAlarm; and reverts back to
  318. itself before returning.
  319. Arguments:
  320. SubsystemName - Supplies a name string identifying the subsystem
  321. calling this routine.
  322. ObjectTypeName - Supplies the name of the type of the object being
  323. accessed.
  324. ObjectName - Supplies the name of the object being accessed.
  325. ContextHandle - Supplies the context handle to the object. On return, the
  326. granted access is written to the AccessGranted field of this structure
  327. if this call succeeds.
  328. SecurityDescriptor - A pointer to the Security Descriptor against which
  329. acccess is to be checked.
  330. DesiredAccess - Supplies desired acccess mask. This mask must have been
  331. previously mapped to contain no generic accesses.
  332. GenericMapping - Supplies a pointer to the generic mapping associated
  333. with this object type.
  334. ForSecurityLog - TRUE if the access check is for the security log.
  335. This is a special case that may require a privilege check.
  336. Return Value:
  337. NT status mapped to Win32 errors.
  338. --*/
  339. {
  340. NTSTATUS Status;
  341. RPC_STATUS RpcStatus;
  342. UNICODE_STRING Subsystem;
  343. UNICODE_STRING ObjectType;
  344. UNICODE_STRING Object;
  345. BOOLEAN GenerateOnClose = FALSE;
  346. NTSTATUS AccessStatus;
  347. ACCESS_MASK GrantedAccess = 0;
  348. HANDLE ClientToken = NULL;
  349. PRIVILEGE_SET PrivilegeSet;
  350. ULONG PrivilegeSetLength = sizeof(PRIVILEGE_SET);
  351. ULONG privileges[1];
  352. GenericMapping = &LogFileObjectMapping;
  353. RtlInitUnicodeString(&Subsystem, SubsystemName);
  354. RtlInitUnicodeString(&ObjectType, ObjectTypeName);
  355. RtlInitUnicodeString(&Object, ObjectName);
  356. RpcStatus = RpcImpersonateClient(NULL);
  357. if (RpcStatus != RPC_S_OK)
  358. {
  359. ELF_LOG1(ERROR,
  360. "ElfpAccessCheckAndAudit: RpcImpersonateClient failed %d\n",
  361. RpcStatus);
  362. return I_RpcMapWin32Status(RpcStatus);
  363. }
  364. // if the client is asking to write to the security log, make sure it is lsass.exe and no one
  365. // else.
  366. if(ForSecurityLog && (DesiredAccess & ELF_LOGFILE_WRITE))
  367. {
  368. Status = ElfpVerifyThatCallerIsLSASS();
  369. if (!NT_SUCCESS(Status))
  370. {
  371. ELF_LOG1(ERROR,
  372. "ElfpVerifyThatCallerIsLSASS failed %#x\n",
  373. Status);
  374. goto CleanExit;
  375. }
  376. }
  377. else if(g_bGetClientProc)
  378. DumpClientProc();
  379. //
  380. // Get a token handle for the client
  381. //
  382. Status = NtOpenThreadToken(NtCurrentThread(),
  383. TOKEN_QUERY, // DesiredAccess
  384. TRUE, // OpenAsSelf
  385. &ClientToken);
  386. if (!NT_SUCCESS(Status))
  387. {
  388. ELF_LOG1(ERROR,
  389. "ElfpAccessCheckAndAudit: NtOpenThreadToken failed %#x\n",
  390. Status);
  391. goto CleanExit;
  392. }
  393. //
  394. // We want to see if we can get the desired access, and if we do
  395. // then we also want all our other accesses granted.
  396. // MAXIMUM_ALLOWED gives us this.
  397. //
  398. DesiredAccess |= MAXIMUM_ALLOWED;
  399. //
  400. // Bug #57153 -- Make sure that the current user has the right to manage
  401. // the security log. Without this check, the Eventlog will allow all
  402. // administrators to manage the log, even if they don't have the access.
  403. //
  404. if (ForSecurityLog)
  405. {
  406. DesiredAccess |= ACCESS_SYSTEM_SECURITY;
  407. }
  408. Status = NtAccessCheck(SecurityDescriptor,
  409. ClientToken,
  410. DesiredAccess,
  411. GenericMapping,
  412. &PrivilegeSet,
  413. &PrivilegeSetLength,
  414. &GrantedAccess,
  415. &AccessStatus);
  416. if (!NT_SUCCESS(Status))
  417. {
  418. ELF_LOG1(ERROR,
  419. "ElfpAccessCheckAndAudit: NtAccessCheck failed %#x\n",
  420. Status);
  421. goto CleanExit;
  422. }
  423. if (AccessStatus != STATUS_SUCCESS)
  424. {
  425. ELF_LOG1(TRACE,
  426. "ElfpAccessCheckAndAudit: NtAccessCheck refused access -- status is %#x\n",
  427. AccessStatus);
  428. //
  429. // MarkBl 1/30/95 : Modified this code a bit to give backup operators
  430. // the ability to open the security log for purposes
  431. // of backup.
  432. //
  433. if ((AccessStatus == STATUS_ACCESS_DENIED ||
  434. AccessStatus == STATUS_PRIVILEGE_NOT_HELD) &&
  435. (ForSecurityLog)
  436. )
  437. {
  438. //
  439. // MarkBl 1/30/95 : First, evalutate the existing code (performed
  440. // for read or clear access), since its
  441. // privilege check is more rigorous than mine.
  442. //
  443. Status = STATUS_ACCESS_DENIED;
  444. if (!(DesiredAccess & ELF_LOGFILE_WRITE))
  445. {
  446. //
  447. // If read or clear access to the security log is desired,
  448. // then we will see if this user passes the privilege check.
  449. //
  450. //
  451. // Do Privilege Check for SeSecurityPrivilege
  452. // (SE_SECURITY_NAME).
  453. //
  454. // MarkBl 1/30/95 : Modified code to fall through on error
  455. // instead of the jump to 'CleanExit'.
  456. //
  457. Status = ElfpTestClientPrivilege(SE_SECURITY_PRIVILEGE,
  458. ClientToken);
  459. if (NT_SUCCESS(Status))
  460. {
  461. GrantedAccess |= (ELF_LOGFILE_READ | ELF_LOGFILE_CLEAR);
  462. ELF_LOG0(TRACE,
  463. "ElfpAccessCheckAndAudit: ElfpTestClientPrivilege for "
  464. "SE_SECURITY_PRIVILEGE succeeded\n");
  465. }
  466. else
  467. {
  468. ELF_LOG1(TRACE,
  469. "ElfpAccessCheckAndAudit: ElfpTestClientPrivilege for "
  470. "SE_SECURITY_PRIVILEGE failed %#x\n",
  471. Status);
  472. }
  473. }
  474. //
  475. // MarkBl 1/30/95 : Finally, my code. If this user has backup
  476. // privilege, let the open succeed.
  477. //
  478. if (!NT_SUCCESS(Status))
  479. {
  480. Status = ElfpTestClientPrivilege(SE_BACKUP_PRIVILEGE,
  481. ClientToken);
  482. if (NT_SUCCESS(Status))
  483. {
  484. ELF_LOG0(TRACE,
  485. "ElfpAccessCheckAndAudit: ElfpTestClientPrivilege for "
  486. "SE_BACKUP_PRIVILEGE succeeded\n");
  487. GrantedAccess |= ELF_LOGFILE_BACKUP;
  488. }
  489. else
  490. {
  491. ELF_LOG1(ERROR,
  492. "ElfpAccessCheckAndAudit: ElfpTestClientPrivilege for "
  493. "SE_BACKUP_PRIVILEGE failed %#x\n",
  494. Status);
  495. // special "fix" for wmi eventlog provider which is hard coded
  496. // to look for a specific error code
  497. if(AccessStatus == STATUS_PRIVILEGE_NOT_HELD)
  498. Status = AccessStatus;
  499. goto CleanExit;
  500. }
  501. }
  502. // special "fix" for wmi eventlog provider which is hard coded
  503. // to look for a specific error code
  504. if(!NT_SUCCESS(Status) && AccessStatus == STATUS_PRIVILEGE_NOT_HELD)
  505. Status = AccessStatus;
  506. }
  507. else
  508. {
  509. Status = AccessStatus;
  510. }
  511. }
  512. //
  513. // Revert to Self
  514. //
  515. RpcStatus = RpcRevertToSelf();
  516. if (RpcStatus != RPC_S_OK)
  517. {
  518. ELF_LOG1(ERROR,
  519. "ElfpAccessCheckAndAudit: RpcRevertToSelf failed %d\n",
  520. RpcStatus);
  521. //
  522. // We don't return the error status here because we don't want
  523. // to write over the other status that is being returned.
  524. //
  525. }
  526. //
  527. // Get SeAuditPrivilege so I can call NtOpenObjectAuditAlarm.
  528. // If any of this stuff fails, I don't want the status to overwrite the
  529. // status that I got back from the access and privilege checks.
  530. //
  531. privileges[0] = SE_AUDIT_PRIVILEGE;
  532. AccessStatus = ElfpGetPrivilege(1, privileges);
  533. if (!NT_SUCCESS(AccessStatus))
  534. {
  535. ELF_LOG1(ERROR,
  536. "ElfpAccessCheckAndAudit: ElfpGetPrivilege (SE_AUDIT_PRIVILEGE) failed %#x\n",
  537. AccessStatus);
  538. }
  539. //
  540. // Call the Audit Alarm function.
  541. //
  542. AccessStatus = NtOpenObjectAuditAlarm(
  543. &Subsystem,
  544. (PVOID) &ContextHandle,
  545. &ObjectType,
  546. &Object,
  547. SecurityDescriptor,
  548. ClientToken, // Handle ClientToken
  549. DesiredAccess,
  550. GrantedAccess,
  551. &PrivilegeSet, // PPRIVLEGE_SET
  552. FALSE, // BOOLEAN ObjectCreation,
  553. TRUE, // BOOLEAN AccessGranted,
  554. &GenerateOnClose);
  555. if (!NT_SUCCESS(AccessStatus))
  556. {
  557. ELF_LOG1(ERROR,
  558. "ElfpAccessCheckAndAudit: NtOpenObjectAuditAlarm failed %#x\n",
  559. AccessStatus);
  560. }
  561. else
  562. {
  563. if (GenerateOnClose)
  564. {
  565. ContextHandle->Flags |= ELF_LOG_HANDLE_GENERATE_ON_CLOSE;
  566. }
  567. }
  568. //
  569. // Update the GrantedAccess in the context handle.
  570. //
  571. ContextHandle->GrantedAccess = GrantedAccess;
  572. NtClose(ClientToken);
  573. ElfpReleasePrivilege();
  574. return Status;
  575. CleanExit:
  576. //
  577. // Revert to Self
  578. //
  579. RpcStatus = RpcRevertToSelf();
  580. if (RpcStatus != RPC_S_OK)
  581. {
  582. ELF_LOG1(ERROR,
  583. "ElfpAccessCheckAndAudit: RpcRevertToSelf (CleanExit) failed %d\n",
  584. RpcStatus);
  585. //
  586. // We don't return the error status here because we don't want
  587. // to write over the other status that is being returned.
  588. //
  589. }
  590. // if we return failure status due to any reason, the log handle will not be given
  591. // to the requesting process (lsass.exe). But we have already incremented g_lNumSecurityWriters
  592. // if g_lNumSecurityWriters > 0 then lsass will not be able to get the access next time.
  593. // So decrement g_lNumSecurityWriters if we have already incremented g_lNumSecurityWriters and
  594. // if we are returning failure
  595. if (!NT_SUCCESS(Status))
  596. {
  597. InterlockedExchange(&g_lNumSecurityWriters,0L);
  598. }
  599. if (ClientToken != NULL)
  600. {
  601. NtClose(ClientToken);
  602. }
  603. return Status;
  604. }
  605. VOID
  606. ElfpCloseAudit(
  607. IN LPWSTR SubsystemName,
  608. IN IELF_HANDLE ContextHandle
  609. )
  610. /*++
  611. Routine Description:
  612. If the GenerateOnClose flag in the ContextHandle is set, then this function
  613. calls NtCloseAuditAlarm in order to generate a close audit for this handle.
  614. Arguments:
  615. ContextHandle - This is a pointer to an ELF_HANDLE structure. This is the
  616. handle that is being closed.
  617. Return Value:
  618. none.
  619. --*/
  620. {
  621. UNICODE_STRING Subsystem;
  622. NTSTATUS Status;
  623. NTSTATUS AccessStatus;
  624. ULONG privileges[1];
  625. RtlInitUnicodeString(&Subsystem, SubsystemName);
  626. if (ContextHandle->Flags & ELF_LOG_HANDLE_GENERATE_ON_CLOSE)
  627. {
  628. BOOLEAN WasEnabled = FALSE;
  629. //
  630. // Get Audit Privilege
  631. //
  632. privileges[0] = SE_AUDIT_PRIVILEGE;
  633. AccessStatus = ElfpGetPrivilege(1, privileges);
  634. if (!NT_SUCCESS(AccessStatus))
  635. {
  636. ELF_LOG1(ERROR,
  637. "ElfpCloseAudit: ElfpGetPrivilege (SE_AUDIT_PRIVILEGE) failed %#x\n",
  638. AccessStatus);
  639. }
  640. //
  641. // Generate the Audit.
  642. //
  643. Status = NtCloseObjectAuditAlarm(&Subsystem,
  644. ContextHandle,
  645. TRUE);
  646. if (!NT_SUCCESS(Status))
  647. {
  648. ELF_LOG1(ERROR,
  649. "ElfpCloseAudit: NtCloseObjectAuditAlarm failed %#x\n",
  650. Status);
  651. }
  652. ContextHandle->Flags &= (~ELF_LOG_HANDLE_GENERATE_ON_CLOSE);
  653. ElfpReleasePrivilege();
  654. }
  655. return;
  656. }
  657. NTSTATUS
  658. ElfpGetPrivilege(
  659. IN DWORD numPrivileges,
  660. IN PULONG pulPrivileges
  661. )
  662. /*++
  663. Routine Description:
  664. This function alters the privilege level for the current thread.
  665. It does this by duplicating the token for the current thread, and then
  666. applying the new privileges to that new token, then the current thread
  667. impersonates with that new token.
  668. Privileges can be relinquished by calling ElfpReleasePrivilege().
  669. Arguments:
  670. numPrivileges - This is a count of the number of privileges in the
  671. array of privileges.
  672. pulPrivileges - This is a pointer to the array of privileges that are
  673. desired. This is an array of ULONGs.
  674. Return Value:
  675. NO_ERROR - If the operation was completely successful.
  676. Otherwise, it returns mapped return codes from the various NT
  677. functions that are called.
  678. --*/
  679. {
  680. NTSTATUS ntStatus;
  681. HANDLE ourToken;
  682. HANDLE newToken;
  683. OBJECT_ATTRIBUTES Obja;
  684. SECURITY_QUALITY_OF_SERVICE SecurityQofS;
  685. ULONG returnLen;
  686. PTOKEN_PRIVILEGES pTokenPrivilege = NULL;
  687. DWORD i;
  688. //
  689. // Initialize the Privileges Structure
  690. //
  691. pTokenPrivilege =
  692. (PTOKEN_PRIVILEGES) ElfpAllocateBuffer(sizeof(TOKEN_PRIVILEGES)
  693. + (sizeof(LUID_AND_ATTRIBUTES) *
  694. numPrivileges));
  695. if (pTokenPrivilege == NULL)
  696. {
  697. ELF_LOG0(ERROR,
  698. "ElfpGetPrivilege: Unable to allocate memory for pTokenPrivilege\n");
  699. return STATUS_NO_MEMORY;
  700. }
  701. pTokenPrivilege->PrivilegeCount = numPrivileges;
  702. for (i = 0; i < numPrivileges; i++)
  703. {
  704. pTokenPrivilege->Privileges[i].Luid = RtlConvertLongToLuid(pulPrivileges[i]);
  705. pTokenPrivilege->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED;
  706. }
  707. //
  708. // Initialize Object Attribute Structure.
  709. //
  710. InitializeObjectAttributes(&Obja, NULL, 0L, NULL, NULL);
  711. //
  712. // Initialize Security Quality Of Service Structure
  713. //
  714. SecurityQofS.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
  715. SecurityQofS.ImpersonationLevel = SecurityImpersonation;
  716. SecurityQofS.ContextTrackingMode = FALSE; // Snapshot client context
  717. SecurityQofS.EffectiveOnly = FALSE;
  718. Obja.SecurityQualityOfService = &SecurityQofS;
  719. //
  720. // Open our own Token
  721. //
  722. ntStatus = NtOpenProcessToken(NtCurrentProcess(),
  723. TOKEN_DUPLICATE,
  724. &ourToken);
  725. if (!NT_SUCCESS(ntStatus))
  726. {
  727. ELF_LOG1(ERROR,
  728. "ElfpGetPrivilege: NtOpenProcessToken failed %#x\n",
  729. ntStatus);
  730. ElfpFreeBuffer(pTokenPrivilege);
  731. return ntStatus;
  732. }
  733. //
  734. // Duplicate that Token
  735. //
  736. ntStatus = NtDuplicateToken(
  737. ourToken,
  738. TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
  739. &Obja,
  740. FALSE, // Duplicate the entire token
  741. TokenImpersonation, // TokenType
  742. &newToken); // Duplicate token
  743. if (!NT_SUCCESS(ntStatus))
  744. {
  745. ELF_LOG1(ERROR,
  746. "ElfpGetPrivilege: NtDuplicateToken failed %#x\n",
  747. ntStatus);
  748. ElfpFreeBuffer(pTokenPrivilege);
  749. NtClose(ourToken);
  750. return ntStatus;
  751. }
  752. //
  753. // Add new privileges
  754. //
  755. ntStatus = NtAdjustPrivilegesToken(
  756. newToken, // TokenHandle
  757. FALSE, // DisableAllPrivileges
  758. pTokenPrivilege, // NewState
  759. 0, // size of previous state buffer
  760. NULL, // no previous state info
  761. &returnLen); // numBytes required for buffer.
  762. if (!NT_SUCCESS(ntStatus))
  763. {
  764. ELF_LOG1(ERROR,
  765. "ElfpGetPrivilege: NtAdjustPrivilegesToken failed %#x\n",
  766. ntStatus);
  767. ElfpFreeBuffer(pTokenPrivilege);
  768. NtClose(ourToken);
  769. NtClose(newToken);
  770. return ntStatus;
  771. }
  772. //
  773. // Begin impersonating with the new token
  774. //
  775. ntStatus = NtSetInformationThread(NtCurrentThread(),
  776. ThreadImpersonationToken,
  777. (PVOID) &newToken,
  778. (ULONG) sizeof(HANDLE));
  779. if (!NT_SUCCESS(ntStatus))
  780. {
  781. ELF_LOG1(ERROR,
  782. "ElfpGetPrivilege: NtAdjustPrivilegeToken failed %#x\n",
  783. ntStatus);
  784. ElfpFreeBuffer(pTokenPrivilege);
  785. NtClose(ourToken);
  786. NtClose(newToken);
  787. return ntStatus;
  788. }
  789. ElfpFreeBuffer(pTokenPrivilege);
  790. NtClose(ourToken);
  791. NtClose(newToken);
  792. return STATUS_SUCCESS;
  793. }
  794. NTSTATUS
  795. ElfpReleasePrivilege(
  796. VOID
  797. )
  798. /*++
  799. Routine Description:
  800. This function relinquishes privileges obtained by calling ElfpGetPrivilege().
  801. Arguments:
  802. none
  803. Return Value:
  804. STATUS_SUCCESS - If the operation was completely successful.
  805. Otherwise, it returns the error that occurred.
  806. --*/
  807. {
  808. NTSTATUS ntStatus;
  809. HANDLE NewToken;
  810. //
  811. // Revert To Self.
  812. //
  813. NewToken = NULL;
  814. ntStatus = NtSetInformationThread(NtCurrentThread(),
  815. ThreadImpersonationToken,
  816. &NewToken,
  817. (ULONG) sizeof(HANDLE));
  818. if (!NT_SUCCESS(ntStatus))
  819. {
  820. ELF_LOG1(ERROR,
  821. "ElfpReleasePrivilege: NtSetInformation thread failed %#x\n",
  822. ntStatus);
  823. return ntStatus;
  824. }
  825. return STATUS_SUCCESS;
  826. }
  827. NTSTATUS
  828. ElfpTestClientPrivilege(
  829. IN ULONG ulPrivilege,
  830. IN HANDLE hThreadToken OPTIONAL
  831. )
  832. /*++
  833. Routine Description:
  834. Checks if the client has the supplied privilege.
  835. Arguments:
  836. None
  837. Return Value:
  838. STATUS_SUCCESS - if the client has the appropriate privilege.
  839. STATUS_ACCESS_DENIED - client does not have the required privilege
  840. --*/
  841. {
  842. NTSTATUS Status;
  843. PRIVILEGE_SET PrivilegeSet;
  844. BOOLEAN Privileged;
  845. HANDLE Token;
  846. RPC_STATUS RpcStatus;
  847. UNICODE_STRING SubSystemName;
  848. RtlInitUnicodeString(&SubSystemName, L"Eventlog");
  849. if (hThreadToken != NULL)
  850. {
  851. Token = hThreadToken;
  852. }
  853. else
  854. {
  855. RpcStatus = RpcImpersonateClient(NULL);
  856. if (RpcStatus != RPC_S_OK)
  857. {
  858. ELF_LOG1(ERROR,
  859. "ElfpTestClientPrivilege: RpcImpersonateClient failed %d\n",
  860. RpcStatus);
  861. return I_RpcMapWin32Status(RpcStatus);
  862. }
  863. Status = NtOpenThreadToken(NtCurrentThread(),
  864. TOKEN_QUERY,
  865. TRUE,
  866. &Token);
  867. if (!NT_SUCCESS(Status))
  868. {
  869. //
  870. // Forget it.
  871. //
  872. ELF_LOG1(ERROR,
  873. "ElfpTestClientPrivilege: NtOpenThreadToken failed %#x\n",
  874. Status);
  875. RpcRevertToSelf();
  876. return Status;
  877. }
  878. }
  879. //
  880. // See if the client has the required privilege
  881. //
  882. PrivilegeSet.PrivilegeCount = 1;
  883. PrivilegeSet.Control = PRIVILEGE_SET_ALL_NECESSARY;
  884. PrivilegeSet.Privilege[0].Luid = RtlConvertLongToLuid(ulPrivilege);
  885. PrivilegeSet.Privilege[0].Attributes = SE_PRIVILEGE_ENABLED;
  886. Status = NtPrivilegeCheck(Token,
  887. &PrivilegeSet,
  888. &Privileged);
  889. if (NT_SUCCESS(Status) || (Status == STATUS_PRIVILEGE_NOT_HELD))
  890. {
  891. Status = NtPrivilegeObjectAuditAlarm(
  892. &SubSystemName,
  893. NULL,
  894. Token,
  895. 0,
  896. &PrivilegeSet,
  897. Privileged);
  898. if (!NT_SUCCESS(Status))
  899. {
  900. ELF_LOG1(ERROR,
  901. "ElfpTestClientPrivilege: NtPrivilegeObjectAuditAlarm failed %#x\n",
  902. Status);
  903. }
  904. }
  905. else
  906. {
  907. ELF_LOG1(ERROR,
  908. "ElfpTestClientPrivilege: NtPrivilegeCheck failed %#x\n",
  909. Status);
  910. }
  911. if (hThreadToken == NULL )
  912. {
  913. //
  914. // We impersonated inside of this function
  915. //
  916. NtClose(Token);
  917. RpcRevertToSelf();
  918. }
  919. //
  920. // Handle unexpected errors
  921. //
  922. if (!NT_SUCCESS(Status))
  923. {
  924. ELF_LOG1(ERROR,
  925. "ElfpTestClientPrivilege: Failed %#x\n",
  926. Status);
  927. return Status;
  928. }
  929. //
  930. // If they failed the privilege check, return an error
  931. //
  932. if (!Privileged)
  933. {
  934. ELF_LOG0(ERROR,
  935. "ElfpTestClientPrivilege: Client failed privilege check\n");
  936. return STATUS_ACCESS_DENIED;
  937. }
  938. //
  939. // They passed muster
  940. //
  941. return STATUS_SUCCESS;
  942. }