Source code of Windows XP (NT5)
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.

1871 lines
45 KiB

  1. //+-----------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (c) Microsoft Corporation 1991 - 1996
  6. //
  7. // File: pac.cxx
  8. //
  9. // Contents: Implementation of routines to manipulate new PACs
  10. //
  11. // Description:
  12. //
  13. //
  14. // History: 23-Jan-96 MikeSw Created
  15. //
  16. //------------------------------------------------------------------------
  17. #include <secpch2.hxx>
  18. #pragma hdrstop
  19. #include <pac.hxx>
  20. #include <sectrace.hxx>
  21. #include <tostring.hxx>
  22. #include <ntlmsp.h>
  23. extern "C"
  24. {
  25. #include <align.h>
  26. #include <ntsam.h>
  27. #include <lmaccess.h>
  28. #include <midles.h>
  29. #include <pacndr.h>
  30. }
  31. //+-------------------------------------------------------------------------
  32. //
  33. // Function: Helper Functions for NDR encoding data types
  34. //
  35. // Synopsis:
  36. //
  37. // Effects:
  38. //
  39. // Arguments:
  40. //
  41. // Requires:
  42. //
  43. // Returns:
  44. //
  45. // Notes:
  46. //
  47. //
  48. //--------------------------------------------------------------------------
  49. typedef struct _PAC_BUFFER_STATE {
  50. PBYTE BufferPointer;
  51. ULONG BufferSize;
  52. } PAC_BUFFER_STATE, *PPAC_BUFFER_STATE;
  53. VOID NTAPI
  54. PacAllocFcn(
  55. IN OUT PVOID pvState,
  56. OUT PCHAR * ppbOut,
  57. IN PUINT32 pulSize
  58. )
  59. {
  60. PPAC_BUFFER_STATE state = (PPAC_BUFFER_STATE) pvState;
  61. //
  62. // MIDL pickling calls this routine with the size of the object
  63. // obtained by _GetSize(). This routine must return a buffer in
  64. // ppbOut with at least *pulSize bytes.
  65. //
  66. DsysAssert( state->BufferPointer != NULL );
  67. DsysAssert( state->BufferSize >= *pulSize );
  68. *ppbOut = (char*)state->BufferPointer;
  69. state->BufferPointer += *pulSize;
  70. state->BufferSize -= *pulSize;
  71. }
  72. VOID NTAPI
  73. PacWriteFcn(
  74. IN OUT PVOID pvState,
  75. OUT PCHAR pbOut,
  76. IN UINT32 ulSize
  77. )
  78. {
  79. //
  80. // Since the data was pickled directly to the target buffer, don't
  81. // do anything here.
  82. //
  83. }
  84. VOID NTAPI
  85. PacReadFcn(
  86. IN OUT PVOID pvState,
  87. OUT PCHAR * ppbOut,
  88. IN OUT PUINT32 pulSize
  89. )
  90. {
  91. PPAC_BUFFER_STATE state = (PPAC_BUFFER_STATE) pvState;
  92. //
  93. // MIDL pickling calls this routine with the size to read.
  94. // This routine must return a buffer in ppbOut which contains the
  95. // encoded data.
  96. //
  97. DsysAssert( state->BufferPointer != NULL );
  98. DsysAssert( state->BufferSize >= *pulSize );
  99. *ppbOut = (char*)state->BufferPointer;
  100. state->BufferPointer += *pulSize;
  101. state->BufferSize -= *pulSize;
  102. }
  103. //+-------------------------------------------------------------------------
  104. //
  105. // Function: PAC_EncodeValidationInformation
  106. //
  107. // Synopsis: NDR encodes the validation information
  108. //
  109. // Effects:
  110. //
  111. // Arguments:
  112. //
  113. // Requires:
  114. //
  115. // Returns:
  116. //
  117. // Notes:
  118. //
  119. //
  120. //--------------------------------------------------------------------------
  121. NTSTATUS
  122. PAC_EncodeValidationInformation(
  123. IN PNETLOGON_VALIDATION_SAM_INFO3 ValidationInfo,
  124. OUT PBYTE * EncodedData,
  125. OUT PULONG DataSize
  126. )
  127. {
  128. NTSTATUS Status = STATUS_SUCCESS;
  129. handle_t PickleHandle = 0;
  130. PAC_BUFFER_STATE BufferState = {0};
  131. ULONG EncodingStatus = 0;
  132. PUCHAR OutputBuffer = NULL;
  133. ULONG OutputSize = 0;
  134. EncodingStatus = MesEncodeIncrementalHandleCreate(
  135. &BufferState,
  136. PacAllocFcn,
  137. PacWriteFcn,
  138. &PickleHandle
  139. );
  140. if (EncodingStatus != 0)
  141. {
  142. Status = STATUS_INSUFFICIENT_RESOURCES;
  143. goto Cleanup;
  144. }
  145. //
  146. // Calculate the size of the required buffer
  147. //
  148. OutputSize = PPAC_IDL_VALIDATION_INFO_AlignSize(
  149. PickleHandle,
  150. &ValidationInfo
  151. );
  152. OutputBuffer = (PBYTE) MIDL_user_allocate(OutputSize);
  153. if (OutputBuffer == NULL)
  154. {
  155. Status = STATUS_INSUFFICIENT_RESOURCES;
  156. goto Cleanup;
  157. }
  158. BufferState.BufferSize = OutputSize;
  159. BufferState.BufferPointer = OutputBuffer;
  160. //
  161. // Now encode the structure
  162. //
  163. MesIncrementalHandleReset(
  164. PickleHandle,
  165. NULL,
  166. NULL,
  167. NULL,
  168. NULL,
  169. MES_ENCODE
  170. );
  171. PPAC_IDL_VALIDATION_INFO_Encode(
  172. PickleHandle,
  173. &ValidationInfo
  174. );
  175. *EncodedData = OutputBuffer;
  176. *DataSize = OutputSize;
  177. OutputBuffer = NULL;
  178. Cleanup:
  179. if (OutputBuffer != NULL)
  180. {
  181. MIDL_user_free(OutputBuffer);
  182. }
  183. if (PickleHandle != NULL)
  184. {
  185. MesHandleFree(PickleHandle);
  186. }
  187. return(Status);
  188. }
  189. //+-------------------------------------------------------------------------
  190. //
  191. // Function: PAC_DecodeValidationInformation
  192. //
  193. // Synopsis: NDR decodes the validation information
  194. //
  195. // Effects:
  196. //
  197. // Arguments:
  198. //
  199. // Requires:
  200. //
  201. // Returns:
  202. //
  203. // Notes:
  204. //
  205. //
  206. //--------------------------------------------------------------------------
  207. NTSTATUS
  208. PAC_DecodeValidationInformation(
  209. IN PBYTE EncodedData,
  210. IN ULONG DataSize,
  211. OUT PNETLOGON_VALIDATION_SAM_INFO3 * ValidationInfo
  212. )
  213. {
  214. NTSTATUS Status = STATUS_SUCCESS;
  215. handle_t PickleHandle = 0;
  216. PAC_BUFFER_STATE BufferState = {0};
  217. ULONG EncodingStatus = 0;
  218. DsysAssert(ROUND_UP_POINTER(EncodedData,8) == (PVOID) EncodedData);
  219. EncodingStatus = MesDecodeIncrementalHandleCreate(
  220. &BufferState,
  221. PacReadFcn,
  222. &PickleHandle
  223. );
  224. if (EncodingStatus != 0)
  225. {
  226. Status = STATUS_INSUFFICIENT_RESOURCES;
  227. goto Cleanup;
  228. }
  229. BufferState.BufferSize = DataSize;
  230. BufferState.BufferPointer = EncodedData;
  231. __try {
  232. PPAC_IDL_VALIDATION_INFO_Decode(
  233. PickleHandle,
  234. ValidationInfo
  235. );
  236. } __except (EXCEPTION_EXECUTE_HANDLER) {
  237. Status = STATUS_INVALID_PARAMETER;
  238. goto Cleanup;
  239. }
  240. Cleanup:
  241. if (PickleHandle != NULL)
  242. {
  243. MesHandleFree(PickleHandle);
  244. }
  245. return(Status);
  246. }
  247. //+-------------------------------------------------------------------------
  248. //
  249. // Function: PAC_EncodeCredentialData
  250. //
  251. // Synopsis: NDR encodes the credential data
  252. //
  253. // Effects:
  254. //
  255. // Arguments:
  256. //
  257. // Requires:
  258. //
  259. // Returns:
  260. //
  261. // Notes:
  262. //
  263. //
  264. //--------------------------------------------------------------------------
  265. NTSTATUS
  266. PAC_EncodeCredentialData(
  267. IN PSECPKG_SUPPLEMENTAL_CRED_ARRAY CredentialData,
  268. OUT PBYTE * EncodedData,
  269. OUT PULONG DataSize
  270. )
  271. {
  272. NTSTATUS Status = STATUS_SUCCESS;
  273. handle_t PickleHandle = 0;
  274. PAC_BUFFER_STATE BufferState = {0};
  275. ULONG EncodingStatus = 0;
  276. PUCHAR OutputBuffer = NULL;
  277. ULONG OutputSize = 0;
  278. EncodingStatus = MesEncodeIncrementalHandleCreate(
  279. &BufferState,
  280. PacAllocFcn,
  281. PacWriteFcn,
  282. &PickleHandle
  283. );
  284. if (EncodingStatus != 0)
  285. {
  286. Status = STATUS_INSUFFICIENT_RESOURCES;
  287. goto Cleanup;
  288. }
  289. //
  290. // Calculate the size of the required buffer
  291. //
  292. OutputSize = PPAC_IDL_CREDENTIAL_DATA_AlignSize(
  293. PickleHandle,
  294. &CredentialData
  295. );
  296. OutputBuffer = (PBYTE) MIDL_user_allocate(OutputSize);
  297. if (OutputBuffer == NULL)
  298. {
  299. Status = STATUS_INSUFFICIENT_RESOURCES;
  300. goto Cleanup;
  301. }
  302. BufferState.BufferSize = OutputSize;
  303. BufferState.BufferPointer = OutputBuffer;
  304. //
  305. // Now encode the structure
  306. //
  307. MesIncrementalHandleReset(
  308. PickleHandle,
  309. NULL,
  310. NULL,
  311. NULL,
  312. NULL,
  313. MES_ENCODE
  314. );
  315. PPAC_IDL_CREDENTIAL_DATA_Encode(
  316. PickleHandle,
  317. &CredentialData
  318. );
  319. *EncodedData = OutputBuffer;
  320. *DataSize = OutputSize;
  321. OutputBuffer = NULL;
  322. Cleanup:
  323. if (OutputBuffer != NULL)
  324. {
  325. MIDL_user_free(OutputBuffer);
  326. }
  327. if (PickleHandle != NULL)
  328. {
  329. MesHandleFree(PickleHandle);
  330. }
  331. return(Status);
  332. }
  333. //+-------------------------------------------------------------------------
  334. //
  335. // Function: PAC_DecodeCredentialData
  336. //
  337. // Synopsis: NDR decodes the validation information
  338. //
  339. // Effects:
  340. //
  341. // Arguments:
  342. //
  343. // Requires:
  344. //
  345. // Returns:
  346. //
  347. // Notes:
  348. //
  349. //
  350. //--------------------------------------------------------------------------
  351. NTSTATUS
  352. PAC_DecodeCredentialData(
  353. IN PBYTE EncodedData,
  354. IN ULONG DataSize,
  355. OUT PSECPKG_SUPPLEMENTAL_CRED_ARRAY * CredentialData
  356. )
  357. {
  358. NTSTATUS Status = STATUS_SUCCESS;
  359. handle_t PickleHandle = 0;
  360. PAC_BUFFER_STATE BufferState = {0};
  361. ULONG EncodingStatus = 0;
  362. DsysAssert(ROUND_UP_POINTER(EncodedData,8) == (PVOID) EncodedData);
  363. EncodingStatus = MesDecodeIncrementalHandleCreate(
  364. &BufferState,
  365. PacReadFcn,
  366. &PickleHandle
  367. );
  368. if (EncodingStatus != 0)
  369. {
  370. Status = STATUS_INSUFFICIENT_RESOURCES;
  371. goto Cleanup;
  372. }
  373. BufferState.BufferSize = DataSize;
  374. BufferState.BufferPointer = EncodedData;
  375. __try {
  376. PPAC_IDL_CREDENTIAL_DATA_Decode(
  377. PickleHandle,
  378. CredentialData
  379. );
  380. } __except (EXCEPTION_EXECUTE_HANDLER) {
  381. Status = STATUS_INVALID_PARAMETER;
  382. goto Cleanup;
  383. }
  384. Cleanup:
  385. if (PickleHandle != NULL)
  386. {
  387. MesHandleFree(PickleHandle);
  388. }
  389. return(Status);
  390. }
  391. //+-------------------------------------------------------------------------
  392. //
  393. // Function: PAC_EncodeTokenRestrictions
  394. //
  395. // Synopsis: NDR encodes the token restrictions
  396. //
  397. // Effects:
  398. //
  399. // Arguments:
  400. //
  401. // Requires:
  402. //
  403. // Returns:
  404. //
  405. // Notes:
  406. //
  407. //
  408. //--------------------------------------------------------------------------
  409. extern "C"
  410. NTSTATUS
  411. PAC_EncodeTokenRestrictions(
  412. IN PKERB_TOKEN_RESTRICTIONS TokenRestrictions,
  413. OUT PBYTE * EncodedData,
  414. OUT PULONG DataSize
  415. )
  416. {
  417. NTSTATUS Status = STATUS_SUCCESS;
  418. handle_t PickleHandle = 0;
  419. PAC_BUFFER_STATE BufferState = {0};
  420. ULONG EncodingStatus = 0;
  421. PUCHAR OutputBuffer = NULL;
  422. ULONG OutputSize = 0;
  423. EncodingStatus = MesEncodeIncrementalHandleCreate(
  424. &BufferState,
  425. PacAllocFcn,
  426. PacWriteFcn,
  427. &PickleHandle
  428. );
  429. if (EncodingStatus != 0)
  430. {
  431. Status = STATUS_INSUFFICIENT_RESOURCES;
  432. goto Cleanup;
  433. }
  434. //
  435. // Calculate the size of the required buffer
  436. //
  437. OutputSize = PKERB_TOKEN_RESTRICTIONS_AlignSize(
  438. PickleHandle,
  439. &TokenRestrictions
  440. );
  441. OutputBuffer = (PBYTE) MIDL_user_allocate(OutputSize);
  442. if (OutputBuffer == NULL)
  443. {
  444. Status = STATUS_INSUFFICIENT_RESOURCES;
  445. goto Cleanup;
  446. }
  447. BufferState.BufferSize = OutputSize;
  448. BufferState.BufferPointer = OutputBuffer;
  449. //
  450. // Now encode the structure
  451. //
  452. MesIncrementalHandleReset(
  453. PickleHandle,
  454. NULL,
  455. NULL,
  456. NULL,
  457. NULL,
  458. MES_ENCODE
  459. );
  460. PKERB_TOKEN_RESTRICTIONS_Encode(
  461. PickleHandle,
  462. &TokenRestrictions
  463. );
  464. *EncodedData = OutputBuffer;
  465. *DataSize = OutputSize;
  466. OutputBuffer = NULL;
  467. Cleanup:
  468. if (OutputBuffer != NULL)
  469. {
  470. MIDL_user_free(OutputBuffer);
  471. }
  472. if (PickleHandle != NULL)
  473. {
  474. MesHandleFree(PickleHandle);
  475. }
  476. return(Status);
  477. }
  478. //+-------------------------------------------------------------------------
  479. //
  480. // Function: PAC_DecodeTokenRestrictions
  481. //
  482. // Synopsis: NDR decodes the token restrictions
  483. //
  484. // Effects:
  485. //
  486. // Arguments:
  487. //
  488. // Requires:
  489. //
  490. // Returns:
  491. //
  492. // Notes:
  493. //
  494. //
  495. //--------------------------------------------------------------------------
  496. extern "C"
  497. NTSTATUS
  498. PAC_DecodeTokenRestrictions(
  499. IN PBYTE EncodedData,
  500. IN ULONG DataSize,
  501. OUT PKERB_TOKEN_RESTRICTIONS * TokenRestrictions
  502. )
  503. {
  504. NTSTATUS Status = STATUS_SUCCESS;
  505. handle_t PickleHandle = 0;
  506. PAC_BUFFER_STATE BufferState = {0};
  507. ULONG EncodingStatus = 0;
  508. DsysAssert(ROUND_UP_POINTER(EncodedData,8) == (PVOID) EncodedData);
  509. EncodingStatus = MesDecodeIncrementalHandleCreate(
  510. &BufferState,
  511. PacReadFcn,
  512. &PickleHandle
  513. );
  514. if (EncodingStatus != 0)
  515. {
  516. Status = STATUS_INSUFFICIENT_RESOURCES;
  517. goto Cleanup;
  518. }
  519. BufferState.BufferSize = DataSize;
  520. BufferState.BufferPointer = EncodedData;
  521. __try {
  522. PKERB_TOKEN_RESTRICTIONS_Decode(
  523. PickleHandle,
  524. TokenRestrictions
  525. );
  526. } __except (EXCEPTION_EXECUTE_HANDLER) {
  527. Status = STATUS_INVALID_PARAMETER;
  528. goto Cleanup;
  529. }
  530. Cleanup:
  531. if (PickleHandle != NULL)
  532. {
  533. MesHandleFree(PickleHandle);
  534. }
  535. return(Status);
  536. }
  537. //+---------------------------------------------------------------------------
  538. //
  539. // Function: PAC_GetSize
  540. //
  541. // Synopsis: Determines the number of bytes required to marshal the
  542. // given PAC.
  543. //
  544. // Arguments:
  545. //
  546. // History: 24-May-95 SuChang Created
  547. //
  548. // Notes:
  549. //
  550. //----------------------------------------------------------------------------
  551. ULONG
  552. PAC_GetSize( IN PACTYPE *pPac )
  553. {
  554. ULONG cbSize = 0;
  555. if (pPac != NULL)
  556. {
  557. cbSize += sizeof( PACTYPE );
  558. cbSize += (pPac->cBuffers - ANYSIZE_ARRAY) * sizeof(PAC_INFO_BUFFER);
  559. cbSize = ROUND_UP_COUNT( cbSize, ALIGN_QUAD );
  560. for (ULONG i = 0; i < pPac->cBuffers; i++ )
  561. {
  562. cbSize += ROUND_UP_COUNT(pPac->Buffers[i].cbBufferSize, ALIGN_QUAD);
  563. }
  564. }
  565. return (cbSize);
  566. }
  567. //+---------------------------------------------------------------------------
  568. //
  569. // Function: PAC_Marshal
  570. //
  571. // Synopsis: Marshals the given PAC into the provided buffer.
  572. //
  573. // Arguments:
  574. //
  575. // History: 24-May-95 SuChang Created
  576. //
  577. // Notes: This assumes the PAC is the same form as created
  578. // by PAC_Init. See header description of the PAC
  579. // structure.
  580. //
  581. // Returns the number of bytes used or 0 if an error
  582. // occurred.
  583. //
  584. //----------------------------------------------------------------------------
  585. ULONG
  586. PAC_Marshal( IN PACTYPE *pPac,
  587. IN ULONG cbBuffer,
  588. OUT PBYTE pBufferOut)
  589. {
  590. DsysAssert( pPac != NULL && pBufferOut != NULL );
  591. ULONG PacLen = PAC_GetSize( pPac );
  592. if (cbBuffer < PacLen)
  593. {
  594. return 0;
  595. }
  596. //
  597. // Copy into pBufferOut and then change the pointers of each
  598. // PAC_INFO_BUFFER to be offsets from pPac.
  599. //
  600. CopyMemory( pBufferOut, pPac, PacLen );
  601. PPACTYPE pPacTemp = (PPACTYPE) pBufferOut;
  602. for (ULONG i = 0; i < pPacTemp->cBuffers; i++ )
  603. {
  604. pPacTemp->Buffers[i].Offset = (ULONG) (pPacTemp->Buffers[i].Data -
  605. (PBYTE)pPac);
  606. }
  607. return PacLen;
  608. }
  609. //+---------------------------------------------------------------------------
  610. //
  611. // Function: PAC_UnMarshal
  612. //
  613. // Synopsis: Does in place unmarshalling of the marshalled PAC.
  614. //
  615. // Arguments:
  616. //
  617. // History: 24-May-95 SuChang Created
  618. //
  619. // Notes: Does in place unmarshalling. No new memory is allocated.
  620. //
  621. // This assumes the PAC is the same form as created
  622. // by PAC_Init. See header description of the PAC
  623. // structure.
  624. //
  625. //----------------------------------------------------------------------------
  626. ULONG
  627. PAC_UnMarshal( IN PPACTYPE pPac,
  628. IN ULONG cbSize )
  629. {
  630. ULONG i;
  631. ULONG cbUnmarshalled = 0;
  632. PBYTE pEnd = (PBYTE)pPac + cbSize;
  633. PBYTE pBufferAddress;
  634. DsysAssert( pPac != NULL );
  635. //
  636. // Do a validation loop. Make sure that the offsets are
  637. // correct. We don't want to do this validation inside the modification
  638. // loop because it wouldn't be nice to change the buffer if it weren't
  639. // valid.
  640. //
  641. if ((pPac->cBuffers * sizeof(PAC_INFO_BUFFER) + sizeof(PACTYPE)) > cbSize)
  642. {
  643. return(0);
  644. }
  645. if (pPac->Version != PAC_VERSION)
  646. {
  647. return(0);
  648. }
  649. for (i = 0; i < pPac->cBuffers; i++)
  650. {
  651. pBufferAddress = (ULONG)pPac->Buffers[i].Offset + (PBYTE)pPac;
  652. if ( (pBufferAddress >= pEnd ) || (pBufferAddress < (PBYTE) pPac) ||
  653. (pBufferAddress + pPac->Buffers[i].cbBufferSize > pEnd))
  654. {
  655. //
  656. // Invalid offset or length
  657. //
  658. return (0);
  659. }
  660. }
  661. for (i = 0; i < pPac->cBuffers; i++ )
  662. {
  663. cbUnmarshalled += pPac->Buffers[i].cbBufferSize;
  664. pPac->Buffers[i].Data = pPac->Buffers[i].Offset +
  665. (PBYTE)pPac;
  666. }
  667. return (cbUnmarshalled);
  668. }
  669. //+---------------------------------------------------------------------------
  670. //
  671. // Function: PAC_ReMarshal
  672. //
  673. // Synopsis: Does in place re-marshalling of an un-marshalled PAC.
  674. //
  675. // Arguments:
  676. //
  677. // History: 24-May-95 SuChang Created
  678. //
  679. // Notes: Does in place re-marshalling. No new memory is allocated.
  680. //
  681. // This assumes the PAC is the same form as created
  682. // by PAC_UnMarshal. See header description of the PAC
  683. // structure.
  684. //
  685. //----------------------------------------------------------------------------
  686. BOOLEAN
  687. PAC_ReMarshal( IN PPACTYPE pPac,
  688. IN ULONG cbSize )
  689. {
  690. ULONG Offset;
  691. ULONG i;
  692. //
  693. // Do a validation loop. Make sure that the offsets are
  694. // correct. We don't want to do this validation inside the modification
  695. // loop because it wouldn't be nice to change the buffer if it weren't
  696. // valid.
  697. //
  698. for (i = 0; i < pPac->cBuffers; i++ )
  699. {
  700. Offset = (ULONG) (pPac->Buffers[i].Data - (PBYTE) pPac);
  701. if ( Offset >= cbSize )
  702. {
  703. //
  704. // Invalid offset or length
  705. //
  706. return (FALSE);
  707. }
  708. pPac->Buffers[i].Offset = Offset;
  709. }
  710. return (TRUE);
  711. }
  712. VOID
  713. PAC_PutString(
  714. IN PVOID Base,
  715. IN PUNICODE_STRING OutString,
  716. IN PUNICODE_STRING InString,
  717. IN PUCHAR *Where
  718. )
  719. /*++
  720. Routine Description:
  721. This routine copies the InString string to the memory pointed to by
  722. the Where parameter, and fixes the OutString string to point to that
  723. new copy.
  724. Parameters:
  725. OutString - A pointer to a destination NT string
  726. InString - A pointer to an NT string to be copied
  727. Where - A pointer to space to put the actual string for the
  728. OutString. The pointer is adjusted to point to the first byte
  729. following the copied string.
  730. Return Values:
  731. None.
  732. --*/
  733. {
  734. DsysAssert( OutString != NULL );
  735. DsysAssert( InString != NULL );
  736. DsysAssert( Where != NULL && *Where != NULL);
  737. DsysAssert( *Where == ROUND_UP_POINTER( *Where, sizeof(WCHAR) ) );
  738. if ( InString->Length > 0 ) {
  739. OutString->Buffer = (PWCH) *Where;
  740. OutString->MaximumLength = (USHORT)(InString->Length + sizeof(WCHAR));
  741. RtlCopyUnicodeString( OutString, InString );
  742. //
  743. // Rest the pointer to be an offset.
  744. //
  745. OutString->Buffer = (PWCH) (*Where - (PUCHAR) Base);
  746. *Where += InString->Length;
  747. // *((WCHAR *)(*Where)) = L'\0';
  748. *(*Where) = '\0';
  749. *(*Where + 1) = '\0';
  750. *Where += 2;
  751. } else {
  752. RtlInitUnicodeString(OutString, NULL);
  753. }
  754. return;
  755. }
  756. //+-------------------------------------------------------------------------
  757. //
  758. // Function: PAC_MarshallValidationInfo
  759. //
  760. // Synopsis: marshals a NETLOGON_VALIDATION_SAM_INFO2
  761. //
  762. // Effects: allocates memory with MIDL_user_allocate
  763. //
  764. // Arguments:
  765. //
  766. // Requires:
  767. //
  768. // Returns:
  769. //
  770. // Notes:
  771. //
  772. //
  773. //--------------------------------------------------------------------------
  774. NTSTATUS
  775. PAC_MarshallValidationInfo
  776. (
  777. IN PSAMPR_USER_ALL_INFORMATION UserAll,
  778. IN PSAMPR_GET_GROUPS_BUFFER GroupsBuffer,
  779. IN PSID_AND_ATTRIBUTES_LIST ExtraGroups,
  780. IN PSID LogonDomainId,
  781. IN PUNICODE_STRING LogonDomainName,
  782. IN PUNICODE_STRING LogonServer,
  783. IN BOOLEAN IncludeUserParms,
  784. IN BOOLEAN NetworkProfile,
  785. OUT PBYTE * ValidationInfo,
  786. OUT PULONG ValidationInfoSize
  787. )
  788. {
  789. NETLOGON_VALIDATION_SAM_INFO3 ValidationSam = {0};
  790. PNETLOGON_SID_AND_ATTRIBUTES MarshalledSids = NULL;
  791. SID ServerSid = {SID_REVISION, 1, SECURITY_NT_AUTHORITY, SECURITY_SERVER_LOGON_RID };
  792. NTSTATUS Status = STATUS_SUCCESS;
  793. BYTE SidBuffer[sizeof(SID) + SID_MAX_SUB_AUTHORITIES * sizeof(ULONG)];
  794. PSID BuiltinSid = SidBuffer;
  795. PUCHAR Where;
  796. ULONG ExtraGroupSize = 0;
  797. ULONG ExtraGroupCount = 0;
  798. ULONG Index;
  799. //
  800. // Allocate a return buffer for validation information.
  801. // (Return less information for a network logon)
  802. // (Return UserParameters for a MNS logon)
  803. //
  804. //
  805. // First calculate the space needed for the extra groups.
  806. //
  807. if (ARGUMENT_PRESENT(ExtraGroups))
  808. {
  809. ExtraGroupCount += ExtraGroups->Count;
  810. }
  811. //
  812. // Add the enterprise server's sids
  813. //
  814. if ((UserAll->UserAccountControl & USER_SERVER_TRUST_ACCOUNT) != 0)
  815. {
  816. ExtraGroupCount += 1;
  817. }
  818. //
  819. // Set the UF_SMARTCARD_REQUIRED flag
  820. //
  821. if ((UserAll->UserAccountControl & USER_SMARTCARD_REQUIRED) != 0)
  822. {
  823. ValidationSam.UserFlags |= UF_SMARTCARD_REQUIRED;
  824. }
  825. //
  826. // Copy the scalars to the validation buffer.
  827. //
  828. ValidationSam.LogonTime = UserAll->LastLogon;
  829. //
  830. // BUG 455821: need logoff time & kickoff time
  831. //
  832. #ifdef notdef
  833. NEW_TO_OLD_LARGE_INTEGER( LogoffTime, ValidationSam.LogoffTime );
  834. NEW_TO_OLD_LARGE_INTEGER( KickoffTime, ValidationSam.KickOffTime );
  835. #else
  836. ValidationSam.LogoffTime.LowPart = 0xffffffff;
  837. ValidationSam.LogoffTime.HighPart = 0x7fffffff;
  838. ValidationSam.KickOffTime.LowPart = 0xffffffff;
  839. ValidationSam.KickOffTime.HighPart = 0x7fffffff;
  840. #endif
  841. ValidationSam.PasswordLastSet = UserAll->PasswordLastSet;
  842. ValidationSam.PasswordCanChange = UserAll->PasswordCanChange;
  843. ValidationSam.PasswordMustChange = UserAll->PasswordMustChange;
  844. ValidationSam.LogonCount = UserAll->LogonCount;
  845. ValidationSam.BadPasswordCount = UserAll->BadPasswordCount;
  846. ValidationSam.UserId = UserAll->UserId;
  847. ValidationSam.PrimaryGroupId = UserAll->PrimaryGroupId;
  848. if (ARGUMENT_PRESENT( GroupsBuffer) )
  849. {
  850. ValidationSam.GroupCount = GroupsBuffer->MembershipCount;
  851. ValidationSam.GroupIds = GroupsBuffer->Groups;
  852. }
  853. else
  854. {
  855. ValidationSam.GroupCount = 0;
  856. ValidationSam.GroupIds = NULL;
  857. }
  858. ValidationSam.ExpansionRoom[SAMINFO_USER_ACCOUNT_CONTROL] = UserAll->UserAccountControl;
  859. //
  860. // If the client asked for extra information, return that
  861. // we support it
  862. //
  863. ValidationSam.UserFlags |= LOGON_EXTRA_SIDS;
  864. //
  865. // Copy ULONG aligned data to the validation buffer.
  866. //
  867. if (ExtraGroupCount != 0)
  868. {
  869. ValidationSam.SidCount = ExtraGroupCount;
  870. MarshalledSids = (PNETLOGON_SID_AND_ATTRIBUTES) MIDL_user_allocate(ExtraGroupCount * sizeof(NETLOGON_SID_AND_ATTRIBUTES));
  871. if (MarshalledSids == NULL)
  872. {
  873. Status = STATUS_INSUFFICIENT_RESOURCES;
  874. goto Cleanup;
  875. }
  876. ValidationSam.ExtraSids = MarshalledSids;
  877. Index = 0;
  878. if (ARGUMENT_PRESENT(ExtraGroups))
  879. {
  880. //
  881. // Now marshall each sid into the buffer
  882. //
  883. DsysAssert(sizeof(SID_AND_ATTRIBUTES) == sizeof(NETLOGON_SID_AND_ATTRIBUTES));
  884. RtlCopyMemory(
  885. &MarshalledSids[Index],
  886. ExtraGroups->SidAndAttributes,
  887. ExtraGroups->Count * sizeof(SID_AND_ATTRIBUTES)
  888. );
  889. Index += ExtraGroups->Count;
  890. }
  891. //
  892. // Add in special sids for domain controllers
  893. //
  894. if ((UserAll->UserAccountControl & USER_SERVER_TRUST_ACCOUNT) != 0)
  895. {
  896. //
  897. // Add in the constant server logon sid
  898. //
  899. MarshalledSids[Index].Attributes = SE_GROUP_MANDATORY |
  900. SE_GROUP_ENABLED |
  901. SE_GROUP_ENABLED_BY_DEFAULT;
  902. MarshalledSids[Index].Sid = &ServerSid;
  903. Index++;
  904. }
  905. }
  906. ValidationSam.LogonDomainId = LogonDomainId;
  907. //
  908. // Copy WCHAR aligned data to the validation buffer.
  909. // (Return less information for a network logon)
  910. //
  911. if ( ! NetworkProfile ) {
  912. ValidationSam.EffectiveName = *(PUNICODE_STRING)&UserAll->UserName;
  913. ValidationSam.FullName = *(PUNICODE_STRING)&UserAll->FullName;
  914. ValidationSam.LogonScript = *(PUNICODE_STRING)&UserAll->ScriptPath;
  915. ValidationSam.ProfilePath = *(PUNICODE_STRING)&UserAll->ProfilePath;
  916. ValidationSam.HomeDirectory = *(PUNICODE_STRING)&UserAll->HomeDirectory;
  917. ValidationSam.HomeDirectoryDrive = *(PUNICODE_STRING)&UserAll->HomeDirectoryDrive;
  918. }
  919. ValidationSam.LogonServer = *LogonServer;
  920. ValidationSam.LogonDomainName = *LogonDomainName;
  921. //
  922. // Kludge: Pass back UserParameters in HomeDirectoryDrive since we
  923. // can't change the NETLOGON_VALIDATION_SAM_INFO2 structure between
  924. // releases NT 1.0 and NT 1.0A. HomeDirectoryDrive was NULL for release 1.0A
  925. // so we'll use that field.
  926. //
  927. if ( IncludeUserParms && NetworkProfile ) {
  928. ValidationSam.HomeDirectoryDrive = *(PUNICODE_STRING)&UserAll->Parameters;
  929. }
  930. Status = PAC_EncodeValidationInformation(
  931. &ValidationSam,
  932. ValidationInfo,
  933. ValidationInfoSize
  934. );
  935. Cleanup:
  936. if (MarshalledSids != NULL)
  937. {
  938. MIDL_user_free(MarshalledSids);
  939. }
  940. return(Status);
  941. }
  942. //+-------------------------------------------------------------------------
  943. //
  944. // Function: PAC_MarshallValidationInfoWithGroups
  945. //
  946. // Synopsis: marshals a NETLOGON_VALIDATION_SAM_INFO2
  947. //
  948. // Effects: allocates memory with MIDL_user_allocate
  949. //
  950. // Arguments:
  951. //
  952. // Requires:
  953. //
  954. // Returns:
  955. //
  956. // Notes:
  957. //
  958. //
  959. //--------------------------------------------------------------------------
  960. NTSTATUS
  961. PAC_ReMarshallValidationInfoWithGroups(
  962. IN PNETLOGON_VALIDATION_SAM_INFO3 OldValidationInfo,
  963. IN PSAMPR_PSID_ARRAY ResourceGroups,
  964. OUT PBYTE * ValidationInfo,
  965. OUT PULONG ValidationInfoSize
  966. )
  967. {
  968. NETLOGON_VALIDATION_SAM_INFO3 ValidationSam = {0};
  969. PNETLOGON_SID_AND_ATTRIBUTES ExtraSids = NULL;
  970. ULONG ExtraSidCount = 0;
  971. NTSTATUS Status = STATUS_SUCCESS;
  972. ULONG Index, Index2;
  973. //
  974. // Copy the original validation information
  975. //
  976. ValidationSam = *OldValidationInfo;
  977. ValidationSam.UserFlags &= ~LOGON_RESOURCE_GROUPS;
  978. //
  979. // Clear any old resource groups
  980. //
  981. ValidationSam.ResourceGroupDomainSid = NULL;
  982. ValidationSam.ResourceGroupIds = NULL;
  983. ValidationSam.ResourceGroupCount = 0;
  984. //
  985. // Set the flag indicating resource groups may be present
  986. //
  987. if (ResourceGroups->Count != 0)
  988. {
  989. ExtraSidCount = ValidationSam.SidCount + ResourceGroups->Count;
  990. ValidationSam.UserFlags |= LOGON_EXTRA_SIDS;
  991. ExtraSids = (PNETLOGON_SID_AND_ATTRIBUTES) MIDL_user_allocate(sizeof(NETLOGON_SID_AND_ATTRIBUTES) * ExtraSidCount);
  992. if (ExtraSids == NULL)
  993. {
  994. Status = STATUS_INSUFFICIENT_RESOURCES;
  995. goto Cleanup;
  996. }
  997. //
  998. // Add in all the extra sids that are not resource groups
  999. //
  1000. Index2 = 0;
  1001. for (Index = 0; Index < OldValidationInfo->SidCount; Index++ )
  1002. {
  1003. if ((OldValidationInfo->ExtraSids[Index].Attributes & SE_GROUP_RESOURCE) == 0)
  1004. {
  1005. ExtraSids[Index2] = OldValidationInfo->ExtraSids[Index];
  1006. Index2++;
  1007. }
  1008. }
  1009. //
  1010. // Copy all the resource group SIDs
  1011. //
  1012. for (Index = 0; Index < ResourceGroups->Count ; Index++ )
  1013. {
  1014. ExtraSids[Index2].Sid = ResourceGroups->Sids[Index].SidPointer;
  1015. ExtraSids[Index2].Attributes = SE_GROUP_MANDATORY |
  1016. SE_GROUP_ENABLED |
  1017. SE_GROUP_ENABLED_BY_DEFAULT |
  1018. SE_GROUP_RESOURCE;
  1019. Index2++;
  1020. }
  1021. ValidationSam.ExtraSids = ExtraSids;
  1022. ValidationSam.SidCount = Index2;
  1023. }
  1024. Status = PAC_EncodeValidationInformation(
  1025. &ValidationSam,
  1026. ValidationInfo,
  1027. ValidationInfoSize
  1028. );
  1029. Cleanup:
  1030. if (ExtraSids != NULL)
  1031. {
  1032. MIDL_user_free(ExtraSids);
  1033. }
  1034. return(Status);
  1035. }
  1036. //+-------------------------------------------------------------------------
  1037. //
  1038. // Function: PAC_UnmarshallValidationInfo
  1039. //
  1040. // Synopsis: un marshals a NETLOGON_VALIDATION_SAM_INFO3
  1041. //
  1042. // Effects: resets offset to be pointers
  1043. //
  1044. // Arguments:
  1045. //
  1046. // Requires:
  1047. //
  1048. // Returns:
  1049. //
  1050. // Notes:
  1051. //
  1052. //
  1053. //--------------------------------------------------------------------------
  1054. NTSTATUS
  1055. PAC_UnmarshallValidationInfo(
  1056. OUT PNETLOGON_VALIDATION_SAM_INFO3 * ValidationInfo,
  1057. IN PBYTE MarshalledInfo,
  1058. IN ULONG ValidationInfoSize
  1059. )
  1060. {
  1061. NTSTATUS Status;
  1062. *ValidationInfo = NULL;
  1063. Status = PAC_DecodeValidationInformation(
  1064. MarshalledInfo,
  1065. ValidationInfoSize,
  1066. ValidationInfo
  1067. );
  1068. return(Status);
  1069. }
  1070. //+-------------------------------------------------------------------------
  1071. //
  1072. // Function: PAC_BuildCredentials
  1073. //
  1074. // Synopsis: Builds the buffer containing supplemental credentials for
  1075. // the pac.
  1076. //
  1077. // Effects:
  1078. //
  1079. // Arguments:
  1080. //
  1081. // Requires:
  1082. //
  1083. // Returns:
  1084. //
  1085. // Notes:
  1086. //
  1087. //
  1088. //--------------------------------------------------------------------------
  1089. NTSTATUS
  1090. PAC_BuildCredentials(
  1091. IN PSAMPR_USER_ALL_INFORMATION UserAll,
  1092. OUT PBYTE * Credentials,
  1093. OUT PULONG CredentialSize
  1094. )
  1095. {
  1096. PSECPKG_SUPPLEMENTAL_CRED_ARRAY PacCreds = NULL;
  1097. PMSV1_0_SUPPLEMENTAL_CREDENTIAL MsvCredentials;
  1098. PUCHAR Where;
  1099. ULONG CredSize;
  1100. NTSTATUS Status = STATUS_SUCCESS;
  1101. *Credentials = NULL;
  1102. //
  1103. // The size of the credentials is the overhead for the structures
  1104. // plus the name "msv1_0"
  1105. //
  1106. CredSize = sizeof(SECPKG_SUPPLEMENTAL_CRED_ARRAY) +
  1107. sizeof(SECPKG_SUPPLEMENTAL_CRED) +
  1108. sizeof(MSV1_0_SUPPLEMENTAL_CREDENTIAL) +
  1109. NTLMSP_NAME_SIZE;
  1110. PacCreds = (PSECPKG_SUPPLEMENTAL_CRED_ARRAY) MIDL_user_allocate(CredSize);
  1111. if (PacCreds == NULL)
  1112. {
  1113. return(STATUS_INSUFFICIENT_RESOURCES);
  1114. }
  1115. //
  1116. // Build the PAC credential
  1117. //
  1118. Where = (PBYTE) PacCreds;
  1119. PacCreds->CredentialCount = 1;
  1120. Where += sizeof(SECPKG_SUPPLEMENTAL_CRED_ARRAY) + sizeof(SECPKG_SUPPLEMENTAL_CRED) - (ANYSIZE_ARRAY * sizeof(SECPKG_SUPPLEMENTAL_CRED));
  1121. //
  1122. // Build the secpkg creds
  1123. //
  1124. RtlCopyMemory(
  1125. Where,
  1126. NTLMSP_NAME,
  1127. NTLMSP_NAME_SIZE
  1128. );
  1129. PacCreds->Credentials[0].PackageName.Buffer = (LPWSTR) Where;
  1130. Where += ROUND_UP_COUNT(NTLMSP_NAME_SIZE,sizeof(ULONG));
  1131. PacCreds->Credentials[0].PackageName.Length = (USHORT) NTLMSP_NAME_SIZE;
  1132. PacCreds->Credentials[0].PackageName.MaximumLength = (USHORT) NTLMSP_NAME_SIZE;
  1133. PacCreds->Credentials[0].CredentialSize = sizeof(MSV1_0_SUPPLEMENTAL_CREDENTIAL);
  1134. PacCreds->Credentials[0].Credentials = Where;
  1135. MsvCredentials = (PMSV1_0_SUPPLEMENTAL_CREDENTIAL) Where;
  1136. Where += sizeof(MSV1_0_SUPPLEMENTAL_CREDENTIAL);
  1137. RtlZeroMemory(
  1138. MsvCredentials,
  1139. sizeof(MSV1_0_SUPPLEMENTAL_CREDENTIAL)
  1140. );
  1141. MsvCredentials->Version = MSV1_0_CRED_VERSION;
  1142. if (UserAll->NtPasswordPresent)
  1143. {
  1144. DsysAssert(UserAll->NtOwfPassword.Length == MSV1_0_OWF_PASSWORD_LENGTH);
  1145. MsvCredentials->Flags |= MSV1_0_CRED_NT_PRESENT;
  1146. RtlCopyMemory(
  1147. MsvCredentials->NtPassword,
  1148. UserAll->NtOwfPassword.Buffer,
  1149. UserAll->NtOwfPassword.Length
  1150. );
  1151. }
  1152. if (UserAll->LmPasswordPresent)
  1153. {
  1154. DsysAssert(UserAll->LmOwfPassword.Length == MSV1_0_OWF_PASSWORD_LENGTH);
  1155. MsvCredentials->Flags |= MSV1_0_CRED_LM_PRESENT;
  1156. RtlCopyMemory(
  1157. MsvCredentials->LmPassword,
  1158. UserAll->LmOwfPassword.Buffer,
  1159. UserAll->LmOwfPassword.Length
  1160. );
  1161. }
  1162. Status = PAC_EncodeCredentialData(
  1163. PacCreds,
  1164. Credentials,
  1165. CredentialSize
  1166. );
  1167. if (PacCreds != NULL)
  1168. {
  1169. MIDL_user_free(PacCreds);
  1170. }
  1171. return(Status);
  1172. }
  1173. //+-------------------------------------------------------------------------
  1174. //
  1175. // Function: PAC_UnmarshallCredentials
  1176. //
  1177. // Synopsis: un marshals a SECPKG_SUPPLEMENTAL_CRED_ARRAY
  1178. //
  1179. // Effects: resets offset to be pointers
  1180. //
  1181. // Arguments:
  1182. //
  1183. // Requires:
  1184. //
  1185. // Returns:
  1186. //
  1187. // Notes:
  1188. //
  1189. //
  1190. //--------------------------------------------------------------------------
  1191. NTSTATUS
  1192. PAC_UnmarshallCredentials(
  1193. OUT PSECPKG_SUPPLEMENTAL_CRED_ARRAY * Credentials,
  1194. IN PBYTE MarshalledInfo,
  1195. OUT ULONG CredentialInfoSize
  1196. )
  1197. {
  1198. NTSTATUS Status;
  1199. *Credentials = NULL;
  1200. Status = PAC_DecodeCredentialData(
  1201. MarshalledInfo,
  1202. CredentialInfoSize,
  1203. Credentials
  1204. );
  1205. return(Status);
  1206. }
  1207. //+---------------------------------------------------------------------------
  1208. //
  1209. // Function: PAC_Init
  1210. //
  1211. // Synopsis: Creates a new PAC with the provided info
  1212. //
  1213. // Arguments: UserAll - UserAllInformation for the user
  1214. // GroupsBuffer - The buffer returned from a call to
  1215. // SamrGetGroupsForUser, contains all global groups
  1216. // LogonDomainId - Domain SID for the domain of this DC
  1217. // SignatureSize - Space to reserve for signatures. If zero,
  1218. // no signatures are added.
  1219. // ppPac - Receives a pac, allocated with MIDL_user_allocate
  1220. //
  1221. //
  1222. // History: 24-May-95 SuChang Created
  1223. //
  1224. // Notes:
  1225. //
  1226. //----------------------------------------------------------------------------
  1227. NTSTATUS
  1228. PAC_Init(
  1229. IN PSAMPR_USER_ALL_INFORMATION UserAll,
  1230. IN OPTIONAL PSAMPR_GET_GROUPS_BUFFER GroupsBuffer,
  1231. IN OPTIONAL PSID_AND_ATTRIBUTES_LIST ExtraGroups,
  1232. IN PSID LogonDomainId,
  1233. IN PUNICODE_STRING LogonDomainName,
  1234. IN PUNICODE_STRING LogonServer,
  1235. IN ULONG SignatureSize,
  1236. IN ULONG AdditionalDataCount,
  1237. IN PPAC_INFO_BUFFER * AdditionalData,
  1238. OUT PPACTYPE * ppPac
  1239. )
  1240. {
  1241. ULONG cbBytes = 0;
  1242. ULONG cPacBuffers = 0;
  1243. PPACTYPE pNewPac = NULL;
  1244. ULONG iBuffer = 0;
  1245. ULONG cbProxyData = 0;
  1246. PBYTE ValidationInfo = NULL;
  1247. ULONG ValidationInfoSize;
  1248. NTSTATUS Status;
  1249. PBYTE pDataStore;
  1250. ULONG Index;
  1251. *ppPac = NULL;
  1252. //
  1253. // We need to determine the number of bytes required to store the provided
  1254. // information. For each type of info, determine the required number of
  1255. // bytes to store that type of info. Then allocate a contiguous buffer
  1256. // for the PAC and store all the info into the buffer.
  1257. //
  1258. //
  1259. // First we will create the validation info buffer. We can copy it into
  1260. // the PAC later.
  1261. //
  1262. Status = PAC_MarshallValidationInfo(
  1263. UserAll,
  1264. GroupsBuffer,
  1265. ExtraGroups,
  1266. LogonDomainId,
  1267. LogonDomainName,
  1268. LogonServer,
  1269. FALSE, // don't include user parms
  1270. FALSE, // not a network logon
  1271. &ValidationInfo,
  1272. &ValidationInfoSize
  1273. );
  1274. if (!NT_SUCCESS(Status))
  1275. {
  1276. goto Cleanup;
  1277. }
  1278. //
  1279. // We need a PAC_INFO_BUFFER to store the validation info.
  1280. //
  1281. cbBytes += ROUND_UP_COUNT(ValidationInfoSize, ALIGN_QUAD);
  1282. cPacBuffers += 1;
  1283. for (Index = 0; Index < AdditionalDataCount ; Index++ )
  1284. {
  1285. cbBytes += ROUND_UP_COUNT(AdditionalData[Index]->cbBufferSize,ALIGN_QUAD);
  1286. cPacBuffers++;
  1287. }
  1288. //
  1289. // If signature size is non-zero, add in space for signatures.
  1290. //
  1291. if (SignatureSize != 0)
  1292. {
  1293. cPacBuffers += 2;
  1294. cbBytes += 2 * (ROUND_UP_COUNT(PAC_SIGNATURE_SIZE(SignatureSize), ALIGN_QUAD));
  1295. }
  1296. //
  1297. // We need space for the PAC structure itself. Because the PAC_INFO_BUFFER
  1298. // is defined to be an array, a sizeof(PAC) already includes the
  1299. // size of ANYSIZE_ARRAY PAC_INFO_BUFFERs so we can subtract some bytes off.
  1300. //
  1301. cbBytes += sizeof(PACTYPE) +
  1302. (cPacBuffers - ANYSIZE_ARRAY) * sizeof(PAC_INFO_BUFFER);
  1303. cbBytes = ROUND_UP_COUNT( cbBytes, ALIGN_QUAD );
  1304. pNewPac = (PPACTYPE) MIDL_user_allocate( cbBytes );
  1305. if (pNewPac == NULL)
  1306. {
  1307. Status = STATUS_INSUFFICIENT_RESOURCES;
  1308. goto Cleanup;
  1309. }
  1310. ZeroMemory( pNewPac, cbBytes );
  1311. pNewPac->Version = PAC_VERSION;
  1312. pNewPac->cBuffers = cPacBuffers;
  1313. //
  1314. // Store data in such a way that the variable length data of
  1315. // PAC_INFO_BUFFER are at the end of all the PAC info buffers.
  1316. //
  1317. pDataStore = (PBYTE)&(pNewPac->Buffers[pNewPac->cBuffers]);
  1318. pDataStore = (PBYTE) ROUND_UP_POINTER( pDataStore, ALIGN_QUAD );
  1319. //
  1320. // Save the PAC identity ...
  1321. //
  1322. pNewPac->Buffers[iBuffer].ulType = PAC_LOGON_INFO;
  1323. pNewPac->Buffers[iBuffer].cbBufferSize = ValidationInfoSize;
  1324. pNewPac->Buffers[iBuffer].Data = pDataStore;
  1325. CopyMemory(
  1326. pDataStore,
  1327. ValidationInfo,
  1328. ValidationInfoSize
  1329. );
  1330. pDataStore += pNewPac->Buffers[iBuffer].cbBufferSize;
  1331. pDataStore = (PBYTE) ROUND_UP_POINTER( pDataStore, ALIGN_QUAD );
  1332. iBuffer ++;
  1333. //
  1334. // Store the additional data
  1335. //
  1336. for (Index = 0; Index < AdditionalDataCount ; Index++ )
  1337. {
  1338. pNewPac->Buffers[iBuffer].ulType = AdditionalData[Index]->ulType;
  1339. pNewPac->Buffers[iBuffer].cbBufferSize = AdditionalData[Index]->cbBufferSize;
  1340. pNewPac->Buffers[iBuffer].Data = pDataStore;
  1341. CopyMemory(
  1342. pDataStore,
  1343. AdditionalData[Index]->Data,
  1344. AdditionalData[Index]->cbBufferSize
  1345. );
  1346. pDataStore += pNewPac->Buffers[iBuffer].cbBufferSize;
  1347. pDataStore = (PBYTE) ROUND_UP_POINTER( pDataStore, ALIGN_QUAD );
  1348. iBuffer ++;
  1349. }
  1350. //
  1351. // Store the signatures
  1352. //
  1353. if (SignatureSize != 0)
  1354. {
  1355. pNewPac->Buffers[iBuffer].ulType = PAC_SERVER_CHECKSUM;
  1356. pNewPac->Buffers[iBuffer].cbBufferSize = PAC_SIGNATURE_SIZE(SignatureSize);
  1357. pNewPac->Buffers[iBuffer].Data = pDataStore;
  1358. pDataStore += ROUND_UP_COUNT(PAC_SIGNATURE_SIZE(SignatureSize),ALIGN_QUAD);
  1359. iBuffer ++;
  1360. pNewPac->Buffers[iBuffer].ulType = PAC_PRIVSVR_CHECKSUM;
  1361. pNewPac->Buffers[iBuffer].cbBufferSize = PAC_SIGNATURE_SIZE(SignatureSize);
  1362. pNewPac->Buffers[iBuffer].Data = pDataStore;
  1363. pDataStore += ROUND_UP_COUNT(PAC_SIGNATURE_SIZE(SignatureSize), ALIGN_QUAD);
  1364. iBuffer ++;
  1365. }
  1366. *ppPac = pNewPac;
  1367. pNewPac = NULL;
  1368. Cleanup:
  1369. if (ValidationInfo != NULL)
  1370. {
  1371. MIDL_user_free(ValidationInfo);
  1372. }
  1373. if (pNewPac != NULL)
  1374. {
  1375. MIDL_user_free(pNewPac);
  1376. }
  1377. return(Status);
  1378. }
  1379. //+---------------------------------------------------------------------------
  1380. //
  1381. // Function: PAC_InitAndUpdateGroups
  1382. //
  1383. // Synopsis: Creates a new PAC from old validation info and a list of
  1384. // resource groupss.
  1385. //
  1386. // Arguments: OldValidationInfo - Old info from a previous PAC
  1387. // ResourceGroups - Resource groups in this domain
  1388. // OldPac - OldPac to copy data from
  1389. // ppPac - Receives a pac, allocated with MIDL_user_allocate
  1390. //
  1391. //
  1392. // History: 24-May-95 SuChang Created
  1393. //
  1394. // Notes:
  1395. //
  1396. //----------------------------------------------------------------------------
  1397. NTSTATUS
  1398. PAC_InitAndUpdateGroups(
  1399. IN PNETLOGON_VALIDATION_SAM_INFO3 OldValidationInfo,
  1400. IN PSAMPR_PSID_ARRAY ResourceGroups,
  1401. IN PPACTYPE OldPac,
  1402. OUT PPACTYPE * ppPac
  1403. )
  1404. {
  1405. ULONG cbBytes = 0;
  1406. ULONG cPacBuffers = 0;
  1407. PPACTYPE pNewPac = NULL;
  1408. ULONG iBuffer = 0;
  1409. ULONG cbProxyData = 0;
  1410. PBYTE ValidationInfo = NULL;
  1411. ULONG ValidationInfoSize;
  1412. NTSTATUS Status;
  1413. PBYTE pDataStore;
  1414. ULONG Index;
  1415. *ppPac = NULL;
  1416. //
  1417. // We need to determine the number of bytes required to store the provided
  1418. // information. For each type of info, determine the required number of
  1419. // bytes to store that type of info. Then allocate a contiguous buffer
  1420. // for the PAC and store all the info into the buffer.
  1421. //
  1422. //
  1423. // First we will create the validation info buffer. We can copy it into
  1424. // the PAC later.
  1425. //
  1426. Status = PAC_ReMarshallValidationInfoWithGroups(
  1427. OldValidationInfo,
  1428. ResourceGroups,
  1429. &ValidationInfo,
  1430. &ValidationInfoSize
  1431. );
  1432. if (!NT_SUCCESS(Status))
  1433. {
  1434. goto Cleanup;
  1435. }
  1436. //
  1437. // We need a PAC_INFO_BUFFER to store the PAC_IDENTITY which
  1438. // contain the principal RID and the principal's domain GUID.
  1439. //
  1440. cbBytes += ROUND_UP_COUNT(ValidationInfoSize, ALIGN_QUAD);
  1441. cPacBuffers += 1;
  1442. for (Index = 0; Index < OldPac->cBuffers ; Index++ )
  1443. {
  1444. if (OldPac->Buffers[Index].ulType != PAC_LOGON_INFO)
  1445. {
  1446. cbBytes += ROUND_UP_COUNT(OldPac->Buffers[Index].cbBufferSize,ALIGN_QUAD);
  1447. cPacBuffers++;
  1448. }
  1449. }
  1450. //
  1451. // We need space for the PAC structure itself. Because the PAC_INFO_BUFFER
  1452. // is defined to be an array, a sizeof(PAC) already includes the
  1453. // size of ANYSIZE_ARRAY PAC_INFO_BUFFERs so we can subtract some bytes off.
  1454. //
  1455. cbBytes += sizeof(PACTYPE) +
  1456. (cPacBuffers - ANYSIZE_ARRAY) * sizeof(PAC_INFO_BUFFER);
  1457. cbBytes = ROUND_UP_COUNT( cbBytes, ALIGN_QUAD );
  1458. pNewPac = (PPACTYPE) MIDL_user_allocate( cbBytes );
  1459. if (pNewPac == NULL)
  1460. {
  1461. Status = STATUS_INSUFFICIENT_RESOURCES;
  1462. goto Cleanup;
  1463. }
  1464. ZeroMemory( pNewPac, cbBytes );
  1465. pNewPac->cBuffers = cPacBuffers;
  1466. //
  1467. // Store data in such a way that the variable length data of
  1468. // PAC_INFO_BUFFER are at the end of all the PAC info buffers.
  1469. //
  1470. pDataStore = (PBYTE)&(pNewPac->Buffers[pNewPac->cBuffers]);
  1471. pDataStore = (PBYTE) ROUND_UP_POINTER( pDataStore, ALIGN_QUAD );
  1472. //
  1473. // Save the PAC identity ...
  1474. //
  1475. pNewPac->Buffers[iBuffer].ulType = PAC_LOGON_INFO;
  1476. pNewPac->Buffers[iBuffer].cbBufferSize = ValidationInfoSize;
  1477. pNewPac->Buffers[iBuffer].Data = pDataStore;
  1478. CopyMemory(
  1479. pDataStore,
  1480. ValidationInfo,
  1481. ValidationInfoSize
  1482. );
  1483. pDataStore += pNewPac->Buffers[iBuffer].cbBufferSize;
  1484. pDataStore = (PBYTE) ROUND_UP_POINTER( pDataStore, ALIGN_QUAD );
  1485. iBuffer ++;
  1486. //
  1487. // Store the additional data
  1488. //
  1489. for (Index = 0; Index < OldPac->cBuffers ; Index++ )
  1490. {
  1491. if (OldPac->Buffers[Index].ulType != PAC_LOGON_INFO)
  1492. {
  1493. pNewPac->Buffers[iBuffer].ulType = OldPac->Buffers[Index].ulType;
  1494. pNewPac->Buffers[iBuffer].cbBufferSize = OldPac->Buffers[Index].cbBufferSize;
  1495. pNewPac->Buffers[iBuffer].Data = pDataStore;
  1496. CopyMemory(
  1497. pDataStore,
  1498. OldPac->Buffers[Index].Data,
  1499. OldPac->Buffers[Index].cbBufferSize
  1500. );
  1501. pDataStore += pNewPac->Buffers[iBuffer].cbBufferSize;
  1502. pDataStore = (PBYTE) ROUND_UP_POINTER( pDataStore, ALIGN_QUAD );
  1503. iBuffer ++;
  1504. }
  1505. }
  1506. *ppPac = pNewPac;
  1507. pNewPac = NULL;
  1508. Cleanup:
  1509. if (ValidationInfo != NULL)
  1510. {
  1511. MIDL_user_free(ValidationInfo);
  1512. }
  1513. if (pNewPac != NULL)
  1514. {
  1515. MIDL_user_free(pNewPac);
  1516. }
  1517. return(Status);
  1518. }
  1519. //+---------------------------------------------------------------------------
  1520. //
  1521. // Function: PAC_Find
  1522. //
  1523. // Synopsis: Finds a type of PAC info buffer in the given PAC.
  1524. // If pElem is NULL, the first buffer found matching the
  1525. // specified type is returned. Otherwise, the next buffer
  1526. // after pElem found matching that type is returned.
  1527. //
  1528. // Arguments:
  1529. //
  1530. // History: 01-June-95 SuChang Created
  1531. //
  1532. // Notes:
  1533. //
  1534. //----------------------------------------------------------------------------
  1535. PPAC_INFO_BUFFER
  1536. PAC_Find( IN PPACTYPE pPac,
  1537. IN ULONG ulType,
  1538. PPAC_INFO_BUFFER pElem)
  1539. {
  1540. PAC_INFO_BUFFER *pTemp = NULL, *pEnd;
  1541. if (pPac)
  1542. {
  1543. pEnd = &(pPac->Buffers[pPac->cBuffers]);
  1544. if (pElem)
  1545. {
  1546. pTemp = pElem + 1;
  1547. }
  1548. else
  1549. {
  1550. pTemp = &(pPac->Buffers[0]);
  1551. }
  1552. while ( pTemp < pEnd && pTemp->ulType != ulType )
  1553. {
  1554. pTemp++;
  1555. }
  1556. if (pTemp >= pEnd)
  1557. {
  1558. // element not found in the PAC
  1559. pTemp = NULL;
  1560. }
  1561. }
  1562. return (pTemp);
  1563. }