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