1605 lines
36 KiB
C
1605 lines
36 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1987-1996 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
replutil.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
Low level functions for SSI Replication apis
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Ported from Lan Man 2.0
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
User mode only.
|
|||
|
Contains NT-specific code.
|
|||
|
Requires ANSI C extensions: slash-slash comments, long external names.
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
22-Jul-1991 (cliffv)
|
|||
|
Ported to NT. Converted to NT style.
|
|||
|
|
|||
|
02-Jan-1992 (madana)
|
|||
|
added support for builtin/multidomain replication.
|
|||
|
|
|||
|
04-Apr-1992 (madana)
|
|||
|
Added support for LSA replication.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
//
|
|||
|
// Common include files.
|
|||
|
//
|
|||
|
|
|||
|
#include "logonsrv.h" // Include files common to entire service
|
|||
|
#pragma hdrstop
|
|||
|
|
|||
|
//
|
|||
|
// Include files specific to this .c file
|
|||
|
//
|
|||
|
|
|||
|
#include <accessp.h> // NetpConvertWorkstationList
|
|||
|
#include "lsarepl.h"
|
|||
|
|
|||
|
|
|||
|
|
|||
|
DWORD
|
|||
|
NlCopyUnicodeString (
|
|||
|
IN PUNICODE_STRING InString,
|
|||
|
OUT PUNICODE_STRING OutString
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine copies the input string to the output. It assumes that
|
|||
|
the input string is allocated by MIDL_user_allocate() and sets the
|
|||
|
input string buffer pointer to NULL so that the buffer will be not
|
|||
|
freed on return.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
InString - Points to the UNICODE string to copy.
|
|||
|
|
|||
|
OutString - Points to the UNICODE string which will be updated to point
|
|||
|
to the input string.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Return the size of the MIDL buffer.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
if ( InString->Length == 0 || InString->Buffer == NULL ) {
|
|||
|
OutString->Length = 0;
|
|||
|
OutString->MaximumLength = 0;
|
|||
|
OutString->Buffer = NULL;
|
|||
|
} else {
|
|||
|
OutString->Length = InString->Length;
|
|||
|
OutString->MaximumLength = InString->Length;
|
|||
|
OutString->Buffer = InString->Buffer;
|
|||
|
InString->Buffer = NULL;
|
|||
|
}
|
|||
|
|
|||
|
return( OutString->MaximumLength );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
DWORD
|
|||
|
NlCopyData(
|
|||
|
IN LPBYTE *InData,
|
|||
|
OUT LPBYTE *OutData,
|
|||
|
DWORD DataLength
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine copies the input data pointer to output data pointer.
|
|||
|
It assumes that the input data buffer is allocated by the
|
|||
|
MIDL_user_allocate() and sets the input buffer buffer pointer to
|
|||
|
NULL on return so that the data buffer will not be freed by SamIFree
|
|||
|
rountine.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
InData - Points to input data buffer pointer.
|
|||
|
|
|||
|
OutString - Pointer to output data buffer pointer.
|
|||
|
|
|||
|
DataLength - Length of input data.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Return the size of the data copied.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
*OutData = *InData;
|
|||
|
*InData = NULL;
|
|||
|
|
|||
|
return(DataLength);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
NlFreeDBDelta(
|
|||
|
IN PNETLOGON_DELTA_ENUM Delta
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine will free the midl buffers that are allocated for
|
|||
|
a delta. This routine does nothing but call the midl generated free
|
|||
|
routine.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Delta: pointer to the delta structure which has to be freed.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
nothing
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
if( Delta != NULL ) {
|
|||
|
_fgs__NETLOGON_DELTA_ENUM (Delta);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
NlFreeDBDeltaArray(
|
|||
|
IN PNETLOGON_DELTA_ENUM DeltaArray,
|
|||
|
IN DWORD ArraySize
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine will free up all delta entries in enum array and the
|
|||
|
array itself.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Delta: pointer to the delta structure array.
|
|||
|
|
|||
|
ArraySize: num of delta structures in the array.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
nothing
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
DWORD i;
|
|||
|
|
|||
|
if( DeltaArray != NULL ) {
|
|||
|
|
|||
|
for( i = 0; i < ArraySize; i++) {
|
|||
|
NlFreeDBDelta( &DeltaArray[i] );
|
|||
|
}
|
|||
|
|
|||
|
MIDL_user_free( DeltaArray );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
NlPackSamUser (
|
|||
|
IN ULONG RelativeId,
|
|||
|
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 user into the specified buffer.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
RelativeId - The relative Id of the user query.
|
|||
|
|
|||
|
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;
|
|||
|
SAMPR_HANDLE UserHandle = NULL;
|
|||
|
PNETLOGON_DELTA_USER DeltaUser;
|
|||
|
PSAMPR_USER_INFO_BUFFER UserAll = NULL;
|
|||
|
|
|||
|
|
|||
|
|
|||
|
DEFPACKTIMER;
|
|||
|
DEFSAMTIMER;
|
|||
|
|
|||
|
INITPACKTIMER;
|
|||
|
INITSAMTIMER;
|
|||
|
|
|||
|
STARTPACKTIMER;
|
|||
|
|
|||
|
NlPrint((NL_SYNC_MORE, "Packing User Object %lx\n", RelativeId));
|
|||
|
|
|||
|
*BufferSize = 0;
|
|||
|
|
|||
|
Delta->DeltaType = AddOrChangeUser;
|
|||
|
Delta->DeltaID.Rid = RelativeId;
|
|||
|
Delta->DeltaUnion.DeltaUser = NULL;
|
|||
|
|
|||
|
//
|
|||
|
// Open a handle to the specified user.
|
|||
|
//
|
|||
|
|
|||
|
STARTSAMTIMER;
|
|||
|
|
|||
|
Status = SamIOpenAccount( DBInfo->DBHandle,
|
|||
|
RelativeId,
|
|||
|
SecurityDbObjectSamUser,
|
|||
|
&UserHandle );
|
|||
|
STOPSAMTIMER;
|
|||
|
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
UserHandle = NULL;
|
|||
|
goto Cleanup;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Query everything there is to know about this user.
|
|||
|
//
|
|||
|
|
|||
|
STARTSAMTIMER;
|
|||
|
|
|||
|
Status = SamrQueryInformationUser(
|
|||
|
UserHandle,
|
|||
|
UserInternal3Information,
|
|||
|
&UserAll );
|
|||
|
STOPSAMTIMER;
|
|||
|
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
UserAll = NULL;
|
|||
|
goto Cleanup;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NlPrint((NL_SYNC_MORE,
|
|||
|
"\t User Object name %wZ\n",
|
|||
|
(PUNICODE_STRING)&UserAll->Internal3.I1.UserName));
|
|||
|
|
|||
|
#define FIELDS_USED ( USER_ALL_USERNAME | \
|
|||
|
USER_ALL_FULLNAME | \
|
|||
|
USER_ALL_USERID | \
|
|||
|
USER_ALL_PRIMARYGROUPID | \
|
|||
|
USER_ALL_HOMEDIRECTORY | \
|
|||
|
USER_ALL_HOMEDIRECTORYDRIVE | \
|
|||
|
USER_ALL_SCRIPTPATH | \
|
|||
|
USER_ALL_PROFILEPATH | \
|
|||
|
USER_ALL_ADMINCOMMENT | \
|
|||
|
USER_ALL_WORKSTATIONS | \
|
|||
|
USER_ALL_LOGONHOURS | \
|
|||
|
USER_ALL_LASTLOGON | \
|
|||
|
USER_ALL_LASTLOGOFF | \
|
|||
|
USER_ALL_BADPASSWORDCOUNT | \
|
|||
|
USER_ALL_LOGONCOUNT | \
|
|||
|
USER_ALL_PASSWORDLASTSET | \
|
|||
|
USER_ALL_ACCOUNTEXPIRES | \
|
|||
|
USER_ALL_USERACCOUNTCONTROL | \
|
|||
|
USER_ALL_USERCOMMENT | \
|
|||
|
USER_ALL_COUNTRYCODE | \
|
|||
|
USER_ALL_CODEPAGE | \
|
|||
|
USER_ALL_PARAMETERS | \
|
|||
|
USER_ALL_NTPASSWORDPRESENT | \
|
|||
|
USER_ALL_LMPASSWORDPRESENT | \
|
|||
|
USER_ALL_PRIVATEDATA | \
|
|||
|
USER_ALL_SECURITYDESCRIPTOR )
|
|||
|
|
|||
|
NlAssert( (UserAll->Internal3.I1.WhichFields & FIELDS_USED) == FIELDS_USED );
|
|||
|
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Allocate a buffer to return to the caller.
|
|||
|
//
|
|||
|
|
|||
|
DeltaUser = (PNETLOGON_DELTA_USER)
|
|||
|
MIDL_user_allocate( sizeof(NETLOGON_DELTA_USER) );
|
|||
|
|
|||
|
if (DeltaUser == NULL) {
|
|||
|
Status = STATUS_NO_MEMORY;
|
|||
|
goto Cleanup;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// wipe off the buffer so that cleanup will not be in fault.
|
|||
|
//
|
|||
|
|
|||
|
RtlZeroMemory( DeltaUser, sizeof(NETLOGON_DELTA_USER) );
|
|||
|
// INIT_PLACE_HOLDER(DeltaUser);
|
|||
|
|
|||
|
Delta->DeltaUnion.DeltaUser = DeltaUser;
|
|||
|
*BufferSize += sizeof(NETLOGON_DELTA_USER);
|
|||
|
|
|||
|
*BufferSize += NlCopyUnicodeString(
|
|||
|
(PUNICODE_STRING)&UserAll->Internal3.I1.UserName,
|
|||
|
&DeltaUser->UserName );
|
|||
|
|
|||
|
*BufferSize += NlCopyUnicodeString(
|
|||
|
(PUNICODE_STRING)&UserAll->Internal3.I1.FullName,
|
|||
|
&DeltaUser->FullName );
|
|||
|
|
|||
|
DeltaUser->UserId = UserAll->Internal3.I1.UserId;
|
|||
|
DeltaUser->PrimaryGroupId = UserAll->Internal3.I1.PrimaryGroupId;
|
|||
|
|
|||
|
*BufferSize += NlCopyUnicodeString(
|
|||
|
(PUNICODE_STRING)&UserAll->Internal3.I1.HomeDirectory,
|
|||
|
&DeltaUser->HomeDirectory );
|
|||
|
|
|||
|
*BufferSize += NlCopyUnicodeString(
|
|||
|
(PUNICODE_STRING)&UserAll->Internal3.I1.HomeDirectoryDrive,
|
|||
|
&DeltaUser->HomeDirectoryDrive );
|
|||
|
|
|||
|
*BufferSize += NlCopyUnicodeString(
|
|||
|
(PUNICODE_STRING)&UserAll->Internal3.I1.ScriptPath,
|
|||
|
&DeltaUser->ScriptPath );
|
|||
|
|
|||
|
*BufferSize += NlCopyUnicodeString(
|
|||
|
(PUNICODE_STRING)&UserAll->Internal3.I1.AdminComment,
|
|||
|
&DeltaUser->AdminComment );
|
|||
|
|
|||
|
*BufferSize += NlCopyUnicodeString(
|
|||
|
(PUNICODE_STRING)&UserAll->Internal3.I1.WorkStations,
|
|||
|
&DeltaUser->WorkStations );
|
|||
|
|
|||
|
DeltaUser->LastLogon = UserAll->Internal3.I1.LastLogon;
|
|||
|
DeltaUser->LastLogoff = UserAll->Internal3.I1.LastLogoff;
|
|||
|
|
|||
|
//
|
|||
|
// Copy Logon Hours
|
|||
|
//
|
|||
|
|
|||
|
DeltaUser->LogonHours.UnitsPerWeek = UserAll->Internal3.I1.LogonHours.UnitsPerWeek;
|
|||
|
DeltaUser->LogonHours.LogonHours = UserAll->Internal3.I1.LogonHours.LogonHours;
|
|||
|
UserAll->Internal3.I1.LogonHours.LogonHours = NULL; // Don't let SAM free this.
|
|||
|
*BufferSize += (UserAll->Internal3.I1.LogonHours.UnitsPerWeek + 7) / 8;
|
|||
|
|
|||
|
|
|||
|
|
|||
|
DeltaUser->BadPasswordCount = UserAll->Internal3.I1.BadPasswordCount;
|
|||
|
DeltaUser->LogonCount = UserAll->Internal3.I1.LogonCount;
|
|||
|
|
|||
|
DeltaUser->PasswordLastSet = UserAll->Internal3.I1.PasswordLastSet;
|
|||
|
DeltaUser->AccountExpires = UserAll->Internal3.I1.AccountExpires;
|
|||
|
|
|||
|
//
|
|||
|
// Don't copy lockout bit to BDC unless it understands it.
|
|||
|
//
|
|||
|
|
|||
|
DeltaUser->UserAccountControl = UserAll->Internal3.I1.UserAccountControl;
|
|||
|
if ( (SessionInfo->NegotiatedFlags & NETLOGON_SUPPORTS_ACCOUNT_LOCKOUT) == 0 ){
|
|||
|
DeltaUser->UserAccountControl &= ~USER_ACCOUNT_AUTO_LOCKED;
|
|||
|
}
|
|||
|
|
|||
|
*BufferSize += NlCopyUnicodeString(
|
|||
|
(PUNICODE_STRING)&UserAll->Internal3.I1.UserComment,
|
|||
|
&DeltaUser->UserComment );
|
|||
|
|
|||
|
*BufferSize += NlCopyUnicodeString(
|
|||
|
(PUNICODE_STRING)&UserAll->Internal3.I1.Parameters,
|
|||
|
&DeltaUser->Parameters );
|
|||
|
|
|||
|
DeltaUser->CountryCode = UserAll->Internal3.I1.CountryCode;
|
|||
|
DeltaUser->CodePage = UserAll->Internal3.I1.CodePage;
|
|||
|
|
|||
|
//
|
|||
|
// Set private data.
|
|||
|
// Includes passwords and password history.
|
|||
|
//
|
|||
|
|
|||
|
DeltaUser->PrivateData.SensitiveData = UserAll->Internal3.I1.PrivateDataSensitive;
|
|||
|
|
|||
|
if ( UserAll->Internal3.I1.PrivateDataSensitive ) {
|
|||
|
|
|||
|
CRYPT_BUFFER Data;
|
|||
|
|
|||
|
//
|
|||
|
// encrypt private data using session key
|
|||
|
// Re-use the SAM's buffer and encrypt it in place.
|
|||
|
//
|
|||
|
|
|||
|
Data.Length = Data.MaximumLength = UserAll->Internal3.I1.PrivateData.Length;
|
|||
|
Data.Buffer = (PUCHAR) UserAll->Internal3.I1.PrivateData.Buffer;
|
|||
|
UserAll->Internal3.I1.PrivateData.Buffer = NULL;
|
|||
|
|
|||
|
Status = NlEncryptSensitiveData( &Data, SessionInfo );
|
|||
|
|
|||
|
if( !NT_SUCCESS(Status) ) {
|
|||
|
goto Cleanup;
|
|||
|
}
|
|||
|
|
|||
|
DeltaUser->PrivateData.DataLength = Data.Length;
|
|||
|
DeltaUser->PrivateData.Data = Data.Buffer;
|
|||
|
} else {
|
|||
|
|
|||
|
DeltaUser->PrivateData.DataLength = UserAll->Internal3.I1.PrivateData.Length;
|
|||
|
DeltaUser->PrivateData.Data = (PUCHAR) UserAll->Internal3.I1.PrivateData.Buffer;
|
|||
|
|
|||
|
UserAll->Internal3.I1.PrivateData.Buffer = NULL;
|
|||
|
}
|
|||
|
|
|||
|
{ // ?? Macro requires a Local named SecurityDescriptor
|
|||
|
PSAMPR_SR_SECURITY_DESCRIPTOR SecurityDescriptor;
|
|||
|
SecurityDescriptor = &UserAll->Internal3.I1.SecurityDescriptor;
|
|||
|
DELTA_SECOBJ_INFO(DeltaUser);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// copy profile path in DummyStrings
|
|||
|
//
|
|||
|
|
|||
|
*BufferSize += NlCopyUnicodeString(
|
|||
|
(PUNICODE_STRING)&UserAll->Internal3.I1.ProfilePath,
|
|||
|
&DeltaUser->DummyString1 );
|
|||
|
|
|||
|
//
|
|||
|
// Copy LastBadPasswordTime to DummyLong1 and DummyLong2.
|
|||
|
//
|
|||
|
|
|||
|
DeltaUser->DummyLong1 = UserAll->Internal3.LastBadPasswordTime.HighPart;
|
|||
|
DeltaUser->DummyLong2 = UserAll->Internal3.LastBadPasswordTime.LowPart;
|
|||
|
|
|||
|
//
|
|||
|
// All Done
|
|||
|
//
|
|||
|
|
|||
|
Status = STATUS_SUCCESS;
|
|||
|
|
|||
|
|
|||
|
Cleanup:
|
|||
|
|
|||
|
|
|||
|
STARTSAMTIMER;
|
|||
|
|
|||
|
if( UserHandle != NULL ) {
|
|||
|
(VOID) SamrCloseHandle( &UserHandle );
|
|||
|
}
|
|||
|
|
|||
|
if ( UserAll != NULL ) {
|
|||
|
SamIFree_SAMPR_USER_INFO_BUFFER( UserAll, UserInternal3Information );
|
|||
|
}
|
|||
|
|
|||
|
STOPSAMTIMER;
|
|||
|
|
|||
|
if( !NT_SUCCESS(Status) ) {
|
|||
|
NlFreeDBDelta( Delta );
|
|||
|
*BufferSize = 0;
|
|||
|
}
|
|||
|
|
|||
|
STOPPACKTIMER;
|
|||
|
|
|||
|
NlPrint((NL_REPL_OBJ_TIME,"Time taken to pack USER object:\n"));
|
|||
|
PRINTPACKTIMER;
|
|||
|
PRINTSAMTIMER;
|
|||
|
|
|||
|
return Status;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
NlPackSamGroup (
|
|||
|
IN ULONG RelativeId,
|
|||
|
IN OUT PNETLOGON_DELTA_ENUM Delta,
|
|||
|
IN PDB_INFO DBInfo,
|
|||
|
LPDWORD BufferSize
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Pack a description of the specified group into the specified buffer.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
RelativeId - The relative Id of the group query.
|
|||
|
|
|||
|
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;
|
|||
|
SAMPR_HANDLE GroupHandle = NULL;
|
|||
|
PNETLOGON_DELTA_GROUP DeltaGroup;
|
|||
|
|
|||
|
//
|
|||
|
// Information returned from SAM
|
|||
|
//
|
|||
|
|
|||
|
PSAMPR_SR_SECURITY_DESCRIPTOR SecurityDescriptor = NULL;
|
|||
|
PSAMPR_GROUP_INFO_BUFFER GroupGeneral = NULL;
|
|||
|
|
|||
|
DEFPACKTIMER;
|
|||
|
DEFSAMTIMER;
|
|||
|
|
|||
|
INITPACKTIMER;
|
|||
|
INITSAMTIMER;
|
|||
|
|
|||
|
STARTPACKTIMER;
|
|||
|
|
|||
|
NlPrint((NL_SYNC_MORE, "Packing Group Object %lx\n", RelativeId ));
|
|||
|
|
|||
|
*BufferSize = 0;
|
|||
|
|
|||
|
Delta->DeltaType = AddOrChangeGroup;
|
|||
|
Delta->DeltaID.Rid = RelativeId;
|
|||
|
Delta->DeltaUnion.DeltaGroup = NULL;
|
|||
|
|
|||
|
//
|
|||
|
// Open a handle to the specified group.
|
|||
|
//
|
|||
|
|
|||
|
STARTSAMTIMER;
|
|||
|
|
|||
|
Status = SamIOpenAccount( DBInfo->DBHandle,
|
|||
|
RelativeId,
|
|||
|
SecurityDbObjectSamGroup,
|
|||
|
&GroupHandle );
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
GroupHandle = NULL;
|
|||
|
goto Cleanup;
|
|||
|
}
|
|||
|
|
|||
|
STOPSAMTIMER;
|
|||
|
|
|||
|
QUERY_SAM_SECOBJ_INFO(GroupHandle);
|
|||
|
|
|||
|
STARTSAMTIMER;
|
|||
|
|
|||
|
Status = SamrQueryInformationGroup(
|
|||
|
GroupHandle,
|
|||
|
GroupReplicationInformation,
|
|||
|
&GroupGeneral );
|
|||
|
|
|||
|
STOPSAMTIMER;
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
GroupGeneral = NULL;
|
|||
|
goto Cleanup;
|
|||
|
}
|
|||
|
|
|||
|
NlPrint((NL_SYNC_MORE,
|
|||
|
"\t Group Object name %wZ\n",
|
|||
|
(PUNICODE_STRING)&GroupGeneral->General.Name ));
|
|||
|
|
|||
|
DeltaGroup = (PNETLOGON_DELTA_GROUP)
|
|||
|
MIDL_user_allocate( sizeof(NETLOGON_DELTA_GROUP) );
|
|||
|
|
|||
|
if( DeltaGroup == NULL ) {
|
|||
|
|
|||
|
Status = STATUS_NO_MEMORY;
|
|||
|
goto Cleanup;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// wipe off the buffer so that cleanup will not be in fault.
|
|||
|
//
|
|||
|
|
|||
|
RtlZeroMemory( DeltaGroup, sizeof(NETLOGON_DELTA_GROUP) );
|
|||
|
// INIT_PLACE_HOLDER(DeltaGroup);
|
|||
|
|
|||
|
Delta->DeltaUnion.DeltaGroup = DeltaGroup;
|
|||
|
*BufferSize += sizeof(NETLOGON_DELTA_GROUP);
|
|||
|
|
|||
|
*BufferSize = NlCopyUnicodeString(
|
|||
|
(PUNICODE_STRING)&GroupGeneral->General.Name,
|
|||
|
&DeltaGroup->Name );
|
|||
|
|
|||
|
DeltaGroup->RelativeId = RelativeId;
|
|||
|
DeltaGroup->Attributes = GroupGeneral->General.Attributes;
|
|||
|
|
|||
|
*BufferSize += NlCopyUnicodeString(
|
|||
|
(PUNICODE_STRING)&GroupGeneral->General.AdminComment,
|
|||
|
&DeltaGroup->AdminComment );
|
|||
|
|
|||
|
|
|||
|
DELTA_SECOBJ_INFO(DeltaGroup);
|
|||
|
|
|||
|
//
|
|||
|
// All Done
|
|||
|
//
|
|||
|
|
|||
|
Status = STATUS_SUCCESS;
|
|||
|
|
|||
|
Cleanup:
|
|||
|
STARTSAMTIMER;
|
|||
|
|
|||
|
if( GroupHandle != NULL ) {
|
|||
|
(VOID) SamrCloseHandle( &GroupHandle );
|
|||
|
}
|
|||
|
|
|||
|
if ( SecurityDescriptor != NULL ) {
|
|||
|
SamIFree_SAMPR_SR_SECURITY_DESCRIPTOR( SecurityDescriptor );
|
|||
|
}
|
|||
|
|
|||
|
if ( GroupGeneral != NULL ) {
|
|||
|
SamIFree_SAMPR_GROUP_INFO_BUFFER( GroupGeneral,
|
|||
|
GroupReplicationInformation );
|
|||
|
}
|
|||
|
|
|||
|
STOPSAMTIMER;
|
|||
|
|
|||
|
if( !NT_SUCCESS(Status) ) {
|
|||
|
NlFreeDBDelta( Delta );
|
|||
|
*BufferSize = 0;
|
|||
|
}
|
|||
|
|
|||
|
STOPPACKTIMER;
|
|||
|
|
|||
|
NlPrint((NL_REPL_OBJ_TIME,"Time taken to pack GROUP object:\n"));
|
|||
|
PRINTPACKTIMER;
|
|||
|
PRINTSAMTIMER;
|
|||
|
|
|||
|
return Status;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
NlPackSamGroupMember (
|
|||
|
IN ULONG RelativeId,
|
|||
|
IN OUT PNETLOGON_DELTA_ENUM Delta,
|
|||
|
IN PDB_INFO DBInfo,
|
|||
|
LPDWORD BufferSize
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Pack a description of the membership of the specified group into
|
|||
|
the specified buffer.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
RelativeId - The relative Id of the group query.
|
|||
|
|
|||
|
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;
|
|||
|
SAMPR_HANDLE GroupHandle = NULL;
|
|||
|
DWORD Size;
|
|||
|
PNETLOGON_DELTA_GROUP_MEMBER DeltaGroupMember;
|
|||
|
|
|||
|
//
|
|||
|
// Information returned from SAM
|
|||
|
//
|
|||
|
|
|||
|
PSAMPR_GET_MEMBERS_BUFFER MembersBuffer = NULL;
|
|||
|
|
|||
|
DEFPACKTIMER;
|
|||
|
DEFSAMTIMER;
|
|||
|
|
|||
|
INITPACKTIMER;
|
|||
|
INITSAMTIMER;
|
|||
|
|
|||
|
STARTPACKTIMER;
|
|||
|
|
|||
|
NlPrint((NL_SYNC_MORE, "Packing GroupMember Object %lx\n", RelativeId));
|
|||
|
|
|||
|
*BufferSize = 0;
|
|||
|
|
|||
|
Delta->DeltaType = ChangeGroupMembership;
|
|||
|
Delta->DeltaID.Rid = RelativeId;
|
|||
|
Delta->DeltaUnion.DeltaGroupMember = NULL;
|
|||
|
|
|||
|
//
|
|||
|
// Open a handle to the specified group.
|
|||
|
//
|
|||
|
|
|||
|
STARTSAMTIMER;
|
|||
|
|
|||
|
Status = SamIOpenAccount( DBInfo->DBHandle,
|
|||
|
RelativeId,
|
|||
|
SecurityDbObjectSamGroup,
|
|||
|
&GroupHandle );
|
|||
|
|
|||
|
STOPSAMTIMER;
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
GroupHandle = NULL;
|
|||
|
goto Cleanup;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Find out everything there is to know about the group.
|
|||
|
//
|
|||
|
|
|||
|
STARTSAMTIMER;
|
|||
|
|
|||
|
Status = SamrGetMembersInGroup( GroupHandle, &MembersBuffer );
|
|||
|
|
|||
|
STOPSAMTIMER;
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
MembersBuffer = NULL;
|
|||
|
goto Cleanup;
|
|||
|
}
|
|||
|
|
|||
|
DeltaGroupMember = (PNETLOGON_DELTA_GROUP_MEMBER)
|
|||
|
MIDL_user_allocate( sizeof(NETLOGON_DELTA_GROUP_MEMBER) );
|
|||
|
|
|||
|
if( DeltaGroupMember == NULL ) {
|
|||
|
|
|||
|
Status = STATUS_NO_MEMORY;
|
|||
|
goto Cleanup;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// wipe off the buffer so that cleanup will not be in fault.
|
|||
|
//
|
|||
|
|
|||
|
RtlZeroMemory( DeltaGroupMember,
|
|||
|
sizeof(NETLOGON_DELTA_GROUP_MEMBER) );
|
|||
|
|
|||
|
Delta->DeltaUnion.DeltaGroupMember = DeltaGroupMember;
|
|||
|
*BufferSize += sizeof(NETLOGON_DELTA_GROUP_MEMBER);
|
|||
|
|
|||
|
if ( MembersBuffer->MemberCount != 0 ) {
|
|||
|
Size = MembersBuffer->MemberCount * sizeof(*MembersBuffer->Members);
|
|||
|
|
|||
|
*BufferSize += NlCopyData(
|
|||
|
(LPBYTE *)&MembersBuffer->Members,
|
|||
|
(LPBYTE *)&DeltaGroupMember->MemberIds,
|
|||
|
Size );
|
|||
|
|
|||
|
Size = MembersBuffer->MemberCount *
|
|||
|
sizeof(*MembersBuffer->Attributes);
|
|||
|
|
|||
|
*BufferSize += NlCopyData(
|
|||
|
(LPBYTE *)&MembersBuffer->Attributes,
|
|||
|
(LPBYTE *)&DeltaGroupMember->Attributes,
|
|||
|
Size );
|
|||
|
}
|
|||
|
|
|||
|
DeltaGroupMember->MemberCount = MembersBuffer->MemberCount;
|
|||
|
|
|||
|
//
|
|||
|
// Initialize placeholder strings to NULL.
|
|||
|
//
|
|||
|
|
|||
|
DeltaGroupMember->DummyLong1 = 0;
|
|||
|
DeltaGroupMember->DummyLong2 = 0;
|
|||
|
DeltaGroupMember->DummyLong3 = 0;
|
|||
|
DeltaGroupMember->DummyLong4 = 0;
|
|||
|
|
|||
|
//
|
|||
|
// All Done
|
|||
|
//
|
|||
|
|
|||
|
Status = STATUS_SUCCESS;
|
|||
|
|
|||
|
Cleanup:
|
|||
|
STARTSAMTIMER;
|
|||
|
|
|||
|
if( GroupHandle != NULL ) {
|
|||
|
(VOID) SamrCloseHandle( &GroupHandle );
|
|||
|
}
|
|||
|
|
|||
|
if ( MembersBuffer != NULL ) {
|
|||
|
SamIFree_SAMPR_GET_MEMBERS_BUFFER( MembersBuffer );
|
|||
|
}
|
|||
|
|
|||
|
STOPSAMTIMER;
|
|||
|
|
|||
|
if( !NT_SUCCESS(Status) ) {
|
|||
|
NlFreeDBDelta( Delta );
|
|||
|
*BufferSize = 0;
|
|||
|
}
|
|||
|
|
|||
|
STOPPACKTIMER;
|
|||
|
|
|||
|
NlPrint((NL_REPL_OBJ_TIME,"Time taken to pack GROUPMEMBER object:\n"));
|
|||
|
PRINTPACKTIMER;
|
|||
|
PRINTSAMTIMER;
|
|||
|
|
|||
|
return Status;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
NlPackSamAlias (
|
|||
|
IN ULONG RelativeId,
|
|||
|
IN OUT PNETLOGON_DELTA_ENUM Delta,
|
|||
|
IN PDB_INFO DBInfo,
|
|||
|
LPDWORD BufferSize
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Pack a description of the specified alias into the specified buffer.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
RelativeId - The relative Id of the alias query.
|
|||
|
|
|||
|
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;
|
|||
|
SAMPR_HANDLE AliasHandle = NULL;
|
|||
|
PNETLOGON_DELTA_ALIAS DeltaAlias;
|
|||
|
|
|||
|
//
|
|||
|
// Information returned from SAM
|
|||
|
//
|
|||
|
|
|||
|
PSAMPR_SR_SECURITY_DESCRIPTOR SecurityDescriptor = NULL;
|
|||
|
|
|||
|
PSAMPR_ALIAS_INFO_BUFFER AliasGeneral = NULL;
|
|||
|
|
|||
|
DEFPACKTIMER;
|
|||
|
DEFSAMTIMER;
|
|||
|
|
|||
|
INITPACKTIMER;
|
|||
|
INITSAMTIMER;
|
|||
|
|
|||
|
STARTPACKTIMER;
|
|||
|
|
|||
|
NlPrint((NL_SYNC_MORE, "Packing Alias Object %lx\n", RelativeId));
|
|||
|
|
|||
|
*BufferSize = 0;
|
|||
|
|
|||
|
Delta->DeltaType = AddOrChangeAlias;
|
|||
|
Delta->DeltaID.Rid = RelativeId;
|
|||
|
Delta->DeltaUnion.DeltaAlias = NULL;
|
|||
|
|
|||
|
//
|
|||
|
// Open a handle to the specified alias.
|
|||
|
//
|
|||
|
|
|||
|
STARTSAMTIMER;
|
|||
|
|
|||
|
Status = SamIOpenAccount( DBInfo->DBHandle,
|
|||
|
RelativeId,
|
|||
|
SecurityDbObjectSamAlias,
|
|||
|
&AliasHandle );
|
|||
|
|
|||
|
STOPSAMTIMER;
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
AliasHandle = NULL;
|
|||
|
goto Cleanup;
|
|||
|
}
|
|||
|
|
|||
|
QUERY_SAM_SECOBJ_INFO(AliasHandle);
|
|||
|
|
|||
|
//
|
|||
|
// Determine the alias name.
|
|||
|
//
|
|||
|
|
|||
|
STARTSAMTIMER;
|
|||
|
|
|||
|
Status = SamrQueryInformationAlias(
|
|||
|
AliasHandle,
|
|||
|
AliasReplicationInformation,
|
|||
|
&AliasGeneral );
|
|||
|
|
|||
|
STOPSAMTIMER;
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
AliasGeneral = NULL;
|
|||
|
goto Cleanup;
|
|||
|
}
|
|||
|
|
|||
|
NlPrint((NL_SYNC_MORE, "\t Alias Object name %wZ\n",
|
|||
|
(PUNICODE_STRING)&(AliasGeneral->General.Name)));
|
|||
|
|
|||
|
DeltaAlias = (PNETLOGON_DELTA_ALIAS)
|
|||
|
MIDL_user_allocate( sizeof(NETLOGON_DELTA_ALIAS) );
|
|||
|
|
|||
|
if( DeltaAlias == NULL ) {
|
|||
|
|
|||
|
Status = STATUS_NO_MEMORY;
|
|||
|
goto Cleanup;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// wipe off the buffer so that cleanup will not be in fault.
|
|||
|
//
|
|||
|
|
|||
|
RtlZeroMemory( DeltaAlias, sizeof(NETLOGON_DELTA_ALIAS) );
|
|||
|
// INIT_PLACE_HOLDER(DeltaAlias);
|
|||
|
|
|||
|
Delta->DeltaUnion.DeltaAlias = DeltaAlias;
|
|||
|
*BufferSize += sizeof(NETLOGON_DELTA_ALIAS);
|
|||
|
|
|||
|
*BufferSize += NlCopyUnicodeString(
|
|||
|
(PUNICODE_STRING)&(AliasGeneral->General.Name),
|
|||
|
&DeltaAlias->Name );
|
|||
|
|
|||
|
DeltaAlias->RelativeId = RelativeId;
|
|||
|
|
|||
|
DELTA_SECOBJ_INFO(DeltaAlias);
|
|||
|
|
|||
|
//
|
|||
|
// copy comment string
|
|||
|
//
|
|||
|
|
|||
|
*BufferSize += NlCopyUnicodeString(
|
|||
|
(PUNICODE_STRING)&(AliasGeneral->General.AdminComment),
|
|||
|
&DeltaAlias->DummyString1 );
|
|||
|
|
|||
|
//
|
|||
|
// All Done
|
|||
|
//
|
|||
|
|
|||
|
Status = STATUS_SUCCESS;
|
|||
|
|
|||
|
Cleanup:
|
|||
|
STARTSAMTIMER;
|
|||
|
|
|||
|
if( AliasHandle != NULL ) {
|
|||
|
(VOID) SamrCloseHandle( &AliasHandle );
|
|||
|
}
|
|||
|
|
|||
|
if ( SecurityDescriptor != NULL ) {
|
|||
|
SamIFree_SAMPR_SR_SECURITY_DESCRIPTOR( SecurityDescriptor );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
if( AliasGeneral != NULL ) {
|
|||
|
|
|||
|
SamIFree_SAMPR_ALIAS_INFO_BUFFER (
|
|||
|
AliasGeneral,
|
|||
|
AliasReplicationInformation );
|
|||
|
}
|
|||
|
|
|||
|
STOPSAMTIMER;
|
|||
|
|
|||
|
if( !NT_SUCCESS(Status) ) {
|
|||
|
NlFreeDBDelta( Delta );
|
|||
|
*BufferSize = 0;
|
|||
|
}
|
|||
|
|
|||
|
STOPPACKTIMER;
|
|||
|
|
|||
|
NlPrint((NL_REPL_OBJ_TIME,"Time taken to pack ALIAS object:\n"));
|
|||
|
PRINTPACKTIMER;
|
|||
|
PRINTSAMTIMER;
|
|||
|
|
|||
|
return Status;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
NlPackSamAliasMember (
|
|||
|
IN ULONG RelativeId,
|
|||
|
IN OUT PNETLOGON_DELTA_ENUM Delta,
|
|||
|
IN PDB_INFO DBInfo,
|
|||
|
LPDWORD BufferSize
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Pack a description of the membership of the specified alias into
|
|||
|
the specified buffer.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
RelativeId - The relative Id of the alias query.
|
|||
|
|
|||
|
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;
|
|||
|
SAMPR_HANDLE AliasHandle = NULL;
|
|||
|
PNETLOGON_DELTA_ALIAS_MEMBER DeltaAliasMember;
|
|||
|
DWORD i;
|
|||
|
|
|||
|
//
|
|||
|
// Information returned from SAM
|
|||
|
//
|
|||
|
|
|||
|
NLPR_SID_ARRAY Members;
|
|||
|
PNLPR_SID_INFORMATION Sids;
|
|||
|
|
|||
|
DEFPACKTIMER;
|
|||
|
DEFSAMTIMER;
|
|||
|
|
|||
|
INITPACKTIMER;
|
|||
|
INITSAMTIMER;
|
|||
|
|
|||
|
STARTPACKTIMER;
|
|||
|
|
|||
|
NlPrint((NL_SYNC_MORE, "Packing AliasMember Object %lx\n", RelativeId));
|
|||
|
|
|||
|
*BufferSize = 0;
|
|||
|
|
|||
|
Delta->DeltaType = ChangeAliasMembership;
|
|||
|
Delta->DeltaID.Rid = RelativeId;
|
|||
|
Delta->DeltaUnion.DeltaAliasMember = NULL;
|
|||
|
|
|||
|
Members.Sids = NULL;
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Open a handle to the specified alias.
|
|||
|
//
|
|||
|
|
|||
|
STARTSAMTIMER;
|
|||
|
|
|||
|
Status = SamIOpenAccount( DBInfo->DBHandle,
|
|||
|
RelativeId,
|
|||
|
SecurityDbObjectSamAlias,
|
|||
|
&AliasHandle );
|
|||
|
|
|||
|
STOPSAMTIMER;
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
AliasHandle = NULL;
|
|||
|
goto Cleanup;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Find out everything there is to know about the alias.
|
|||
|
//
|
|||
|
|
|||
|
STARTSAMTIMER;
|
|||
|
|
|||
|
Status = SamrGetMembersInAlias( AliasHandle,
|
|||
|
(PSAMPR_PSID_ARRAY)&Members );
|
|||
|
|
|||
|
STOPSAMTIMER;
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
Members.Sids = NULL;
|
|||
|
goto Cleanup;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
DeltaAliasMember = (PNETLOGON_DELTA_ALIAS_MEMBER)
|
|||
|
MIDL_user_allocate( sizeof(NETLOGON_DELTA_ALIAS_MEMBER) );
|
|||
|
|
|||
|
if( DeltaAliasMember == NULL ) {
|
|||
|
|
|||
|
Status = STATUS_NO_MEMORY;
|
|||
|
goto Cleanup;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// wipe off the buffer so that cleanup will not be in fault.
|
|||
|
//
|
|||
|
|
|||
|
RtlZeroMemory( DeltaAliasMember,
|
|||
|
sizeof(NETLOGON_DELTA_ALIAS_MEMBER) );
|
|||
|
|
|||
|
Delta->DeltaUnion.DeltaAliasMember = DeltaAliasMember;
|
|||
|
*BufferSize += sizeof(NETLOGON_DELTA_ALIAS_MEMBER);
|
|||
|
|
|||
|
//
|
|||
|
// tie up sam return node to our return node
|
|||
|
//
|
|||
|
|
|||
|
DeltaAliasMember->Members = Members;
|
|||
|
|
|||
|
//
|
|||
|
// however, compute the MIDL buffer consumed for members node.
|
|||
|
//
|
|||
|
|
|||
|
for(i = 0, Sids = Members.Sids; i < Members.Count; ++i, Sids++) {
|
|||
|
|
|||
|
*BufferSize += (sizeof(PNLPR_SID_INFORMATION) +
|
|||
|
RtlLengthSid(Sids->SidPointer));
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
*BufferSize += sizeof(SAMPR_PSID_ARRAY);
|
|||
|
|
|||
|
//
|
|||
|
// Initialize placeholder strings to NULL.
|
|||
|
//
|
|||
|
|
|||
|
DeltaAliasMember->DummyLong1 = 0;
|
|||
|
DeltaAliasMember->DummyLong2 = 0;
|
|||
|
DeltaAliasMember->DummyLong3 = 0;
|
|||
|
DeltaAliasMember->DummyLong4 = 0;
|
|||
|
|
|||
|
//
|
|||
|
// All Done
|
|||
|
//
|
|||
|
|
|||
|
Status = STATUS_SUCCESS;
|
|||
|
|
|||
|
Cleanup:
|
|||
|
|
|||
|
STARTSAMTIMER;
|
|||
|
|
|||
|
if( AliasHandle != NULL ) {
|
|||
|
(VOID) SamrCloseHandle( &AliasHandle );
|
|||
|
}
|
|||
|
|
|||
|
if ( Members.Sids != NULL ) {
|
|||
|
|
|||
|
//
|
|||
|
// don't free this node because we have tied up this
|
|||
|
// node to our return info to RPC which will free it up
|
|||
|
// when it is done with it.
|
|||
|
//
|
|||
|
// however, free this node under error conditions
|
|||
|
//
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if( !NT_SUCCESS(Status) ) {
|
|||
|
|
|||
|
SamIFree_SAMPR_PSID_ARRAY( (PSAMPR_PSID_ARRAY)&Members );
|
|||
|
|
|||
|
if( Delta->DeltaUnion.DeltaAliasMember != NULL ) {
|
|||
|
Delta->DeltaUnion.DeltaAliasMember->Members.Sids = NULL;
|
|||
|
}
|
|||
|
|
|||
|
NlFreeDBDelta( Delta );
|
|||
|
*BufferSize = 0;
|
|||
|
}
|
|||
|
|
|||
|
STOPSAMTIMER;
|
|||
|
|
|||
|
STOPPACKTIMER;
|
|||
|
|
|||
|
NlPrint((NL_REPL_OBJ_TIME,"Timing for ALIASMEBER object packing:\n"));
|
|||
|
PRINTPACKTIMER;
|
|||
|
PRINTSAMTIMER;
|
|||
|
|
|||
|
return Status;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
NlPackSamDomain (
|
|||
|
IN OUT PNETLOGON_DELTA_ENUM Delta,
|
|||
|
IN PDB_INFO DBInfo,
|
|||
|
IN LPDWORD BufferSize
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Pack a description of the sam domain 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;
|
|||
|
|
|||
|
PNETLOGON_DELTA_DOMAIN DeltaDomain = NULL;
|
|||
|
|
|||
|
//
|
|||
|
// Information returned from SAM
|
|||
|
//
|
|||
|
|
|||
|
PSAMPR_SR_SECURITY_DESCRIPTOR SecurityDescriptor = NULL;
|
|||
|
PSAMPR_DOMAIN_INFO_BUFFER DomainGeneral = NULL;
|
|||
|
PSAMPR_DOMAIN_INFO_BUFFER DomainPassword = NULL;
|
|||
|
PSAMPR_DOMAIN_INFO_BUFFER DomainModified = NULL;
|
|||
|
PSAMPR_DOMAIN_INFO_BUFFER DomainLockout = NULL;
|
|||
|
|
|||
|
DEFPACKTIMER;
|
|||
|
DEFSAMTIMER;
|
|||
|
|
|||
|
INITPACKTIMER;
|
|||
|
INITSAMTIMER;
|
|||
|
|
|||
|
STARTPACKTIMER;
|
|||
|
|
|||
|
NlPrint((NL_SYNC_MORE, "Packing Domain Object\n"));
|
|||
|
|
|||
|
*BufferSize = 0;
|
|||
|
|
|||
|
Delta->DeltaType = AddOrChangeDomain;
|
|||
|
Delta->DeltaID.Rid = 0;
|
|||
|
Delta->DeltaUnion.DeltaDomain = NULL;
|
|||
|
|
|||
|
|
|||
|
QUERY_SAM_SECOBJ_INFO(DBInfo->DBHandle);
|
|||
|
|
|||
|
STARTSAMTIMER;
|
|||
|
|
|||
|
Status = SamrQueryInformationDomain(
|
|||
|
DBInfo->DBHandle,
|
|||
|
DomainGeneralInformation,
|
|||
|
&DomainGeneral );
|
|||
|
|
|||
|
STOPSAMTIMER;
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
DomainGeneral = NULL;
|
|||
|
goto Cleanup;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
STARTSAMTIMER;
|
|||
|
|
|||
|
Status = SamrQueryInformationDomain(
|
|||
|
DBInfo->DBHandle,
|
|||
|
DomainPasswordInformation,
|
|||
|
&DomainPassword );
|
|||
|
|
|||
|
STOPSAMTIMER;
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
DomainPassword = NULL;
|
|||
|
goto Cleanup;
|
|||
|
}
|
|||
|
|
|||
|
STARTSAMTIMER;
|
|||
|
|
|||
|
Status = SamrQueryInformationDomain(
|
|||
|
DBInfo->DBHandle,
|
|||
|
DomainModifiedInformation,
|
|||
|
&DomainModified );
|
|||
|
|
|||
|
STOPSAMTIMER;
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
DomainModified = NULL;
|
|||
|
goto Cleanup;
|
|||
|
}
|
|||
|
|
|||
|
STARTSAMTIMER;
|
|||
|
|
|||
|
Status = SamrQueryInformationDomain(
|
|||
|
DBInfo->DBHandle,
|
|||
|
DomainLockoutInformation,
|
|||
|
&DomainLockout );
|
|||
|
|
|||
|
STOPSAMTIMER;
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
DomainLockout = NULL;
|
|||
|
goto Cleanup;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Fill in the delta structure
|
|||
|
//
|
|||
|
|
|||
|
|
|||
|
DeltaDomain = (PNETLOGON_DELTA_DOMAIN)
|
|||
|
MIDL_user_allocate( sizeof(NETLOGON_DELTA_DOMAIN) );
|
|||
|
|
|||
|
if( DeltaDomain == NULL ) {
|
|||
|
|
|||
|
Status = STATUS_NO_MEMORY;
|
|||
|
goto Cleanup;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Zero the buffer so that cleanup will not access violate.
|
|||
|
//
|
|||
|
|
|||
|
RtlZeroMemory( DeltaDomain, sizeof(NETLOGON_DELTA_DOMAIN) );
|
|||
|
// INIT_PLACE_HOLDER(DeltaDomain);
|
|||
|
|
|||
|
Delta->DeltaUnion.DeltaDomain = DeltaDomain;
|
|||
|
*BufferSize += sizeof(NETLOGON_DELTA_DOMAIN);
|
|||
|
|
|||
|
*BufferSize += NlCopyUnicodeString(
|
|||
|
(PUNICODE_STRING)&DomainGeneral->General.DomainName,
|
|||
|
&DeltaDomain->DomainName );
|
|||
|
|
|||
|
*BufferSize = NlCopyUnicodeString(
|
|||
|
(PUNICODE_STRING)&DomainGeneral->General.OemInformation,
|
|||
|
&DeltaDomain->OemInformation );
|
|||
|
|
|||
|
DeltaDomain->ForceLogoff = DomainGeneral->General.ForceLogoff;
|
|||
|
DeltaDomain->MinPasswordLength =
|
|||
|
DomainPassword->Password.MinPasswordLength;
|
|||
|
DeltaDomain->PasswordHistoryLength =
|
|||
|
DomainPassword->Password.PasswordHistoryLength;
|
|||
|
|
|||
|
NEW_TO_OLD_LARGE_INTEGER(
|
|||
|
DomainPassword->Password.MaxPasswordAge,
|
|||
|
DeltaDomain->MaxPasswordAge );
|
|||
|
|
|||
|
NEW_TO_OLD_LARGE_INTEGER(
|
|||
|
DomainPassword->Password.MinPasswordAge,
|
|||
|
DeltaDomain->MinPasswordAge );
|
|||
|
|
|||
|
NEW_TO_OLD_LARGE_INTEGER(
|
|||
|
DomainModified->Modified.DomainModifiedCount,
|
|||
|
DeltaDomain->DomainModifiedCount );
|
|||
|
|
|||
|
NEW_TO_OLD_LARGE_INTEGER(
|
|||
|
DomainModified->Modified.CreationTime,
|
|||
|
DeltaDomain->DomainCreationTime );
|
|||
|
|
|||
|
|
|||
|
DELTA_SECOBJ_INFO(DeltaDomain);
|
|||
|
|
|||
|
//
|
|||
|
// replicate PasswordProperties using reserved field.
|
|||
|
//
|
|||
|
|
|||
|
DeltaDomain->DummyLong1 =
|
|||
|
DomainPassword->Password.PasswordProperties;
|
|||
|
|
|||
|
//
|
|||
|
// Replicate DOMAIN_LOCKOUT_INFORMATION using reserved field.
|
|||
|
//
|
|||
|
|
|||
|
DeltaDomain->DummyString1.Buffer = (LPWSTR) DomainLockout;
|
|||
|
DeltaDomain->DummyString1.MaximumLength =
|
|||
|
DeltaDomain->DummyString1.Length = sizeof( DomainLockout->Lockout);
|
|||
|
DomainLockout = NULL;
|
|||
|
|
|||
|
//
|
|||
|
// All Done
|
|||
|
//
|
|||
|
|
|||
|
Status = STATUS_SUCCESS;
|
|||
|
|
|||
|
Cleanup:
|
|||
|
|
|||
|
STARTSAMTIMER;
|
|||
|
|
|||
|
if ( SecurityDescriptor != NULL ) {
|
|||
|
SamIFree_SAMPR_SR_SECURITY_DESCRIPTOR( SecurityDescriptor );
|
|||
|
}
|
|||
|
|
|||
|
if ( DomainGeneral != NULL ) {
|
|||
|
SamIFree_SAMPR_DOMAIN_INFO_BUFFER( DomainGeneral,
|
|||
|
DomainGeneralInformation );
|
|||
|
}
|
|||
|
|
|||
|
if ( DomainPassword != NULL ) {
|
|||
|
SamIFree_SAMPR_DOMAIN_INFO_BUFFER( DomainPassword,
|
|||
|
DomainPasswordInformation );
|
|||
|
}
|
|||
|
|
|||
|
if ( DomainModified != NULL ) {
|
|||
|
SamIFree_SAMPR_DOMAIN_INFO_BUFFER( DomainModified,
|
|||
|
DomainModifiedInformation );
|
|||
|
}
|
|||
|
|
|||
|
if ( DomainLockout != NULL ) {
|
|||
|
SamIFree_SAMPR_DOMAIN_INFO_BUFFER( DomainLockout,
|
|||
|
DomainLockoutInformation );
|
|||
|
}
|
|||
|
|
|||
|
STOPSAMTIMER;
|
|||
|
|
|||
|
if( !NT_SUCCESS(Status) ) {
|
|||
|
NlFreeDBDelta( Delta );
|
|||
|
*BufferSize = 0;
|
|||
|
}
|
|||
|
|
|||
|
STOPPACKTIMER;
|
|||
|
|
|||
|
NlPrint((NL_REPL_OBJ_TIME,"Timing for DOMAIN object packing:\n"));
|
|||
|
PRINTPACKTIMER;
|
|||
|
PRINTSAMTIMER;
|
|||
|
|
|||
|
return Status;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
NlEncryptSensitiveData(
|
|||
|
IN OUT PCRYPT_BUFFER Data,
|
|||
|
IN PSESSION_INFO SessionInfo
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Encrypt data using the the server session key.
|
|||
|
|
|||
|
Either DES or RC4 will be used depending on the negotiated flags in SessionInfo.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Data: Pointer to the data to be decrypted. If the decrypted data is longer
|
|||
|
than the encrypt data, this routine will allocate a buffer for
|
|||
|
the returned data using MIDL_user_allocate and return a description to
|
|||
|
that buffer here. In that case, this routine will free the buffer
|
|||
|
containing the encrypted text data using MIDL_user_free.
|
|||
|
|
|||
|
SessionInfo: Info describing BDC that's calling us
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NT status code
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
NTSTATUS Status;
|
|||
|
DATA_KEY KeyData;
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// If both sides support RC4 encryption, use it.
|
|||
|
//
|
|||
|
|
|||
|
if ( SessionInfo->NegotiatedFlags & NETLOGON_SUPPORTS_RC4_ENCRYPTION ) {
|
|||
|
|
|||
|
NlEncryptRC4( Data->Buffer, Data->Length, SessionInfo );
|
|||
|
Status = STATUS_SUCCESS;
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// If the other side is running NT 3.1,
|
|||
|
// use the slower DES based encryption.
|
|||
|
//
|
|||
|
|
|||
|
} else {
|
|||
|
CYPHER_DATA TempData;
|
|||
|
|
|||
|
//
|
|||
|
// Build a data buffer to describe the encryption key.
|
|||
|
//
|
|||
|
|
|||
|
KeyData.Length = sizeof(NETLOGON_SESSION_KEY);
|
|||
|
KeyData.MaximumLength = sizeof(NETLOGON_SESSION_KEY);
|
|||
|
KeyData.Buffer = (PVOID)&SessionInfo->SessionKey;
|
|||
|
|
|||
|
//
|
|||
|
// Build a data buffer to describe the encrypted data.
|
|||
|
//
|
|||
|
|
|||
|
TempData.Length = 0;
|
|||
|
TempData.MaximumLength = 0;
|
|||
|
TempData.Buffer = NULL;
|
|||
|
|
|||
|
//
|
|||
|
// First time make the encrypt call to determine the length.
|
|||
|
//
|
|||
|
|
|||
|
Status = RtlEncryptData(
|
|||
|
(PCLEAR_DATA)Data,
|
|||
|
&KeyData,
|
|||
|
&TempData );
|
|||
|
|
|||
|
if( Status != STATUS_BUFFER_TOO_SMALL ) {
|
|||
|
return(Status);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// allocate output buffer.
|
|||
|
//
|
|||
|
|
|||
|
TempData.MaximumLength = TempData.Length;
|
|||
|
TempData.Buffer = MIDL_user_allocate( TempData.Length );
|
|||
|
|
|||
|
if( TempData.Buffer == NULL ) {
|
|||
|
return(STATUS_NO_MEMORY);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Encrypt the data.
|
|||
|
//
|
|||
|
|
|||
|
IF_NL_DEBUG( ENCRYPT ) {
|
|||
|
NlPrint((NL_ENCRYPT, "NlEncryptSensitiveData: Clear data: " ));
|
|||
|
NlpDumpBuffer( NL_ENCRYPT, Data->Buffer, Data->Length );
|
|||
|
}
|
|||
|
|
|||
|
Status = RtlEncryptData(
|
|||
|
(PCLEAR_DATA)Data,
|
|||
|
&KeyData,
|
|||
|
&TempData );
|
|||
|
|
|||
|
IF_NL_DEBUG( ENCRYPT ) {
|
|||
|
NlPrint((NL_ENCRYPT, "NlEncryptSensitiveData: Encrypted data: " ));
|
|||
|
NlpDumpBuffer( NL_ENCRYPT, TempData.Buffer, TempData.Length );
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Return either the clear text or encrypted buffer to the caller.
|
|||
|
//
|
|||
|
|
|||
|
if( NT_SUCCESS(Status) ) {
|
|||
|
MIDL_user_free( Data->Buffer );
|
|||
|
Data->Length = TempData.Length;
|
|||
|
Data->MaximumLength = TempData.MaximumLength;
|
|||
|
Data->Buffer = TempData.Buffer;
|
|||
|
} else {
|
|||
|
MIDL_user_free( TempData.Buffer );
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
return( Status );
|
|||
|
|
|||
|
}
|
|||
|
|