/*++ Copyright (c) 1989 Microsoft Corporation Module Name: sepaudit.c Abstract: This Module implements the audit and alarm procedures that are private to the security component. Author: Robert Reichel (robertre) September 10, 1991 Environment: Kernel Mode Revision History: --*/ #include #include #include #include "tokenp.h" #include "adt.h" #include "adtp.h" #ifdef ALLOC_PRAGMA #pragma alloc_text(PAGE,SeAuditHandleDuplication) // #pragma alloc_text(PAGE,SepAdtAuditThisEvent) #pragma alloc_text(PAGE,SepAdtPrivilegeObjectAuditAlarm) #pragma alloc_text(PAGE,SepAdtPrivilegedServiceAuditAlarm) #pragma alloc_text(PAGE,SepAdtOpenObjectAuditAlarm) #pragma alloc_text(PAGE,SepAdtOpenObjectForDeleteAuditAlarm) #pragma alloc_text(PAGE,SepAdtHandleAuditAlarm) #pragma alloc_text(PAGE,SepAdtObjectReferenceAuditAlarm) #pragma alloc_text(PAGE,SepQueryNameString) #pragma alloc_text(PAGE,SepQueryTypeString) #pragma alloc_text(PAGE,SeAuditProcessCreation) #pragma alloc_text(PAGE,SeAuditProcessExit) #pragma alloc_text(PAGE,SepAdtGenerateDiscardAudit) #endif #define SepSetParmTypeSid( AuditParameters, Index, Sid ) \ { \ (AuditParameters).Parameters[(Index)].Type = SeAdtParmTypeSid; \ (AuditParameters).Parameters[(Index)].Length = RtlLengthSid( (Sid) ); \ (AuditParameters).Parameters[(Index)].Address = (Sid); \ } #define SepSetParmTypeString( AuditParameters, Index, String ) \ { \ (AuditParameters).Parameters[(Index)].Type = SeAdtParmTypeString; \ (AuditParameters).Parameters[(Index)].Length = \ sizeof(UNICODE_STRING)+(String)->Length; \ (AuditParameters).Parameters[(Index)].Address = (String); \ } #define SepSetParmTypeFileSpec( AuditParameters, Index, String ) \ { \ (AuditParameters).Parameters[(Index)].Type = SeAdtParmTypeFileSpec; \ (AuditParameters).Parameters[(Index)].Length = \ sizeof(UNICODE_STRING)+(String)->Length; \ (AuditParameters).Parameters[(Index)].Address = (String); \ } #define SepSetParmTypeUlong( AuditParameters, Index, Ulong ) \ { \ (AuditParameters).Parameters[(Index)].Type = SeAdtParmTypeUlong; \ (AuditParameters).Parameters[(Index)].Length = sizeof( (Ulong) ); \ (AuditParameters).Parameters[(Index)].Data[0] = (ULONG)(Ulong); \ } #define SepSetParmTypeNoLogon( AuditParameters, Index ) \ { \ (AuditParameters).Parameters[(Index)].Type = SeAdtParmTypeNoLogonId; \ } #define SepSetParmTypeLogonId( AuditParameters, Index, LogonId ) \ { \ LUID UNALIGNED * TmpLuid; \ \ (AuditParameters).Parameters[(Index)].Type = SeAdtParmTypeLogonId; \ (AuditParameters).Parameters[(Index)].Length = sizeof( (LogonId) ); \ TmpLuid = (LUID UNALIGNED *)(&(AuditParameters).Parameters[(Index)].Data[0]); \ *TmpLuid = (LogonId); \ } #define SepSetParmTypeAccessMask( AuditParameters, Index, AccessMask, ObjectTypeIndex ) \ { \ (AuditParameters).Parameters[(Index)].Type = SeAdtParmTypeAccessMask; \ (AuditParameters).Parameters[(Index)].Length = sizeof( ACCESS_MASK ); \ (AuditParameters).Parameters[(Index)].Data[0] = (AccessMask); \ (AuditParameters).Parameters[(Index)].Data[1] = (ObjectTypeIndex); \ } #define SepSetParmTypePrivileges( AuditParameters, Index, Privileges ) \ { \ (AuditParameters).Parameters[(Index)].Type = SeAdtParmTypePrivs; \ (AuditParameters).Parameters[(Index)].Length = SepPrivilegeSetSize( (Privileges) ); \ (AuditParameters).Parameters[(Index)].Address = (Privileges); \ } BOOLEAN SepAdtPrivilegeObjectAuditAlarm ( IN PUNICODE_STRING CapturedSubsystemName OPTIONAL, IN PVOID HandleId, IN PTOKEN ClientToken OPTIONAL, IN PTOKEN PrimaryToken, IN PVOID ProcessId, IN ACCESS_MASK DesiredAccess, IN PPRIVILEGE_SET CapturedPrivileges, IN BOOLEAN AccessGranted ) /*++ Routine Description: Implements NtPrivilegeObjectAuditAlarm after parameters have been captured. This routine is used to generate audit and alarm messages when an attempt is made to perform privileged operations on a protected subsystem object after the object is already opened. This routine may result in several messages being generated and sent to Port objects. This may result in a significant latency before returning. Design of routines that must call this routine must take this potential latency into account. This may have an impact on the approach taken for data structure mutex locking, for example. This API requires the caller have SeTcbPrivilege privilege. The test for this privilege is always against the primary token of the calling process, allowing the caller to be impersonating a client during the call with no ill effects. This routine will create an SE_ADT_PARAMETERS array organized as follows: Parameter[0] - User Sid Parameter[1] - Subsystem name (if available) Parameter[2] - New handle ID Parameter[3] - Subject's process id Parameter[4] - Subject's primary authentication ID Parameter[5] - Subject's client authentication ID Parameter[6] - Privileges used for open Arguments: CapturedSubsystemName - Supplies a name string identifying the subsystem calling the routine. HandleId - A unique value representing the client's handle to the object. ClientToken - Optionally provides a pointer to the client token (only if the caller is currently impersonating) PrimaryToken - Provides a pointer to the caller's primary token. DesiredAccess - The desired access mask. This mask must have been previously mapped to contain no generic accesses. CapturedPrivileges - The set of privileges required for the requested operation. Those privileges that were held by the subject are marked using the UsedForAccess flag of the attributes associated with each privilege. AccessGranted - Indicates whether the requested access was granted or not. A value of TRUE indicates the access was granted. A value of FALSE indicates the access was not granted. Return value: --*/ { SE_ADT_PARAMETER_ARRAY AuditParameters; PSID CapturedUserSid; LUID ClientAuthenticationId; LUID PrimaryAuthenticationId; PAGED_CODE(); // // Determine if we are auditing the use of privileges // if ( SepAdtAuditThisEvent( AuditCategoryPrivilegeUse, &AccessGranted ) && SepFilterPrivilegeAudits( CapturedPrivileges )) { if ( ARGUMENT_PRESENT( ClientToken )) { CapturedUserSid = SepTokenUserSid( ClientToken ); ClientAuthenticationId = SepTokenAuthenticationId( ClientToken ); } else { CapturedUserSid = SepTokenUserSid( PrimaryToken ); } if ( RtlEqualSid( SeLocalSystemSid, CapturedUserSid )) { return (FALSE); } PrimaryAuthenticationId = SepTokenAuthenticationId( PrimaryToken ); // // A completely zero'd entry will be interpreted // as a "null string" or not supplied parameter. // // Initializing the entire array up front will allow // us to avoid filling in each not supplied entry. // RtlZeroMemory ( (PVOID) &AuditParameters, sizeof( AuditParameters ) ); ASSERT( SeAdtParmTypeNone == 0 ); AuditParameters.CategoryId = SE_CATEGID_PRIVILEGE_USE; AuditParameters.AuditId = SE_AUDITID_PRIVILEGED_OBJECT; AuditParameters.ParameterCount = 0; if ( AccessGranted ) { AuditParameters.Type = EVENTLOG_AUDIT_SUCCESS; } else { AuditParameters.Type = EVENTLOG_AUDIT_FAILURE; } // // Parameter[0] - User Sid // SepSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, CapturedUserSid ); AuditParameters.ParameterCount++; // // Parameter[1] - Subsystem name (if available) // SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, CapturedSubsystemName ); AuditParameters.ParameterCount++; // // Parameter[1] - Subsystem name (if available) // SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, CapturedSubsystemName ); AuditParameters.ParameterCount++; // // Parameter[2] - New handle ID // SepSetParmTypeUlong( AuditParameters, AuditParameters.ParameterCount, HandleId ); AuditParameters.ParameterCount++; // // Parameter[3] - Subject's process id // SepSetParmTypeUlong( AuditParameters, AuditParameters.ParameterCount, ProcessId ); AuditParameters.ParameterCount++; // // Parameter[4] - Subject's primary authentication ID // SepSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, PrimaryAuthenticationId ); AuditParameters.ParameterCount++; // // Parameter[5] - Subject's client authentication ID // if ( ARGUMENT_PRESENT( ClientToken )) { SepSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, ClientAuthenticationId ); } else { SepSetParmTypeNoLogon( AuditParameters, AuditParameters.ParameterCount ); } AuditParameters.ParameterCount++; // // Parameter[6] - Privileges used for open // if ( (CapturedPrivileges != NULL) && (CapturedPrivileges->PrivilegeCount > 0) ) { SepSetParmTypePrivileges( AuditParameters, AuditParameters.ParameterCount, CapturedPrivileges ); } AuditParameters.ParameterCount++; SepAdtLogAuditRecord( &AuditParameters ); return( TRUE ); } return( FALSE ); } VOID SepAdtPrivilegedServiceAuditAlarm ( IN PUNICODE_STRING CapturedSubsystemName, IN PUNICODE_STRING CapturedServiceName, IN PTOKEN ClientToken OPTIONAL, IN PTOKEN PrimaryToken, IN PPRIVILEGE_SET CapturedPrivileges, IN BOOLEAN AccessGranted ) /*++ Routine Description: This routine is the active part of NtPrivilegedServiceAuditAlarm. This routine is used to generate audit and alarm messages when an attempt is made to perform privileged system service operations. This routine may result in several messages being generated and sent to Port objects. This may result in a significant latency before returning. Design of routines that must call this routine must take this potential latency into account. This may have an impact on the approach taken for data structure mutex locking, for example. This API requires the caller have SeTcbPrivilege privilege. The test for this privilege is always against the primary token of the calling process, allowing the caller to be impersonating a client during the call with no ill effects. The test for this privilege is assumed to have occurred at a higher level. This routine will create an SE_ADT_PARAMETERS array organized as follows: Parameter[0] - User Sid Parameter[1] - Subsystem name (if available) Parameter[2] - Subject's primary authentication ID Parameter[3] - Subject's client authentication ID Parameter[4] - Privileges used for open Arguments: SubsystemName - Supplies a name string identifying the subsystem calling the routine. ServiceName - Supplies a name of the privileged subsystem service. For example, "RESET RUNTIME LOCAL SECURITY POLICY" might be specified by a Local Security Authority service used to update the local security policy database. ClientToken - Optionally provides a pointer to the client token (only if the caller is currently impersonating) PrimaryToken - Provides a pointer to the caller's primary token. Privileges - Points to a set of privileges required to perform the privileged operation. Those privileges that were held by the subject are marked using the UsedForAccess flag of the attributes associated with each privilege. AccessGranted - Indicates whether the requested access was granted or not. A value of TRUE indicates the access was granted. A value of FALSE indicates the access was not granted. Return value: --*/ { SE_ADT_PARAMETER_ARRAY AuditParameters; PSID CapturedUserSid; LUID ClientAuthenticationId; LUID PrimaryAuthenticationId; PUNICODE_STRING SubsystemName; PAGED_CODE(); // // Determine if we are auditing privileged services // if ( SepAdtAuditThisEvent( AuditCategoryPrivilegeUse, &AccessGranted )) { if ( ARGUMENT_PRESENT( ClientToken )) { CapturedUserSid = SepTokenUserSid( ClientToken ); ClientAuthenticationId = SepTokenAuthenticationId( ClientToken ); } else { CapturedUserSid = SepTokenUserSid( PrimaryToken ); } PrimaryAuthenticationId = SepTokenAuthenticationId( PrimaryToken ); if ( !ARGUMENT_PRESENT( CapturedSubsystemName )) { SubsystemName = &SeSubsystemName; } else { SubsystemName = CapturedSubsystemName; } // // A completely zero'd entry will be interpreted // as a "null string" or not supplied parameter. // // Initializing the entire array up front will allow // us to avoid filling in each not supplied entry. // RtlZeroMemory ( (PVOID) &AuditParameters, sizeof( AuditParameters ) ); ASSERT( SeAdtParmTypeNone == 0 ); AuditParameters.CategoryId = SE_CATEGID_PRIVILEGE_USE; AuditParameters.AuditId = SE_AUDITID_PRIVILEGED_SERVICE; AuditParameters.ParameterCount = 0; if ( AccessGranted ) { AuditParameters.Type = EVENTLOG_AUDIT_SUCCESS; } else { AuditParameters.Type = EVENTLOG_AUDIT_FAILURE; } // // Parameter[0] - User Sid // SepSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, CapturedUserSid ); AuditParameters.ParameterCount++; // // Parameter[1] - Subsystem name (if available) // SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, SubsystemName ); AuditParameters.ParameterCount++; // // Parameter[2] - Server // SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, SubsystemName ); AuditParameters.ParameterCount++; // // Parameter[3] - Service name (if available) // if ( ARGUMENT_PRESENT( CapturedServiceName )) { SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, CapturedServiceName ); } AuditParameters.ParameterCount++; // // Parameter[3] - Subject's primary authentication ID // SepSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, PrimaryAuthenticationId ); AuditParameters.ParameterCount++; // // Parameter[4] - Subject's client authentication ID // if ( ARGUMENT_PRESENT( ClientToken )) { SepSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, ClientAuthenticationId ); } else { SepSetParmTypeNoLogon( AuditParameters, AuditParameters.ParameterCount ); } AuditParameters.ParameterCount++; // // Parameter[5] - Privileges used for open // if ( (CapturedPrivileges != NULL) && (CapturedPrivileges->PrivilegeCount > 0) ) { SepSetParmTypePrivileges( AuditParameters, AuditParameters.ParameterCount, CapturedPrivileges ); } AuditParameters.ParameterCount++; SepAdtLogAuditRecord( &AuditParameters ); } } BOOLEAN SepAdtOpenObjectAuditAlarm ( IN PUNICODE_STRING CapturedSubsystemName, IN PVOID *HandleId OPTIONAL, IN PUNICODE_STRING CapturedObjectTypeName, IN PVOID Object OPTIONAL, IN PUNICODE_STRING CapturedObjectName OPTIONAL, IN PTOKEN ClientToken OPTIONAL, IN PTOKEN PrimaryToken, IN ACCESS_MASK DesiredAccess, IN ACCESS_MASK GrantedAccess, IN PLUID OperationId, IN PPRIVILEGE_SET CapturedPrivileges OPTIONAL, IN BOOLEAN ObjectCreated, IN BOOLEAN AccessGranted, IN BOOLEAN GenerateAudit, IN BOOLEAN GenerateAlarm, IN HANDLE ProcessID ) /*++ Routine Description: Implements NtOpenObjectAuditAlarm after parameters have been captured. This routine is used to generate audit and alarm messages when an attempt is made to access an existing protected subsystem object or create a new one. This routine may result in several messages being generated and sent to Port objects. This may result in a significant latency before returning. Design of routines that must call this routine must take this potential latency into account. This may have an impact on the approach taken for data structure mutex locking, for example. This API requires the caller have SeTcbPrivilege privilege. The test for this privilege is always against the primary token of the calling process, not the impersonation token of the thread. This routine will create an SE_ADT_PARAMETERS array organized as follows: Parameter[0] - User Sid Parameter[1] - Subsystem name (if available) Parameter[2] - Server name (if available) Parameter[3] - Object Type Name Parameter[4] - Object Name Parameter[5] - New handle ID Parameter[6] - Subject's process id Parameter[7] - Subject's primary authentication ID Parameter[8] - Subject's client authentication ID Parameter[9] - DesiredAccess mask Parameter[10] - Privileges used for open Arguments: CapturedSubsystemName - Supplies a name string identifying the subsystem calling the routine. HandleId - A unique value representing the client's handle to the object. If the access attempt was not successful (AccessGranted is FALSE), then this parameter is ignored. CapturedObjectTypeName - Supplies the name of the type of object being accessed. CapturedObjectName - Supplies the name of the object the client accessed or attempted to access. CapturedSecurityDescriptor - A pointer to the security descriptor of the object being accessed. ClientToken - Optionally provides a pointer to the client token (only if the caller is currently impersonating) PrimaryToken - Provides a pointer to the caller's primary token. DesiredAccess - The desired access mask. This mask must have been previously mapped to contain no generic accesses. GrantedAccess - The mask of accesses that were actually granted. CapturedPrivileges - Optionally points to a set of privileges that were required for the access attempt. Those privileges that were held by the subject are marked using the UsedForAccess flag of the attributes associated with each privilege. ObjectCreation - A boolean flag indicating whether the access will result in a new object being created if granted. A value of TRUE indicates an object will be created, FALSE indicates an existing object will be opened. AccessGranted - Indicates whether the requested access was granted or not. A value of TRUE indicates the access was granted. A value of FALSE indicates the access was not granted. GenerateOnClose - Points to a boolean that is set by the audit generation routine and must be passed to NtCloseObjectAuditAlarm() when the object handle is closed. GenerateAudit - Indicates if we should generate an audit for this operation. GenerateAlarm - Indicates if we should generate an alarm for this operation. Return Value: Returns TRUE if audit is generated, FALSE otherwise. --*/ { SE_ADT_PARAMETER_ARRAY AuditParameters; ULONG ObjectTypeIndex; PSID CapturedUserSid; LUID PrimaryAuthenticationId; LUID ClientAuthenticationId; PAGED_CODE(); if ( ARGUMENT_PRESENT( ClientToken )) { CapturedUserSid = SepTokenUserSid( ClientToken ); ClientAuthenticationId = SepTokenAuthenticationId( ClientToken ); } else { CapturedUserSid = SepTokenUserSid( PrimaryToken ); } PrimaryAuthenticationId = SepTokenAuthenticationId( PrimaryToken ); // // A completely zero'd entry will be interpreted // as a "null string" or not supplied parameter. // // Initializing the entire array up front will allow // us to avoid filling in each not supplied entry. // RtlZeroMemory ( (PVOID) &AuditParameters, sizeof( AuditParameters ) ); ASSERT( SeAdtParmTypeNone == 0 ); AuditParameters.CategoryId = SE_CATEGID_OBJECT_ACCESS; AuditParameters.AuditId = SE_AUDITID_OPEN_HANDLE; AuditParameters.ParameterCount = 0; if ( AccessGranted ) { AuditParameters.Type = EVENTLOG_AUDIT_SUCCESS; } else { AuditParameters.Type = EVENTLOG_AUDIT_FAILURE; } // // Parameter[0] - User Sid // SepSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, CapturedUserSid ); AuditParameters.ParameterCount++; // // Parameter[1] - Subsystem name (if available) // SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, CapturedSubsystemName ); AuditParameters.ParameterCount++; // // Parameter[2] - Object Server (if available) // if ( ARGUMENT_PRESENT( CapturedSubsystemName )) { SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, CapturedSubsystemName ); } AuditParameters.ParameterCount++; // // Parameter[3] - Object Type Name // if ( ARGUMENT_PRESENT( CapturedObjectTypeName )) { SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, CapturedObjectTypeName ); ObjectTypeIndex = AuditParameters.ParameterCount; } AuditParameters.ParameterCount++; // // Parameter[4] - Object Name // if ( ARGUMENT_PRESENT( CapturedObjectName )) { SepSetParmTypeFileSpec( AuditParameters, AuditParameters.ParameterCount, CapturedObjectName ); } AuditParameters.ParameterCount++; // // Parameter[5] - New handle ID // if ( ARGUMENT_PRESENT( HandleId )) { SepSetParmTypeUlong( AuditParameters, AuditParameters.ParameterCount, *HandleId ); } AuditParameters.ParameterCount++; if ( ARGUMENT_PRESENT( OperationId )) { SepSetParmTypeUlong( AuditParameters, AuditParameters.ParameterCount, (*OperationId).HighPart ); AuditParameters.ParameterCount++; SepSetParmTypeUlong( AuditParameters, AuditParameters.ParameterCount, (*OperationId).LowPart ); AuditParameters.ParameterCount++; } else { AuditParameters.ParameterCount += 2; } // // Parameter[6] - Subject's process id // SepSetParmTypeUlong( AuditParameters, AuditParameters.ParameterCount, ProcessID ); AuditParameters.ParameterCount++; // // Parameter[7] - Subject's primary authentication ID // SepSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, PrimaryAuthenticationId ); AuditParameters.ParameterCount++; // // Parameter[8] - Subject's client authentication ID // if ( ARGUMENT_PRESENT( ClientToken )) { SepSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, ClientAuthenticationId ); } else { SepSetParmTypeNoLogon( AuditParameters, AuditParameters.ParameterCount ); } AuditParameters.ParameterCount++; // // Parameter[9] - DesiredAccess mask // if ( AccessGranted ) { SepSetParmTypeAccessMask( AuditParameters, AuditParameters.ParameterCount, GrantedAccess, ObjectTypeIndex ); } else { SepSetParmTypeAccessMask( AuditParameters, AuditParameters.ParameterCount, DesiredAccess, ObjectTypeIndex ); } AuditParameters.ParameterCount++; // // Parameter[10] - Privileges used for open // if ( (CapturedPrivileges != NULL) && (CapturedPrivileges->PrivilegeCount > 0) ) { SepSetParmTypePrivileges( AuditParameters, AuditParameters.ParameterCount, CapturedPrivileges ); } AuditParameters.ParameterCount++; SepAdtLogAuditRecord( &AuditParameters ); return( TRUE ); } BOOLEAN SepAdtOpenObjectForDeleteAuditAlarm ( IN PUNICODE_STRING CapturedSubsystemName, IN PVOID *HandleId OPTIONAL, IN PUNICODE_STRING CapturedObjectTypeName, IN PVOID Object OPTIONAL, IN PUNICODE_STRING CapturedObjectName OPTIONAL, IN PTOKEN ClientToken OPTIONAL, IN PTOKEN PrimaryToken, IN ACCESS_MASK DesiredAccess, IN ACCESS_MASK GrantedAccess, IN PLUID OperationId, IN PPRIVILEGE_SET CapturedPrivileges OPTIONAL, IN BOOLEAN ObjectCreated, IN BOOLEAN AccessGranted, IN BOOLEAN GenerateAudit, IN BOOLEAN GenerateAlarm, IN HANDLE ProcessID ) /*++ Routine Description: Implements SeOpenObjectForDeleteAuditAlarm after parameters have been captured. This routine is used to generate audit and alarm messages when an attempt is made to access an existing protected subsystem object or create a new one. This routine may result in several messages being generated and sent to Port objects. This may result in a significant latency before returning. Design of routines that must call this routine must take this potential latency into account. This may have an impact on the approach taken for data structure mutex locking, for example. This API requires the caller have SeTcbPrivilege privilege. The test for this privilege is always against the primary token of the calling process, not the impersonation token of the thread. This routine will create an SE_ADT_PARAMETERS array organized as follows: Parameter[0] - User Sid Parameter[1] - Subsystem name (if available) Parameter[2] - Server name (if available) Parameter[3] - Object Type Name Parameter[4] - Object Name Parameter[5] - New handle ID Parameter[6] - Subject's process id Parameter[7] - Subject's primary authentication ID Parameter[8] - Subject's client authentication ID Parameter[9] - DesiredAccess mask Parameter[10] - Privileges used for open Arguments: CapturedSubsystemName - Supplies a name string identifying the subsystem calling the routine. HandleId - A unique value representing the client's handle to the object. If the access attempt was not successful (AccessGranted is FALSE), then this parameter is ignored. CapturedObjectTypeName - Supplies the name of the type of object being accessed. CapturedObjectName - Supplies the name of the object the client accessed or attempted to access. CapturedSecurityDescriptor - A pointer to the security descriptor of the object being accessed. ClientToken - Optionally provides a pointer to the client token (only if the caller is currently impersonating) PrimaryToken - Provides a pointer to the caller's primary token. DesiredAccess - The desired access mask. This mask must have been previously mapped to contain no generic accesses. GrantedAccess - The mask of accesses that were actually granted. CapturedPrivileges - Optionally points to a set of privileges that were required for the access attempt. Those privileges that were held by the subject are marked using the UsedForAccess flag of the attributes associated with each privilege. ObjectCreation - A boolean flag indicating whether the access will result in a new object being created if granted. A value of TRUE indicates an object will be created, FALSE indicates an existing object will be opened. AccessGranted - Indicates whether the requested access was granted or not. A value of TRUE indicates the access was granted. A value of FALSE indicates the access was not granted. GenerateOnClose - Points to a boolean that is set by the audit generation routine and must be passed to NtCloseObjectAuditAlarm() when the object handle is closed. GenerateAudit - Indicates if we should generate an audit for this operation. GenerateAlarm - Indicates if we should generate an alarm for this operation. Return Value: Returns TRUE if audit is generated, FALSE otherwise. --*/ { SE_ADT_PARAMETER_ARRAY AuditParameters; ULONG ObjectTypeIndex; PSID CapturedUserSid; LUID PrimaryAuthenticationId; LUID ClientAuthenticationId; PAGED_CODE(); if ( ARGUMENT_PRESENT( ClientToken )) { CapturedUserSid = SepTokenUserSid( ClientToken ); ClientAuthenticationId = SepTokenAuthenticationId( ClientToken ); } else { CapturedUserSid = SepTokenUserSid( PrimaryToken ); } PrimaryAuthenticationId = SepTokenAuthenticationId( PrimaryToken ); // // A completely zero'd entry will be interpreted // as a "null string" or not supplied parameter. // // Initializing the entire array up front will allow // us to avoid filling in each not supplied entry. // RtlZeroMemory ( (PVOID) &AuditParameters, sizeof( AuditParameters ) ); ASSERT( SeAdtParmTypeNone == 0 ); AuditParameters.CategoryId = SE_CATEGID_OBJECT_ACCESS; AuditParameters.AuditId = SE_AUDITID_OPEN_OBJECT_FOR_DELETE; AuditParameters.ParameterCount = 0; if ( AccessGranted ) { AuditParameters.Type = EVENTLOG_AUDIT_SUCCESS; } else { AuditParameters.Type = EVENTLOG_AUDIT_FAILURE; } // // Parameter[0] - User Sid // SepSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, CapturedUserSid ); AuditParameters.ParameterCount++; // // Parameter[1] - Subsystem name (if available) // SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, CapturedSubsystemName ); AuditParameters.ParameterCount++; // // Parameter[2] - Object Server (if available) // if ( ARGUMENT_PRESENT( CapturedSubsystemName )) { SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, CapturedSubsystemName ); } AuditParameters.ParameterCount++; // // Parameter[3] - Object Type Name // if ( ARGUMENT_PRESENT( CapturedObjectTypeName )) { SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, CapturedObjectTypeName ); ObjectTypeIndex = AuditParameters.ParameterCount; } AuditParameters.ParameterCount++; // // Parameter[4] - Object Name // if ( ARGUMENT_PRESENT( CapturedObjectName )) { SepSetParmTypeFileSpec( AuditParameters, AuditParameters.ParameterCount, CapturedObjectName ); } AuditParameters.ParameterCount++; // // Parameter[5] - New handle ID // if ( ARGUMENT_PRESENT( HandleId )) { SepSetParmTypeUlong( AuditParameters, AuditParameters.ParameterCount, *HandleId ); } AuditParameters.ParameterCount++; if ( ARGUMENT_PRESENT( OperationId )) { SepSetParmTypeUlong( AuditParameters, AuditParameters.ParameterCount, (*OperationId).HighPart ); AuditParameters.ParameterCount++; SepSetParmTypeUlong( AuditParameters, AuditParameters.ParameterCount, (*OperationId).LowPart ); AuditParameters.ParameterCount++; } else { AuditParameters.ParameterCount += 2; } // // Parameter[6] - Subject's process id // SepSetParmTypeUlong( AuditParameters, AuditParameters.ParameterCount, ProcessID ); AuditParameters.ParameterCount++; // // Parameter[7] - Subject's primary authentication ID // SepSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, PrimaryAuthenticationId ); AuditParameters.ParameterCount++; // // Parameter[8] - Subject's client authentication ID // if ( ARGUMENT_PRESENT( ClientToken )) { SepSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, ClientAuthenticationId ); } else { SepSetParmTypeNoLogon( AuditParameters, AuditParameters.ParameterCount ); } AuditParameters.ParameterCount++; // // Parameter[9] - DesiredAccess mask // if ( AccessGranted ) { SepSetParmTypeAccessMask( AuditParameters, AuditParameters.ParameterCount, GrantedAccess, ObjectTypeIndex ); } else { SepSetParmTypeAccessMask( AuditParameters, AuditParameters.ParameterCount, DesiredAccess, ObjectTypeIndex ); } AuditParameters.ParameterCount++; // // Parameter[10] - Privileges used for open // if ( (CapturedPrivileges != NULL) && (CapturedPrivileges->PrivilegeCount > 0) ) { SepSetParmTypePrivileges( AuditParameters, AuditParameters.ParameterCount, CapturedPrivileges ); } AuditParameters.ParameterCount++; SepAdtLogAuditRecord( &AuditParameters ); return( TRUE ); } VOID SepAdtCloseObjectAuditAlarm ( IN PUNICODE_STRING CapturedSubsystemName, IN PVOID HandleId, IN PVOID Object, IN PSID UserSid, IN LUID AuthenticationId ) /*++ Routine Description: This routine implements NtCloseObjectAuditAlarm after parameters have been captured. This routine is used to generate audit and alarm messages when a handle to a protected subsystem object is deleted. This routine may result in several messages being generated and sent to Port objects. This may result in a significant latency before returning. Design of routines that must call this routine must take this potential latency into account. This may have an impact on the approach taken for data structure mutex locking, for example. This API requires the caller have SeTcbPrivilege privilege. The test for this privilege is always against the primary token of the calling process, allowing the caller to be impersonating a client during the call with no ill effects. It is assumed that this privilege has been tested at a higher level. This routine will create an SE_ADT_PARAMETERS array organized as follows: Parameter[0] - User Sid Parameter[1] - Subsystem name (if available) Parameter[2] - New handle ID Parameter[3] - Subject's process id Arguments: CapturedSubsystemName - Supplies a name string identifying the subsystem calling the routine. HandleId - A unique value representing the client's handle to the object. Object - The address of the object being closed UserSid - The Sid identifying the current caller. Return value: None. --*/ { SE_ADT_PARAMETER_ARRAY AuditParameters; BOOLEAN AccessGranted = TRUE; HANDLE ProcessId; PAGED_CODE(); if ( SepAdtAuditThisEvent( AuditCategoryObjectAccess, &AccessGranted ) ) { // // A completely zero'd entry will be interpreted // as a "null string" or not supplied parameter. // // Initializing the entire array up front will allow // us to avoid filling in each not supplied entry. // RtlZeroMemory ( (PVOID) &AuditParameters, sizeof( AuditParameters ) ); ASSERT( SeAdtParmTypeNone == 0 ); AuditParameters.CategoryId = SE_CATEGID_OBJECT_ACCESS; AuditParameters.AuditId = SE_AUDITID_CLOSE_HANDLE; AuditParameters.ParameterCount = 0; AuditParameters.Type = EVENTLOG_AUDIT_SUCCESS; // // Parameter[0] - User Sid // SepSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, UserSid ); AuditParameters.ParameterCount++; // // Parameter[1] - Subsystem name (if available) // if ( ARGUMENT_PRESENT( CapturedSubsystemName )) { SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, CapturedSubsystemName ); } AuditParameters.ParameterCount++; // // Parameter[2] - Subsystem name (if available) // if ( ARGUMENT_PRESENT( CapturedSubsystemName )) { SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, CapturedSubsystemName ); } AuditParameters.ParameterCount++; // // Parameter[3] - New handle ID // SepSetParmTypeUlong( AuditParameters, AuditParameters.ParameterCount, HandleId ); AuditParameters.ParameterCount++; // // Parameter[4] - Subject's process id // ProcessId = PsProcessAuditId( PsGetCurrentProcess() ); SepSetParmTypeUlong( AuditParameters, AuditParameters.ParameterCount, ProcessId ); AuditParameters.ParameterCount++; SepAdtLogAuditRecord( &AuditParameters ); } } VOID SepAdtDeleteObjectAuditAlarm ( IN PUNICODE_STRING CapturedSubsystemName, IN PVOID HandleId, IN PVOID Object, IN PSID UserSid, IN LUID AuthenticationId ) /*++ Routine Description: This routine implements NtDeleteObjectAuditAlarm after parameters have been captured. This routine is used to generate audit and alarm messages when an object in a protected subsystem object is deleted. This routine may result in several messages being generated and sent to Port objects. This may result in a significant latency before returning. Design of routines that must call this routine must take this potential latency into account. This may have an impact on the approach taken for data structure mutex locking, for example. This API requires the caller have SeTcbPrivilege privilege. The test for this privilege is always against the primary token of the calling process, allowing the caller to be impersonating a client during the call with no ill effects. It is assumed that this privilege has been tested at a higher level. This routine will create an SE_ADT_PARAMETERS array organized as follows: Parameter[0] - User Sid Parameter[1] - Subsystem name (if available) Parameter[2] - Handle ID Parameter[3] - Subject's process id Arguments: CapturedSubsystemName - Supplies a name string identifying the subsystem calling the routine. HandleId - A unique value representing the client's handle to the object. Object - The address of the object being closed UserSid - The Sid identifying the current caller. Return value: None. --*/ { SE_ADT_PARAMETER_ARRAY AuditParameters; BOOLEAN AccessGranted = TRUE; HANDLE ProcessId; PAGED_CODE(); if ( SepAdtAuditThisEvent( AuditCategoryObjectAccess, &AccessGranted ) ) { // // A completely zero'd entry will be interpreted // as a "null string" or not supplied parameter. // // Initializing the entire array up front will allow // us to avoid filling in each not supplied entry. // RtlZeroMemory ( (PVOID) &AuditParameters, sizeof( AuditParameters ) ); ASSERT( SeAdtParmTypeNone == 0 ); AuditParameters.CategoryId = SE_CATEGID_OBJECT_ACCESS; AuditParameters.AuditId = SE_AUDITID_DELETE_OBJECT; AuditParameters.ParameterCount = 0; AuditParameters.Type = EVENTLOG_AUDIT_SUCCESS; // // Parameter[0] - User Sid // SepSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, UserSid ); AuditParameters.ParameterCount++; // // Parameter[1] - Subsystem name (if available) // if ( ARGUMENT_PRESENT( CapturedSubsystemName )) { SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, CapturedSubsystemName ); } AuditParameters.ParameterCount++; // // Parameter[2] - Subsystem name (if available) // if ( ARGUMENT_PRESENT( CapturedSubsystemName )) { SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, CapturedSubsystemName ); } AuditParameters.ParameterCount++; // // Parameter[3] - New handle ID // SepSetParmTypeUlong( AuditParameters, AuditParameters.ParameterCount, HandleId ); AuditParameters.ParameterCount++; // // Parameter[4] - Subject's process id // ProcessId = PsProcessAuditId( PsGetCurrentProcess() ); SepSetParmTypeUlong( AuditParameters, AuditParameters.ParameterCount, ProcessId ); AuditParameters.ParameterCount++; SepAdtLogAuditRecord( &AuditParameters ); } } // //VOID //SepAdtTraverseAuditAlarm( // IN PLUID OperationId, // IN PVOID DirectoryObject, // IN PSID UserSid, // IN LUID AuthenticationId, // IN ACCESS_MASK DesiredAccess, // IN PPRIVILEGE_SET Privileges OPTIONAL, // IN BOOLEAN AccessGranted, // IN BOOLEAN GenerateAudit, // IN BOOLEAN GenerateAlarm // ) ///*++ // //Routine Description: // // This routine constructs an audit record to record that a request // to traverse a directory has occurred. // //Arguments: // // OperationID - LUID identifying the operation in progress // // DirectoryObject - Pointer to the directory being traversed. // // UserSid - Provides the User Sid for the caller. // // DesiredAccess - Mask to indicate the traverse access for this object // type. // // Privileges - Optional parameter to indicate any privilges that the // subject may have used to gain access to the object. // // AccessGranted - Indicates if the access was granted or denied based on // the access check or privilege check. // // GenerateAudit - Indicates if we should generate an audit for this operation. // // GenerateAlarm - Indicates if we should generate an alarm for this operation. // //Return Value: // // None. // //--*/ //{ // POLICY_AUDIT_TRAVERSE AuditTraverse; // // UNREFERENCED_PARAMETER( GenerateAudit ); // UNREFERENCED_PARAMETER( GenerateAlarm ); // UNREFERENCED_PARAMETER( DirectoryObject ); // UNREFERENCED_PARAMETER( DesiredAccess ); // // // // // BUGWARNING need a way to get the directory name from // // the directory object // // // // AuditTraverse.AccessGranted = AccessGranted; // AuditTraverse.DirectoryName = NULL; // AuditTraverse.OperationId = *OperationId; // AuditTraverse.PrivilegeSet = Privileges; // AuditTraverse.UserSid = UserSid; // AuditTraverse.AuthenticationId = AuthenticationId; // //// SepAdtLogAuditRecord( AuditEventTraverse, &AuditTraverse ); //} // //VOID //SepAdtCreateObjectAuditAlarm( // IN PLUID OperationID, // IN PUNICODE_STRING DirectoryName, // IN PUNICODE_STRING ComponentName, // IN PSID UserSid, // IN LUID AuthenticationId, // IN ACCESS_MASK DesiredAccess, // IN BOOLEAN AccessGranted, // IN BOOLEAN GenerateAudit, // IN BOOLEAN GenerateAlarm // ) ///*++ // //Routine Description: // // description-of-function. // //Arguments: // // // GenerateAudit - Indicates if we should generate an audit for this operation. // // GenerateAlarm - Indicates if we should generate an alarm for this operation. // //Return Value: // // return-value - Description of conditions needed to return value. - or - // None. // //--*/ // //{ // POLICY_AUDIT_CREATE_OBJECT AuditCreateObject; // // UNREFERENCED_PARAMETER( GenerateAudit ); // UNREFERENCED_PARAMETER( GenerateAlarm ); // // // AuditCreateObject.AccessGranted = AccessGranted; // AuditCreateObject.DesiredAccess = DesiredAccess; // AuditCreateObject.DirectoryName = DirectoryName; // AuditCreateObject.ComponentName = ComponentName; // AuditCreateObject.OperationId = *OperationID; // AuditCreateObject.UserSid = UserSid; // AuditCreateObject.AuthenticationId = AuthenticationId; // //// SepAdtLogAuditRecord( AuditEventCreateObject, &AuditCreateObject ); //} // //VOID //SepAdtImplicitObjectAuditAlarm( // IN PLUID OperationId OPTIONAL, // IN PVOID Object, // IN PSID UserSid, // IN ACCESS_MASK DesiredAccess, // IN PPRIVILEGE_SET Privileges OPTIONAL, // IN BOOLEAN AccessGranted, // IN BOOLEAN GenerateAudit, // IN BOOLEAN GenerateAlarm // ) ///*++ // //Routine Description: // // description-of-function. // //Arguments: // // GenerateAudit - Indicates if we should generate an audit for this operation. // // GenerateAlarm - Indicates if we should generate an alarm for this operation. // // //Return Value: // // None // //--*/ // //{ // POLICY_AUDIT_IMPLICIT_ACCESS AuditImplicitAccess; // // UNREFERENCED_PARAMETER( GenerateAudit ); // UNREFERENCED_PARAMETER( GenerateAlarm ); // // // // // // BUGWARNING need a way to obtain the object type // // // // AuditImplicitAccess.AccessGranted = AccessGranted; // AuditImplicitAccess.DesiredAccess = DesiredAccess; // AuditImplicitAccess.ObjectTypeName = NULL; // AuditImplicitAccess.OperationId = *OperationId; // AuditImplicitAccess.PrivilegeSet = Privileges; // AuditImplicitAccess.UserSid = UserSid; // // SepAdtLogAuditRecord( AuditEventImplicitAccess, &AuditImplicitAccess ); //} VOID SepAdtHandleAuditAlarm( IN PUNICODE_STRING Source, IN LUID OperationId, IN HANDLE Handle, IN PSID UserSid ) /*++ Routine Description: Creates an audit record for the creation of an object handle. Arguments: Return Value: None. --*/ { BOOLEAN AccessGranted = TRUE; SE_ADT_PARAMETER_ARRAY AuditParameters; HANDLE ProcessID; PAGED_CODE(); if ( SepAdtAuditThisEvent( AuditCategoryObjectAccess, &AccessGranted )) { // // A completely zero'd entry will be interpreted // as a "null string" or not supplied parameter. // // Initializing the entire array up front will allow // us to avoid filling in each not supplied entry. // RtlZeroMemory ( (PVOID) &AuditParameters, sizeof( AuditParameters ) ); ASSERT( SeAdtParmTypeNone == 0 ); AuditParameters.CategoryId = SE_CATEGID_OBJECT_ACCESS; AuditParameters.AuditId = SE_AUDITID_CREATE_HANDLE; AuditParameters.ParameterCount = 0; AuditParameters.Type = EVENTLOG_AUDIT_SUCCESS; // // Parameter[0] - User Sid // SepSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, UserSid ); AuditParameters.ParameterCount++; // // Parameter[1] - Subsystem name (if available) // if ( ARGUMENT_PRESENT( Source )) { SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, Source ); } AuditParameters.ParameterCount++; // // Parameter[2] - New handle ID // SepSetParmTypeUlong( AuditParameters, AuditParameters.ParameterCount, Handle ); AuditParameters.ParameterCount++; // // Parameters 3,4 - Operation ID // SepSetParmTypeUlong( AuditParameters, AuditParameters.ParameterCount, OperationId.HighPart ); AuditParameters.ParameterCount++; SepSetParmTypeUlong( AuditParameters, AuditParameters.ParameterCount, OperationId.LowPart ); AuditParameters.ParameterCount++; // // Parameter[5] - Subject's process id // ProcessID = PsProcessAuditId( PsGetCurrentProcess() ); SepSetParmTypeUlong( AuditParameters, AuditParameters.ParameterCount, ProcessID ); AuditParameters.ParameterCount++; SepAdtLogAuditRecord( &AuditParameters ); } } VOID SepAdtObjectReferenceAuditAlarm( IN PLUID OperationId OPTIONAL, IN PVOID Object, IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext, IN ACCESS_MASK DesiredAccess, IN PPRIVILEGE_SET Privileges OPTIONAL, IN BOOLEAN AccessGranted, IN BOOLEAN GenerateAudit, IN BOOLEAN GenerateAlarm ) /*++ Routine Description: description-of-function. This routine will create an SE_ADT_PARAMETERS array organized as follows: Parameter[0] - User Sid Parameter[1] - Subsystem name (if available) Parameter[2] - Object Type Name Parameter[3] - Object Name Parameter[4] - Subject's process id Parameter[5] - Subject's primary authentication ID Parameter[6] - Subject's client authentication ID Parameter[7] - DesiredAccess mask Arguments: GenerateAudit - Indicates if we should generate an audit for this operation. GenerateAlarm - Indicates if we should generate an alarm for this operation. Return Value: return-value - Description of conditions needed to return value. - or - None. --*/ { SE_ADT_PARAMETER_ARRAY AuditParameters; ULONG ObjectTypeIndex; POBJECT_NAME_INFORMATION ObjectNameInformation; PUNICODE_STRING ObjectTypeInformation; PSID UserSid; LUID PrimaryAuthenticationId; LUID ClientAuthenticationId; PTOKEN ClientToken = (PTOKEN)SubjectSecurityContext->ClientToken; PTOKEN PrimaryToken = (PTOKEN)SubjectSecurityContext->PrimaryToken; PAGED_CODE(); if ( ARGUMENT_PRESENT( ClientToken )) { UserSid = SepTokenUserSid( ClientToken ); ClientAuthenticationId = SepTokenAuthenticationId( ClientToken ); } else { UserSid = SepTokenUserSid( PrimaryToken ); } PrimaryAuthenticationId = SepTokenAuthenticationId( PrimaryToken ); // // A completely zero'd entry will be interpreted // as a "null string" or not supplied parameter. // // Initializing the entire array up front will allow // us to avoid filling in each not supplied entry. // RtlZeroMemory ( (PVOID) &AuditParameters, sizeof( AuditParameters ) ); ASSERT( SeAdtParmTypeNone == 0 ); AuditParameters.CategoryId = SE_CATEGID_DETAILED_TRACKING; AuditParameters.AuditId = SE_AUDITID_INDIRECT_REFERENCE; AuditParameters.ParameterCount = 8; if ( AccessGranted ) { AuditParameters.Type = EVENTLOG_AUDIT_SUCCESS; } else { AuditParameters.Type = EVENTLOG_AUDIT_FAILURE; } // // Obtain the object name and object type name from the // object. // ObjectNameInformation = SepQueryNameString( Object ); ObjectTypeInformation = SepQueryTypeString( Object ); // // Parameter[0] - User Sid // SepSetParmTypeSid( AuditParameters, 0, UserSid ); // // Parameter[1] - Subsystem name (if available) // SepSetParmTypeString( AuditParameters, 1, &SeSubsystemName ); // // Parameter[2] - Object Type Name // if ( ObjectTypeInformation != NULL ) { SepSetParmTypeString( AuditParameters, 2, ObjectTypeInformation ); ObjectTypeIndex = 2; } // // Parameter[3] - Object Name // if ( ObjectNameInformation != NULL ) { SepSetParmTypeString( AuditParameters, 3, &ObjectNameInformation->Name ); } // // Parameter[4] - Subject's process id // // // BUGWARNING: The process Id is currently unavailable. // SepSetParmTypeUlong( AuditParameters, 4, SubjectSecurityContext->ProcessAuditId ); // // Parameter[5] - Subject's primary authentication ID // SepSetParmTypeLogonId( AuditParameters, 5, PrimaryAuthenticationId ); // // Parameter[6] - Subject's client authentication ID // if ( ARGUMENT_PRESENT( ClientToken )) { SepSetParmTypeLogonId( AuditParameters, 6, ClientAuthenticationId ); } else { SepSetParmTypeNoLogon( AuditParameters, 6 ); } // // Parameter[7] - DesiredAccess mask // SepSetParmTypeAccessMask( AuditParameters, 7, DesiredAccess, ObjectTypeIndex ); SepAdtLogAuditRecord( &AuditParameters ); if ( ObjectNameInformation != NULL ) { ExFreePool( ObjectNameInformation ); } if ( ObjectTypeInformation != NULL ) { ExFreePool( ObjectTypeInformation ); } } //VOID //SepAdtCreateInstanceAuditAlarm( // IN PLUID OperationID, // IN PVOID Object, // IN PSID UserSid, // IN LUID AuthenticationId, // IN ACCESS_MASK DesiredAccess, // IN PPRIVILEGE_SET Privileges OPTIONAL, // IN BOOLEAN AccessGranted, // IN BOOLEAN GenerateAudit, // IN BOOLEAN GenerateAlarm // ) // ///*++ // //Routine Description: // // description-of-function. // //Arguments: // // GenerateAudit - Indicates if we should generate an audit for this operation. // // GenerateAlarm - Indicates if we should generate an alarm for this operation. // // //Return Value: // // return-value - Description of conditions needed to return value. - or - // None. // //--*/ // //{ // POLICY_AUDIT_CREATE_INSTANCE AuditCreateInstance; // // UNREFERENCED_PARAMETER( GenerateAudit ); // UNREFERENCED_PARAMETER( GenerateAlarm ); // // // // // BUGWARNING Must obtain the object type object from the passed // // object // // // // AuditCreateInstance.AccessGranted = AccessGranted; // AuditCreateInstance.ObjectTypeName = NULL; // AuditCreateInstance.OperationId = *OperationID; // AuditCreateInstance.UserSid = UserSid; // AuditCreateInstance.AuthenticationId = AuthenticationId; // //// SepAdtLogAuditRecord( AuditEventCreateInstance, &AuditCreateInstance ); // // return; //} // //VOID //SeShutdownAuditAlarm( // VOID // ) // ///*++ // //Routine Description: // // This routine will can a shutdown audit record to be generated. // // There must be a forced delay after this routine is called to ensure // that the generated audit record actually makes it to disk. // //Arguments: // // None // //Return Value: // // None. // //--*/ // //{ // SECURITY_SUBJECT_CONTEXT SubjectSecurityContext; // SE_ADT_PARAMETER_ARRAY AuditParameters; // UNICODE_STRING SubsystemName; // PSID UserSid; // // // // // Make sure we're auditing shutdown events. // // // // if ( SepAdtAuditThisEvent( AuditEventShutdown, NULL )) { // // SeCaptureSubjectContext( &SubjectSecurityContext ); // // // // // // A completely zero'd entry will be interpreted // // as a "null string" or not supplied parameter. // // // // Initializing the entire array up front will allow // // us to avoid filling in each not supplied entry. // // // // RtlZeroMemory ( // (PVOID) &AuditParameters, // sizeof( AuditParameters ) // ); // // ASSERT( SeAdtParmTypeNone == 0 ); // // AuditParameters.CategoryId = SE_CATEGID_SYSTEM; // AuditParameters.AuditId = SE_AUDITID_SYSTEM_SHUTDOWN; // AuditParameters.ParameterCount = 2; // // UserSid = SepTokenUserSid(EffectiveToken( &SubjectSecurityContext )); // // // RtlInitUnicodeString( &SubsystemName, L"Security" ); // // // // // // Parameter[0] - User Sid // // // // SepSetParmTypeSid( AuditParameters, 0, UserSid ); // // // // // // Parameter[1] - Subsystem name (if available) // // // // SepSetParmTypeString( AuditParameters, 1, &SubsystemName ); // // // SepAdtLogAuditRecord( &AuditParameters ); // // SeReleaseSubjectContext( &SubjectSecurityContext ); // // } // //} // // BOOLEAN // SepAdtAuditThisEvent( // IN POLICY_AUDIT_EVENT_TYPE AuditType, // IN PBOOLEAN AccessGranted OPTIONAL // ) // // /*++ // // Routine Description: // // This routine will return whether or not to generate an audit log // record for the passed event type. // // Arguments: // // AuditType - The type of event to be audited. // // AccessGranted - An optional flag indicating whether or not // the operation was successful. This does not all apply to all // types of audit events. // // Note that a pointer to the flag is passed rather than the // flag itself, so that we may tell whether or not the argument // is present. // // Return Value: // // Flag indicating whether or not to proceed with the audit. // // --*/ // // { // PAGED_CODE(); // // if (SepAdtAuditingEnabled) { // // if ( ARGUMENT_PRESENT( AccessGranted )) { // // if ((SeAuditingState[AuditType].AuditOnSuccess && *AccessGranted) || // SeAuditingState[AuditType].AuditOnFailure && !(*AccessGranted)) { // // return( TRUE ); // // } // } // } // // return( FALSE ); // } POBJECT_NAME_INFORMATION SepQueryNameString( IN PVOID Object ) /*++ Routine Description: Takes a pointer to an object and returns the name of the object. Arguments: Object - a pointer to an object. Return Value: A pointer to a buffer containing a POBJECT_NAME_INFORMATION structure containing the name of the object. The string is allocated out of paged pool and should be freed by the caller. NULL may also be returned. --*/ { NTSTATUS Status; ULONG ReturnLength = 0; POBJECT_NAME_INFORMATION ObjectNameInfo = NULL; PUNICODE_STRING ObjectName = NULL; PAGED_CODE(); Status = ObQueryNameString( Object, ObjectNameInfo, 0, &ReturnLength ); if ( Status == STATUS_INFO_LENGTH_MISMATCH ) { ObjectNameInfo = ExAllocatePoolWithTag( PagedPool, ReturnLength, 'nOeS' ); if ( ObjectNameInfo != NULL ) { Status = ObQueryNameString( Object, ObjectNameInfo, ReturnLength, &ReturnLength ); if ( NT_SUCCESS( Status )) { if (ObjectNameInfo->Name.Length != 0) { return( ObjectNameInfo ); } else { ExFreePool( ObjectNameInfo ); return( NULL ); } } } } return( NULL ); } PUNICODE_STRING SepQueryTypeString( IN PVOID Object ) /*++ Routine Description: Takes a pointer to an object and returns the type of the object. Arguments: Object - a pointer to an object. Return Value: A pointer to a UNICODE_STRING that contains the name of the object type. The string is allocated out of paged pool and should be freed by the caller. NULL may also be returned. --*/ { NTSTATUS Status; PUNICODE_STRING TypeName = NULL; ULONG ReturnLength; PAGED_CODE(); Status = ObQueryTypeName( Object, TypeName, 0, &ReturnLength ); if ( Status == STATUS_INFO_LENGTH_MISMATCH ) { TypeName = ExAllocatePoolWithTag( PagedPool, ReturnLength, 'nTeS' ); if ( TypeName != NULL ) { Status = ObQueryTypeName( Object, TypeName, ReturnLength, &ReturnLength ); if ( NT_SUCCESS( Status )) { return( TypeName ); } } } return( NULL ); } VOID SeAuditProcessCreation( PEPROCESS Process, PEPROCESS Parent ) /*++ Routine Description: Audits the creation of a process. It is the caller's responsibility to determine if process auditing is in progress. Arguments: Process - Points to the new process object. Parent - Points to the creator (parent) process object. Return Value: None. --*/ { ANSI_STRING Ansi; LUID UserAuthenticationId; NTSTATUS Status; PSID UserSid; SECURITY_SUBJECT_CONTEXT SubjectSecurityContext; SE_ADT_PARAMETER_ARRAY AuditParameters; UNICODE_STRING ImageFileName; PAGED_CODE(); RtlInitAnsiString( &Ansi, Process->ImageFileName ); Status = RtlAnsiStringToUnicodeString( &ImageFileName, &Ansi, TRUE ); // // Not enough memory to complete the audit, return. // if ( !NT_SUCCESS( Status )) { return; } SeCaptureSubjectContext( &SubjectSecurityContext ); RtlZeroMemory ( (PVOID) &AuditParameters, sizeof( AuditParameters ) ); ASSERT( SeAdtParmTypeNone == 0 ); AuditParameters.CategoryId = SE_CATEGID_DETAILED_TRACKING; AuditParameters.AuditId = SE_AUDITID_PROCESS_CREATED; AuditParameters.ParameterCount = 0; AuditParameters.Type = EVENTLOG_AUDIT_SUCCESS; // // Use the primary token here, because that's what's going to show up // when the created process exits. // UserSid = SepTokenUserSid( SubjectSecurityContext.PrimaryToken ); UserAuthenticationId = SepTokenAuthenticationId( SubjectSecurityContext.PrimaryToken ); // // Fill in the AuditParameters structure. // SepSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, UserSid ); AuditParameters.ParameterCount++; SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, &SeSubsystemName ); AuditParameters.ParameterCount++; SepSetParmTypeUlong( AuditParameters, AuditParameters.ParameterCount, Process ); AuditParameters.ParameterCount++; SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, &ImageFileName ); AuditParameters.ParameterCount++; SepSetParmTypeUlong( AuditParameters, AuditParameters.ParameterCount, Parent ); AuditParameters.ParameterCount++; SepSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, UserAuthenticationId ); AuditParameters.ParameterCount++; SepAdtLogAuditRecord( &AuditParameters ); SeReleaseSubjectContext( &SubjectSecurityContext ); RtlFreeUnicodeString( &ImageFileName ); return; } VOID SeAuditHandleDuplication( PVOID SourceHandle, PVOID NewHandle, PEPROCESS SourceProcess, PEPROCESS TargetProcess ) /*++ Routine Description: This routine generates a handle duplication audit. It is up to the caller to determine if this routine should be called or not. Arguments: SourceHandle - Original handle NewHandle - New handle SourceProcess - Process containing SourceHandle TargetProcess - Process containing NewHandle Return Value: None. --*/ { SE_ADT_PARAMETER_ARRAY AuditParameters; SECURITY_SUBJECT_CONTEXT SubjectSecurityContext; PSID UserSid; PAGED_CODE(); SeCaptureSubjectContext( &SubjectSecurityContext ); UserSid = SepTokenUserSid( EffectiveToken( &SubjectSecurityContext )); RtlZeroMemory ( (PVOID) &AuditParameters, sizeof( AuditParameters ) ); ASSERT( SeAdtParmTypeNone == 0 ); AuditParameters.CategoryId = SE_CATEGID_DETAILED_TRACKING; AuditParameters.AuditId = SE_AUDITID_DUPLICATE_HANDLE; AuditParameters.ParameterCount = 0; AuditParameters.Type = EVENTLOG_AUDIT_SUCCESS; SepSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, UserSid ); AuditParameters.ParameterCount++; SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, &SeSubsystemName ); AuditParameters.ParameterCount++; SepSetParmTypeUlong( AuditParameters, AuditParameters.ParameterCount, SourceHandle ); AuditParameters.ParameterCount++; SepSetParmTypeUlong( AuditParameters, AuditParameters.ParameterCount, PsProcessAuditId( SourceProcess )); AuditParameters.ParameterCount++; SepSetParmTypeUlong( AuditParameters, AuditParameters.ParameterCount, NewHandle ); AuditParameters.ParameterCount++; SepSetParmTypeUlong( AuditParameters, AuditParameters.ParameterCount, PsProcessAuditId( TargetProcess )); AuditParameters.ParameterCount++; SepAdtLogAuditRecord( &AuditParameters ); SeReleaseSubjectContext( &SubjectSecurityContext ); } VOID SeAuditProcessExit( PEPROCESS Process ) /*++ Routine Description: Audits the exit of a process. The caller is responsible for determining if this should be called. Arguments: Process - Pointer to the process object that is exiting. Return Value: None. --*/ { PTOKEN Token; SE_ADT_PARAMETER_ARRAY AuditParameters; PSID UserSid; LUID LogonId; PAGED_CODE(); Token = (PTOKEN)Process->Token; UserSid = SepTokenUserSid( Token ); LogonId = SepTokenAuthenticationId( Token ); RtlZeroMemory ( (PVOID) &AuditParameters, sizeof( AuditParameters ) ); ASSERT( SeAdtParmTypeNone == 0 ); AuditParameters.CategoryId = SE_CATEGID_DETAILED_TRACKING; AuditParameters.AuditId = SE_AUDITID_PROCESS_EXIT; AuditParameters.ParameterCount = 0; AuditParameters.Type = EVENTLOG_AUDIT_SUCCESS; SepSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, UserSid ); AuditParameters.ParameterCount++; SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, &SeSubsystemName ); AuditParameters.ParameterCount++; SepSetParmTypeUlong( AuditParameters, AuditParameters.ParameterCount, PsProcessAuditId( Process )); AuditParameters.ParameterCount++; SepSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, LogonId ); AuditParameters.ParameterCount++; SepAdtLogAuditRecord( &AuditParameters ); } VOID SepAdtGenerateDiscardAudit( VOID ) /*++ Routine Description: Generates an 'audits discarded' audit. Arguments: none Return Value: None. --*/ { SE_ADT_PARAMETER_ARRAY AuditParameters; PSID UserSid; PAGED_CODE(); UserSid = SeLocalSystemSid; RtlZeroMemory ( (PVOID) &AuditParameters, sizeof( AuditParameters ) ); ASSERT( SeAdtParmTypeNone == 0 ); AuditParameters.CategoryId = SE_CATEGID_SYSTEM; AuditParameters.AuditId = SE_AUDITID_AUDITS_DISCARDED; AuditParameters.ParameterCount = 0; AuditParameters.Type = EVENTLOG_AUDIT_SUCCESS; SepSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, UserSid ); AuditParameters.ParameterCount++; SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, &SeSubsystemName ); AuditParameters.ParameterCount++; SepSetParmTypeUlong( AuditParameters, AuditParameters.ParameterCount, SepAdtCountEventsDiscarded ); AuditParameters.ParameterCount++; SepAdtLogAuditRecord( &AuditParameters ); }