You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3955 lines
97 KiB
3955 lines
97 KiB
/*++
|
|
|
|
Copyright (c) 1991 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
adtevent.c
|
|
|
|
Abstract:
|
|
|
|
Functions that implement audits generated by LSA itself.
|
|
|
|
Author:
|
|
|
|
Scott Birrell (ScottBi) January 19, 1993
|
|
|
|
Environment:
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include <lsapch2.h>
|
|
#include "adtp.h"
|
|
#include "adtutil.h"
|
|
#include "adtdebug.h"
|
|
#include "msobjs.h"
|
|
|
|
//
|
|
// Forwards
|
|
//
|
|
NTSTATUS
|
|
LsapAdtGetDbAttributesChangeString(
|
|
IN LSAP_DB_ATTRIBUTE* OldAttributes,
|
|
IN LSAP_DB_ATTRIBUTE* NewAttributes,
|
|
IN ULONG AttributeCount,
|
|
OUT LPWSTR* AttributeChangeString
|
|
);
|
|
|
|
|
|
NTSTATUS
|
|
LsapAdtGenerateObjectOperationAuditEvent(
|
|
IN LSAPR_HANDLE ObjectHandle,
|
|
IN USHORT AuditEventType,
|
|
IN OBJECT_OPERATION_TYPE OperationType
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Generates an audit entry when an operation on the object
|
|
represented by ObjectHandle succeeds/fails and if this type of
|
|
auditing is enabled.
|
|
|
|
Arguments:
|
|
|
|
ObjectHandle - Handle of the object being accessed
|
|
|
|
AuditEventType - The type of audit event to be generated.
|
|
EVENTLOG_AUDIT_SUCCESS or EVENTLOG_AUDIT_FAILURE
|
|
|
|
OperationType - Type of operation performed on the object
|
|
represented by ObjectHandle.
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS - Standard Nt Result Code
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
SE_ADT_PARAMETER_ARRAY AuditParameters;
|
|
LUID ClientAuthenticationId;
|
|
PTOKEN_USER TokenUserInformation=NULL;
|
|
UNICODE_STRING OperationTypeName;
|
|
LSAP_DB_HANDLE InternalHandle;
|
|
UNICODE_STRING ObjectName;
|
|
LUID SystemAuthId = SYSTEM_LUID;
|
|
BOOLEAN bAudit;
|
|
|
|
static LPCWSTR ObjectOperationNames[ObjectOperationDummyLast] = {
|
|
L"None",
|
|
L"Query"
|
|
};
|
|
|
|
LsapEnterFunc("LsapAdtGenerateObjectAcessAuditEvent");
|
|
|
|
InternalHandle = (LSAP_DB_HANDLE) ObjectHandle;
|
|
|
|
Status = LsapQueryClientInfo(
|
|
&TokenUserInformation,
|
|
&ClientAuthenticationId
|
|
);
|
|
|
|
if ( !NT_SUCCESS( Status )) {
|
|
goto Cleanup;
|
|
}
|
|
|
|
if ( RtlEqualLuid( &ClientAuthenticationId, &SystemAuthId )) {
|
|
|
|
//
|
|
// do not audit secret queries by the system
|
|
//
|
|
|
|
goto Cleanup;
|
|
}
|
|
|
|
Status = LsapAdtAuditingEnabledByLogonId(
|
|
AuditCategoryObjectAccess,
|
|
&ClientAuthenticationId,
|
|
AuditEventType,
|
|
&bAudit
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status) || !bAudit)
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// LsarQuerySecret sometimes passes us a secret whose name will
|
|
// be rejected by ElfReportEventW because the length parameter
|
|
// includes the terminating NULL.
|
|
//
|
|
// For example,
|
|
// name.Buffer = "foo\0"
|
|
// name.Length = 8
|
|
// name.MaximumLength = 8
|
|
//
|
|
// We cannot change the input param or change the LSA code to
|
|
// not do this, therfore we make a local copy, fix it
|
|
// and use that instead
|
|
//
|
|
|
|
ObjectName = InternalHandle->PhysicalNameU;
|
|
ObjectName.Length = (USHORT) LsapSafeWcslen( ObjectName.Buffer,
|
|
ObjectName.MaximumLength );
|
|
|
|
//
|
|
// Build an audit parameters structure.
|
|
//
|
|
RtlInitUnicodeString( &OperationTypeName, ObjectOperationNames[OperationType] );
|
|
|
|
Status =
|
|
LsapAdtInitParametersArray(
|
|
&AuditParameters,
|
|
SE_CATEGID_OBJECT_ACCESS,
|
|
SE_AUDITID_OBJECT_OPERATION,
|
|
AuditEventType,
|
|
13, // there are 13 params to init
|
|
|
|
//
|
|
// User Sid
|
|
//
|
|
SeAdtParmTypeSid, TokenUserInformation->User.Sid,
|
|
|
|
//
|
|
// Subsystem name
|
|
//
|
|
SeAdtParmTypeString, &LsapSubsystemName,
|
|
|
|
//
|
|
// Object server
|
|
//
|
|
SeAdtParmTypeString, &LsapLsaName,
|
|
|
|
//
|
|
// Operation Type
|
|
//
|
|
SeAdtParmTypeString, &OperationTypeName,
|
|
|
|
//
|
|
// Object Type : index of this is 4, used later
|
|
//
|
|
SeAdtParmTypeString, &LsapDbObjectTypeNames[InternalHandle->
|
|
ObjectTypeId],
|
|
|
|
//
|
|
// Object Name
|
|
//
|
|
SeAdtParmTypeString, &ObjectName,
|
|
|
|
//
|
|
// Object Handle ID
|
|
//
|
|
SeAdtParmTypePtr, ObjectHandle,
|
|
|
|
//
|
|
// Primary Authentication information
|
|
//
|
|
SeAdtParmTypeLogonId, LsapSystemLogonId,
|
|
|
|
//
|
|
// Clients's Authentication information
|
|
//
|
|
SeAdtParmTypeLogonId, ClientAuthenticationId,
|
|
|
|
//
|
|
// Requested access : 4 is the index of ObjectType parameter
|
|
//
|
|
SeAdtParmTypeAccessMask, InternalHandle->RequestedAccess, 4,
|
|
|
|
//
|
|
// there are no object properties (object-type list)
|
|
//
|
|
SeAdtParmTypeNone,
|
|
|
|
//
|
|
// no additional information
|
|
//
|
|
SeAdtParmTypeNone,
|
|
|
|
//
|
|
// Access Mask (hex)
|
|
//
|
|
SeAdtParmTypeHexUlong, InternalHandle->RequestedAccess
|
|
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
|
|
( VOID ) LsapAdtWriteLog( &AuditParameters );
|
|
|
|
Cleanup:
|
|
|
|
if (TokenUserInformation != NULL)
|
|
{
|
|
LsapFreeLsaHeap( TokenUserInformation );
|
|
}
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
|
|
LsapAuditFailed( Status );
|
|
}
|
|
|
|
LsapExitFunc("LsapAdtGenerateObjectAcessAuditEvent", Status);
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
LsapAdtGenerateLsaAuditEvent(
|
|
IN LSAPR_HANDLE ObjectHandle,
|
|
IN ULONG AuditEventCategory,
|
|
IN ULONG AuditEventId,
|
|
IN PPRIVILEGE_SET Privileges,
|
|
IN ULONG SidCount,
|
|
IN PSID *Sids OPTIONAL,
|
|
IN ULONG UnicodeStringCount,
|
|
IN PUNICODE_STRING UnicodeStrings OPTIONAL,
|
|
IN PLSARM_POLICY_AUDIT_EVENTS_INFO PolicyAuditEventsInfo OPTIONAL
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function generates an Lsa-originated Audit Event. Audit Events
|
|
of this kind are generated as a result of Local Security Policy changes
|
|
such as assigning/removing user rights to an account.
|
|
|
|
Arguments:
|
|
|
|
ObjectHandle - Specifies the handle of an object in the Lsa Policy
|
|
Database. For global changes to policy, a handle to the
|
|
Lsa Policy object is passed.
|
|
|
|
AuditEventCategory - Specifies the Id of the Audit Event Category
|
|
to which this Audit Event belongs.
|
|
|
|
AuditEventId - Specifies the Id of the Audit Event being generated.
|
|
|
|
Privileges - set of privileges to be recorded
|
|
|
|
SidCount - Count of Sids being passed via the Sids parameter. If no
|
|
Sids are passed, this parameter must be set to 0.
|
|
|
|
Sids - Pointer to array of SidCount Sids. If 0 is passed for the
|
|
SidCount parameter, this parameter is ignored and NULL may be
|
|
specified.
|
|
|
|
UnicodeStringCount - Count of Unicode Strings being passed via the
|
|
UnicodeStrings parameter. If no Unicode Strings are passed, this
|
|
parameter must be set to 0.
|
|
|
|
UnicodeStrings - Pointer to array of UnicodeStringCount strings. If 0 is
|
|
passed for the SidCount parameter, this parameter is ignored and NULL
|
|
may be specified.
|
|
|
|
PolicyAuditEventsInfo - Pointer to Auditing Events information structure
|
|
containing the AuditingMode and the array of Policy Audit Event
|
|
Information entries. This parameter must be non-NULL if and only if
|
|
the AuditEventCategory parameter is SE_AUDIT_POLICY_CHANGE.
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
LUID ClientAuthenticationId;
|
|
PTOKEN_USER TokenUserInformation = NULL;
|
|
PSID ClientSid;
|
|
BOOLEAN bAudit;
|
|
|
|
UNREFERENCED_PARAMETER( ObjectHandle );
|
|
|
|
if (Privileges && !IsValidPrivilegeCount(Privileges->PrivilegeCount)) {
|
|
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
Status = LsapQueryClientInfo(
|
|
&TokenUserInformation,
|
|
&ClientAuthenticationId
|
|
);
|
|
|
|
if ( !NT_SUCCESS( Status )) {
|
|
|
|
goto Cleanup;
|
|
}
|
|
|
|
ClientSid = TokenUserInformation->User.Sid;
|
|
|
|
if (AuditEventId != SE_AUDITID_POLICY_CHANGE) {
|
|
|
|
Status = LsapAdtAuditingEnabledByLogonId(
|
|
LsapAdtEventTypeFromCategoryId(AuditEventCategory),
|
|
&ClientAuthenticationId,
|
|
EVENTLOG_AUDIT_SUCCESS,
|
|
&bAudit
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status) || !bAudit) {
|
|
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
|
|
Status = LsapAdtGenerateLsaAuditEventWithClientSid( AuditEventCategory,
|
|
AuditEventId,
|
|
ClientSid,
|
|
ClientAuthenticationId,
|
|
Privileges,
|
|
SidCount,
|
|
Sids,
|
|
UnicodeStringCount,
|
|
UnicodeStrings,
|
|
PolicyAuditEventsInfo );
|
|
|
|
|
|
|
|
Cleanup:
|
|
|
|
if (TokenUserInformation != NULL)
|
|
{
|
|
LsapFreeLsaHeap( TokenUserInformation );
|
|
}
|
|
|
|
if ( !NT_SUCCESS( Status )) {
|
|
|
|
LsapAuditFailed( Status );
|
|
}
|
|
|
|
return(Status);
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
LsapAdtGenerateLsaAuditEventWithClientSid(
|
|
IN ULONG AuditEventCategory,
|
|
IN ULONG AuditEventId,
|
|
IN PSID ClientSid,
|
|
IN LUID ClientAuthenticationId,
|
|
IN PPRIVILEGE_SET Privileges,
|
|
IN ULONG SidCount,
|
|
IN PSID *Sids OPTIONAL,
|
|
IN ULONG UnicodeStringCount,
|
|
IN PUNICODE_STRING UnicodeStrings OPTIONAL,
|
|
IN PLSARM_POLICY_AUDIT_EVENTS_INFO PolicyAuditEventsInfo OPTIONAL
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function generates an Lsa-originated Audit Event. Audit Events
|
|
of this kind are generated as a result of Local Security Policy changes
|
|
such as assigning/removing user rights to an account.
|
|
|
|
|
|
The decision to generate these audits is made in LsapAdtGenerateLsaAuditEvent.
|
|
|
|
Arguments:
|
|
|
|
ObjectHandle - Specifies the handle of an object in the Lsa Policy
|
|
Database. For global changes to policy, a handle to the
|
|
Lsa Policy object is passed.
|
|
|
|
AuditEventCategory - Specifies the Id of the Audit Event Category
|
|
to which this Audit Event belongs.
|
|
|
|
AuditEventId - Specifies the Id of the Audit Event being generated.
|
|
|
|
Privileges - set of privileges to be recorded
|
|
|
|
SidCount - Count of Sids being passed via the Sids parameter. If no
|
|
Sids are passed, this parameter must be set to 0.
|
|
|
|
Sids - Pointer to array of SidCount Sids. If 0 is passed for the
|
|
SidCount parameter, this parameter is ignored and NULL may be
|
|
specified.
|
|
|
|
UnicodeStringCount - Count of Unicode Strings being passed via the
|
|
UnicodeStrings parameter. If no Unicode Strings are passed, this
|
|
parameter must be set to 0.
|
|
|
|
UnicodeStrings - Pointer to array of UnicodeStringCount strings. If 0 is
|
|
passed for the SidCount parameter, this parameter is ignored and NULL
|
|
may be specified.
|
|
|
|
PolicyAuditEventsInfo - Pointer to Auditing Events information structure
|
|
containing the AuditingMode and the array of Policy Audit Event
|
|
Information entries. This parameter must be non-NULL if and only if
|
|
the AuditEventCategory parameter is SE_AUDIT_POLICY_CHANGE.
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
UNICODE_STRING NullString = {0};
|
|
|
|
if (NULL == UnicodeStrings)
|
|
{
|
|
UnicodeStrings = &NullString;
|
|
}
|
|
|
|
UNREFERENCED_PARAMETER( UnicodeStringCount );
|
|
UNREFERENCED_PARAMETER( SidCount );
|
|
|
|
switch ( AuditEventCategory ) {
|
|
case SE_CATEGID_POLICY_CHANGE:
|
|
{
|
|
switch ( AuditEventId ) {
|
|
|
|
default:
|
|
DsysAssertMsg(FALSE, "LsapAdtGenerateLsaAuditEventWithClientSid: invalid AuditEventId");
|
|
break;
|
|
|
|
case SE_AUDITID_POLICY_CHANGE:
|
|
{
|
|
LsapAdtPolicyChange(
|
|
(USHORT)AuditEventCategory,
|
|
AuditEventId,
|
|
EVENTLOG_AUDIT_SUCCESS,
|
|
ClientSid,
|
|
ClientAuthenticationId,
|
|
PolicyAuditEventsInfo
|
|
);
|
|
break;
|
|
}
|
|
|
|
case SE_AUDITID_USER_RIGHT_ASSIGNED:
|
|
case SE_AUDITID_USER_RIGHT_REMOVED:
|
|
{
|
|
DsysAssertMsg( SidCount == 1,
|
|
"LsapAdtGenerateLsaAuditEventWithClientSid" );
|
|
LsapAdtUserRightAssigned(
|
|
(USHORT)AuditEventCategory,
|
|
AuditEventId,
|
|
EVENTLOG_AUDIT_SUCCESS,
|
|
ClientSid,
|
|
ClientAuthenticationId,
|
|
Sids[0],
|
|
Privileges
|
|
);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
{
|
|
DsysAssertMsg( FALSE, "LsapAdtGenerateLsaAuditEventWithClientSid: unsupported audit category" );
|
|
return( STATUS_SUCCESS );
|
|
}
|
|
}
|
|
|
|
|
|
return(Status);
|
|
}
|
|
|
|
|
|
VOID
|
|
LsapAdtUserRightAssigned(
|
|
IN USHORT EventCategory,
|
|
IN ULONG EventID,
|
|
IN USHORT EventType,
|
|
IN PSID ClientSid,
|
|
IN LUID CallerAuthenticationId,
|
|
IN PSID TargetSid,
|
|
IN PPRIVILEGE_SET Privileges
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Generates an audit for a user right being either assigned or removed.
|
|
|
|
The decision to generate this audit is made in LsapAdtGenerateLsaAuditEvent.
|
|
|
|
Arguments:
|
|
|
|
ISSUE-2002/03/11-kumarp : add desc
|
|
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
SE_ADT_PARAMETER_ARRAY AuditParameters;
|
|
|
|
//
|
|
// if no privileges are being assigned/removed, dont generate the audit
|
|
//
|
|
|
|
if (!(Privileges && Privileges->PrivilegeCount))
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Build an audit parameters structure.
|
|
//
|
|
|
|
RtlZeroMemory (
|
|
(PVOID) &AuditParameters,
|
|
sizeof( AuditParameters )
|
|
);
|
|
|
|
AuditParameters.CategoryId = EventCategory;
|
|
AuditParameters.AuditId = EventID;
|
|
AuditParameters.Type = EventType;
|
|
AuditParameters.ParameterCount = 0;
|
|
|
|
//
|
|
// User Sid
|
|
//
|
|
|
|
LsapSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, ClientSid );
|
|
AuditParameters.ParameterCount++;
|
|
|
|
//
|
|
// Subsystem name (if available)
|
|
//
|
|
|
|
LsapSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, &LsapSubsystemName );
|
|
AuditParameters.ParameterCount++;
|
|
|
|
//
|
|
// Rights
|
|
//
|
|
|
|
LsapSetParmTypePrivileges( AuditParameters, AuditParameters.ParameterCount, Privileges );
|
|
AuditParameters.ParameterCount++;
|
|
|
|
//
|
|
// Target Sid
|
|
//
|
|
|
|
LsapSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, TargetSid );
|
|
AuditParameters.ParameterCount++;
|
|
|
|
//
|
|
// Caller's Authentication information
|
|
//
|
|
|
|
LsapSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, CallerAuthenticationId );
|
|
AuditParameters.ParameterCount++;
|
|
|
|
|
|
( VOID ) LsapAdtWriteLog( &AuditParameters );
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
VOID
|
|
LsapAdtGenerateLsaAuditSystemAccessChange(
|
|
IN USHORT EventCategory,
|
|
IN ULONG EventID,
|
|
IN USHORT EventType,
|
|
IN PSID ClientSid,
|
|
IN LUID CallerAuthenticationId,
|
|
IN PSID TargetSid,
|
|
IN PCWSTR szSystemAccess
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Generates an audit for System Security Access changes.
|
|
|
|
The decision to generate this audit is made in LsapSetSystemAccessAccount.
|
|
|
|
Arguments:
|
|
|
|
EventCategory - The category of this event
|
|
EventID - specific ID of event
|
|
EventType - success or failure
|
|
ClientSid - sid of client
|
|
CallerAuthenticationID - Logon ID of caller
|
|
TargetSid - receives access change
|
|
szSystemAccess - string describing which access changed
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
SE_ADT_PARAMETER_ARRAY AuditParameters;
|
|
UNICODE_STRING SystemAccessString;
|
|
|
|
//
|
|
// Build an audit parameters structure.
|
|
//
|
|
|
|
RtlZeroMemory (
|
|
(PVOID) &AuditParameters,
|
|
sizeof( AuditParameters )
|
|
);
|
|
|
|
RtlInitUnicodeString( &SystemAccessString, szSystemAccess );
|
|
|
|
Status =
|
|
LsapAdtInitParametersArray( &AuditParameters,
|
|
EventCategory,
|
|
EventID,
|
|
EventType,
|
|
5,
|
|
SeAdtParmTypeSid, ClientSid,
|
|
SeAdtParmTypeString, &LsapSubsystemName,
|
|
SeAdtParmTypeLogonId, CallerAuthenticationId,
|
|
SeAdtParmTypeString, &SystemAccessString,
|
|
SeAdtParmTypeSid, TargetSid
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
(VOID) LsapAdtWriteLog( &AuditParameters );
|
|
|
|
Cleanup:
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
LsapAuditFailed( Status );
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NTSTATUS
|
|
LsapAdtTrustedDomainAdd(
|
|
IN USHORT EventType,
|
|
IN PUNICODE_STRING pName,
|
|
IN PSID pSid,
|
|
IN ULONG Type,
|
|
IN ULONG Direction,
|
|
IN ULONG Attributes
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Generate an audit event when a trusted domain object (TDO) is created.
|
|
|
|
Arguments:
|
|
|
|
EventType - EVENTLOG_AUDIT_SUCCESS or EVENTLOG_AUDIT_FAILURE
|
|
|
|
pName - name of the domain
|
|
|
|
pSid - domain SID
|
|
|
|
Type - TDO type
|
|
|
|
Direction - TDO direction
|
|
|
|
Attributes - TDO attributes
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS - Standard Nt Result Code
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
LUID ClientAuthenticationId;
|
|
PTOKEN_USER TokenUserInformation=NULL;
|
|
SE_ADT_PARAMETER_ARRAY AuditParameters = { 0 };
|
|
BOOLEAN bAudit = FALSE;
|
|
|
|
Status = LsapQueryClientInfo( &TokenUserInformation, &ClientAuthenticationId );
|
|
|
|
if ( !NT_SUCCESS( Status ))
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
Status = LsapAdtAuditingEnabledByLogonId(
|
|
AuditCategoryPolicyChange,
|
|
&ClientAuthenticationId,
|
|
EventType,
|
|
&bAudit
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status) || !bAudit)
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Build an audit parameters structure.
|
|
//
|
|
|
|
Status =
|
|
LsapAdtInitParametersArray(
|
|
&AuditParameters,
|
|
SE_CATEGID_POLICY_CHANGE,
|
|
SE_AUDITID_TRUSTED_DOMAIN_ADD,
|
|
EventType,
|
|
9, // there are 9 params to init
|
|
|
|
//
|
|
// User Sid
|
|
//
|
|
|
|
SeAdtParmTypeSid, TokenUserInformation->User.Sid,
|
|
|
|
//
|
|
// Subsystem name (if available)
|
|
//
|
|
|
|
SeAdtParmTypeString, &LsapSubsystemName,
|
|
|
|
//
|
|
// domain name
|
|
//
|
|
|
|
SeAdtParmTypeString, pName,
|
|
|
|
//
|
|
// domain id
|
|
//
|
|
|
|
SeAdtParmTypeSid, pSid,
|
|
|
|
//
|
|
// client auth-id
|
|
//
|
|
|
|
SeAdtParmTypeLogonId, ClientAuthenticationId,
|
|
|
|
//
|
|
// TDO type
|
|
//
|
|
|
|
SeAdtParmTypeUlong, Type,
|
|
|
|
//
|
|
// TDO direction
|
|
//
|
|
|
|
SeAdtParmTypeUlong, Direction,
|
|
|
|
//
|
|
// TDO attributes
|
|
//
|
|
|
|
SeAdtParmTypeUlong, Attributes,
|
|
|
|
//
|
|
// TDO: attribute quarantined spelled out
|
|
//
|
|
|
|
SeAdtParmTypeMessage, (Attributes & TRUST_ATTRIBUTE_QUARANTINED_DOMAIN) ? SE_ADT_MSG_ENABLED : SE_ADT_MSG_DISABLED
|
|
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
Status = LsapAdtWriteLog( &AuditParameters );
|
|
|
|
Cleanup:
|
|
|
|
if (TokenUserInformation != NULL)
|
|
{
|
|
LsapFreeLsaHeap( TokenUserInformation );
|
|
}
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
LsapAuditFailed( Status );
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
LsapAdtTrustedDomainRem(
|
|
IN USHORT EventType,
|
|
IN PUNICODE_STRING pName,
|
|
IN PSID pSid,
|
|
IN PSID pClientSid,
|
|
IN PLUID pClientAuthId
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Generate an audit event when a trusted domain object (TDO) is deleted.
|
|
|
|
Arguments:
|
|
|
|
EventType - EVENTLOG_AUDIT_SUCCESS or EVENTLOG_AUDIT_FAILURE
|
|
|
|
pName - name of the domain
|
|
|
|
pSid - domain SID
|
|
|
|
pClientSid - SID of the client who deleted the TDO
|
|
if NULL, it is determined from the thread token
|
|
|
|
pClientAuthId- auth-id of the client who deleted the TDO
|
|
if NULL, it is determined from the thread token
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS - Standard Nt Result Code
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
LUID ClientAuthenticationId;
|
|
PTOKEN_USER TokenUserInformation=NULL;
|
|
SE_ADT_PARAMETER_ARRAY AuditParameters = { 0 };
|
|
BOOLEAN bAudit = FALSE;
|
|
|
|
if ( pClientSid == NULL )
|
|
{
|
|
DsysAssertMsg( pClientAuthId == NULL, "LsapAdtTrustedDomainRem" );
|
|
|
|
Status = LsapQueryClientInfo( &TokenUserInformation,
|
|
&ClientAuthenticationId );
|
|
|
|
if ( !NT_SUCCESS( Status ))
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
pClientSid = TokenUserInformation->User.Sid;
|
|
pClientAuthId = &ClientAuthenticationId;
|
|
}
|
|
#if DBG
|
|
else
|
|
{
|
|
DsysAssertMsg( pClientAuthId != NULL, "LsapAdtTrustedDomainRem" );
|
|
}
|
|
#endif
|
|
|
|
Status = LsapAdtAuditingEnabledByLogonId(
|
|
AuditCategoryPolicyChange,
|
|
pClientAuthId,
|
|
EventType,
|
|
&bAudit
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status) || !bAudit)
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Build an audit parameters structure.
|
|
//
|
|
|
|
Status =
|
|
LsapAdtInitParametersArray(
|
|
&AuditParameters,
|
|
SE_CATEGID_POLICY_CHANGE,
|
|
SE_AUDITID_TRUSTED_DOMAIN_REM,
|
|
EventType,
|
|
5, // there are 5 params to init
|
|
|
|
//
|
|
// User Sid
|
|
//
|
|
|
|
SeAdtParmTypeSid, pClientSid,
|
|
|
|
//
|
|
// Subsystem name (if available)
|
|
//
|
|
|
|
SeAdtParmTypeString, &LsapSubsystemName,
|
|
|
|
//
|
|
// domain name
|
|
//
|
|
|
|
SeAdtParmTypeString, pName,
|
|
|
|
//
|
|
// domain id (SID of the root domain)
|
|
//
|
|
|
|
SeAdtParmTypeSid, pSid,
|
|
|
|
//
|
|
// client auth-id
|
|
//
|
|
|
|
SeAdtParmTypeLogonId, *pClientAuthId
|
|
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
Status = LsapAdtWriteLog( &AuditParameters );
|
|
|
|
Cleanup:
|
|
|
|
if (TokenUserInformation != NULL)
|
|
{
|
|
LsapFreeLsaHeap( TokenUserInformation );
|
|
}
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
LsapAuditFailed( Status );
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
LsapAdtTrustedDomainMod(
|
|
IN USHORT EventType,
|
|
IN PSID pDomainSid,
|
|
|
|
IN PUNICODE_STRING pOldName,
|
|
IN ULONG OldType,
|
|
IN ULONG OldDirection,
|
|
IN ULONG OldAttributes,
|
|
|
|
IN PUNICODE_STRING pNewName,
|
|
IN ULONG NewType,
|
|
IN ULONG NewDirection,
|
|
IN ULONG NewAttributes
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Generate an audit event when a trusted domain object (TDO) is modified.
|
|
the unmodified fields are represented by a '-' in the audit log.
|
|
|
|
Arguments:
|
|
|
|
EventType - EVENTLOG_AUDIT_SUCCESS or EVENTLOG_AUDIT_FAILURE
|
|
|
|
pOldName - old name of the domain
|
|
|
|
pOldSid - old domain SID
|
|
|
|
OldType - old TDO type
|
|
|
|
OldDirection - old TDO direction
|
|
|
|
OldAttributes - old TDO attributes
|
|
|
|
pNewName - new name of the domain
|
|
|
|
pNewSid - new domain SID
|
|
|
|
NewType - new TDO type
|
|
|
|
NewDirection - new TDO direction
|
|
|
|
NewAttributes - new TDO attributes
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS - Standard Nt Result Code
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
LUID ClientAuthenticationId;
|
|
PTOKEN_USER TokenUserInformation=NULL;
|
|
SE_ADT_PARAMETER_ARRAY AuditParameters = { 0 };
|
|
BOOLEAN bAudit = FALSE;
|
|
|
|
Status = LsapQueryClientInfo( &TokenUserInformation, &ClientAuthenticationId );
|
|
|
|
if ( !NT_SUCCESS( Status ))
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// if auditing is not enabled, return asap
|
|
//
|
|
|
|
Status = LsapAdtAuditingEnabledByLogonId(
|
|
AuditCategoryPolicyChange,
|
|
&ClientAuthenticationId,
|
|
EventType,
|
|
&bAudit
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status) || !bAudit)
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
AuditParameters.CategoryId = SE_CATEGID_POLICY_CHANGE;
|
|
AuditParameters.AuditId = SE_AUDITID_TRUSTED_DOMAIN_MOD;
|
|
AuditParameters.Type = EventType;
|
|
AuditParameters.ParameterCount = 9;
|
|
|
|
//
|
|
// User Sid
|
|
//
|
|
|
|
LsapSetParmTypeSid( AuditParameters, 0, TokenUserInformation->User.Sid );
|
|
|
|
//
|
|
// Subsystem name (if available)
|
|
//
|
|
|
|
LsapSetParmTypeString( AuditParameters, 1, &LsapSubsystemName );
|
|
|
|
|
|
//
|
|
// for all subsequent fields (except the domain SID),
|
|
// output a value only if it changed.
|
|
//
|
|
|
|
//
|
|
// domain name
|
|
//
|
|
|
|
if ( pOldName && pNewName &&
|
|
!RtlEqualUnicodeString( pOldName, pNewName, TRUE ) )
|
|
{
|
|
LsapSetParmTypeString( AuditParameters, 2, pNewName );
|
|
}
|
|
|
|
//
|
|
// domain id
|
|
//
|
|
|
|
LsapSetParmTypeSid( AuditParameters, 3, pDomainSid );
|
|
|
|
//
|
|
// client auth-id
|
|
//
|
|
|
|
LsapSetParmTypeLogonId( AuditParameters, 4, ClientAuthenticationId );
|
|
|
|
//
|
|
// TDO type
|
|
//
|
|
|
|
if ( OldType != NewType )
|
|
{
|
|
LsapSetParmTypeUlong( AuditParameters, 5, NewType );
|
|
}
|
|
|
|
//
|
|
// TDO direction
|
|
//
|
|
|
|
if ( OldDirection != NewDirection )
|
|
{
|
|
LsapSetParmTypeUlong( AuditParameters, 6, NewDirection );
|
|
}
|
|
|
|
//
|
|
// TDO attributes
|
|
//
|
|
|
|
if ( OldAttributes != NewAttributes )
|
|
{
|
|
LsapSetParmTypeUlong( AuditParameters, 7, NewAttributes );
|
|
}
|
|
|
|
//
|
|
// TDO attributes
|
|
//
|
|
|
|
if ( OldAttributes != NewAttributes )
|
|
{
|
|
LsapSetParmTypeMessage( AuditParameters, 8, (NewAttributes & TRUST_ATTRIBUTE_QUARANTINED_DOMAIN) ? SE_ADT_MSG_ENABLED : SE_ADT_MSG_DISABLED );
|
|
}
|
|
|
|
Status = LsapAdtWriteLog( &AuditParameters );
|
|
|
|
Cleanup:
|
|
|
|
if (TokenUserInformation != NULL)
|
|
{
|
|
LsapFreeLsaHeap( TokenUserInformation );
|
|
}
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
LsapAuditFailed( Status );
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
LsapAdtTrustedForestNamespaceCollision(
|
|
IN LSA_FOREST_TRUST_COLLISION_RECORD_TYPE CollisionTargetType,
|
|
IN PUNICODE_STRING pCollisionTargetName,
|
|
IN PUNICODE_STRING pForestRootDomainName,
|
|
IN PUNICODE_STRING pTopLevelName,
|
|
IN PUNICODE_STRING pDnsName,
|
|
IN PUNICODE_STRING pNetbiosName,
|
|
IN PSID pSid,
|
|
IN ULONG NewFlags
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function generates the audit event that represents
|
|
a namespace element collision.
|
|
|
|
|
|
Arguments:
|
|
|
|
CollisionTargetType - type of the collision target
|
|
CollisionTdo : indicates a collision with a namespace element of
|
|
another forest
|
|
CollisionXref : indicates a collision with a domain in our forest
|
|
|
|
pCollisionTargetName -
|
|
name of the collision target (TDO name or Xref name)
|
|
|
|
pForestRootDomainName - name of other forest
|
|
|
|
pTopLevelName - top level name (NULL == not in conflict)
|
|
|
|
pDnsName - DNS domain name (this is NULL if TLN is non-NULL)
|
|
|
|
pNetbiosName - NetBIOS name (NULL == not in conflict)
|
|
|
|
pSid - SID of domain (NULL == not in conflict)
|
|
|
|
NewFlags - the new value of flags
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS - Standard Nt Result Code
|
|
|
|
Notes:
|
|
|
|
This event is generated only in the success case.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
SE_ADT_PARAMETER_ARRAY AuditParameters = { 0 };
|
|
BOOLEAN bAudit;
|
|
#if DBG
|
|
HANDLE hToken;
|
|
#endif
|
|
DsysAssert(( CollisionTargetType == CollisionTdo ) ||
|
|
( CollisionTargetType == CollisionXref));
|
|
DsysAssert( pCollisionTargetName != NULL );
|
|
DsysAssert( pForestRootDomainName != NULL );
|
|
|
|
#if DBG
|
|
if ( pTopLevelName )
|
|
{
|
|
DsysAssert( pDnsName == NULL );
|
|
DsysAssert( pNetbiosName == NULL );
|
|
DsysAssert( pSid == NULL );
|
|
}
|
|
else
|
|
{
|
|
DsysAssert( pDnsName != NULL );
|
|
|
|
if ( pNetbiosName != NULL )
|
|
{
|
|
DsysAssert( pSid == NULL );
|
|
}
|
|
|
|
if ( pSid != NULL )
|
|
{
|
|
DsysAssert( pNetbiosName == NULL );
|
|
}
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// if auditing is not enabled, return asap
|
|
//
|
|
|
|
Status = LsapAdtAuditingEnabledBySid(
|
|
AuditCategoryPolicyChange,
|
|
LsapLocalSystemSid,
|
|
EVENTLOG_AUDIT_SUCCESS,
|
|
&bAudit
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status) || !bAudit)
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
#if DBG
|
|
//
|
|
// make sure that this is called in the system context
|
|
//
|
|
|
|
Status = NtOpenThreadToken( NtCurrentThread(), TOKEN_QUERY, TRUE, &hToken );
|
|
|
|
DsysAssertMsg( Status == STATUS_NO_TOKEN, "LsapAdtTrustedForestNamespaceCollision" );
|
|
|
|
if ( NT_SUCCESS(Status) )
|
|
{
|
|
NtClose( hToken );
|
|
}
|
|
else
|
|
{
|
|
Status = STATUS_SUCCESS;
|
|
}
|
|
|
|
#endif
|
|
|
|
//
|
|
// Build an audit parameters structure.
|
|
//
|
|
|
|
Status =
|
|
LsapAdtInitParametersArray(
|
|
&AuditParameters,
|
|
SE_CATEGID_POLICY_CHANGE,
|
|
SE_AUDITID_NAMESPACE_COLLISION,
|
|
EVENTLOG_AUDIT_SUCCESS,
|
|
|
|
//
|
|
// number of params to follow
|
|
//
|
|
|
|
10,
|
|
|
|
//
|
|
// User Sid
|
|
//
|
|
|
|
SeAdtParmTypeSid, LsapLocalSystemSid,
|
|
|
|
//
|
|
// Subsystem name (if available)
|
|
//
|
|
|
|
SeAdtParmTypeString, &LsapSubsystemName,
|
|
|
|
//
|
|
// collision target type
|
|
//
|
|
// 0 == CollisionTdo
|
|
// 1 == CollisionXref
|
|
//
|
|
|
|
SeAdtParmTypeUlong, CollisionTargetType,
|
|
|
|
//
|
|
// collision target name
|
|
//
|
|
// name of a TDO or cross-ref
|
|
//
|
|
|
|
SeAdtParmTypeString, pCollisionTargetName,
|
|
|
|
//
|
|
// Name of forest involved in the collision
|
|
//
|
|
|
|
SeAdtParmTypeString, pForestRootDomainName,
|
|
|
|
//
|
|
// top level name
|
|
//
|
|
|
|
SeAdtParmTypeString, pTopLevelName,
|
|
|
|
//
|
|
// DNS name
|
|
//
|
|
|
|
SeAdtParmTypeString, pDnsName,
|
|
|
|
//
|
|
// NetBIOS name
|
|
//
|
|
|
|
SeAdtParmTypeString, pNetbiosName,
|
|
|
|
//
|
|
// SID
|
|
//
|
|
|
|
SeAdtParmTypeSid, pSid,
|
|
|
|
//
|
|
// new flags value
|
|
//
|
|
|
|
SeAdtParmTypeUlong, NewFlags
|
|
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
Status = LsapAdtWriteLog( &AuditParameters );
|
|
|
|
Cleanup:
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
LsapAuditFailed( Status );
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
LsapAdtTrustedForestInfoEntryAddRemHelper(
|
|
IN ULONG EventId,
|
|
IN USHORT EventType,
|
|
IN PUNICODE_STRING ForestName,
|
|
IN PSID pForestRootDomainSid,
|
|
IN PLUID pOperationId,
|
|
IN LSA_FOREST_TRUST_RECORD_TYPE EntryType,
|
|
IN ULONG Flags,
|
|
IN PUNICODE_STRING TopLevelName,
|
|
IN PUNICODE_STRING DnsName,
|
|
IN PUNICODE_STRING NetbiosName,
|
|
IN PSID pSid
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Helper function for generating audit event when a namespace
|
|
element has been added to / removed from forest trust info.
|
|
If multiple entries get added, deleted or modified
|
|
in a single update of the forest trust information, all the generated
|
|
audit events will have a single unique identifier called OperationID.
|
|
This allows one to determine that the multiple generated audits are
|
|
the result of a single operation.
|
|
|
|
Arguments:
|
|
|
|
EventId - SE_AUDITID_TRUSTED_FOREST_INFO_ENTRY_ADD/REM
|
|
|
|
EventType - EVENTLOG_AUDIT_SUCCESS or EVENTLOG_AUDIT_FAILURE
|
|
|
|
ForestName - name of the forest
|
|
|
|
pForestRootDomainSid - SID of the forest
|
|
|
|
pOperationId - operation id (see description above)
|
|
|
|
EntryType - type of entry ( TLN | TLN excl. | domain info )
|
|
|
|
Flags - flags associated with the entry ( see ntlsa.h )
|
|
|
|
TopLevelName - TopLevel name
|
|
|
|
DnsName - Dns name
|
|
|
|
NetbiosName - Netbios name
|
|
|
|
pSid - domain sid
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS - Standard Nt Result Code
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
LUID ClientAuthenticationId;
|
|
PTOKEN_USER TokenUserInformation=NULL;
|
|
SE_ADT_PARAMETER_ARRAY AuditParameters = { 0 };
|
|
BOOLEAN bAudit;
|
|
|
|
Status = LsapQueryClientInfo( &TokenUserInformation, &ClientAuthenticationId );
|
|
|
|
if ( !NT_SUCCESS( Status ))
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// if auditing is not enabled, return asap
|
|
//
|
|
|
|
Status = LsapAdtAuditingEnabledByLogonId(
|
|
AuditCategoryPolicyChange,
|
|
&ClientAuthenticationId,
|
|
EventType,
|
|
&bAudit);
|
|
|
|
if (!NT_SUCCESS(Status) || !bAudit)
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Build an audit parameters structure.
|
|
//
|
|
|
|
Status =
|
|
LsapAdtInitParametersArray(
|
|
&AuditParameters,
|
|
SE_CATEGID_POLICY_CHANGE,
|
|
EventId,
|
|
EventType,
|
|
|
|
//
|
|
// number of params to follow
|
|
//
|
|
|
|
13,
|
|
|
|
//
|
|
// User Sid
|
|
//
|
|
|
|
SeAdtParmTypeSid, TokenUserInformation->User.Sid,
|
|
|
|
//
|
|
// Subsystem name (if available)
|
|
//
|
|
|
|
SeAdtParmTypeString, &LsapSubsystemName,
|
|
|
|
//
|
|
// Forest name
|
|
//
|
|
|
|
SeAdtParmTypeString, ForestName,
|
|
|
|
//
|
|
// Forest SID
|
|
//
|
|
|
|
SeAdtParmTypeSid, pForestRootDomainSid,
|
|
|
|
//
|
|
// Operation ID
|
|
//
|
|
|
|
SeAdtParmTypeUlong, pOperationId->HighPart,
|
|
SeAdtParmTypeUlong, pOperationId->LowPart,
|
|
|
|
//
|
|
// Entry Type
|
|
//
|
|
|
|
SeAdtParmTypeUlong, EntryType,
|
|
|
|
//
|
|
// Flags
|
|
//
|
|
|
|
SeAdtParmTypeUlong, Flags,
|
|
|
|
//
|
|
// top level name
|
|
//
|
|
|
|
SeAdtParmTypeString, TopLevelName,
|
|
|
|
//
|
|
// DNS domain name
|
|
//
|
|
|
|
SeAdtParmTypeString, DnsName,
|
|
|
|
//
|
|
// NetBIOS domain name
|
|
//
|
|
|
|
SeAdtParmTypeString, NetbiosName,
|
|
|
|
//
|
|
// domain SID
|
|
//
|
|
|
|
SeAdtParmTypeSid, pSid,
|
|
|
|
//
|
|
// user info
|
|
//
|
|
|
|
SeAdtParmTypeLogonId, ClientAuthenticationId
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
Status = LsapAdtWriteLog( &AuditParameters );
|
|
|
|
Cleanup:
|
|
|
|
if (TokenUserInformation != NULL)
|
|
{
|
|
LsapFreeLsaHeap( TokenUserInformation );
|
|
}
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
LsapAuditFailed( Status );
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
LsapAdtTrustedForestInfoEntryAdd(
|
|
IN PUNICODE_STRING pForestRootDomainName,
|
|
IN PSID pForestRootDomainSid,
|
|
IN PLUID pOperationId,
|
|
IN LSA_FOREST_TRUST_RECORD_TYPE EntryType,
|
|
IN ULONG Flags,
|
|
IN PUNICODE_STRING TopLevelName,
|
|
IN PUNICODE_STRING DnsName,
|
|
IN PUNICODE_STRING NetbiosName,
|
|
IN PSID pSid
|
|
)
|
|
{
|
|
return LsapAdtTrustedForestInfoEntryAddRemHelper(
|
|
SE_AUDITID_TRUSTED_FOREST_INFO_ENTRY_ADD,
|
|
EVENTLOG_AUDIT_SUCCESS,
|
|
pForestRootDomainName,
|
|
pForestRootDomainSid,
|
|
pOperationId,
|
|
EntryType,
|
|
Flags,
|
|
TopLevelName,
|
|
DnsName,
|
|
NetbiosName,
|
|
pSid
|
|
);
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
LsapAdtTrustedForestInfoEntryRem(
|
|
IN PUNICODE_STRING pForestRootDomainName,
|
|
IN PSID pForestRootDomainSid,
|
|
IN PLUID pOperationId,
|
|
IN LSA_FOREST_TRUST_RECORD_TYPE EntryType,
|
|
IN ULONG Flags,
|
|
IN PUNICODE_STRING TopLevelName,
|
|
IN PUNICODE_STRING DnsName,
|
|
IN PUNICODE_STRING NetbiosName,
|
|
IN PSID pSid
|
|
)
|
|
{
|
|
return LsapAdtTrustedForestInfoEntryAddRemHelper(
|
|
SE_AUDITID_TRUSTED_FOREST_INFO_ENTRY_REM,
|
|
EVENTLOG_AUDIT_SUCCESS,
|
|
pForestRootDomainName,
|
|
pForestRootDomainSid,
|
|
pOperationId,
|
|
EntryType,
|
|
Flags,
|
|
TopLevelName,
|
|
DnsName,
|
|
NetbiosName,
|
|
pSid
|
|
);
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
LsapAdtTrustedForestInfoEntryMod(
|
|
IN PUNICODE_STRING pForestRootDomainName,
|
|
IN PSID pForestRootDomainSid,
|
|
IN PLUID pOperationId,
|
|
IN LSA_FOREST_TRUST_RECORD_TYPE EntryType,
|
|
|
|
IN ULONG OldFlags,
|
|
IN PUNICODE_STRING pOldTopLevelName,
|
|
IN PUNICODE_STRING pOldDnsName,
|
|
IN PUNICODE_STRING pOldNetbiosName,
|
|
IN PSID pOldSid,
|
|
|
|
IN ULONG NewFlags,
|
|
IN PUNICODE_STRING pNewTopLevelName,
|
|
IN PUNICODE_STRING pNewDnsName,
|
|
IN PUNICODE_STRING pNewNetbiosName,
|
|
IN PSID pNewSid
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Helper function for generating audit event when a namespace
|
|
element in forest trust info has been modified.
|
|
If multiple entries get added, deleted or modified
|
|
in a single update of the forest trust information, all the generated
|
|
audit events will have a single unique identifier called OperationID.
|
|
This allows one to determine that the multiple generated audits are
|
|
the result of a single operation.
|
|
|
|
Arguments:
|
|
|
|
EventType - EVENTLOG_AUDIT_SUCCESS or EVENTLOG_AUDIT_FAILURE
|
|
|
|
ForestName - name of the forest
|
|
|
|
pForestRootDomainSid - SID of the forest
|
|
|
|
pOperationId - operation id (see description above)
|
|
|
|
EntryType - type of entry ( TLN | TLN excl. | domain info )
|
|
|
|
OldFlags - old flags associated with the entry ( see ntlsa.h )
|
|
|
|
pOldTopLevelName - old TopLevel name
|
|
|
|
pOldDnsName - old Dns name
|
|
|
|
pOldNetbiosName - old Netbios name
|
|
|
|
pOldSid - old domain sid
|
|
|
|
NewFlags - new flags associated with the entry ( see ntlsa.h )
|
|
|
|
pNewTopLevelName - new TopLevel name
|
|
|
|
pNewDnsName - new Dns name
|
|
|
|
pNewNetbiosName - new Netbios name
|
|
|
|
pNewSid - new domain sid
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS - Standard Nt Result Code
|
|
|
|
Notes:
|
|
|
|
The unmodified fields are represented by a '-' in the audit log.
|
|
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
LUID ClientAuthenticationId;
|
|
PTOKEN_USER TokenUserInformation=NULL;
|
|
SE_ADT_PARAMETER_ARRAY AuditParameters = { 0 };
|
|
BOOLEAN bAudit;
|
|
|
|
Status = LsapQueryClientInfo( &TokenUserInformation, &ClientAuthenticationId );
|
|
|
|
if ( !NT_SUCCESS( Status ))
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// if auditing is not enabled, return asap
|
|
//
|
|
|
|
Status = LsapAdtAuditingEnabledByLogonId(
|
|
AuditCategoryPolicyChange,
|
|
&ClientAuthenticationId,
|
|
EVENTLOG_AUDIT_SUCCESS,
|
|
&bAudit
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status) || !bAudit)
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
AuditParameters.CategoryId = SE_CATEGID_POLICY_CHANGE;
|
|
AuditParameters.AuditId = SE_AUDITID_TRUSTED_FOREST_INFO_ENTRY_MOD;
|
|
AuditParameters.Type = EVENTLOG_AUDIT_SUCCESS;
|
|
AuditParameters.ParameterCount = 13;
|
|
|
|
//
|
|
// User Sid
|
|
//
|
|
|
|
LsapSetParmTypeSid( AuditParameters, 0, TokenUserInformation->User.Sid );
|
|
|
|
//
|
|
// Subsystem name (if available)
|
|
//
|
|
|
|
LsapSetParmTypeString( AuditParameters, 1, &LsapSubsystemName );
|
|
|
|
|
|
//
|
|
// forest name
|
|
//
|
|
|
|
LsapSetParmTypeString( AuditParameters, 2, pForestRootDomainName );
|
|
|
|
//
|
|
// forest id (SID of the root domain)
|
|
//
|
|
|
|
LsapSetParmTypeSid( AuditParameters, 3, pForestRootDomainSid );
|
|
|
|
//
|
|
// Operation ID
|
|
//
|
|
|
|
LsapSetParmTypeUlong( AuditParameters, 4, pOperationId->HighPart );
|
|
LsapSetParmTypeUlong( AuditParameters, 5, pOperationId->LowPart );
|
|
|
|
//
|
|
// entry type
|
|
//
|
|
|
|
LsapSetParmTypeUlong( AuditParameters, 6, EntryType );
|
|
|
|
//
|
|
// for all subsequent types, output a value only if it changed.
|
|
//
|
|
|
|
//
|
|
// Flags
|
|
//
|
|
|
|
if ( OldFlags != NewFlags )
|
|
{
|
|
LsapSetParmTypeUlong( AuditParameters, 7, NewFlags );
|
|
}
|
|
|
|
//
|
|
// top level name
|
|
//
|
|
|
|
if ( pOldTopLevelName && pNewTopLevelName &&
|
|
!RtlEqualUnicodeString( pOldTopLevelName, pNewTopLevelName, TRUE ) )
|
|
{
|
|
LsapSetParmTypeString( AuditParameters, 8, pNewTopLevelName );
|
|
}
|
|
|
|
//
|
|
// DNS domain name
|
|
//
|
|
|
|
if ( pOldDnsName && pNewDnsName &&
|
|
!RtlEqualUnicodeString( pOldDnsName, pNewDnsName, TRUE ) )
|
|
{
|
|
LsapSetParmTypeString( AuditParameters, 9, pNewDnsName );
|
|
}
|
|
|
|
//
|
|
// NetBIOS domain name
|
|
//
|
|
|
|
if ( pOldNetbiosName && pNewNetbiosName &&
|
|
!RtlEqualUnicodeString( pOldNetbiosName, pNewNetbiosName, TRUE ) )
|
|
{
|
|
LsapSetParmTypeString( AuditParameters, 10, pNewNetbiosName );
|
|
}
|
|
|
|
//
|
|
// domain SID
|
|
//
|
|
|
|
if ( pOldSid && pNewSid && !RtlEqualSid( pOldSid, pNewSid ) )
|
|
{
|
|
LsapSetParmTypeSid( AuditParameters, 11, pNewSid );
|
|
}
|
|
|
|
//
|
|
// client auth-id
|
|
//
|
|
|
|
LsapSetParmTypeLogonId( AuditParameters, 12, ClientAuthenticationId );
|
|
|
|
|
|
Status = LsapAdtWriteLog( &AuditParameters );
|
|
|
|
Cleanup:
|
|
|
|
if (TokenUserInformation != NULL)
|
|
{
|
|
LsapFreeLsaHeap( TokenUserInformation );
|
|
}
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
LsapAuditFailed( Status );
|
|
}
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
LsapAdtPolicyChange(
|
|
IN USHORT EventCategory,
|
|
IN ULONG EventID,
|
|
IN USHORT EventType,
|
|
IN PSID ClientSid,
|
|
IN LUID CallerAuthenticationId,
|
|
IN PLSARM_POLICY_AUDIT_EVENTS_INFO PolicyAuditEventsInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Generates an audit for a policy change event.
|
|
|
|
The decision to generate this audit is made in LsapAdtGenerateLsaAuditEvent.
|
|
|
|
Arguments:
|
|
|
|
EventCategory - The category of this audit.
|
|
|
|
EventID - The event we are auditing.
|
|
|
|
EventType - Whether the audit is success or failure.
|
|
|
|
ClientSid - The SID of the user performing the policy change.
|
|
|
|
CallerAuthenticationId - The Authentication id of the user.
|
|
|
|
PolicyAuditEventsInfo - The information to audit.
|
|
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
Note:
|
|
--*/
|
|
{
|
|
PPOLICY_AUDIT_EVENT_OPTIONS EventAuditingOptions;
|
|
SE_ADT_PARAMETER_ARRAY AuditParameters;
|
|
UNICODE_STRING Enabled;
|
|
UNICODE_STRING Disabled;
|
|
ULONG i;
|
|
|
|
RtlInitUnicodeString( &Enabled, L"+" );
|
|
RtlInitUnicodeString( &Disabled, L"-" );
|
|
EventAuditingOptions = PolicyAuditEventsInfo->EventAuditingOptions;
|
|
|
|
//
|
|
// Build an audit parameters structure.
|
|
//
|
|
|
|
RtlZeroMemory (
|
|
(PVOID) &AuditParameters,
|
|
sizeof( AuditParameters )
|
|
);
|
|
|
|
AuditParameters.CategoryId = EventCategory;
|
|
AuditParameters.AuditId = EventID;
|
|
AuditParameters.Type = EventType;
|
|
AuditParameters.ParameterCount = 0;
|
|
|
|
//
|
|
// User Sid
|
|
//
|
|
|
|
LsapSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, ClientSid );
|
|
AuditParameters.ParameterCount++;
|
|
|
|
//
|
|
// Subsystem name (if available)
|
|
//
|
|
|
|
LsapSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, &LsapSubsystemName );
|
|
AuditParameters.ParameterCount++;
|
|
|
|
//
|
|
// If auditing is disabled, mark all options as disabled. Otherwise
|
|
// mark them as the appropriate
|
|
//
|
|
|
|
for ( i=0; i<POLICY_AUDIT_EVENT_TYPE_COUNT; i++ ) {
|
|
|
|
LsapSetParmTypeString(
|
|
AuditParameters,
|
|
AuditParameters.ParameterCount,
|
|
(EventAuditingOptions[i] & POLICY_AUDIT_EVENT_SUCCESS ? &Enabled : &Disabled)
|
|
);
|
|
|
|
AuditParameters.ParameterCount++;
|
|
|
|
LsapSetParmTypeString(
|
|
AuditParameters,
|
|
AuditParameters.ParameterCount,
|
|
(EventAuditingOptions[i] & POLICY_AUDIT_EVENT_FAILURE ? &Enabled : &Disabled)
|
|
);
|
|
|
|
AuditParameters.ParameterCount++;
|
|
}
|
|
|
|
//
|
|
// Caller's Authentication information
|
|
//
|
|
|
|
LsapSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, CallerAuthenticationId );
|
|
AuditParameters.ParameterCount++;
|
|
|
|
|
|
( VOID ) LsapAdtWriteLog( &AuditParameters );
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
LsapAdtGenerateDomainPolicyChangeAuditEvent(
|
|
IN POLICY_DOMAIN_INFORMATION_CLASS InformationClass,
|
|
IN USHORT AuditEventType,
|
|
IN LSAP_DB_ATTRIBUTE* OldAttributes,
|
|
IN LSAP_DB_ATTRIBUTE* NewAttributes,
|
|
IN ULONG AttributeCount
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Generate an audit event when any of the following policies changes:
|
|
- PolicyDomainEfsInformation
|
|
- PolicyDomainKerberosTicketInformation
|
|
|
|
Arguments:
|
|
|
|
InformationClass - type of policy that changed
|
|
|
|
AuditEventType - The type of audit event to be generated.
|
|
EVENTLOG_AUDIT_SUCCESS or EVENTLOG_AUDIT_FAILURE
|
|
|
|
OldAttributes - pointer to array of old attributes
|
|
|
|
NewAttributes - pointer to array of new attributes
|
|
|
|
AttributeCount - number of attributes
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS - Standard Nt Result Code
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS Status=STATUS_SUCCESS;
|
|
SE_ADT_PARAMETER_ARRAY AuditParameters;
|
|
ULONG AuditId;
|
|
LPWSTR AttributeChanges=NULL;
|
|
UNICODE_STRING ChangesToAttributes;
|
|
LUID ClientAuthenticationId;
|
|
PTOKEN_USER TokenUserInformation=NULL;
|
|
BOOLEAN bAudit;
|
|
|
|
Status = LsapQueryClientInfo(
|
|
&TokenUserInformation,
|
|
&ClientAuthenticationId
|
|
);
|
|
|
|
if ( !NT_SUCCESS( Status )) {
|
|
goto Cleanup;
|
|
}
|
|
|
|
Status = LsapAdtAuditingEnabledByLogonId(
|
|
AuditCategoryPolicyChange,
|
|
&ClientAuthenticationId,
|
|
AuditEventType,
|
|
&bAudit
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status) || !bAudit)
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
switch (InformationClass) {
|
|
default:
|
|
ASSERT(FALSE);
|
|
goto Cleanup;
|
|
break;
|
|
|
|
case PolicyDomainEfsInformation:
|
|
AuditId = SE_AUDITID_EFS_POLICY_CHANGE;
|
|
break;
|
|
|
|
case PolicyDomainKerberosTicketInformation:
|
|
AuditId = SE_AUDITID_KERBEROS_POLICY_CHANGE;
|
|
break;
|
|
}
|
|
|
|
Status = LsapAdtGetDbAttributesChangeString( OldAttributes,
|
|
NewAttributes,
|
|
AttributeCount,
|
|
&AttributeChanges );
|
|
if (!NT_SUCCESS(Status)) {
|
|
goto Cleanup;
|
|
}
|
|
|
|
RtlInitUnicodeString(&ChangesToAttributes, AttributeChanges);
|
|
|
|
Status =
|
|
LsapAdtInitParametersArray(
|
|
&AuditParameters,
|
|
SE_CATEGID_POLICY_CHANGE,
|
|
AuditId,
|
|
AuditEventType,
|
|
4,
|
|
//
|
|
// User Sid
|
|
//
|
|
SeAdtParmTypeSid, TokenUserInformation->User.Sid,
|
|
|
|
//
|
|
// Subsystem name (if available)
|
|
//
|
|
SeAdtParmTypeString, &LsapSubsystemName,
|
|
|
|
//
|
|
// Caller's Authentication information
|
|
//
|
|
SeAdtParmTypeLogonId, ClientAuthenticationId,
|
|
|
|
//
|
|
// Changes to attributes
|
|
//
|
|
SeAdtParmTypeString, &ChangesToAttributes);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
( VOID ) LsapAdtWriteLog( &AuditParameters );
|
|
|
|
Cleanup:
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
LsapAuditFailed(Status);
|
|
}
|
|
|
|
if (TokenUserInformation != NULL)
|
|
{
|
|
LsapFreeLsaHeap( TokenUserInformation );
|
|
}
|
|
|
|
LsapFreeLsaHeap( AttributeChanges );
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
VOID
|
|
LsapAdtGetAttributeValueString(
|
|
IN LSAP_DB_ATTRIBUTE* Attribute,
|
|
OUT LPWSTR ValueString OPTIONAL,
|
|
IN OUT PULONG RequiredLength
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Generate a string representation of the value of an attribute
|
|
|
|
Arguments:
|
|
|
|
Attribute - pointer to attribute
|
|
|
|
ValueString - receives a string representation of the value of Attribute
|
|
|
|
RequiredLength - pointer to length of ValueString
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
WCHAR Buffer[32];
|
|
ULONG Length;
|
|
|
|
if (Attribute->AttributeValue) {
|
|
|
|
switch (Attribute->DbNameIndex) {
|
|
|
|
default:
|
|
lstrcpy(Buffer, L"unknown");
|
|
break;
|
|
|
|
// binary blob
|
|
case PolEfDat:
|
|
lstrcpy(Buffer, L"<binary data>");
|
|
break;
|
|
|
|
// ULONG
|
|
case KerOpts:
|
|
swprintf(Buffer, L"0x%x", *((ULONG*) Attribute->AttributeValue));
|
|
break;
|
|
|
|
// LARGE_INTEGER
|
|
case KerMinT:
|
|
case KerMaxT:
|
|
case KerMaxR:
|
|
case KerProxy:
|
|
case KerLogoff:
|
|
swprintf(Buffer, L"0x%I64x",
|
|
*((ULONGLONG*) Attribute->AttributeValue));
|
|
break;
|
|
}
|
|
} else {
|
|
lstrcpy(Buffer, L"none");
|
|
}
|
|
|
|
Length = lstrlen(Buffer);
|
|
|
|
if (ValueString && Length <= *RequiredLength)
|
|
{
|
|
CopyMemory(
|
|
ValueString,
|
|
Buffer,
|
|
Length * sizeof(WCHAR));
|
|
}
|
|
|
|
*RequiredLength = Length;
|
|
}
|
|
|
|
|
|
VOID
|
|
LsapAdtGetDbAttributeChangeString(
|
|
IN LSAP_DB_ATTRIBUTE* OldAttribute,
|
|
IN LSAP_DB_ATTRIBUTE* NewAttribute,
|
|
OUT LPWSTR AttributeChangeString, OPTIONAL
|
|
IN OUT PULONG RequiredLength
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Given an old attribute and a new attribute, return
|
|
a string representation of the difference between the two.
|
|
|
|
If there are no changes, RequiredLength is returned as 0
|
|
and AttributeChangeString is left unchanged;
|
|
otherwise if AttributeChangeString is non-NULL, the change is
|
|
written to it as:
|
|
<ParameterName>: <new value> (<old value>)
|
|
|
|
Arguments:
|
|
|
|
OldAttribute - pointer to old attribute
|
|
|
|
NewAttribute - pointer to new attribute
|
|
|
|
AttributeChangeString - if non-NULL, receives the string representation
|
|
of the difference between OldAttribute and NewAttribute
|
|
|
|
RequiredLength - pointer to length of AttributeChangeString
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
PWSTR TmpString;
|
|
ULONG ChangeStringLength = 0;
|
|
ULONG ValueLength;
|
|
|
|
//
|
|
// do the processing only if there is a change in value
|
|
//
|
|
if ((OldAttribute->AttributeValue && NewAttribute->AttributeValue &&
|
|
(0 != memcmp(OldAttribute->AttributeValue,
|
|
NewAttribute->AttributeValue,
|
|
OldAttribute->AttributeValueLength))) ||
|
|
(OldAttribute->AttributeValue && !NewAttribute->AttributeValue) ||
|
|
(!OldAttribute->AttributeValue && NewAttribute->AttributeValue))
|
|
{
|
|
ChangeStringLength += OldAttribute->AttributeName->Length / sizeof(WCHAR);
|
|
ChangeStringLength += 2; // ": "
|
|
LsapAdtGetAttributeValueString(NewAttribute, 0, &ValueLength);
|
|
ChangeStringLength += ValueLength;
|
|
ChangeStringLength += 2; // " ("
|
|
LsapAdtGetAttributeValueString(OldAttribute, 0, &ValueLength);
|
|
ChangeStringLength += ValueLength;
|
|
ChangeStringLength += 4; // "); "
|
|
|
|
if (AttributeChangeString && ChangeStringLength <= *RequiredLength)
|
|
{
|
|
//
|
|
// Parameter Name
|
|
//
|
|
lstrcpy(AttributeChangeString, OldAttribute->AttributeName->Buffer);
|
|
ChangeStringLength = OldAttribute->AttributeName->Length / sizeof(WCHAR);
|
|
TmpString = AttributeChangeString + ChangeStringLength;
|
|
|
|
lstrcpy(TmpString, L": ");
|
|
ChangeStringLength += 2;
|
|
TmpString = AttributeChangeString + ChangeStringLength;
|
|
|
|
//
|
|
// Old value
|
|
//
|
|
ValueLength = *RequiredLength - ChangeStringLength;
|
|
LsapAdtGetAttributeValueString( NewAttribute, TmpString, &ValueLength );
|
|
ChangeStringLength += ValueLength;
|
|
TmpString = AttributeChangeString + ChangeStringLength;
|
|
|
|
//
|
|
// New value
|
|
//
|
|
lstrcpy(TmpString, L" (");
|
|
ChangeStringLength += 2;
|
|
TmpString = AttributeChangeString + ChangeStringLength;
|
|
|
|
ValueLength = *RequiredLength - ChangeStringLength;
|
|
LsapAdtGetAttributeValueString( OldAttribute, TmpString, &ValueLength );
|
|
ChangeStringLength += ValueLength;
|
|
TmpString = AttributeChangeString + ChangeStringLength;
|
|
|
|
//
|
|
// Don't copy the terminating '\0' in order to avoid a BO !
|
|
//
|
|
CopyMemory(TmpString, L"); ", 4 * sizeof(WCHAR));
|
|
ChangeStringLength += 4;
|
|
}
|
|
}
|
|
|
|
*RequiredLength = ChangeStringLength;
|
|
}
|
|
|
|
NTSTATUS
|
|
LsapAdtGetDbAttributesChangeString(
|
|
IN LSAP_DB_ATTRIBUTE* OldAttributes,
|
|
IN LSAP_DB_ATTRIBUTE* NewAttributes,
|
|
IN ULONG AttributeCount,
|
|
OUT LPWSTR* AttributeChangeString
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Given old attributes and new attributes, return a string representation
|
|
of the difference between old and new attributes.
|
|
|
|
If there are no changes, "--" is returned,
|
|
otherwise each change is written to the string as:
|
|
<ParameterName>: <new value> (<old value>)
|
|
|
|
This function is used for writing information about
|
|
changes to certain policies to the audit log.
|
|
|
|
Arguments:
|
|
|
|
OldAttributes - pointer to array of old attributes
|
|
|
|
NewAttributes - pointer to array of new attributes
|
|
|
|
AttributeCount - Number of attributes.
|
|
|
|
AttributeChangeString - pointer to string that receives the diff.
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS - Standard Nt Result Code
|
|
|
|
Notes:
|
|
|
|
Memory allocated for AttributeChangeString must be freed by the
|
|
caller using LsapFreeLsaHeap.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS Status=STATUS_SUCCESS;
|
|
LSAP_DB_ATTRIBUTE* OldAttribute;
|
|
LSAP_DB_ATTRIBUTE* NewAttribute;
|
|
ULONG TmpStringLength;
|
|
ULONG TotalRequiredLength;
|
|
LPWSTR TmpString;
|
|
UINT AttributeNumber;
|
|
USHORT n=1;
|
|
|
|
OldAttribute = OldAttributes;
|
|
NewAttribute = NewAttributes;
|
|
|
|
TotalRequiredLength = 0;
|
|
|
|
//
|
|
// first find out the size of the buffer required
|
|
//
|
|
for (AttributeNumber = 0; AttributeNumber < AttributeCount; AttributeNumber++) {
|
|
|
|
LsapAdtGetDbAttributeChangeString( OldAttribute, NewAttribute,
|
|
NULL, &TmpStringLength );
|
|
OldAttribute++;
|
|
NewAttribute++;
|
|
TotalRequiredLength += TmpStringLength;
|
|
}
|
|
|
|
//
|
|
// reserve space for '--'
|
|
//
|
|
|
|
if (!TotalRequiredLength) {
|
|
n += 2;
|
|
}
|
|
|
|
*AttributeChangeString = TmpString =
|
|
LsapAllocateLsaHeap((TotalRequiredLength+n)*sizeof(WCHAR));
|
|
|
|
if ( TmpString ) {
|
|
|
|
if (TotalRequiredLength) {
|
|
|
|
//
|
|
// Now get the actual string
|
|
//
|
|
OldAttribute = OldAttributes;
|
|
NewAttribute = NewAttributes;
|
|
|
|
for (AttributeNumber = 0;
|
|
AttributeNumber < AttributeCount;
|
|
AttributeNumber++) {
|
|
|
|
TmpStringLength = TotalRequiredLength;
|
|
LsapAdtGetDbAttributeChangeString( OldAttribute, NewAttribute,
|
|
TmpString, &TmpStringLength );
|
|
TmpString += TmpStringLength;
|
|
OldAttribute++;
|
|
NewAttribute++;
|
|
}
|
|
|
|
*TmpString = L'\0';
|
|
} else {
|
|
lstrcpy(TmpString, L"--");
|
|
}
|
|
} else {
|
|
Status = STATUS_NO_MEMORY;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
PLUID LsaFilterPrivileges[] =
|
|
{
|
|
&ChangeNotifyPrivilege,
|
|
&AuditPrivilege,
|
|
&CreateTokenPrivilege,
|
|
&AssignPrimaryTokenPrivilege,
|
|
&BackupPrivilege,
|
|
&RestorePrivilege,
|
|
&DebugPrivilege,
|
|
NULL
|
|
};
|
|
|
|
|
|
VOID
|
|
LsapAdtAuditSpecialPrivileges(
|
|
PPRIVILEGE_SET Privileges,
|
|
LUID LogonId,
|
|
PSID UserSid
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Audits the assignment of special privileges at logon time.
|
|
|
|
Arguments:
|
|
|
|
Privileges - List of privileges being assigned.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
PPRIVILEGE_SET Buffer = NULL;
|
|
PLUID *FilterPrivilege = NULL;
|
|
ULONG i;
|
|
SE_ADT_PARAMETER_ARRAY AuditParameters;
|
|
BOOLEAN bAuditPrivUse = FALSE;
|
|
BOOLEAN bAuditLogon = FALSE;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
if ( (Privileges == NULL) || (Privileges->PrivilegeCount == 0) ) {
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// allow this audit to be generated when either the logon/logoff
|
|
// or the priv-use category is enabled
|
|
//
|
|
|
|
Status = LsapAdtAuditingEnabledByLogonId(
|
|
AuditCategoryPrivilegeUse,
|
|
&LogonId,
|
|
EVENTLOG_AUDIT_SUCCESS,
|
|
&bAuditPrivUse
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
|
|
goto Cleanup;
|
|
}
|
|
|
|
Status = LsapAdtAuditingEnabledByLogonId(
|
|
AuditCategoryLogon,
|
|
&LogonId,
|
|
EVENTLOG_AUDIT_SUCCESS,
|
|
&bAuditLogon
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// if neither category is set, return quickly
|
|
//
|
|
|
|
if ( !bAuditPrivUse && !bAuditLogon ) {
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
DsysAssertMsg( IsValidPrivilegeCount(Privileges->PrivilegeCount),
|
|
"LsapAdtAuditSpecialPrivileges" );
|
|
|
|
|
|
//
|
|
// We can't need any more space than what's being passed in.
|
|
//
|
|
|
|
Buffer = (PPRIVILEGE_SET)LsapAllocateLsaHeap( LsapPrivilegeSetSize( Privileges ) );
|
|
|
|
if ( Buffer == NULL ) {
|
|
|
|
Status = STATUS_NO_MEMORY;
|
|
goto Cleanup;
|
|
}
|
|
|
|
Buffer->PrivilegeCount = 0;
|
|
|
|
//
|
|
// For each privilege in the privilege set, see if it's in the filter
|
|
// list.
|
|
//
|
|
|
|
for ( i=0; i<Privileges->PrivilegeCount; i++) {
|
|
|
|
FilterPrivilege = LsaFilterPrivileges;
|
|
|
|
do {
|
|
|
|
if ( RtlEqualLuid( &Privileges->Privilege[i].Luid, *FilterPrivilege )) {
|
|
|
|
Buffer->Privilege[Buffer->PrivilegeCount].Luid = **FilterPrivilege;
|
|
Buffer->PrivilegeCount++;
|
|
}
|
|
|
|
} while ( *++FilterPrivilege != NULL );
|
|
}
|
|
|
|
if ( Buffer->PrivilegeCount == 0 ) {
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// We matched on at least one, generate an audit.
|
|
//
|
|
|
|
RtlZeroMemory ((PVOID) &AuditParameters, sizeof( AuditParameters ));
|
|
|
|
AuditParameters.CategoryId = SE_CATEGID_PRIVILEGE_USE;
|
|
AuditParameters.AuditId = SE_AUDITID_ASSIGN_SPECIAL_PRIV;
|
|
AuditParameters.Type = EVENTLOG_AUDIT_SUCCESS;
|
|
AuditParameters.ParameterCount = 0;
|
|
|
|
LsapSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, UserSid );
|
|
AuditParameters.ParameterCount++;
|
|
|
|
LsapSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, &LsapSubsystemName );
|
|
AuditParameters.ParameterCount++;
|
|
|
|
LsapSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, LogonId );
|
|
AuditParameters.ParameterCount++;
|
|
|
|
LsapSetParmTypePrivileges( AuditParameters, AuditParameters.ParameterCount, Buffer );
|
|
AuditParameters.ParameterCount++;
|
|
|
|
( VOID ) LsapAdtWriteLog( &AuditParameters );
|
|
|
|
Cleanup:
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
|
|
LsapAuditFailed(Status);
|
|
}
|
|
|
|
if (Buffer != NULL) {
|
|
|
|
LsapFreeLsaHeap( Buffer );
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
|
|
VOID
|
|
LsapAdtAuditPackageLoad(
|
|
PUNICODE_STRING PackageFileName
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Audits the loading of an authentication package.
|
|
|
|
Arguments:
|
|
|
|
PackageFileName - The name of the package being loaded.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
SE_ADT_PARAMETER_ARRAY AuditParameters;
|
|
NTSTATUS Status;
|
|
BOOLEAN bAudit;
|
|
|
|
Status = LsapAdtAuditingEnabledBySid(
|
|
AuditCategorySystem,
|
|
LsapLocalSystemSid,
|
|
EVENTLOG_AUDIT_SUCCESS,
|
|
&bAudit
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status) || !bAudit) {
|
|
goto Cleanup;
|
|
}
|
|
|
|
RtlZeroMemory (
|
|
(PVOID) &AuditParameters,
|
|
sizeof( AuditParameters )
|
|
);
|
|
|
|
AuditParameters.CategoryId = SE_CATEGID_SYSTEM;
|
|
AuditParameters.AuditId = SE_AUDITID_AUTH_PACKAGE_LOAD;
|
|
AuditParameters.Type = EVENTLOG_AUDIT_SUCCESS;
|
|
AuditParameters.ParameterCount = 0;
|
|
|
|
LsapSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, LsapLocalSystemSid );
|
|
AuditParameters.ParameterCount++;
|
|
|
|
LsapSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, &LsapSubsystemName );
|
|
AuditParameters.ParameterCount++;
|
|
|
|
LsapSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, PackageFileName );
|
|
AuditParameters.ParameterCount++;
|
|
|
|
( VOID ) LsapAdtWriteLog( &AuditParameters );
|
|
|
|
Cleanup:
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
|
|
LsapAuditFailed(Status);
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
VOID
|
|
LsapAdtAuditLogonProcessRegistration(
|
|
IN PLSAP_AU_REGISTER_CONNECT_INFO_EX ConnectInfo
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Audits the registration of a logon process
|
|
|
|
Arguments:
|
|
|
|
ConnectInfo - Supplies the connection information for the new
|
|
logon process.
|
|
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status;
|
|
ANSI_STRING AnsiString;
|
|
UNICODE_STRING Unicode = {0};
|
|
PSZ LogonProcessNameBuffer = NULL;
|
|
SE_ADT_PARAMETER_ARRAY AuditParameters;
|
|
BOOLEAN bAudit;
|
|
|
|
Status = LsapAdtAuditingEnabledBySid(
|
|
AuditCategorySystem,
|
|
LsapLocalSystemSid,
|
|
EVENTLOG_AUDIT_SUCCESS,
|
|
&bAudit
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status) || !bAudit) {
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Turn the name text in the ConnectInfo structure into
|
|
// something we can work with.
|
|
//
|
|
|
|
LogonProcessNameBuffer = (PSZ)LsapAllocateLsaHeap( ConnectInfo->LogonProcessNameLength+1 );
|
|
|
|
if ( LogonProcessNameBuffer == NULL ) {
|
|
|
|
Status = STATUS_NO_MEMORY;
|
|
goto Cleanup;
|
|
}
|
|
|
|
RtlCopyMemory(
|
|
LogonProcessNameBuffer,
|
|
ConnectInfo->LogonProcessName,
|
|
ConnectInfo->LogonProcessNameLength
|
|
);
|
|
|
|
LogonProcessNameBuffer[ConnectInfo->LogonProcessNameLength] = 0;
|
|
RtlInitAnsiString( &AnsiString, LogonProcessNameBuffer );
|
|
|
|
Status = RtlAnsiStringToUnicodeString( &Unicode, &AnsiString, TRUE );
|
|
|
|
if ( !NT_SUCCESS( Status )) {
|
|
|
|
goto Cleanup;
|
|
}
|
|
|
|
RtlZeroMemory (
|
|
(PVOID) &AuditParameters,
|
|
sizeof( AuditParameters )
|
|
);
|
|
|
|
AuditParameters.CategoryId = SE_CATEGID_SYSTEM;
|
|
AuditParameters.AuditId = SE_AUDITID_SYSTEM_LOGON_PROC_REGISTER;
|
|
AuditParameters.Type = EVENTLOG_AUDIT_SUCCESS;
|
|
AuditParameters.ParameterCount = 0;
|
|
|
|
LsapSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, LsapLocalSystemSid );
|
|
AuditParameters.ParameterCount++;
|
|
|
|
LsapSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, &LsapSubsystemName );
|
|
AuditParameters.ParameterCount++;
|
|
|
|
LsapSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, &Unicode );
|
|
AuditParameters.ParameterCount++;
|
|
|
|
( VOID ) LsapAdtWriteLog( &AuditParameters );
|
|
|
|
Cleanup:
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
LsapAuditFailed(Status);
|
|
}
|
|
LsapFreeLsaHeap( LogonProcessNameBuffer );
|
|
RtlFreeUnicodeString( &Unicode );
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
|
|
VOID
|
|
LsapAdtSystemRestart(
|
|
PLSARM_POLICY_AUDIT_EVENTS_INFO AuditEventsInfo
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function is called during LSA initialization to generate
|
|
a system restart event.
|
|
|
|
Arguments:
|
|
|
|
AuditEventsInfo - Auditing data.
|
|
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS - Standard Nt Result Code.
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
SE_ADT_PARAMETER_ARRAY AuditParameters;
|
|
BOOLEAN bAudit;
|
|
|
|
Status = LsapAdtAuditingEnabledBySid(
|
|
AuditCategorySystem,
|
|
LsapLocalSystemSid,
|
|
EVENTLOG_AUDIT_SUCCESS,
|
|
&bAudit
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status) || !bAudit) {
|
|
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Construct an audit parameters array
|
|
// for the restart event.
|
|
//
|
|
|
|
RtlZeroMemory (
|
|
(PVOID) &AuditParameters,
|
|
sizeof( AuditParameters )
|
|
);
|
|
|
|
AuditParameters.CategoryId = SE_CATEGID_SYSTEM;
|
|
AuditParameters.AuditId = SE_AUDITID_SYSTEM_RESTART;
|
|
AuditParameters.Type = EVENTLOG_AUDIT_SUCCESS;
|
|
AuditParameters.ParameterCount = 0;
|
|
|
|
//
|
|
// User Sid
|
|
//
|
|
|
|
LsapSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, LsapLocalSystemSid );
|
|
|
|
AuditParameters.ParameterCount++;
|
|
|
|
//
|
|
// Subsystem name
|
|
//
|
|
|
|
LsapSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, &LsapSubsystemName );
|
|
|
|
AuditParameters.ParameterCount++;
|
|
|
|
( VOID ) LsapAdtWriteLog( &AuditParameters );
|
|
|
|
Cleanup:
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
|
|
LsapAuditFailed(Status);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
VOID
|
|
LsapAdtAuditLogon(
|
|
IN USHORT EventCategory,
|
|
IN ULONG EventID,
|
|
IN USHORT EventType,
|
|
IN PUNICODE_STRING AccountName,
|
|
IN PUNICODE_STRING AuthenticatingAuthority,
|
|
IN PUNICODE_STRING Source,
|
|
IN PUNICODE_STRING PackageName,
|
|
IN SECURITY_LOGON_TYPE LogonType,
|
|
IN PSID UserSid,
|
|
IN LUID AuthenticationId,
|
|
IN PUNICODE_STRING WorkstationName,
|
|
IN NTSTATUS LogonStatus,
|
|
IN NTSTATUS SubStatus,
|
|
IN LPGUID LogonGuid, OPTIONAL
|
|
IN PLUID CallerLogonId, OPTIONAL
|
|
IN PHANDLE CallerProcessID, OPTIONAL
|
|
IN PLSA_ADT_STRING_LIST TransittedServices, OPTIONAL
|
|
IN SOCKADDR* pSockAddr OPTIONAL
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Generates an audit of a logon event as appropriate.
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
UNICODE_STRING AuthenticationIdString = { 0 };
|
|
BOOLEAN FreeWhenDone = FALSE;
|
|
SE_ADT_PARAMETER_ARRAY AuditParameters;
|
|
BOOL AuditingSuccess;
|
|
BOOL AuditingFailure;
|
|
PSID pSid;
|
|
PLSAP_LOGON_SESSION pLogonSession = NULL;
|
|
BOOLEAN bAudit = FALSE;
|
|
UNICODE_STRING LocalAccountName;
|
|
UNICODE_STRING LocalAuthenticatingAuthority;
|
|
UNICODE_STRING LocalWorkstationName;
|
|
|
|
//
|
|
// Get the system Audit settings
|
|
//
|
|
|
|
AuditingFailure = (EventType == EVENTLOG_AUDIT_FAILURE) && LsapAdtAuditingEnabledByCategory(AuditCategoryLogon, EVENTLOG_AUDIT_FAILURE);
|
|
AuditingSuccess = (EventType == EVENTLOG_AUDIT_SUCCESS) && LsapAdtAuditingEnabledByCategory(AuditCategoryLogon, EVENTLOG_AUDIT_SUCCESS);
|
|
|
|
//
|
|
// If this is a success audit then we have a real user sid. Check if there
|
|
// exist per user audit settings for the user which may override system
|
|
// settings.
|
|
//
|
|
// In case of failed logons, the auth packages do not pass us the
|
|
// user SID therefore we cannot check pua policy here
|
|
//
|
|
|
|
if (AuditingSuccess)
|
|
{
|
|
Status = LsapAdtAuditingEnabledByLogonId(
|
|
AuditCategoryLogon,
|
|
&AuthenticationId,
|
|
EVENTLOG_AUDIT_SUCCESS,
|
|
&bAudit
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status) || !bAudit)
|
|
{
|
|
goto Finish;
|
|
}
|
|
}
|
|
|
|
//
|
|
// return quickly if auditing is not enabled
|
|
//
|
|
if ( !(AuditingFailure || AuditingSuccess || bAudit) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Build an audit parameters structure.
|
|
//
|
|
|
|
RtlZeroMemory ( (PVOID) &AuditParameters, sizeof( AuditParameters ) );
|
|
|
|
AuditParameters.CategoryId = EventCategory;
|
|
AuditParameters.AuditId = EventID;
|
|
AuditParameters.Type = EventType;
|
|
AuditParameters.ParameterCount = 0;
|
|
|
|
//
|
|
// If this is a successful logon audit event and the caller did not
|
|
// supply a logon GUID, extract it from the logon session.
|
|
//
|
|
if ( AuditingSuccess && !LogonGuid &&
|
|
( EventType == EVENTLOG_AUDIT_SUCCESS ) )
|
|
{
|
|
pLogonSession = LsapLocateLogonSession( &AuthenticationId );
|
|
|
|
ASSERT( pLogonSession && L"LsapAdtAuditLogon: logon session not found" );
|
|
|
|
if ( pLogonSession )
|
|
{
|
|
LogonGuid = &pLogonSession->LogonGuid;
|
|
}
|
|
}
|
|
|
|
#if DBG
|
|
if ( AuditingSuccess )
|
|
{
|
|
DsysAssert( EventID != SE_AUDITID_DOMAIN_TRUST_INCONSISTENT );
|
|
}
|
|
#endif
|
|
//
|
|
// User Sid
|
|
//
|
|
|
|
pSid = AuditingSuccess ? UserSid : LsapLocalSystemSid;
|
|
|
|
LsapSetParmTypeSid( AuditParameters, AuditParameters.ParameterCount, pSid );
|
|
|
|
AuditParameters.ParameterCount++;
|
|
|
|
//
|
|
// Subsystem name
|
|
//
|
|
|
|
LsapSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, &LsapSubsystemName );
|
|
AuditParameters.ParameterCount++;
|
|
|
|
//
|
|
// Account name
|
|
//
|
|
|
|
if ( ARGUMENT_PRESENT( AccountName ) ) {
|
|
|
|
|
|
LocalAccountName = *AccountName;
|
|
|
|
if ( EventID == SE_AUDITID_UNKNOWN_USER_OR_PWD ) {
|
|
|
|
//
|
|
// For failed logons of type SE_AUDITID_UNKNOWN_USER_OR_PWD
|
|
// the user name can be invalid (for example,
|
|
// with embedded NULLs). This causes the
|
|
// eventlog to reject the string and we drop the audit.
|
|
//
|
|
// To avoid this, adjust the length parameter if necessary.
|
|
//
|
|
|
|
LocalAccountName.Length =
|
|
(USHORT) LsapSafeWcslen( LocalAccountName.Buffer,
|
|
LocalAccountName.MaximumLength );
|
|
|
|
}
|
|
|
|
LsapSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, &LocalAccountName );
|
|
|
|
}
|
|
|
|
AuditParameters.ParameterCount++;
|
|
|
|
//
|
|
// Authenticating Authority (domain name)
|
|
//
|
|
|
|
if ( ARGUMENT_PRESENT( AuthenticatingAuthority ) ) {
|
|
|
|
|
|
LocalAuthenticatingAuthority = *AuthenticatingAuthority;
|
|
|
|
//
|
|
// The domain name is used by NTLM as unauthenticated hint
|
|
// thus it can be invalid (for example,
|
|
// with embedded NULLs). This causes the
|
|
// eventlog to reject the string and we drop the audit.
|
|
//
|
|
// To avoid this, adjust the length parameter if necessary.
|
|
//
|
|
|
|
LocalAuthenticatingAuthority.Length =
|
|
(USHORT) LsapSafeWcslen( LocalAuthenticatingAuthority.Buffer,
|
|
LocalAuthenticatingAuthority.MaximumLength );
|
|
|
|
|
|
LsapSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, &LocalAuthenticatingAuthority );
|
|
|
|
}
|
|
|
|
AuditParameters.ParameterCount++;
|
|
|
|
if ( AuditingSuccess ) {
|
|
|
|
//
|
|
// Logon Id (as a string)
|
|
//
|
|
|
|
Status = LsapAdtBuildLuidString(
|
|
&AuthenticationId,
|
|
&AuthenticationIdString,
|
|
&FreeWhenDone
|
|
);
|
|
|
|
if ( NT_SUCCESS( Status )) {
|
|
|
|
LsapSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, &AuthenticationIdString );
|
|
|
|
} else {
|
|
|
|
goto Finish;
|
|
}
|
|
|
|
AuditParameters.ParameterCount++;
|
|
}
|
|
|
|
//
|
|
// Logon Type
|
|
//
|
|
|
|
LsapSetParmTypeUlong( AuditParameters, AuditParameters.ParameterCount, LogonType );
|
|
AuditParameters.ParameterCount++;
|
|
|
|
//
|
|
// Source
|
|
//
|
|
|
|
if ( ARGUMENT_PRESENT( Source )) {
|
|
|
|
LsapSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, Source );
|
|
|
|
} else {
|
|
|
|
//
|
|
// No need to do anything here, since an empty entry will turn
|
|
// into a '-' in the output
|
|
//
|
|
|
|
}
|
|
|
|
AuditParameters.ParameterCount++;
|
|
|
|
//
|
|
// Authentication Package
|
|
//
|
|
|
|
LsapSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, PackageName );
|
|
AuditParameters.ParameterCount++;
|
|
|
|
//
|
|
// Workstation Name
|
|
//
|
|
|
|
if ( ARGUMENT_PRESENT( WorkstationName )) {
|
|
|
|
|
|
LocalWorkstationName = *WorkstationName;
|
|
|
|
//
|
|
// NTLM accepts wks name from clients. A client can supply
|
|
// invalid name (for example, with embedded NULLs). This causes
|
|
// eventlog to reject the string and we drop the audit.
|
|
//
|
|
// To avoid this, adjust the length parameter if necessary.
|
|
//
|
|
|
|
LocalWorkstationName.Length =
|
|
(USHORT) LsapSafeWcslen( LocalWorkstationName.Buffer,
|
|
LocalWorkstationName.MaximumLength );
|
|
|
|
LsapSetParmTypeString( AuditParameters, AuditParameters.ParameterCount, &LocalWorkstationName );
|
|
}
|
|
|
|
AuditParameters.ParameterCount++;
|
|
|
|
if ( EventID == SE_AUDITID_UNSUCCESSFUL_LOGON ) {
|
|
|
|
//
|
|
// we need to supply the logon status for this event,
|
|
// so that some information can be gleened from the log.
|
|
//
|
|
|
|
LsapSetParmTypeHexUlong( AuditParameters, AuditParameters.ParameterCount, LogonStatus );
|
|
AuditParameters.ParameterCount++;
|
|
LsapSetParmTypeHexUlong( AuditParameters, AuditParameters.ParameterCount, SubStatus );
|
|
AuditParameters.ParameterCount++;
|
|
}
|
|
|
|
//
|
|
// Logon GUID
|
|
//
|
|
|
|
if ( ARGUMENT_PRESENT( LogonGuid )) {
|
|
|
|
LsapSetParmTypeGuid( AuditParameters, AuditParameters.ParameterCount, LogonGuid );
|
|
AuditParameters.ParameterCount++;
|
|
}
|
|
|
|
//
|
|
// Caller Logon-ID
|
|
//
|
|
|
|
if ( ARGUMENT_PRESENT( CallerLogonId )) {
|
|
|
|
LsapSetParmTypeLogonId( AuditParameters, AuditParameters.ParameterCount, *CallerLogonId );
|
|
} else {
|
|
|
|
LsapSetParmTypeNoLogon( AuditParameters, AuditParameters.ParameterCount );
|
|
}
|
|
|
|
AuditParameters.ParameterCount++;
|
|
|
|
//
|
|
// Caller Process-ID
|
|
//
|
|
|
|
if ( ARGUMENT_PRESENT( CallerProcessID )) {
|
|
|
|
LsapSetParmTypePtr( AuditParameters, AuditParameters.ParameterCount, *CallerProcessID );
|
|
}
|
|
|
|
AuditParameters.ParameterCount++;
|
|
|
|
//
|
|
// Transitted Services (Kerberos only)
|
|
//
|
|
|
|
if ( ARGUMENT_PRESENT( TransittedServices )) {
|
|
|
|
LsapSetParmTypeStringList( AuditParameters, AuditParameters.ParameterCount, TransittedServices );
|
|
}
|
|
|
|
AuditParameters.ParameterCount++;
|
|
|
|
//
|
|
// IP address/port of caller
|
|
//
|
|
if ( ARGUMENT_PRESENT( pSockAddr )) {
|
|
|
|
LsapSetParmTypeSockAddr( AuditParameters, AuditParameters.ParameterCount, pSockAddr );
|
|
}
|
|
|
|
AuditParameters.ParameterCount++;
|
|
|
|
( VOID ) LsapAdtWriteLog( &AuditParameters );
|
|
|
|
Finish:
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
LsapAuditFailed( Status );
|
|
}
|
|
|
|
if ( FreeWhenDone ) {
|
|
LsapFreeLsaHeap( AuthenticationIdString.Buffer );
|
|
}
|
|
|
|
if ( pLogonSession != NULL )
|
|
{
|
|
LsapReleaseLogonSession( pLogonSession );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
VOID
|
|
LsapAuditLogon(
|
|
IN NTSTATUS LogonStatus,
|
|
IN NTSTATUS LogonSubStatus,
|
|
IN PUNICODE_STRING AccountName,
|
|
IN PUNICODE_STRING AuthenticatingAuthority,
|
|
IN PUNICODE_STRING WorkstationName,
|
|
IN PSID UserSid, OPTIONAL
|
|
IN SECURITY_LOGON_TYPE LogonType,
|
|
IN PTOKEN_SOURCE TokenSource,
|
|
IN PLUID LogonId
|
|
)
|
|
/*++
|
|
|
|
Routine Description/Arguments/Return value
|
|
|
|
See header comment for LsapAuditLogonHelper
|
|
|
|
--*/
|
|
{
|
|
LsapAuditLogonHelper(
|
|
LogonStatus,
|
|
LogonSubStatus,
|
|
AccountName,
|
|
AuthenticatingAuthority,
|
|
WorkstationName,
|
|
UserSid,
|
|
LogonType,
|
|
TokenSource,
|
|
LogonId,
|
|
NULL, // no logon guid
|
|
NULL, // caller logon-id
|
|
NULL, // caller process-id
|
|
NULL // no transitted services
|
|
);
|
|
}
|
|
|
|
|
|
|
|
|
|
VOID
|
|
LsapAuditLogonHelper(
|
|
IN NTSTATUS LogonStatus,
|
|
IN NTSTATUS LogonSubStatus,
|
|
IN PUNICODE_STRING AccountName,
|
|
IN PUNICODE_STRING AuthenticatingAuthority,
|
|
IN PUNICODE_STRING WorkstationName,
|
|
IN PSID UserSid, OPTIONAL
|
|
IN SECURITY_LOGON_TYPE LogonType,
|
|
IN PTOKEN_SOURCE TokenSource,
|
|
IN PLUID LogonId,
|
|
IN LPGUID LogonGuid, OPTIONAL
|
|
IN PLUID CallerLogonId, OPTIONAL
|
|
IN PHANDLE CallerProcessID, OPTIONAL
|
|
IN PLSA_ADT_STRING_LIST TransittedServices OPTIONAL
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Helper routine for security packages to generate a logon audit
|
|
|
|
Arguments:
|
|
LogonStatus - Status code for the logon.
|
|
|
|
LogonSubStatus - more detailed Status code for the logon.
|
|
|
|
AccountName - Name of principal attempting logon.
|
|
|
|
AuthenticatingAuthority - Authority validating the logon.
|
|
|
|
Workstation - Machine from which the logon was attempted.
|
|
For a network logon, this is the client machine.
|
|
|
|
UserSid - Sid for the logged on account.
|
|
|
|
LogonType - Type of logon, such as Network, Interactive, etc.
|
|
|
|
TokenSource - Source for the token.
|
|
|
|
LogonId - If the logon was successful,
|
|
the logon ID for the logon session.
|
|
|
|
LogonGuid - globally unique ID for a logon.
|
|
This is supported only by the kerberos package.
|
|
|
|
CallerLogonId - Logon-ID of the caller.
|
|
For example, if foo calls LsaLogonUser to create
|
|
a logon session for bar. This will be the logon-ID
|
|
of foo.
|
|
|
|
CallerProcessID - Process ID of the calling process.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
ANSI_STRING AnsiSourceContext;
|
|
CHAR AnsiBuffer[TOKEN_SOURCE_LENGTH + 2];
|
|
UNICODE_STRING UnicodeSourceContext;
|
|
WCHAR UnicodeBuffer[TOKEN_SOURCE_LENGTH + 2];
|
|
NTSTATUS Status;
|
|
USHORT EventType;
|
|
USHORT EventCategory;
|
|
ULONG EventID;
|
|
PLSAP_SECURITY_PACKAGE SecurityPackage;
|
|
ULONG_PTR PackageId;
|
|
PLSA_CALL_INFO pCallInfo;
|
|
SOCKADDR* pSockAddr = NULL;
|
|
SOCKADDR EmptySockAddr = {0};
|
|
|
|
//
|
|
// get the IP address/port of the caller
|
|
//
|
|
|
|
pCallInfo = LsapGetCurrentCall();
|
|
|
|
if ( pCallInfo == NULL ) {
|
|
|
|
//
|
|
// If we cannot get the call info then use the 0.0.0.0:0 address.
|
|
//
|
|
pSockAddr = &EmptySockAddr;
|
|
pSockAddr->sa_family = AF_INET;
|
|
} else {
|
|
pSockAddr = (SOCKADDR*) pCallInfo->IpAddress;
|
|
}
|
|
|
|
PackageId = GetCurrentPackageId();
|
|
DsysAssertMsg( PackageId != SPMGR_ID, "LsapAuditLogon" );
|
|
|
|
SecurityPackage = SpmpLocatePackage( PackageId );
|
|
DsysAssertMsg( SecurityPackage != NULL, "LsapAuditLogon" );
|
|
|
|
|
|
//
|
|
// Audit the logon attempt. The event type and logged information
|
|
// will depend to some extent on the whether we failed and why.
|
|
//
|
|
|
|
//
|
|
// Turn the SourceContext into something we can
|
|
// work with.
|
|
//
|
|
|
|
AnsiSourceContext.Buffer = AnsiBuffer;
|
|
AnsiSourceContext.Length = TOKEN_SOURCE_LENGTH * sizeof( CHAR );
|
|
AnsiSourceContext.MaximumLength = (TOKEN_SOURCE_LENGTH + 2) * sizeof( CHAR );
|
|
|
|
UnicodeSourceContext.Buffer = UnicodeBuffer;
|
|
UnicodeSourceContext.MaximumLength = (TOKEN_SOURCE_LENGTH + 2) * sizeof( WCHAR );
|
|
|
|
RtlCopyMemory(
|
|
AnsiBuffer,
|
|
TokenSource->SourceName,
|
|
TOKEN_SOURCE_LENGTH * sizeof( CHAR )
|
|
);
|
|
|
|
Status = RtlAnsiStringToUnicodeString(
|
|
&UnicodeSourceContext,
|
|
&AnsiSourceContext,
|
|
FALSE
|
|
);
|
|
|
|
if ( NT_SUCCESS( Status )) {
|
|
|
|
UnicodeSourceContext.Length =
|
|
(USHORT) LsapSafeWcslen( UnicodeSourceContext.Buffer,
|
|
UnicodeSourceContext.MaximumLength );
|
|
|
|
} else {
|
|
|
|
UnicodeSourceContext.Buffer = NULL;
|
|
|
|
//
|
|
// we cannot fail the audit because of this but catch the
|
|
// internal clients who supply bad source contexts
|
|
//
|
|
DsysAssertMsg( FALSE, "LsapAuditLogon: could not convert AnsiSourceContext to unicode" );
|
|
}
|
|
|
|
//
|
|
// Assume the logon failed, reset if necessary.
|
|
//
|
|
|
|
EventCategory = SE_CATEGID_LOGON;
|
|
EventType = EVENTLOG_AUDIT_FAILURE;
|
|
|
|
|
|
switch ( LogonStatus )
|
|
{
|
|
case STATUS_SUCCESS:
|
|
{
|
|
//
|
|
// Use a separate event for network logons
|
|
//
|
|
|
|
if (( LogonType == Network ) ||
|
|
( LogonType == NetworkCleartext ))
|
|
{
|
|
EventID = SE_AUDITID_NETWORK_LOGON;
|
|
}
|
|
else
|
|
{
|
|
EventID = SE_AUDITID_SUCCESSFUL_LOGON;
|
|
}
|
|
|
|
EventType = EVENTLOG_AUDIT_SUCCESS;
|
|
break;
|
|
}
|
|
|
|
case STATUS_BAD_VALIDATION_CLASS:
|
|
EventID = SE_AUDITID_UNSUCCESSFUL_LOGON;
|
|
break;
|
|
|
|
case STATUS_ACCOUNT_EXPIRED:
|
|
EventID = SE_AUDITID_ACCOUNT_EXPIRED;
|
|
break;
|
|
|
|
case STATUS_NETLOGON_NOT_STARTED:
|
|
EventID = SE_AUDITID_NETLOGON_NOT_STARTED;
|
|
break;
|
|
|
|
case STATUS_ACCOUNT_LOCKED_OUT:
|
|
EventID = SE_AUDITID_ACCOUNT_LOCKED;
|
|
break;
|
|
|
|
case STATUS_LOGON_TYPE_NOT_GRANTED:
|
|
EventID = SE_AUDITID_LOGON_TYPE_RESTR;
|
|
break;
|
|
|
|
case STATUS_PASSWORD_MUST_CHANGE:
|
|
EventID = SE_AUDITID_PASSWORD_EXPIRED;
|
|
break;
|
|
|
|
|
|
case STATUS_ACCOUNT_RESTRICTION:
|
|
{
|
|
|
|
switch ( LogonSubStatus )
|
|
{
|
|
case STATUS_PASSWORD_EXPIRED:
|
|
EventID = SE_AUDITID_PASSWORD_EXPIRED;
|
|
break;
|
|
|
|
case STATUS_ACCOUNT_DISABLED:
|
|
EventID = SE_AUDITID_ACCOUNT_DISABLED;
|
|
break;
|
|
|
|
case STATUS_INVALID_LOGON_HOURS:
|
|
EventID = SE_AUDITID_ACCOUNT_TIME_RESTR;
|
|
break;
|
|
|
|
case STATUS_INVALID_WORKSTATION:
|
|
EventID = SE_AUDITID_WORKSTATION_RESTR;
|
|
break;
|
|
|
|
default:
|
|
EventID = SE_AUDITID_UNKNOWN_USER_OR_PWD;
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case STATUS_LOGON_FAILURE:
|
|
{
|
|
if ( ( LogonSubStatus == STATUS_WRONG_PASSWORD ) ||
|
|
( LogonSubStatus == STATUS_NO_SUCH_USER ) )
|
|
{
|
|
EventID = SE_AUDITID_UNKNOWN_USER_OR_PWD;
|
|
|
|
}
|
|
else if ( LogonSubStatus == STATUS_DOMAIN_TRUST_INCONSISTENT )
|
|
{
|
|
EventID = SE_AUDITID_DOMAIN_TRUST_INCONSISTENT;
|
|
}
|
|
else
|
|
{
|
|
EventID = SE_AUDITID_UNSUCCESSFUL_LOGON;
|
|
}
|
|
break;
|
|
}
|
|
|
|
default:
|
|
EventID = SE_AUDITID_UNSUCCESSFUL_LOGON;
|
|
break;
|
|
}
|
|
|
|
LsapAdtAuditLogon( EventCategory,
|
|
EventID,
|
|
EventType,
|
|
AccountName,
|
|
AuthenticatingAuthority,
|
|
&UnicodeSourceContext,
|
|
&SecurityPackage->Name,
|
|
LogonType,
|
|
UserSid,
|
|
*LogonId,
|
|
WorkstationName,
|
|
LogonStatus,
|
|
LogonSubStatus,
|
|
LogonGuid,
|
|
CallerLogonId,
|
|
CallerProcessID,
|
|
TransittedServices,
|
|
pSockAddr
|
|
);
|
|
|
|
}
|
|
|
|
|
|
VOID
|
|
LsapAdtAuditLogoff(
|
|
PLSAP_LOGON_SESSION Session
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Generates a logoff audit. The caller is responsible for determining
|
|
if logoff auditing is enabled.
|
|
|
|
Arguments:
|
|
|
|
Session - Points to the logon session being removed.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
SE_ADT_PARAMETER_ARRAY AuditParameters;
|
|
NTSTATUS Status;
|
|
UNICODE_STRING usLogonId;
|
|
BOOLEAN fFreeLogonId=FALSE;
|
|
|
|
RtlZeroMemory ( &usLogonId, sizeof(UNICODE_STRING) );
|
|
|
|
//
|
|
// normally we would simply store the logon-id to be audited
|
|
// as SeAdtParmTypeLogonId. But in this case, the logon session
|
|
// will have gone away by the time we try to convert it
|
|
// to a string representation in LsapAdtDemarshallAuditInfo.
|
|
// using LsapGetLogonSessionAccountInfo.
|
|
//
|
|
// To avoid this, we pre-convert the logon-id here
|
|
//
|
|
|
|
Status = LsapAdtBuildLuidString( &Session->LogonId,
|
|
&usLogonId, &fFreeLogonId );
|
|
|
|
if ( !NT_SUCCESS(Status) )
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
Status =
|
|
LsapAdtInitParametersArray(
|
|
&AuditParameters,
|
|
SE_CATEGID_LOGON,
|
|
SE_AUDITID_LOGOFF,
|
|
EVENTLOG_AUDIT_SUCCESS,
|
|
6, // there are 6 params to init
|
|
|
|
//
|
|
// User Sid
|
|
//
|
|
SeAdtParmTypeSid, Session->UserSid,
|
|
|
|
//
|
|
// Subsystem name (if available)
|
|
//
|
|
SeAdtParmTypeString, &LsapSubsystemName,
|
|
|
|
//
|
|
// User
|
|
//
|
|
SeAdtParmTypeString, &Session->AccountName,
|
|
|
|
//
|
|
// Domain
|
|
//
|
|
SeAdtParmTypeString, &Session->AuthorityName,
|
|
|
|
//
|
|
// LogonId
|
|
//
|
|
SeAdtParmTypeString, &usLogonId,
|
|
|
|
//
|
|
// Logon Type
|
|
//
|
|
SeAdtParmTypeUlong, Session->LogonType
|
|
|
|
);
|
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
( VOID ) LsapAdtWriteLog( &AuditParameters );
|
|
|
|
Cleanup:
|
|
if (fFreeLogonId)
|
|
{
|
|
LsapFreeLsaHeap(usLogonId.Buffer);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
LsapAdtAuditPerUserTableCreation(
|
|
BOOLEAN bSuccess
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Generates an audit to report that the per user table was regenerated. The
|
|
table should be locked for read access during this call.
|
|
|
|
This routine will generate a single audit to indicate that the table
|
|
has been created. It will then generate individual audits for each
|
|
user that has an element in the per user audit table.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
SE_ADT_PARAMETER_ARRAY AuditParameters;
|
|
NTSTATUS Status;
|
|
BOOLEAN bAudit;
|
|
ULONG i;
|
|
ULONG j;
|
|
PPER_USER_AUDITING_ELEMENT pElement = NULL;
|
|
LUID TableId;
|
|
ULONG AuditSettings[POLICY_AUDIT_EVENT_TYPE_COUNT];
|
|
|
|
if (!AllocateLocallyUniqueId(&TableId))
|
|
{
|
|
Status = LsapWinerrorToNtStatus(GetLastError());
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// First log an audit to indicate that the table is being
|
|
// created.
|
|
//
|
|
|
|
Status = LsapAdtAuditingEnabledBySid(
|
|
AuditCategoryPolicyChange,
|
|
LsapLocalSystemSid,
|
|
EVENTLOG_AUDIT_SUCCESS,
|
|
&bAudit
|
|
);
|
|
|
|
if (!NT_SUCCESS( Status ))
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
if (bAudit)
|
|
{
|
|
Status =
|
|
LsapAdtInitParametersArray(
|
|
&AuditParameters,
|
|
SE_CATEGID_POLICY_CHANGE,
|
|
SE_AUDITID_PER_USER_AUDIT_TABLE_CREATION,
|
|
bSuccess ? EVENTLOG_AUDIT_SUCCESS : EVENTLOG_AUDIT_FAILURE,
|
|
4,
|
|
|
|
//
|
|
// User Sid
|
|
//
|
|
SeAdtParmTypeSid, LsapLocalSystemSid,
|
|
|
|
//
|
|
// Subsystem name (if available)
|
|
//
|
|
SeAdtParmTypeString, &LsapSubsystemName,
|
|
|
|
//
|
|
// Number of users in the per user table
|
|
//
|
|
SeAdtParmTypeUlong, bSuccess ? LsapAdtPerUserAuditUserCount : 0,
|
|
|
|
//
|
|
// Table ID
|
|
//
|
|
SeAdtParmTypeLuid, TableId
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
(VOID)LsapAdtWriteLog(&AuditParameters);
|
|
|
|
//
|
|
// If this is a failure audit, then exit now.
|
|
//
|
|
|
|
if (!bSuccess)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Now log audits for the individual records in the table.
|
|
//
|
|
|
|
for (i = 0; i < PER_USER_AUDITING_POLICY_TABLE_SIZE; i++)
|
|
{
|
|
pElement = LsapAdtPerUserAuditingTable[i];
|
|
|
|
while (pElement)
|
|
{
|
|
RtlZeroMemory(
|
|
AuditSettings,
|
|
sizeof(AuditSettings)
|
|
);
|
|
|
|
for (j = 0; j < pElement->TokenAuditPolicy.PolicyCount; j++)
|
|
{
|
|
AuditSettings[pElement->TokenAuditPolicy.Policy[j].Category] = pElement->TokenAuditPolicy.Policy[j].PolicyMask;
|
|
}
|
|
|
|
Status =
|
|
LsapAdtInitParametersArray(
|
|
&AuditParameters,
|
|
SE_CATEGID_POLICY_CHANGE,
|
|
SE_AUDITID_PER_USER_AUDIT_TABLE_ELEMENT_CREATION,
|
|
EVENTLOG_AUDIT_SUCCESS,
|
|
13,
|
|
|
|
//
|
|
// User Sid
|
|
//
|
|
SeAdtParmTypeSid, LsapLocalSystemSid,
|
|
|
|
//
|
|
// Subsystem name (if available)
|
|
//
|
|
SeAdtParmTypeString, &LsapSubsystemName,
|
|
|
|
//
|
|
// User Sid
|
|
//
|
|
SeAdtParmTypeSid, pElement->pSid,
|
|
|
|
//
|
|
// Table Id
|
|
//
|
|
SeAdtParmTypeLuid, TableId,
|
|
|
|
//
|
|
// System
|
|
//
|
|
SeAdtParmTypeHexUlong, AuditSettings[AuditCategorySystem],
|
|
|
|
//
|
|
// Logon
|
|
//
|
|
SeAdtParmTypeHexUlong, AuditSettings[AuditCategoryLogon],
|
|
|
|
//
|
|
// Object Access
|
|
//
|
|
SeAdtParmTypeHexUlong, AuditSettings[AuditCategoryObjectAccess],
|
|
|
|
//
|
|
// Privilege Use
|
|
//
|
|
SeAdtParmTypeHexUlong, AuditSettings[AuditCategoryPrivilegeUse],
|
|
|
|
//
|
|
// Detailed Tracking
|
|
//
|
|
SeAdtParmTypeHexUlong, AuditSettings[AuditCategoryDetailedTracking],
|
|
|
|
//
|
|
// Policy Change
|
|
//
|
|
SeAdtParmTypeHexUlong, AuditSettings[AuditCategoryPolicyChange],
|
|
|
|
//
|
|
// Account Management
|
|
//
|
|
SeAdtParmTypeHexUlong, AuditSettings[AuditCategoryAccountManagement],
|
|
|
|
//
|
|
// DS Access
|
|
//
|
|
SeAdtParmTypeHexUlong, AuditSettings[AuditCategoryDirectoryServiceAccess],
|
|
|
|
//
|
|
// Account Logon
|
|
//
|
|
SeAdtParmTypeHexUlong, AuditSettings[AuditCategoryAccountLogon]
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
(VOID)LsapAdtWriteLog(&AuditParameters);
|
|
pElement = pElement->Next;
|
|
}
|
|
}
|
|
|
|
Cleanup:
|
|
|
|
if (!NT_SUCCESS( Status ))
|
|
{
|
|
LsapAuditFailed( Status );
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
LsapAdtLogAuditFailureEvent(
|
|
NTSTATUS AuditStatus
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Generates SE_AUDITID_UNABLE_TO_LOG_EVENTS event
|
|
|
|
Arguments:
|
|
|
|
AuditStatus : failure code
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
SE_ADT_PARAMETER_ARRAY AuditParameters;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
ULONG CrashOnAuditFailState;
|
|
|
|
//
|
|
// determine the CrashOnAuditFailState value
|
|
//
|
|
|
|
if ( LsapCrashOnAuditFail )
|
|
{
|
|
CrashOnAuditFailState = 1;
|
|
}
|
|
else if ( LsapAllowAdminLogonsOnly )
|
|
{
|
|
CrashOnAuditFailState = 2;
|
|
}
|
|
else
|
|
{
|
|
CrashOnAuditFailState = 0;
|
|
}
|
|
|
|
Status =
|
|
LsapAdtInitParametersArray(
|
|
&AuditParameters,
|
|
SE_CATEGID_SYSTEM,
|
|
SE_AUDITID_UNABLE_TO_LOG_EVENTS,
|
|
EVENTLOG_AUDIT_SUCCESS,
|
|
4, // there are 4 params to init
|
|
|
|
//
|
|
// User Sid
|
|
//
|
|
SeAdtParmTypeSid, LsapLocalSystemSid,
|
|
|
|
//
|
|
// Subsystem name (if available)
|
|
//
|
|
SeAdtParmTypeString, &LsapSubsystemName,
|
|
|
|
//
|
|
// Audit failure code
|
|
//
|
|
SeAdtParmTypeHexUlong, AuditStatus,
|
|
|
|
//
|
|
// value of CrashOnAuditFail
|
|
//
|
|
SeAdtParmTypeUlong, CrashOnAuditFailState
|
|
);
|
|
|
|
AdtAssert(NT_SUCCESS(Status), ("LsapAdtLogAuditFailureEvent: LsapAdtInitParametersArray failed: %x", Status));
|
|
|
|
//
|
|
// note: we do not call LsapAuditFailed here because this function
|
|
// itself gets called by LsapAuditFailed. We just hope
|
|
// for the best.
|
|
//
|
|
|
|
//
|
|
// call LsapAdtDemarshallAuditInfo directly so that the audit event
|
|
// will bypass the queue and go directly to the eventlog.
|
|
//
|
|
|
|
Status = LsapAdtDemarshallAuditInfo( &AuditParameters );
|
|
|
|
AdtAssert(NT_SUCCESS(Status), ("LsapAdtLogAuditFailureEvent: LsapAdtDemarshallAuditInfo failed: %x", Status));
|
|
|
|
|
|
//
|
|
// now flush the eventlog
|
|
//
|
|
|
|
Status = LsapFlushSecurityLog();
|
|
|
|
AdtAssert(NT_SUCCESS(Status), ("LsapAdtLogAuditFailureEvent: ElfFlushEventLog failed: %x", Status));
|
|
|
|
}
|