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.

2450 lines
62 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 "krbprgma.h"
  18. #include <secpch2.hxx>
  19. #pragma hdrstop
  20. #include <pac.hxx>
  21. #include <sectrace.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 = (ULONG) 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 = (ULONG) 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 = (ULONG) 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_EncodeS4UDelegationInformation
  540. //
  541. // Synopsis: NDR encodes the S4U delegation information
  542. //
  543. // Effects:
  544. //
  545. // Arguments:
  546. //
  547. // Requires:
  548. //
  549. // Returns:
  550. //
  551. // Notes:
  552. //
  553. //
  554. //--------------------------------------------------------------------------
  555. NTSTATUS
  556. PAC_EncodeS4UDelegationInformation(
  557. IN PS4U_DELEGATION_INFO S4UDelegationInfo,
  558. OUT PBYTE * EncodedData,
  559. OUT PULONG DataSize
  560. )
  561. {
  562. NTSTATUS Status = STATUS_SUCCESS;
  563. handle_t PickleHandle = 0;
  564. PAC_BUFFER_STATE BufferState = {0};
  565. ULONG EncodingStatus = 0;
  566. PUCHAR OutputBuffer = NULL;
  567. ULONG OutputSize = 0;
  568. EncodingStatus = MesEncodeIncrementalHandleCreate(
  569. &BufferState,
  570. PacAllocFcn,
  571. PacWriteFcn,
  572. &PickleHandle
  573. );
  574. if (EncodingStatus != 0)
  575. {
  576. Status = STATUS_INSUFFICIENT_RESOURCES;
  577. goto Cleanup;
  578. }
  579. //
  580. // Calculate the size of the required buffer
  581. //
  582. OutputSize = (ULONG) PPAC_IDL_S4U_DELEGATION_INFO_AlignSize(
  583. PickleHandle,
  584. &S4UDelegationInfo
  585. );
  586. OutputBuffer = (PBYTE) MIDL_user_allocate(OutputSize);
  587. if (OutputBuffer == NULL)
  588. {
  589. Status = STATUS_INSUFFICIENT_RESOURCES;
  590. goto Cleanup;
  591. }
  592. BufferState.BufferSize = OutputSize;
  593. BufferState.BufferPointer = OutputBuffer;
  594. //
  595. // Now encode the structure
  596. //
  597. MesIncrementalHandleReset(
  598. PickleHandle,
  599. NULL,
  600. NULL,
  601. NULL,
  602. NULL,
  603. MES_ENCODE
  604. );
  605. PPAC_IDL_S4U_DELEGATION_INFO_Encode(
  606. PickleHandle,
  607. &S4UDelegationInfo
  608. );
  609. *EncodedData = OutputBuffer;
  610. *DataSize = OutputSize;
  611. OutputBuffer = NULL;
  612. Cleanup:
  613. if (OutputBuffer != NULL)
  614. {
  615. MIDL_user_free(OutputBuffer);
  616. }
  617. if (PickleHandle != NULL)
  618. {
  619. MesHandleFree(PickleHandle);
  620. }
  621. return(Status);
  622. }
  623. //+-------------------------------------------------------------------------
  624. //
  625. // Function: PAC_DecodeS4UDelegationInformation
  626. //
  627. // Synopsis: NDR decodes the S4U delegation information
  628. //
  629. // Effects:
  630. //
  631. // Arguments:
  632. //
  633. // Requires:
  634. //
  635. // Returns:
  636. //
  637. // Notes:
  638. //
  639. //
  640. //--------------------------------------------------------------------------
  641. NTSTATUS
  642. PAC_DecodeS4UDelegationInformation(
  643. IN PBYTE EncodedData,
  644. IN ULONG DataSize,
  645. OUT PS4U_DELEGATION_INFO * S4UDelegationInfo
  646. )
  647. {
  648. NTSTATUS Status = STATUS_SUCCESS;
  649. handle_t PickleHandle = 0;
  650. PAC_BUFFER_STATE BufferState = {0};
  651. ULONG EncodingStatus = 0;
  652. DsysAssert(ROUND_UP_POINTER(EncodedData,8) == (PVOID) EncodedData);
  653. EncodingStatus = MesDecodeIncrementalHandleCreate(
  654. &BufferState,
  655. PacReadFcn,
  656. &PickleHandle
  657. );
  658. if (EncodingStatus != 0)
  659. {
  660. Status = STATUS_INSUFFICIENT_RESOURCES;
  661. goto Cleanup;
  662. }
  663. BufferState.BufferSize = DataSize;
  664. BufferState.BufferPointer = EncodedData;
  665. __try {
  666. PPAC_IDL_S4U_DELEGATION_INFO_Decode(
  667. PickleHandle,
  668. S4UDelegationInfo
  669. );
  670. } __except (EXCEPTION_EXECUTE_HANDLER) {
  671. Status = STATUS_INVALID_PARAMETER;
  672. goto Cleanup;
  673. }
  674. Cleanup:
  675. if (PickleHandle != NULL)
  676. {
  677. MesHandleFree(PickleHandle);
  678. }
  679. return(Status);
  680. }
  681. //+---------------------------------------------------------------------------
  682. //
  683. // Function: PAC_GetSize
  684. //
  685. // Synopsis: Determines the number of bytes required to marshal the
  686. // given PAC.
  687. //
  688. // Arguments:
  689. //
  690. // History: 24-May-95 SuChang Created
  691. //
  692. // Notes:
  693. //
  694. //----------------------------------------------------------------------------
  695. ULONG
  696. PAC_GetSize( IN PACTYPE *pPac )
  697. {
  698. ULONG cbSize = 0;
  699. if (pPac != NULL)
  700. {
  701. cbSize += sizeof( PACTYPE );
  702. cbSize += (pPac->cBuffers - ANYSIZE_ARRAY) * sizeof(PAC_INFO_BUFFER);
  703. cbSize = ROUND_UP_COUNT( cbSize, ALIGN_QUAD );
  704. for (ULONG i = 0; i < pPac->cBuffers; i++ )
  705. {
  706. cbSize += ROUND_UP_COUNT(pPac->Buffers[i].cbBufferSize, ALIGN_QUAD);
  707. }
  708. }
  709. return (cbSize);
  710. }
  711. //+---------------------------------------------------------------------------
  712. //
  713. // Function: PAC_Marshal
  714. //
  715. // Synopsis: Marshals the given PAC into the provided buffer.
  716. //
  717. // Arguments:
  718. //
  719. // History: 24-May-95 SuChang Created
  720. //
  721. // Notes: This assumes the PAC is the same form as created
  722. // by PAC_Init. See header description of the PAC
  723. // structure.
  724. //
  725. // Returns the number of bytes used or 0 if an error
  726. // occurred.
  727. //
  728. //----------------------------------------------------------------------------
  729. ULONG
  730. PAC_Marshal( IN PACTYPE *pPac,
  731. IN ULONG cbBuffer,
  732. OUT PBYTE pBufferOut)
  733. {
  734. DsysAssert( pPac != NULL && pBufferOut != NULL );
  735. ULONG PacLen = PAC_GetSize( pPac );
  736. if (cbBuffer < PacLen)
  737. {
  738. return 0;
  739. }
  740. //
  741. // Copy into pBufferOut and then change the pointers of each
  742. // PAC_INFO_BUFFER to be offsets from pPac.
  743. //
  744. CopyMemory( pBufferOut, pPac, PacLen );
  745. PPACTYPE pPacTemp = (PPACTYPE) pBufferOut;
  746. for (ULONG i = 0; i < pPacTemp->cBuffers; i++ )
  747. {
  748. pPacTemp->Buffers[i].Offset = (ULONG) (pPacTemp->Buffers[i].Data -
  749. (PBYTE)pPac);
  750. }
  751. return PacLen;
  752. }
  753. //+---------------------------------------------------------------------------
  754. //
  755. // Function: PAC_UnMarshal
  756. //
  757. // Synopsis: Does in place unmarshalling of the marshalled PAC.
  758. //
  759. // Arguments:
  760. //
  761. // History: 24-May-95 SuChang Created
  762. //
  763. // Notes: Does in place unmarshalling. No new memory is allocated.
  764. //
  765. // This assumes the PAC is the same form as created
  766. // by PAC_Init. See header description of the PAC
  767. // structure.
  768. //
  769. //----------------------------------------------------------------------------
  770. ULONG
  771. PAC_UnMarshal( IN PPACTYPE pPac,
  772. IN ULONG cbSize )
  773. {
  774. ULONG i;
  775. ULONG cbUnmarshalled = 0;
  776. PBYTE pEnd = (PBYTE)pPac + cbSize;
  777. PBYTE pBufferAddress;
  778. DsysAssert( pPac != NULL );
  779. //
  780. // Do a validation loop. Make sure that the offsets are
  781. // correct. We don't want to do this validation inside the modification
  782. // loop because it wouldn't be nice to change the buffer if it weren't
  783. // valid.
  784. //
  785. if ((pPac->cBuffers * sizeof(PAC_INFO_BUFFER) + sizeof(PACTYPE)) > cbSize)
  786. {
  787. return(0);
  788. }
  789. if (pPac->Version != PAC_VERSION)
  790. {
  791. return(0);
  792. }
  793. for (i = 0; i < pPac->cBuffers; i++)
  794. {
  795. pBufferAddress = (ULONG)pPac->Buffers[i].Offset + (PBYTE)pPac;
  796. if ( (pBufferAddress >= pEnd ) || (pBufferAddress < (PBYTE) pPac) ||
  797. (pBufferAddress + pPac->Buffers[i].cbBufferSize > pEnd))
  798. {
  799. //
  800. // Invalid offset or length
  801. //
  802. return (0);
  803. }
  804. }
  805. for (i = 0; i < pPac->cBuffers; i++ )
  806. {
  807. cbUnmarshalled += pPac->Buffers[i].cbBufferSize;
  808. pPac->Buffers[i].Data = pPac->Buffers[i].Offset +
  809. (PBYTE)pPac;
  810. }
  811. return (cbUnmarshalled);
  812. }
  813. //+---------------------------------------------------------------------------
  814. //
  815. // Function: PAC_ReMarshal
  816. //
  817. // Synopsis: Does in place re-marshalling of an un-marshalled PAC.
  818. //
  819. // Arguments:
  820. //
  821. // History: 24-May-95 SuChang Created
  822. //
  823. // Notes: Does in place re-marshalling. No new memory is allocated.
  824. //
  825. // This assumes the PAC is the same form as created
  826. // by PAC_UnMarshal. See header description of the PAC
  827. // structure.
  828. //
  829. //----------------------------------------------------------------------------
  830. BOOLEAN
  831. PAC_ReMarshal( IN PPACTYPE pPac,
  832. IN ULONG cbSize )
  833. {
  834. ULONG Offset;
  835. ULONG i;
  836. //
  837. // Do a validation loop. Make sure that the offsets are
  838. // correct. We don't want to do this validation inside the modification
  839. // loop because it wouldn't be nice to change the buffer if it weren't
  840. // valid.
  841. //
  842. for (i = 0; i < pPac->cBuffers; i++ )
  843. {
  844. Offset = (ULONG) (pPac->Buffers[i].Data - (PBYTE) pPac);
  845. if ( Offset >= cbSize )
  846. {
  847. //
  848. // Invalid offset or length
  849. //
  850. return (FALSE);
  851. }
  852. pPac->Buffers[i].Offset = Offset;
  853. }
  854. return (TRUE);
  855. }
  856. VOID
  857. PAC_PutString(
  858. IN PVOID Base,
  859. IN PUNICODE_STRING OutString,
  860. IN PUNICODE_STRING InString,
  861. IN PUCHAR *Where
  862. )
  863. /*++
  864. Routine Description:
  865. This routine copies the InString string to the memory pointed to by
  866. the Where parameter, and fixes the OutString string to point to that
  867. new copy.
  868. Parameters:
  869. OutString - A pointer to a destination NT string
  870. InString - A pointer to an NT string to be copied
  871. Where - A pointer to space to put the actual string for the
  872. OutString. The pointer is adjusted to point to the first byte
  873. following the copied string.
  874. Return Values:
  875. None.
  876. --*/
  877. {
  878. DsysAssert( OutString != NULL );
  879. DsysAssert( InString != NULL );
  880. DsysAssert( Where != NULL && *Where != NULL);
  881. DsysAssert( *Where == ROUND_UP_POINTER( *Where, sizeof(WCHAR) ) );
  882. if ( InString->Length > 0 ) {
  883. OutString->Buffer = (PWCH) *Where;
  884. OutString->MaximumLength = (USHORT)(InString->Length + sizeof(WCHAR));
  885. RtlCopyUnicodeString( OutString, InString );
  886. //
  887. // Rest the pointer to be an offset.
  888. //
  889. OutString->Buffer = (PWCH) (*Where - (PUCHAR) Base);
  890. *Where += InString->Length;
  891. // *((WCHAR *)(*Where)) = L'\0';
  892. *(*Where) = '\0';
  893. *(*Where + 1) = '\0';
  894. *Where += 2;
  895. } else {
  896. RtlInitUnicodeString(OutString, NULL);
  897. }
  898. return;
  899. }
  900. //+-------------------------------------------------------------------------
  901. //
  902. // Function: PAC_MarshallValidationInfo
  903. //
  904. // Synopsis: marshals a NETLOGON_VALIDATION_SAM_INFO2
  905. //
  906. // Effects: allocates memory with MIDL_user_allocate
  907. //
  908. // Arguments:
  909. //
  910. // Requires:
  911. //
  912. // Returns:
  913. //
  914. // Notes:
  915. //
  916. //
  917. //--------------------------------------------------------------------------
  918. NTSTATUS
  919. PAC_MarshallValidationInfo
  920. (
  921. IN PSAMPR_USER_ALL_INFORMATION UserAll,
  922. IN PSAMPR_GET_GROUPS_BUFFER GroupsBuffer,
  923. IN PSID_AND_ATTRIBUTES_LIST ExtraGroups,
  924. IN PSID LogonDomainId,
  925. IN PUNICODE_STRING LogonDomainName,
  926. IN PUNICODE_STRING LogonServer,
  927. IN BOOLEAN IncludeUserParms,
  928. IN BOOLEAN NetworkProfile,
  929. OUT PBYTE * ValidationInfo,
  930. OUT PULONG ValidationInfoSize
  931. )
  932. {
  933. NETLOGON_VALIDATION_SAM_INFO3 ValidationSam = {0};
  934. PNETLOGON_SID_AND_ATTRIBUTES MarshalledSids = NULL;
  935. SID ServerSid = {SID_REVISION, 1, SECURITY_NT_AUTHORITY, SECURITY_SERVER_LOGON_RID };
  936. NTSTATUS Status = STATUS_SUCCESS;
  937. ULONG ExtraGroupCount = 0;
  938. ULONG Index;
  939. //
  940. // Allocate a return buffer for validation information.
  941. // (Return less information for a network logon)
  942. // (Return UserParameters for a MNS logon)
  943. //
  944. //
  945. // First calculate the space needed for the extra groups.
  946. //
  947. if (ARGUMENT_PRESENT(ExtraGroups))
  948. {
  949. ExtraGroupCount += ExtraGroups->Count;
  950. }
  951. //
  952. // Add the enterprise server's sids
  953. //
  954. if ((UserAll->UserAccountControl & USER_SERVER_TRUST_ACCOUNT) != 0)
  955. {
  956. ExtraGroupCount += 1;
  957. }
  958. //
  959. // Set the UF_SMARTCARD_REQUIRED flag
  960. //
  961. if ((UserAll->UserAccountControl & USER_SMARTCARD_REQUIRED) != 0)
  962. {
  963. ValidationSam.UserFlags |= UF_SMARTCARD_REQUIRED;
  964. }
  965. //
  966. // Copy the scalars to the validation buffer.
  967. //
  968. ValidationSam.LogonTime = UserAll->LastLogon;
  969. //
  970. // BUG 455821: need logoff time & kickoff time
  971. //
  972. #ifdef notdef
  973. NEW_TO_OLD_LARGE_INTEGER( LogoffTime, ValidationSam.LogoffTime );
  974. NEW_TO_OLD_LARGE_INTEGER( KickoffTime, ValidationSam.KickOffTime );
  975. #else
  976. ValidationSam.LogoffTime.LowPart = 0xffffffff;
  977. ValidationSam.LogoffTime.HighPart = 0x7fffffff;
  978. ValidationSam.KickOffTime.LowPart = 0xffffffff;
  979. ValidationSam.KickOffTime.HighPart = 0x7fffffff;
  980. #endif
  981. ValidationSam.PasswordLastSet = UserAll->PasswordLastSet;
  982. ValidationSam.PasswordCanChange = UserAll->PasswordCanChange;
  983. ValidationSam.PasswordMustChange = UserAll->PasswordMustChange;
  984. ValidationSam.LogonCount = UserAll->LogonCount;
  985. ValidationSam.BadPasswordCount = UserAll->BadPasswordCount;
  986. ValidationSam.UserId = UserAll->UserId;
  987. ValidationSam.PrimaryGroupId = UserAll->PrimaryGroupId;
  988. if (ARGUMENT_PRESENT( GroupsBuffer) )
  989. {
  990. ValidationSam.GroupCount = GroupsBuffer->MembershipCount;
  991. ValidationSam.GroupIds = GroupsBuffer->Groups;
  992. }
  993. else
  994. {
  995. ValidationSam.GroupCount = 0;
  996. ValidationSam.GroupIds = NULL;
  997. }
  998. ValidationSam.ExpansionRoom[SAMINFO_USER_ACCOUNT_CONTROL] = UserAll->UserAccountControl;
  999. //
  1000. // If the client asked for extra information, return that
  1001. // we support it
  1002. //
  1003. ValidationSam.UserFlags |= LOGON_EXTRA_SIDS;
  1004. //
  1005. // Copy ULONG aligned data to the validation buffer.
  1006. //
  1007. if (ExtraGroupCount != 0)
  1008. {
  1009. ValidationSam.SidCount = ExtraGroupCount;
  1010. MarshalledSids = (PNETLOGON_SID_AND_ATTRIBUTES) MIDL_user_allocate(ExtraGroupCount * sizeof(NETLOGON_SID_AND_ATTRIBUTES));
  1011. if (MarshalledSids == NULL)
  1012. {
  1013. Status = STATUS_INSUFFICIENT_RESOURCES;
  1014. goto Cleanup;
  1015. }
  1016. ValidationSam.ExtraSids = MarshalledSids;
  1017. Index = 0;
  1018. if (ARGUMENT_PRESENT(ExtraGroups))
  1019. {
  1020. //
  1021. // Now marshall each sid into the buffer
  1022. //
  1023. C_ASSERT(sizeof(SID_AND_ATTRIBUTES) == sizeof(NETLOGON_SID_AND_ATTRIBUTES));
  1024. RtlCopyMemory(
  1025. &MarshalledSids[Index],
  1026. ExtraGroups->SidAndAttributes,
  1027. ExtraGroups->Count * sizeof(SID_AND_ATTRIBUTES)
  1028. );
  1029. Index += ExtraGroups->Count;
  1030. }
  1031. //
  1032. // Add in special sids for domain controllers
  1033. //
  1034. if ((UserAll->UserAccountControl & USER_SERVER_TRUST_ACCOUNT) != 0)
  1035. {
  1036. //
  1037. // Add in the constant server logon sid
  1038. //
  1039. MarshalledSids[Index].Attributes = SE_GROUP_MANDATORY |
  1040. SE_GROUP_ENABLED |
  1041. SE_GROUP_ENABLED_BY_DEFAULT;
  1042. MarshalledSids[Index].Sid = &ServerSid;
  1043. Index++;
  1044. }
  1045. }
  1046. ValidationSam.LogonDomainId = LogonDomainId;
  1047. //
  1048. // Copy WCHAR aligned data to the validation buffer.
  1049. // (Return less information for a network logon)
  1050. //
  1051. if ( ! NetworkProfile ) {
  1052. ValidationSam.EffectiveName = *(PUNICODE_STRING)&UserAll->UserName;
  1053. ValidationSam.FullName = *(PUNICODE_STRING)&UserAll->FullName;
  1054. ValidationSam.LogonScript = *(PUNICODE_STRING)&UserAll->ScriptPath;
  1055. ValidationSam.ProfilePath = *(PUNICODE_STRING)&UserAll->ProfilePath;
  1056. ValidationSam.HomeDirectory = *(PUNICODE_STRING)&UserAll->HomeDirectory;
  1057. ValidationSam.HomeDirectoryDrive = *(PUNICODE_STRING)&UserAll->HomeDirectoryDrive;
  1058. }
  1059. ValidationSam.LogonServer = *LogonServer;
  1060. ValidationSam.LogonDomainName = *LogonDomainName;
  1061. //
  1062. // Kludge: Pass back UserParameters in HomeDirectoryDrive since we
  1063. // can't change the NETLOGON_VALIDATION_SAM_INFO2 structure between
  1064. // releases NT 1.0 and NT 1.0A. HomeDirectoryDrive was NULL for release 1.0A
  1065. // so we'll use that field.
  1066. //
  1067. if ( IncludeUserParms && NetworkProfile ) {
  1068. ValidationSam.HomeDirectoryDrive = *(PUNICODE_STRING)&UserAll->Parameters;
  1069. }
  1070. Status = PAC_EncodeValidationInformation(
  1071. &ValidationSam,
  1072. ValidationInfo,
  1073. ValidationInfoSize
  1074. );
  1075. Cleanup:
  1076. if (MarshalledSids != NULL)
  1077. {
  1078. MIDL_user_free(MarshalledSids);
  1079. }
  1080. return(Status);
  1081. }
  1082. //+-------------------------------------------------------------------------
  1083. //
  1084. // Function: PAC_MarshallValidationInfoWithGroups
  1085. //
  1086. // Synopsis: marshals a NETLOGON_VALIDATION_SAM_INFO2
  1087. //
  1088. // Effects: allocates memory with MIDL_user_allocate
  1089. //
  1090. // Arguments:
  1091. //
  1092. // Requires:
  1093. //
  1094. // Returns:
  1095. //
  1096. // Notes:
  1097. //
  1098. //
  1099. //--------------------------------------------------------------------------
  1100. NTSTATUS
  1101. PAC_ReMarshallValidationInfoWithGroups(
  1102. IN PNETLOGON_VALIDATION_SAM_INFO3 OldValidationInfo,
  1103. IN PSAMPR_PSID_ARRAY ResourceGroups,
  1104. OUT PBYTE * ValidationInfo,
  1105. OUT PULONG ValidationInfoSize
  1106. )
  1107. {
  1108. NETLOGON_VALIDATION_SAM_INFO3 ValidationSam = {0};
  1109. PNETLOGON_SID_AND_ATTRIBUTES ExtraSids = NULL;
  1110. ULONG ExtraSidCount = 0;
  1111. NTSTATUS Status = STATUS_SUCCESS;
  1112. ULONG Index, Index2;
  1113. //
  1114. // Copy the original validation information
  1115. //
  1116. ValidationSam = *OldValidationInfo;
  1117. ValidationSam.UserFlags &= ~LOGON_RESOURCE_GROUPS;
  1118. //
  1119. // Clear any old resource groups
  1120. //
  1121. ValidationSam.ResourceGroupDomainSid = NULL;
  1122. ValidationSam.ResourceGroupIds = NULL;
  1123. ValidationSam.ResourceGroupCount = 0;
  1124. //
  1125. // Set the flag indicating resource groups may be present
  1126. //
  1127. if (ResourceGroups->Count != 0)
  1128. {
  1129. ExtraSidCount = ValidationSam.SidCount + ResourceGroups->Count;
  1130. ValidationSam.UserFlags |= LOGON_EXTRA_SIDS;
  1131. ExtraSids = (PNETLOGON_SID_AND_ATTRIBUTES) MIDL_user_allocate(sizeof(NETLOGON_SID_AND_ATTRIBUTES) * ExtraSidCount);
  1132. if (ExtraSids == NULL)
  1133. {
  1134. Status = STATUS_INSUFFICIENT_RESOURCES;
  1135. goto Cleanup;
  1136. }
  1137. //
  1138. // Add in all the extra sids that are not resource groups
  1139. //
  1140. Index2 = 0;
  1141. for (Index = 0; Index < OldValidationInfo->SidCount; Index++ )
  1142. {
  1143. if ((OldValidationInfo->ExtraSids[Index].Attributes & SE_GROUP_RESOURCE) == 0)
  1144. {
  1145. ExtraSids[Index2] = OldValidationInfo->ExtraSids[Index];
  1146. Index2++;
  1147. }
  1148. }
  1149. //
  1150. // Copy all the resource group SIDs
  1151. //
  1152. for (Index = 0; Index < ResourceGroups->Count ; Index++ )
  1153. {
  1154. ExtraSids[Index2].Sid = ResourceGroups->Sids[Index].SidPointer;
  1155. ExtraSids[Index2].Attributes = SE_GROUP_MANDATORY |
  1156. SE_GROUP_ENABLED |
  1157. SE_GROUP_ENABLED_BY_DEFAULT |
  1158. SE_GROUP_RESOURCE;
  1159. Index2++;
  1160. }
  1161. ValidationSam.ExtraSids = ExtraSids;
  1162. ValidationSam.SidCount = Index2;
  1163. }
  1164. Status = PAC_EncodeValidationInformation(
  1165. &ValidationSam,
  1166. ValidationInfo,
  1167. ValidationInfoSize
  1168. );
  1169. Cleanup:
  1170. if (ExtraSids != NULL)
  1171. {
  1172. MIDL_user_free(ExtraSids);
  1173. }
  1174. return(Status);
  1175. }
  1176. //+-------------------------------------------------------------------------
  1177. //
  1178. // Function: PAC_UnmarshallValidationInfo
  1179. //
  1180. // Synopsis: un marshals a NETLOGON_VALIDATION_SAM_INFO3
  1181. //
  1182. // Effects: resets offset to be pointers
  1183. //
  1184. // Arguments:
  1185. //
  1186. // Requires:
  1187. //
  1188. // Returns:
  1189. //
  1190. // Notes:
  1191. //
  1192. //
  1193. //--------------------------------------------------------------------------
  1194. NTSTATUS
  1195. PAC_UnmarshallValidationInfo(
  1196. OUT PNETLOGON_VALIDATION_SAM_INFO3 * ValidationInfo,
  1197. IN PBYTE MarshalledInfo,
  1198. IN ULONG ValidationInfoSize
  1199. )
  1200. {
  1201. NTSTATUS Status;
  1202. *ValidationInfo = NULL;
  1203. Status = PAC_DecodeValidationInformation(
  1204. MarshalledInfo,
  1205. ValidationInfoSize,
  1206. ValidationInfo
  1207. );
  1208. return(Status);
  1209. }
  1210. //+-------------------------------------------------------------------------
  1211. //
  1212. // Function: PAC_BuildCredentials
  1213. //
  1214. // Synopsis: Builds the buffer containing supplemental credentials for
  1215. // the pac.
  1216. //
  1217. // Effects:
  1218. //
  1219. // Arguments:
  1220. //
  1221. // Requires:
  1222. //
  1223. // Returns:
  1224. //
  1225. // Notes:
  1226. //
  1227. //
  1228. //--------------------------------------------------------------------------
  1229. NTSTATUS
  1230. PAC_BuildCredentials(
  1231. IN PSAMPR_USER_ALL_INFORMATION UserAll,
  1232. OUT PBYTE * Credentials,
  1233. OUT PULONG CredentialSize
  1234. )
  1235. {
  1236. PSECPKG_SUPPLEMENTAL_CRED_ARRAY PacCreds = NULL;
  1237. PMSV1_0_SUPPLEMENTAL_CREDENTIAL MsvCredentials;
  1238. PUCHAR Where;
  1239. ULONG CredSize;
  1240. NTSTATUS Status = STATUS_SUCCESS;
  1241. *Credentials = NULL;
  1242. //
  1243. // The size of the credentials is the overhead for the structures
  1244. // plus the name "msv1_0"
  1245. //
  1246. CredSize = sizeof(SECPKG_SUPPLEMENTAL_CRED_ARRAY) +
  1247. sizeof(SECPKG_SUPPLEMENTAL_CRED) +
  1248. sizeof(MSV1_0_SUPPLEMENTAL_CREDENTIAL) +
  1249. NTLMSP_NAME_SIZE;
  1250. PacCreds = (PSECPKG_SUPPLEMENTAL_CRED_ARRAY) MIDL_user_allocate(CredSize);
  1251. if (PacCreds == NULL)
  1252. {
  1253. return(STATUS_INSUFFICIENT_RESOURCES);
  1254. }
  1255. //
  1256. // Build the PAC credential
  1257. //
  1258. Where = (PBYTE) PacCreds;
  1259. PacCreds->CredentialCount = 1;
  1260. Where += sizeof(SECPKG_SUPPLEMENTAL_CRED_ARRAY) + sizeof(SECPKG_SUPPLEMENTAL_CRED) - (ANYSIZE_ARRAY * sizeof(SECPKG_SUPPLEMENTAL_CRED));
  1261. //
  1262. // Build the secpkg creds
  1263. //
  1264. RtlCopyMemory(
  1265. Where,
  1266. NTLMSP_NAME,
  1267. NTLMSP_NAME_SIZE
  1268. );
  1269. PacCreds->Credentials[0].PackageName.Buffer = (LPWSTR) Where;
  1270. Where += ROUND_UP_COUNT(NTLMSP_NAME_SIZE,sizeof(ULONG));
  1271. PacCreds->Credentials[0].PackageName.Length = (USHORT) NTLMSP_NAME_SIZE;
  1272. PacCreds->Credentials[0].PackageName.MaximumLength = (USHORT) NTLMSP_NAME_SIZE;
  1273. PacCreds->Credentials[0].CredentialSize = sizeof(MSV1_0_SUPPLEMENTAL_CREDENTIAL);
  1274. PacCreds->Credentials[0].Credentials = Where;
  1275. MsvCredentials = (PMSV1_0_SUPPLEMENTAL_CREDENTIAL) Where;
  1276. Where += sizeof(MSV1_0_SUPPLEMENTAL_CREDENTIAL);
  1277. RtlZeroMemory(
  1278. MsvCredentials,
  1279. sizeof(MSV1_0_SUPPLEMENTAL_CREDENTIAL)
  1280. );
  1281. MsvCredentials->Version = MSV1_0_CRED_VERSION;
  1282. if (UserAll->NtPasswordPresent)
  1283. {
  1284. DsysAssert(UserAll->NtOwfPassword.Length == MSV1_0_OWF_PASSWORD_LENGTH);
  1285. MsvCredentials->Flags |= MSV1_0_CRED_NT_PRESENT;
  1286. RtlCopyMemory(
  1287. MsvCredentials->NtPassword,
  1288. UserAll->NtOwfPassword.Buffer,
  1289. UserAll->NtOwfPassword.Length
  1290. );
  1291. }
  1292. if (UserAll->LmPasswordPresent)
  1293. {
  1294. DsysAssert(UserAll->LmOwfPassword.Length == MSV1_0_OWF_PASSWORD_LENGTH);
  1295. MsvCredentials->Flags |= MSV1_0_CRED_LM_PRESENT;
  1296. RtlCopyMemory(
  1297. MsvCredentials->LmPassword,
  1298. UserAll->LmOwfPassword.Buffer,
  1299. UserAll->LmOwfPassword.Length
  1300. );
  1301. }
  1302. Status = PAC_EncodeCredentialData(
  1303. PacCreds,
  1304. Credentials,
  1305. CredentialSize
  1306. );
  1307. if (PacCreds != NULL)
  1308. {
  1309. MIDL_user_free(PacCreds);
  1310. }
  1311. return(Status);
  1312. }
  1313. //+-------------------------------------------------------------------------
  1314. //
  1315. // Function: PAC_UnmarshallCredentials
  1316. //
  1317. // Synopsis: unmarshals a SECPKG_SUPPLEMENTAL_CRED_ARRAY
  1318. //
  1319. // Effects: resets offset to be pointers
  1320. //
  1321. // Arguments:
  1322. //
  1323. // Requires:
  1324. //
  1325. // Returns:
  1326. //
  1327. // Notes:
  1328. //
  1329. //
  1330. //--------------------------------------------------------------------------
  1331. NTSTATUS
  1332. PAC_UnmarshallCredentials(
  1333. OUT PSECPKG_SUPPLEMENTAL_CRED_ARRAY * Credentials,
  1334. IN PBYTE MarshalledInfo,
  1335. IN ULONG CredentialInfoSize
  1336. )
  1337. {
  1338. NTSTATUS Status;
  1339. *Credentials = NULL;
  1340. Status = PAC_DecodeCredentialData(
  1341. MarshalledInfo,
  1342. CredentialInfoSize,
  1343. Credentials
  1344. );
  1345. return(Status);
  1346. }
  1347. //+-------------------------------------------------------------------------
  1348. //
  1349. // Function: PAC_ReMarshallDelegationInfoWithTransitedService
  1350. //
  1351. // Synopsis: Updates an S4U_DELEGATION_INFO with a new
  1352. // transited service name
  1353. //
  1354. // Effects: allocates memory with MIDL_user_allocate
  1355. //
  1356. // Arguments:
  1357. //
  1358. // Requires:
  1359. //
  1360. // Returns:
  1361. //
  1362. // Notes:
  1363. //
  1364. //
  1365. //--------------------------------------------------------------------------
  1366. NTSTATUS
  1367. PAC_ReMarshallDelegationInfoWithTransitedService(
  1368. IN PS4U_DELEGATION_INFO OldDelegationInfo,
  1369. IN OPTIONAL PUNICODE_STRING TransitedService,
  1370. IN OPTIONAL PUNICODE_STRING NewTargetName,
  1371. OUT PBYTE * DelegationInfo,
  1372. OUT PULONG DelegationInfoSize
  1373. )
  1374. {
  1375. S4U_DELEGATION_INFO Delegation = {0};
  1376. NTSTATUS Status = STATUS_SUCCESS;
  1377. ULONG ListSize = OldDelegationInfo->TransitedListSize;
  1378. DsysAssert( OldDelegationInfo );
  1379. DsysAssert( DelegationInfo );
  1380. DsysAssert( DelegationInfoSize );
  1381. //
  1382. // Copy the original validation information
  1383. //
  1384. Delegation = *OldDelegationInfo;
  1385. if (ARGUMENT_PRESENT( NewTargetName ))
  1386. {
  1387. Delegation.S4U2proxyTarget.Buffer = NewTargetName->Buffer;
  1388. Delegation.S4U2proxyTarget.Length = NewTargetName->Length;
  1389. Delegation.S4U2proxyTarget.MaximumLength = NewTargetName->MaximumLength;
  1390. }
  1391. //
  1392. // If we've transitted a service, add an entry. Otherwise, just remarshall
  1393. // w/ new data.
  1394. //
  1395. if (ARGUMENT_PRESENT( TransitedService ))
  1396. {
  1397. ListSize++;
  1398. }
  1399. Delegation.S4UTransitedServices = (PUNICODE_STRING)MIDL_user_allocate(ListSize * sizeof(UNICODE_STRING));
  1400. if ( Delegation.S4UTransitedServices == NULL )
  1401. {
  1402. return STATUS_INSUFFICIENT_RESOURCES;
  1403. }
  1404. for ( ULONG i = 0 ; i < Delegation.TransitedListSize ; i++ )
  1405. {
  1406. Delegation.S4UTransitedServices[i] = (*OldDelegationInfo).S4UTransitedServices[i];
  1407. }
  1408. if (ARGUMENT_PRESENT( TransitedService ))
  1409. {
  1410. Delegation.S4UTransitedServices[Delegation.TransitedListSize] = *TransitedService;
  1411. }
  1412. Delegation.TransitedListSize = ListSize;
  1413. Status = PAC_EncodeS4UDelegationInformation(
  1414. &Delegation,
  1415. DelegationInfo,
  1416. DelegationInfoSize
  1417. );
  1418. MIDL_user_free( Delegation.S4UTransitedServices );
  1419. return Status;
  1420. }
  1421. //+-------------------------------------------------------------------------
  1422. //
  1423. // Function: PAC_UnmarshallS4UDelegationInfo
  1424. //
  1425. // Synopsis: unmarshals an S4U_DELEGATION_INFO structure
  1426. //
  1427. // Arguments:
  1428. //
  1429. // Requires:
  1430. //
  1431. // Returns:
  1432. //
  1433. // Notes:
  1434. //
  1435. //
  1436. //--------------------------------------------------------------------------
  1437. NTSTATUS
  1438. PAC_UnmarshallS4UDelegationInfo(
  1439. OUT PS4U_DELEGATION_INFO * S4UDelegationInfo,
  1440. IN PBYTE MarshalledInfo,
  1441. IN ULONG MarshalledInfoSize
  1442. )
  1443. {
  1444. NTSTATUS Status;
  1445. *S4UDelegationInfo = NULL;
  1446. Status = PAC_DecodeS4UDelegationInformation(
  1447. MarshalledInfo,
  1448. MarshalledInfoSize,
  1449. S4UDelegationInfo
  1450. );
  1451. return Status;
  1452. }
  1453. //+---------------------------------------------------------------------------
  1454. //
  1455. // Function: PAC_Init
  1456. //
  1457. // Synopsis: Creates a new PAC with the provided info
  1458. //
  1459. // Arguments: UserAll - UserAllInformation for the user
  1460. // GroupsBuffer - The buffer returned from a call to
  1461. // SamrGetGroupsForUser, contains all global groups
  1462. // LogonDomainId - Domain SID for the domain of this DC
  1463. // SignatureSize - Space to reserve for signatures. If zero,
  1464. // no signatures are added.
  1465. // ppPac - Receives a pac, allocated with MIDL_user_allocate
  1466. //
  1467. //
  1468. // History: 24-May-95 SuChang Created
  1469. //
  1470. // Notes:
  1471. //
  1472. //----------------------------------------------------------------------------
  1473. NTSTATUS
  1474. PAC_Init(
  1475. IN PSAMPR_USER_ALL_INFORMATION UserAll,
  1476. IN OPTIONAL PSAMPR_GET_GROUPS_BUFFER GroupsBuffer,
  1477. IN OPTIONAL PSID_AND_ATTRIBUTES_LIST ExtraGroups,
  1478. IN PSID LogonDomainId,
  1479. IN PUNICODE_STRING LogonDomainName,
  1480. IN PUNICODE_STRING LogonServer,
  1481. IN ULONG SignatureSize,
  1482. IN ULONG AdditionalDataCount,
  1483. IN PPAC_INFO_BUFFER * AdditionalData,
  1484. OUT PPACTYPE * ppPac
  1485. )
  1486. {
  1487. ULONG cbBytes = 0;
  1488. ULONG cPacBuffers = 0;
  1489. PPACTYPE pNewPac = NULL;
  1490. ULONG iBuffer = 0;
  1491. PBYTE ValidationInfo = NULL;
  1492. ULONG ValidationInfoSize = 0;
  1493. NTSTATUS Status;
  1494. PBYTE pDataStore;
  1495. ULONG Index;
  1496. *ppPac = NULL;
  1497. //
  1498. // We need to determine the number of bytes required to store the provided
  1499. // information. For each type of info, determine the required number of
  1500. // bytes to store that type of info. Then allocate a contiguous buffer
  1501. // for the PAC and store all the info into the buffer.
  1502. //
  1503. //
  1504. // First we will create the validation info buffer. We can copy it into
  1505. // the PAC later.
  1506. //
  1507. Status = PAC_MarshallValidationInfo(
  1508. UserAll,
  1509. GroupsBuffer,
  1510. ExtraGroups,
  1511. LogonDomainId,
  1512. LogonDomainName,
  1513. LogonServer,
  1514. FALSE, // don't include user parms
  1515. FALSE, // not a network logon
  1516. &ValidationInfo,
  1517. &ValidationInfoSize
  1518. );
  1519. if (!NT_SUCCESS(Status))
  1520. {
  1521. goto Cleanup;
  1522. }
  1523. //
  1524. // We need a PAC_INFO_BUFFER to store the validation info.
  1525. //
  1526. cbBytes += ROUND_UP_COUNT(ValidationInfoSize, ALIGN_QUAD);
  1527. cPacBuffers += 1;
  1528. for (Index = 0; Index < AdditionalDataCount ; Index++ )
  1529. {
  1530. cbBytes += ROUND_UP_COUNT(AdditionalData[Index]->cbBufferSize,ALIGN_QUAD);
  1531. cPacBuffers++;
  1532. }
  1533. //
  1534. // If signature size is non-zero, add in space for signatures.
  1535. //
  1536. if (SignatureSize != 0)
  1537. {
  1538. cPacBuffers += 2;
  1539. cbBytes += 2 * (ROUND_UP_COUNT(PAC_SIGNATURE_SIZE(SignatureSize), ALIGN_QUAD));
  1540. }
  1541. //
  1542. // We need space for the PAC structure itself. Because the PAC_INFO_BUFFER
  1543. // is defined to be an array, a sizeof(PAC) already includes the
  1544. // size of ANYSIZE_ARRAY PAC_INFO_BUFFERs so we can subtract some bytes off.
  1545. //
  1546. cbBytes += sizeof(PACTYPE) +
  1547. (cPacBuffers - ANYSIZE_ARRAY) * sizeof(PAC_INFO_BUFFER);
  1548. cbBytes = ROUND_UP_COUNT( cbBytes, ALIGN_QUAD );
  1549. pNewPac = (PPACTYPE) MIDL_user_allocate( cbBytes );
  1550. if (pNewPac == NULL)
  1551. {
  1552. Status = STATUS_INSUFFICIENT_RESOURCES;
  1553. goto Cleanup;
  1554. }
  1555. ZeroMemory( pNewPac, cbBytes );
  1556. pNewPac->Version = PAC_VERSION;
  1557. pNewPac->cBuffers = cPacBuffers;
  1558. //
  1559. // Store data in such a way that the variable length data of
  1560. // PAC_INFO_BUFFER are at the end of all the PAC info buffers.
  1561. //
  1562. pDataStore = (PBYTE)&(pNewPac->Buffers[pNewPac->cBuffers]);
  1563. pDataStore = (PBYTE) ROUND_UP_POINTER( pDataStore, ALIGN_QUAD );
  1564. //
  1565. // Save the PAC identity ...
  1566. //
  1567. pNewPac->Buffers[iBuffer].ulType = PAC_LOGON_INFO;
  1568. pNewPac->Buffers[iBuffer].cbBufferSize = ValidationInfoSize;
  1569. pNewPac->Buffers[iBuffer].Data = pDataStore;
  1570. CopyMemory(
  1571. pDataStore,
  1572. ValidationInfo,
  1573. ValidationInfoSize
  1574. );
  1575. pDataStore += pNewPac->Buffers[iBuffer].cbBufferSize;
  1576. pDataStore = (PBYTE) ROUND_UP_POINTER( pDataStore, ALIGN_QUAD );
  1577. iBuffer ++;
  1578. //
  1579. // Store the additional data
  1580. //
  1581. for (Index = 0; Index < AdditionalDataCount ; Index++ )
  1582. {
  1583. pNewPac->Buffers[iBuffer].ulType = AdditionalData[Index]->ulType;
  1584. pNewPac->Buffers[iBuffer].cbBufferSize = AdditionalData[Index]->cbBufferSize;
  1585. pNewPac->Buffers[iBuffer].Data = pDataStore;
  1586. CopyMemory(
  1587. pDataStore,
  1588. AdditionalData[Index]->Data,
  1589. AdditionalData[Index]->cbBufferSize
  1590. );
  1591. pDataStore += pNewPac->Buffers[iBuffer].cbBufferSize;
  1592. pDataStore = (PBYTE) ROUND_UP_POINTER( pDataStore, ALIGN_QUAD );
  1593. iBuffer ++;
  1594. }
  1595. //
  1596. // Store the signatures
  1597. //
  1598. if (SignatureSize != 0)
  1599. {
  1600. pNewPac->Buffers[iBuffer].ulType = PAC_SERVER_CHECKSUM;
  1601. pNewPac->Buffers[iBuffer].cbBufferSize = PAC_SIGNATURE_SIZE(SignatureSize);
  1602. pNewPac->Buffers[iBuffer].Data = pDataStore;
  1603. pDataStore += ROUND_UP_COUNT(PAC_SIGNATURE_SIZE(SignatureSize),ALIGN_QUAD);
  1604. iBuffer ++;
  1605. pNewPac->Buffers[iBuffer].ulType = PAC_PRIVSVR_CHECKSUM;
  1606. pNewPac->Buffers[iBuffer].cbBufferSize = PAC_SIGNATURE_SIZE(SignatureSize);
  1607. pNewPac->Buffers[iBuffer].Data = pDataStore;
  1608. pDataStore += ROUND_UP_COUNT(PAC_SIGNATURE_SIZE(SignatureSize), ALIGN_QUAD);
  1609. iBuffer ++;
  1610. }
  1611. *ppPac = pNewPac;
  1612. pNewPac = NULL;
  1613. Cleanup:
  1614. MIDL_user_free(ValidationInfo);
  1615. MIDL_user_free(pNewPac);
  1616. return(Status);
  1617. }
  1618. //+---------------------------------------------------------------------------
  1619. //
  1620. // Function: PAC_InitAndUpdateGroups
  1621. //
  1622. // Synopsis: Creates a new PAC from old validation info and a list of
  1623. // resource groupss.
  1624. //
  1625. // Arguments: OldValidationInfo - Old info from a previous PAC
  1626. // ResourceGroups - Resource groups in this domain
  1627. // OldPac - OldPac to copy data from
  1628. // ppPac - Receives a pac, allocated with MIDL_user_allocate
  1629. //
  1630. //
  1631. // History: 24-May-95 SuChang Created
  1632. //
  1633. // Notes:
  1634. //
  1635. //----------------------------------------------------------------------------
  1636. NTSTATUS
  1637. PAC_InitAndUpdateGroups(
  1638. IN PNETLOGON_VALIDATION_SAM_INFO3 OldValidationInfo,
  1639. IN PSAMPR_PSID_ARRAY ResourceGroups,
  1640. IN PPACTYPE OldPac,
  1641. OUT PPACTYPE * ppPac
  1642. )
  1643. {
  1644. ULONG cbBytes = 0;
  1645. ULONG cPacBuffers = 0;
  1646. PPACTYPE pNewPac = NULL;
  1647. ULONG iBuffer = 0;
  1648. PBYTE ValidationInfo = NULL;
  1649. ULONG ValidationInfoSize;
  1650. NTSTATUS Status;
  1651. PBYTE pDataStore;
  1652. ULONG Index;
  1653. *ppPac = NULL;
  1654. //
  1655. // We need to determine the number of bytes required to store the provided
  1656. // information. For each type of info, determine the required number of
  1657. // bytes to store that type of info. Then allocate a contiguous buffer
  1658. // for the PAC and store all the info into the buffer.
  1659. //
  1660. //
  1661. // First we will create the validation info buffer. We can copy it into
  1662. // the PAC later.
  1663. //
  1664. Status = PAC_ReMarshallValidationInfoWithGroups(
  1665. OldValidationInfo,
  1666. ResourceGroups,
  1667. &ValidationInfo,
  1668. &ValidationInfoSize
  1669. );
  1670. if (!NT_SUCCESS(Status))
  1671. {
  1672. goto Cleanup;
  1673. }
  1674. //
  1675. // We need a PAC_INFO_BUFFER to store the PAC_IDENTITY which
  1676. // contain the principal RID and the principal's domain GUID.
  1677. //
  1678. cbBytes += ROUND_UP_COUNT(ValidationInfoSize, ALIGN_QUAD);
  1679. cPacBuffers += 1;
  1680. for (Index = 0; Index < OldPac->cBuffers ; Index++ )
  1681. {
  1682. if (OldPac->Buffers[Index].ulType != PAC_LOGON_INFO)
  1683. {
  1684. cbBytes += ROUND_UP_COUNT(OldPac->Buffers[Index].cbBufferSize,ALIGN_QUAD);
  1685. cPacBuffers++;
  1686. }
  1687. }
  1688. //
  1689. // We need space for the PAC structure itself. Because the PAC_INFO_BUFFER
  1690. // is defined to be an array, a sizeof(PAC) already includes the
  1691. // size of ANYSIZE_ARRAY PAC_INFO_BUFFERs so we can subtract some bytes off.
  1692. //
  1693. cbBytes += sizeof(PACTYPE) +
  1694. (cPacBuffers - ANYSIZE_ARRAY) * sizeof(PAC_INFO_BUFFER);
  1695. cbBytes = ROUND_UP_COUNT( cbBytes, ALIGN_QUAD );
  1696. pNewPac = (PPACTYPE) MIDL_user_allocate( cbBytes );
  1697. if (pNewPac == NULL)
  1698. {
  1699. Status = STATUS_INSUFFICIENT_RESOURCES;
  1700. goto Cleanup;
  1701. }
  1702. //
  1703. // FESTER: overkill???
  1704. //
  1705. ZeroMemory( pNewPac, cbBytes );
  1706. pNewPac->cBuffers = cPacBuffers;
  1707. //
  1708. // Store data in such a way that the variable length data of
  1709. // PAC_INFO_BUFFER are at the end of all the PAC info buffers.
  1710. //
  1711. pDataStore = (PBYTE)&(pNewPac->Buffers[pNewPac->cBuffers]);
  1712. pDataStore = (PBYTE) ROUND_UP_POINTER( pDataStore, ALIGN_QUAD );
  1713. //
  1714. // Save the PAC identity ...
  1715. //
  1716. pNewPac->Buffers[iBuffer].ulType = PAC_LOGON_INFO;
  1717. pNewPac->Buffers[iBuffer].cbBufferSize = ValidationInfoSize;
  1718. pNewPac->Buffers[iBuffer].Data = pDataStore;
  1719. CopyMemory(
  1720. pDataStore,
  1721. ValidationInfo,
  1722. ValidationInfoSize
  1723. );
  1724. pDataStore += pNewPac->Buffers[iBuffer].cbBufferSize;
  1725. pDataStore = (PBYTE) ROUND_UP_POINTER( pDataStore, ALIGN_QUAD );
  1726. iBuffer ++;
  1727. //
  1728. // Store the additional data
  1729. //
  1730. for (Index = 0; Index < OldPac->cBuffers ; Index++ )
  1731. {
  1732. if (OldPac->Buffers[Index].ulType != PAC_LOGON_INFO)
  1733. {
  1734. pNewPac->Buffers[iBuffer].ulType = OldPac->Buffers[Index].ulType;
  1735. pNewPac->Buffers[iBuffer].cbBufferSize = OldPac->Buffers[Index].cbBufferSize;
  1736. pNewPac->Buffers[iBuffer].Data = pDataStore;
  1737. CopyMemory(
  1738. pDataStore,
  1739. OldPac->Buffers[Index].Data,
  1740. OldPac->Buffers[Index].cbBufferSize
  1741. );
  1742. pDataStore += pNewPac->Buffers[iBuffer].cbBufferSize;
  1743. pDataStore = (PBYTE) ROUND_UP_POINTER( pDataStore, ALIGN_QUAD );
  1744. iBuffer ++;
  1745. }
  1746. }
  1747. *ppPac = pNewPac;
  1748. pNewPac = NULL;
  1749. Cleanup:
  1750. if (ValidationInfo != NULL)
  1751. {
  1752. MIDL_user_free(ValidationInfo);
  1753. }
  1754. if (pNewPac != NULL)
  1755. {
  1756. MIDL_user_free(pNewPac);
  1757. }
  1758. return(Status);
  1759. }
  1760. //+---------------------------------------------------------------------------
  1761. //
  1762. // Function: PAC_RemoveSection
  1763. //
  1764. // Synopsis: Creates a new PAC from old validation info and a list of
  1765. // resource groupss.
  1766. //
  1767. // Arguments: OldPac - OldPac to copy data from
  1768. // InfoType - section type to remove
  1769. // ppPac - Receives a pac, allocated with MIDL_user_allocate
  1770. //
  1771. // History: 22-Aug-02 MarkPu Created
  1772. //
  1773. // Notes:
  1774. //
  1775. //----------------------------------------------------------------------------
  1776. NTSTATUS
  1777. PAC_RemoveSection(
  1778. IN PPACTYPE OldPac,
  1779. IN ULONG RemoveType,
  1780. OUT PPACTYPE * ppPac
  1781. )
  1782. {
  1783. NTSTATUS Status = STATUS_SUCCESS;
  1784. ULONG Index;
  1785. ULONG iBuffer = 0;
  1786. ULONG cbBytes = 0;
  1787. ULONG cPacBuffers = 0;
  1788. PPACTYPE pNewPac = NULL;
  1789. PBYTE pDataStore;
  1790. *ppPac = NULL;
  1791. //
  1792. // We need to determine the number of bytes required to store the PAC
  1793. // information. For each type of info, determine the required number of
  1794. // bytes to store that type of info. Then allocate a contiguous buffer
  1795. // for the PAC and store all the info into the buffer.
  1796. //
  1797. for (Index = 0; Index < OldPac->cBuffers ; Index++ )
  1798. {
  1799. if (OldPac->Buffers[Index].ulType != RemoveType)
  1800. {
  1801. cbBytes += ROUND_UP_COUNT(OldPac->Buffers[Index].cbBufferSize,ALIGN_QUAD);
  1802. cPacBuffers++;
  1803. }
  1804. }
  1805. if ( cPacBuffers == OldPac->cBuffers )
  1806. {
  1807. //
  1808. // Info type not found, thus not removed, thus nothing to do
  1809. //
  1810. Status = STATUS_NOT_FOUND;
  1811. goto Cleanup;
  1812. }
  1813. else if ( cPacBuffers == 0 )
  1814. {
  1815. Status = STATUS_SUCCESS;
  1816. goto Cleanup;
  1817. }
  1818. //
  1819. // We need space for the PAC structure itself. Because the PAC_INFO_BUFFER
  1820. // is defined to be an array, a sizeof(PAC) already includes the
  1821. // size of ANYSIZE_ARRAY PAC_INFO_BUFFERs so we can subtract some bytes off.
  1822. //
  1823. cbBytes += sizeof(PACTYPE) +
  1824. (cPacBuffers - ANYSIZE_ARRAY) * sizeof(PAC_INFO_BUFFER);
  1825. cbBytes = ROUND_UP_COUNT( cbBytes, ALIGN_QUAD );
  1826. pNewPac = (PPACTYPE) MIDL_user_allocate( cbBytes );
  1827. if (pNewPac == NULL)
  1828. {
  1829. Status = STATUS_INSUFFICIENT_RESOURCES;
  1830. goto Cleanup;
  1831. }
  1832. pNewPac->cBuffers = cPacBuffers;
  1833. //
  1834. // Store data in such a way that the variable length data of
  1835. // PAC_INFO_BUFFER are at the end of all the PAC info buffers.
  1836. //
  1837. pDataStore = (PBYTE)&(pNewPac->Buffers[pNewPac->cBuffers]);
  1838. pDataStore = (PBYTE) ROUND_UP_POINTER( pDataStore, ALIGN_QUAD );
  1839. //
  1840. // Copy the data over
  1841. //
  1842. for (Index = 0; Index < OldPac->cBuffers ; Index++ )
  1843. {
  1844. if (OldPac->Buffers[Index].ulType != RemoveType)
  1845. {
  1846. pNewPac->Buffers[iBuffer].ulType = OldPac->Buffers[Index].ulType;
  1847. pNewPac->Buffers[iBuffer].cbBufferSize = OldPac->Buffers[Index].cbBufferSize;
  1848. pNewPac->Buffers[iBuffer].Data = pDataStore;
  1849. CopyMemory(
  1850. pDataStore,
  1851. OldPac->Buffers[Index].Data,
  1852. OldPac->Buffers[Index].cbBufferSize
  1853. );
  1854. pDataStore += pNewPac->Buffers[iBuffer].cbBufferSize;
  1855. pDataStore = (PBYTE) ROUND_UP_POINTER( pDataStore, ALIGN_QUAD );
  1856. iBuffer ++;
  1857. }
  1858. }
  1859. *ppPac = pNewPac;
  1860. pNewPac = NULL;
  1861. Cleanup:
  1862. MIDL_user_free(pNewPac);
  1863. return Status;
  1864. }
  1865. //+---------------------------------------------------------------------------
  1866. //
  1867. // Function: PAC_InitAndUpdateTransitedServices
  1868. //
  1869. // Synopsis: Creates a new PAC from old delegation info and a new transited
  1870. // service name
  1871. //
  1872. // Arguments: OldDelegationInfo - Old delegation info from a previous PAC
  1873. // TransitedService - Name of transited service to add
  1874. // OldPac - OldPac to copy data from
  1875. // ppPac - Receives a pac, allocated with MIDL_user_allocate
  1876. //
  1877. //
  1878. // History: 09-May-01 MarkPu Created
  1879. //
  1880. // Notes:
  1881. //
  1882. //----------------------------------------------------------------------------
  1883. NTSTATUS
  1884. PAC_InitAndUpdateTransitedService(
  1885. IN PS4U_DELEGATION_INFO OldDelegationInfo,
  1886. IN OPTIONAL PUNICODE_STRING TransitedService,
  1887. IN OPTIONAL PUNICODE_STRING NewTargetName,
  1888. IN PPACTYPE OldPac,
  1889. OUT PPACTYPE * ppPac,
  1890. OUT PULONG NewDelegationInfoMarshalledSize,
  1891. OUT BYTE** NewDelegationInfoMarshalled
  1892. )
  1893. {
  1894. ULONG cbBytes = 0;
  1895. ULONG cPacBuffers = 0;
  1896. PPACTYPE pNewPac = NULL;
  1897. ULONG iBuffer = 0;
  1898. NTSTATUS Status;
  1899. PBYTE pDataStore;
  1900. ULONG Index;
  1901. *ppPac = NULL;
  1902. //
  1903. // We need to determine the number of bytes required to store the provided
  1904. // information. For each type of info, determine the required number of
  1905. // bytes to store that type of info. Then allocate a contiguous buffer
  1906. // for the PAC and store all the info into the buffer.
  1907. //
  1908. //
  1909. // First we will create the S4UDelegation buffer. We can copy it into
  1910. // the PAC later.
  1911. //
  1912. Status = PAC_ReMarshallDelegationInfoWithTransitedService(
  1913. OldDelegationInfo,
  1914. TransitedService,
  1915. NewTargetName,
  1916. NewDelegationInfoMarshalled,
  1917. NewDelegationInfoMarshalledSize
  1918. );
  1919. if (!NT_SUCCESS(Status))
  1920. {
  1921. goto Cleanup;
  1922. }
  1923. //
  1924. // Get the sizes of the old pac buffers. If there's delegation info in the
  1925. // old pac, skip it, as we'll be substituing our new version from above.
  1926. //
  1927. cbBytes += ROUND_UP_COUNT(*NewDelegationInfoMarshalledSize, ALIGN_QUAD);
  1928. cPacBuffers += 1;
  1929. for ( Index = 0; Index < OldPac->cBuffers; Index++ )
  1930. {
  1931. if ( OldPac->Buffers[Index].ulType != PAC_DELEGATION_INFO )
  1932. {
  1933. cbBytes += ROUND_UP_COUNT(OldPac->Buffers[Index].cbBufferSize,ALIGN_QUAD);
  1934. cPacBuffers++;
  1935. }
  1936. }
  1937. //
  1938. // We need space for the PAC structure itself. Because the PAC_INFO_BUFFER
  1939. // is defined to be an array, a sizeof(PAC) already includes the
  1940. // size of ANYSIZE_ARRAY PAC_INFO_BUFFERs so we can subtract some bytes off.
  1941. //
  1942. cbBytes += sizeof(PACTYPE) +
  1943. (cPacBuffers - ANYSIZE_ARRAY) * sizeof(PAC_INFO_BUFFER);
  1944. cbBytes = ROUND_UP_COUNT( cbBytes, ALIGN_QUAD );
  1945. pNewPac = (PPACTYPE) MIDL_user_allocate( cbBytes );
  1946. if (pNewPac == NULL)
  1947. {
  1948. Status = STATUS_INSUFFICIENT_RESOURCES;
  1949. goto Cleanup;
  1950. }
  1951. ZeroMemory( pNewPac, cbBytes );
  1952. pNewPac->cBuffers = cPacBuffers;
  1953. //
  1954. // Store data in such a way that the variable length data of
  1955. // PAC_INFO_BUFFER are at the end of all the PAC info buffers.
  1956. //
  1957. pDataStore = (PBYTE)&(pNewPac->Buffers[pNewPac->cBuffers]);
  1958. pDataStore = (PBYTE) ROUND_UP_POINTER( pDataStore, ALIGN_QUAD );
  1959. //
  1960. // Save the S4U identity ...
  1961. //
  1962. pNewPac->Buffers[iBuffer].ulType = PAC_DELEGATION_INFO;
  1963. pNewPac->Buffers[iBuffer].cbBufferSize = *NewDelegationInfoMarshalledSize;
  1964. pNewPac->Buffers[iBuffer].Data = pDataStore;
  1965. CopyMemory(
  1966. pDataStore,
  1967. *NewDelegationInfoMarshalled,
  1968. *NewDelegationInfoMarshalledSize
  1969. );
  1970. pDataStore += pNewPac->Buffers[iBuffer].cbBufferSize;
  1971. pDataStore = (PBYTE) ROUND_UP_POINTER( pDataStore, ALIGN_QUAD );
  1972. iBuffer ++;
  1973. //
  1974. // Store the additional data
  1975. //
  1976. for (Index = 0; Index < OldPac->cBuffers ; Index++ )
  1977. {
  1978. if ( OldPac->Buffers[Index].ulType != PAC_DELEGATION_INFO )
  1979. {
  1980. pNewPac->Buffers[iBuffer].ulType = OldPac->Buffers[Index].ulType;
  1981. pNewPac->Buffers[iBuffer].cbBufferSize = OldPac->Buffers[Index].cbBufferSize;
  1982. pNewPac->Buffers[iBuffer].Data = pDataStore;
  1983. CopyMemory(
  1984. pDataStore,
  1985. OldPac->Buffers[Index].Data,
  1986. OldPac->Buffers[Index].cbBufferSize
  1987. );
  1988. pDataStore += pNewPac->Buffers[iBuffer].cbBufferSize;
  1989. pDataStore = (PBYTE) ROUND_UP_POINTER( pDataStore, ALIGN_QUAD );
  1990. iBuffer ++;
  1991. }
  1992. }
  1993. *ppPac = pNewPac;
  1994. pNewPac = NULL;
  1995. Cleanup:
  1996. MIDL_user_free(pNewPac);
  1997. return(Status);
  1998. }
  1999. //+---------------------------------------------------------------------------
  2000. //
  2001. // Function: PAC_Find
  2002. //
  2003. // Synopsis: Finds a type of PAC info buffer in the given PAC.
  2004. // If pElem is NULL, the first buffer found matching the
  2005. // specified type is returned. Otherwise, the next buffer
  2006. // after pElem found matching that type is returned.
  2007. //
  2008. // Arguments:
  2009. //
  2010. // History: 01-June-95 SuChang Created
  2011. //
  2012. // Notes:
  2013. //
  2014. //----------------------------------------------------------------------------
  2015. PPAC_INFO_BUFFER
  2016. PAC_Find( IN PPACTYPE pPac,
  2017. IN ULONG ulType,
  2018. PPAC_INFO_BUFFER pElem)
  2019. {
  2020. PAC_INFO_BUFFER *pTemp = NULL, *pEnd;
  2021. if (pPac)
  2022. {
  2023. pEnd = &(pPac->Buffers[pPac->cBuffers]);
  2024. if (pElem)
  2025. {
  2026. pTemp = pElem + 1;
  2027. }
  2028. else
  2029. {
  2030. pTemp = &(pPac->Buffers[0]);
  2031. }
  2032. while ( pTemp < pEnd && pTemp->ulType != ulType )
  2033. {
  2034. pTemp++;
  2035. }
  2036. if (pTemp >= pEnd)
  2037. {
  2038. // element not found in the PAC
  2039. pTemp = NULL;
  2040. }
  2041. }
  2042. return (pTemp);
  2043. }