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.

3720 lines
104 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. sepaudit.c
  5. Abstract:
  6. This Module implements the audit and alarm procedures that are
  7. private to the security component.
  8. Author:
  9. Robert Reichel (robertre) September 10, 1991
  10. Environment:
  11. Kernel Mode
  12. Revision History:
  13. --*/
  14. #include "pch.h"
  15. #pragma hdrstop
  16. #include <msaudite.h>
  17. #include <string.h>
  18. #ifdef ALLOC_PRAGMA
  19. #pragma alloc_text(PAGE,SepAdtPrivilegeObjectAuditAlarm)
  20. #pragma alloc_text(PAGE,SepAdtPrivilegedServiceAuditAlarm)
  21. #pragma alloc_text(PAGE,SepAdtOpenObjectAuditAlarm)
  22. #pragma alloc_text(PAGE,SepAdtOpenObjectForDeleteAuditAlarm)
  23. #pragma alloc_text(PAGE,SepAdtCloseObjectAuditAlarm)
  24. #pragma alloc_text(PAGE,SepAdtDeleteObjectAuditAlarm)
  25. #pragma alloc_text(PAGE,SepAdtObjectReferenceAuditAlarm)
  26. #pragma alloc_text(PAGE,SepQueryNameString)
  27. #pragma alloc_text(PAGE,SepQueryTypeString)
  28. #pragma alloc_text(PAGE,SeAuditProcessCreation)
  29. #pragma alloc_text(PAGE,SeAuditHandleDuplication)
  30. #pragma alloc_text(PAGE,SeAuditProcessExit)
  31. #pragma alloc_text(PAGE,SeAuditSystemTimeChange)
  32. #pragma alloc_text(PAGE,SepAdtGenerateDiscardAudit)
  33. #pragma alloc_text(PAGE,SeLocateProcessImageName)
  34. #pragma alloc_text(PAGE,SeInitializeProcessAuditName)
  35. #pragma alloc_text(PAGE,SepAuditAssignPrimaryToken)
  36. #pragma alloc_text(PAGE,SeAuditLPCInvalidUse)
  37. #pragma alloc_text(PAGE,SeAuditHardLinkCreation)
  38. #pragma alloc_text(PAGE,SeOperationAuditAlarm)
  39. #pragma alloc_text(PAGE,SeDetailedAuditingWithToken)
  40. #pragma alloc_text(PAGE,SepAdtAuditThisEventWithContext)
  41. #endif
  42. #define SepSetParmTypeSid( AuditParameters, Index, Sid ) \
  43. { \
  44. (AuditParameters).Parameters[(Index)].Type = SeAdtParmTypeSid; \
  45. (AuditParameters).Parameters[(Index)].Length = SeLengthSid( (Sid) ); \
  46. (AuditParameters).Parameters[(Index)].Address = (Sid); \
  47. }
  48. #define SepSetParmTypeString( AuditParameters, Index, String ) \
  49. { \
  50. (AuditParameters).Parameters[(Index)].Type = SeAdtParmTypeString; \
  51. (AuditParameters).Parameters[(Index)].Length = \
  52. sizeof(UNICODE_STRING)+(String)->Length; \
  53. (AuditParameters).Parameters[(Index)].Address = (String); \
  54. }
  55. #define SepSetParmTypeFileSpec( AuditParameters, Index, String ) \
  56. { \
  57. (AuditParameters).Parameters[(Index)].Type = SeAdtParmTypeFileSpec; \
  58. (AuditParameters).Parameters[(Index)].Length = \
  59. sizeof(UNICODE_STRING)+(String)->Length; \
  60. (AuditParameters).Parameters[(Index)].Address = (String); \
  61. }
  62. #define SepSetParmTypeUlong( AuditParameters, Index, Ulong ) \
  63. { \
  64. (AuditParameters).Parameters[(Index)].Type = SeAdtParmTypeUlong; \
  65. (AuditParameters).Parameters[(Index)].Length = sizeof( (Ulong) ); \
  66. (AuditParameters).Parameters[(Index)].Data[0] = (ULONG)(Ulong); \
  67. }
  68. #define SepSetParmTypeHexUlong( AuditParameters, Index, Ulong ) \
  69. { \
  70. (AuditParameters).Parameters[(Index)].Type = SeAdtParmTypeHexUlong; \
  71. (AuditParameters).Parameters[(Index)].Length = sizeof( (Ulong) ); \
  72. (AuditParameters).Parameters[(Index)].Data[0] = (ULONG)(Ulong); \
  73. }
  74. #define SepSetParmTypePtr( AuditParameters, Index, Ptr ) \
  75. { \
  76. (AuditParameters).Parameters[(Index)].Type = SeAdtParmTypePtr; \
  77. (AuditParameters).Parameters[(Index)].Length = sizeof( ULONG_PTR ); \
  78. (AuditParameters).Parameters[(Index)].Data[0] = (ULONG_PTR)(Ptr); \
  79. }
  80. #define SepSetParmTypeNoLogon( AuditParameters, Index ) \
  81. { \
  82. (AuditParameters).Parameters[(Index)].Type = SeAdtParmTypeNoLogonId; \
  83. }
  84. #define SepSetParmTypeLogonId( AuditParameters, Index, LogonId ) \
  85. { \
  86. LUID * TmpLuid; \
  87. \
  88. (AuditParameters).Parameters[(Index)].Type = SeAdtParmTypeLogonId; \
  89. (AuditParameters).Parameters[(Index)].Length = sizeof( (LogonId) ); \
  90. TmpLuid = (LUID *)(&(AuditParameters).Parameters[(Index)].Data[0]); \
  91. *TmpLuid = (LogonId); \
  92. }
  93. #define SepSetParmTypeAccessMask( AuditParameters, Index, AccessMask, ObjectTypeIndex ) \
  94. { \
  95. ASSERT( (ObjectTypeIndex < Index) && L"SepSetParmTypeAccessMask" ); \
  96. (AuditParameters).Parameters[(Index)].Type = SeAdtParmTypeAccessMask;\
  97. (AuditParameters).Parameters[(Index)].Length = sizeof( ACCESS_MASK );\
  98. (AuditParameters).Parameters[(Index)].Data[0] = (AccessMask); \
  99. (AuditParameters).Parameters[(Index)].Data[1] = (ObjectTypeIndex); \
  100. }
  101. #define SepSetParmTypePrivileges( AuditParameters, Index, Privileges ) \
  102. { \
  103. ASSERT( Privileges->PrivilegeCount <= SEP_MAX_PRIVILEGE_COUNT ); \
  104. (AuditParameters).Parameters[(Index)].Type = SeAdtParmTypePrivs; \
  105. (AuditParameters).Parameters[(Index)].Length = SepPrivilegeSetSize( (Privileges) ); \
  106. (AuditParameters).Parameters[(Index)].Address = (Privileges); \
  107. }
  108. #define SepSetParmTypeObjectTypes( AuditParameters, Index, ObjectTypes, ObjectTypeCount, ObjectTypeIndex ) \
  109. { \
  110. (AuditParameters).Parameters[(Index)].Type = SeAdtParmTypeObjectTypes; \
  111. (AuditParameters).Parameters[(Index)].Length = sizeof( SE_ADT_OBJECT_TYPE ) * (ObjectTypeCount);\
  112. (AuditParameters).Parameters[(Index)].Address = (ObjectTypes); \
  113. (AuditParameters).Parameters[(Index)].Data[1] = (ObjectTypeIndex); \
  114. }
  115. #define SepSetParmTypeTime( AuditParameters, Index, Time ) \
  116. { \
  117. (AuditParameters).Parameters[(Index)].Type = SeAdtParmTypeTime; \
  118. (AuditParameters).Parameters[(Index)].Length = sizeof( (Time) ); \
  119. *((PLARGE_INTEGER)(&(AuditParameters).Parameters[(Index)].Data[0])) = Time; \
  120. }
  121. BOOLEAN
  122. FASTCALL
  123. SeDetailedAuditingWithToken(
  124. IN PACCESS_TOKEN AccessToken OPTIONAL
  125. )
  126. /*++
  127. Routine Description
  128. This routine computes whether or not a detailed tracking audit should be
  129. generated for a given token or context. If no token is passed then the
  130. current effective token will be captured.
  131. The caller is responsible for referencing and dereferencing AccessToken.
  132. Arguments
  133. AccessToken - token for which to query audit policy
  134. Return Value
  135. BOOLEAN.
  136. --*/
  137. {
  138. PTOKEN Token;
  139. ULONG Mask;
  140. SECURITY_SUBJECT_CONTEXT LocalSecurityContext;
  141. BOOLEAN AuditThisEvent;
  142. PAGED_CODE();
  143. if (SepTokenPolicyCounter[AuditCategoryDetailedTracking] == 0) {
  144. return SeAuditingState[AuditCategoryDetailedTracking].AuditOnSuccess;
  145. }
  146. //
  147. // If no token was passed in and there exists tokens in the system with
  148. // detailed tracking per user policy settings then capture the context.
  149. //
  150. if (ARGUMENT_PRESENT(AccessToken)) {
  151. Token = (PTOKEN)AccessToken;
  152. } else {
  153. SeCaptureSubjectContext( &LocalSecurityContext );
  154. Token = EffectiveToken( &LocalSecurityContext );
  155. }
  156. //
  157. // Audit if the token specifies success auditing (there is not a detailed tracking failure concept)
  158. // or if global audit policy specifies detailed tracking auditing and this token is not excluded.
  159. //
  160. Mask = Token->AuditPolicy.PolicyElements.DetailedTracking;
  161. if ( (Mask & TOKEN_AUDIT_SUCCESS_INCLUDE) ||
  162. (SeAuditingState[AuditCategoryDetailedTracking].AuditOnSuccess && (0 == (Mask & TOKEN_AUDIT_SUCCESS_EXCLUDE))) ) {
  163. AuditThisEvent = TRUE;
  164. } else {
  165. AuditThisEvent = FALSE;
  166. }
  167. if (AccessToken == NULL) {
  168. //
  169. // if AccessToken is NULL then we had to capture the context. Release
  170. // it.
  171. //
  172. SeReleaseSubjectContext( &LocalSecurityContext );
  173. }
  174. return AuditThisEvent;
  175. }
  176. //
  177. // ISSUE-2002/03/07-kumarp : the semantics of AccessGranted/AccessDenied
  178. // is confusing. The function should really get success/failure flag as param
  179. // to return the right setting.
  180. //
  181. // Further, these functions should be rearranged so that the inner-most
  182. // function is SepAdtAuditThisEventWithToken and everything else ends up
  183. // calling it with right parameters
  184. //
  185. // Longhorn bug# 595575
  186. //
  187. BOOLEAN
  188. SepAdtAuditThisEventWithContext(
  189. IN POLICY_AUDIT_EVENT_TYPE Category,
  190. IN BOOLEAN AccessGranted,
  191. IN BOOLEAN AccessDenied,
  192. IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext OPTIONAL
  193. )
  194. /*++
  195. Routine Description
  196. Determines if an audit should be generated based upon current policy
  197. settings and the per user audit policy set in the effective token of
  198. the context. If no context is passed in then the current context is
  199. captured and examined.
  200. Arguments
  201. Category - the category for which we determine whether or not
  202. to generate an audit
  203. AccessGranted - whether or not access was granted
  204. AccessDenied - whether or not access was denied
  205. SubjectSecurityContext - the context to query for per user settings
  206. Return Value
  207. BOOLEAN.
  208. --*/
  209. {
  210. ULONG Mask;
  211. PTOKEN Token;
  212. SECURITY_SUBJECT_CONTEXT LocalSecurityContext;
  213. PSECURITY_SUBJECT_CONTEXT pLocalSecurityContext;
  214. BOOLEAN AuditThisEvent = FALSE;
  215. PAGED_CODE();
  216. ASSERT((!(AccessGranted && AccessDenied)) && "SepAdtAuditThisEventWithContext");
  217. if ((SeAuditingState[Category].AuditOnSuccess && AccessGranted) ||
  218. (SeAuditingState[Category].AuditOnFailure && AccessDenied)) {
  219. AuditThisEvent = TRUE;
  220. } else {
  221. AuditThisEvent = FALSE;
  222. }
  223. if (SepTokenPolicyCounter[Category] == 0) {
  224. return AuditThisEvent;
  225. }
  226. //
  227. // We cannot decide quickly whether or not to audit (there exist tokens
  228. // with per user policy settings), so continue with
  229. // examining the token's policy.
  230. //
  231. if (!ARGUMENT_PRESENT(SubjectSecurityContext)) {
  232. pLocalSecurityContext = &LocalSecurityContext;
  233. SeCaptureSubjectContext( pLocalSecurityContext );
  234. } else {
  235. pLocalSecurityContext = SubjectSecurityContext;
  236. }
  237. Token = EffectiveToken( pLocalSecurityContext );
  238. //
  239. // Now we have to check the token audit mask because the token may
  240. // override the policy and say 'do not audit,' even though the array claims we
  241. // must (or vice versa)
  242. //
  243. switch (Category) {
  244. case AuditCategorySystem:
  245. Mask = Token->AuditPolicy.PolicyElements.System;
  246. break;
  247. case AuditCategoryLogon:
  248. Mask = Token->AuditPolicy.PolicyElements.Logon;
  249. break;
  250. case AuditCategoryObjectAccess:
  251. Mask = Token->AuditPolicy.PolicyElements.ObjectAccess;
  252. break;
  253. case AuditCategoryPrivilegeUse:
  254. Mask = Token->AuditPolicy.PolicyElements.PrivilegeUse;
  255. break;
  256. case AuditCategoryDetailedTracking:
  257. Mask = Token->AuditPolicy.PolicyElements.DetailedTracking;
  258. break;
  259. case AuditCategoryPolicyChange:
  260. Mask = Token->AuditPolicy.PolicyElements.PolicyChange;
  261. break;
  262. case AuditCategoryAccountManagement:
  263. Mask = Token->AuditPolicy.PolicyElements.AccountManagement;
  264. break;
  265. case AuditCategoryDirectoryServiceAccess:
  266. Mask = Token->AuditPolicy.PolicyElements.DirectoryServiceAccess;
  267. break;
  268. case AuditCategoryAccountLogon:
  269. Mask = Token->AuditPolicy.PolicyElements.AccountLogon;
  270. break;
  271. default:
  272. ASSERT(FALSE && "Illegal audit category");
  273. Mask = 0;
  274. break;
  275. }
  276. if (Mask) {
  277. //
  278. // If granted and the token is marked for success_include OR
  279. // if not granted and token is marked for failure_include then
  280. // audit the event.
  281. //
  282. if (( AccessGranted && (Mask & TOKEN_AUDIT_SUCCESS_INCLUDE) ) ||
  283. ( AccessDenied && (Mask & TOKEN_AUDIT_FAILURE_INCLUDE) )) {
  284. AuditThisEvent = TRUE;
  285. }
  286. //
  287. // If granted and the token is marked for success_exclude OR
  288. // if not granted and token is marked for failure_exclude then
  289. // do not audit the event.
  290. //
  291. else if (( AccessGranted && (Mask & TOKEN_AUDIT_SUCCESS_EXCLUDE) ) ||
  292. ( AccessDenied && (Mask & TOKEN_AUDIT_FAILURE_EXCLUDE) )) {
  293. AuditThisEvent = FALSE;
  294. }
  295. }
  296. if (!ARGUMENT_PRESENT(SubjectSecurityContext)) {
  297. SeReleaseSubjectContext( pLocalSecurityContext );
  298. }
  299. return AuditThisEvent;
  300. }
  301. BOOLEAN
  302. SepAdtPrivilegeObjectAuditAlarm (
  303. IN PUNICODE_STRING CapturedSubsystemName OPTIONAL,
  304. IN PVOID HandleId,
  305. IN PTOKEN ClientToken OPTIONAL,
  306. IN PTOKEN PrimaryToken,
  307. IN PVOID ProcessId,
  308. IN ACCESS_MASK DesiredAccess,
  309. IN PPRIVILEGE_SET CapturedPrivileges,
  310. IN BOOLEAN AccessGranted
  311. )
  312. /*++
  313. Routine Description:
  314. Implements NtPrivilegeObjectAuditAlarm after parameters have been
  315. captured.
  316. This routine is used to generate audit and alarm messages when an
  317. attempt is made to perform privileged operations on a protected
  318. subsystem object after the object is already opened. This routine may
  319. result in several messages being generated and sent to Port objects.
  320. This may result in a significant latency before returning. Design of
  321. routines that must call this routine must take this potential latency
  322. into account. This may have an impact on the approach taken for data
  323. structure mutex locking, for example.
  324. This routine will create an SE_ADT_PARAMETERS array organized as follows:
  325. Parameter[0] - User Sid
  326. Parameter[1] - Subsystem name (if available)
  327. Parameter[2] - Subsystem name (if available)
  328. Parameter[3] - New handle ID
  329. Parameter[4] - Subject's process id
  330. Parameter[5] - Subject's primary authentication ID
  331. Parameter[6] - Subject's client authentication ID
  332. Parameter[7] - Privileges used for open
  333. Arguments:
  334. CapturedSubsystemName - Supplies a name string identifying the
  335. subsystem calling the routine.
  336. HandleId - A unique value representing the client's handle to the
  337. object.
  338. ClientToken - Optionally provides a pointer to the client token
  339. (only if the caller is currently impersonating)
  340. PrimaryToken - Provides a pointer to the caller's primary token.
  341. DesiredAccess - The desired access mask. This mask must have been
  342. previously mapped to contain no generic accesses.
  343. CapturedPrivileges - The set of privileges required for the requested
  344. operation. Those privileges that were held by the subject are
  345. marked using the UsedForAccess flag of the attributes
  346. associated with each privilege.
  347. AccessGranted - Indicates whether the requested access was granted or
  348. not. A value of TRUE indicates the access was granted. A value of
  349. FALSE indicates the access was not granted.
  350. Return value:
  351. --*/
  352. {
  353. SE_ADT_PARAMETER_ARRAY AuditParameters;
  354. PSID CapturedUserSid;
  355. LUID ClientAuthenticationId;
  356. LUID PrimaryAuthenticationId;
  357. PUNICODE_STRING SubsystemName;
  358. PAGED_CODE();
  359. UNREFERENCED_PARAMETER( DesiredAccess );
  360. //
  361. // Determine if we are auditing the use of privileges
  362. //
  363. if ( SepAdtAuditThisEventWithContext( AuditCategoryPrivilegeUse, AccessGranted, !AccessGranted, NULL ) &&
  364. SepFilterPrivilegeAudits( CapturedPrivileges )) {
  365. if ( ARGUMENT_PRESENT( ClientToken )) {
  366. CapturedUserSid = SepTokenUserSid( ClientToken );
  367. } else {
  368. CapturedUserSid = SepTokenUserSid( PrimaryToken );
  369. }
  370. if ( RtlEqualSid( SeLocalSystemSid, CapturedUserSid )) {
  371. return (FALSE);
  372. }
  373. PrimaryAuthenticationId = SepTokenAuthenticationId( PrimaryToken );
  374. if ( !ARGUMENT_PRESENT( CapturedSubsystemName )) {
  375. SubsystemName = (PUNICODE_STRING)&SeSubsystemName;
  376. } else {
  377. SubsystemName = CapturedSubsystemName;
  378. }
  379. //
  380. // A completely zero'd entry will be interpreted
  381. // as a "null string" or not supplied parameter.
  382. //
  383. // Initializing the entire array up front will allow
  384. // us to avoid filling in each not supplied entry.
  385. //
  386. RtlZeroMemory (
  387. (PVOID) &AuditParameters,
  388. sizeof( AuditParameters )
  389. );
  390. ASSERT( SeAdtParmTypeNone == 0 );
  391. AuditParameters.CategoryId = SE_CATEGID_PRIVILEGE_USE;
  392. AuditParameters.AuditId = SE_AUDITID_PRIVILEGED_OBJECT;
  393. AuditParameters.ParameterCount = 0;
  394. if ( AccessGranted ) {
  395. AuditParameters.Type = EVENTLOG_AUDIT_SUCCESS;
  396. } else {
  397. AuditParameters.Type = EVENTLOG_AUDIT_FAILURE;
  398. }
  399. //
  400. // Parameter[0] - User Sid
  401. //
  402. SepSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, CapturedUserSid );
  403. AuditParameters.ParameterCount++;
  404. //
  405. // Parameter[1] - Subsystem name
  406. //
  407. SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, SubsystemName );
  408. AuditParameters.ParameterCount++;
  409. //
  410. // Parameter[2] - Subsystem name (if available)
  411. //
  412. if (ARGUMENT_PRESENT( CapturedSubsystemName )) {
  413. SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, CapturedSubsystemName );
  414. }
  415. AuditParameters.ParameterCount++;
  416. //
  417. // Parameter[3] - New handle ID
  418. //
  419. SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, HandleId );
  420. AuditParameters.ParameterCount++;
  421. //
  422. // Parameter[4] - Subject's process id
  423. //
  424. SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, ProcessId );
  425. AuditParameters.ParameterCount++;
  426. //
  427. // Parameter[5] - Subject's primary authentication ID
  428. //
  429. SepSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, PrimaryAuthenticationId );
  430. AuditParameters.ParameterCount++;
  431. //
  432. // Parameter[6] - Subject's client authentication ID
  433. //
  434. if ( ARGUMENT_PRESENT( ClientToken )) {
  435. ClientAuthenticationId = SepTokenAuthenticationId( ClientToken );
  436. SepSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, ClientAuthenticationId );
  437. } else {
  438. SepSetParmTypeNoLogon( AuditParameters, AuditParameters.ParameterCount );
  439. }
  440. AuditParameters.ParameterCount++;
  441. //
  442. // Parameter[7] - Privileges used for open
  443. //
  444. //
  445. // Longhorn-ISSUE-2002/02/21-kumarp : remove the NULL check after fixing bug# 551545
  446. //
  447. if ( (CapturedPrivileges != NULL) && (CapturedPrivileges->PrivilegeCount > 0) ) {
  448. SepSetParmTypePrivileges( AuditParameters, AuditParameters.ParameterCount, CapturedPrivileges );
  449. }
  450. AuditParameters.ParameterCount++;
  451. SepAdtLogAuditRecord( &AuditParameters );
  452. return ( TRUE );
  453. }
  454. return ( FALSE );
  455. }
  456. VOID
  457. SepAdtPrivilegedServiceAuditAlarm (
  458. IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext,
  459. IN PUNICODE_STRING CapturedSubsystemName,
  460. IN PUNICODE_STRING CapturedServiceName,
  461. IN PTOKEN ClientToken OPTIONAL,
  462. IN PTOKEN PrimaryToken,
  463. IN PPRIVILEGE_SET CapturedPrivileges,
  464. IN BOOLEAN AccessGranted
  465. )
  466. /*++
  467. Routine Description:
  468. This routine is the active part of NtPrivilegedServiceAuditAlarm.
  469. This routine is used to generate audit and alarm messages when an
  470. attempt is made to perform privileged system service operations. This
  471. routine may result in several messages being generated and sent to Port
  472. objects. This may result in a significant latency before returning.
  473. Design of routines that must call this routine must take this potential
  474. latency into account. This may have an impact on the approach taken
  475. for data structure mutex locking, for example.
  476. This routine will create an SE_ADT_PARAMETERS array organized as follows:
  477. Parameter[0] - User Sid
  478. Parameter[1] - Subsystem name (if available)
  479. Parameter[2] - object server (same as Subsystem name)
  480. Parameter[3] - Subject's primary authentication ID
  481. Parameter[4] - Subject's client authentication ID
  482. Parameter[5] - Privileges used for open
  483. Arguments:
  484. SubjectSecurityContext - The subject security context representing
  485. the caller of the system service.
  486. SubsystemName - Supplies a name string identifying the subsystem
  487. calling the routine.
  488. ServiceName - Supplies a name of the privileged subsystem service. For
  489. example, "RESET RUNTIME LOCAL SECURITY" might be specified
  490. by a Local Security Authority service used to update the local
  491. security policy database.
  492. ClientToken - Optionally provides a pointer to the client token
  493. (only if the caller is currently impersonating)
  494. PrimaryToken - Provides a pointer to the caller's primary token.
  495. Privileges - Points to a set of privileges required to perform the
  496. privileged operation. Those privileges that were held by the
  497. subject are marked using the UsedForAccess flag of the
  498. attributes associated with each privilege.
  499. AccessGranted - Indicates whether the requested access was granted or
  500. not. A value of TRUE indicates the access was granted. A value of
  501. FALSE indicates the access was not granted.
  502. Return value:
  503. --*/
  504. {
  505. SE_ADT_PARAMETER_ARRAY AuditParameters;
  506. PSID CapturedUserSid;
  507. LUID ClientAuthenticationId;
  508. LUID PrimaryAuthenticationId;
  509. PUNICODE_STRING SubsystemName;
  510. PAGED_CODE();
  511. //
  512. // Determine if we are auditing privileged services
  513. //
  514. if ( !(SepAdtAuditThisEventWithContext( AuditCategoryPrivilegeUse, AccessGranted, !AccessGranted, SubjectSecurityContext ) &&
  515. SepFilterPrivilegeAudits( CapturedPrivileges ))) {
  516. return;
  517. }
  518. if ( ARGUMENT_PRESENT( ClientToken )) {
  519. CapturedUserSid = SepTokenUserSid( ClientToken );
  520. } else {
  521. CapturedUserSid = SepTokenUserSid( PrimaryToken );
  522. }
  523. PrimaryAuthenticationId = SepTokenAuthenticationId( PrimaryToken );
  524. if ( !ARGUMENT_PRESENT( CapturedSubsystemName )) {
  525. SubsystemName = (PUNICODE_STRING)&SeSubsystemName;
  526. } else {
  527. SubsystemName = CapturedSubsystemName;
  528. }
  529. //
  530. // A completely zero'd entry will be interpreted
  531. // as a "null string" or not supplied parameter.
  532. //
  533. // Initializing the entire array up front will allow
  534. // us to avoid filling in each not supplied entry.
  535. //
  536. RtlZeroMemory (
  537. (PVOID) &AuditParameters,
  538. sizeof( AuditParameters )
  539. );
  540. ASSERT( SeAdtParmTypeNone == 0 );
  541. AuditParameters.CategoryId = SE_CATEGID_PRIVILEGE_USE;
  542. AuditParameters.AuditId = SE_AUDITID_PRIVILEGED_SERVICE;
  543. AuditParameters.ParameterCount = 0;
  544. if ( AccessGranted ) {
  545. AuditParameters.Type = EVENTLOG_AUDIT_SUCCESS;
  546. } else {
  547. AuditParameters.Type = EVENTLOG_AUDIT_FAILURE;
  548. }
  549. //
  550. // Parameter[0] - User Sid
  551. //
  552. SepSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, CapturedUserSid );
  553. AuditParameters.ParameterCount++;
  554. //
  555. // Parameter[1] - Subsystem name
  556. //
  557. SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, SubsystemName );
  558. AuditParameters.ParameterCount++;
  559. //
  560. // Parameter[2] - Server
  561. //
  562. SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, SubsystemName );
  563. AuditParameters.ParameterCount++;
  564. //
  565. // Parameter[3] - Service name (if available)
  566. //
  567. if ( ARGUMENT_PRESENT( CapturedServiceName )) {
  568. SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, CapturedServiceName );
  569. }
  570. AuditParameters.ParameterCount++;
  571. //
  572. // Parameter[3] - Subject's primary authentication ID
  573. //
  574. SepSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, PrimaryAuthenticationId );
  575. AuditParameters.ParameterCount++;
  576. //
  577. // Parameter[4] - Subject's client authentication ID
  578. //
  579. if ( ARGUMENT_PRESENT( ClientToken )) {
  580. ClientAuthenticationId = SepTokenAuthenticationId( ClientToken );
  581. SepSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, ClientAuthenticationId );
  582. } else {
  583. SepSetParmTypeNoLogon( AuditParameters, AuditParameters.ParameterCount );
  584. }
  585. AuditParameters.ParameterCount++;
  586. //
  587. // Parameter[5] - Privileges used for open
  588. //
  589. //
  590. // Longhorn-ISSUE-2002/02/21-kumarp : remove the NULL check after fixing bug# 551690
  591. //
  592. if ( (CapturedPrivileges != NULL) && (CapturedPrivileges->PrivilegeCount > 0) ) {
  593. SepSetParmTypePrivileges( AuditParameters, AuditParameters.ParameterCount, CapturedPrivileges );
  594. }
  595. AuditParameters.ParameterCount++;
  596. SepAdtLogAuditRecord( &AuditParameters );
  597. }
  598. BOOLEAN
  599. SepAdtOpenObjectAuditAlarm (
  600. IN PUNICODE_STRING CapturedSubsystemName,
  601. IN PVOID *HandleId OPTIONAL,
  602. IN PUNICODE_STRING CapturedObjectTypeName,
  603. IN PUNICODE_STRING CapturedObjectName OPTIONAL,
  604. IN PTOKEN ClientToken OPTIONAL,
  605. IN PTOKEN PrimaryToken,
  606. IN ACCESS_MASK DesiredAccess,
  607. IN ACCESS_MASK GrantedAccess,
  608. IN PLUID OperationId,
  609. IN PPRIVILEGE_SET CapturedPrivileges OPTIONAL,
  610. IN BOOLEAN AccessGranted,
  611. IN HANDLE ProcessID,
  612. IN POLICY_AUDIT_EVENT_TYPE AuditType,
  613. IN PIOBJECT_TYPE_LIST ObjectTypeList OPTIONAL,
  614. IN ULONG ObjectTypeListLength,
  615. IN PACCESS_MASK GrantedAccessArray OPTIONAL
  616. )
  617. /*++
  618. Routine Description:
  619. Implements NtOpenObjectAuditAlarm after parameters have been captured.
  620. This routine is used to generate audit and alarm messages when an
  621. attempt is made to access an existing protected subsystem object or
  622. create a new one. This routine may result in several messages being
  623. generated and sent to Port objects. This may result in a significant
  624. latency before returning. Design of routines that must call this
  625. routine must take this potential latency into account. This may have
  626. an impact on the approach taken for data structure mutex locking, for
  627. example. This API requires the caller have SeTcbPrivilege privilege.
  628. The test for this privilege is always against the primary token of the
  629. calling process, not the impersonation token of the thread.
  630. This routine will create an SE_ADT_PARAMETERS array organized as follows:
  631. Parameter[0] - User Sid
  632. Parameter[1] - Subsystem name (if available)
  633. Parameter[2] - Server name (if available)
  634. Parameter[3] - Object Type Name
  635. Parameter[4] - Object Name
  636. Parameter[5] - New handle ID
  637. Parameter[6] - Subject's process id
  638. Parameter[7] - Subject's image file name
  639. Parameter[8] - Subject's primary authentication ID
  640. Parameter[9] - Subject's client authentication ID
  641. Parameter[10] - DesiredAccess mask
  642. Parameter[11] - Privileges used for open
  643. Parameter[12] - Guid/Level/AccessMask of objects/property sets/properties accesses.
  644. Parameter[13] - Number of restricted SIDs in the token
  645. Arguments:
  646. CapturedSubsystemName - Supplies a name string identifying the
  647. subsystem calling the routine.
  648. HandleId - A unique value representing the client's handle to the
  649. object. If the access attempt was not successful (AccessGranted is
  650. FALSE), then this parameter is ignored.
  651. CapturedObjectTypeName - Supplies the name of the type of object being
  652. accessed.
  653. CapturedObjectName - Supplies the name of the object the client
  654. accessed or attempted to access.
  655. CapturedSecurityDescriptor - A pointer to the security descriptor of
  656. the object being accessed.
  657. ClientToken - Optionally provides a pointer to the client token
  658. (only if the caller is currently impersonating)
  659. PrimaryToken - Provides a pointer to the caller's primary token.
  660. DesiredAccess - The desired access mask. This mask must have been
  661. previously mapped to contain no generic accesses.
  662. GrantedAccess - The mask of accesses that were actually granted.
  663. CapturedPrivileges - Optionally points to a set of privileges that were
  664. required for the access attempt. Those privileges that were held
  665. by the subject are marked using the UsedForAccess flag of the
  666. attributes associated with each privilege.
  667. ObjectCreation - A boolean flag indicating whether the access will
  668. result in a new object being created if granted. A value of TRUE
  669. indicates an object will be created, FALSE indicates an existing
  670. object will be opened.
  671. AccessGranted - Indicates whether the requested access was granted or
  672. not. A value of TRUE indicates the access was granted. A value of
  673. FALSE indicates the access was not granted.
  674. GenerateOnClose - Points to a boolean that is set by the audit
  675. generation routine and must be passed to NtCloseObjectAuditAlarm()
  676. when the object handle is closed.
  677. GenerateAudit - Indicates if we should generate an audit for this operation.
  678. GenerateAlarm - Indicates if we should generate an alarm for this operation.
  679. AuditType - Specifies the type of audit to be generated. Valid values
  680. are: AuditCategoryObjectAccess and AuditCategoryDirectoryServiceAccess.
  681. ObjectTypeList - Supplies a list of GUIDs representing the object (and
  682. sub-objects) being accessed.
  683. ObjectTypeListLength - Specifies the number of elements in the ObjectTypeList.
  684. GrantedAccessArray - If non NULL, specifies an array of access mask granted
  685. to each object in ObjectTypeList.
  686. Return Value:
  687. Returns TRUE if audit is generated, FALSE otherwise.
  688. --*/
  689. {
  690. SE_ADT_PARAMETER_ARRAY AuditParameters;
  691. ULONG ObjectTypeIndex;
  692. PSID CapturedUserSid;
  693. LUID PrimaryAuthenticationId = { 0 };
  694. LUID ClientAuthenticationId = { 0 };
  695. PSE_ADT_OBJECT_TYPE AdtObjectTypeBuffer = NULL;
  696. PEPROCESS Process = NULL;
  697. PUNICODE_STRING ImageFileName;
  698. UNICODE_STRING NullString = {0};
  699. NTSTATUS Status;
  700. PUNICODE_STRING SubsystemName;
  701. PAGED_CODE();
  702. Process = PsGetCurrentProcess();
  703. Status = SeLocateProcessImageName( Process, &ImageFileName );
  704. if ( !NT_SUCCESS(Status) ) {
  705. ImageFileName = &NullString;
  706. //
  707. // ignore this failure
  708. //
  709. Status = STATUS_SUCCESS;
  710. }
  711. if ( ARGUMENT_PRESENT( ClientToken )) {
  712. CapturedUserSid = SepTokenUserSid( ClientToken );
  713. ClientAuthenticationId = SepTokenAuthenticationId( ClientToken );
  714. } else {
  715. CapturedUserSid = SepTokenUserSid( PrimaryToken );
  716. }
  717. PrimaryAuthenticationId = SepTokenAuthenticationId( PrimaryToken );
  718. //
  719. // A completely zero'd entry will be interpreted
  720. // as a "null string" or not supplied parameter.
  721. //
  722. // Initializing the entire array up front will allow
  723. // us to avoid filling in each not supplied entry.
  724. //
  725. RtlZeroMemory (
  726. (PVOID) &AuditParameters,
  727. sizeof( AuditParameters )
  728. );
  729. ASSERT( SeAdtParmTypeNone == 0 );
  730. ASSERT( ( AuditType == AuditCategoryObjectAccess ) ||
  731. ( AuditType == AuditCategoryDirectoryServiceAccess ) );
  732. if (AuditType == AuditCategoryObjectAccess) {
  733. AuditParameters.CategoryId = SE_CATEGID_OBJECT_ACCESS;
  734. } else {
  735. AuditParameters.CategoryId = SE_CATEGID_DS_ACCESS;
  736. }
  737. AuditParameters.AuditId = SE_AUDITID_OPEN_HANDLE;
  738. AuditParameters.ParameterCount = 0;
  739. if ( AccessGranted ) {
  740. AuditParameters.Type = EVENTLOG_AUDIT_SUCCESS;
  741. } else {
  742. AuditParameters.Type = EVENTLOG_AUDIT_FAILURE;
  743. }
  744. if ( !ARGUMENT_PRESENT( CapturedSubsystemName )) {
  745. SubsystemName = (PUNICODE_STRING)&SeSubsystemName;
  746. } else {
  747. SubsystemName = CapturedSubsystemName;
  748. }
  749. //
  750. // Parameter[0] - User Sid
  751. //
  752. SepSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, CapturedUserSid );
  753. AuditParameters.ParameterCount++;
  754. //
  755. // Parameter[1] - Subsystem name
  756. //
  757. SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, SubsystemName );
  758. AuditParameters.ParameterCount++;
  759. //
  760. // Parameter[2] - Object Server (if available)
  761. //
  762. if ( ARGUMENT_PRESENT( CapturedSubsystemName )) {
  763. SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, CapturedSubsystemName );
  764. }
  765. AuditParameters.ParameterCount++;
  766. //
  767. // Parameter[3] - Object Type Name
  768. //
  769. if ( !ARGUMENT_PRESENT( CapturedObjectTypeName )) {
  770. //
  771. // We have to have an ObjectTypeName for the audit to succeed.
  772. //
  773. Status = STATUS_INVALID_PARAMETER;
  774. goto Cleanup;
  775. }
  776. SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, CapturedObjectTypeName );
  777. ObjectTypeIndex = AuditParameters.ParameterCount;
  778. AuditParameters.ParameterCount++;
  779. //
  780. // Parameter[4] - Object Name
  781. //
  782. if ( ARGUMENT_PRESENT( CapturedObjectName )) {
  783. SepSetParmTypeFileSpec( AuditParameters, AuditParameters.ParameterCount, CapturedObjectName );
  784. }
  785. AuditParameters.ParameterCount++;
  786. //
  787. // Parameter[5] - New handle ID
  788. //
  789. if ( ARGUMENT_PRESENT( HandleId )) {
  790. SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, *HandleId );
  791. }
  792. AuditParameters.ParameterCount++;
  793. if ( ARGUMENT_PRESENT( OperationId )) {
  794. SepSetParmTypeUlong( AuditParameters, AuditParameters.ParameterCount, (*OperationId).HighPart );
  795. AuditParameters.ParameterCount++;
  796. SepSetParmTypeUlong( AuditParameters, AuditParameters.ParameterCount, (*OperationId).LowPart );
  797. AuditParameters.ParameterCount++;
  798. } else {
  799. AuditParameters.ParameterCount += 2;
  800. }
  801. //
  802. // Parameter[6] - Subject's process id
  803. //
  804. SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, ProcessID );
  805. AuditParameters.ParameterCount++;
  806. //
  807. // Parameter[7] - Subject's Image Name
  808. //
  809. SepSetParmTypeFileSpec( AuditParameters, AuditParameters.ParameterCount, ImageFileName );
  810. AuditParameters.ParameterCount ++;
  811. //
  812. // Parameter[8] - Subject's primary authentication ID
  813. //
  814. SepSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, PrimaryAuthenticationId );
  815. AuditParameters.ParameterCount++;
  816. //
  817. // Parameter[9] - Subject's client authentication ID
  818. //
  819. if ( ARGUMENT_PRESENT( ClientToken )) {
  820. SepSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, ClientAuthenticationId );
  821. } else {
  822. SepSetParmTypeNoLogon( AuditParameters, AuditParameters.ParameterCount );
  823. }
  824. AuditParameters.ParameterCount++;
  825. //
  826. // Parameter[10] - DesiredAccess mask
  827. //
  828. if ( AccessGranted ) {
  829. SepSetParmTypeAccessMask( AuditParameters, AuditParameters.ParameterCount, GrantedAccess, ObjectTypeIndex );
  830. } else {
  831. SepSetParmTypeAccessMask( AuditParameters, AuditParameters.ParameterCount, DesiredAccess, ObjectTypeIndex );
  832. }
  833. AuditParameters.ParameterCount++;
  834. //
  835. // Parameter[11] - Privileges used for open
  836. //
  837. if ( (CapturedPrivileges != NULL) && (CapturedPrivileges->PrivilegeCount > 0) ) {
  838. SepSetParmTypePrivileges( AuditParameters, AuditParameters.ParameterCount, CapturedPrivileges );
  839. }
  840. AuditParameters.ParameterCount++;
  841. //
  842. // Parameter[12] - ObjectTypes of Audited objects/parameter sets/parameters
  843. //
  844. if ( ObjectTypeListLength != 0 ) {
  845. ULONG GuidCount;
  846. ULONG i;
  847. USHORT FlagMask = AccessGranted ? OBJECT_SUCCESS_AUDIT : OBJECT_FAILURE_AUDIT;
  848. //
  849. // Count the number of GUIDs to audit.
  850. //
  851. GuidCount = 0;
  852. for ( i=0; i<ObjectTypeListLength; i++ ) {
  853. if ( i == 0 ) {
  854. GuidCount++;
  855. } else if ( ObjectTypeList[i].Flags & FlagMask ) {
  856. GuidCount ++;
  857. }
  858. }
  859. //
  860. // If there are any Guids to audit,
  861. // copy them into a locally allocated buffer.
  862. //
  863. if ( GuidCount > 0 ) {
  864. AdtObjectTypeBuffer = ExAllocatePoolWithTag( PagedPool, GuidCount * sizeof(SE_ADT_OBJECT_TYPE), 'pAeS' );
  865. //
  866. // If the buffer can be allocated,
  867. // fill it in.
  868. // If not,
  869. // generate a truncated audit.
  870. //
  871. if ( AdtObjectTypeBuffer != NULL ) {
  872. //
  873. // Copy the GUIDs and optional access masks to the buffer.
  874. //
  875. GuidCount = 0;
  876. for ( i=0; i<ObjectTypeListLength; i++ ) {
  877. if ( ( i > 0 ) && !( ObjectTypeList[i].Flags & FlagMask ) ) {
  878. continue;
  879. } else {
  880. AdtObjectTypeBuffer[GuidCount].ObjectType = ObjectTypeList[i].ObjectType;
  881. AdtObjectTypeBuffer[GuidCount].Level = ObjectTypeList[i].Level;
  882. if ( i == 0 ) {
  883. //
  884. // Always copy the GUID representing the object itself.
  885. // Mark it as a such to avoid including it in the audit.
  886. //
  887. AdtObjectTypeBuffer[GuidCount].Flags = SE_ADT_OBJECT_ONLY;
  888. AdtObjectTypeBuffer[GuidCount].AccessMask = 0;
  889. } else {
  890. AdtObjectTypeBuffer[GuidCount].Flags = 0;
  891. if ( ARGUMENT_PRESENT(GrantedAccessArray) && AccessGranted ) {
  892. AdtObjectTypeBuffer[GuidCount].AccessMask = GrantedAccessArray[i];
  893. }
  894. }
  895. GuidCount ++;
  896. }
  897. }
  898. //
  899. // Store the Object Types.
  900. //
  901. SepSetParmTypeObjectTypes( AuditParameters, AuditParameters.ParameterCount, AdtObjectTypeBuffer, GuidCount, ObjectTypeIndex );
  902. AuditParameters.ParameterCount ++;
  903. AuditParameters.AuditId = SE_AUDITID_OPEN_HANDLE_OBJECT_TYPE;
  904. }
  905. }
  906. }
  907. //
  908. // Parameter[13] - Restricted Sids in token
  909. //
  910. SepSetParmTypeUlong( AuditParameters, AuditParameters.ParameterCount, PrimaryToken->RestrictedSidCount );
  911. AuditParameters.ParameterCount ++;
  912. //
  913. // Parameter[14] - AccessMask in hex
  914. //
  915. if ( AccessGranted ) {
  916. SepSetParmTypeHexUlong( AuditParameters, AuditParameters.ParameterCount, GrantedAccess );
  917. } else {
  918. SepSetParmTypeHexUlong( AuditParameters, AuditParameters.ParameterCount, DesiredAccess );
  919. }
  920. AuditParameters.ParameterCount ++;
  921. //
  922. // Audit it.
  923. //
  924. SepAdtLogAuditRecord( &AuditParameters );
  925. Cleanup:
  926. if ( AdtObjectTypeBuffer != NULL ) {
  927. ExFreePool( AdtObjectTypeBuffer );
  928. }
  929. if ( ImageFileName != &NullString ) {
  930. ExFreePool( ImageFileName );
  931. }
  932. return( NT_SUCCESS(Status) );
  933. }
  934. BOOLEAN
  935. SepAdtOpenObjectForDeleteAuditAlarm (
  936. IN PUNICODE_STRING CapturedSubsystemName,
  937. IN PVOID *HandleId OPTIONAL,
  938. IN PUNICODE_STRING CapturedObjectTypeName,
  939. IN PUNICODE_STRING CapturedObjectName OPTIONAL,
  940. IN PTOKEN ClientToken OPTIONAL,
  941. IN PTOKEN PrimaryToken,
  942. IN ACCESS_MASK DesiredAccess,
  943. IN ACCESS_MASK GrantedAccess,
  944. IN PLUID OperationId,
  945. IN PPRIVILEGE_SET CapturedPrivileges OPTIONAL,
  946. IN BOOLEAN AccessGranted,
  947. IN HANDLE ProcessID
  948. )
  949. /*++
  950. Routine Description:
  951. Implements SeOpenObjectForDeleteAuditAlarm after parameters have been
  952. captured.
  953. This routine is used to generate audit and alarm messages when an
  954. attempt is made to access an existing protected subsystem object or
  955. create a new one. This routine may result in several messages being
  956. generated and sent to Port objects. This may result in a significant
  957. latency before returning. Design of routines that must call this
  958. routine must take this potential latency into account. This may have
  959. an impact on the approach taken for data structure mutex locking, for
  960. example. This API requires the caller have SeTcbPrivilege privilege.
  961. The test for this privilege is always against the primary token of the
  962. calling process, not the impersonation token of the thread.
  963. This routine will create an SE_ADT_PARAMETERS array organized as follows:
  964. Parameter[0] - User Sid
  965. Parameter[1] - Subsystem name (if available)
  966. Parameter[2] - Server name (if available)
  967. Parameter[3] - Object Type Name
  968. Parameter[4] - Object Name
  969. Parameter[5] - New handle ID
  970. Parameter[6] - Subject's process id
  971. Parameter[7] - Subject's primary authentication ID
  972. Parameter[8] - Subject's client authentication ID
  973. Parameter[9] - DesiredAccess mask
  974. Parameter[10] - Privileges used for open
  975. Arguments:
  976. CapturedSubsystemName - Supplies a name string identifying the
  977. subsystem calling the routine.
  978. HandleId - A unique value representing the client's handle to the
  979. object. If the access attempt was not successful (AccessGranted is
  980. FALSE), then this parameter is ignored.
  981. CapturedObjectTypeName - Supplies the name of the type of object being
  982. accessed.
  983. CapturedObjectName - Supplies the name of the object the client
  984. accessed or attempted to access.
  985. CapturedSecurityDescriptor - A pointer to the security descriptor of
  986. the object being accessed.
  987. ClientToken - Optionally provides a pointer to the client token
  988. (only if the caller is currently impersonating)
  989. PrimaryToken - Provides a pointer to the caller's primary token.
  990. DesiredAccess - The desired access mask. This mask must have been
  991. previously mapped to contain no generic accesses.
  992. GrantedAccess - The mask of accesses that were actually granted.
  993. CapturedPrivileges - Optionally points to a set of privileges that were
  994. required for the access attempt. Those privileges that were held
  995. by the subject are marked using the UsedForAccess flag of the
  996. attributes associated with each privilege.
  997. ObjectCreation - A boolean flag indicating whether the access will
  998. result in a new object being created if granted. A value of TRUE
  999. indicates an object will be created, FALSE indicates an existing
  1000. object will be opened.
  1001. AccessGranted - Indicates whether the requested access was granted or
  1002. not. A value of TRUE indicates the access was granted. A value of
  1003. FALSE indicates the access was not granted.
  1004. GenerateOnClose - Points to a boolean that is set by the audit
  1005. generation routine and must be passed to NtCloseObjectAuditAlarm()
  1006. when the object handle is closed.
  1007. GenerateAudit - Indicates if we should generate an audit for this operation.
  1008. GenerateAlarm - Indicates if we should generate an alarm for this operation.
  1009. Return Value:
  1010. Returns TRUE if audit is generated, FALSE otherwise.
  1011. --*/
  1012. {
  1013. SE_ADT_PARAMETER_ARRAY AuditParameters;
  1014. ULONG ObjectTypeIndex;
  1015. PSID CapturedUserSid;
  1016. LUID PrimaryAuthenticationId;
  1017. LUID ClientAuthenticationId;
  1018. PUNICODE_STRING SubsystemName;
  1019. PAGED_CODE();
  1020. if ( ARGUMENT_PRESENT( ClientToken )) {
  1021. CapturedUserSid = SepTokenUserSid( ClientToken );
  1022. } else {
  1023. CapturedUserSid = SepTokenUserSid( PrimaryToken );
  1024. }
  1025. PrimaryAuthenticationId = SepTokenAuthenticationId( PrimaryToken );
  1026. //
  1027. // A completely zero'd entry will be interpreted
  1028. // as a "null string" or not supplied parameter.
  1029. //
  1030. // Initializing the entire array up front will allow
  1031. // us to avoid filling in each not supplied entry.
  1032. //
  1033. RtlZeroMemory (
  1034. (PVOID) &AuditParameters,
  1035. sizeof( AuditParameters )
  1036. );
  1037. ASSERT( SeAdtParmTypeNone == 0 );
  1038. AuditParameters.CategoryId = SE_CATEGID_OBJECT_ACCESS;
  1039. AuditParameters.AuditId = SE_AUDITID_OPEN_OBJECT_FOR_DELETE;
  1040. AuditParameters.ParameterCount = 0;
  1041. if ( AccessGranted ) {
  1042. AuditParameters.Type = EVENTLOG_AUDIT_SUCCESS;
  1043. } else {
  1044. AuditParameters.Type = EVENTLOG_AUDIT_FAILURE;
  1045. }
  1046. if ( !ARGUMENT_PRESENT( CapturedSubsystemName )) {
  1047. SubsystemName = (PUNICODE_STRING)&SeSubsystemName;
  1048. } else {
  1049. SubsystemName = CapturedSubsystemName;
  1050. }
  1051. //
  1052. // Parameter[0] - User Sid
  1053. //
  1054. SepSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, CapturedUserSid );
  1055. AuditParameters.ParameterCount++;
  1056. //
  1057. // Parameter[1] - Subsystem name
  1058. //
  1059. SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, SubsystemName );
  1060. AuditParameters.ParameterCount++;
  1061. //
  1062. // Parameter[2] - Object Server (if available)
  1063. //
  1064. if ( ARGUMENT_PRESENT( CapturedSubsystemName )) {
  1065. SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, CapturedSubsystemName );
  1066. }
  1067. AuditParameters.ParameterCount++;
  1068. //
  1069. // Parameter[3] - Object Type Name
  1070. //
  1071. if ( ARGUMENT_PRESENT( CapturedObjectTypeName )) {
  1072. SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, CapturedObjectTypeName );
  1073. }
  1074. ObjectTypeIndex = AuditParameters.ParameterCount;
  1075. AuditParameters.ParameterCount++;
  1076. //
  1077. // Parameter[4] - Object Name
  1078. //
  1079. if ( ARGUMENT_PRESENT( CapturedObjectName )) {
  1080. SepSetParmTypeFileSpec( AuditParameters, AuditParameters.ParameterCount, CapturedObjectName );
  1081. }
  1082. AuditParameters.ParameterCount++;
  1083. //
  1084. // Parameter[5] - New handle ID
  1085. //
  1086. if ( ARGUMENT_PRESENT( HandleId )) {
  1087. SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, *HandleId );
  1088. }
  1089. AuditParameters.ParameterCount++;
  1090. if ( ARGUMENT_PRESENT( OperationId )) {
  1091. SepSetParmTypeUlong( AuditParameters, AuditParameters.ParameterCount, (*OperationId).HighPart );
  1092. AuditParameters.ParameterCount++;
  1093. SepSetParmTypeUlong( AuditParameters, AuditParameters.ParameterCount, (*OperationId).LowPart );
  1094. AuditParameters.ParameterCount++;
  1095. } else {
  1096. AuditParameters.ParameterCount += 2;
  1097. }
  1098. //
  1099. // Parameter[6] - Subject's process id
  1100. //
  1101. SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, ProcessID );
  1102. AuditParameters.ParameterCount++;
  1103. //
  1104. // Parameter[7] - Subject's primary authentication ID
  1105. //
  1106. SepSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, PrimaryAuthenticationId );
  1107. AuditParameters.ParameterCount++;
  1108. //
  1109. // Parameter[8] - Subject's client authentication ID
  1110. //
  1111. if ( ARGUMENT_PRESENT( ClientToken )) {
  1112. ClientAuthenticationId = SepTokenAuthenticationId( ClientToken );
  1113. SepSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, ClientAuthenticationId );
  1114. } else {
  1115. SepSetParmTypeNoLogon( AuditParameters, AuditParameters.ParameterCount );
  1116. }
  1117. AuditParameters.ParameterCount++;
  1118. //
  1119. // Parameter[9] - DesiredAccess mask
  1120. //
  1121. if ( AccessGranted ) {
  1122. SepSetParmTypeAccessMask( AuditParameters, AuditParameters.ParameterCount, GrantedAccess, ObjectTypeIndex );
  1123. } else {
  1124. SepSetParmTypeAccessMask( AuditParameters, AuditParameters.ParameterCount, DesiredAccess, ObjectTypeIndex );
  1125. }
  1126. AuditParameters.ParameterCount++;
  1127. //
  1128. // Parameter[10] - Privileges used for open
  1129. //
  1130. if ( (CapturedPrivileges != NULL) && (CapturedPrivileges->PrivilegeCount > 0) ) {
  1131. SepSetParmTypePrivileges( AuditParameters, AuditParameters.ParameterCount, CapturedPrivileges );
  1132. }
  1133. AuditParameters.ParameterCount++;
  1134. //
  1135. // Parameter[11] - DesiredAccess mask in hex
  1136. //
  1137. if ( AccessGranted ) {
  1138. SepSetParmTypeHexUlong( AuditParameters, AuditParameters.ParameterCount, GrantedAccess );
  1139. } else {
  1140. SepSetParmTypeHexUlong( AuditParameters, AuditParameters.ParameterCount, DesiredAccess );
  1141. }
  1142. AuditParameters.ParameterCount++;
  1143. SepAdtLogAuditRecord( &AuditParameters );
  1144. return( TRUE );
  1145. }
  1146. VOID
  1147. SepAdtCloseObjectAuditAlarm (
  1148. IN PUNICODE_STRING CapturedSubsystemName,
  1149. IN PVOID HandleId,
  1150. IN PSID UserSid
  1151. )
  1152. /*++
  1153. Routine Description:
  1154. This routine implements NtCloseObjectAuditAlarm after parameters have
  1155. been captured.
  1156. This routine is used to generate audit and alarm messages when a handle
  1157. to a protected subsystem object is deleted. This routine may result in
  1158. several messages being generated and sent to Port objects. This may
  1159. result in a significant latency before returning. Design of routines
  1160. that must call this routine must take this potential latency into
  1161. account. This may have an impact on the approach taken for data
  1162. structure mutex locking, for example.
  1163. This API requires the caller have SeTcbPrivilege privilege. The test
  1164. for this privilege is always against the primary token of the calling
  1165. process, allowing the caller to be impersonating a client during the
  1166. call with no ill effects. It is assumed that this privilege has been
  1167. tested at a higher level.
  1168. This routine will create an SE_ADT_PARAMETERS array organized as follows:
  1169. Parameter[0] - User Sid
  1170. Parameter[1] - Subsystem name (if available)
  1171. Parameter[2] - object server name (same as subsystem name)
  1172. Parameter[3] - New handle ID
  1173. Parameter[4] - Subject's process id
  1174. Parameter[5] - Image file name
  1175. Arguments:
  1176. CapturedSubsystemName - Supplies a name string identifying the
  1177. subsystem calling the routine.
  1178. HandleId - A unique value representing the client's handle to the
  1179. object.
  1180. Object - The address of the object being closed
  1181. UserSid - The Sid identifying the current caller.
  1182. Return value:
  1183. None.
  1184. --*/
  1185. {
  1186. SE_ADT_PARAMETER_ARRAY AuditParameters;
  1187. HANDLE ProcessId;
  1188. PEPROCESS Process = NULL;
  1189. PUNICODE_STRING ImageFileName;
  1190. UNICODE_STRING NullString = {0};
  1191. NTSTATUS Status;
  1192. PUNICODE_STRING SubsystemName;
  1193. PAGED_CODE();
  1194. if ( SepAuditOptions.DoNotAuditCloseObjectEvents ) {
  1195. return;
  1196. }
  1197. if ( SepAdtAuditThisEventWithContext( AuditCategoryObjectAccess, TRUE, FALSE, NULL ) ) {
  1198. Process = PsGetCurrentProcess();
  1199. ProcessId = PsProcessAuditId( Process );
  1200. Status = SeLocateProcessImageName( Process, &ImageFileName );
  1201. if ( !NT_SUCCESS(Status) ) {
  1202. ImageFileName = &NullString;
  1203. }
  1204. //
  1205. // A completely zero'd entry will be interpreted
  1206. // as a "null string" or not supplied parameter.
  1207. //
  1208. // Initializing the entire array up front will allow
  1209. // us to avoid filling in each not supplied entry.
  1210. //
  1211. RtlZeroMemory (
  1212. (PVOID) &AuditParameters,
  1213. sizeof( AuditParameters )
  1214. );
  1215. ASSERT( SeAdtParmTypeNone == 0 );
  1216. AuditParameters.CategoryId = SE_CATEGID_OBJECT_ACCESS;
  1217. AuditParameters.AuditId = SE_AUDITID_CLOSE_HANDLE;
  1218. AuditParameters.ParameterCount = 0;
  1219. AuditParameters.Type = EVENTLOG_AUDIT_SUCCESS;
  1220. if ( !ARGUMENT_PRESENT( CapturedSubsystemName )) {
  1221. SubsystemName = (PUNICODE_STRING)&SeSubsystemName;
  1222. } else {
  1223. SubsystemName = CapturedSubsystemName;
  1224. }
  1225. //
  1226. // Parameter[0] - User Sid
  1227. //
  1228. SepSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, UserSid );
  1229. AuditParameters.ParameterCount++;
  1230. //
  1231. // Parameter[1] - Subsystem name
  1232. //
  1233. SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, SubsystemName );
  1234. AuditParameters.ParameterCount++;
  1235. //
  1236. // Parameter[2] - Object server name (if available)
  1237. //
  1238. if ( ARGUMENT_PRESENT( CapturedSubsystemName )) {
  1239. SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, CapturedSubsystemName );
  1240. }
  1241. AuditParameters.ParameterCount++;
  1242. //
  1243. // Parameter[3] - New handle ID
  1244. //
  1245. SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, HandleId );
  1246. AuditParameters.ParameterCount++;
  1247. //
  1248. // Parameter[4] - Subject's process id
  1249. //
  1250. SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, ProcessId );
  1251. AuditParameters.ParameterCount++;
  1252. //
  1253. // Parameter[5] - Subject's Image Name
  1254. //
  1255. SepSetParmTypeFileSpec( AuditParameters, AuditParameters.ParameterCount, ImageFileName );
  1256. AuditParameters.ParameterCount ++;
  1257. SepAdtLogAuditRecord( &AuditParameters );
  1258. if ( ImageFileName != &NullString ) {
  1259. ExFreePool( ImageFileName );
  1260. }
  1261. }
  1262. }
  1263. VOID
  1264. SepAdtDeleteObjectAuditAlarm (
  1265. IN PUNICODE_STRING CapturedSubsystemName,
  1266. IN PVOID HandleId,
  1267. IN PSID UserSid
  1268. )
  1269. /*++
  1270. Routine Description:
  1271. This routine implements NtDeleteObjectAuditAlarm after parameters have
  1272. been captured.
  1273. This routine is used to generate audit and alarm messages when an object
  1274. in a protected subsystem object is deleted. This routine may result in
  1275. several messages being generated and sent to Port objects. This may
  1276. result in a significant latency before returning. Design of routines
  1277. that must call this routine must take this potential latency into
  1278. account. This may have an impact on the approach taken for data
  1279. structure mutex locking, for example.
  1280. This routine will create an SE_ADT_PARAMETERS array organized as follows:
  1281. Parameter[0] - User Sid
  1282. Parameter[1] - Subsystem name
  1283. Parameter[2] - Object server (same as Subsystem name)
  1284. Parameter[3] - Handle ID
  1285. Parameter[4] - Subject's process id
  1286. Parameter[5] - Subject's process image name
  1287. Arguments:
  1288. CapturedSubsystemName - Supplies a name string identifying the
  1289. subsystem calling the routine.
  1290. HandleId - A unique value representing the client's handle to the
  1291. object.
  1292. Object - The address of the object being closed
  1293. UserSid - The Sid identifying the current caller.
  1294. Return value:
  1295. None.
  1296. --*/
  1297. {
  1298. SE_ADT_PARAMETER_ARRAY AuditParameters;
  1299. HANDLE ProcessId;
  1300. PUNICODE_STRING ImageFileName = NULL;
  1301. UNICODE_STRING NullString = {0};
  1302. PEPROCESS Process = NULL;
  1303. NTSTATUS Status = STATUS_SUCCESS;
  1304. PUNICODE_STRING SubsystemName;
  1305. PAGED_CODE();
  1306. if ( SepAdtAuditThisEventWithContext( AuditCategoryObjectAccess, TRUE, FALSE, NULL ) ) {
  1307. Process = PsGetCurrentProcess();
  1308. Status = SeLocateProcessImageName( Process, &ImageFileName );
  1309. if ( !NT_SUCCESS(Status) ) {
  1310. ImageFileName = &NullString;
  1311. }
  1312. //
  1313. // A completely zero'd entry will be interpreted
  1314. // as a "null string" or not supplied parameter.
  1315. //
  1316. // Initializing the entire array up front will allow
  1317. // us to avoid filling in each not supplied entry.
  1318. //
  1319. RtlZeroMemory (
  1320. (PVOID) &AuditParameters,
  1321. sizeof( AuditParameters )
  1322. );
  1323. ASSERT( SeAdtParmTypeNone == 0 );
  1324. AuditParameters.CategoryId = SE_CATEGID_OBJECT_ACCESS;
  1325. AuditParameters.AuditId = SE_AUDITID_DELETE_OBJECT;
  1326. AuditParameters.ParameterCount = 0;
  1327. AuditParameters.Type = EVENTLOG_AUDIT_SUCCESS;
  1328. if ( !ARGUMENT_PRESENT( CapturedSubsystemName )) {
  1329. SubsystemName = (PUNICODE_STRING)&SeSubsystemName;
  1330. } else {
  1331. SubsystemName = CapturedSubsystemName;
  1332. }
  1333. //
  1334. // Parameter[0] - User Sid
  1335. //
  1336. SepSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, UserSid );
  1337. AuditParameters.ParameterCount++;
  1338. //
  1339. // Parameter[1] - Subsystem name
  1340. //
  1341. SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, SubsystemName );
  1342. AuditParameters.ParameterCount++;
  1343. //
  1344. // Parameter[2] - Subsystem name (if available)
  1345. //
  1346. if ( ARGUMENT_PRESENT( CapturedSubsystemName )) {
  1347. SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, CapturedSubsystemName );
  1348. }
  1349. AuditParameters.ParameterCount++;
  1350. //
  1351. // Parameter[3] - New handle ID
  1352. //
  1353. SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, HandleId );
  1354. AuditParameters.ParameterCount++;
  1355. //
  1356. // Parameter[4] - Subject's process id
  1357. //
  1358. ProcessId = PsProcessAuditId( PsGetCurrentProcess() );
  1359. SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, ProcessId );
  1360. AuditParameters.ParameterCount++;
  1361. //
  1362. // Parameter[5] - Subject's Image Name
  1363. //
  1364. SepSetParmTypeFileSpec( AuditParameters, AuditParameters.ParameterCount, ImageFileName );
  1365. AuditParameters.ParameterCount ++;
  1366. SepAdtLogAuditRecord( &AuditParameters );
  1367. if (ImageFileName != &NullString) {
  1368. ExFreePool(ImageFileName);
  1369. }
  1370. }
  1371. }
  1372. VOID
  1373. SeOperationAuditAlarm (
  1374. IN PUNICODE_STRING CapturedSubsystemName OPTIONAL,
  1375. IN PVOID HandleId,
  1376. IN PUNICODE_STRING ObjectTypeName,
  1377. IN ACCESS_MASK AuditMask,
  1378. IN PSID UserSid OPTIONAL
  1379. )
  1380. /*++
  1381. Routine Description:
  1382. This routine generates an "operation-based" audit.
  1383. This routine may result in several messages being generated and sent
  1384. to Port objects. This may result in a significant latency before
  1385. returning. Design of routines that must call this routine must take
  1386. this potential latency into account. This may have an impact on the
  1387. approach taken for data structure mutex locking, for example.
  1388. This routine will create an SE_ADT_PARAMETERS array organized as follows:
  1389. Parameter[0] - User Sid
  1390. Parameter[1] - Subsystem name (if available)
  1391. Parameter[2] - Object server (same as Subsystem name)
  1392. Parameter[3] - Handle ID
  1393. Parameter[4] - object type name
  1394. Parameter[5] - Subject's process id
  1395. Parameter[6] - Subject's process image name
  1396. Parameter[7] - Audit mask
  1397. Arguments:
  1398. CapturedSubsystemName - Supplies a name string identifying the
  1399. subsystem calling the routine.
  1400. HandleId - A unique value representing the client's handle to the
  1401. object.
  1402. ObjectTypeName - The type of the object being accessed.
  1403. AuditMask - Mask of bits being audited.
  1404. UserSid - Optionally supplies the user sid.
  1405. Return value:
  1406. None.
  1407. --*/
  1408. {
  1409. SE_ADT_PARAMETER_ARRAY AuditParameters;
  1410. BOOLEAN AccessGranted = TRUE;
  1411. HANDLE ProcessId;
  1412. SECURITY_SUBJECT_CONTEXT SubjectSecurityContext;
  1413. ULONG ObjectTypeIndex;
  1414. PUNICODE_STRING SubsystemName;
  1415. NTSTATUS Status;
  1416. UNICODE_STRING NullString = {0};
  1417. PUNICODE_STRING ImageFileName = NULL;
  1418. PEPROCESS Process = NULL;
  1419. PAGED_CODE();
  1420. Process = PsGetCurrentProcess();
  1421. ProcessId = PsProcessAuditId( Process );
  1422. Status = SeLocateProcessImageName( Process, &ImageFileName );
  1423. if ( !NT_SUCCESS(Status) ) {
  1424. ImageFileName = &NullString;
  1425. }
  1426. //
  1427. // A completely zero'd entry will be interpreted
  1428. // as a "null string" or not supplied parameter.
  1429. //
  1430. // Initializing the entire array up front will allow
  1431. // us to avoid filling in each not supplied entry.
  1432. //
  1433. RtlZeroMemory (
  1434. (PVOID) &AuditParameters,
  1435. sizeof( AuditParameters )
  1436. );
  1437. ASSERT( SeAdtParmTypeNone == 0 );
  1438. AuditParameters.CategoryId = SE_CATEGID_OBJECT_ACCESS;
  1439. AuditParameters.AuditId = SE_AUDITID_OBJECT_ACCESS;
  1440. AuditParameters.ParameterCount = 0;
  1441. AuditParameters.Type = EVENTLOG_AUDIT_SUCCESS;
  1442. //
  1443. // If the user's SID was not passed, get it out of the current
  1444. // subject context
  1445. //
  1446. SeCaptureSubjectContext( &SubjectSecurityContext );
  1447. if ( !ARGUMENT_PRESENT( UserSid )) {
  1448. UserSid = SepTokenUserSid( EffectiveToken( &SubjectSecurityContext ));
  1449. }
  1450. if ( !ARGUMENT_PRESENT( CapturedSubsystemName )) {
  1451. SubsystemName = (PUNICODE_STRING)&SeSubsystemName;
  1452. } else {
  1453. SubsystemName = CapturedSubsystemName;
  1454. }
  1455. //
  1456. // Parameter[0] - User Sid
  1457. //
  1458. SepSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, UserSid );
  1459. AuditParameters.ParameterCount++;
  1460. //
  1461. // Parameter[1] - Subsystem name
  1462. //
  1463. SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, SubsystemName );
  1464. AuditParameters.ParameterCount++;
  1465. //
  1466. // Parameter[2] - object server (same as subsystem name)
  1467. //
  1468. SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, SubsystemName );
  1469. AuditParameters.ParameterCount++;
  1470. //
  1471. // Parameter[3] - New handle ID
  1472. //
  1473. SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, HandleId );
  1474. AuditParameters.ParameterCount++;
  1475. //
  1476. // Parameter[4] - Object Type Name
  1477. //
  1478. SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, ObjectTypeName );
  1479. ObjectTypeIndex = AuditParameters.ParameterCount;
  1480. AuditParameters.ParameterCount++;
  1481. //
  1482. // Parameter[5] - Subject's process id
  1483. //
  1484. SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, ProcessId );
  1485. AuditParameters.ParameterCount++;
  1486. //
  1487. // Parameter[6] - Subject's process name
  1488. //
  1489. SepSetParmTypeFileSpec( AuditParameters, AuditParameters.ParameterCount, ImageFileName );
  1490. AuditParameters.ParameterCount++;
  1491. //
  1492. // Parameter[7] - Audit Mask
  1493. //
  1494. SepSetParmTypeAccessMask( AuditParameters, AuditParameters.ParameterCount, AuditMask, ObjectTypeIndex );
  1495. AuditParameters.ParameterCount++;
  1496. //
  1497. // Parameter[8] - Access Mask (hex)
  1498. //
  1499. SepSetParmTypeHexUlong( AuditParameters, AuditParameters.ParameterCount, AuditMask );
  1500. AuditParameters.ParameterCount++;
  1501. SepAdtLogAuditRecord( &AuditParameters );
  1502. if ( ImageFileName != &NullString ) {
  1503. ExFreePool( ImageFileName );
  1504. }
  1505. SeReleaseSubjectContext( &SubjectSecurityContext );
  1506. }
  1507. VOID
  1508. SepAdtObjectReferenceAuditAlarm(
  1509. IN PVOID Object,
  1510. IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext,
  1511. IN ACCESS_MASK DesiredAccess,
  1512. IN BOOLEAN AccessGranted
  1513. )
  1514. /*++
  1515. Routine Description:
  1516. Note: the caller (SeObjectReferenceAuditAlarm) checks audit policy.
  1517. description-of-function.
  1518. This routine will create an SE_ADT_PARAMETERS array organized as follows:
  1519. Parameter[0] - User Sid
  1520. Parameter[1] - Subsystem name (if available)
  1521. Parameter[2] - Object Type Name
  1522. Parameter[3] - Object Name
  1523. Parameter[4] - Subject's process id
  1524. Parameter[5] - Subject's primary authentication ID
  1525. Parameter[6] - Subject's client authentication ID
  1526. Parameter[7] - DesiredAccess mask
  1527. Arguments:
  1528. Return Value:
  1529. return-value - Description of conditions needed to return value. - or -
  1530. None.
  1531. --*/
  1532. {
  1533. SE_ADT_PARAMETER_ARRAY AuditParameters;
  1534. ULONG ObjectTypeIndex;
  1535. POBJECT_NAME_INFORMATION ObjectNameInformation;
  1536. PUNICODE_STRING ObjectTypeInformation;
  1537. PSID UserSid;
  1538. LUID PrimaryAuthenticationId;
  1539. LUID ClientAuthenticationId;
  1540. PTOKEN ClientToken = (PTOKEN)SubjectSecurityContext->ClientToken;
  1541. PTOKEN PrimaryToken = (PTOKEN)SubjectSecurityContext->PrimaryToken;
  1542. PAGED_CODE();
  1543. if ( ARGUMENT_PRESENT( ClientToken )) {
  1544. UserSid = SepTokenUserSid( ClientToken );
  1545. } else {
  1546. UserSid = SepTokenUserSid( PrimaryToken );
  1547. }
  1548. PrimaryAuthenticationId = SepTokenAuthenticationId( PrimaryToken );
  1549. //
  1550. // A completely zero'd entry will be interpreted
  1551. // as a "null string" or not supplied parameter.
  1552. //
  1553. // Initializing the entire array up front will allow
  1554. // us to avoid filling in each not supplied entry.
  1555. //
  1556. RtlZeroMemory (
  1557. (PVOID) &AuditParameters,
  1558. sizeof( AuditParameters )
  1559. );
  1560. ASSERT( SeAdtParmTypeNone == 0 );
  1561. AuditParameters.CategoryId = SE_CATEGID_DETAILED_TRACKING;
  1562. AuditParameters.AuditId = SE_AUDITID_INDIRECT_REFERENCE;
  1563. AuditParameters.ParameterCount = 9;
  1564. if ( AccessGranted ) {
  1565. AuditParameters.Type = EVENTLOG_AUDIT_SUCCESS;
  1566. } else {
  1567. AuditParameters.Type = EVENTLOG_AUDIT_FAILURE;
  1568. }
  1569. //
  1570. // Obtain the object name and object type name from the object.
  1571. //
  1572. ObjectNameInformation = SepQueryNameString( Object );
  1573. ObjectTypeInformation = SepQueryTypeString( Object );
  1574. //
  1575. // Parameter[0] - User Sid
  1576. //
  1577. SepSetParmTypeSid( AuditParameters, 0, UserSid );
  1578. //
  1579. // Parameter[1] - Subsystem name
  1580. //
  1581. SepSetParmTypeString( AuditParameters, 1, (PUNICODE_STRING)&SeSubsystemName );
  1582. //
  1583. // Parameter[2] - Object Type Name
  1584. //
  1585. if ( ObjectTypeInformation != NULL ) {
  1586. SepSetParmTypeString( AuditParameters, 2, ObjectTypeInformation );
  1587. }
  1588. ObjectTypeIndex = 2;
  1589. //
  1590. // Parameter[3] - Object Name
  1591. //
  1592. if ( ObjectNameInformation != NULL ) {
  1593. SepSetParmTypeString( AuditParameters, 3, &ObjectNameInformation->Name );
  1594. }
  1595. //
  1596. // Parameter[4] - Subject's process id
  1597. //
  1598. SepSetParmTypePtr( AuditParameters, 4, SubjectSecurityContext->ProcessAuditId );
  1599. //
  1600. // Parameter[5] - Subject's primary authentication ID
  1601. //
  1602. SepSetParmTypeLogonId( AuditParameters, 5, PrimaryAuthenticationId );
  1603. //
  1604. // Parameter[6] - Subject's client authentication ID
  1605. //
  1606. if ( ARGUMENT_PRESENT( ClientToken )) {
  1607. ClientAuthenticationId = SepTokenAuthenticationId( ClientToken );
  1608. SepSetParmTypeLogonId( AuditParameters, 6, ClientAuthenticationId );
  1609. } else {
  1610. SepSetParmTypeNoLogon( AuditParameters, 6 );
  1611. }
  1612. //
  1613. // Parameter[7] - DesiredAccess mask
  1614. //
  1615. SepSetParmTypeAccessMask( AuditParameters, 7, DesiredAccess, ObjectTypeIndex );
  1616. //
  1617. // Parameter[8] - DesiredAccess mask
  1618. //
  1619. SepSetParmTypeHexUlong( AuditParameters, 8, DesiredAccess );
  1620. SepAdtLogAuditRecord( &AuditParameters );
  1621. if ( ObjectNameInformation != NULL ) {
  1622. ExFreePool( ObjectNameInformation );
  1623. }
  1624. if ( ObjectTypeInformation != NULL ) {
  1625. ExFreePool( ObjectTypeInformation );
  1626. }
  1627. }
  1628. POBJECT_NAME_INFORMATION
  1629. SepQueryNameString(
  1630. IN PVOID Object
  1631. )
  1632. /*++
  1633. Routine Description:
  1634. Takes a pointer to an object and returns the name of the object.
  1635. Arguments:
  1636. Object - a pointer to an object.
  1637. Return Value:
  1638. A pointer to a buffer containing a POBJECT_NAME_INFORMATION
  1639. structure containing the name of the object. The string is
  1640. allocated out of paged pool and should be freed by the caller.
  1641. NULL may also be returned.
  1642. --*/
  1643. {
  1644. NTSTATUS Status;
  1645. ULONG ReturnLength = 0;
  1646. POBJECT_NAME_INFORMATION ObjectNameInfo = NULL;
  1647. PUNICODE_STRING ObjectName = NULL;
  1648. PAGED_CODE();
  1649. Status = ObQueryNameString(
  1650. Object,
  1651. ObjectNameInfo,
  1652. 0,
  1653. &ReturnLength
  1654. );
  1655. if ( Status == STATUS_INFO_LENGTH_MISMATCH ) {
  1656. ObjectNameInfo = ExAllocatePoolWithTag( PagedPool, ReturnLength, 'nOeS' );
  1657. if ( ObjectNameInfo != NULL ) {
  1658. Status = ObQueryNameString(
  1659. Object,
  1660. ObjectNameInfo,
  1661. ReturnLength,
  1662. &ReturnLength
  1663. );
  1664. if ( NT_SUCCESS( Status ) && (ObjectNameInfo->Name.Length != 0) ) {
  1665. return( ObjectNameInfo );
  1666. } else {
  1667. ExFreePool( ObjectNameInfo );
  1668. return( NULL );
  1669. }
  1670. }
  1671. }
  1672. return( NULL );
  1673. }
  1674. PUNICODE_STRING
  1675. SepQueryTypeString(
  1676. IN PVOID Object
  1677. )
  1678. /*++
  1679. Routine Description:
  1680. Takes a pointer to an object and returns the type of the object.
  1681. Arguments:
  1682. Object - a pointer to an object.
  1683. Return Value:
  1684. A pointer to a UNICODE_STRING that contains the name of the object
  1685. type. The string is allocated out of paged pool and should be freed
  1686. by the caller.
  1687. NULL may also be returned.
  1688. --*/
  1689. {
  1690. NTSTATUS Status;
  1691. PUNICODE_STRING TypeName = NULL;
  1692. ULONG ReturnLength;
  1693. PAGED_CODE();
  1694. Status = ObQueryTypeName(
  1695. Object,
  1696. TypeName,
  1697. 0,
  1698. &ReturnLength
  1699. );
  1700. if ( Status == STATUS_INFO_LENGTH_MISMATCH ) {
  1701. TypeName = ExAllocatePoolWithTag( PagedPool, ReturnLength, 'nTeS' );
  1702. if ( TypeName != NULL ) {
  1703. Status = ObQueryTypeName(
  1704. Object,
  1705. TypeName,
  1706. ReturnLength,
  1707. &ReturnLength
  1708. );
  1709. if ( NT_SUCCESS( Status )) {
  1710. return( TypeName );
  1711. } else {
  1712. ExFreePool( TypeName );
  1713. }
  1714. }
  1715. }
  1716. return( NULL );
  1717. }
  1718. VOID
  1719. SeAuditProcessCreation(
  1720. PEPROCESS Process
  1721. )
  1722. /*++
  1723. Routine Description:
  1724. Audits the creation of a process. It is the caller's responsibility
  1725. to determine if process auditing is in progress.
  1726. Arguments:
  1727. Process - Points to the new process object.
  1728. Return Value:
  1729. None.
  1730. --*/
  1731. {
  1732. ANSI_STRING Ansi;
  1733. LUID UserAuthenticationId;
  1734. NTSTATUS Status;
  1735. PSID UserSid;
  1736. SECURITY_SUBJECT_CONTEXT SubjectSecurityContext;
  1737. SE_ADT_PARAMETER_ARRAY AuditParameters;
  1738. HANDLE ProcessId;
  1739. HANDLE ParentProcessId;
  1740. PUNICODE_STRING ImageFileName;
  1741. UNICODE_STRING NullString = {0};
  1742. PAGED_CODE();
  1743. //
  1744. // Set up the various data that will be needed for the audit:
  1745. // - process id
  1746. // - parent's process id
  1747. // - image file name (unicode)
  1748. //
  1749. ProcessId = Process->UniqueProcessId;
  1750. ParentProcessId = Process->InheritedFromUniqueProcessId;
  1751. Status = SeLocateProcessImageName( Process, &ImageFileName );
  1752. if ( !NT_SUCCESS(Status) ) {
  1753. ImageFileName = &NullString;
  1754. }
  1755. //
  1756. // NtCreateProcess with no section will cause this to be NULL
  1757. // fork() for posix will do this, or someone calling NtCreateProcess
  1758. // directly.
  1759. //
  1760. SeCaptureSubjectContext( &SubjectSecurityContext );
  1761. RtlZeroMemory (
  1762. (PVOID) &AuditParameters,
  1763. sizeof( AuditParameters )
  1764. );
  1765. ASSERT( SeAdtParmTypeNone == 0 );
  1766. AuditParameters.CategoryId = SE_CATEGID_DETAILED_TRACKING;
  1767. AuditParameters.AuditId = SE_AUDITID_PROCESS_CREATED;
  1768. AuditParameters.ParameterCount = 0;
  1769. AuditParameters.Type = EVENTLOG_AUDIT_SUCCESS;
  1770. //
  1771. // Use the primary token here, because that's what's going to show up
  1772. // when the created process exits.
  1773. //
  1774. UserSid = SepTokenUserSid( SubjectSecurityContext.PrimaryToken );
  1775. UserAuthenticationId = SepTokenAuthenticationId( SubjectSecurityContext.PrimaryToken );
  1776. //
  1777. // Fill in the AuditParameters structure.
  1778. //
  1779. SepSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, UserSid );
  1780. AuditParameters.ParameterCount++;
  1781. SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, (PUNICODE_STRING)&SeSubsystemName );
  1782. AuditParameters.ParameterCount++;
  1783. SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, ProcessId );
  1784. AuditParameters.ParameterCount++;
  1785. SepSetParmTypeFileSpec( AuditParameters, AuditParameters.ParameterCount, ImageFileName );
  1786. AuditParameters.ParameterCount++;
  1787. SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, ParentProcessId );
  1788. AuditParameters.ParameterCount++;
  1789. SepSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, UserAuthenticationId );
  1790. AuditParameters.ParameterCount++;
  1791. SepAdtLogAuditRecord( &AuditParameters );
  1792. SeReleaseSubjectContext( &SubjectSecurityContext );
  1793. if ( ImageFileName != &NullString ) {
  1794. ExFreePool( ImageFileName );
  1795. }
  1796. return;
  1797. }
  1798. VOID
  1799. SeAuditHandleDuplication(
  1800. PVOID SourceHandle,
  1801. PVOID NewHandle,
  1802. PEPROCESS SourceProcess,
  1803. PEPROCESS TargetProcess
  1804. )
  1805. /*++
  1806. Routine Description:
  1807. This routine generates a handle duplication audit. It is up to the caller
  1808. to determine if this routine should be called or not.
  1809. Arguments:
  1810. SourceHandle - Original handle
  1811. NewHandle - New handle
  1812. SourceProcess - Process containing SourceHandle
  1813. TargetProcess - Process containing NewHandle
  1814. Return Value:
  1815. None.
  1816. --*/
  1817. {
  1818. SE_ADT_PARAMETER_ARRAY AuditParameters;
  1819. SECURITY_SUBJECT_CONTEXT SubjectSecurityContext;
  1820. PSID UserSid;
  1821. PAGED_CODE();
  1822. SeCaptureSubjectContext( &SubjectSecurityContext );
  1823. UserSid = SepTokenUserSid( EffectiveToken( &SubjectSecurityContext ));
  1824. RtlZeroMemory (
  1825. (PVOID) &AuditParameters,
  1826. sizeof( AuditParameters )
  1827. );
  1828. ASSERT( SeAdtParmTypeNone == 0 );
  1829. AuditParameters.CategoryId = SE_CATEGID_DETAILED_TRACKING;
  1830. AuditParameters.AuditId = SE_AUDITID_DUPLICATE_HANDLE;
  1831. AuditParameters.ParameterCount = 0;
  1832. AuditParameters.Type = EVENTLOG_AUDIT_SUCCESS;
  1833. SepSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, UserSid );
  1834. AuditParameters.ParameterCount++;
  1835. SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, (PUNICODE_STRING)&SeSubsystemName );
  1836. AuditParameters.ParameterCount++;
  1837. SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, SourceHandle );
  1838. AuditParameters.ParameterCount++;
  1839. SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, PsProcessAuditId( SourceProcess ));
  1840. AuditParameters.ParameterCount++;
  1841. SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, NewHandle );
  1842. AuditParameters.ParameterCount++;
  1843. SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, PsProcessAuditId( TargetProcess ));
  1844. AuditParameters.ParameterCount++;
  1845. SepAdtLogAuditRecord( &AuditParameters );
  1846. SeReleaseSubjectContext( &SubjectSecurityContext );
  1847. }
  1848. VOID
  1849. SeAuditProcessExit(
  1850. PEPROCESS Process
  1851. )
  1852. /*++
  1853. Routine Description:
  1854. Audits the exit of a process. The caller is responsible for
  1855. determining if this should be called.
  1856. Arguments:
  1857. Process - Pointer to the process object that is exiting.
  1858. Return Value:
  1859. None.
  1860. --*/
  1861. {
  1862. PTOKEN Token;
  1863. SE_ADT_PARAMETER_ARRAY AuditParameters;
  1864. PSID UserSid;
  1865. LUID LogonId;
  1866. HANDLE ProcessId;
  1867. PUNICODE_STRING ImageFileName;
  1868. UNICODE_STRING NullString = {0};
  1869. NTSTATUS Status;
  1870. PAGED_CODE();
  1871. Token = (PTOKEN) PsReferencePrimaryToken (Process);
  1872. UserSid = SepTokenUserSid( Token );
  1873. LogonId = SepTokenAuthenticationId( Token );
  1874. RtlZeroMemory (
  1875. (PVOID) &AuditParameters,
  1876. sizeof( AuditParameters )
  1877. );
  1878. ASSERT( SeAdtParmTypeNone == 0 );
  1879. Status = SeLocateProcessImageName( Process, &ImageFileName );
  1880. if ( !NT_SUCCESS(Status) ) {
  1881. ImageFileName = &NullString;
  1882. }
  1883. AuditParameters.CategoryId = SE_CATEGID_DETAILED_TRACKING;
  1884. AuditParameters.AuditId = SE_AUDITID_PROCESS_EXIT;
  1885. AuditParameters.ParameterCount = 0;
  1886. AuditParameters.Type = EVENTLOG_AUDIT_SUCCESS;
  1887. SepSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, UserSid );
  1888. AuditParameters.ParameterCount++;
  1889. SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, (PUNICODE_STRING)&SeSubsystemName );
  1890. AuditParameters.ParameterCount++;
  1891. ProcessId = PsProcessAuditId( Process );
  1892. SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, ProcessId );
  1893. AuditParameters.ParameterCount++;
  1894. SepSetParmTypeFileSpec( AuditParameters, AuditParameters.ParameterCount, ImageFileName );
  1895. AuditParameters.ParameterCount++;
  1896. SepSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, LogonId );
  1897. AuditParameters.ParameterCount++;
  1898. SepAdtLogAuditRecord( &AuditParameters );
  1899. PsDereferencePrimaryToken( Token );
  1900. if ( ImageFileName != &NullString ) {
  1901. ExFreePool( ImageFileName );
  1902. }
  1903. }
  1904. VOID
  1905. SepAdtGenerateDiscardAudit(
  1906. VOID
  1907. )
  1908. /*++
  1909. Routine Description:
  1910. Generates an 'audits discarded' audit.
  1911. Arguments:
  1912. none
  1913. Return Value:
  1914. None.
  1915. --*/
  1916. {
  1917. SE_ADT_PARAMETER_ARRAY AuditParameters;
  1918. PSID UserSid;
  1919. PAGED_CODE();
  1920. UserSid = SeLocalSystemSid;
  1921. RtlZeroMemory (
  1922. (PVOID) &AuditParameters,
  1923. sizeof( AuditParameters )
  1924. );
  1925. ASSERT( SeAdtParmTypeNone == 0 );
  1926. AuditParameters.CategoryId = SE_CATEGID_SYSTEM;
  1927. AuditParameters.AuditId = SE_AUDITID_AUDITS_DISCARDED;
  1928. AuditParameters.ParameterCount = 0;
  1929. AuditParameters.Type = EVENTLOG_AUDIT_SUCCESS;
  1930. SepSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, UserSid );
  1931. AuditParameters.ParameterCount++;
  1932. SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, (PUNICODE_STRING)&SeSubsystemName );
  1933. AuditParameters.ParameterCount++;
  1934. SepSetParmTypeUlong( AuditParameters, AuditParameters.ParameterCount, SepAdtCountEventsDiscarded );
  1935. AuditParameters.ParameterCount++;
  1936. SepAdtLogAuditRecord( &AuditParameters );
  1937. }
  1938. NTSTATUS
  1939. SeInitializeProcessAuditName (
  1940. IN PVOID FileObject,
  1941. IN BOOLEAN bIgnoreAuditPolicy,
  1942. OUT POBJECT_NAME_INFORMATION *pAuditName
  1943. )
  1944. /*++
  1945. Routine Description:
  1946. This routine initializes the executable name for auditing purposes. It allocates memory for the
  1947. image file name. This memory is pointed to by pAuditName.
  1948. Arguments:
  1949. FileObject - Supplies a pointer to a file object for the image being
  1950. executed.
  1951. bIgnoreAuditPolicy - boolean that indicates that the call should proceed without
  1952. regard to the system's auditing policy.
  1953. pAuditName - Supplies a pointer to a pointer for the object name information.
  1954. Return value:
  1955. NTSTATUS.
  1956. ISSUE-2002/03/11-kumarp : need to document the case when return code
  1957. is STATUS_SUCCESS
  1958. Environment:
  1959. KeAttached to the target process so not all system services are available.
  1960. --*/
  1961. {
  1962. NTSTATUS Status;
  1963. OBJECT_NAME_INFORMATION TempNameInfo;
  1964. ULONG ObjectNameInformationLength;
  1965. POBJECT_NAME_INFORMATION pInternalAuditName;
  1966. PFILE_OBJECT FilePointer;
  1967. PAGED_CODE();
  1968. ASSERT (pAuditName != NULL);
  1969. *pAuditName = NULL;
  1970. //
  1971. // Check if the caller would like to get the process name, even if auditing does not
  1972. // require it.
  1973. //
  1974. if (FALSE == bIgnoreAuditPolicy) {
  1975. //
  1976. // At the time of process creation, this routine should only proceed when Object Access or
  1977. // Detailed Tracking auditing is enabled. In all other cases, the process name is acquired
  1978. // when it is requested.
  1979. //
  1980. //
  1981. // Longhorn-ISSUE-2002/03/11-kumarp : why capture subj context twice?
  1982. // bug# 572609
  1983. //
  1984. if (!SepAdtAuditThisEventWithContext( AuditCategoryObjectAccess, TRUE, FALSE, NULL ) &&
  1985. !SepAdtAuditThisEventWithContext( AuditCategoryDetailedTracking, TRUE, FALSE, NULL )) {
  1986. return STATUS_SUCCESS;
  1987. }
  1988. }
  1989. FilePointer = (PFILE_OBJECT) FileObject;
  1990. //
  1991. // Compute full path for imagefile.
  1992. // This first call to ObQueryNameString is guaranteed to fail.
  1993. // The ObjectNameInformationLength contains only a
  1994. // UNICODE_STRING, so if this call succeeded it would indicate
  1995. // an imagefile name of length 0. That is bad, so all return
  1996. // values except STATUS_BUFFER_OVERFLOW (from NTFS) and
  1997. // STATUS_BUFFER_TOO_SMALL (from DFS). This call gives
  1998. // me the buffer size that I need to store the image name.
  1999. //
  2000. pInternalAuditName = &TempNameInfo;
  2001. ObjectNameInformationLength = sizeof(OBJECT_NAME_INFORMATION);
  2002. Status = ObQueryNameString (FilePointer,
  2003. pInternalAuditName,
  2004. ObjectNameInformationLength,
  2005. &ObjectNameInformationLength);
  2006. if ((Status == STATUS_BUFFER_OVERFLOW) ||
  2007. (Status == STATUS_BUFFER_TOO_SMALL)) {
  2008. //
  2009. // Sanity check ObQueryNameString. Different filesystems
  2010. // may be buggy, so make sure that the return length makes
  2011. // sense (that it has room for a non-NULL Buffer in the
  2012. // UNICODE_STRING).
  2013. //
  2014. if (ObjectNameInformationLength > sizeof(OBJECT_NAME_INFORMATION)) {
  2015. pInternalAuditName = ExAllocatePoolWithTag (NonPagedPool,
  2016. ObjectNameInformationLength,
  2017. 'aPeS');
  2018. if (pInternalAuditName != NULL) {
  2019. Status = ObQueryNameString (FilePointer,
  2020. pInternalAuditName,
  2021. ObjectNameInformationLength,
  2022. &ObjectNameInformationLength);
  2023. if (!NT_SUCCESS(Status)) {
  2024. #if DBG
  2025. DbgPrint("\n** ObqueryNameString failed with 0x%x.\n", Status);
  2026. #endif //DBG
  2027. //
  2028. // If the second call to ObQueryNameString did not succeed, then
  2029. // something is very wrong. Set the image name to NULL string.
  2030. //
  2031. // Free the memory that the first call to ObQueryNameString requested,
  2032. // and allocate enough space to store an empty UNICODE_STRING.
  2033. //
  2034. ExFreePool (pInternalAuditName);
  2035. ObjectNameInformationLength = sizeof(OBJECT_NAME_INFORMATION);
  2036. pInternalAuditName = ExAllocatePoolWithTag (NonPagedPool,
  2037. ObjectNameInformationLength,
  2038. 'aPeS');
  2039. if (pInternalAuditName != NULL) {
  2040. RtlZeroMemory(pInternalAuditName, ObjectNameInformationLength);
  2041. //
  2042. // Status = STATUS_SUCCESS to allow the process creation to continue.
  2043. //
  2044. Status = STATUS_SUCCESS;
  2045. } else {
  2046. Status = STATUS_NO_MEMORY;
  2047. }
  2048. }
  2049. } else {
  2050. Status = STATUS_NO_MEMORY;
  2051. }
  2052. } else {
  2053. //
  2054. // If this happens, then ObQueryNameString is broken for the FS on which
  2055. // it was called.
  2056. //
  2057. #if DBG
  2058. DbgPrint("\n** ObqueryNameString failed with 0x%x.\n", Status);
  2059. #endif //DBG
  2060. ObjectNameInformationLength = sizeof(OBJECT_NAME_INFORMATION);
  2061. pInternalAuditName = ExAllocatePoolWithTag (NonPagedPool,
  2062. ObjectNameInformationLength,
  2063. 'aPeS');
  2064. if (pInternalAuditName != NULL) {
  2065. RtlZeroMemory(pInternalAuditName, ObjectNameInformationLength);
  2066. //
  2067. // Status = STATUS_SUCCESS to allow the process creation to continue.
  2068. //
  2069. Status = STATUS_SUCCESS;
  2070. } else {
  2071. Status = STATUS_NO_MEMORY;
  2072. }
  2073. }
  2074. } else {
  2075. //
  2076. // If ObQueryNameString returns some other error code, we cannot
  2077. // be certain of which action to take, or whether it has properly
  2078. // set the ReturnLength. For example, ObQueryNameString has slightly
  2079. // different semantics under DFS than NTFS. Additionally, 3rd
  2080. // party file systems may also behave unpredictably. For these reasons,
  2081. // in the case of an unexpected error code from ObQueryNameString
  2082. // we set AuditName to zero length unicode string and allow process
  2083. // creation to continue.
  2084. //
  2085. #if DBG
  2086. DbgPrint("\n** ObqueryNameString failed with 0x%x.\n", Status);
  2087. #endif //DBG
  2088. ObjectNameInformationLength = sizeof(OBJECT_NAME_INFORMATION);
  2089. pInternalAuditName = ExAllocatePoolWithTag(NonPagedPool, ObjectNameInformationLength, 'aPeS');
  2090. if (pInternalAuditName != NULL) {
  2091. RtlZeroMemory(pInternalAuditName, ObjectNameInformationLength);
  2092. //
  2093. // Status = STATUS_SUCCESS to allow the process creation to continue.
  2094. //
  2095. Status = STATUS_SUCCESS;
  2096. } else {
  2097. Status = STATUS_NO_MEMORY;
  2098. }
  2099. }
  2100. *pAuditName = pInternalAuditName;
  2101. return Status;
  2102. }
  2103. NTSTATUS
  2104. SeLocateProcessImageName(
  2105. IN PEPROCESS Process,
  2106. OUT PUNICODE_STRING *pImageFileName
  2107. )
  2108. /*++
  2109. Routine Description
  2110. This routine returns the ImageFileName information from the process, if available. This is a "lazy evaluation" wrapper
  2111. around SeInitializeProcessAuditName. If the image file name information has already been computed, then this call simply
  2112. allocates and returns a UNICODE_STRING with this information. Otherwise, the function determines the name, stores the name in the
  2113. EPROCESS structure, and then allocates and returns a UNICODE_STRING. Caller must free the memory returned in pImageFileName.
  2114. Arguments
  2115. Process - process for which to acquire the name
  2116. pImageFileName - output parameter to return name to caller
  2117. Return Value
  2118. NTSTATUS.
  2119. --*/
  2120. {
  2121. NTSTATUS Status = STATUS_SUCCESS;
  2122. PVOID FilePointer = NULL;
  2123. PVOID PreviousValue = NULL;
  2124. POBJECT_NAME_INFORMATION pProcessImageName = NULL;
  2125. PUNICODE_STRING pTempUS = NULL;
  2126. ULONG NameLength = 0;
  2127. PAGED_CODE();
  2128. *pImageFileName = NULL;
  2129. if (NULL == Process->SeAuditProcessCreationInfo.ImageFileName) {
  2130. //
  2131. // The name has not been predetermined. We must determine the process name. First, reference the
  2132. // PFILE_OBJECT and lookup the name. Then again check the process image name pointer against NULL.
  2133. // Finally, set the name.
  2134. //
  2135. Status = PsReferenceProcessFilePointer( Process, &FilePointer );
  2136. if (NT_SUCCESS(Status)) {
  2137. //
  2138. // Get the process name information.
  2139. //
  2140. Status = SeInitializeProcessAuditName(
  2141. FilePointer,
  2142. TRUE, // skip audit policy
  2143. &pProcessImageName // to be allocated in nonpaged pool
  2144. );
  2145. if (NT_SUCCESS(Status)) {
  2146. //
  2147. // Only use the pProcessImageName if the field in the process is currently NULL.
  2148. //
  2149. PreviousValue = InterlockedCompareExchangePointer(
  2150. (PVOID *) &Process->SeAuditProcessCreationInfo.ImageFileName,
  2151. (PVOID) pProcessImageName,
  2152. (PVOID) NULL
  2153. );
  2154. if (NULL != PreviousValue) {
  2155. ExFreePool(pProcessImageName); // free what we caused to be allocated.
  2156. }
  2157. }
  2158. ObDereferenceObject( FilePointer );
  2159. }
  2160. }
  2161. if (NT_SUCCESS(Status)) {
  2162. //
  2163. // Allocate space for a buffer to contain the name for returning to the caller.
  2164. //
  2165. NameLength = sizeof(UNICODE_STRING) + Process->SeAuditProcessCreationInfo.ImageFileName->Name.MaximumLength;
  2166. pTempUS = ExAllocatePoolWithTag( NonPagedPool, NameLength, 'aPeS' );
  2167. if (NULL != pTempUS) {
  2168. RtlCopyMemory(
  2169. pTempUS,
  2170. &Process->SeAuditProcessCreationInfo.ImageFileName->Name,
  2171. NameLength
  2172. );
  2173. pTempUS->Buffer = (PWSTR)(((PUCHAR) pTempUS) + sizeof(UNICODE_STRING));
  2174. *pImageFileName = pTempUS;
  2175. } else {
  2176. Status = STATUS_NO_MEMORY;
  2177. }
  2178. }
  2179. return Status;
  2180. }
  2181. VOID
  2182. SepAuditAssignPrimaryToken(
  2183. IN PEPROCESS Process,
  2184. IN PACCESS_TOKEN AccessToken
  2185. )
  2186. /*++
  2187. Routine Description:
  2188. This routine generates an assign primary token audit. It is up to the caller
  2189. to determine if this routine should be called or not.
  2190. Arguments:
  2191. Process - process which gets the new token
  2192. AccessToken - new primary token for the process
  2193. Return Value:
  2194. None.
  2195. --*/
  2196. {
  2197. SE_ADT_PARAMETER_ARRAY AuditParameters;
  2198. NTSTATUS Status;
  2199. PSID UserSid;
  2200. PTOKEN Token;
  2201. HANDLE ProcessId;
  2202. SECURITY_SUBJECT_CONTEXT SubjectSecurityContext;
  2203. PTOKEN CurrentToken;
  2204. PEPROCESS CurrentProcess;
  2205. HANDLE CurrentProcessId;
  2206. PUNICODE_STRING CurrentImageFileName;
  2207. PUNICODE_STRING ImageFileName;
  2208. UNICODE_STRING NullString = {0};
  2209. PAGED_CODE();
  2210. RtlZeroMemory (
  2211. (PVOID) &AuditParameters,
  2212. sizeof( AuditParameters )
  2213. );
  2214. //
  2215. // Get information about the current process, that is, the process
  2216. // that is assigning a new primary token.
  2217. //
  2218. CurrentProcess = PsGetCurrentProcess();
  2219. CurrentProcessId = PsProcessAuditId( CurrentProcess );
  2220. SeCaptureSubjectContext( &SubjectSecurityContext );
  2221. CurrentToken = EffectiveToken( &SubjectSecurityContext );
  2222. UserSid = SepTokenUserSid( CurrentToken );
  2223. Status = SeLocateProcessImageName( CurrentProcess, &CurrentImageFileName );
  2224. if (!NT_SUCCESS(Status)) {
  2225. CurrentImageFileName = &NullString;
  2226. }
  2227. //
  2228. // Retrieve information about the process receiving the new token.
  2229. //
  2230. Token = (PTOKEN) AccessToken;
  2231. ProcessId = PsProcessAuditId( Process );
  2232. Status = SeLocateProcessImageName( Process, &ImageFileName );
  2233. if ( !NT_SUCCESS(Status) ) {
  2234. ImageFileName = &NullString;
  2235. }
  2236. ASSERT( SeAdtParmTypeNone == 0 );
  2237. AuditParameters.CategoryId = SE_CATEGID_DETAILED_TRACKING;
  2238. AuditParameters.AuditId = SE_AUDITID_ASSIGN_TOKEN;
  2239. AuditParameters.ParameterCount = 0;
  2240. AuditParameters.Type = EVENTLOG_AUDIT_SUCCESS;
  2241. SepSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, UserSid );
  2242. AuditParameters.ParameterCount++;
  2243. SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, (PUNICODE_STRING)&SeSubsystemName );
  2244. AuditParameters.ParameterCount++;
  2245. //
  2246. // Information regarding the assigning process
  2247. //
  2248. SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, CurrentProcessId );
  2249. AuditParameters.ParameterCount++;
  2250. SepSetParmTypeFileSpec( AuditParameters, AuditParameters.ParameterCount, CurrentImageFileName );
  2251. AuditParameters.ParameterCount++;
  2252. SepSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, SepTokenAuthenticationId( CurrentToken ) );
  2253. AuditParameters.ParameterCount++;
  2254. //
  2255. // Information about the process receiving the new primary token.
  2256. //
  2257. SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, ProcessId );
  2258. AuditParameters.ParameterCount++;
  2259. SepSetParmTypeFileSpec( AuditParameters, AuditParameters.ParameterCount, ImageFileName );
  2260. AuditParameters.ParameterCount++;
  2261. SepSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, SepTokenAuthenticationId( Token ) );
  2262. AuditParameters.ParameterCount++;
  2263. SepAdtLogAuditRecord( &AuditParameters );
  2264. if ( ImageFileName != &NullString ) {
  2265. ExFreePool( ImageFileName );
  2266. }
  2267. if ( CurrentImageFileName != &NullString ) {
  2268. ExFreePool( CurrentImageFileName );
  2269. }
  2270. SeReleaseSubjectContext( &SubjectSecurityContext );
  2271. }
  2272. VOID
  2273. SeAuditLPCInvalidUse(
  2274. IN PUNICODE_STRING LpcCallName,
  2275. IN PUNICODE_STRING LpcServerPort
  2276. )
  2277. /*++
  2278. Routine Description:
  2279. Audits the invalid use of an LPC port.
  2280. Arguments:
  2281. LpcCallName - type of call: impersonation or reply
  2282. LpcServerPort - name of port
  2283. Return Value:
  2284. None.
  2285. --*/
  2286. {
  2287. LUID UserAuthenticationId;
  2288. PSID UserSid;
  2289. LUID ThreadAuthenticationId;
  2290. SECURITY_SUBJECT_CONTEXT SubjectSecurityContext;
  2291. SE_ADT_PARAMETER_ARRAY AuditParameters;
  2292. PEPROCESS Process;
  2293. HANDLE ProcessID;
  2294. PUNICODE_STRING ImageFileName;
  2295. UNICODE_STRING NullString = {0};
  2296. NTSTATUS Status;
  2297. PAGED_CODE();
  2298. if ( SepAdtAuditThisEventWithContext( AuditCategorySystem, TRUE, FALSE, NULL )) {
  2299. RtlZeroMemory (
  2300. (PVOID) &AuditParameters,
  2301. sizeof( AuditParameters )
  2302. );
  2303. Process = PsGetCurrentProcess();
  2304. ProcessID = PsProcessAuditId( Process );
  2305. Status = SeLocateProcessImageName( Process, &ImageFileName );
  2306. if ( !NT_SUCCESS(Status) ) {
  2307. ImageFileName = &NullString;
  2308. }
  2309. ASSERT( SeAdtParmTypeNone == 0 );
  2310. AuditParameters.CategoryId = SE_CATEGID_SYSTEM;
  2311. AuditParameters.AuditId = SE_AUDITID_LPC_INVALID_USE;
  2312. AuditParameters.ParameterCount = 0;
  2313. AuditParameters.Type = EVENTLOG_AUDIT_SUCCESS;
  2314. SeCaptureSubjectContext( &SubjectSecurityContext );
  2315. UserSid = SepTokenUserSid( SubjectSecurityContext.PrimaryToken );
  2316. UserAuthenticationId = SepTokenAuthenticationId( SubjectSecurityContext.PrimaryToken );
  2317. //
  2318. // Fill in the AuditParameters structure.
  2319. //
  2320. SepSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, UserSid );
  2321. AuditParameters.ParameterCount++;
  2322. SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, (PUNICODE_STRING)&SeSubsystemName );
  2323. AuditParameters.ParameterCount++;
  2324. SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, ProcessID );
  2325. AuditParameters.ParameterCount++;
  2326. SepSetParmTypeFileSpec( AuditParameters, AuditParameters.ParameterCount, ImageFileName );
  2327. AuditParameters.ParameterCount++;
  2328. SepSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, UserAuthenticationId );
  2329. AuditParameters.ParameterCount++;
  2330. if ( SubjectSecurityContext.ClientToken ) {
  2331. SepSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, SepTokenAuthenticationId( SubjectSecurityContext.ClientToken ));
  2332. } else {
  2333. SepSetParmTypeNoLogon( AuditParameters, AuditParameters.ParameterCount );
  2334. }
  2335. AuditParameters.ParameterCount++;
  2336. SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, LpcCallName );
  2337. AuditParameters.ParameterCount++;
  2338. SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, LpcServerPort );
  2339. AuditParameters.ParameterCount++;
  2340. SepAdtLogAuditRecord( &AuditParameters );
  2341. SeReleaseSubjectContext( &SubjectSecurityContext );
  2342. if ( ImageFileName != &NullString ) {
  2343. ExFreePool( ImageFileName );
  2344. }
  2345. }
  2346. return;
  2347. }
  2348. VOID
  2349. SeAuditSystemTimeChange(
  2350. IN LARGE_INTEGER OldTime,
  2351. IN LARGE_INTEGER NewTime
  2352. )
  2353. /*++
  2354. Routine Description:
  2355. Audits the modification of system time.
  2356. Arguments:
  2357. OldTime - Time before modification.
  2358. NewTime - Time after modification.
  2359. Return Value:
  2360. None.
  2361. --*/
  2362. {
  2363. SE_ADT_PARAMETER_ARRAY AuditParameters;
  2364. PSID UserSid;
  2365. LUID LogonId;
  2366. HANDLE ProcessId;
  2367. PEPROCESS Process;
  2368. PUNICODE_STRING ImageFileName;
  2369. UNICODE_STRING NullString = {0};
  2370. NTSTATUS Status;
  2371. SECURITY_SUBJECT_CONTEXT SubjectSecurityContext;
  2372. PAGED_CODE();
  2373. SeCaptureSubjectContext( &SubjectSecurityContext );
  2374. //
  2375. // Make sure that we care to audit system events.
  2376. //
  2377. if (SepAdtAuditThisEventWithContext(AuditCategorySystem, TRUE, FALSE, &SubjectSecurityContext)) {
  2378. UserSid = SepTokenUserSid( EffectiveToken(&SubjectSecurityContext) );
  2379. LogonId = SepTokenAuthenticationId( SubjectSecurityContext.PrimaryToken );
  2380. Process = PsGetCurrentProcess();
  2381. RtlZeroMemory (
  2382. (PVOID) &AuditParameters,
  2383. sizeof( AuditParameters )
  2384. );
  2385. Status = SeLocateProcessImageName( Process, &ImageFileName );
  2386. if ( !NT_SUCCESS(Status) ) {
  2387. ImageFileName = &NullString;
  2388. }
  2389. ASSERT( SeAdtParmTypeNone == 0 );
  2390. AuditParameters.CategoryId = SE_CATEGID_SYSTEM;
  2391. AuditParameters.AuditId = SE_AUDITID_SYSTEM_TIME_CHANGE;
  2392. AuditParameters.ParameterCount = 0;
  2393. AuditParameters.Type = EVENTLOG_AUDIT_SUCCESS;
  2394. SepSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, UserSid );
  2395. AuditParameters.ParameterCount++;
  2396. SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, (PUNICODE_STRING)&SeSubsystemName );
  2397. AuditParameters.ParameterCount++;
  2398. ProcessId = PsProcessAuditId( Process );
  2399. SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, ProcessId );
  2400. AuditParameters.ParameterCount++;
  2401. SepSetParmTypeFileSpec( AuditParameters, AuditParameters.ParameterCount, ImageFileName );
  2402. AuditParameters.ParameterCount++;
  2403. SepSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, LogonId );
  2404. AuditParameters.ParameterCount++;
  2405. if ( SubjectSecurityContext.ClientToken ) {
  2406. SepSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, SepTokenAuthenticationId( SubjectSecurityContext.ClientToken ));
  2407. } else {
  2408. SepSetParmTypeNoLogon( AuditParameters, AuditParameters.ParameterCount );
  2409. }
  2410. AuditParameters.ParameterCount++;
  2411. SepSetParmTypeTime( AuditParameters, AuditParameters.ParameterCount, OldTime );
  2412. AuditParameters.ParameterCount++;
  2413. SepSetParmTypeTime( AuditParameters, AuditParameters.ParameterCount, NewTime );
  2414. AuditParameters.ParameterCount++;
  2415. SepAdtLogAuditRecord( &AuditParameters );
  2416. if ( ImageFileName != &NullString ) {
  2417. ExFreePool( ImageFileName );
  2418. }
  2419. }
  2420. SeReleaseSubjectContext( &SubjectSecurityContext );
  2421. }
  2422. VOID
  2423. SeAuditHardLinkCreation(
  2424. IN PUNICODE_STRING FileName,
  2425. IN PUNICODE_STRING LinkName,
  2426. IN BOOLEAN bSuccess
  2427. )
  2428. /*++
  2429. Routine Description:
  2430. Audits the attempted creation of a hard link.
  2431. The caller checks audit policy.
  2432. Arguments:
  2433. FileName - Name of the original file.
  2434. LinkName - The name of the hard link.
  2435. bSuccess - Boolean indicating if the hard link creation attempt was successful or not.
  2436. Return Value:
  2437. None.
  2438. --*/
  2439. {
  2440. LUID UserAuthenticationId;
  2441. PSID UserSid;
  2442. SECURITY_SUBJECT_CONTEXT SubjectSecurityContext;
  2443. SE_ADT_PARAMETER_ARRAY AuditParameters = { 0 };
  2444. PAGED_CODE();
  2445. ASSERT( SeAdtParmTypeNone == 0 );
  2446. AuditParameters.CategoryId = SE_CATEGID_OBJECT_ACCESS;
  2447. AuditParameters.AuditId = SE_AUDITID_HARDLINK_CREATION;
  2448. AuditParameters.ParameterCount = 0;
  2449. AuditParameters.Type = bSuccess ? EVENTLOG_AUDIT_SUCCESS : EVENTLOG_AUDIT_FAILURE;
  2450. //
  2451. // Use the effective token.
  2452. //
  2453. SeCaptureSubjectContext( &SubjectSecurityContext );
  2454. UserSid = SepTokenUserSid( EffectiveToken( &SubjectSecurityContext ));
  2455. UserAuthenticationId = SepTokenAuthenticationId( EffectiveToken( &SubjectSecurityContext ));
  2456. //
  2457. // Fill in the AuditParameters structure.
  2458. //
  2459. SepSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, UserSid );
  2460. AuditParameters.ParameterCount++;
  2461. SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, (PUNICODE_STRING)&SeSubsystemName );
  2462. AuditParameters.ParameterCount++;
  2463. SepSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, UserAuthenticationId );
  2464. AuditParameters.ParameterCount++;
  2465. SepSetParmTypeFileSpec( AuditParameters, AuditParameters.ParameterCount, FileName );
  2466. AuditParameters.ParameterCount++;
  2467. SepSetParmTypeFileSpec( AuditParameters, AuditParameters.ParameterCount, LinkName );
  2468. AuditParameters.ParameterCount++;
  2469. SepAdtLogAuditRecord( &AuditParameters );
  2470. SeReleaseSubjectContext( &SubjectSecurityContext );
  2471. return;
  2472. }