Leaked source code of windows server 2003
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.
 
 
 
 
 
 

595 lines
14 KiB

/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
adtpol.c
Abstract:
This file has functions related to audit policy.
Author:
16-August-2000 kumarp
--*/
#include <lsapch2.h>
#include "adtp.h"
//
// Audit Events Information.
//
LSARM_POLICY_AUDIT_EVENTS_INFO LsapAdtEventsInformation;
POLICY_AUDIT_EVENT_TYPE
LsapAdtEventTypeFromCategoryId(
IN ULONG CategoryId
)
/**
Routine Description:
This function translates a Category ID to an POLICY_AUDIT_EVENT_TYPE.
For example SE_CATEGID_SYSTEM is translated to AuditCategorySystem.
Arguments:
CategoryId - category as defined in msaudite.h
Return Value:
POLICY_AUDIT_EVENT_TYPE.
**/
{
ASSERT(SE_ADT_MIN_CATEGORY_ID <= CategoryId && CategoryId <= SE_ADT_MAX_CATEGORY_ID);
return (POLICY_AUDIT_EVENT_TYPE)(CategoryId - 1);
}
BOOLEAN
LsapAdtAuditingEnabledByCategory(
IN POLICY_AUDIT_EVENT_TYPE Category,
IN UINT AuditEventType
)
/**
Routine Description:
This function returns the system audit settings for a given category
and event type. This does not consider any per user settings.
Arguments:
Category - category to query
AuditEventType - either EVENTLOG_AUDIT_SUCCESS or EVENTLOG_AUDIT_FAILURE.
Return Value:
Boolean.
**/
{
if (AuditEventType == EVENTLOG_AUDIT_SUCCESS)
{
return (BOOLEAN)(LsapAdtEventsInformation.EventAuditingOptions[Category] & POLICY_AUDIT_EVENT_SUCCESS);
}
else if (AuditEventType == EVENTLOG_AUDIT_FAILURE)
{
return (BOOLEAN)(LsapAdtEventsInformation.EventAuditingOptions[Category] & POLICY_AUDIT_EVENT_FAILURE);
}
//
// Should not reach this point.
//
ASSERT(FALSE);
return FALSE;
}
NTSTATUS
LsapAdtAuditingEnabledByLogonId(
IN POLICY_AUDIT_EVENT_TYPE Category,
IN PLUID LogonId,
IN UINT AuditEventType,
OUT PBOOLEAN bAudit
)
/**
Routine Description:
Returns whether or not an audit should be generated for a given logon id.
Arguments:
Category - category to query.
LogonId - LogonId of a user.
AuditEventType - either EVENTLOG_AUDIT_SUCCESS or EVENTLOG_AUDIT_FAILURE.
bAudit - address of boolean to receive audit settings.
Return Value:
Appropriate NTSTATUS value.
**/
{
UCHAR Buffer[PER_USER_AUDITING_MAX_POLICY_SIZE];
PTOKEN_AUDIT_POLICY pPolicy = (PTOKEN_AUDIT_POLICY) Buffer;
ULONG Length = sizeof(Buffer);
NTSTATUS Status = STATUS_SUCCESS;
BOOLEAN bFound = FALSE;
ASSERT((AuditEventType == EVENTLOG_AUDIT_SUCCESS) ||
(AuditEventType == EVENTLOG_AUDIT_FAILURE));
if (0 == LsapAdtEventsInformation.EventAuditingOptions[Category] &&
0 == LsapAdtPerUserPolicyCategoryCount[Category])
{
*bAudit = FALSE;
goto Cleanup;
}
//
// Get system settings first.
//
*bAudit = LsapAdtAuditingEnabledByCategory(
Category,
AuditEventType
);
//
// Now get the per user settings.
//
Status = LsapAdtQueryPolicyByLuidPerUserAuditing(
LogonId,
pPolicy,
&Length,
&bFound
);
if (!NT_SUCCESS(Status) || !bFound)
{
goto Cleanup;
}
Status = LsapAdtAuditingEnabledByPolicy(
Category,
pPolicy,
AuditEventType,
bAudit
);
Cleanup:
if (!NT_SUCCESS(Status))
{
LsapAuditFailed(Status);
}
return Status;
}
NTSTATUS
LsapAdtAuditingEnabledBySid(
IN POLICY_AUDIT_EVENT_TYPE Category,
IN PSID UserSid,
IN UINT AuditEventType,
OUT PBOOLEAN bAudit
)
/**
Routine Description:
Returns whether or not an audit should be generated for a given Sid.
Arguments:
Category - category to query.
Sid - Sid of a user.
AuditEventType - either EVENTLOG_AUDIT_SUCCESS or EVENTLOG_AUDIT_FAILURE.
bAudit - address of boolean to receive audit settings.
Return Value:
Appropriate NTSTATUS value.
**/
{
UCHAR Buffer[PER_USER_AUDITING_MAX_POLICY_SIZE];
PTOKEN_AUDIT_POLICY pPolicy = (PTOKEN_AUDIT_POLICY) Buffer;
ULONG Length = sizeof(Buffer);
NTSTATUS Status = STATUS_SUCCESS;
BOOLEAN bFound = FALSE;
ASSERT((AuditEventType == EVENTLOG_AUDIT_SUCCESS) ||
(AuditEventType == EVENTLOG_AUDIT_FAILURE));
if (0 == LsapAdtEventsInformation.EventAuditingOptions[Category] &&
0 == LsapAdtPerUserPolicyCategoryCount[Category])
{
*bAudit = FALSE;
goto Cleanup;
}
//
// Get system settings first.
//
*bAudit = LsapAdtAuditingEnabledByCategory(
Category,
AuditEventType
);
//
// Now get the per user settings.
//
Status = LsapAdtQueryPerUserAuditing(
UserSid,
pPolicy,
&Length,
&bFound
);
if (!NT_SUCCESS(Status) || !bFound)
{
goto Cleanup;
}
Status = LsapAdtAuditingEnabledByPolicy(
Category,
pPolicy,
AuditEventType,
bAudit
);
Cleanup:
if (!NT_SUCCESS(Status))
{
LsapAuditFailed(Status);
}
return Status;
}
NTSTATUS
LsapAdtAuditingEnabledByPolicy(
IN POLICY_AUDIT_EVENT_TYPE Category,
IN PTOKEN_AUDIT_POLICY pPolicy,
IN UINT AuditEventType,
OUT PBOOLEAN bAudit
)
/*++
Routine Description
This routine will indicate whether or not an audit should be generated. It must return
an NT_SUCCESS value, and *bAudit == TRUE to indicate that an audit should be generated.
Arguments
Category - which category to query
pPolicy - policy to read.
AuditEventType - either success or failure.
bAudit - address of a boolean which will indicate if we should audit.
Return Value
Appropriate NTSTATUS value.
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
ULONG i;
ULONG Mask = 0;
BOOLEAN bSuccess;
//
// Set the returns to reflect the system settings.
//
bSuccess = (AuditEventType == EVENTLOG_AUDIT_SUCCESS) ? TRUE : FALSE;
*bAudit = LsapAdtAuditingEnabledByCategory(Category, AuditEventType);
//
// Locate the policy element in the user's Policy that contains information for the
// specified category.
//
// When we go to per event policy this must be modified to use a better search.
//
for (i = 0; i < pPolicy->PolicyCount; i++)
{
if (pPolicy->Policy[i].Category == Category)
{
Mask = pPolicy->Policy[i].PolicyMask;
break;
}
}
//
// Now decide if we should override system policy based upon
// the audit policy of this user.
//
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 ((bSuccess && (Mask & TOKEN_AUDIT_SUCCESS_INCLUDE)) ||
(!bSuccess && (Mask & TOKEN_AUDIT_FAILURE_INCLUDE)))
{
*bAudit = 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 ((bSuccess && (Mask & TOKEN_AUDIT_SUCCESS_EXCLUDE)) ||
(!bSuccess && (Mask & TOKEN_AUDIT_FAILURE_EXCLUDE)))
{
*bAudit = FALSE;
}
}
return Status;
}
BOOLEAN
LsapAdtAuditingEnabledHint(
IN POLICY_AUDIT_EVENT_TYPE AuditCategory,
IN UINT AuditEventType
)
/**
Routine Description
This is a hinting version of LsapAdtAuditingEnabledBy*. It can be called to quickly determine
if an audit codepath may need to be executed.
Arguments
AuditCategory - the category to query
AuditEventType - either a success or failure audit
Return Value
Appropriate NTSTATUS value.
**/
{
BOOLEAN AuditingEnabled;
POLICY_AUDIT_EVENT_OPTIONS EventAuditingOptions;
ASSERT((AuditEventType == EVENTLOG_AUDIT_SUCCESS) ||
(AuditEventType == EVENTLOG_AUDIT_FAILURE));
AuditingEnabled = FALSE;
EventAuditingOptions = LsapAdtEventsInformation.EventAuditingOptions[AuditCategory];
//
// If there are users with this category active in their per user settings, then flip
// both success and fail into the EventAuditingOptions.
//
if (LsapAdtPerUserAuditHint[AuditCategory])
{
EventAuditingOptions |= (POLICY_AUDIT_EVENT_SUCCESS | POLICY_AUDIT_EVENT_FAILURE);
}
AuditingEnabled =
(AuditEventType == EVENTLOG_AUDIT_SUCCESS) ?
(BOOLEAN) (EventAuditingOptions & POLICY_AUDIT_EVENT_SUCCESS) :
(BOOLEAN) (EventAuditingOptions & POLICY_AUDIT_EVENT_FAILURE);
return AuditingEnabled;
}
VOID
LsapAuditFailed(
IN NTSTATUS AuditStatus
)
/*++
Routine Description:
Implements current policy of how to deal with a failed audit.
Arguments:
None.
Return Value:
None.
--*/
{
NTSTATUS Status;
OBJECT_ATTRIBUTES Obja;
HANDLE KeyHandle;
UNICODE_STRING KeyName;
UNICODE_STRING ValueName;
DWORD NewValue;
ULONG Response;
ULONG_PTR HardErrorParam;
BOOLEAN PrivWasEnabled;
if (LsapCrashOnAuditFail) {
//
// Turn off flag in the registry that controls crashing on audit failure
//
RtlInitUnicodeString( &KeyName, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Lsa");
InitializeObjectAttributes( &Obja,
&KeyName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL
);
do {
Status = NtOpenKey(
&KeyHandle,
KEY_SET_VALUE,
&Obja
);
} while ((Status == STATUS_INSUFFICIENT_RESOURCES) || (Status == STATUS_NO_MEMORY));
//
// If the LSA key isn't there, he's got big problems. But don't crash.
//
if (Status == STATUS_OBJECT_NAME_NOT_FOUND) {
LsapCrashOnAuditFail = FALSE;
return;
}
if (!NT_SUCCESS( Status )) {
goto bugcheck;
}
RtlInitUnicodeString( &ValueName, CRASH_ON_AUDIT_FAIL_VALUE );
NewValue = LSAP_ALLOW_ADIMIN_LOGONS_ONLY;
do {
Status = NtSetValueKey( KeyHandle,
&ValueName,
0,
REG_DWORD,
&NewValue,
sizeof(NewValue)
);
} while ((Status == STATUS_INSUFFICIENT_RESOURCES) || (Status == STATUS_NO_MEMORY));
ASSERT(NT_SUCCESS(Status));
if (!NT_SUCCESS( Status )) {
goto bugcheck;
}
do {
Status = NtFlushKey( KeyHandle );
} while ((Status == STATUS_INSUFFICIENT_RESOURCES) || (Status == STATUS_NO_MEMORY));
ASSERT(NT_SUCCESS(Status));
//
// go boom.
//
bugcheck:
//
// Write the audit-failed event to the security log and
// flush the log.
//
LsapAdtLogAuditFailureEvent( AuditStatus );
HardErrorParam = AuditStatus;
//
// stop impersonating
//
Status = NtSetInformationThread(
NtCurrentThread(),
ThreadImpersonationToken,
NULL,
(ULONG) sizeof(HANDLE)
);
DsysAssertMsg( NT_SUCCESS(Status), "LsapAuditFailed: NtSetInformationThread" );
//
// enable the shutdown privilege so that we can bugcheck
//
Status = RtlAdjustPrivilege( SE_SHUTDOWN_PRIVILEGE, TRUE, FALSE, &PrivWasEnabled );
DsysAssertMsg( NT_SUCCESS(Status), "LsapAuditFailed: RtlAdjustPrivilege" );
Status = NtRaiseHardError(
STATUS_AUDIT_FAILED,
1,
0,
&HardErrorParam,
OptionShutdownSystem,
&Response
);
//
// if the bugcheck succeeds, we should not really come here
//
DsysAssertMsg( FALSE, "LsapAuditFailed: we should have bugchecked on the prior line!!" );
}
#if DBG
else
{
DbgPrint("LsapAuditFailed: auditing failed with 0x%x\n", AuditStatus);
if (AuditStatus != RPC_NT_NO_CONTEXT_AVAILABLE &&
AuditStatus != RPC_NT_NO_CALL_ACTIVE &&
LsapAdtNeedToAssert( AuditStatus ))
{
ASSERT(FALSE && "LsapAuditFailed: auditing failed.");
}
}
#endif
}