diff options
Diffstat (limited to '')
-rw-r--r-- | private/ntos/se/sepaudit.c | 2629 |
1 files changed, 2629 insertions, 0 deletions
diff --git a/private/ntos/se/sepaudit.c b/private/ntos/se/sepaudit.c new file mode 100644 index 000000000..6fb6fc17d --- /dev/null +++ b/private/ntos/se/sepaudit.c @@ -0,0 +1,2629 @@ +/*++ + +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 <nt.h> +#include <ntlsa.h> +#include <msaudite.h> +#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 ); +} |