/*++ 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; iMaximumAuditEventCount; 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); }