879 lines
20 KiB
C
879 lines
20 KiB
C
/*++
|
||
|
||
Copyright (c) 1991 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
adtinit.c
|
||
|
||
Abstract:
|
||
|
||
Local Security Authority - Auditing Initialization
|
||
|
||
Author:
|
||
|
||
Scott Birrell (ScottBi) November 20, 1991
|
||
|
||
Environment:
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
|
||
#include <msaudite.h>
|
||
#include "lsasrvp.h"
|
||
#include "adtp.h"
|
||
|
||
NTSTATUS LsapAdtInitializeCrashOnFail( VOID );
|
||
BOOL LsapShutdownNotification( IN ULONG ControlType );
|
||
|
||
BOOLEAN LsapShutdownInProgress = FALSE;
|
||
ULONG LsapAdtInitializationPass = 0;
|
||
|
||
|
||
//
|
||
// Array of drive letter to device mappings for generating path strings.
|
||
//
|
||
|
||
DRIVE_MAPPING DriveMappingArray[MAX_DRIVE_MAPPING];
|
||
|
||
|
||
//
|
||
// Name that will be used as the default subsystem name for LSA generated events
|
||
//
|
||
|
||
UNICODE_STRING LsapSubsystemName;
|
||
|
||
|
||
//
|
||
// Special privilege values which are not normally audited,
|
||
// but generate audits when assigned to a user. See
|
||
// LsapAdtAuditSpecialPrivileges.
|
||
//
|
||
|
||
LUID ChangeNotifyPrivilege;
|
||
LUID AuditPrivilege;
|
||
LUID CreateTokenPrivilege;
|
||
LUID AssignPrimaryTokenPrivilege;
|
||
LUID BackupPrivilege;
|
||
LUID RestorePrivilege;
|
||
LUID DebugPrivilege;
|
||
|
||
|
||
//
|
||
// Global variable indicating whether or not we are supposed
|
||
// to crash when an audit fails.
|
||
//
|
||
|
||
BOOLEAN LsapCrashOnAuditFail = FALSE;
|
||
BOOLEAN LsapAllowAdminLogonsOnly = FALSE;
|
||
|
||
|
||
|
||
NTSTATUS
|
||
LsapAdtInitialize(
|
||
IN ULONG Pass
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function performs initialization of auditing within the LSA, and
|
||
it also issues commands to the Reference Monitor to enable it to
|
||
complete any initialization of auditing variables that is dependent
|
||
on the content of the LSA Database. At time of call, the main
|
||
System Init thread is in the Reference Monitor awaiting completion
|
||
of all LSA initialization, and the Reference Monitor Command
|
||
Server thread is waiting for commands.
|
||
|
||
The following steps are performed:
|
||
|
||
o Read the Audit Event and Audit Log information from the LSA
|
||
Database.
|
||
o Call the Event Logging function to open the Audit Log
|
||
o Issue a Reference Monitor command to write the Audit Event Info
|
||
to the Reference-Monitor's in-memory database.
|
||
|
||
Arguments:
|
||
|
||
Pass - Specifies the stage of initialization to be performed.
|
||
|
||
Pass 1 - Initialization required before Audit Records can
|
||
be written to the Audit Log. Any Audit Records received
|
||
during this time will be "cached" by the LSA and will
|
||
be written out at Pass 2.
|
||
|
||
Pass 2 - Write out Audit Records cached during Pass 1.
|
||
|
||
Return Value:
|
||
|
||
NTSTATUS - Standard Nt Result Code.
|
||
|
||
All Result Codes are generated by called routines.
|
||
--*/
|
||
|
||
{
|
||
NTSTATUS Status = STATUS_SUCCESS;
|
||
NTSTATUS SecondaryStatus = STATUS_SUCCESS;
|
||
ULONG AuditLogInfoLength = sizeof (POLICY_AUDIT_LOG_INFO);
|
||
ULONG AuditEventInfoLength = sizeof (LSARM_POLICY_AUDIT_EVENTS_INFO);
|
||
ULONG AuditFullQueryInfoLength = sizeof (POLICY_AUDIT_FULL_QUERY_INFO);
|
||
BOOLEAN AcquiredLock = FALSE;
|
||
UNICODE_STRING UnicodeString;
|
||
PUNICODE_STRING Strings;
|
||
PSID Sid = NULL;
|
||
LSARM_POLICY_AUDIT_EVENTS_INFO AuditEventsInfo;
|
||
|
||
Strings = &UnicodeString;
|
||
|
||
RtlInitUnicodeString( Strings, L"System Restart");
|
||
|
||
RtlInitUnicodeString( &LsapSubsystemName, L"Security" );
|
||
|
||
if (Pass == 1) {
|
||
|
||
Status = LsapAdtInitializeLogQueue();
|
||
|
||
if (!NT_SUCCESS(Status)) {
|
||
|
||
goto AuditInitError;
|
||
}
|
||
|
||
//
|
||
// Acquire the LSA Database Lock.
|
||
//
|
||
|
||
Status = LsapDbAcquireLock();
|
||
|
||
if (!NT_SUCCESS(Status)) {
|
||
|
||
goto AuditInitError;
|
||
}
|
||
|
||
AcquiredLock = TRUE;
|
||
|
||
//
|
||
// Read the Audit Log Information from the PolAdtLg attribute of the Lsa
|
||
// Database object.
|
||
//
|
||
|
||
Status = LsapDbReadAttributeObject(
|
||
LsapDbHandle,
|
||
&LsapDbNames[PolAdtLg],
|
||
&LsapAdtLogInformation,
|
||
&AuditLogInfoLength
|
||
);
|
||
|
||
if (!NT_SUCCESS(Status)) {
|
||
|
||
LsapLogError(
|
||
"LsapAdtInitialize: Read Audit Log Info returned 0x%lx\n",
|
||
Status
|
||
);
|
||
|
||
goto AuditInitError;
|
||
}
|
||
|
||
//
|
||
// Query the Audit Log Full Information in the LSA Database. Note
|
||
// that it is too early to update a log full condition, so don't
|
||
// try to write to the Audit Log.
|
||
//
|
||
|
||
Status = LsapAdtQueryAuditLogFullInfo(
|
||
LsapDbHandle,
|
||
(ULONG) 0,
|
||
&LsapAdtLogFullInformation
|
||
);
|
||
|
||
if (!NT_SUCCESS(Status)) {
|
||
|
||
LsapLogError(
|
||
"LsapAdtInitialize: Update Audit Log Full Info returned 0x%lx\n",
|
||
Status
|
||
);
|
||
|
||
goto AuditInitError;
|
||
}
|
||
|
||
//
|
||
// Read the Audit Event Information from the AdtEvent attribute of the Lsa
|
||
// Database object. The information consists of the Auditing Mode and
|
||
// the Auditing Options for each Audit Event Type.
|
||
//
|
||
|
||
Status = LsapDbReadAttributeObject(
|
||
LsapDbHandle,
|
||
&LsapDbNames[PolAdtEv],
|
||
&AuditEventsInfo,
|
||
&AuditEventInfoLength
|
||
);
|
||
|
||
if (!NT_SUCCESS(Status)) {
|
||
|
||
//
|
||
// This section of code is temporary and allows an old
|
||
// Policy Database to work with the new Audit Event Categories
|
||
// without the need to re-install. The Audit Event Information
|
||
// is overwritten with the new format and all auditing is turned
|
||
// off.
|
||
//
|
||
|
||
if (Status == STATUS_BUFFER_OVERFLOW) {
|
||
|
||
KdPrint(("LsapAdtInitialize: Old Audit Event Info detected\n"
|
||
"Replacing with new format, all auditing disabled\n"));
|
||
|
||
//
|
||
// Initialize Default Event Auditing Options. No auditing is specified
|
||
// for any event type.
|
||
//
|
||
|
||
Status = LsapAdtInitializeDefaultAuditing(
|
||
LSAP_DB_UPDATE_POLICY_DATABASE,
|
||
&AuditEventsInfo
|
||
);
|
||
|
||
if (!NT_SUCCESS(Status)) {
|
||
|
||
goto AuditInitError;
|
||
}
|
||
|
||
} else {
|
||
|
||
LsapLogError(
|
||
"LsapAdtInitialize: Read Audit Event Info returned 0x%lx\n",
|
||
Status
|
||
);
|
||
goto AuditInitError;
|
||
}
|
||
}
|
||
|
||
//
|
||
// Set global flags to tell us if we're supposed to be auditing
|
||
// successful logons, failed logons, or both
|
||
//
|
||
//
|
||
|
||
LsapAdtAuditingLogon( &AuditEventsInfo );
|
||
|
||
//
|
||
// During system initialization, we are effectively logged on as
|
||
// system.
|
||
//
|
||
|
||
LsapAdtSystemRestart( &AuditEventsInfo );
|
||
|
||
(VOID) LsapAdtInitializeCrashOnFail();
|
||
|
||
//
|
||
// Send a command to the Reference Monitor to write the Auditing
|
||
// State to its in-memory data.
|
||
//
|
||
|
||
Status = LsapCallRm(
|
||
RmAuditSetCommand,
|
||
&AuditEventsInfo,
|
||
sizeof (LSARM_POLICY_AUDIT_EVENTS_INFO),
|
||
NULL,
|
||
0
|
||
);
|
||
|
||
if (!NT_SUCCESS(Status)) {
|
||
|
||
LsapLogError("LsapAdtInitialize: LsapCallRm returned 0x%lx\n", Status);
|
||
goto AuditInitError;
|
||
}
|
||
|
||
RtlCopyMemory(
|
||
&LsapAdtEventsInformation,
|
||
&AuditEventsInfo,
|
||
sizeof(LSARM_POLICY_AUDIT_EVENTS_INFO)
|
||
);
|
||
|
||
|
||
LsapAdtInitializeDriveLetters();
|
||
|
||
//
|
||
// Initialize privilege values we need
|
||
//
|
||
|
||
ChangeNotifyPrivilege = RtlConvertLongToLuid( SE_CHANGE_NOTIFY_PRIVILEGE );
|
||
AuditPrivilege = RtlConvertLongToLuid( SE_AUDIT_PRIVILEGE );
|
||
CreateTokenPrivilege = RtlConvertLongToLuid( SE_CREATE_TOKEN_PRIVILEGE );
|
||
AssignPrimaryTokenPrivilege = RtlConvertLongToLuid( SE_ASSIGNPRIMARYTOKEN_PRIVILEGE );
|
||
BackupPrivilege = RtlConvertLongToLuid( SE_BACKUP_PRIVILEGE );
|
||
RestorePrivilege = RtlConvertLongToLuid( SE_RESTORE_PRIVILEGE );
|
||
DebugPrivilege = RtlConvertLongToLuid( SE_DEBUG_PRIVILEGE );
|
||
|
||
//
|
||
// Tell base/wincon how to shut us down.
|
||
// First, tell base to shut us down as late in the game as possible.
|
||
//
|
||
|
||
SetProcessShutdownParameters(LSAP_SHUTDOWN_LEVEL, SHUTDOWN_NORETRY);
|
||
|
||
// And, tell them what function to call when we are being shutdown:
|
||
|
||
SetConsoleCtrlHandler(LsapShutdownNotification, TRUE);
|
||
|
||
|
||
} else if (Pass == 2) {
|
||
|
||
//
|
||
// Write out any Audit Records that were cached during the
|
||
// first stage of initialization. The Audit Log will be opened
|
||
// on the first write if necessary.
|
||
//
|
||
|
||
//
|
||
// BUGBUG - ScottBi 8/6/92 - This action cannot be taken here
|
||
// unless we know that the EventLog service is running. For now,
|
||
// an attempt is made to open the log each time an Audit Record
|
||
// is generated, and the cache grows until a limit is reached,
|
||
// at which point auditing is turned off and subsequent records
|
||
// are discarded.
|
||
//
|
||
|
||
/*
|
||
Status = LsapAdtWriteLog( NULL, (ULONG) 0);
|
||
|
||
if (!NT_SUCCESS(Status)) {
|
||
|
||
goto AuditInitError;
|
||
}
|
||
*/
|
||
}
|
||
|
||
AuditInitFinish:
|
||
|
||
if (AcquiredLock) {
|
||
|
||
LsapDbReleaseLock();
|
||
}
|
||
|
||
return(Status);
|
||
|
||
AuditInitError:
|
||
|
||
//
|
||
// If the Audit Log is full, signal the Log Full condition
|
||
//
|
||
|
||
if (Status == STATUS_LOG_FILE_FULL) {
|
||
|
||
SecondaryStatus = LsapAdtSignalLogFull();
|
||
}
|
||
|
||
//
|
||
// If auditing failed to initialize, output warning and disable
|
||
// auditing.
|
||
//
|
||
|
||
if (Pass == 1) {
|
||
|
||
LsapLogError(
|
||
"LSA: Warning - Audit Initialization Pass 1 Returned 0x%lx\n"
|
||
" Auditing has been disabled\n",
|
||
Status
|
||
);
|
||
|
||
} else {
|
||
|
||
LsapLogError(
|
||
"LSA: Warning - Audit Initialization Pass 2 Returned 0x%lx\n"
|
||
" Auditing has been disabled\n",
|
||
Status
|
||
);
|
||
}
|
||
|
||
LsapAdtEventsInformation.AuditingMode = FALSE;
|
||
|
||
Status = LsarSetInformationPolicy(
|
||
LsapDbHandle,
|
||
PolicyAuditEventsInformation,
|
||
(PLSAPR_POLICY_INFORMATION) &LsapAdtEventsInformation
|
||
);
|
||
|
||
goto AuditInitFinish;
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
LsapAdtInitializeDefaultAuditing(
|
||
IN ULONG Options,
|
||
OUT PLSARM_POLICY_AUDIT_EVENTS_INFO AuditEventsInformation
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine sets an initial default Auditing State in which auditing
|
||
is turned off. It is called only during initialization of the LSA
|
||
or during the installation of its Policy Database. The initial
|
||
auditing state may also optionally be written to the Lsa Policy
|
||
Database provided that the Policy Object has been created and its
|
||
internal handle is available.
|
||
|
||
Arguments:
|
||
|
||
Options - Specifies optional actions to be taken
|
||
|
||
LSAP_DB_UPDATE_POLICY_DATABASE - Update the corresponding information
|
||
in the Policy Database. This option must only be specified
|
||
where it is known that the Policy Object exists.
|
||
|
||
AuditEventsInformation - Pointer to structure that will receive the Audit Event
|
||
Information
|
||
|
||
Return Values:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
NTSTATUS Status = STATUS_SUCCESS;
|
||
LSAP_DB_ATTRIBUTE AuditEventsAttribute;
|
||
BOOLEAN ObjectReferenced = FALSE;
|
||
|
||
ULONG EventAuditingOptionsLength =
|
||
(POLICY_AUDIT_EVENT_TYPE_COUNT * sizeof(POLICY_AUDIT_EVENT_OPTIONS));
|
||
|
||
//
|
||
// Turn off auditing and set the count of Audit Event Types (Categories)
|
||
//
|
||
|
||
AuditEventsInformation->AuditingMode = FALSE;
|
||
AuditEventsInformation->MaximumAuditEventCount = POLICY_AUDIT_EVENT_TYPE_COUNT;
|
||
|
||
//
|
||
// Turn off auditing for all events.
|
||
//
|
||
|
||
RtlZeroMemory(AuditEventsInformation->EventAuditingOptions, EventAuditingOptionsLength);
|
||
|
||
|
||
if (Options & LSAP_DB_UPDATE_POLICY_DATABASE) {
|
||
|
||
ASSERT(LsapPolicyHandle != NULL);
|
||
|
||
//
|
||
// Start a transaction on the Policy Object
|
||
//
|
||
|
||
Status = LsapDbReferenceObject(
|
||
LsapPolicyHandle,
|
||
(ACCESS_MASK) 0,
|
||
PolicyObject,
|
||
LSAP_DB_ACQUIRE_LOCK | LSAP_DB_START_TRANSACTION
|
||
);
|
||
|
||
if (!NT_SUCCESS(Status)) {
|
||
|
||
goto InitializeDefaultAuditingError;
|
||
}
|
||
|
||
ObjectReferenced = TRUE;
|
||
|
||
LsapDbInitializeAttribute(
|
||
&AuditEventsAttribute,
|
||
&LsapDbNames[PolAdtEv],
|
||
AuditEventsInformation,
|
||
sizeof (LSARM_POLICY_AUDIT_EVENTS_INFO),
|
||
FALSE
|
||
);
|
||
|
||
Status = LsapDbWriteAttributesObject(
|
||
LsapPolicyHandle,
|
||
&AuditEventsAttribute,
|
||
(ULONG) 1
|
||
);
|
||
|
||
if (!NT_SUCCESS(Status)) {
|
||
|
||
goto InitializeDefaultAuditingError;
|
||
}
|
||
}
|
||
|
||
InitializeDefaultAuditingFinish:
|
||
|
||
if (ObjectReferenced) {
|
||
|
||
Status = LsapDbDereferenceObject(
|
||
LsapPolicyHandle,
|
||
PolicyObject,
|
||
LSAP_DB_RELEASE_LOCK | LSAP_DB_FINISH_TRANSACTION,
|
||
(SECURITY_DB_DELTA_TYPE) 0,
|
||
Status
|
||
);
|
||
|
||
ObjectReferenced = FALSE;
|
||
}
|
||
|
||
return(Status);
|
||
|
||
InitializeDefaultAuditingError:
|
||
|
||
goto InitializeDefaultAuditingFinish;
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
LsapAdtInitializeLogQueue(
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function initializes the Audit Log Queue.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Values:
|
||
|
||
NTSTATUS - Standard Nt Result Code
|
||
|
||
Currently, STATUS_SUCCESS is always returned.
|
||
|
||
--*/
|
||
|
||
{
|
||
NTSTATUS Status = STATUS_SUCCESS;
|
||
|
||
Status = RtlInitializeCriticalSection(&LsapAdtQueueLock);
|
||
|
||
if (NT_SUCCESS(Status)) {
|
||
Status = RtlInitializeCriticalSection(&LsapAdtLogFullLock);
|
||
}
|
||
|
||
LsapAdtLogQueue.FirstQueuedRecord = NULL;
|
||
LsapAdtLogQueue.LastQueuedRecord = NULL;
|
||
|
||
return(Status);
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
VOID
|
||
LsapAdtAuditingLogon(
|
||
PLSARM_POLICY_AUDIT_EVENTS_INFO AuditEventsInfo
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Examines auditing data and determines if we are auditing
|
||
logon events.
|
||
|
||
Arguments:
|
||
|
||
|
||
AuditEventsInfo - Auditing data.
|
||
|
||
Return Value:
|
||
|
||
TRUE if auditing logon, FALSE otherwise.
|
||
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
if ( !AuditEventsInfo->AuditingMode ) {
|
||
|
||
LsapAuditSuccessfulLogons = FALSE;
|
||
LsapAuditFailedLogons = FALSE;
|
||
|
||
return;
|
||
}
|
||
|
||
if ( (AuditEventsInfo->EventAuditingOptions)[AuditCategoryLogon] & POLICY_AUDIT_EVENT_SUCCESS ) {
|
||
|
||
LsapAuditSuccessfulLogons = TRUE;
|
||
|
||
} else {
|
||
|
||
LsapAuditSuccessfulLogons = FALSE;
|
||
}
|
||
|
||
|
||
|
||
|
||
if ( (AuditEventsInfo->EventAuditingOptions)[AuditCategoryLogon] & POLICY_AUDIT_EVENT_FAILURE ) {
|
||
|
||
LsapAuditFailedLogons = TRUE;
|
||
|
||
} else {
|
||
|
||
LsapAuditFailedLogons = FALSE;
|
||
}
|
||
}
|
||
|
||
|
||
|
||
VOID
|
||
LsapAdtInitializeDriveLetters(
|
||
VOID
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Initializes an array of symbolic link to drive letter mappings
|
||
for use by auditing code.
|
||
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
UNICODE_STRING LinkName;
|
||
PUNICODE_STRING DeviceName;
|
||
OBJECT_ATTRIBUTES Obja;
|
||
HANDLE LinkHandle;
|
||
NTSTATUS Status;
|
||
ULONG i;
|
||
PWCHAR p;
|
||
PWCHAR DeviceNameBuffer;
|
||
ULONG MappingIndex = 0;
|
||
|
||
WCHAR wszDosDevices[sizeof(L"\\DosDevices\\A:") + 1];
|
||
|
||
wcscpy(wszDosDevices, L"\\DosDevices\\A:");
|
||
|
||
RtlInitUnicodeString(&LinkName, wszDosDevices);
|
||
|
||
|
||
p = (PWCHAR)LinkName.Buffer;
|
||
|
||
//
|
||
// Make p point to the drive letter in the LinkName string
|
||
//
|
||
|
||
p = p+12;
|
||
|
||
|
||
|
||
for( i=0 ; i<26 ; i++ ){
|
||
|
||
*p = (WCHAR)'A' + (WCHAR)i;
|
||
|
||
InitializeObjectAttributes(
|
||
&Obja,
|
||
&LinkName,
|
||
OBJ_CASE_INSENSITIVE,
|
||
NULL,
|
||
NULL
|
||
);
|
||
Status = NtOpenSymbolicLinkObject(
|
||
&LinkHandle,
|
||
SYMBOLIC_LINK_QUERY,
|
||
&Obja
|
||
);
|
||
if (NT_SUCCESS( Status )) {
|
||
|
||
//
|
||
// Open succeeded, Now get the link value
|
||
//
|
||
|
||
DriveMappingArray[MappingIndex].DriveLetter = *p;
|
||
DeviceName = &DriveMappingArray[MappingIndex].DeviceName;
|
||
|
||
|
||
DeviceNameBuffer = LsapAllocateLsaHeap( MAXIMUM_FILENAME_LENGTH );
|
||
|
||
|
||
DeviceName->Length = 0;
|
||
DeviceName->MaximumLength = MAXIMUM_FILENAME_LENGTH;
|
||
DeviceName->Buffer = DeviceNameBuffer;
|
||
|
||
Status = NtQuerySymbolicLinkObject(
|
||
LinkHandle,
|
||
DeviceName,
|
||
NULL
|
||
);
|
||
|
||
NtClose(LinkHandle);
|
||
|
||
if ( NT_SUCCESS(Status) ) {
|
||
|
||
MappingIndex++;
|
||
|
||
} else {
|
||
|
||
LsapFreeLsaHeap( DeviceNameBuffer );
|
||
RtlInitUnicodeString( DeviceName, NULL );
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
LsapAdtInitializeCrashOnFail(
|
||
VOID
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Reads the registry to see if the user has told us to crash if an audit fails.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
STATUS_SUCCESS
|
||
|
||
--*/
|
||
|
||
{
|
||
HANDLE KeyHandle;
|
||
NTSTATUS Status;
|
||
NTSTATUS TmpStatus;
|
||
OBJECT_ATTRIBUTES Obja;
|
||
ULONG ResultLength;
|
||
UNICODE_STRING KeyName;
|
||
UNICODE_STRING ValueName;
|
||
CHAR KeyInfo[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(BOOLEAN)];
|
||
PKEY_VALUE_PARTIAL_INFORMATION pKeyInfo;
|
||
|
||
//
|
||
// Check the value of the CrashOnAudit key.
|
||
//
|
||
|
||
RtlInitUnicodeString( &KeyName, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Lsa");
|
||
|
||
InitializeObjectAttributes( &Obja,
|
||
&KeyName,
|
||
OBJ_CASE_INSENSITIVE,
|
||
NULL,
|
||
NULL
|
||
);
|
||
|
||
Status = NtOpenKey(
|
||
&KeyHandle,
|
||
KEY_QUERY_VALUE | KEY_SET_VALUE,
|
||
&Obja
|
||
);
|
||
|
||
|
||
if (Status == STATUS_OBJECT_NAME_NOT_FOUND) {
|
||
LsapCrashOnAuditFail = FALSE;
|
||
return( STATUS_SUCCESS );
|
||
}
|
||
|
||
RtlInitUnicodeString( &ValueName, CRASH_ON_AUDIT_FAIL_VALUE );
|
||
|
||
Status = NtQueryValueKey(
|
||
KeyHandle,
|
||
&ValueName,
|
||
KeyValuePartialInformation,
|
||
KeyInfo,
|
||
sizeof(KeyInfo),
|
||
&ResultLength
|
||
);
|
||
|
||
TmpStatus = NtClose(KeyHandle);
|
||
ASSERT(NT_SUCCESS(TmpStatus));
|
||
|
||
//
|
||
// If it's not found, don't enable CrashOnFail.
|
||
//
|
||
|
||
if (!NT_SUCCESS( Status )) {
|
||
|
||
LsapCrashOnAuditFail = FALSE;
|
||
|
||
} else {
|
||
|
||
//
|
||
// Check the value of the CrashOnFail value. If it is 1, we
|
||
// crash on audit fail. If it is two, we only allow admins to
|
||
// logon.
|
||
//
|
||
|
||
pKeyInfo = (PKEY_VALUE_PARTIAL_INFORMATION)KeyInfo;
|
||
if (*(pKeyInfo->Data) == LSAP_CRASH_ON_AUDIT_FAIL) {
|
||
LsapCrashOnAuditFail = TRUE;
|
||
} else if (*(pKeyInfo->Data) == LSAP_ALLOW_ADIMIN_LOGONS_ONLY) {
|
||
LsapAllowAdminLogonsOnly = TRUE;
|
||
}
|
||
|
||
}
|
||
|
||
if ( LsapCrashOnAuditFail ) {
|
||
|
||
BOOLEAN WasEnabled;
|
||
|
||
Status = RtlAdjustPrivilege(
|
||
SE_SHUTDOWN_PRIVILEGE,
|
||
TRUE,
|
||
FALSE,
|
||
&WasEnabled
|
||
);
|
||
|
||
//
|
||
// This had better work.
|
||
//
|
||
|
||
ASSERT(NT_SUCCESS(Status));
|
||
|
||
return( Status );
|
||
|
||
}
|
||
|
||
return( STATUS_SUCCESS );
|
||
}
|
||
|
||
|
||
BOOL
|
||
LsapShutdownNotification(
|
||
IN ULONG ControlType
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine sets a global flag indicating that shutdown is in progress.
|
||
The flag is used by the auditing subsystem to tell whether to bugcheck
|
||
when an audit fails - we don't want to bugcheck during shutdown because
|
||
the eventlog stopped.
|
||
|
||
Arguments:
|
||
|
||
ControlType - a flag indicating what event occurred.
|
||
|
||
Return Value:
|
||
|
||
TRUE
|
||
|
||
--*/
|
||
{
|
||
if (ControlType == CTRL_SHUTDOWN_EVENT) {
|
||
LsapShutdownInProgress = TRUE;
|
||
}
|
||
return(TRUE);
|
||
}
|
||
|