Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1604 lines
37 KiB

  1. /*++
  2. Copyright (c) 1987-1996 Microsoft Corporation
  3. Module Name:
  4. replutil.c
  5. Abstract:
  6. Low level functions for SSI Replication apis
  7. Author:
  8. Ported from Lan Man 2.0
  9. Environment:
  10. User mode only.
  11. Contains NT-specific code.
  12. Requires ANSI C extensions: slash-slash comments, long external names.
  13. Revision History:
  14. 22-Jul-1991 (cliffv)
  15. Ported to NT. Converted to NT style.
  16. 02-Jan-1992 (madana)
  17. added support for builtin/multidomain replication.
  18. 04-Apr-1992 (madana)
  19. Added support for LSA replication.
  20. --*/
  21. //
  22. // Common include files.
  23. //
  24. #include "logonsrv.h" // Include files common to entire service
  25. #pragma hdrstop
  26. //
  27. // Include files specific to this .c file
  28. //
  29. #include <accessp.h> // NetpConvertWorkstationList
  30. #include "lsarepl.h"
  31. DWORD
  32. NlCopyUnicodeString (
  33. IN PUNICODE_STRING InString,
  34. OUT PUNICODE_STRING OutString
  35. )
  36. /*++
  37. Routine Description:
  38. This routine copies the input string to the output. It assumes that
  39. the input string is allocated by MIDL_user_allocate() and sets the
  40. input string buffer pointer to NULL so that the buffer will be not
  41. freed on return.
  42. Arguments:
  43. InString - Points to the UNICODE string to copy.
  44. OutString - Points to the UNICODE string which will be updated to point
  45. to the input string.
  46. Return Value:
  47. Return the size of the MIDL buffer.
  48. --*/
  49. {
  50. if ( InString->Length == 0 || InString->Buffer == NULL ) {
  51. OutString->Length = 0;
  52. OutString->MaximumLength = 0;
  53. OutString->Buffer = NULL;
  54. } else {
  55. OutString->Length = InString->Length;
  56. OutString->MaximumLength = InString->Length;
  57. OutString->Buffer = InString->Buffer;
  58. InString->Buffer = NULL;
  59. }
  60. return( OutString->MaximumLength );
  61. }
  62. DWORD
  63. NlCopyData(
  64. IN LPBYTE *InData,
  65. OUT LPBYTE *OutData,
  66. DWORD DataLength
  67. )
  68. /*++
  69. Routine Description:
  70. This routine copies the input data pointer to output data pointer.
  71. It assumes that the input data buffer is allocated by the
  72. MIDL_user_allocate() and sets the input buffer buffer pointer to
  73. NULL on return so that the data buffer will not be freed by SamIFree
  74. rountine.
  75. Arguments:
  76. InData - Points to input data buffer pointer.
  77. OutString - Pointer to output data buffer pointer.
  78. DataLength - Length of input data.
  79. Return Value:
  80. Return the size of the data copied.
  81. --*/
  82. {
  83. *OutData = *InData;
  84. *InData = NULL;
  85. return(DataLength);
  86. }
  87. VOID
  88. NlFreeDBDelta(
  89. IN PNETLOGON_DELTA_ENUM Delta
  90. )
  91. /*++
  92. Routine Description:
  93. This routine will free the midl buffers that are allocated for
  94. a delta. This routine does nothing but call the midl generated free
  95. routine.
  96. Arguments:
  97. Delta: pointer to the delta structure which has to be freed.
  98. Return Value:
  99. nothing
  100. --*/
  101. {
  102. if( Delta != NULL ) {
  103. _fgs__NETLOGON_DELTA_ENUM (Delta);
  104. }
  105. }
  106. VOID
  107. NlFreeDBDeltaArray(
  108. IN PNETLOGON_DELTA_ENUM DeltaArray,
  109. IN DWORD ArraySize
  110. )
  111. /*++
  112. Routine Description:
  113. This routine will free up all delta entries in enum array and the
  114. array itself.
  115. Arguments:
  116. Delta: pointer to the delta structure array.
  117. ArraySize: num of delta structures in the array.
  118. Return Value:
  119. nothing
  120. --*/
  121. {
  122. DWORD i;
  123. if( DeltaArray != NULL ) {
  124. for( i = 0; i < ArraySize; i++) {
  125. NlFreeDBDelta( &DeltaArray[i] );
  126. }
  127. MIDL_user_free( DeltaArray );
  128. }
  129. }
  130. NTSTATUS
  131. NlPackSamUser (
  132. IN ULONG RelativeId,
  133. IN OUT PNETLOGON_DELTA_ENUM Delta,
  134. IN PDB_INFO DBInfo,
  135. IN LPDWORD BufferSize,
  136. IN PSESSION_INFO SessionInfo
  137. )
  138. /*++
  139. Routine Description:
  140. Pack a description of the specified user into the specified buffer.
  141. Arguments:
  142. RelativeId - The relative Id of the user query.
  143. Delta: pointer to the delta structure where the new delta will
  144. be returned.
  145. DBInfo: pointer to the database info structure.
  146. BufferSize: size of MIDL buffer that is consumed for this delta is
  147. returned here.
  148. SessionInfo: Info describing BDC that's calling us
  149. Return Value:
  150. NT status code.
  151. --*/
  152. {
  153. NTSTATUS Status;
  154. SAMPR_HANDLE UserHandle = NULL;
  155. PNETLOGON_DELTA_USER DeltaUser;
  156. PSAMPR_USER_INFO_BUFFER UserAll = NULL;
  157. DEFPACKTIMER;
  158. DEFSAMTIMER;
  159. INITPACKTIMER;
  160. INITSAMTIMER;
  161. STARTPACKTIMER;
  162. NlPrint((NL_SYNC_MORE, "Packing User Object %lx\n", RelativeId));
  163. *BufferSize = 0;
  164. Delta->DeltaType = AddOrChangeUser;
  165. Delta->DeltaID.Rid = RelativeId;
  166. Delta->DeltaUnion.DeltaUser = NULL;
  167. //
  168. // Open a handle to the specified user.
  169. //
  170. STARTSAMTIMER;
  171. Status = SamIOpenAccount( DBInfo->DBHandle,
  172. RelativeId,
  173. SecurityDbObjectSamUser,
  174. &UserHandle );
  175. STOPSAMTIMER;
  176. if (!NT_SUCCESS(Status)) {
  177. UserHandle = NULL;
  178. goto Cleanup;
  179. }
  180. //
  181. // Query everything there is to know about this user.
  182. //
  183. STARTSAMTIMER;
  184. Status = SamrQueryInformationUser(
  185. UserHandle,
  186. UserInternal3Information,
  187. &UserAll );
  188. STOPSAMTIMER;
  189. if (!NT_SUCCESS(Status)) {
  190. UserAll = NULL;
  191. goto Cleanup;
  192. }
  193. NlPrint((NL_SYNC_MORE,
  194. "\t User Object name %wZ\n",
  195. (PUNICODE_STRING)&UserAll->Internal3.I1.UserName));
  196. #define FIELDS_USED ( USER_ALL_USERNAME | \
  197. USER_ALL_FULLNAME | \
  198. USER_ALL_USERID | \
  199. USER_ALL_PRIMARYGROUPID | \
  200. USER_ALL_HOMEDIRECTORY | \
  201. USER_ALL_HOMEDIRECTORYDRIVE | \
  202. USER_ALL_SCRIPTPATH | \
  203. USER_ALL_PROFILEPATH | \
  204. USER_ALL_ADMINCOMMENT | \
  205. USER_ALL_WORKSTATIONS | \
  206. USER_ALL_LOGONHOURS | \
  207. USER_ALL_LASTLOGON | \
  208. USER_ALL_LASTLOGOFF | \
  209. USER_ALL_BADPASSWORDCOUNT | \
  210. USER_ALL_LOGONCOUNT | \
  211. USER_ALL_PASSWORDLASTSET | \
  212. USER_ALL_ACCOUNTEXPIRES | \
  213. USER_ALL_USERACCOUNTCONTROL | \
  214. USER_ALL_USERCOMMENT | \
  215. USER_ALL_COUNTRYCODE | \
  216. USER_ALL_CODEPAGE | \
  217. USER_ALL_PARAMETERS | \
  218. USER_ALL_NTPASSWORDPRESENT | \
  219. USER_ALL_LMPASSWORDPRESENT | \
  220. USER_ALL_PRIVATEDATA | \
  221. USER_ALL_SECURITYDESCRIPTOR )
  222. NlAssert( (UserAll->Internal3.I1.WhichFields & FIELDS_USED) == FIELDS_USED );
  223. //
  224. // Allocate a buffer to return to the caller.
  225. //
  226. DeltaUser = (PNETLOGON_DELTA_USER)
  227. MIDL_user_allocate( sizeof(NETLOGON_DELTA_USER) );
  228. if (DeltaUser == NULL) {
  229. Status = STATUS_NO_MEMORY;
  230. goto Cleanup;
  231. }
  232. //
  233. // wipe off the buffer so that cleanup will not be in fault.
  234. //
  235. RtlZeroMemory( DeltaUser, sizeof(NETLOGON_DELTA_USER) );
  236. // INIT_PLACE_HOLDER(DeltaUser);
  237. Delta->DeltaUnion.DeltaUser = DeltaUser;
  238. *BufferSize += sizeof(NETLOGON_DELTA_USER);
  239. *BufferSize += NlCopyUnicodeString(
  240. (PUNICODE_STRING)&UserAll->Internal3.I1.UserName,
  241. &DeltaUser->UserName );
  242. *BufferSize += NlCopyUnicodeString(
  243. (PUNICODE_STRING)&UserAll->Internal3.I1.FullName,
  244. &DeltaUser->FullName );
  245. DeltaUser->UserId = UserAll->Internal3.I1.UserId;
  246. DeltaUser->PrimaryGroupId = UserAll->Internal3.I1.PrimaryGroupId;
  247. *BufferSize += NlCopyUnicodeString(
  248. (PUNICODE_STRING)&UserAll->Internal3.I1.HomeDirectory,
  249. &DeltaUser->HomeDirectory );
  250. *BufferSize += NlCopyUnicodeString(
  251. (PUNICODE_STRING)&UserAll->Internal3.I1.HomeDirectoryDrive,
  252. &DeltaUser->HomeDirectoryDrive );
  253. *BufferSize += NlCopyUnicodeString(
  254. (PUNICODE_STRING)&UserAll->Internal3.I1.ScriptPath,
  255. &DeltaUser->ScriptPath );
  256. *BufferSize += NlCopyUnicodeString(
  257. (PUNICODE_STRING)&UserAll->Internal3.I1.AdminComment,
  258. &DeltaUser->AdminComment );
  259. *BufferSize += NlCopyUnicodeString(
  260. (PUNICODE_STRING)&UserAll->Internal3.I1.WorkStations,
  261. &DeltaUser->WorkStations );
  262. DeltaUser->LastLogon = UserAll->Internal3.I1.LastLogon;
  263. DeltaUser->LastLogoff = UserAll->Internal3.I1.LastLogoff;
  264. //
  265. // Copy Logon Hours
  266. //
  267. DeltaUser->LogonHours.UnitsPerWeek = UserAll->Internal3.I1.LogonHours.UnitsPerWeek;
  268. DeltaUser->LogonHours.LogonHours = UserAll->Internal3.I1.LogonHours.LogonHours;
  269. UserAll->Internal3.I1.LogonHours.LogonHours = NULL; // Don't let SAM free this.
  270. *BufferSize += (UserAll->Internal3.I1.LogonHours.UnitsPerWeek + 7) / 8;
  271. DeltaUser->BadPasswordCount = UserAll->Internal3.I1.BadPasswordCount;
  272. DeltaUser->LogonCount = UserAll->Internal3.I1.LogonCount;
  273. DeltaUser->PasswordLastSet = UserAll->Internal3.I1.PasswordLastSet;
  274. DeltaUser->AccountExpires = UserAll->Internal3.I1.AccountExpires;
  275. //
  276. // Don't copy lockout bit to BDC unless it understands it.
  277. //
  278. DeltaUser->UserAccountControl = UserAll->Internal3.I1.UserAccountControl;
  279. if ( (SessionInfo->NegotiatedFlags & NETLOGON_SUPPORTS_ACCOUNT_LOCKOUT) == 0 ){
  280. DeltaUser->UserAccountControl &= ~USER_ACCOUNT_AUTO_LOCKED;
  281. }
  282. *BufferSize += NlCopyUnicodeString(
  283. (PUNICODE_STRING)&UserAll->Internal3.I1.UserComment,
  284. &DeltaUser->UserComment );
  285. *BufferSize += NlCopyUnicodeString(
  286. (PUNICODE_STRING)&UserAll->Internal3.I1.Parameters,
  287. &DeltaUser->Parameters );
  288. DeltaUser->CountryCode = UserAll->Internal3.I1.CountryCode;
  289. DeltaUser->CodePage = UserAll->Internal3.I1.CodePage;
  290. //
  291. // Set private data.
  292. // Includes passwords and password history.
  293. //
  294. DeltaUser->PrivateData.SensitiveData = UserAll->Internal3.I1.PrivateDataSensitive;
  295. if ( UserAll->Internal3.I1.PrivateDataSensitive ) {
  296. CRYPT_BUFFER Data;
  297. //
  298. // encrypt private data using session key
  299. // Re-use the SAM's buffer and encrypt it in place.
  300. //
  301. Data.Length = Data.MaximumLength = UserAll->Internal3.I1.PrivateData.Length;
  302. Data.Buffer = (PUCHAR) UserAll->Internal3.I1.PrivateData.Buffer;
  303. UserAll->Internal3.I1.PrivateData.Buffer = NULL;
  304. Status = NlEncryptSensitiveData( &Data, SessionInfo );
  305. if( !NT_SUCCESS(Status) ) {
  306. goto Cleanup;
  307. }
  308. DeltaUser->PrivateData.DataLength = Data.Length;
  309. DeltaUser->PrivateData.Data = Data.Buffer;
  310. } else {
  311. DeltaUser->PrivateData.DataLength = UserAll->Internal3.I1.PrivateData.Length;
  312. DeltaUser->PrivateData.Data = (PUCHAR) UserAll->Internal3.I1.PrivateData.Buffer;
  313. UserAll->Internal3.I1.PrivateData.Buffer = NULL;
  314. }
  315. { // ?? Macro requires a Local named SecurityDescriptor
  316. PSAMPR_SR_SECURITY_DESCRIPTOR SecurityDescriptor;
  317. SecurityDescriptor = &UserAll->Internal3.I1.SecurityDescriptor;
  318. DELTA_SECOBJ_INFO(DeltaUser);
  319. }
  320. //
  321. // copy profile path in DummyStrings
  322. //
  323. *BufferSize += NlCopyUnicodeString(
  324. (PUNICODE_STRING)&UserAll->Internal3.I1.ProfilePath,
  325. &DeltaUser->DummyString1 );
  326. //
  327. // Copy LastBadPasswordTime to DummyLong1 and DummyLong2.
  328. //
  329. DeltaUser->DummyLong1 = UserAll->Internal3.LastBadPasswordTime.HighPart;
  330. DeltaUser->DummyLong2 = UserAll->Internal3.LastBadPasswordTime.LowPart;
  331. //
  332. // All Done
  333. //
  334. Status = STATUS_SUCCESS;
  335. Cleanup:
  336. STARTSAMTIMER;
  337. if( UserHandle != NULL ) {
  338. (VOID) SamrCloseHandle( &UserHandle );
  339. }
  340. if ( UserAll != NULL ) {
  341. SamIFree_SAMPR_USER_INFO_BUFFER( UserAll, UserInternal3Information );
  342. }
  343. STOPSAMTIMER;
  344. if( !NT_SUCCESS(Status) ) {
  345. NlFreeDBDelta( Delta );
  346. *BufferSize = 0;
  347. }
  348. STOPPACKTIMER;
  349. NlPrint((NL_REPL_OBJ_TIME,"Time taken to pack USER object:\n"));
  350. PRINTPACKTIMER;
  351. PRINTSAMTIMER;
  352. return Status;
  353. }
  354. NTSTATUS
  355. NlPackSamGroup (
  356. IN ULONG RelativeId,
  357. IN OUT PNETLOGON_DELTA_ENUM Delta,
  358. IN PDB_INFO DBInfo,
  359. LPDWORD BufferSize
  360. )
  361. /*++
  362. Routine Description:
  363. Pack a description of the specified group into the specified buffer.
  364. Arguments:
  365. RelativeId - The relative Id of the group query.
  366. Delta: pointer to the delta structure where the new delta will
  367. be returned.
  368. DBInfo: pointer to the database info structure.
  369. BufferSize: size of MIDL buffer that is consumed for this delta is
  370. returned here.
  371. Return Value:
  372. NT status code.
  373. --*/
  374. {
  375. NTSTATUS Status;
  376. SAMPR_HANDLE GroupHandle = NULL;
  377. PNETLOGON_DELTA_GROUP DeltaGroup;
  378. //
  379. // Information returned from SAM
  380. //
  381. PSAMPR_SR_SECURITY_DESCRIPTOR SecurityDescriptor = NULL;
  382. PSAMPR_GROUP_INFO_BUFFER GroupGeneral = NULL;
  383. DEFPACKTIMER;
  384. DEFSAMTIMER;
  385. INITPACKTIMER;
  386. INITSAMTIMER;
  387. STARTPACKTIMER;
  388. NlPrint((NL_SYNC_MORE, "Packing Group Object %lx\n", RelativeId ));
  389. *BufferSize = 0;
  390. Delta->DeltaType = AddOrChangeGroup;
  391. Delta->DeltaID.Rid = RelativeId;
  392. Delta->DeltaUnion.DeltaGroup = NULL;
  393. //
  394. // Open a handle to the specified group.
  395. //
  396. STARTSAMTIMER;
  397. Status = SamIOpenAccount( DBInfo->DBHandle,
  398. RelativeId,
  399. SecurityDbObjectSamGroup,
  400. &GroupHandle );
  401. if (!NT_SUCCESS(Status)) {
  402. GroupHandle = NULL;
  403. goto Cleanup;
  404. }
  405. STOPSAMTIMER;
  406. QUERY_SAM_SECOBJ_INFO(GroupHandle);
  407. STARTSAMTIMER;
  408. Status = SamrQueryInformationGroup(
  409. GroupHandle,
  410. GroupReplicationInformation,
  411. &GroupGeneral );
  412. STOPSAMTIMER;
  413. if (!NT_SUCCESS(Status)) {
  414. GroupGeneral = NULL;
  415. goto Cleanup;
  416. }
  417. NlPrint((NL_SYNC_MORE,
  418. "\t Group Object name %wZ\n",
  419. (PUNICODE_STRING)&GroupGeneral->General.Name ));
  420. DeltaGroup = (PNETLOGON_DELTA_GROUP)
  421. MIDL_user_allocate( sizeof(NETLOGON_DELTA_GROUP) );
  422. if( DeltaGroup == NULL ) {
  423. Status = STATUS_NO_MEMORY;
  424. goto Cleanup;
  425. }
  426. //
  427. // wipe off the buffer so that cleanup will not be in fault.
  428. //
  429. RtlZeroMemory( DeltaGroup, sizeof(NETLOGON_DELTA_GROUP) );
  430. // INIT_PLACE_HOLDER(DeltaGroup);
  431. Delta->DeltaUnion.DeltaGroup = DeltaGroup;
  432. *BufferSize += sizeof(NETLOGON_DELTA_GROUP);
  433. *BufferSize = NlCopyUnicodeString(
  434. (PUNICODE_STRING)&GroupGeneral->General.Name,
  435. &DeltaGroup->Name );
  436. DeltaGroup->RelativeId = RelativeId;
  437. DeltaGroup->Attributes = GroupGeneral->General.Attributes;
  438. *BufferSize += NlCopyUnicodeString(
  439. (PUNICODE_STRING)&GroupGeneral->General.AdminComment,
  440. &DeltaGroup->AdminComment );
  441. DELTA_SECOBJ_INFO(DeltaGroup);
  442. //
  443. // All Done
  444. //
  445. Status = STATUS_SUCCESS;
  446. Cleanup:
  447. STARTSAMTIMER;
  448. if( GroupHandle != NULL ) {
  449. (VOID) SamrCloseHandle( &GroupHandle );
  450. }
  451. if ( SecurityDescriptor != NULL ) {
  452. SamIFree_SAMPR_SR_SECURITY_DESCRIPTOR( SecurityDescriptor );
  453. }
  454. if ( GroupGeneral != NULL ) {
  455. SamIFree_SAMPR_GROUP_INFO_BUFFER( GroupGeneral,
  456. GroupReplicationInformation );
  457. }
  458. STOPSAMTIMER;
  459. if( !NT_SUCCESS(Status) ) {
  460. NlFreeDBDelta( Delta );
  461. *BufferSize = 0;
  462. }
  463. STOPPACKTIMER;
  464. NlPrint((NL_REPL_OBJ_TIME,"Time taken to pack GROUP object:\n"));
  465. PRINTPACKTIMER;
  466. PRINTSAMTIMER;
  467. return Status;
  468. }
  469. NTSTATUS
  470. NlPackSamGroupMember (
  471. IN ULONG RelativeId,
  472. IN OUT PNETLOGON_DELTA_ENUM Delta,
  473. IN PDB_INFO DBInfo,
  474. LPDWORD BufferSize
  475. )
  476. /*++
  477. Routine Description:
  478. Pack a description of the membership of the specified group into
  479. the specified buffer.
  480. Arguments:
  481. RelativeId - The relative Id of the group query.
  482. Delta: pointer to the delta structure where the new delta will
  483. be returned.
  484. DBInfo: pointer to the database info structure.
  485. BufferSize: size of MIDL buffer that is consumed for this delta is
  486. returned here.
  487. Return Value:
  488. NT status code.
  489. --*/
  490. {
  491. NTSTATUS Status;
  492. SAMPR_HANDLE GroupHandle = NULL;
  493. DWORD Size;
  494. PNETLOGON_DELTA_GROUP_MEMBER DeltaGroupMember;
  495. //
  496. // Information returned from SAM
  497. //
  498. PSAMPR_GET_MEMBERS_BUFFER MembersBuffer = NULL;
  499. DEFPACKTIMER;
  500. DEFSAMTIMER;
  501. INITPACKTIMER;
  502. INITSAMTIMER;
  503. STARTPACKTIMER;
  504. NlPrint((NL_SYNC_MORE, "Packing GroupMember Object %lx\n", RelativeId));
  505. *BufferSize = 0;
  506. Delta->DeltaType = ChangeGroupMembership;
  507. Delta->DeltaID.Rid = RelativeId;
  508. Delta->DeltaUnion.DeltaGroupMember = NULL;
  509. //
  510. // Open a handle to the specified group.
  511. //
  512. STARTSAMTIMER;
  513. Status = SamIOpenAccount( DBInfo->DBHandle,
  514. RelativeId,
  515. SecurityDbObjectSamGroup,
  516. &GroupHandle );
  517. STOPSAMTIMER;
  518. if (!NT_SUCCESS(Status)) {
  519. GroupHandle = NULL;
  520. goto Cleanup;
  521. }
  522. //
  523. // Find out everything there is to know about the group.
  524. //
  525. STARTSAMTIMER;
  526. Status = SamrGetMembersInGroup( GroupHandle, &MembersBuffer );
  527. STOPSAMTIMER;
  528. if (!NT_SUCCESS(Status)) {
  529. MembersBuffer = NULL;
  530. goto Cleanup;
  531. }
  532. DeltaGroupMember = (PNETLOGON_DELTA_GROUP_MEMBER)
  533. MIDL_user_allocate( sizeof(NETLOGON_DELTA_GROUP_MEMBER) );
  534. if( DeltaGroupMember == NULL ) {
  535. Status = STATUS_NO_MEMORY;
  536. goto Cleanup;
  537. }
  538. //
  539. // wipe off the buffer so that cleanup will not be in fault.
  540. //
  541. RtlZeroMemory( DeltaGroupMember,
  542. sizeof(NETLOGON_DELTA_GROUP_MEMBER) );
  543. Delta->DeltaUnion.DeltaGroupMember = DeltaGroupMember;
  544. *BufferSize += sizeof(NETLOGON_DELTA_GROUP_MEMBER);
  545. if ( MembersBuffer->MemberCount != 0 ) {
  546. Size = MembersBuffer->MemberCount * sizeof(*MembersBuffer->Members);
  547. *BufferSize += NlCopyData(
  548. (LPBYTE *)&MembersBuffer->Members,
  549. (LPBYTE *)&DeltaGroupMember->MemberIds,
  550. Size );
  551. Size = MembersBuffer->MemberCount *
  552. sizeof(*MembersBuffer->Attributes);
  553. *BufferSize += NlCopyData(
  554. (LPBYTE *)&MembersBuffer->Attributes,
  555. (LPBYTE *)&DeltaGroupMember->Attributes,
  556. Size );
  557. }
  558. DeltaGroupMember->MemberCount = MembersBuffer->MemberCount;
  559. //
  560. // Initialize placeholder strings to NULL.
  561. //
  562. DeltaGroupMember->DummyLong1 = 0;
  563. DeltaGroupMember->DummyLong2 = 0;
  564. DeltaGroupMember->DummyLong3 = 0;
  565. DeltaGroupMember->DummyLong4 = 0;
  566. //
  567. // All Done
  568. //
  569. Status = STATUS_SUCCESS;
  570. Cleanup:
  571. STARTSAMTIMER;
  572. if( GroupHandle != NULL ) {
  573. (VOID) SamrCloseHandle( &GroupHandle );
  574. }
  575. if ( MembersBuffer != NULL ) {
  576. SamIFree_SAMPR_GET_MEMBERS_BUFFER( MembersBuffer );
  577. }
  578. STOPSAMTIMER;
  579. if( !NT_SUCCESS(Status) ) {
  580. NlFreeDBDelta( Delta );
  581. *BufferSize = 0;
  582. }
  583. STOPPACKTIMER;
  584. NlPrint((NL_REPL_OBJ_TIME,"Time taken to pack GROUPMEMBER object:\n"));
  585. PRINTPACKTIMER;
  586. PRINTSAMTIMER;
  587. return Status;
  588. }
  589. NTSTATUS
  590. NlPackSamAlias (
  591. IN ULONG RelativeId,
  592. IN OUT PNETLOGON_DELTA_ENUM Delta,
  593. IN PDB_INFO DBInfo,
  594. LPDWORD BufferSize
  595. )
  596. /*++
  597. Routine Description:
  598. Pack a description of the specified alias into the specified buffer.
  599. Arguments:
  600. RelativeId - The relative Id of the alias query.
  601. Delta: pointer to the delta structure where the new delta will
  602. be returned.
  603. DBInfo: pointer to the database info structure.
  604. BufferSize: size of MIDL buffer that is consumed for this delta is
  605. returned here.
  606. Return Value:
  607. NT status code.
  608. --*/
  609. {
  610. NTSTATUS Status;
  611. SAMPR_HANDLE AliasHandle = NULL;
  612. PNETLOGON_DELTA_ALIAS DeltaAlias;
  613. //
  614. // Information returned from SAM
  615. //
  616. PSAMPR_SR_SECURITY_DESCRIPTOR SecurityDescriptor = NULL;
  617. PSAMPR_ALIAS_INFO_BUFFER AliasGeneral = NULL;
  618. DEFPACKTIMER;
  619. DEFSAMTIMER;
  620. INITPACKTIMER;
  621. INITSAMTIMER;
  622. STARTPACKTIMER;
  623. NlPrint((NL_SYNC_MORE, "Packing Alias Object %lx\n", RelativeId));
  624. *BufferSize = 0;
  625. Delta->DeltaType = AddOrChangeAlias;
  626. Delta->DeltaID.Rid = RelativeId;
  627. Delta->DeltaUnion.DeltaAlias = NULL;
  628. //
  629. // Open a handle to the specified alias.
  630. //
  631. STARTSAMTIMER;
  632. Status = SamIOpenAccount( DBInfo->DBHandle,
  633. RelativeId,
  634. SecurityDbObjectSamAlias,
  635. &AliasHandle );
  636. STOPSAMTIMER;
  637. if (!NT_SUCCESS(Status)) {
  638. AliasHandle = NULL;
  639. goto Cleanup;
  640. }
  641. QUERY_SAM_SECOBJ_INFO(AliasHandle);
  642. //
  643. // Determine the alias name.
  644. //
  645. STARTSAMTIMER;
  646. Status = SamrQueryInformationAlias(
  647. AliasHandle,
  648. AliasReplicationInformation,
  649. &AliasGeneral );
  650. STOPSAMTIMER;
  651. if (!NT_SUCCESS(Status)) {
  652. AliasGeneral = NULL;
  653. goto Cleanup;
  654. }
  655. NlPrint((NL_SYNC_MORE, "\t Alias Object name %wZ\n",
  656. (PUNICODE_STRING)&(AliasGeneral->General.Name)));
  657. DeltaAlias = (PNETLOGON_DELTA_ALIAS)
  658. MIDL_user_allocate( sizeof(NETLOGON_DELTA_ALIAS) );
  659. if( DeltaAlias == NULL ) {
  660. Status = STATUS_NO_MEMORY;
  661. goto Cleanup;
  662. }
  663. //
  664. // wipe off the buffer so that cleanup will not be in fault.
  665. //
  666. RtlZeroMemory( DeltaAlias, sizeof(NETLOGON_DELTA_ALIAS) );
  667. // INIT_PLACE_HOLDER(DeltaAlias);
  668. Delta->DeltaUnion.DeltaAlias = DeltaAlias;
  669. *BufferSize += sizeof(NETLOGON_DELTA_ALIAS);
  670. *BufferSize += NlCopyUnicodeString(
  671. (PUNICODE_STRING)&(AliasGeneral->General.Name),
  672. &DeltaAlias->Name );
  673. DeltaAlias->RelativeId = RelativeId;
  674. DELTA_SECOBJ_INFO(DeltaAlias);
  675. //
  676. // copy comment string
  677. //
  678. *BufferSize += NlCopyUnicodeString(
  679. (PUNICODE_STRING)&(AliasGeneral->General.AdminComment),
  680. &DeltaAlias->DummyString1 );
  681. //
  682. // All Done
  683. //
  684. Status = STATUS_SUCCESS;
  685. Cleanup:
  686. STARTSAMTIMER;
  687. if( AliasHandle != NULL ) {
  688. (VOID) SamrCloseHandle( &AliasHandle );
  689. }
  690. if ( SecurityDescriptor != NULL ) {
  691. SamIFree_SAMPR_SR_SECURITY_DESCRIPTOR( SecurityDescriptor );
  692. }
  693. if( AliasGeneral != NULL ) {
  694. SamIFree_SAMPR_ALIAS_INFO_BUFFER (
  695. AliasGeneral,
  696. AliasReplicationInformation );
  697. }
  698. STOPSAMTIMER;
  699. if( !NT_SUCCESS(Status) ) {
  700. NlFreeDBDelta( Delta );
  701. *BufferSize = 0;
  702. }
  703. STOPPACKTIMER;
  704. NlPrint((NL_REPL_OBJ_TIME,"Time taken to pack ALIAS object:\n"));
  705. PRINTPACKTIMER;
  706. PRINTSAMTIMER;
  707. return Status;
  708. }
  709. NTSTATUS
  710. NlPackSamAliasMember (
  711. IN ULONG RelativeId,
  712. IN OUT PNETLOGON_DELTA_ENUM Delta,
  713. IN PDB_INFO DBInfo,
  714. LPDWORD BufferSize
  715. )
  716. /*++
  717. Routine Description:
  718. Pack a description of the membership of the specified alias into
  719. the specified buffer.
  720. Arguments:
  721. RelativeId - The relative Id of the alias query.
  722. Delta: pointer to the delta structure where the new delta will
  723. be returned.
  724. DBInfo: pointer to the database info structure.
  725. BufferSize: size of MIDL buffer that is consumed for this delta is
  726. returned here.
  727. Return Value:
  728. NT status code.
  729. --*/
  730. {
  731. NTSTATUS Status;
  732. SAMPR_HANDLE AliasHandle = NULL;
  733. PNETLOGON_DELTA_ALIAS_MEMBER DeltaAliasMember;
  734. DWORD i;
  735. //
  736. // Information returned from SAM
  737. //
  738. NLPR_SID_ARRAY Members;
  739. PNLPR_SID_INFORMATION Sids;
  740. DEFPACKTIMER;
  741. DEFSAMTIMER;
  742. INITPACKTIMER;
  743. INITSAMTIMER;
  744. STARTPACKTIMER;
  745. NlPrint((NL_SYNC_MORE, "Packing AliasMember Object %lx\n", RelativeId));
  746. *BufferSize = 0;
  747. Delta->DeltaType = ChangeAliasMembership;
  748. Delta->DeltaID.Rid = RelativeId;
  749. Delta->DeltaUnion.DeltaAliasMember = NULL;
  750. Members.Sids = NULL;
  751. //
  752. // Open a handle to the specified alias.
  753. //
  754. STARTSAMTIMER;
  755. Status = SamIOpenAccount( DBInfo->DBHandle,
  756. RelativeId,
  757. SecurityDbObjectSamAlias,
  758. &AliasHandle );
  759. STOPSAMTIMER;
  760. if (!NT_SUCCESS(Status)) {
  761. AliasHandle = NULL;
  762. goto Cleanup;
  763. }
  764. //
  765. // Find out everything there is to know about the alias.
  766. //
  767. STARTSAMTIMER;
  768. Status = SamrGetMembersInAlias( AliasHandle,
  769. (PSAMPR_PSID_ARRAY_OUT)&Members );
  770. STOPSAMTIMER;
  771. if (!NT_SUCCESS(Status)) {
  772. Members.Sids = NULL;
  773. goto Cleanup;
  774. }
  775. DeltaAliasMember = (PNETLOGON_DELTA_ALIAS_MEMBER)
  776. MIDL_user_allocate( sizeof(NETLOGON_DELTA_ALIAS_MEMBER) );
  777. if( DeltaAliasMember == NULL ) {
  778. Status = STATUS_NO_MEMORY;
  779. goto Cleanup;
  780. }
  781. //
  782. // wipe off the buffer so that cleanup will not be in fault.
  783. //
  784. RtlZeroMemory( DeltaAliasMember,
  785. sizeof(NETLOGON_DELTA_ALIAS_MEMBER) );
  786. Delta->DeltaUnion.DeltaAliasMember = DeltaAliasMember;
  787. *BufferSize += sizeof(NETLOGON_DELTA_ALIAS_MEMBER);
  788. //
  789. // tie up sam return node to our return node
  790. //
  791. DeltaAliasMember->Members = Members;
  792. //
  793. // however, compute the MIDL buffer consumed for members node.
  794. //
  795. for(i = 0, Sids = Members.Sids; i < Members.Count; ++i, Sids++) {
  796. *BufferSize += (sizeof(PNLPR_SID_INFORMATION) +
  797. RtlLengthSid(Sids->SidPointer));
  798. }
  799. *BufferSize += sizeof(SAMPR_PSID_ARRAY);
  800. //
  801. // Initialize placeholder strings to NULL.
  802. //
  803. DeltaAliasMember->DummyLong1 = 0;
  804. DeltaAliasMember->DummyLong2 = 0;
  805. DeltaAliasMember->DummyLong3 = 0;
  806. DeltaAliasMember->DummyLong4 = 0;
  807. //
  808. // All Done
  809. //
  810. Status = STATUS_SUCCESS;
  811. Cleanup:
  812. STARTSAMTIMER;
  813. if( AliasHandle != NULL ) {
  814. (VOID) SamrCloseHandle( &AliasHandle );
  815. }
  816. if ( Members.Sids != NULL ) {
  817. //
  818. // don't free this node because we have tied up this
  819. // node to our return info to RPC which will free it up
  820. // when it is done with it.
  821. //
  822. // however, free this node under error conditions
  823. //
  824. }
  825. if( !NT_SUCCESS(Status) ) {
  826. SamIFree_SAMPR_PSID_ARRAY( (PSAMPR_PSID_ARRAY)&Members );
  827. if( Delta->DeltaUnion.DeltaAliasMember != NULL ) {
  828. Delta->DeltaUnion.DeltaAliasMember->Members.Sids = NULL;
  829. }
  830. NlFreeDBDelta( Delta );
  831. *BufferSize = 0;
  832. }
  833. STOPSAMTIMER;
  834. STOPPACKTIMER;
  835. NlPrint((NL_REPL_OBJ_TIME,"Timing for ALIASMEBER object packing:\n"));
  836. PRINTPACKTIMER;
  837. PRINTSAMTIMER;
  838. return Status;
  839. }
  840. NTSTATUS
  841. NlPackSamDomain (
  842. IN OUT PNETLOGON_DELTA_ENUM Delta,
  843. IN PDB_INFO DBInfo,
  844. IN LPDWORD BufferSize
  845. )
  846. /*++
  847. Routine Description:
  848. Pack a description of the sam domain into the specified buffer.
  849. Arguments:
  850. Delta: pointer to the delta structure where the new delta will
  851. be returned.
  852. DBInfo: pointer to the database info structure.
  853. BufferSize: size of MIDL buffer that is consumed for this delta is
  854. returned here.
  855. Return Value:
  856. NT status code.
  857. --*/
  858. {
  859. NTSTATUS Status;
  860. PNETLOGON_DELTA_DOMAIN DeltaDomain = NULL;
  861. //
  862. // Information returned from SAM
  863. //
  864. PSAMPR_SR_SECURITY_DESCRIPTOR SecurityDescriptor = NULL;
  865. PSAMPR_DOMAIN_INFO_BUFFER DomainGeneral = NULL;
  866. PSAMPR_DOMAIN_INFO_BUFFER DomainPassword = NULL;
  867. PSAMPR_DOMAIN_INFO_BUFFER DomainModified = NULL;
  868. PSAMPR_DOMAIN_INFO_BUFFER DomainLockout = NULL;
  869. DEFPACKTIMER;
  870. DEFSAMTIMER;
  871. INITPACKTIMER;
  872. INITSAMTIMER;
  873. STARTPACKTIMER;
  874. NlPrint((NL_SYNC_MORE, "Packing Domain Object\n"));
  875. *BufferSize = 0;
  876. Delta->DeltaType = AddOrChangeDomain;
  877. Delta->DeltaID.Rid = 0;
  878. Delta->DeltaUnion.DeltaDomain = NULL;
  879. QUERY_SAM_SECOBJ_INFO(DBInfo->DBHandle);
  880. STARTSAMTIMER;
  881. Status = SamrQueryInformationDomain(
  882. DBInfo->DBHandle,
  883. DomainGeneralInformation,
  884. &DomainGeneral );
  885. STOPSAMTIMER;
  886. if (!NT_SUCCESS(Status)) {
  887. DomainGeneral = NULL;
  888. goto Cleanup;
  889. }
  890. STARTSAMTIMER;
  891. Status = SamrQueryInformationDomain(
  892. DBInfo->DBHandle,
  893. DomainPasswordInformation,
  894. &DomainPassword );
  895. STOPSAMTIMER;
  896. if (!NT_SUCCESS(Status)) {
  897. DomainPassword = NULL;
  898. goto Cleanup;
  899. }
  900. STARTSAMTIMER;
  901. Status = SamrQueryInformationDomain(
  902. DBInfo->DBHandle,
  903. DomainModifiedInformation,
  904. &DomainModified );
  905. STOPSAMTIMER;
  906. if (!NT_SUCCESS(Status)) {
  907. DomainModified = NULL;
  908. goto Cleanup;
  909. }
  910. STARTSAMTIMER;
  911. Status = SamrQueryInformationDomain(
  912. DBInfo->DBHandle,
  913. DomainLockoutInformation,
  914. &DomainLockout );
  915. STOPSAMTIMER;
  916. if (!NT_SUCCESS(Status)) {
  917. DomainLockout = NULL;
  918. goto Cleanup;
  919. }
  920. //
  921. // Fill in the delta structure
  922. //
  923. DeltaDomain = (PNETLOGON_DELTA_DOMAIN)
  924. MIDL_user_allocate( sizeof(NETLOGON_DELTA_DOMAIN) );
  925. if( DeltaDomain == NULL ) {
  926. Status = STATUS_NO_MEMORY;
  927. goto Cleanup;
  928. }
  929. //
  930. // Zero the buffer so that cleanup will not access violate.
  931. //
  932. RtlZeroMemory( DeltaDomain, sizeof(NETLOGON_DELTA_DOMAIN) );
  933. // INIT_PLACE_HOLDER(DeltaDomain);
  934. Delta->DeltaUnion.DeltaDomain = DeltaDomain;
  935. *BufferSize += sizeof(NETLOGON_DELTA_DOMAIN);
  936. *BufferSize += NlCopyUnicodeString(
  937. (PUNICODE_STRING)&DomainGeneral->General.DomainName,
  938. &DeltaDomain->DomainName );
  939. *BufferSize = NlCopyUnicodeString(
  940. (PUNICODE_STRING)&DomainGeneral->General.OemInformation,
  941. &DeltaDomain->OemInformation );
  942. DeltaDomain->ForceLogoff = DomainGeneral->General.ForceLogoff;
  943. DeltaDomain->MinPasswordLength =
  944. DomainPassword->Password.MinPasswordLength;
  945. DeltaDomain->PasswordHistoryLength =
  946. DomainPassword->Password.PasswordHistoryLength;
  947. NEW_TO_OLD_LARGE_INTEGER(
  948. DomainPassword->Password.MaxPasswordAge,
  949. DeltaDomain->MaxPasswordAge );
  950. NEW_TO_OLD_LARGE_INTEGER(
  951. DomainPassword->Password.MinPasswordAge,
  952. DeltaDomain->MinPasswordAge );
  953. NEW_TO_OLD_LARGE_INTEGER(
  954. DomainModified->Modified.DomainModifiedCount,
  955. DeltaDomain->DomainModifiedCount );
  956. NEW_TO_OLD_LARGE_INTEGER(
  957. DomainModified->Modified.CreationTime,
  958. DeltaDomain->DomainCreationTime );
  959. DELTA_SECOBJ_INFO(DeltaDomain);
  960. //
  961. // replicate PasswordProperties using reserved field.
  962. //
  963. DeltaDomain->DummyLong1 =
  964. DomainPassword->Password.PasswordProperties;
  965. //
  966. // Replicate DOMAIN_LOCKOUT_INFORMATION using reserved field.
  967. //
  968. DeltaDomain->DummyString1.Buffer = (LPWSTR) DomainLockout;
  969. DeltaDomain->DummyString1.MaximumLength =
  970. DeltaDomain->DummyString1.Length = sizeof( DomainLockout->Lockout);
  971. DomainLockout = NULL;
  972. //
  973. // All Done
  974. //
  975. Status = STATUS_SUCCESS;
  976. Cleanup:
  977. STARTSAMTIMER;
  978. if ( SecurityDescriptor != NULL ) {
  979. SamIFree_SAMPR_SR_SECURITY_DESCRIPTOR( SecurityDescriptor );
  980. }
  981. if ( DomainGeneral != NULL ) {
  982. SamIFree_SAMPR_DOMAIN_INFO_BUFFER( DomainGeneral,
  983. DomainGeneralInformation );
  984. }
  985. if ( DomainPassword != NULL ) {
  986. SamIFree_SAMPR_DOMAIN_INFO_BUFFER( DomainPassword,
  987. DomainPasswordInformation );
  988. }
  989. if ( DomainModified != NULL ) {
  990. SamIFree_SAMPR_DOMAIN_INFO_BUFFER( DomainModified,
  991. DomainModifiedInformation );
  992. }
  993. if ( DomainLockout != NULL ) {
  994. SamIFree_SAMPR_DOMAIN_INFO_BUFFER( DomainLockout,
  995. DomainLockoutInformation );
  996. }
  997. STOPSAMTIMER;
  998. if( !NT_SUCCESS(Status) ) {
  999. NlFreeDBDelta( Delta );
  1000. *BufferSize = 0;
  1001. }
  1002. STOPPACKTIMER;
  1003. NlPrint((NL_REPL_OBJ_TIME,"Timing for DOMAIN object packing:\n"));
  1004. PRINTPACKTIMER;
  1005. PRINTSAMTIMER;
  1006. return Status;
  1007. }
  1008. NTSTATUS
  1009. NlEncryptSensitiveData(
  1010. IN OUT PCRYPT_BUFFER Data,
  1011. IN PSESSION_INFO SessionInfo
  1012. )
  1013. /*++
  1014. Routine Description:
  1015. Encrypt data using the the server session key.
  1016. Either DES or RC4 will be used depending on the negotiated flags in SessionInfo.
  1017. Arguments:
  1018. Data: Pointer to the data to be decrypted. If the decrypted data is longer
  1019. than the encrypt data, this routine will allocate a buffer for
  1020. the returned data using MIDL_user_allocate and return a description to
  1021. that buffer here. In that case, this routine will free the buffer
  1022. containing the encrypted text data using MIDL_user_free.
  1023. SessionInfo: Info describing BDC that's calling us
  1024. Return Value:
  1025. NT status code
  1026. --*/
  1027. {
  1028. NTSTATUS Status;
  1029. DATA_KEY KeyData;
  1030. //
  1031. // If both sides support RC4 encryption, use it.
  1032. //
  1033. if ( SessionInfo->NegotiatedFlags & NETLOGON_SUPPORTS_RC4_ENCRYPTION ) {
  1034. NlEncryptRC4( Data->Buffer, Data->Length, SessionInfo );
  1035. Status = STATUS_SUCCESS;
  1036. //
  1037. // If the other side is running NT 3.1,
  1038. // use the slower DES based encryption.
  1039. //
  1040. } else {
  1041. CYPHER_DATA TempData;
  1042. //
  1043. // Build a data buffer to describe the encryption key.
  1044. //
  1045. KeyData.Length = sizeof(NETLOGON_SESSION_KEY);
  1046. KeyData.MaximumLength = sizeof(NETLOGON_SESSION_KEY);
  1047. KeyData.Buffer = (PVOID)&SessionInfo->SessionKey;
  1048. //
  1049. // Build a data buffer to describe the encrypted data.
  1050. //
  1051. TempData.Length = 0;
  1052. TempData.MaximumLength = 0;
  1053. TempData.Buffer = NULL;
  1054. //
  1055. // First time make the encrypt call to determine the length.
  1056. //
  1057. Status = RtlEncryptData(
  1058. (PCLEAR_DATA)Data,
  1059. &KeyData,
  1060. &TempData );
  1061. if( Status != STATUS_BUFFER_TOO_SMALL ) {
  1062. return(Status);
  1063. }
  1064. //
  1065. // allocate output buffer.
  1066. //
  1067. TempData.MaximumLength = TempData.Length;
  1068. TempData.Buffer = MIDL_user_allocate( TempData.Length );
  1069. if( TempData.Buffer == NULL ) {
  1070. return(STATUS_NO_MEMORY);
  1071. }
  1072. //
  1073. // Encrypt the data.
  1074. //
  1075. IF_NL_DEBUG( ENCRYPT ) {
  1076. NlPrint((NL_ENCRYPT, "NlEncryptSensitiveData: Clear data: " ));
  1077. NlpDumpBuffer( NL_ENCRYPT, Data->Buffer, Data->Length );
  1078. }
  1079. Status = RtlEncryptData(
  1080. (PCLEAR_DATA)Data,
  1081. &KeyData,
  1082. &TempData );
  1083. IF_NL_DEBUG( ENCRYPT ) {
  1084. NlPrint((NL_ENCRYPT, "NlEncryptSensitiveData: Encrypted data: " ));
  1085. NlpDumpBuffer( NL_ENCRYPT, TempData.Buffer, TempData.Length );
  1086. }
  1087. //
  1088. // Return either the clear text or encrypted buffer to the caller.
  1089. //
  1090. if( NT_SUCCESS(Status) ) {
  1091. MIDL_user_free( Data->Buffer );
  1092. Data->Length = TempData.Length;
  1093. Data->MaximumLength = TempData.MaximumLength;
  1094. Data->Buffer = TempData.Buffer;
  1095. } else {
  1096. MIDL_user_free( TempData.Buffer );
  1097. }
  1098. }
  1099. return( Status );
  1100. }