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);
|
|||
|
}
|
|||
|
|