3721 lines
104 KiB
C
3721 lines
104 KiB
C
|
||
/*++
|
||
|
||
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 "pch.h"
|
||
|
||
#pragma hdrstop
|
||
|
||
#include <msaudite.h>
|
||
#include <string.h>
|
||
|
||
|
||
#ifdef ALLOC_PRAGMA
|
||
#pragma alloc_text(PAGE,SepAdtPrivilegeObjectAuditAlarm)
|
||
#pragma alloc_text(PAGE,SepAdtPrivilegedServiceAuditAlarm)
|
||
#pragma alloc_text(PAGE,SepAdtOpenObjectAuditAlarm)
|
||
#pragma alloc_text(PAGE,SepAdtOpenObjectForDeleteAuditAlarm)
|
||
#pragma alloc_text(PAGE,SepAdtCloseObjectAuditAlarm)
|
||
#pragma alloc_text(PAGE,SepAdtDeleteObjectAuditAlarm)
|
||
#pragma alloc_text(PAGE,SepAdtObjectReferenceAuditAlarm)
|
||
#pragma alloc_text(PAGE,SepQueryNameString)
|
||
#pragma alloc_text(PAGE,SepQueryTypeString)
|
||
#pragma alloc_text(PAGE,SeAuditProcessCreation)
|
||
#pragma alloc_text(PAGE,SeAuditHandleDuplication)
|
||
#pragma alloc_text(PAGE,SeAuditProcessExit)
|
||
#pragma alloc_text(PAGE,SeAuditSystemTimeChange)
|
||
#pragma alloc_text(PAGE,SepAdtGenerateDiscardAudit)
|
||
#pragma alloc_text(PAGE,SeLocateProcessImageName)
|
||
#pragma alloc_text(PAGE,SeInitializeProcessAuditName)
|
||
#pragma alloc_text(PAGE,SepAuditAssignPrimaryToken)
|
||
#pragma alloc_text(PAGE,SeAuditLPCInvalidUse)
|
||
#pragma alloc_text(PAGE,SeAuditHardLinkCreation)
|
||
#pragma alloc_text(PAGE,SeOperationAuditAlarm)
|
||
#pragma alloc_text(PAGE,SeDetailedAuditingWithToken)
|
||
#pragma alloc_text(PAGE,SepAdtAuditThisEventWithContext)
|
||
#endif
|
||
|
||
|
||
#define SepSetParmTypeSid( AuditParameters, Index, Sid ) \
|
||
{ \
|
||
(AuditParameters).Parameters[(Index)].Type = SeAdtParmTypeSid; \
|
||
(AuditParameters).Parameters[(Index)].Length = SeLengthSid( (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 SepSetParmTypeHexUlong( AuditParameters, Index, Ulong ) \
|
||
{ \
|
||
(AuditParameters).Parameters[(Index)].Type = SeAdtParmTypeHexUlong; \
|
||
(AuditParameters).Parameters[(Index)].Length = sizeof( (Ulong) ); \
|
||
(AuditParameters).Parameters[(Index)].Data[0] = (ULONG)(Ulong); \
|
||
}
|
||
|
||
#define SepSetParmTypePtr( AuditParameters, Index, Ptr ) \
|
||
{ \
|
||
(AuditParameters).Parameters[(Index)].Type = SeAdtParmTypePtr; \
|
||
(AuditParameters).Parameters[(Index)].Length = sizeof( ULONG_PTR ); \
|
||
(AuditParameters).Parameters[(Index)].Data[0] = (ULONG_PTR)(Ptr); \
|
||
}
|
||
|
||
#define SepSetParmTypeNoLogon( AuditParameters, Index ) \
|
||
{ \
|
||
(AuditParameters).Parameters[(Index)].Type = SeAdtParmTypeNoLogonId; \
|
||
}
|
||
|
||
#define SepSetParmTypeLogonId( AuditParameters, Index, LogonId ) \
|
||
{ \
|
||
LUID * TmpLuid; \
|
||
\
|
||
(AuditParameters).Parameters[(Index)].Type = SeAdtParmTypeLogonId; \
|
||
(AuditParameters).Parameters[(Index)].Length = sizeof( (LogonId) ); \
|
||
TmpLuid = (LUID *)(&(AuditParameters).Parameters[(Index)].Data[0]); \
|
||
*TmpLuid = (LogonId); \
|
||
}
|
||
|
||
#define SepSetParmTypeAccessMask( AuditParameters, Index, AccessMask, ObjectTypeIndex ) \
|
||
{ \
|
||
ASSERT( (ObjectTypeIndex < Index) && L"SepSetParmTypeAccessMask" ); \
|
||
(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 ) \
|
||
{ \
|
||
ASSERT( Privileges->PrivilegeCount <= SEP_MAX_PRIVILEGE_COUNT ); \
|
||
(AuditParameters).Parameters[(Index)].Type = SeAdtParmTypePrivs; \
|
||
(AuditParameters).Parameters[(Index)].Length = SepPrivilegeSetSize( (Privileges) ); \
|
||
(AuditParameters).Parameters[(Index)].Address = (Privileges); \
|
||
}
|
||
|
||
#define SepSetParmTypeObjectTypes( AuditParameters, Index, ObjectTypes, ObjectTypeCount, ObjectTypeIndex ) \
|
||
{ \
|
||
(AuditParameters).Parameters[(Index)].Type = SeAdtParmTypeObjectTypes; \
|
||
(AuditParameters).Parameters[(Index)].Length = sizeof( SE_ADT_OBJECT_TYPE ) * (ObjectTypeCount);\
|
||
(AuditParameters).Parameters[(Index)].Address = (ObjectTypes); \
|
||
(AuditParameters).Parameters[(Index)].Data[1] = (ObjectTypeIndex); \
|
||
}
|
||
|
||
|
||
#define SepSetParmTypeTime( AuditParameters, Index, Time ) \
|
||
{ \
|
||
(AuditParameters).Parameters[(Index)].Type = SeAdtParmTypeTime; \
|
||
(AuditParameters).Parameters[(Index)].Length = sizeof( (Time) ); \
|
||
*((PLARGE_INTEGER)(&(AuditParameters).Parameters[(Index)].Data[0])) = Time; \
|
||
}
|
||
|
||
BOOLEAN
|
||
FASTCALL
|
||
SeDetailedAuditingWithToken(
|
||
IN PACCESS_TOKEN AccessToken OPTIONAL
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description
|
||
|
||
This routine computes whether or not a detailed tracking audit should be
|
||
generated for a given token or context. If no token is passed then the
|
||
current effective token will be captured.
|
||
|
||
The caller is responsible for referencing and dereferencing AccessToken.
|
||
|
||
Arguments
|
||
|
||
AccessToken - token for which to query audit policy
|
||
|
||
Return Value
|
||
|
||
BOOLEAN.
|
||
|
||
--*/
|
||
|
||
{
|
||
PTOKEN Token;
|
||
ULONG Mask;
|
||
SECURITY_SUBJECT_CONTEXT LocalSecurityContext;
|
||
BOOLEAN AuditThisEvent;
|
||
|
||
PAGED_CODE();
|
||
|
||
if (SepTokenPolicyCounter[AuditCategoryDetailedTracking] == 0) {
|
||
|
||
return SeAuditingState[AuditCategoryDetailedTracking].AuditOnSuccess;
|
||
}
|
||
|
||
//
|
||
// If no token was passed in and there exists tokens in the system with
|
||
// detailed tracking per user policy settings then capture the context.
|
||
//
|
||
|
||
if (ARGUMENT_PRESENT(AccessToken)) {
|
||
|
||
Token = (PTOKEN)AccessToken;
|
||
|
||
} else {
|
||
|
||
SeCaptureSubjectContext( &LocalSecurityContext );
|
||
Token = EffectiveToken( &LocalSecurityContext );
|
||
}
|
||
|
||
//
|
||
// Audit if the token specifies success auditing (there is not a detailed tracking failure concept)
|
||
// or if global audit policy specifies detailed tracking auditing and this token is not excluded.
|
||
//
|
||
|
||
Mask = Token->AuditPolicy.PolicyElements.DetailedTracking;
|
||
|
||
if ( (Mask & TOKEN_AUDIT_SUCCESS_INCLUDE) ||
|
||
(SeAuditingState[AuditCategoryDetailedTracking].AuditOnSuccess && (0 == (Mask & TOKEN_AUDIT_SUCCESS_EXCLUDE))) ) {
|
||
|
||
AuditThisEvent = TRUE;
|
||
|
||
} else {
|
||
|
||
AuditThisEvent = FALSE;
|
||
}
|
||
|
||
if (AccessToken == NULL) {
|
||
|
||
//
|
||
// if AccessToken is NULL then we had to capture the context. Release
|
||
// it.
|
||
//
|
||
|
||
SeReleaseSubjectContext( &LocalSecurityContext );
|
||
}
|
||
|
||
return AuditThisEvent;
|
||
}
|
||
|
||
//
|
||
// ISSUE-2002/03/07-kumarp : the semantics of AccessGranted/AccessDenied
|
||
// is confusing. The function should really get success/failure flag as param
|
||
// to return the right setting.
|
||
//
|
||
// Further, these functions should be rearranged so that the inner-most
|
||
// function is SepAdtAuditThisEventWithToken and everything else ends up
|
||
// calling it with right parameters
|
||
//
|
||
// Longhorn bug# 595575
|
||
//
|
||
|
||
|
||
BOOLEAN
|
||
SepAdtAuditThisEventWithContext(
|
||
IN POLICY_AUDIT_EVENT_TYPE Category,
|
||
IN BOOLEAN AccessGranted,
|
||
IN BOOLEAN AccessDenied,
|
||
IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext OPTIONAL
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description
|
||
|
||
Determines if an audit should be generated based upon current policy
|
||
settings and the per user audit policy set in the effective token of
|
||
the context. If no context is passed in then the current context is
|
||
captured and examined.
|
||
|
||
Arguments
|
||
|
||
Category - the category for which we determine whether or not
|
||
to generate an audit
|
||
|
||
AccessGranted - whether or not access was granted
|
||
|
||
AccessDenied - whether or not access was denied
|
||
|
||
SubjectSecurityContext - the context to query for per user settings
|
||
|
||
Return Value
|
||
|
||
BOOLEAN.
|
||
|
||
--*/
|
||
|
||
{
|
||
ULONG Mask;
|
||
PTOKEN Token;
|
||
SECURITY_SUBJECT_CONTEXT LocalSecurityContext;
|
||
PSECURITY_SUBJECT_CONTEXT pLocalSecurityContext;
|
||
BOOLEAN AuditThisEvent = FALSE;
|
||
|
||
PAGED_CODE();
|
||
|
||
ASSERT((!(AccessGranted && AccessDenied)) && "SepAdtAuditThisEventWithContext");
|
||
|
||
|
||
if ((SeAuditingState[Category].AuditOnSuccess && AccessGranted) ||
|
||
(SeAuditingState[Category].AuditOnFailure && AccessDenied)) {
|
||
|
||
AuditThisEvent = TRUE;
|
||
|
||
} else {
|
||
|
||
AuditThisEvent = FALSE;
|
||
}
|
||
|
||
if (SepTokenPolicyCounter[Category] == 0) {
|
||
|
||
return AuditThisEvent;
|
||
}
|
||
|
||
//
|
||
// We cannot decide quickly whether or not to audit (there exist tokens
|
||
// with per user policy settings), so continue with
|
||
// examining the token's policy.
|
||
//
|
||
|
||
if (!ARGUMENT_PRESENT(SubjectSecurityContext)) {
|
||
|
||
pLocalSecurityContext = &LocalSecurityContext;
|
||
SeCaptureSubjectContext( pLocalSecurityContext );
|
||
|
||
} else {
|
||
|
||
pLocalSecurityContext = SubjectSecurityContext;
|
||
}
|
||
|
||
Token = EffectiveToken( pLocalSecurityContext );
|
||
|
||
//
|
||
// Now we have to check the token audit mask because the token may
|
||
// override the policy and say 'do not audit,' even though the array claims we
|
||
// must (or vice versa)
|
||
//
|
||
|
||
switch (Category) {
|
||
|
||
case AuditCategorySystem:
|
||
Mask = Token->AuditPolicy.PolicyElements.System;
|
||
break;
|
||
case AuditCategoryLogon:
|
||
Mask = Token->AuditPolicy.PolicyElements.Logon;
|
||
break;
|
||
case AuditCategoryObjectAccess:
|
||
Mask = Token->AuditPolicy.PolicyElements.ObjectAccess;
|
||
break;
|
||
case AuditCategoryPrivilegeUse:
|
||
Mask = Token->AuditPolicy.PolicyElements.PrivilegeUse;
|
||
break;
|
||
case AuditCategoryDetailedTracking:
|
||
Mask = Token->AuditPolicy.PolicyElements.DetailedTracking;
|
||
break;
|
||
case AuditCategoryPolicyChange:
|
||
Mask = Token->AuditPolicy.PolicyElements.PolicyChange;
|
||
break;
|
||
case AuditCategoryAccountManagement:
|
||
Mask = Token->AuditPolicy.PolicyElements.AccountManagement;
|
||
break;
|
||
case AuditCategoryDirectoryServiceAccess:
|
||
Mask = Token->AuditPolicy.PolicyElements.DirectoryServiceAccess;
|
||
break;
|
||
case AuditCategoryAccountLogon:
|
||
Mask = Token->AuditPolicy.PolicyElements.AccountLogon;
|
||
break;
|
||
default:
|
||
ASSERT(FALSE && "Illegal audit category");
|
||
Mask = 0;
|
||
break;
|
||
}
|
||
|
||
if (Mask) {
|
||
|
||
//
|
||
// If granted and the token is marked for success_include OR
|
||
// if not granted and token is marked for failure_include then
|
||
// audit the event.
|
||
//
|
||
|
||
if (( AccessGranted && (Mask & TOKEN_AUDIT_SUCCESS_INCLUDE) ) ||
|
||
( AccessDenied && (Mask & TOKEN_AUDIT_FAILURE_INCLUDE) )) {
|
||
|
||
AuditThisEvent = TRUE;
|
||
}
|
||
|
||
//
|
||
// If granted and the token is marked for success_exclude OR
|
||
// if not granted and token is marked for failure_exclude then
|
||
// do not audit the event.
|
||
//
|
||
|
||
else if (( AccessGranted && (Mask & TOKEN_AUDIT_SUCCESS_EXCLUDE) ) ||
|
||
( AccessDenied && (Mask & TOKEN_AUDIT_FAILURE_EXCLUDE) )) {
|
||
|
||
AuditThisEvent = FALSE;
|
||
|
||
}
|
||
}
|
||
|
||
if (!ARGUMENT_PRESENT(SubjectSecurityContext)) {
|
||
|
||
SeReleaseSubjectContext( pLocalSecurityContext );
|
||
}
|
||
|
||
return AuditThisEvent;
|
||
}
|
||
|
||
|
||
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 routine will create an SE_ADT_PARAMETERS array organized as follows:
|
||
|
||
Parameter[0] - User Sid
|
||
|
||
Parameter[1] - Subsystem name (if available)
|
||
|
||
Parameter[2] - Subsystem name (if available)
|
||
|
||
Parameter[3] - New handle ID
|
||
|
||
Parameter[4] - Subject's process id
|
||
|
||
Parameter[5] - Subject's primary authentication ID
|
||
|
||
Parameter[6] - Subject's client authentication ID
|
||
|
||
Parameter[7] - 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;
|
||
PUNICODE_STRING SubsystemName;
|
||
|
||
PAGED_CODE();
|
||
|
||
UNREFERENCED_PARAMETER( DesiredAccess );
|
||
|
||
//
|
||
// Determine if we are auditing the use of privileges
|
||
//
|
||
|
||
if ( SepAdtAuditThisEventWithContext( AuditCategoryPrivilegeUse, AccessGranted, !AccessGranted, NULL ) &&
|
||
SepFilterPrivilegeAudits( CapturedPrivileges )) {
|
||
|
||
if ( ARGUMENT_PRESENT( ClientToken )) {
|
||
|
||
CapturedUserSid = SepTokenUserSid( ClientToken );
|
||
|
||
} else {
|
||
|
||
CapturedUserSid = SepTokenUserSid( PrimaryToken );
|
||
}
|
||
|
||
if ( RtlEqualSid( SeLocalSystemSid, CapturedUserSid )) {
|
||
|
||
return (FALSE);
|
||
}
|
||
|
||
PrimaryAuthenticationId = SepTokenAuthenticationId( PrimaryToken );
|
||
|
||
if ( !ARGUMENT_PRESENT( CapturedSubsystemName )) {
|
||
|
||
SubsystemName = (PUNICODE_STRING)&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_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
|
||
//
|
||
|
||
SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, SubsystemName );
|
||
|
||
AuditParameters.ParameterCount++;
|
||
|
||
//
|
||
// Parameter[2] - Subsystem name (if available)
|
||
//
|
||
|
||
if (ARGUMENT_PRESENT( CapturedSubsystemName )) {
|
||
|
||
SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, CapturedSubsystemName );
|
||
}
|
||
|
||
AuditParameters.ParameterCount++;
|
||
|
||
//
|
||
// Parameter[3] - New handle ID
|
||
//
|
||
|
||
SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, HandleId );
|
||
|
||
AuditParameters.ParameterCount++;
|
||
|
||
//
|
||
// Parameter[4] - Subject's process id
|
||
//
|
||
|
||
SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, ProcessId );
|
||
|
||
AuditParameters.ParameterCount++;
|
||
|
||
//
|
||
// Parameter[5] - Subject's primary authentication ID
|
||
//
|
||
|
||
SepSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, PrimaryAuthenticationId );
|
||
|
||
AuditParameters.ParameterCount++;
|
||
|
||
//
|
||
// Parameter[6] - Subject's client authentication ID
|
||
//
|
||
|
||
if ( ARGUMENT_PRESENT( ClientToken )) {
|
||
|
||
ClientAuthenticationId = SepTokenAuthenticationId( ClientToken );
|
||
SepSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, ClientAuthenticationId );
|
||
|
||
} else {
|
||
|
||
SepSetParmTypeNoLogon( AuditParameters, AuditParameters.ParameterCount );
|
||
}
|
||
|
||
AuditParameters.ParameterCount++;
|
||
|
||
//
|
||
// Parameter[7] - Privileges used for open
|
||
//
|
||
|
||
//
|
||
// Longhorn-ISSUE-2002/02/21-kumarp : remove the NULL check after fixing bug# 551545
|
||
//
|
||
if ( (CapturedPrivileges != NULL) && (CapturedPrivileges->PrivilegeCount > 0) ) {
|
||
|
||
SepSetParmTypePrivileges( AuditParameters, AuditParameters.ParameterCount, CapturedPrivileges );
|
||
}
|
||
|
||
AuditParameters.ParameterCount++;
|
||
|
||
SepAdtLogAuditRecord( &AuditParameters );
|
||
|
||
return ( TRUE );
|
||
|
||
}
|
||
|
||
return ( FALSE );
|
||
}
|
||
|
||
|
||
VOID
|
||
SepAdtPrivilegedServiceAuditAlarm (
|
||
IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext,
|
||
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 routine will create an SE_ADT_PARAMETERS array organized as follows:
|
||
|
||
Parameter[0] - User Sid
|
||
|
||
Parameter[1] - Subsystem name (if available)
|
||
|
||
Parameter[2] - object server (same as Subsystem name)
|
||
|
||
Parameter[3] - Subject's primary authentication ID
|
||
|
||
Parameter[4] - Subject's client authentication ID
|
||
|
||
Parameter[5] - Privileges used for open
|
||
|
||
Arguments:
|
||
|
||
SubjectSecurityContext - The subject security context representing
|
||
the caller of the system service.
|
||
|
||
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" 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 ( !(SepAdtAuditThisEventWithContext( AuditCategoryPrivilegeUse, AccessGranted, !AccessGranted, SubjectSecurityContext ) &&
|
||
SepFilterPrivilegeAudits( CapturedPrivileges ))) {
|
||
|
||
return;
|
||
}
|
||
|
||
|
||
if ( ARGUMENT_PRESENT( ClientToken )) {
|
||
|
||
CapturedUserSid = SepTokenUserSid( ClientToken );
|
||
|
||
} else {
|
||
|
||
CapturedUserSid = SepTokenUserSid( PrimaryToken );
|
||
}
|
||
|
||
PrimaryAuthenticationId = SepTokenAuthenticationId( PrimaryToken );
|
||
|
||
if ( !ARGUMENT_PRESENT( CapturedSubsystemName )) {
|
||
|
||
SubsystemName = (PUNICODE_STRING)&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
|
||
//
|
||
|
||
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 )) {
|
||
|
||
ClientAuthenticationId = SepTokenAuthenticationId( ClientToken );
|
||
SepSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, ClientAuthenticationId );
|
||
|
||
} else {
|
||
|
||
SepSetParmTypeNoLogon( AuditParameters, AuditParameters.ParameterCount );
|
||
}
|
||
|
||
AuditParameters.ParameterCount++;
|
||
|
||
|
||
//
|
||
// Parameter[5] - Privileges used for open
|
||
//
|
||
|
||
|
||
//
|
||
// Longhorn-ISSUE-2002/02/21-kumarp : remove the NULL check after fixing bug# 551690
|
||
//
|
||
|
||
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 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 AccessGranted,
|
||
IN HANDLE ProcessID,
|
||
IN POLICY_AUDIT_EVENT_TYPE AuditType,
|
||
IN PIOBJECT_TYPE_LIST ObjectTypeList OPTIONAL,
|
||
IN ULONG ObjectTypeListLength,
|
||
IN PACCESS_MASK GrantedAccessArray OPTIONAL
|
||
)
|
||
|
||
/*++
|
||
|
||
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 image file name
|
||
|
||
Parameter[8] - Subject's primary authentication ID
|
||
|
||
Parameter[9] - Subject's client authentication ID
|
||
|
||
Parameter[10] - DesiredAccess mask
|
||
|
||
Parameter[11] - Privileges used for open
|
||
|
||
Parameter[12] - Guid/Level/AccessMask of objects/property sets/properties accesses.
|
||
|
||
Parameter[13] - Number of restricted SIDs in the token
|
||
|
||
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.
|
||
|
||
AuditType - Specifies the type of audit to be generated. Valid values
|
||
are: AuditCategoryObjectAccess and AuditCategoryDirectoryServiceAccess.
|
||
|
||
ObjectTypeList - Supplies a list of GUIDs representing the object (and
|
||
sub-objects) being accessed.
|
||
|
||
ObjectTypeListLength - Specifies the number of elements in the ObjectTypeList.
|
||
|
||
GrantedAccessArray - If non NULL, specifies an array of access mask granted
|
||
to each object in ObjectTypeList.
|
||
|
||
Return Value:
|
||
|
||
Returns TRUE if audit is generated, FALSE otherwise.
|
||
|
||
--*/
|
||
|
||
{
|
||
SE_ADT_PARAMETER_ARRAY AuditParameters;
|
||
ULONG ObjectTypeIndex;
|
||
PSID CapturedUserSid;
|
||
LUID PrimaryAuthenticationId = { 0 };
|
||
LUID ClientAuthenticationId = { 0 };
|
||
PSE_ADT_OBJECT_TYPE AdtObjectTypeBuffer = NULL;
|
||
PEPROCESS Process = NULL;
|
||
PUNICODE_STRING ImageFileName;
|
||
UNICODE_STRING NullString = {0};
|
||
NTSTATUS Status;
|
||
PUNICODE_STRING SubsystemName;
|
||
|
||
PAGED_CODE();
|
||
|
||
Process = PsGetCurrentProcess();
|
||
|
||
Status = SeLocateProcessImageName( Process, &ImageFileName );
|
||
|
||
if ( !NT_SUCCESS(Status) ) {
|
||
ImageFileName = &NullString;
|
||
|
||
//
|
||
// ignore this failure
|
||
//
|
||
|
||
Status = STATUS_SUCCESS;
|
||
}
|
||
|
||
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 );
|
||
|
||
ASSERT( ( AuditType == AuditCategoryObjectAccess ) ||
|
||
( AuditType == AuditCategoryDirectoryServiceAccess ) );
|
||
|
||
if (AuditType == AuditCategoryObjectAccess) {
|
||
|
||
AuditParameters.CategoryId = SE_CATEGID_OBJECT_ACCESS;
|
||
|
||
} else {
|
||
|
||
AuditParameters.CategoryId = SE_CATEGID_DS_ACCESS;
|
||
}
|
||
|
||
AuditParameters.AuditId = SE_AUDITID_OPEN_HANDLE;
|
||
AuditParameters.ParameterCount = 0;
|
||
|
||
if ( AccessGranted ) {
|
||
|
||
AuditParameters.Type = EVENTLOG_AUDIT_SUCCESS;
|
||
|
||
} else {
|
||
|
||
AuditParameters.Type = EVENTLOG_AUDIT_FAILURE;
|
||
}
|
||
|
||
if ( !ARGUMENT_PRESENT( CapturedSubsystemName )) {
|
||
|
||
SubsystemName = (PUNICODE_STRING)&SeSubsystemName;
|
||
|
||
} else {
|
||
|
||
SubsystemName = CapturedSubsystemName;
|
||
}
|
||
|
||
//
|
||
// Parameter[0] - User Sid
|
||
//
|
||
|
||
SepSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, CapturedUserSid );
|
||
|
||
AuditParameters.ParameterCount++;
|
||
|
||
//
|
||
// Parameter[1] - Subsystem name
|
||
//
|
||
|
||
SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, SubsystemName );
|
||
|
||
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 )) {
|
||
|
||
//
|
||
// We have to have an ObjectTypeName for the audit to succeed.
|
||
//
|
||
|
||
Status = STATUS_INVALID_PARAMETER;
|
||
goto Cleanup;
|
||
}
|
||
|
||
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 )) {
|
||
|
||
SepSetParmTypePtr( 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
|
||
//
|
||
|
||
SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, ProcessID );
|
||
|
||
AuditParameters.ParameterCount++;
|
||
|
||
|
||
//
|
||
// Parameter[7] - Subject's Image Name
|
||
//
|
||
|
||
SepSetParmTypeFileSpec( AuditParameters, AuditParameters.ParameterCount, ImageFileName );
|
||
AuditParameters.ParameterCount ++;
|
||
|
||
//
|
||
// Parameter[8] - Subject's primary authentication ID
|
||
//
|
||
|
||
SepSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, PrimaryAuthenticationId );
|
||
|
||
AuditParameters.ParameterCount++;
|
||
|
||
//
|
||
// Parameter[9] - Subject's client authentication ID
|
||
//
|
||
|
||
if ( ARGUMENT_PRESENT( ClientToken )) {
|
||
|
||
SepSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, ClientAuthenticationId );
|
||
|
||
} else {
|
||
|
||
SepSetParmTypeNoLogon( AuditParameters, AuditParameters.ParameterCount );
|
||
}
|
||
|
||
AuditParameters.ParameterCount++;
|
||
|
||
//
|
||
// Parameter[10] - DesiredAccess mask
|
||
//
|
||
|
||
if ( AccessGranted ) {
|
||
|
||
SepSetParmTypeAccessMask( AuditParameters, AuditParameters.ParameterCount, GrantedAccess, ObjectTypeIndex );
|
||
|
||
} else {
|
||
|
||
SepSetParmTypeAccessMask( AuditParameters, AuditParameters.ParameterCount, DesiredAccess, ObjectTypeIndex );
|
||
}
|
||
|
||
AuditParameters.ParameterCount++;
|
||
|
||
//
|
||
// Parameter[11] - Privileges used for open
|
||
//
|
||
|
||
if ( (CapturedPrivileges != NULL) && (CapturedPrivileges->PrivilegeCount > 0) ) {
|
||
|
||
SepSetParmTypePrivileges( AuditParameters, AuditParameters.ParameterCount, CapturedPrivileges );
|
||
}
|
||
|
||
AuditParameters.ParameterCount++;
|
||
|
||
//
|
||
// Parameter[12] - ObjectTypes of Audited objects/parameter sets/parameters
|
||
//
|
||
|
||
if ( ObjectTypeListLength != 0 ) {
|
||
ULONG GuidCount;
|
||
ULONG i;
|
||
USHORT FlagMask = AccessGranted ? OBJECT_SUCCESS_AUDIT : OBJECT_FAILURE_AUDIT;
|
||
|
||
//
|
||
// Count the number of GUIDs to audit.
|
||
//
|
||
|
||
GuidCount = 0;
|
||
for ( i=0; i<ObjectTypeListLength; i++ ) {
|
||
|
||
if ( i == 0 ) {
|
||
GuidCount++;
|
||
} else if ( ObjectTypeList[i].Flags & FlagMask ) {
|
||
GuidCount ++;
|
||
}
|
||
}
|
||
|
||
//
|
||
// If there are any Guids to audit,
|
||
// copy them into a locally allocated buffer.
|
||
//
|
||
|
||
if ( GuidCount > 0 ) {
|
||
|
||
AdtObjectTypeBuffer = ExAllocatePoolWithTag( PagedPool, GuidCount * sizeof(SE_ADT_OBJECT_TYPE), 'pAeS' );
|
||
|
||
//
|
||
// If the buffer can be allocated,
|
||
// fill it in.
|
||
// If not,
|
||
// generate a truncated audit.
|
||
//
|
||
|
||
if ( AdtObjectTypeBuffer != NULL ) {
|
||
|
||
//
|
||
// Copy the GUIDs and optional access masks to the buffer.
|
||
//
|
||
|
||
GuidCount = 0;
|
||
for ( i=0; i<ObjectTypeListLength; i++ ) {
|
||
|
||
if ( ( i > 0 ) && !( ObjectTypeList[i].Flags & FlagMask ) ) {
|
||
|
||
continue;
|
||
|
||
} else {
|
||
|
||
AdtObjectTypeBuffer[GuidCount].ObjectType = ObjectTypeList[i].ObjectType;
|
||
AdtObjectTypeBuffer[GuidCount].Level = ObjectTypeList[i].Level;
|
||
|
||
if ( i == 0 ) {
|
||
//
|
||
// Always copy the GUID representing the object itself.
|
||
// Mark it as a such to avoid including it in the audit.
|
||
//
|
||
AdtObjectTypeBuffer[GuidCount].Flags = SE_ADT_OBJECT_ONLY;
|
||
AdtObjectTypeBuffer[GuidCount].AccessMask = 0;
|
||
|
||
} else {
|
||
|
||
AdtObjectTypeBuffer[GuidCount].Flags = 0;
|
||
if ( ARGUMENT_PRESENT(GrantedAccessArray) && AccessGranted ) {
|
||
|
||
AdtObjectTypeBuffer[GuidCount].AccessMask = GrantedAccessArray[i];
|
||
}
|
||
}
|
||
GuidCount ++;
|
||
}
|
||
}
|
||
|
||
//
|
||
// Store the Object Types.
|
||
//
|
||
|
||
SepSetParmTypeObjectTypes( AuditParameters, AuditParameters.ParameterCount, AdtObjectTypeBuffer, GuidCount, ObjectTypeIndex );
|
||
AuditParameters.ParameterCount ++;
|
||
AuditParameters.AuditId = SE_AUDITID_OPEN_HANDLE_OBJECT_TYPE;
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
//
|
||
// Parameter[13] - Restricted Sids in token
|
||
//
|
||
|
||
SepSetParmTypeUlong( AuditParameters, AuditParameters.ParameterCount, PrimaryToken->RestrictedSidCount );
|
||
AuditParameters.ParameterCount ++;
|
||
|
||
|
||
//
|
||
// Parameter[14] - AccessMask in hex
|
||
//
|
||
|
||
if ( AccessGranted ) {
|
||
|
||
SepSetParmTypeHexUlong( AuditParameters, AuditParameters.ParameterCount, GrantedAccess );
|
||
|
||
} else {
|
||
|
||
SepSetParmTypeHexUlong( AuditParameters, AuditParameters.ParameterCount, DesiredAccess );
|
||
}
|
||
AuditParameters.ParameterCount ++;
|
||
|
||
|
||
//
|
||
// Audit it.
|
||
//
|
||
SepAdtLogAuditRecord( &AuditParameters );
|
||
|
||
Cleanup:
|
||
|
||
if ( AdtObjectTypeBuffer != NULL ) {
|
||
ExFreePool( AdtObjectTypeBuffer );
|
||
}
|
||
|
||
if ( ImageFileName != &NullString ) {
|
||
ExFreePool( ImageFileName );
|
||
}
|
||
|
||
return( NT_SUCCESS(Status) );
|
||
}
|
||
|
||
|
||
BOOLEAN
|
||
SepAdtOpenObjectForDeleteAuditAlarm (
|
||
IN PUNICODE_STRING CapturedSubsystemName,
|
||
IN PVOID *HandleId OPTIONAL,
|
||
IN PUNICODE_STRING CapturedObjectTypeName,
|
||
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 AccessGranted,
|
||
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;
|
||
PUNICODE_STRING SubsystemName;
|
||
|
||
PAGED_CODE();
|
||
|
||
if ( ARGUMENT_PRESENT( ClientToken )) {
|
||
|
||
CapturedUserSid = SepTokenUserSid( 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;
|
||
}
|
||
|
||
if ( !ARGUMENT_PRESENT( CapturedSubsystemName )) {
|
||
|
||
SubsystemName = (PUNICODE_STRING)&SeSubsystemName;
|
||
|
||
} else {
|
||
|
||
SubsystemName = CapturedSubsystemName;
|
||
}
|
||
|
||
//
|
||
// Parameter[0] - User Sid
|
||
//
|
||
|
||
SepSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, CapturedUserSid );
|
||
|
||
AuditParameters.ParameterCount++;
|
||
|
||
//
|
||
// Parameter[1] - Subsystem name
|
||
//
|
||
|
||
SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, SubsystemName );
|
||
|
||
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 )) {
|
||
|
||
SepSetParmTypePtr( 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
|
||
//
|
||
|
||
SepSetParmTypePtr( 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 )) {
|
||
|
||
ClientAuthenticationId = SepTokenAuthenticationId( 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++;
|
||
|
||
//
|
||
// Parameter[11] - DesiredAccess mask in hex
|
||
//
|
||
|
||
if ( AccessGranted ) {
|
||
|
||
SepSetParmTypeHexUlong( AuditParameters, AuditParameters.ParameterCount, GrantedAccess );
|
||
|
||
} else {
|
||
|
||
SepSetParmTypeHexUlong( AuditParameters, AuditParameters.ParameterCount, DesiredAccess );
|
||
}
|
||
|
||
AuditParameters.ParameterCount++;
|
||
|
||
SepAdtLogAuditRecord( &AuditParameters );
|
||
|
||
return( TRUE );
|
||
}
|
||
|
||
|
||
|
||
|
||
VOID
|
||
SepAdtCloseObjectAuditAlarm (
|
||
IN PUNICODE_STRING CapturedSubsystemName,
|
||
IN PVOID HandleId,
|
||
IN PSID UserSid
|
||
)
|
||
|
||
/*++
|
||
|
||
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] - object server name (same as subsystem name)
|
||
|
||
Parameter[3] - New handle ID
|
||
|
||
Parameter[4] - Subject's process id
|
||
|
||
Parameter[5] - Image file name
|
||
|
||
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;
|
||
HANDLE ProcessId;
|
||
PEPROCESS Process = NULL;
|
||
PUNICODE_STRING ImageFileName;
|
||
UNICODE_STRING NullString = {0};
|
||
NTSTATUS Status;
|
||
PUNICODE_STRING SubsystemName;
|
||
|
||
PAGED_CODE();
|
||
|
||
if ( SepAuditOptions.DoNotAuditCloseObjectEvents ) {
|
||
|
||
return;
|
||
}
|
||
|
||
if ( SepAdtAuditThisEventWithContext( AuditCategoryObjectAccess, TRUE, FALSE, NULL ) ) {
|
||
|
||
Process = PsGetCurrentProcess();
|
||
ProcessId = PsProcessAuditId( Process );
|
||
|
||
Status = SeLocateProcessImageName( Process, &ImageFileName );
|
||
|
||
if ( !NT_SUCCESS(Status) ) {
|
||
ImageFileName = &NullString;
|
||
}
|
||
|
||
//
|
||
// 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;
|
||
|
||
if ( !ARGUMENT_PRESENT( CapturedSubsystemName )) {
|
||
|
||
SubsystemName = (PUNICODE_STRING)&SeSubsystemName;
|
||
|
||
} else {
|
||
|
||
SubsystemName = CapturedSubsystemName;
|
||
}
|
||
|
||
//
|
||
// Parameter[0] - User Sid
|
||
//
|
||
|
||
SepSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, UserSid );
|
||
|
||
AuditParameters.ParameterCount++;
|
||
|
||
|
||
//
|
||
// Parameter[1] - Subsystem name
|
||
//
|
||
|
||
SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, SubsystemName );
|
||
|
||
AuditParameters.ParameterCount++;
|
||
|
||
//
|
||
// Parameter[2] - Object server name (if available)
|
||
//
|
||
|
||
if ( ARGUMENT_PRESENT( CapturedSubsystemName )) {
|
||
|
||
SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, CapturedSubsystemName );
|
||
}
|
||
|
||
AuditParameters.ParameterCount++;
|
||
|
||
//
|
||
// Parameter[3] - New handle ID
|
||
//
|
||
|
||
SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, HandleId );
|
||
|
||
AuditParameters.ParameterCount++;
|
||
|
||
//
|
||
// Parameter[4] - Subject's process id
|
||
//
|
||
|
||
SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, ProcessId );
|
||
|
||
AuditParameters.ParameterCount++;
|
||
|
||
//
|
||
// Parameter[5] - Subject's Image Name
|
||
//
|
||
|
||
SepSetParmTypeFileSpec( AuditParameters, AuditParameters.ParameterCount, ImageFileName );
|
||
AuditParameters.ParameterCount ++;
|
||
|
||
SepAdtLogAuditRecord( &AuditParameters );
|
||
|
||
if ( ImageFileName != &NullString ) {
|
||
ExFreePool( ImageFileName );
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
|
||
|
||
VOID
|
||
SepAdtDeleteObjectAuditAlarm (
|
||
IN PUNICODE_STRING CapturedSubsystemName,
|
||
IN PVOID HandleId,
|
||
IN PSID UserSid
|
||
)
|
||
|
||
/*++
|
||
|
||
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 routine will create an SE_ADT_PARAMETERS array organized as follows:
|
||
|
||
Parameter[0] - User Sid
|
||
|
||
Parameter[1] - Subsystem name
|
||
|
||
Parameter[2] - Object server (same as Subsystem name)
|
||
|
||
Parameter[3] - Handle ID
|
||
|
||
Parameter[4] - Subject's process id
|
||
|
||
Parameter[5] - Subject's process image name
|
||
|
||
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;
|
||
HANDLE ProcessId;
|
||
PUNICODE_STRING ImageFileName = NULL;
|
||
UNICODE_STRING NullString = {0};
|
||
PEPROCESS Process = NULL;
|
||
NTSTATUS Status = STATUS_SUCCESS;
|
||
PUNICODE_STRING SubsystemName;
|
||
|
||
PAGED_CODE();
|
||
|
||
if ( SepAdtAuditThisEventWithContext( AuditCategoryObjectAccess, TRUE, FALSE, NULL ) ) {
|
||
|
||
Process = PsGetCurrentProcess();
|
||
Status = SeLocateProcessImageName( Process, &ImageFileName );
|
||
|
||
if ( !NT_SUCCESS(Status) ) {
|
||
ImageFileName = &NullString;
|
||
}
|
||
|
||
//
|
||
// 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;
|
||
|
||
if ( !ARGUMENT_PRESENT( CapturedSubsystemName )) {
|
||
|
||
SubsystemName = (PUNICODE_STRING)&SeSubsystemName;
|
||
|
||
} else {
|
||
|
||
SubsystemName = CapturedSubsystemName;
|
||
}
|
||
|
||
//
|
||
// Parameter[0] - User Sid
|
||
//
|
||
|
||
SepSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, UserSid );
|
||
|
||
AuditParameters.ParameterCount++;
|
||
|
||
|
||
//
|
||
// Parameter[1] - Subsystem name
|
||
//
|
||
|
||
SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, SubsystemName );
|
||
|
||
AuditParameters.ParameterCount++;
|
||
|
||
//
|
||
// Parameter[2] - Subsystem name (if available)
|
||
//
|
||
|
||
if ( ARGUMENT_PRESENT( CapturedSubsystemName )) {
|
||
|
||
SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, CapturedSubsystemName );
|
||
}
|
||
|
||
AuditParameters.ParameterCount++;
|
||
|
||
//
|
||
// Parameter[3] - New handle ID
|
||
//
|
||
|
||
SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, HandleId );
|
||
|
||
AuditParameters.ParameterCount++;
|
||
|
||
//
|
||
// Parameter[4] - Subject's process id
|
||
//
|
||
|
||
ProcessId = PsProcessAuditId( PsGetCurrentProcess() );
|
||
|
||
SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, ProcessId );
|
||
|
||
AuditParameters.ParameterCount++;
|
||
|
||
//
|
||
// Parameter[5] - Subject's Image Name
|
||
//
|
||
|
||
SepSetParmTypeFileSpec( AuditParameters, AuditParameters.ParameterCount, ImageFileName );
|
||
AuditParameters.ParameterCount ++;
|
||
|
||
SepAdtLogAuditRecord( &AuditParameters );
|
||
|
||
if (ImageFileName != &NullString) {
|
||
ExFreePool(ImageFileName);
|
||
}
|
||
}
|
||
}
|
||
|
||
VOID
|
||
SeOperationAuditAlarm (
|
||
IN PUNICODE_STRING CapturedSubsystemName OPTIONAL,
|
||
IN PVOID HandleId,
|
||
IN PUNICODE_STRING ObjectTypeName,
|
||
IN ACCESS_MASK AuditMask,
|
||
IN PSID UserSid OPTIONAL
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine generates an "operation-based" audit.
|
||
|
||
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 routine will create an SE_ADT_PARAMETERS array organized as follows:
|
||
|
||
Parameter[0] - User Sid
|
||
|
||
Parameter[1] - Subsystem name (if available)
|
||
|
||
Parameter[2] - Object server (same as Subsystem name)
|
||
|
||
Parameter[3] - Handle ID
|
||
|
||
Parameter[4] - object type name
|
||
|
||
Parameter[5] - Subject's process id
|
||
|
||
Parameter[6] - Subject's process image name
|
||
|
||
Parameter[7] - Audit mask
|
||
|
||
Arguments:
|
||
|
||
CapturedSubsystemName - Supplies a name string identifying the
|
||
subsystem calling the routine.
|
||
|
||
HandleId - A unique value representing the client's handle to the
|
||
object.
|
||
|
||
ObjectTypeName - The type of the object being accessed.
|
||
|
||
AuditMask - Mask of bits being audited.
|
||
|
||
UserSid - Optionally supplies the user sid.
|
||
|
||
Return value:
|
||
|
||
None.
|
||
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
SE_ADT_PARAMETER_ARRAY AuditParameters;
|
||
BOOLEAN AccessGranted = TRUE;
|
||
HANDLE ProcessId;
|
||
SECURITY_SUBJECT_CONTEXT SubjectSecurityContext;
|
||
ULONG ObjectTypeIndex;
|
||
PUNICODE_STRING SubsystemName;
|
||
NTSTATUS Status;
|
||
UNICODE_STRING NullString = {0};
|
||
PUNICODE_STRING ImageFileName = NULL;
|
||
PEPROCESS Process = NULL;
|
||
|
||
PAGED_CODE();
|
||
|
||
Process = PsGetCurrentProcess();
|
||
ProcessId = PsProcessAuditId( Process );
|
||
|
||
Status = SeLocateProcessImageName( Process, &ImageFileName );
|
||
|
||
if ( !NT_SUCCESS(Status) ) {
|
||
ImageFileName = &NullString;
|
||
}
|
||
|
||
//
|
||
// 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_OBJECT_ACCESS;
|
||
AuditParameters.ParameterCount = 0;
|
||
AuditParameters.Type = EVENTLOG_AUDIT_SUCCESS;
|
||
|
||
//
|
||
// If the user's SID was not passed, get it out of the current
|
||
// subject context
|
||
//
|
||
|
||
SeCaptureSubjectContext( &SubjectSecurityContext );
|
||
|
||
if ( !ARGUMENT_PRESENT( UserSid )) {
|
||
|
||
UserSid = SepTokenUserSid( EffectiveToken( &SubjectSecurityContext ));
|
||
|
||
}
|
||
|
||
|
||
if ( !ARGUMENT_PRESENT( CapturedSubsystemName )) {
|
||
|
||
SubsystemName = (PUNICODE_STRING)&SeSubsystemName;
|
||
|
||
} else {
|
||
|
||
SubsystemName = CapturedSubsystemName;
|
||
}
|
||
|
||
//
|
||
// Parameter[0] - User Sid
|
||
//
|
||
|
||
SepSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, UserSid );
|
||
|
||
AuditParameters.ParameterCount++;
|
||
|
||
|
||
//
|
||
// Parameter[1] - Subsystem name
|
||
//
|
||
|
||
SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, SubsystemName );
|
||
|
||
AuditParameters.ParameterCount++;
|
||
|
||
//
|
||
// Parameter[2] - object server (same as subsystem name)
|
||
//
|
||
|
||
SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, SubsystemName );
|
||
|
||
AuditParameters.ParameterCount++;
|
||
|
||
//
|
||
// Parameter[3] - New handle ID
|
||
//
|
||
|
||
SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, HandleId );
|
||
|
||
AuditParameters.ParameterCount++;
|
||
|
||
//
|
||
// Parameter[4] - Object Type Name
|
||
//
|
||
|
||
SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, ObjectTypeName );
|
||
ObjectTypeIndex = AuditParameters.ParameterCount;
|
||
|
||
AuditParameters.ParameterCount++;
|
||
|
||
//
|
||
// Parameter[5] - Subject's process id
|
||
//
|
||
|
||
SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, ProcessId );
|
||
|
||
AuditParameters.ParameterCount++;
|
||
|
||
|
||
//
|
||
// Parameter[6] - Subject's process name
|
||
//
|
||
|
||
SepSetParmTypeFileSpec( AuditParameters, AuditParameters.ParameterCount, ImageFileName );
|
||
|
||
AuditParameters.ParameterCount++;
|
||
|
||
//
|
||
// Parameter[7] - Audit Mask
|
||
//
|
||
|
||
SepSetParmTypeAccessMask( AuditParameters, AuditParameters.ParameterCount, AuditMask, ObjectTypeIndex );
|
||
|
||
AuditParameters.ParameterCount++;
|
||
|
||
//
|
||
// Parameter[8] - Access Mask (hex)
|
||
//
|
||
|
||
SepSetParmTypeHexUlong( AuditParameters, AuditParameters.ParameterCount, AuditMask );
|
||
|
||
AuditParameters.ParameterCount++;
|
||
|
||
SepAdtLogAuditRecord( &AuditParameters );
|
||
|
||
if ( ImageFileName != &NullString ) {
|
||
ExFreePool( ImageFileName );
|
||
}
|
||
|
||
SeReleaseSubjectContext( &SubjectSecurityContext );
|
||
|
||
}
|
||
|
||
|
||
|
||
VOID
|
||
SepAdtObjectReferenceAuditAlarm(
|
||
IN PVOID Object,
|
||
IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext,
|
||
IN ACCESS_MASK DesiredAccess,
|
||
IN BOOLEAN AccessGranted
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Note: the caller (SeObjectReferenceAuditAlarm) checks audit policy.
|
||
|
||
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:
|
||
|
||
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 );
|
||
|
||
} 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 = 9;
|
||
|
||
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
|
||
//
|
||
|
||
SepSetParmTypeString( AuditParameters, 1, (PUNICODE_STRING)&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
|
||
//
|
||
|
||
SepSetParmTypePtr( 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 )) {
|
||
|
||
ClientAuthenticationId = SepTokenAuthenticationId( ClientToken );
|
||
SepSetParmTypeLogonId( AuditParameters, 6, ClientAuthenticationId );
|
||
|
||
} else {
|
||
|
||
SepSetParmTypeNoLogon( AuditParameters, 6 );
|
||
|
||
}
|
||
|
||
//
|
||
// Parameter[7] - DesiredAccess mask
|
||
//
|
||
|
||
SepSetParmTypeAccessMask( AuditParameters, 7, DesiredAccess, ObjectTypeIndex );
|
||
|
||
//
|
||
// Parameter[8] - DesiredAccess mask
|
||
//
|
||
|
||
SepSetParmTypeHexUlong( AuditParameters, 8, DesiredAccess );
|
||
|
||
|
||
SepAdtLogAuditRecord( &AuditParameters );
|
||
|
||
if ( ObjectNameInformation != NULL ) {
|
||
ExFreePool( ObjectNameInformation );
|
||
}
|
||
|
||
if ( ObjectTypeInformation != NULL ) {
|
||
ExFreePool( ObjectTypeInformation );
|
||
}
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
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 ) && (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 );
|
||
|
||
} else {
|
||
|
||
ExFreePool( TypeName );
|
||
}
|
||
}
|
||
}
|
||
|
||
return( NULL );
|
||
}
|
||
|
||
|
||
VOID
|
||
SeAuditProcessCreation(
|
||
PEPROCESS Process
|
||
)
|
||
/*++
|
||
|
||
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.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
ANSI_STRING Ansi;
|
||
LUID UserAuthenticationId;
|
||
NTSTATUS Status;
|
||
PSID UserSid;
|
||
SECURITY_SUBJECT_CONTEXT SubjectSecurityContext;
|
||
SE_ADT_PARAMETER_ARRAY AuditParameters;
|
||
HANDLE ProcessId;
|
||
HANDLE ParentProcessId;
|
||
PUNICODE_STRING ImageFileName;
|
||
UNICODE_STRING NullString = {0};
|
||
|
||
PAGED_CODE();
|
||
|
||
//
|
||
// Set up the various data that will be needed for the audit:
|
||
// - process id
|
||
// - parent's process id
|
||
// - image file name (unicode)
|
||
//
|
||
|
||
ProcessId = Process->UniqueProcessId;
|
||
ParentProcessId = Process->InheritedFromUniqueProcessId;
|
||
|
||
Status = SeLocateProcessImageName( Process, &ImageFileName );
|
||
|
||
if ( !NT_SUCCESS(Status) ) {
|
||
ImageFileName = &NullString;
|
||
}
|
||
|
||
//
|
||
// NtCreateProcess with no section will cause this to be NULL
|
||
// fork() for posix will do this, or someone calling NtCreateProcess
|
||
// directly.
|
||
//
|
||
|
||
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, (PUNICODE_STRING)&SeSubsystemName );
|
||
AuditParameters.ParameterCount++;
|
||
|
||
SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, ProcessId );
|
||
AuditParameters.ParameterCount++;
|
||
|
||
SepSetParmTypeFileSpec( AuditParameters, AuditParameters.ParameterCount, ImageFileName );
|
||
AuditParameters.ParameterCount++;
|
||
|
||
SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, ParentProcessId );
|
||
AuditParameters.ParameterCount++;
|
||
|
||
SepSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, UserAuthenticationId );
|
||
AuditParameters.ParameterCount++;
|
||
|
||
SepAdtLogAuditRecord( &AuditParameters );
|
||
|
||
SeReleaseSubjectContext( &SubjectSecurityContext );
|
||
|
||
if ( ImageFileName != &NullString ) {
|
||
ExFreePool( 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, (PUNICODE_STRING)&SeSubsystemName );
|
||
AuditParameters.ParameterCount++;
|
||
|
||
SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, SourceHandle );
|
||
AuditParameters.ParameterCount++;
|
||
|
||
SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, PsProcessAuditId( SourceProcess ));
|
||
AuditParameters.ParameterCount++;
|
||
|
||
SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, NewHandle );
|
||
AuditParameters.ParameterCount++;
|
||
|
||
SepSetParmTypePtr( 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;
|
||
HANDLE ProcessId;
|
||
PUNICODE_STRING ImageFileName;
|
||
UNICODE_STRING NullString = {0};
|
||
NTSTATUS Status;
|
||
|
||
PAGED_CODE();
|
||
|
||
Token = (PTOKEN) PsReferencePrimaryToken (Process);
|
||
|
||
UserSid = SepTokenUserSid( Token );
|
||
LogonId = SepTokenAuthenticationId( Token );
|
||
|
||
RtlZeroMemory (
|
||
(PVOID) &AuditParameters,
|
||
sizeof( AuditParameters )
|
||
);
|
||
|
||
ASSERT( SeAdtParmTypeNone == 0 );
|
||
|
||
Status = SeLocateProcessImageName( Process, &ImageFileName );
|
||
|
||
if ( !NT_SUCCESS(Status) ) {
|
||
ImageFileName = &NullString;
|
||
}
|
||
|
||
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, (PUNICODE_STRING)&SeSubsystemName );
|
||
AuditParameters.ParameterCount++;
|
||
|
||
ProcessId = PsProcessAuditId( Process );
|
||
|
||
SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, ProcessId );
|
||
AuditParameters.ParameterCount++;
|
||
|
||
SepSetParmTypeFileSpec( AuditParameters, AuditParameters.ParameterCount, ImageFileName );
|
||
AuditParameters.ParameterCount++;
|
||
|
||
SepSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, LogonId );
|
||
AuditParameters.ParameterCount++;
|
||
|
||
SepAdtLogAuditRecord( &AuditParameters );
|
||
|
||
PsDereferencePrimaryToken( Token );
|
||
|
||
if ( ImageFileName != &NullString ) {
|
||
ExFreePool( ImageFileName );
|
||
}
|
||
|
||
}
|
||
|
||
|
||
|
||
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, (PUNICODE_STRING)&SeSubsystemName );
|
||
AuditParameters.ParameterCount++;
|
||
|
||
SepSetParmTypeUlong( AuditParameters, AuditParameters.ParameterCount, SepAdtCountEventsDiscarded );
|
||
AuditParameters.ParameterCount++;
|
||
|
||
SepAdtLogAuditRecord( &AuditParameters );
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
SeInitializeProcessAuditName (
|
||
IN PVOID FileObject,
|
||
IN BOOLEAN bIgnoreAuditPolicy,
|
||
OUT POBJECT_NAME_INFORMATION *pAuditName
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine initializes the executable name for auditing purposes. It allocates memory for the
|
||
image file name. This memory is pointed to by pAuditName.
|
||
|
||
Arguments:
|
||
|
||
FileObject - Supplies a pointer to a file object for the image being
|
||
executed.
|
||
|
||
bIgnoreAuditPolicy - boolean that indicates that the call should proceed without
|
||
regard to the system's auditing policy.
|
||
|
||
pAuditName - Supplies a pointer to a pointer for the object name information.
|
||
|
||
Return value:
|
||
|
||
NTSTATUS.
|
||
|
||
ISSUE-2002/03/11-kumarp : need to document the case when return code
|
||
is STATUS_SUCCESS
|
||
|
||
Environment:
|
||
|
||
KeAttached to the target process so not all system services are available.
|
||
|
||
--*/
|
||
|
||
{
|
||
NTSTATUS Status;
|
||
OBJECT_NAME_INFORMATION TempNameInfo;
|
||
ULONG ObjectNameInformationLength;
|
||
POBJECT_NAME_INFORMATION pInternalAuditName;
|
||
PFILE_OBJECT FilePointer;
|
||
|
||
PAGED_CODE();
|
||
|
||
ASSERT (pAuditName != NULL);
|
||
*pAuditName = NULL;
|
||
|
||
//
|
||
// Check if the caller would like to get the process name, even if auditing does not
|
||
// require it.
|
||
//
|
||
|
||
if (FALSE == bIgnoreAuditPolicy) {
|
||
//
|
||
// At the time of process creation, this routine should only proceed when Object Access or
|
||
// Detailed Tracking auditing is enabled. In all other cases, the process name is acquired
|
||
// when it is requested.
|
||
//
|
||
|
||
//
|
||
// Longhorn-ISSUE-2002/03/11-kumarp : why capture subj context twice?
|
||
// bug# 572609
|
||
//
|
||
|
||
if (!SepAdtAuditThisEventWithContext( AuditCategoryObjectAccess, TRUE, FALSE, NULL ) &&
|
||
!SepAdtAuditThisEventWithContext( AuditCategoryDetailedTracking, TRUE, FALSE, NULL )) {
|
||
|
||
return STATUS_SUCCESS;
|
||
}
|
||
}
|
||
|
||
FilePointer = (PFILE_OBJECT) FileObject;
|
||
|
||
//
|
||
// Compute full path for imagefile.
|
||
// This first call to ObQueryNameString is guaranteed to fail.
|
||
// The ObjectNameInformationLength contains only a
|
||
// UNICODE_STRING, so if this call succeeded it would indicate
|
||
// an imagefile name of length 0. That is bad, so all return
|
||
// values except STATUS_BUFFER_OVERFLOW (from NTFS) and
|
||
// STATUS_BUFFER_TOO_SMALL (from DFS). This call gives
|
||
// me the buffer size that I need to store the image name.
|
||
//
|
||
|
||
pInternalAuditName = &TempNameInfo;
|
||
ObjectNameInformationLength = sizeof(OBJECT_NAME_INFORMATION);
|
||
|
||
Status = ObQueryNameString (FilePointer,
|
||
pInternalAuditName,
|
||
ObjectNameInformationLength,
|
||
&ObjectNameInformationLength);
|
||
|
||
if ((Status == STATUS_BUFFER_OVERFLOW) ||
|
||
(Status == STATUS_BUFFER_TOO_SMALL)) {
|
||
|
||
//
|
||
// Sanity check ObQueryNameString. Different filesystems
|
||
// may be buggy, so make sure that the return length makes
|
||
// sense (that it has room for a non-NULL Buffer in the
|
||
// UNICODE_STRING).
|
||
//
|
||
|
||
if (ObjectNameInformationLength > sizeof(OBJECT_NAME_INFORMATION)) {
|
||
pInternalAuditName = ExAllocatePoolWithTag (NonPagedPool,
|
||
ObjectNameInformationLength,
|
||
'aPeS');
|
||
|
||
if (pInternalAuditName != NULL) {
|
||
Status = ObQueryNameString (FilePointer,
|
||
pInternalAuditName,
|
||
ObjectNameInformationLength,
|
||
&ObjectNameInformationLength);
|
||
|
||
if (!NT_SUCCESS(Status)) {
|
||
|
||
#if DBG
|
||
DbgPrint("\n** ObqueryNameString failed with 0x%x.\n", Status);
|
||
#endif //DBG
|
||
|
||
//
|
||
// If the second call to ObQueryNameString did not succeed, then
|
||
// something is very wrong. Set the image name to NULL string.
|
||
//
|
||
// Free the memory that the first call to ObQueryNameString requested,
|
||
// and allocate enough space to store an empty UNICODE_STRING.
|
||
//
|
||
|
||
ExFreePool (pInternalAuditName);
|
||
ObjectNameInformationLength = sizeof(OBJECT_NAME_INFORMATION);
|
||
pInternalAuditName = ExAllocatePoolWithTag (NonPagedPool,
|
||
ObjectNameInformationLength,
|
||
'aPeS');
|
||
|
||
if (pInternalAuditName != NULL) {
|
||
RtlZeroMemory(pInternalAuditName, ObjectNameInformationLength);
|
||
|
||
//
|
||
// Status = STATUS_SUCCESS to allow the process creation to continue.
|
||
//
|
||
|
||
Status = STATUS_SUCCESS;
|
||
} else {
|
||
Status = STATUS_NO_MEMORY;
|
||
}
|
||
}
|
||
} else {
|
||
Status = STATUS_NO_MEMORY;
|
||
}
|
||
} else {
|
||
|
||
//
|
||
// If this happens, then ObQueryNameString is broken for the FS on which
|
||
// it was called.
|
||
//
|
||
|
||
#if DBG
|
||
DbgPrint("\n** ObqueryNameString failed with 0x%x.\n", Status);
|
||
#endif //DBG
|
||
|
||
ObjectNameInformationLength = sizeof(OBJECT_NAME_INFORMATION);
|
||
pInternalAuditName = ExAllocatePoolWithTag (NonPagedPool,
|
||
ObjectNameInformationLength,
|
||
'aPeS');
|
||
|
||
if (pInternalAuditName != NULL) {
|
||
RtlZeroMemory(pInternalAuditName, ObjectNameInformationLength);
|
||
|
||
//
|
||
// Status = STATUS_SUCCESS to allow the process creation to continue.
|
||
//
|
||
|
||
Status = STATUS_SUCCESS;
|
||
} else {
|
||
Status = STATUS_NO_MEMORY;
|
||
}
|
||
}
|
||
} else {
|
||
|
||
//
|
||
// If ObQueryNameString returns some other error code, we cannot
|
||
// be certain of which action to take, or whether it has properly
|
||
// set the ReturnLength. For example, ObQueryNameString has slightly
|
||
// different semantics under DFS than NTFS. Additionally, 3rd
|
||
// party file systems may also behave unpredictably. For these reasons,
|
||
// in the case of an unexpected error code from ObQueryNameString
|
||
// we set AuditName to zero length unicode string and allow process
|
||
// creation to continue.
|
||
//
|
||
|
||
#if DBG
|
||
DbgPrint("\n** ObqueryNameString failed with 0x%x.\n", Status);
|
||
#endif //DBG
|
||
|
||
ObjectNameInformationLength = sizeof(OBJECT_NAME_INFORMATION);
|
||
pInternalAuditName = ExAllocatePoolWithTag(NonPagedPool, ObjectNameInformationLength, 'aPeS');
|
||
|
||
if (pInternalAuditName != NULL) {
|
||
RtlZeroMemory(pInternalAuditName, ObjectNameInformationLength);
|
||
|
||
//
|
||
// Status = STATUS_SUCCESS to allow the process creation to continue.
|
||
//
|
||
|
||
Status = STATUS_SUCCESS;
|
||
} else {
|
||
Status = STATUS_NO_MEMORY;
|
||
}
|
||
}
|
||
|
||
*pAuditName = pInternalAuditName;
|
||
|
||
return Status;
|
||
}
|
||
|
||
|
||
|
||
NTSTATUS
|
||
SeLocateProcessImageName(
|
||
IN PEPROCESS Process,
|
||
OUT PUNICODE_STRING *pImageFileName
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description
|
||
|
||
This routine returns the ImageFileName information from the process, if available. This is a "lazy evaluation" wrapper
|
||
around SeInitializeProcessAuditName. If the image file name information has already been computed, then this call simply
|
||
allocates and returns a UNICODE_STRING with this information. Otherwise, the function determines the name, stores the name in the
|
||
EPROCESS structure, and then allocates and returns a UNICODE_STRING. Caller must free the memory returned in pImageFileName.
|
||
|
||
Arguments
|
||
|
||
Process - process for which to acquire the name
|
||
|
||
pImageFileName - output parameter to return name to caller
|
||
|
||
Return Value
|
||
|
||
NTSTATUS.
|
||
|
||
--*/
|
||
|
||
{
|
||
NTSTATUS Status = STATUS_SUCCESS;
|
||
PVOID FilePointer = NULL;
|
||
PVOID PreviousValue = NULL;
|
||
POBJECT_NAME_INFORMATION pProcessImageName = NULL;
|
||
PUNICODE_STRING pTempUS = NULL;
|
||
ULONG NameLength = 0;
|
||
|
||
PAGED_CODE();
|
||
|
||
*pImageFileName = NULL;
|
||
|
||
if (NULL == Process->SeAuditProcessCreationInfo.ImageFileName) {
|
||
|
||
//
|
||
// The name has not been predetermined. We must determine the process name. First, reference the
|
||
// PFILE_OBJECT and lookup the name. Then again check the process image name pointer against NULL.
|
||
// Finally, set the name.
|
||
//
|
||
|
||
Status = PsReferenceProcessFilePointer( Process, &FilePointer );
|
||
|
||
if (NT_SUCCESS(Status)) {
|
||
|
||
//
|
||
// Get the process name information.
|
||
//
|
||
|
||
Status = SeInitializeProcessAuditName(
|
||
FilePointer,
|
||
TRUE, // skip audit policy
|
||
&pProcessImageName // to be allocated in nonpaged pool
|
||
);
|
||
|
||
if (NT_SUCCESS(Status)) {
|
||
|
||
//
|
||
// Only use the pProcessImageName if the field in the process is currently NULL.
|
||
//
|
||
|
||
PreviousValue = InterlockedCompareExchangePointer(
|
||
(PVOID *) &Process->SeAuditProcessCreationInfo.ImageFileName,
|
||
(PVOID) pProcessImageName,
|
||
(PVOID) NULL
|
||
);
|
||
|
||
if (NULL != PreviousValue) {
|
||
ExFreePool(pProcessImageName); // free what we caused to be allocated.
|
||
}
|
||
}
|
||
ObDereferenceObject( FilePointer );
|
||
}
|
||
}
|
||
|
||
|
||
if (NT_SUCCESS(Status)) {
|
||
|
||
//
|
||
// Allocate space for a buffer to contain the name for returning to the caller.
|
||
//
|
||
|
||
NameLength = sizeof(UNICODE_STRING) + Process->SeAuditProcessCreationInfo.ImageFileName->Name.MaximumLength;
|
||
pTempUS = ExAllocatePoolWithTag( NonPagedPool, NameLength, 'aPeS' );
|
||
|
||
if (NULL != pTempUS) {
|
||
|
||
RtlCopyMemory(
|
||
pTempUS,
|
||
&Process->SeAuditProcessCreationInfo.ImageFileName->Name,
|
||
NameLength
|
||
);
|
||
|
||
pTempUS->Buffer = (PWSTR)(((PUCHAR) pTempUS) + sizeof(UNICODE_STRING));
|
||
*pImageFileName = pTempUS;
|
||
|
||
} else {
|
||
|
||
Status = STATUS_NO_MEMORY;
|
||
}
|
||
}
|
||
|
||
return Status;
|
||
}
|
||
|
||
|
||
|
||
VOID
|
||
SepAuditAssignPrimaryToken(
|
||
IN PEPROCESS Process,
|
||
IN PACCESS_TOKEN AccessToken
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine generates an assign primary token audit. It is up to the caller
|
||
to determine if this routine should be called or not.
|
||
|
||
Arguments:
|
||
|
||
Process - process which gets the new token
|
||
|
||
AccessToken - new primary token for the process
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
SE_ADT_PARAMETER_ARRAY AuditParameters;
|
||
NTSTATUS Status;
|
||
PSID UserSid;
|
||
PTOKEN Token;
|
||
HANDLE ProcessId;
|
||
|
||
SECURITY_SUBJECT_CONTEXT SubjectSecurityContext;
|
||
PTOKEN CurrentToken;
|
||
PEPROCESS CurrentProcess;
|
||
HANDLE CurrentProcessId;
|
||
PUNICODE_STRING CurrentImageFileName;
|
||
PUNICODE_STRING ImageFileName;
|
||
UNICODE_STRING NullString = {0};
|
||
|
||
PAGED_CODE();
|
||
|
||
RtlZeroMemory (
|
||
(PVOID) &AuditParameters,
|
||
sizeof( AuditParameters )
|
||
);
|
||
|
||
//
|
||
// Get information about the current process, that is, the process
|
||
// that is assigning a new primary token.
|
||
//
|
||
|
||
CurrentProcess = PsGetCurrentProcess();
|
||
CurrentProcessId = PsProcessAuditId( CurrentProcess );
|
||
SeCaptureSubjectContext( &SubjectSecurityContext );
|
||
CurrentToken = EffectiveToken( &SubjectSecurityContext );
|
||
UserSid = SepTokenUserSid( CurrentToken );
|
||
Status = SeLocateProcessImageName( CurrentProcess, &CurrentImageFileName );
|
||
|
||
if (!NT_SUCCESS(Status)) {
|
||
CurrentImageFileName = &NullString;
|
||
}
|
||
|
||
//
|
||
// Retrieve information about the process receiving the new token.
|
||
//
|
||
|
||
Token = (PTOKEN) AccessToken;
|
||
ProcessId = PsProcessAuditId( Process );
|
||
|
||
Status = SeLocateProcessImageName( Process, &ImageFileName );
|
||
|
||
if ( !NT_SUCCESS(Status) ) {
|
||
ImageFileName = &NullString;
|
||
}
|
||
|
||
ASSERT( SeAdtParmTypeNone == 0 );
|
||
|
||
AuditParameters.CategoryId = SE_CATEGID_DETAILED_TRACKING;
|
||
AuditParameters.AuditId = SE_AUDITID_ASSIGN_TOKEN;
|
||
AuditParameters.ParameterCount = 0;
|
||
AuditParameters.Type = EVENTLOG_AUDIT_SUCCESS;
|
||
|
||
SepSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, UserSid );
|
||
AuditParameters.ParameterCount++;
|
||
|
||
SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, (PUNICODE_STRING)&SeSubsystemName );
|
||
AuditParameters.ParameterCount++;
|
||
|
||
//
|
||
// Information regarding the assigning process
|
||
//
|
||
|
||
SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, CurrentProcessId );
|
||
AuditParameters.ParameterCount++;
|
||
|
||
SepSetParmTypeFileSpec( AuditParameters, AuditParameters.ParameterCount, CurrentImageFileName );
|
||
AuditParameters.ParameterCount++;
|
||
|
||
SepSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, SepTokenAuthenticationId( CurrentToken ) );
|
||
AuditParameters.ParameterCount++;
|
||
|
||
//
|
||
// Information about the process receiving the new primary token.
|
||
//
|
||
|
||
SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, ProcessId );
|
||
AuditParameters.ParameterCount++;
|
||
|
||
SepSetParmTypeFileSpec( AuditParameters, AuditParameters.ParameterCount, ImageFileName );
|
||
AuditParameters.ParameterCount++;
|
||
|
||
SepSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, SepTokenAuthenticationId( Token ) );
|
||
AuditParameters.ParameterCount++;
|
||
|
||
SepAdtLogAuditRecord( &AuditParameters );
|
||
|
||
if ( ImageFileName != &NullString ) {
|
||
ExFreePool( ImageFileName );
|
||
}
|
||
|
||
if ( CurrentImageFileName != &NullString ) {
|
||
ExFreePool( CurrentImageFileName );
|
||
}
|
||
|
||
SeReleaseSubjectContext( &SubjectSecurityContext );
|
||
|
||
}
|
||
|
||
VOID
|
||
SeAuditLPCInvalidUse(
|
||
IN PUNICODE_STRING LpcCallName,
|
||
IN PUNICODE_STRING LpcServerPort
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Audits the invalid use of an LPC port.
|
||
|
||
Arguments:
|
||
|
||
LpcCallName - type of call: impersonation or reply
|
||
|
||
LpcServerPort - name of port
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
LUID UserAuthenticationId;
|
||
PSID UserSid;
|
||
LUID ThreadAuthenticationId;
|
||
SECURITY_SUBJECT_CONTEXT SubjectSecurityContext;
|
||
SE_ADT_PARAMETER_ARRAY AuditParameters;
|
||
PEPROCESS Process;
|
||
HANDLE ProcessID;
|
||
PUNICODE_STRING ImageFileName;
|
||
UNICODE_STRING NullString = {0};
|
||
NTSTATUS Status;
|
||
|
||
PAGED_CODE();
|
||
|
||
|
||
if ( SepAdtAuditThisEventWithContext( AuditCategorySystem, TRUE, FALSE, NULL )) {
|
||
|
||
RtlZeroMemory (
|
||
(PVOID) &AuditParameters,
|
||
sizeof( AuditParameters )
|
||
);
|
||
|
||
Process = PsGetCurrentProcess();
|
||
ProcessID = PsProcessAuditId( Process );
|
||
Status = SeLocateProcessImageName( Process, &ImageFileName );
|
||
|
||
if ( !NT_SUCCESS(Status) ) {
|
||
ImageFileName = &NullString;
|
||
}
|
||
|
||
ASSERT( SeAdtParmTypeNone == 0 );
|
||
|
||
AuditParameters.CategoryId = SE_CATEGID_SYSTEM;
|
||
AuditParameters.AuditId = SE_AUDITID_LPC_INVALID_USE;
|
||
AuditParameters.ParameterCount = 0;
|
||
AuditParameters.Type = EVENTLOG_AUDIT_SUCCESS;
|
||
|
||
SeCaptureSubjectContext( &SubjectSecurityContext );
|
||
|
||
UserSid = SepTokenUserSid( SubjectSecurityContext.PrimaryToken );
|
||
UserAuthenticationId = SepTokenAuthenticationId( SubjectSecurityContext.PrimaryToken );
|
||
|
||
//
|
||
// Fill in the AuditParameters structure.
|
||
//
|
||
|
||
SepSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, UserSid );
|
||
AuditParameters.ParameterCount++;
|
||
|
||
SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, (PUNICODE_STRING)&SeSubsystemName );
|
||
AuditParameters.ParameterCount++;
|
||
|
||
SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, ProcessID );
|
||
AuditParameters.ParameterCount++;
|
||
|
||
SepSetParmTypeFileSpec( AuditParameters, AuditParameters.ParameterCount, ImageFileName );
|
||
AuditParameters.ParameterCount++;
|
||
|
||
SepSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, UserAuthenticationId );
|
||
AuditParameters.ParameterCount++;
|
||
|
||
if ( SubjectSecurityContext.ClientToken ) {
|
||
|
||
SepSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, SepTokenAuthenticationId( SubjectSecurityContext.ClientToken ));
|
||
} else {
|
||
|
||
SepSetParmTypeNoLogon( AuditParameters, AuditParameters.ParameterCount );
|
||
}
|
||
|
||
AuditParameters.ParameterCount++;
|
||
|
||
SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, LpcCallName );
|
||
AuditParameters.ParameterCount++;
|
||
|
||
SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, LpcServerPort );
|
||
AuditParameters.ParameterCount++;
|
||
|
||
SepAdtLogAuditRecord( &AuditParameters );
|
||
|
||
SeReleaseSubjectContext( &SubjectSecurityContext );
|
||
|
||
if ( ImageFileName != &NullString ) {
|
||
ExFreePool( ImageFileName );
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
|
||
|
||
VOID
|
||
SeAuditSystemTimeChange(
|
||
IN LARGE_INTEGER OldTime,
|
||
IN LARGE_INTEGER NewTime
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Audits the modification of system time.
|
||
|
||
Arguments:
|
||
|
||
OldTime - Time before modification.
|
||
NewTime - Time after modification.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
SE_ADT_PARAMETER_ARRAY AuditParameters;
|
||
PSID UserSid;
|
||
LUID LogonId;
|
||
HANDLE ProcessId;
|
||
PEPROCESS Process;
|
||
PUNICODE_STRING ImageFileName;
|
||
UNICODE_STRING NullString = {0};
|
||
NTSTATUS Status;
|
||
SECURITY_SUBJECT_CONTEXT SubjectSecurityContext;
|
||
|
||
PAGED_CODE();
|
||
|
||
SeCaptureSubjectContext( &SubjectSecurityContext );
|
||
|
||
//
|
||
// Make sure that we care to audit system events.
|
||
//
|
||
|
||
if (SepAdtAuditThisEventWithContext(AuditCategorySystem, TRUE, FALSE, &SubjectSecurityContext)) {
|
||
|
||
UserSid = SepTokenUserSid( EffectiveToken(&SubjectSecurityContext) );
|
||
LogonId = SepTokenAuthenticationId( SubjectSecurityContext.PrimaryToken );
|
||
|
||
Process = PsGetCurrentProcess();
|
||
|
||
RtlZeroMemory (
|
||
(PVOID) &AuditParameters,
|
||
sizeof( AuditParameters )
|
||
);
|
||
|
||
Status = SeLocateProcessImageName( Process, &ImageFileName );
|
||
|
||
if ( !NT_SUCCESS(Status) ) {
|
||
ImageFileName = &NullString;
|
||
}
|
||
|
||
ASSERT( SeAdtParmTypeNone == 0 );
|
||
|
||
AuditParameters.CategoryId = SE_CATEGID_SYSTEM;
|
||
AuditParameters.AuditId = SE_AUDITID_SYSTEM_TIME_CHANGE;
|
||
AuditParameters.ParameterCount = 0;
|
||
AuditParameters.Type = EVENTLOG_AUDIT_SUCCESS;
|
||
|
||
SepSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, UserSid );
|
||
AuditParameters.ParameterCount++;
|
||
|
||
SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, (PUNICODE_STRING)&SeSubsystemName );
|
||
AuditParameters.ParameterCount++;
|
||
|
||
ProcessId = PsProcessAuditId( Process );
|
||
|
||
SepSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, ProcessId );
|
||
AuditParameters.ParameterCount++;
|
||
|
||
SepSetParmTypeFileSpec( AuditParameters, AuditParameters.ParameterCount, ImageFileName );
|
||
AuditParameters.ParameterCount++;
|
||
|
||
SepSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, LogonId );
|
||
AuditParameters.ParameterCount++;
|
||
|
||
if ( SubjectSecurityContext.ClientToken ) {
|
||
|
||
SepSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, SepTokenAuthenticationId( SubjectSecurityContext.ClientToken ));
|
||
} else {
|
||
|
||
SepSetParmTypeNoLogon( AuditParameters, AuditParameters.ParameterCount );
|
||
}
|
||
|
||
AuditParameters.ParameterCount++;
|
||
SepSetParmTypeTime( AuditParameters, AuditParameters.ParameterCount, OldTime );
|
||
AuditParameters.ParameterCount++;
|
||
|
||
SepSetParmTypeTime( AuditParameters, AuditParameters.ParameterCount, NewTime );
|
||
AuditParameters.ParameterCount++;
|
||
|
||
SepAdtLogAuditRecord( &AuditParameters );
|
||
|
||
if ( ImageFileName != &NullString ) {
|
||
ExFreePool( ImageFileName );
|
||
}
|
||
}
|
||
SeReleaseSubjectContext( &SubjectSecurityContext );
|
||
}
|
||
|
||
|
||
VOID
|
||
SeAuditHardLinkCreation(
|
||
IN PUNICODE_STRING FileName,
|
||
IN PUNICODE_STRING LinkName,
|
||
IN BOOLEAN bSuccess
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Audits the attempted creation of a hard link.
|
||
|
||
The caller checks audit policy.
|
||
|
||
Arguments:
|
||
|
||
FileName - Name of the original file.
|
||
|
||
LinkName - The name of the hard link.
|
||
|
||
bSuccess - Boolean indicating if the hard link creation attempt was successful or not.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
LUID UserAuthenticationId;
|
||
PSID UserSid;
|
||
SECURITY_SUBJECT_CONTEXT SubjectSecurityContext;
|
||
SE_ADT_PARAMETER_ARRAY AuditParameters = { 0 };
|
||
|
||
PAGED_CODE();
|
||
|
||
ASSERT( SeAdtParmTypeNone == 0 );
|
||
|
||
AuditParameters.CategoryId = SE_CATEGID_OBJECT_ACCESS;
|
||
AuditParameters.AuditId = SE_AUDITID_HARDLINK_CREATION;
|
||
AuditParameters.ParameterCount = 0;
|
||
AuditParameters.Type = bSuccess ? EVENTLOG_AUDIT_SUCCESS : EVENTLOG_AUDIT_FAILURE;
|
||
|
||
//
|
||
// Use the effective token.
|
||
//
|
||
|
||
SeCaptureSubjectContext( &SubjectSecurityContext );
|
||
UserSid = SepTokenUserSid( EffectiveToken( &SubjectSecurityContext ));
|
||
UserAuthenticationId = SepTokenAuthenticationId( EffectiveToken( &SubjectSecurityContext ));
|
||
|
||
//
|
||
// Fill in the AuditParameters structure.
|
||
//
|
||
|
||
SepSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, UserSid );
|
||
AuditParameters.ParameterCount++;
|
||
|
||
SepSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, (PUNICODE_STRING)&SeSubsystemName );
|
||
AuditParameters.ParameterCount++;
|
||
|
||
SepSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, UserAuthenticationId );
|
||
AuditParameters.ParameterCount++;
|
||
|
||
SepSetParmTypeFileSpec( AuditParameters, AuditParameters.ParameterCount, FileName );
|
||
AuditParameters.ParameterCount++;
|
||
|
||
SepSetParmTypeFileSpec( AuditParameters, AuditParameters.ParameterCount, LinkName );
|
||
AuditParameters.ParameterCount++;
|
||
|
||
SepAdtLogAuditRecord( &AuditParameters );
|
||
|
||
SeReleaseSubjectContext( &SubjectSecurityContext );
|
||
|
||
return;
|
||
}
|