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

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