Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

947 lines
19 KiB

/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
dbadmin.c
Abstract:
Local Security Authority - Database Administration
This file contains routines that perform general Lsa Database
administration functions
Author:
Scott Birrell (ScottBi) August 27, 1991
Environment:
Revision History:
--*/
#include "lsasrvp.h"
#include "dbp.h"
#include "adtp.h"
NTSTATUS
LsapDbSetStates(
IN ULONG DesiredStatesSet
)
/*++
Routine Description:
This routine turns on special states in the Lsa Database. These
states can be turned off using LsapDbResetStates.
Arguments:
DesiredStatesSet - Specifies the states to be set.
LSAP_DB_ACQUIRE_LOCK - Acquire the Lsa Database lock.
LSAP_DB_ACQUIRE_LOG_QUEUE_LOCK - Acquire the Lsa Audit Log
Queue Lock.
LSAP_DB_ENABLE_NON_TRUSTED_ACCESS - Enabled for general access and
update by non-trusted clients.
LSAP_DB_START_TRANSACTION - Start an Lsa Database transaction. There
must not already be one in progress.
Return Value:
NTSTATUS - Standard Nt Result Code
STATUS_INVALID_STATE - The Database is not in the correct state
to allow this state change.
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
NTSTATUS SecondaryStatus = STATUS_SUCCESS;
ULONG StatesSetHere = 0;
//
// If requested, lock the Audit Log Queue
//
if (DesiredStatesSet & LSAP_DB_ACQUIRE_LOG_QUEUE_LOCK) {
Status = LsapAdtAcquireLogQueueLock();
if (!NT_SUCCESS(Status)) {
goto SetStatesError;
}
StatesSetHere |= LSAP_DB_ACQUIRE_LOG_QUEUE_LOCK;
}
//
// If requested, lock the Lsa database
//
if (DesiredStatesSet & LSAP_DB_ACQUIRE_LOCK) {
Status = LsapDbAcquireLock();
if (!NT_SUCCESS(Status)) {
goto SetStatesError;
}
StatesSetHere |= LSAP_DB_ACQUIRE_LOCK;
}
//
// If requested, enable the database for access by non-trusted clients.
//
if (DesiredStatesSet & LSAP_DB_ENABLE_NON_TRUSTED_ACCESS) {
Status = LsapDbEnableNonTrustedAccess();
if (!NT_SUCCESS(Status)) {
goto SetStatesError;
}
StatesSetHere |= LSAP_DB_ENABLE_NON_TRUSTED_ACCESS;
}
//
// If requested, open a database update transaction.
//
if (DesiredStatesSet & LSAP_DB_START_TRANSACTION) {
Status = LsapDbOpenTransaction();
if (!NT_SUCCESS(Status)) {
goto SetStatesError;
}
StatesSetHere |= LSAP_DB_START_TRANSACTION;
}
SetStatesFinish:
return( Status );
SetStatesError:
//
// If we started a transaction, abort it.
//
if (StatesSetHere & LSAP_DB_START_TRANSACTION) {
SecondaryStatus = LsapDbAbortTransaction();
}
//
// If we disabled non-trusted access, re-enable it.
//
if (StatesSetHere & LSAP_DB_DISABLE_NON_TRUSTED_ACCESS) {
SecondaryStatus = LsapDbEnableNonTrustedAccess();
}
//
// If we locked the database, unlock it.
//
if (StatesSetHere & LSAP_DB_ACQUIRE_LOCK) {
LsapDbReleaseLock();
}
//
// If we locked the Audit Log Queue, unlock it.
//
if (StatesSetHere & LSAP_DB_ACQUIRE_LOG_QUEUE_LOCK) {
LsapAdtReleaseLogQueueLock();
}
goto SetStatesFinish;
}
NTSTATUS
LsapDbResetStates(
IN LSAPR_HANDLE ObjectHandle,
IN ULONG Options,
IN SECURITY_DB_DELTA_TYPE SecurityDbDeltaType,
IN NTSTATUS PreliminaryStatus
)
/*++
Routine Description:
This function resets the Lsa Database states specified. It is used
to reset states set by LsapDbSetStates.
Arguments:
ObjectHandle - Handle to an LSA object. This is expected to have
already been validated.
Options - Specifies optional actions, including states to be reset
LSAP_DB_RELEASE_LOCK - Lsa Database lock to be released
LSAP_DB_RELEASE_LOG_QUEUE_LOCK - Lsa Audit Log Queue Lock to
be released.
LSAP_DB_FINISH_TRANSACTION - Lsa database transaction open.
LSAP_DB_DISABLE_NON_TRUSTED_ACCESS - Disable the Lsa Database for
access by non-trusted clients.
LSAP_DB_OMIT_REPLICATOR_NOTIFICATION - Omit notification to
Replicators.
PreliminaryStatus - Indicates the preliminary result code of the
calling routine. Allows reset action to vary depending on the
result code, for example, apply or abort transaction.
Return Value:
NTSTATUS - Standard Nt Result Code. This is the final status to be used
by the caller and is equal to the Preliminary status except in the
case where that is as success status and this routine fails.
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
ULONG StatesResetSuccessfully = 0;
ULONG StatesResetAttempted = 0;
//
// If requested, disable the database for access by non-trusted clients.
//
if (Options & LSAP_DB_DISABLE_NON_TRUSTED_ACCESS) {
StatesResetAttempted |= LSAP_DB_DISABLE_NON_TRUSTED_ACCESS;
Status = LsapDbDisableNonTrustedAccess();
if (!NT_SUCCESS(Status)) {
goto ResetStatesError;
}
StatesResetSuccessfully |= LSAP_DB_DISABLE_NON_TRUSTED_ACCESS;
}
//
// If requested, finish a database update transaction.
//
if (Options & LSAP_DB_FINISH_TRANSACTION) {
StatesResetAttempted |= LSAP_DB_FINISH_TRANSACTION;
if (NT_SUCCESS(PreliminaryStatus)) {
Status = LsapDbApplyTransaction(
ObjectHandle,
Options,
SecurityDbDeltaType
);
} else {
Status = LsapDbAbortTransaction();
}
if (!NT_SUCCESS(Status)) {
goto ResetStatesError;
}
StatesResetSuccessfully |= LSAP_DB_FINISH_TRANSACTION;
}
//
// If unlocking requested, unlock the Lsa Database.
//
if (Options & LSAP_DB_RELEASE_LOCK) {
StatesResetAttempted |= LSAP_DB_RELEASE_LOCK;
LsapDbReleaseLock();
StatesResetSuccessfully |= LSAP_DB_RELEASE_LOCK;
}
//
// If unlocking if the Audit Log Queue requested, unlock the queue.
//
if (Options & LSAP_DB_RELEASE_LOG_QUEUE_LOCK) {
StatesResetAttempted |= LSAP_DB_RELEASE_LOG_QUEUE_LOCK;
LsapAdtReleaseLogQueueLock();
StatesResetSuccessfully |= LSAP_DB_RELEASE_LOG_QUEUE_LOCK;
}
//
// The requested reset operations were performed successfully.
// Propagate the preliminary status back to the caller.
//
Status = PreliminaryStatus;
ResetStatesFinish:
return( Status );
ResetStatesError:
//
// One or more of the requested reset operations could not be performed.
// Attempt to restore the database to a usable state.
//
LsapDbResetStatesError(
ObjectHandle,
PreliminaryStatus,
Options,
SecurityDbDeltaType,
StatesResetAttempted
);
goto ResetStatesFinish;
}
VOID
LsapDbResetStatesError(
IN LSAPR_HANDLE ObjectHandle,
IN NTSTATUS PreliminaryStatus,
IN ULONG Options,
IN SECURITY_DB_DELTA_TYPE SecurityDbDeltaType,
IN ULONG StatesResetAttempted
)
/*++
Routine Description:
This function attempts to restore the Lsa Database state to a usable
form after a call to LsapDbResetStates() has failed. It will attempt
resets that were not attempted by that function because an error
occurred.
Arguments:
ObjectHandle - Handle to an LSA object. This is expected to have
already been validated.
PreliminaryStatus - The preliminary Result Code that the caller of
LsapDbResetStates had. This is normally propagated back by that
caller.
Options - Specifies optional actions, including states to be reset
LSAP_DB_RELEASE_LOCK - Lsa Database lock to be released
LSAP_DB_RELEASE_LOG_QUEUE_LOCK - Lsa Audit Log Queue Lock to
be released.
LSAP_DB_FINISH_TRANSACTION - Lsa database transaction open.
LSAP_DB_DISABLE_NON_TRUSTED_ACCESS - Disable the Lsa Database for
access by non-trusted clients.
LSAP_DB_OMIT_REPLICATOR_NOTIFICATION - Omit notification to
Replicators.
LSAP_DB_REBUILD_CACHE - Rebuild the cache for the object's type.
Note the the cache is normally rebuilt only if the
Preliminary Status was success and the Final Status was
a failure.
StatesResetAttempted - Specifies the state resets that were actually
attempted.
--*/
{
NTSTATUS SecondaryStatus = STATUS_SUCCESS;
NTSTATUS IgnoreStatus;
LSAP_DB_OBJECT_TYPE_ID ObjectTypeId;
//
// If disabling the database for access by non-trusted clients was
// requested but not attempted, do it now. SecondaryStatus is
// intentionally NOT checked afterwards.
//
if (Options & LSAP_DB_DISABLE_NON_TRUSTED_ACCESS) {
SecondaryStatus = LsapDbDisableNonTrustedAccess();
}
//
// If finishing of a database update transaction was requested but
// not attempted, do it now. SecondaryStatus is intentionally NOT
// checked afterwards.
//
if ((Options & LSAP_DB_FINISH_TRANSACTION) &&
!(StatesResetAttempted & LSAP_DB_FINISH_TRANSACTION)) {
if (NT_SUCCESS(PreliminaryStatus)) {
SecondaryStatus = LsapDbApplyTransaction(
ObjectHandle,
Options,
SecurityDbDeltaType
);
} else {
SecondaryStatus = LsapDbAbortTransaction();
}
}
//
// If the PreliminaryStatus was successful, attempt to rebuild
// the cache for this object type.
//
if (NT_SUCCESS(PreliminaryStatus) || (Options & LSAP_DB_REBUILD_CACHE)) {
ObjectTypeId = ((LSAP_DB_HANDLE) ObjectHandle)->ObjectTypeId;
IgnoreStatus = LsapDbRebuildCache( ObjectTypeId );
}
//
// If an unlock of the database was requested but not attempted,
// do this now.
//
if ((Options & LSAP_DB_RELEASE_LOCK) &&
!(StatesResetAttempted & LSAP_DB_RELEASE_LOCK)) {
LsapDbReleaseLock();
}
//
// If an unlock of the Audlt Log Queue was requested but not attempted,
// do this now.
//
if ((Options & LSAP_DB_RELEASE_LOG_QUEUE_LOCK) &&
!(StatesResetAttempted & LSAP_DB_RELEASE_LOG_QUEUE_LOCK)) {
LsapAdtReleaseLogQueueLock();
}
}
NTSTATUS
LsapDbAcquireLock(
)
/*++
Routine Description:
This function acquires the LSA Database Lock. This lock serializes
most Lsa Database operations whether read or update. It is
typically acquired near the beginning of an Lsa Database API server
worker routine and released near the end of the routine.
Arguments:
None.
Return Value:
NTSTATUS - Standard Nt Result Code
--*/
{
NTSTATUS Status;
Status = RtlEnterCriticalSection(&LsapDbState.DbLock);
return Status;
}
VOID
LsapDbReleaseLock(
)
/*++
Routine Description:
This function releases the LSA Database Lock. This lock serializes
most Lsa Database operations whether read or update. It is
typically acquired near the beginning of an Lsa Database API server
worker routine and released near the end of the routine.
Arguments:
None.
Return Value:
None. Any error occurring within this routine is an internal error.
--*/
{
RtlLeaveCriticalSection(&LsapDbState.DbLock);
}
NTSTATUS
LsapDbEnableNonTrustedAccess(
)
/*++
Routine Description:
This function changes the LSA Database State to allow access by non-
Trusted clients.
Arguments:
None.
Return Values:
NTSTATUS - Standard Nt Result Code.
STATUS_INTERNAL_DB_ERROR - An internal error has been detected in
the LSA Database.
STATUS_INVALID_SERVER_STATE - The Lsa Database is in the wrong
state for this operation. Specifically, non-trusted access
is already enables.
Errors from the Registry package.
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
// TBS
return( Status );
}
NTSTATUS
LsapDbDisableNonTrustedAccess(
)
/*++
Routine Description:
This function changes the LSA Database State to disallow access by non-
Trusted clients.
Arguments:
None.
Return Values:
NTSTATUS - Standard Nt Result Code.
STATUS_INTERNAL_DB_ERROR - An internal error has been detected in
the LSA Database.
STATUS_INVALID_SERVER_STATE - The Lsa Database is in the wrong
state for this operation. Specifically, non-trusted access
is already disabled.
Errors from the Registry package.
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
// TBS
return( Status );
}
NTSTATUS
LsapDbOpenTransaction(
)
/*++
Routine Description:
This function starts a transaction within the LSA Database.
WARNING: The Lsa Database must be in the locked state when this function
is called.
Arguments:
None.
Return Value:
NTSTATUS - Standard Nt Result Code
Result codes are those returned from the Registry Transaction
Package.
--*/
{
NTSTATUS Status;
//
// Verify that the LSA Database is locked
//
ASSERT (LsapDbIsLocked());
//
// Start the Regisrtry Transaction
//
Status = RtlStartRXact(LsapDbState.RXactContext);
if (NT_SUCCESS(Status)) {
LsapDbState.TransactionOpen = TRUE;
}
return Status;
}
NTSTATUS
LsapDbApplyTransaction(
IN LSAPR_HANDLE ObjectHandle,
IN ULONG Options,
IN SECURITY_DB_DELTA_TYPE SecurityDbDeltaType
)
/*++
Routine Description:
This function applies a transaction within the LSA Database.
WARNING: The Lsa Database must be in the locked state when this function
is called.
Arguments:
ObjectHandle - Handle to an LSA object. This is expected to have
already been validated.
Options - Specifies optional actions to be taken. The following
options are recognized, other options relevant to calling routines
are ignored.
LSAP_DB_OMIT_REPLICATOR_NOTIFICATION - Omit notification to
Replicator.
Return Value:
NTSTATUS - Standard Nt Result Code
Result codes are those returned from the Registry Transaction
Package.
--*/
{
NTSTATUS Status;
LARGE_INTEGER PromotionIncrement = LSA_PROMOTION_INCREMENT,
Increment = {1,0},
OriginalModifiedId;
//
// Verify that the LSA Database is locked
//
ASSERT (LsapDbIsLocked());
//
// Except in the cases where we are installing the Policy Object,
// we are a Backup Domain Controller, or we are to omit replicator
// notification (e.g. for creation of a local secret), increment
// the Policy Database Modification Count and notify any replicator
// of the change.
//
if ((LsapDbState.PolicyLsaServerRoleInfo.LsaServerRole != PolicyServerRoleBackup) &&
(!(Options & LSAP_DB_OMIT_REPLICATOR_NOTIFICATION)) &&
(LsapDbHandle != NULL)) {
OriginalModifiedId = LsapDbState.PolicyModificationInfo.ModifiedId;
//
// Increment Modification Count.
//
LsapDbState.PolicyModificationInfo.ModifiedId.QuadPart =
LsapDbState.PolicyModificationInfo.ModifiedId.QuadPart +
Increment.QuadPart;
if (Options & LSAP_DB_PROMOTION_INCREMENT) {
LsapDbState.PolicyModificationInfo.ModifiedId.QuadPart =
LsapDbState.PolicyModificationInfo.ModifiedId.QuadPart +
PromotionIncrement.QuadPart;
}
Status = LsapDbWriteAttributeObject(
LsapDbHandle,
&LsapDbNames[ PolMod ],
&LsapDbState.PolicyModificationInfo,
(ULONG) sizeof (POLICY_MODIFICATION_INFO)
);
if (!NT_SUCCESS(Status)) {
goto ApplyTransactionError;
}
//
// Invalidate the cache for the Policy Modification Information
//
LsapDbMakeInvalidInformationPolicy( PolicyModificationInformation );
//
// Apply the Registry Transaction.
//
Status = RtlApplyRXact(LsapDbState.RXactContext);
if (!NT_SUCCESS(Status)) {
goto ApplyTransactionError;
}
//
// Notify the Replicator
//
Status = LsapDbNotifyChangeObject( ObjectHandle, SecurityDbDeltaType );
if (!NT_SUCCESS(Status)) {
goto ApplyTransactionError;
}
} else {
//
// Apply the Registry Transaction.
//
Status = RtlApplyRXact(LsapDbState.RXactContext);
if (!NT_SUCCESS(Status)) {
goto ApplyTransactionError;
}
}
ApplyTransactionFinish:
return( Status );
ApplyTransactionError:
//
// Transaction failed. Adjust in-memory copy of the Modification
// Count, noting that backing store copy is unaltered.
//
LsapDbState.PolicyModificationInfo.ModifiedId =
OriginalModifiedId;
//
// abort the transaction
//
(VOID) RtlAbortRXact( LsapDbState.RXactContext );
goto ApplyTransactionFinish;
}
NTSTATUS
LsapDbAbortTransaction(
)
/*++
Routine Description:
This function aborts a transaction within the LSA Database.
WARNING: The Lsa Database must be in the locked state when this function
is called.
Arguments:
None.
Return Value:
NTSTATUS - Standard Nt Result Code
Result codes are those returned from the Registry Transaction
Package.
--*/
{
//
// Verify that the LSA Database is locked
//
ASSERT (LsapDbIsLocked());
//
// Abort the Registry Transaction
//
LsapDbState.TransactionOpen = FALSE;
return RtlAbortRXact(LsapDbState.RXactContext);
}
BOOLEAN
LsapDbOpenedTransaction(
)
/*++
Routine Description:
This function checks if there is an open LSA Database Transaction.
Arguments:
None.
Return Value:
BOOLEAN - TRUE if there is an open transaction, else FALSE
--*/
{
return LsapDbState.TransactionOpen;
}
BOOLEAN
LsapDbIsServerInitialized(
)
/*++
Routine Description:
This function indicates whether the Lsa Database Server is initialized.
Arguments:
None.
Return Value:
BOOLEAN - TRUE if the LSA Database Server is initialized, else FALSE.
--*/
{
if (LsapDbState.DbServerInitialized) {
return TRUE;
} else {
return FALSE;
}
}
VOID
LsapDbEnableReplicatorNotification(
)
/*++
Routine Description:
This function turns on Replicator Notification.
Arguments:
None.
Return Value:
None.
--*/
{
LsapDbState.ReplicatorNotificationEnabled = TRUE;
}
VOID
LsapDbDisableReplicatorNotification(
)
/*++
Routine Description:
This function turns off Replicator Notification.
Arguments:
None.
Return Value:
None.
--*/
{
LsapDbState.ReplicatorNotificationEnabled = FALSE;
}