windows-nt/Source/XPSP1/NT/ds/netapi/svcdlls/logonsrv/server/lsarepl.c

1143 lines
26 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1987-1996 Microsoft Corporation
Module Name:
lsarepl.c
Abstract:
Low level LSA Replication functions.
Author:
06-Apr-1992 (madana)
Created for LSA replication.
Environment:
User mode only.
Contains NT-specific code.
Requires ANSI C extensions: slash-slash comments, long external names.
Revision History:
--*/
//
// Common include files.
//
#include "logonsrv.h" // Include files common to entire service
#pragma hdrstop
#include "lsarepl.h"
NTSTATUS
NlPackLsaPolicy(
IN OUT PNETLOGON_DELTA_ENUM Delta,
IN PDB_INFO DBInfo,
IN LPDWORD BufferSize )
/*++
Routine Description:
Pack a description of the LSA policy info into the specified buffer.
Arguments:
Delta: pointer to the delta structure where the new delta will
be returned.
DBInfo: pointer to the database info structure.
BufferSize: size of MIDL buffer that is consumed for this delta is
returned here.
Return Value:
NT status code.
--*/
{
NTSTATUS Status;
ULONG i;
PLSAPR_SR_SECURITY_DESCRIPTOR SecurityDescriptor = NULL;
PLSAPR_POLICY_INFORMATION PolicyAuditLogInfo = NULL;
PLSAPR_POLICY_INFORMATION PolicyAuditEventsInfo = NULL;
PLSAPR_POLICY_INFORMATION PolicyPrimaryDomainInfo = NULL;
PLSAPR_POLICY_INFORMATION PolicyDefaultQuotaInfo = NULL;
PLSAPR_POLICY_INFORMATION PolicyModificationInfo = NULL;
PNETLOGON_DELTA_POLICY DeltaPolicy = NULL;
DEFPACKTIMER;
DEFLSATIMER;
INITPACKTIMER;
INITLSATIMER;
STARTPACKTIMER;
NlPrint((NL_SYNC_MORE, "Packing Policy Object\n"));
*BufferSize = 0;
Delta->DeltaType = AddOrChangeLsaPolicy;
Delta->DeltaUnion.DeltaPolicy = NULL;
QUERY_LSA_SECOBJ_INFO(DBInfo->DBHandle);
STARTLSATIMER;
Status = LsarQueryInformationPolicy(
DBInfo->DBHandle,
PolicyAuditLogInformation,
&PolicyAuditLogInfo);
STOPLSATIMER;
if (!NT_SUCCESS(Status)) {
PolicyAuditLogInfo = NULL;
goto Cleanup;
}
STARTLSATIMER;
Status = LsarQueryInformationPolicy(
DBInfo->DBHandle,
PolicyAuditEventsInformation,
&PolicyAuditEventsInfo);
STOPLSATIMER;
if (!NT_SUCCESS(Status)) {
PolicyAuditEventsInfo = NULL;
goto Cleanup;
}
STARTLSATIMER;
Status = LsarQueryInformationPolicy(
DBInfo->DBHandle,
PolicyPrimaryDomainInformation,
&PolicyPrimaryDomainInfo);
STOPLSATIMER;
if (!NT_SUCCESS(Status)) {
PolicyPrimaryDomainInfo = NULL;
goto Cleanup;
}
STARTLSATIMER;
Status = LsarQueryInformationPolicy(
DBInfo->DBHandle,
PolicyDefaultQuotaInformation,
&PolicyDefaultQuotaInfo);
STOPLSATIMER;
if (!NT_SUCCESS(Status)) {
PolicyDefaultQuotaInfo = NULL;
goto Cleanup;
}
STARTLSATIMER;
Status = LsarQueryInformationPolicy(
DBInfo->DBHandle,
PolicyModificationInformation,
&PolicyModificationInfo);
STOPLSATIMER;
if (!NT_SUCCESS(Status)) {
PolicyModificationInfo = NULL;
goto Cleanup;
}
//
// Fill in the delta structure
//
//
// copy SID info (There is only one policy database. It has no SID).
//
Delta->DeltaID.Sid = NULL;
//
// allocate delta buffer
//
DeltaPolicy = (PNETLOGON_DELTA_POLICY)
MIDL_user_allocate( sizeof(NETLOGON_DELTA_POLICY) );
if( DeltaPolicy == NULL ) {
Status = STATUS_NO_MEMORY;
goto Cleanup;
}
//
// wipe off the buffer so that cleanup will not be in fault.
//
RtlZeroMemory( DeltaPolicy, sizeof(NETLOGON_DELTA_POLICY) );
// INIT_PLACE_HOLDER(DeltaPolicy);
Delta->DeltaUnion.DeltaPolicy = DeltaPolicy;
*BufferSize += sizeof(NETLOGON_DELTA_POLICY);
DeltaPolicy->MaximumLogSize =
PolicyAuditLogInfo->PolicyAuditLogInfo.MaximumLogSize;
DeltaPolicy->AuditRetentionPeriod;
PolicyAuditLogInfo->PolicyAuditLogInfo.AuditRetentionPeriod;
DeltaPolicy->AuditingMode =
PolicyAuditEventsInfo->
PolicyAuditEventsInfo.AuditingMode;
DeltaPolicy->MaximumAuditEventCount =
PolicyAuditEventsInfo->
PolicyAuditEventsInfo.MaximumAuditEventCount;
*BufferSize += NlCopyData(
(LPBYTE *)&(PolicyAuditEventsInfo->
PolicyAuditEventsInfo.EventAuditingOptions),
(LPBYTE *)&(DeltaPolicy->EventAuditingOptions),
(DeltaPolicy->MaximumAuditEventCount + 1) *
sizeof(ULONG));
// Tell the BDC to 'set' these bits and not just 'or' them in to the current ones
for ( i=0; i<DeltaPolicy->MaximumAuditEventCount; i++ ) {
DeltaPolicy->EventAuditingOptions[i] |= POLICY_AUDIT_EVENT_NONE;
}
//
// sanitity check, EventAuditingOptions size is ULONG size.
//
NlAssert(sizeof(*(PolicyAuditEventsInfo->
PolicyAuditEventsInfo.EventAuditingOptions)) ==
sizeof(ULONG) );
*BufferSize += NlCopyUnicodeString(
(PUNICODE_STRING)&PolicyPrimaryDomainInfo->
PolicyPrimaryDomainInfo.Name,
&DeltaPolicy->PrimaryDomainName );
*BufferSize += NlCopyData(
(LPBYTE *)&(PolicyPrimaryDomainInfo->
PolicyPrimaryDomainInfo.Sid),
(LPBYTE *)&(DeltaPolicy->PrimaryDomainSid),
RtlLengthSid((PSID)(PolicyPrimaryDomainInfo->
PolicyPrimaryDomainInfo.Sid) ));
DeltaPolicy->QuotaLimits.PagedPoolLimit =
(ULONG)PolicyDefaultQuotaInfo->PolicyDefaultQuotaInfo.QuotaLimits.PagedPoolLimit;
DeltaPolicy->QuotaLimits.NonPagedPoolLimit =
(ULONG)PolicyDefaultQuotaInfo->PolicyDefaultQuotaInfo.QuotaLimits.NonPagedPoolLimit;
DeltaPolicy->QuotaLimits.MinimumWorkingSetSize =
(ULONG)PolicyDefaultQuotaInfo->PolicyDefaultQuotaInfo.QuotaLimits.MinimumWorkingSetSize;
DeltaPolicy->QuotaLimits.MaximumWorkingSetSize =
(ULONG)PolicyDefaultQuotaInfo->PolicyDefaultQuotaInfo.QuotaLimits.MaximumWorkingSetSize;
DeltaPolicy->QuotaLimits.PagefileLimit =
(ULONG)PolicyDefaultQuotaInfo->PolicyDefaultQuotaInfo.QuotaLimits.PagefileLimit;
NEW_TO_OLD_LARGE_INTEGER(
PolicyDefaultQuotaInfo->PolicyDefaultQuotaInfo.QuotaLimits.TimeLimit,
DeltaPolicy->QuotaLimits.TimeLimit );
NEW_TO_OLD_LARGE_INTEGER(
PolicyModificationInfo->PolicyModificationInfo.ModifiedId,
DeltaPolicy->ModifiedId );
NEW_TO_OLD_LARGE_INTEGER(
PolicyModificationInfo->PolicyModificationInfo.DatabaseCreationTime,
DeltaPolicy->DatabaseCreationTime );
DELTA_SECOBJ_INFO(DeltaPolicy);
//
// All Done
//
Status = STATUS_SUCCESS;
Cleanup:
STARTLSATIMER;
if ( SecurityDescriptor != NULL ) {
LsaIFree_LSAPR_SR_SECURITY_DESCRIPTOR( SecurityDescriptor );
}
if ( PolicyAuditLogInfo != NULL ) {
LsaIFree_LSAPR_POLICY_INFORMATION(
PolicyAuditLogInformation,
PolicyAuditLogInfo );
}
if ( PolicyAuditEventsInfo != NULL ) {
LsaIFree_LSAPR_POLICY_INFORMATION(
PolicyAuditEventsInformation,
PolicyAuditEventsInfo );
}
if ( PolicyPrimaryDomainInfo != NULL ) {
LsaIFree_LSAPR_POLICY_INFORMATION(
PolicyPrimaryDomainInformation,
PolicyPrimaryDomainInfo );
}
if ( PolicyDefaultQuotaInfo != NULL ) {
LsaIFree_LSAPR_POLICY_INFORMATION(
PolicyDefaultQuotaInformation,
PolicyDefaultQuotaInfo );
}
if ( PolicyModificationInfo != NULL ) {
LsaIFree_LSAPR_POLICY_INFORMATION(
PolicyModificationInformation,
PolicyModificationInfo );
}
STOPLSATIMER;
if( !NT_SUCCESS(Status) ) {
NlFreeDBDelta( Delta );
*BufferSize = 0;
}
STOPPACKTIMER;
NlPrint((NL_REPL_OBJ_TIME,"Time taken to pack POLICY object:\n"));
PRINTPACKTIMER;
PRINTLSATIMER;
return(Status);
}
NTSTATUS
NlPackLsaTDomain(
IN PSID Sid,
IN OUT PNETLOGON_DELTA_ENUM Delta,
IN PDB_INFO DBInfo,
IN LPDWORD BufferSize )
/*++
Routine Description:
Pack a description of the specified trusted domain info into the
specified buffer.
Arguments:
Sid - The SID of the trusted domain.
Delta: pointer to the delta structure where the new delta will
be returned.
DBInfo: pointer to the database info structure.
BufferSize: size of MIDL buffer that is consumed for this delta is
returned here.
Return Value:
NT status code.
--*/
{
NTSTATUS Status;
LSAPR_HANDLE TrustedDomainHandle = NULL;
PLSAPR_TRUSTED_DOMAIN_INFO TrustedDomainNameInfo = NULL;
PLSAPR_TRUSTED_DOMAIN_INFO TrustedPosixOffsetInfo = NULL;
PLSAPR_SR_SECURITY_DESCRIPTOR SecurityDescriptor = NULL;
PNETLOGON_DELTA_TRUSTED_DOMAINS DeltaTDomain = NULL;
DWORD i;
DWORD Entries;
DWORD Size = 0;
PLSAPR_UNICODE_STRING UnicodeControllerName;
DEFPACKTIMER;
DEFLSATIMER;
INITPACKTIMER;
INITLSATIMER;
STARTPACKTIMER;
NlPrint((NL_SYNC_MORE, "Packing Trusted Domain Object\n"));
*BufferSize = 0;
Delta->DeltaType = AddOrChangeLsaTDomain;
Delta->DeltaID.Sid = NULL;
Delta->DeltaUnion.DeltaTDomains = NULL;
//
// open trusted domain
//
STARTLSATIMER;
Status = LsarOpenTrustedDomain(
DBInfo->DBHandle,
(PLSAPR_SID)Sid,
0,
&TrustedDomainHandle );
STOPLSATIMER;
if (!NT_SUCCESS(Status)) {
TrustedDomainHandle = NULL;
goto Cleanup;
}
QUERY_LSA_SECOBJ_INFO(TrustedDomainHandle);
STARTLSATIMER;
Status = LsarQueryInfoTrustedDomain(
TrustedDomainHandle,
TrustedDomainNameInformation,
&TrustedDomainNameInfo );
STOPLSATIMER;
if (!NT_SUCCESS(Status)) {
TrustedDomainNameInfo = NULL;
goto Cleanup;
}
NlPrint((NL_SYNC_MORE,
"\t Trusted Domain Object name %wZ\n",
(PUNICODE_STRING)&TrustedDomainNameInfo->
TrustedDomainNameInfo.Name ));
STARTLSATIMER;
Status = LsarQueryInfoTrustedDomain(
TrustedDomainHandle,
TrustedPosixOffsetInformation,
&TrustedPosixOffsetInfo );
STOPLSATIMER;
if (!NT_SUCCESS(Status)) {
TrustedPosixOffsetInfo = NULL;
goto Cleanup;
}
//
// Fill in the delta structure
//
//
// copy SID info
//
Delta->DeltaID.Sid = MIDL_user_allocate( RtlLengthSid(Sid) );
if( Delta->DeltaID.Sid == NULL ) {
Status = STATUS_NO_MEMORY;
goto Cleanup;
}
RtlCopyMemory( Delta->DeltaID.Sid, Sid, RtlLengthSid(Sid) );
//
// allocate delta buffer
//
DeltaTDomain = (PNETLOGON_DELTA_TRUSTED_DOMAINS)
MIDL_user_allocate( sizeof(NETLOGON_DELTA_TRUSTED_DOMAINS) );
if( DeltaTDomain == NULL ) {
Status = STATUS_NO_MEMORY;
goto Cleanup;
}
//
// wipe off the buffer so that cleanup will not be in fault.
//
RtlZeroMemory( DeltaTDomain, sizeof(NETLOGON_DELTA_TRUSTED_DOMAINS) );
// INIT_PLACE_HOLDER(DeltaTDomain);
Delta->DeltaUnion.DeltaTDomains = DeltaTDomain;
*BufferSize += sizeof(NETLOGON_DELTA_TRUSTED_DOMAINS);
*BufferSize += NlCopyUnicodeString(
(PUNICODE_STRING)&TrustedDomainNameInfo->
TrustedDomainNameInfo.Name,
&DeltaTDomain->DomainName );
DELTA_SECOBJ_INFO(DeltaTDomain);
//
// send Posix Offset info across using place holder.
//
DeltaTDomain->DummyLong1 =
TrustedPosixOffsetInfo->TrustedPosixOffsetInfo.Offset;
//
// All Done
//
Status = STATUS_SUCCESS;
Cleanup:
STARTLSATIMER;
if ( TrustedDomainHandle != NULL ) {
LsarClose( &TrustedDomainHandle );
}
if ( SecurityDescriptor != NULL ) {
LsaIFree_LSAPR_SR_SECURITY_DESCRIPTOR( SecurityDescriptor );
}
if ( TrustedDomainNameInfo != NULL ) {
LsaIFree_LSAPR_TRUSTED_DOMAIN_INFO(
TrustedDomainNameInformation,
TrustedDomainNameInfo );
}
if ( TrustedPosixOffsetInfo != NULL ) {
LsaIFree_LSAPR_TRUSTED_DOMAIN_INFO(
TrustedPosixOffsetInformation,
TrustedPosixOffsetInfo );
}
STOPLSATIMER;
if( !NT_SUCCESS(Status) ) {
NlFreeDBDelta( Delta );
*BufferSize = 0;
}
STOPPACKTIMER;
NlPrint((NL_REPL_OBJ_TIME,"Time taken to pack TDOMAIN object:\n"));
PRINTPACKTIMER;
PRINTLSATIMER;
return(Status);
}
NTSTATUS
NlPackLsaAccount(
IN PSID Sid,
IN OUT PNETLOGON_DELTA_ENUM Delta,
IN PDB_INFO DBInfo,
IN LPDWORD BufferSize,
IN PSESSION_INFO SessionInfo
)
/*++
Routine Description:
Pack a description of the specified LSA account info into the
specified buffer.
Arguments:
Sid - The SID of the LSA account.
Delta: pointer to the delta structure where the new delta will
be returned.
DBInfo: pointer to the database info structure.
BufferSize: size of MIDL buffer that is consumed for this delta is
returned here.
SessionInfo: Info describing BDC that's calling us
Return Value:
NT status code.
--*/
{
NTSTATUS Status;
PLSAPR_SR_SECURITY_DESCRIPTOR SecurityDescriptor = NULL;
PNETLOGON_DELTA_ACCOUNTS DeltaAccount = NULL;
LSAPR_HANDLE AccountHandle = NULL;
PLSAPR_PRIVILEGE_SET Privileges = NULL;
ULONG SystemAccessFlags;
PULONG PrivilegeAttributes;
PUNICODE_STRING PrivilegeNames;
LUID MachineAccountPrivilegeLuid;
DWORD CopiedPrivilegeCount;
DWORD i;
DWORD Size;
DEFPACKTIMER;
DEFLSATIMER;
INITPACKTIMER;
INITLSATIMER;
STARTPACKTIMER;
NlPrint((NL_SYNC_MORE, "Packing Lsa Account Object\n"));
*BufferSize = 0;
MachineAccountPrivilegeLuid = RtlConvertLongToLuid(SE_MACHINE_ACCOUNT_PRIVILEGE);
Delta->DeltaType = AddOrChangeLsaAccount;
Delta->DeltaID.Sid = NULL;
Delta->DeltaUnion.DeltaAccounts = NULL;
//
// open lsa account
//
STARTLSATIMER;
Status = LsarOpenAccount(
DBInfo->DBHandle,
(PLSAPR_SID)Sid,
0,
&AccountHandle );
STOPLSATIMER;
if (!NT_SUCCESS(Status)) {
AccountHandle = NULL;
goto Cleanup;
}
QUERY_LSA_SECOBJ_INFO(AccountHandle);
STARTLSATIMER;
Status = LsarEnumeratePrivilegesAccount(
AccountHandle,
&Privileges );
STOPLSATIMER;
if (!NT_SUCCESS(Status)) {
Privileges = NULL;
goto Cleanup;
}
STARTLSATIMER;
Status = LsarGetSystemAccessAccount(
AccountHandle,
&SystemAccessFlags );
STOPLSATIMER;
if (!NT_SUCCESS(Status)) {
goto Cleanup;
}
//
// Fill in the delta structure
//
//
// copy SID info
//
Delta->DeltaID.Sid = MIDL_user_allocate( RtlLengthSid(Sid) );
if( Delta->DeltaID.Sid == NULL ) {
Status = STATUS_NO_MEMORY;
goto Cleanup;
}
RtlCopyMemory( Delta->DeltaID.Sid, Sid, RtlLengthSid(Sid) );
//
// allocate delta buffer
//
DeltaAccount = (PNETLOGON_DELTA_ACCOUNTS)
MIDL_user_allocate( sizeof(NETLOGON_DELTA_ACCOUNTS) );
if( DeltaAccount == NULL ) {
Status = STATUS_NO_MEMORY;
goto Cleanup;
}
//
// wipe off the buffer so that cleanup will not be in fault.
//
RtlZeroMemory( DeltaAccount, sizeof(NETLOGON_DELTA_ACCOUNTS) );
// INIT_PLACE_HOLDER(DeltaAccount);
Delta->DeltaUnion.DeltaAccounts = DeltaAccount;
*BufferSize += sizeof(NETLOGON_DELTA_ACCOUNTS);
DeltaAccount->PrivilegeControl = Privileges->Control;
DeltaAccount->PrivilegeEntries = 0;
DeltaAccount->PrivilegeAttributes = NULL;
DeltaAccount->PrivilegeNames = NULL;
Size = Privileges->PrivilegeCount * sizeof(ULONG);
PrivilegeAttributes = MIDL_user_allocate( Size );
if( PrivilegeAttributes == NULL ) {
Status = STATUS_NO_MEMORY;
goto Cleanup;
}
DeltaAccount->PrivilegeAttributes = PrivilegeAttributes;
*BufferSize += Size;
Size = Privileges->PrivilegeCount * sizeof(UNICODE_STRING);
PrivilegeNames = MIDL_user_allocate( Size );
if( PrivilegeNames == NULL ) {
Status = STATUS_NO_MEMORY;
goto Cleanup;
}
DeltaAccount->PrivilegeNames = PrivilegeNames;
*BufferSize += Size;
//
// now fill up Privilege Attributes and Names
//
CopiedPrivilegeCount = 0;
for( i = 0; i < Privileges->PrivilegeCount; i++ ) {
//
// Don't replicate SeMachineAccount privilege to NT 3.1. It can't handle it.
// (Use the SUPPORTS_ACCOUNT_LOCKOUT bit so we don't have to consume
// another bit.)
//
if ( (SessionInfo->NegotiatedFlags & NETLOGON_SUPPORTS_ACCOUNT_LOCKOUT) ||
(!RtlEqualLuid((PLUID)(&Privileges->Privilege[i].Luid),
&MachineAccountPrivilegeLuid ))) {
PLSAPR_UNICODE_STRING PrivName = NULL;
*PrivilegeAttributes = Privileges->Privilege[i].Attributes;
//
// convert LUID to Name
//
STARTLSATIMER;
Status = LsarLookupPrivilegeName(
DBInfo->DBHandle,
(PLUID)&Privileges->Privilege[i].Luid,
&PrivName );
STOPLSATIMER;
if (!NT_SUCCESS(Status)) {
goto Cleanup;
}
*BufferSize += NlCopyUnicodeString(
(PUNICODE_STRING)PrivName,
PrivilegeNames );
LsaIFree_LSAPR_UNICODE_STRING( PrivName );
CopiedPrivilegeCount ++;
PrivilegeAttributes++;
PrivilegeNames++;
} else {
NlPrint((NL_SYNC_MORE,
"NlPackLsaAccount: ignored privilege %ld %ld\n",
(PLUID) LongToPtr( (&Privileges->Privilege[i].Luid)->HighPart ),
(PLUID) ULongToPtr( (&Privileges->Privilege[i].Luid)->LowPart ) ));
}
}
DeltaAccount->PrivilegeEntries = CopiedPrivilegeCount;
//
// Send only those bits that NT4.0 BDC understands.
// Otherwise, it will choke on it.
//
DeltaAccount->SystemAccessFlags = SystemAccessFlags & POLICY_MODE_ALL_NT4;
DELTA_SECOBJ_INFO(DeltaAccount);
//
// All Done
//
Status = STATUS_SUCCESS;
Cleanup:
STARTLSATIMER;
if ( AccountHandle != NULL ) {
LsarClose( &AccountHandle );
}
if ( SecurityDescriptor != NULL ) {
LsaIFree_LSAPR_SR_SECURITY_DESCRIPTOR( SecurityDescriptor );
}
if ( Privileges != NULL ) {
LsaIFree_LSAPR_PRIVILEGE_SET( Privileges );
}
STOPLSATIMER;
if( !NT_SUCCESS(Status) ) {
NlFreeDBDelta( Delta );
*BufferSize = 0;
}
STOPPACKTIMER;
NlPrint((NL_REPL_OBJ_TIME,"Time taken to pack LSAACCOUNT object:\n"));
PRINTPACKTIMER;
PRINTLSATIMER;
return(Status);
}
NTSTATUS
NlPackLsaSecret(
IN PUNICODE_STRING Name,
IN OUT PNETLOGON_DELTA_ENUM Delta,
IN PDB_INFO DBInfo,
IN LPDWORD BufferSize,
IN PSESSION_INFO SessionInfo
)
/*++
Routine Description:
Pack a description of the specified LSA secret info into the
specified buffer.
Arguments:
Name - Name of the secret.
Delta: pointer to the delta structure where the new delta will
be returned.
DBInfo: pointer to the database info structure.
BufferSize: size of MIDL buffer that is consumed for this delta is
returned here.
SessionInfo: Information shared between BDC and PDC
Return Value:
NT status code.
--*/
{
NTSTATUS Status;
PLSAPR_SR_SECURITY_DESCRIPTOR SecurityDescriptor = NULL;
LSAPR_HANDLE SecretHandle = NULL;
PNETLOGON_DELTA_SECRET DeltaSecret = NULL;
PLSAPR_CR_CIPHER_VALUE CurrentValue = NULL;
PLSAPR_CR_CIPHER_VALUE OldValue = NULL;
LARGE_INTEGER CurrentValueSetTime;
LARGE_INTEGER OldValueSetTime;
DEFPACKTIMER;
DEFLSATIMER;
INITPACKTIMER;
INITLSATIMER;
STARTPACKTIMER;
NlPrint((NL_SYNC_MORE, "Packing Secret Object: %wZ\n", Name));
//
// we should be packing only GLOBAL secrets
//
NlAssert(
(Name->Length / sizeof(WCHAR) >
LSA_GLOBAL_SECRET_PREFIX_LENGTH ) &&
(_wcsnicmp( Name->Buffer,
LSA_GLOBAL_SECRET_PREFIX,
LSA_GLOBAL_SECRET_PREFIX_LENGTH ) == 0) );
*BufferSize = 0;
Delta->DeltaType = AddOrChangeLsaSecret;
Delta->DeltaID.Name = NULL;
Delta->DeltaUnion.DeltaPolicy = NULL;
//
// open lsa account
//
STARTLSATIMER;
Status = LsarOpenSecret(
DBInfo->DBHandle,
(PLSAPR_UNICODE_STRING)Name,
0,
&SecretHandle );
STOPLSATIMER;
if (!NT_SUCCESS(Status)) {
SecretHandle = NULL;
goto Cleanup;
}
QUERY_LSA_SECOBJ_INFO(SecretHandle);
STARTLSATIMER;
Status = LsarQuerySecret(
SecretHandle,
&CurrentValue,
&CurrentValueSetTime,
&OldValue,
&OldValueSetTime );
STOPLSATIMER;
if (!NT_SUCCESS(Status)) {
CurrentValue = NULL;
OldValue = NULL;
goto Cleanup;
}
//
// Fill in the delta structure
//
//
// copy ID field
//
Delta->DeltaID.Name =
MIDL_user_allocate( Name->Length + sizeof(WCHAR) );
if( Delta->DeltaID.Name == NULL ) {
Status = STATUS_NO_MEMORY;
goto Cleanup;
}
wcsncpy( Delta->DeltaID.Name,
Name->Buffer,
Name->Length / sizeof(WCHAR) );
//
// terminate string
//
Delta->DeltaID.Name[ Name->Length / sizeof(WCHAR) ] = L'\0';
DeltaSecret = (PNETLOGON_DELTA_SECRET)
MIDL_user_allocate( sizeof(NETLOGON_DELTA_SECRET) );
if( DeltaSecret == NULL ) {
Status = STATUS_NO_MEMORY;
goto Cleanup;
}
//
// wipe off the buffer so that cleanup will not be in fault.
//
RtlZeroMemory( DeltaSecret, sizeof(NETLOGON_DELTA_SECRET) );
// INIT_PLACE_HOLDER(DeltaSecret);
Delta->DeltaUnion.DeltaSecret = DeltaSecret;
*BufferSize += sizeof(NETLOGON_DELTA_SECRET);
NEW_TO_OLD_LARGE_INTEGER(
CurrentValueSetTime,
DeltaSecret->CurrentValueSetTime );
NEW_TO_OLD_LARGE_INTEGER(
OldValueSetTime,
DeltaSecret->OldValueSetTime );
if( CurrentValue != NULL && CurrentValue->Buffer != NULL && CurrentValue->Length != 0) {
//
// Copy the secret into an allocated buffer and encrypt it in place.
// Don't use the LSA's buffer since it a ALLOCATE_ALL_NODES.
//
DeltaSecret->CurrentValue.Buffer =
MIDL_user_allocate( CurrentValue->Length );
if( DeltaSecret->CurrentValue.Buffer == NULL ) {
Status = STATUS_NO_MEMORY;
goto Cleanup;
}
DeltaSecret->CurrentValue.Length =
DeltaSecret->CurrentValue.MaximumLength = CurrentValue->Length;
RtlCopyMemory( DeltaSecret->CurrentValue.Buffer,
CurrentValue->Buffer,
CurrentValue->Length );
//
// secret values are encrypted using session keys.
//
Status = NlEncryptSensitiveData(
(PCRYPT_BUFFER) &DeltaSecret->CurrentValue,
SessionInfo );
if (!NT_SUCCESS(Status)) {
goto Cleanup;
}
} else {
DeltaSecret->CurrentValue.Length = 0;
DeltaSecret->CurrentValue.MaximumLength = 0;
DeltaSecret->CurrentValue.Buffer = NULL;
}
*BufferSize += DeltaSecret->CurrentValue.MaximumLength;
if( OldValue != NULL && OldValue->Buffer != NULL && OldValue->Length != 0 ) {
//
// Copy the secret into an allocated buffer and encrypt it in place.
// Don't use the LSA's buffer since it a ALLOCATE_ALL_NODES.
//
DeltaSecret->OldValue.Buffer =
MIDL_user_allocate( OldValue->Length );
if( DeltaSecret->OldValue.Buffer == NULL ) {
Status = STATUS_NO_MEMORY;
goto Cleanup;
}
DeltaSecret->OldValue.Length =
DeltaSecret->OldValue.MaximumLength = OldValue->Length;
RtlCopyMemory( DeltaSecret->OldValue.Buffer,
OldValue->Buffer,
OldValue->Length );
//
// secret values are encrypted using session keys.
//
Status = NlEncryptSensitiveData(
(PCRYPT_BUFFER) &DeltaSecret->OldValue,
SessionInfo );
if (!NT_SUCCESS(Status)) {
goto Cleanup;
}
} else {
DeltaSecret->OldValue.Length = 0;
DeltaSecret->OldValue.MaximumLength = 0;
DeltaSecret->OldValue.Buffer = NULL;
}
*BufferSize += DeltaSecret->OldValue.MaximumLength;
DELTA_SECOBJ_INFO(DeltaSecret);
//
// All Done
//
Status = STATUS_SUCCESS;
Cleanup:
STARTLSATIMER;
if ( SecretHandle != NULL ) {
LsarClose( &SecretHandle );
}
if ( SecurityDescriptor != NULL ) {
LsaIFree_LSAPR_SR_SECURITY_DESCRIPTOR( SecurityDescriptor );
}
if( CurrentValue != NULL ) {
LsaIFree_LSAPR_CR_CIPHER_VALUE( CurrentValue );
}
if( OldValue != NULL ) {
LsaIFree_LSAPR_CR_CIPHER_VALUE( OldValue );
}
STOPLSATIMER;
if( !NT_SUCCESS(Status) ) {
NlFreeDBDelta( Delta );
*BufferSize = 0;
}
STOPPACKTIMER;
NlPrint((NL_REPL_OBJ_TIME,"Time taken to pack SECRET object:\n"));
PRINTPACKTIMER;
PRINTLSATIMER;
return(Status);
}