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.

1925 lines
44 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1997.
  5. //
  6. // File: samhooks.cxx
  7. //
  8. // Contents: SAM Hooks for security packages
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 3-10-97 RichardW Created
  15. //
  16. //----------------------------------------------------------------------------
  17. #include <lsapch.hxx>
  18. #include <lmcons.h>
  19. #include <ntsam.h>
  20. #include <samrpc.h>
  21. #include <samisrv.h>
  22. #include <ntmsv1_0.h>
  23. #include <pac.hxx>
  24. #include "samhooks.hxx"
  25. //+---------------------------------------------------------------------------
  26. //
  27. // Function: LsapMakeDomainRelativeSid
  28. //
  29. // Synopsis: Build a new SID based on a domain SID and a RID
  30. //
  31. // Arguments: [DomainId] --
  32. // [RelativeId] --
  33. //
  34. // History: 3-11-97 RichardW Created
  35. //
  36. // Notes:
  37. //
  38. //----------------------------------------------------------------------------
  39. PSID
  40. LsapMakeDomainRelativeSid(
  41. IN PSID DomainId,
  42. IN ULONG RelativeId
  43. )
  44. {
  45. UCHAR DomainIdSubAuthorityCount;
  46. ULONG Size;
  47. PSID Sid;
  48. if ( !DomainId ) {
  49. return( NULL );
  50. }
  51. //
  52. // Allocate a Sid which has one more sub-authority than the domain ID.
  53. //
  54. DomainIdSubAuthorityCount = *(RtlSubAuthorityCountSid( DomainId ));
  55. Size = RtlLengthRequiredSid(DomainIdSubAuthorityCount+1);
  56. if ((Sid = LsapAllocateLsaHeap( Size )) == NULL ) {
  57. return NULL;
  58. }
  59. //
  60. // Initialize the new SID to have the same inital value as the
  61. // domain ID.
  62. //
  63. if ( !NT_SUCCESS( RtlCopySid( Size, Sid, DomainId ) ) ) {
  64. LsapFreeLsaHeap( Sid );
  65. return NULL;
  66. }
  67. //
  68. // Adjust the sub-authority count and
  69. // add the relative Id unique to the newly allocated SID
  70. //
  71. (*(RtlSubAuthorityCountSid( Sid ))) ++;
  72. *RtlSubAuthoritySid( Sid, DomainIdSubAuthorityCount ) = RelativeId;
  73. return Sid;
  74. }
  75. PSID
  76. LsapMakeDomainRelativeSid2(
  77. IN PSID DomainId,
  78. IN ULONG RelativeId
  79. )
  80. {
  81. UCHAR DomainIdSubAuthorityCount;
  82. ULONG Size;
  83. PSID Sid;
  84. if ( !DomainId ) {
  85. return( NULL );
  86. }
  87. //
  88. // Allocate a Sid which has one more sub-authority than the domain ID.
  89. //
  90. DomainIdSubAuthorityCount = *(RtlSubAuthorityCountSid( DomainId ));
  91. Size = RtlLengthRequiredSid(DomainIdSubAuthorityCount+1);
  92. if ((Sid = LsapAllocatePrivateHeap( Size )) == NULL ) {
  93. return NULL;
  94. }
  95. //
  96. // Initialize the new SID to have the same inital value as the
  97. // domain ID.
  98. //
  99. if ( !NT_SUCCESS( RtlCopySid( Size, Sid, DomainId ) ) ) {
  100. LsapFreePrivateHeap( Sid );
  101. return NULL;
  102. }
  103. //
  104. // Adjust the sub-authority count and
  105. // add the relative Id unique to the newly allocated SID
  106. //
  107. (*(RtlSubAuthorityCountSid( Sid ))) ++;
  108. *RtlSubAuthoritySid( Sid, DomainIdSubAuthorityCount ) = RelativeId;
  109. return Sid;
  110. }
  111. //+-------------------------------------------------------------------------
  112. //
  113. // Function: LsapDuplicateSid
  114. //
  115. // Synopsis: Duplicates a SID
  116. //
  117. // Effects: allocates memory with LsaFunctions.AllocateLsaHeap
  118. //
  119. // Arguments: DestinationSid - Receives a copy of the SourceSid
  120. // SourceSid - SID to copy
  121. //
  122. // Requires:
  123. //
  124. // Returns: STATUS_SUCCESS - the copy succeeded
  125. // STATUS_INSUFFICIENT_RESOURCES - the call to allocate memory
  126. // failed
  127. //
  128. // Notes:
  129. //
  130. //
  131. //--------------------------------------------------------------------------
  132. NTSTATUS
  133. LsapDuplicateSid(
  134. OUT PSID * DestinationSid,
  135. IN PSID SourceSid
  136. )
  137. {
  138. ULONG SidSize;
  139. DsysAssert(RtlValidSid(SourceSid));
  140. SidSize = RtlLengthSid(SourceSid);
  141. *DestinationSid = (PSID) LsapAllocateLsaHeap( SidSize );
  142. if (*DestinationSid == NULL)
  143. {
  144. return(STATUS_INSUFFICIENT_RESOURCES);
  145. }
  146. RtlCopyMemory(
  147. *DestinationSid,
  148. SourceSid,
  149. SidSize
  150. );
  151. return(STATUS_SUCCESS);
  152. }
  153. NTSTATUS
  154. LsapDuplicateSid2(
  155. OUT PSID * DestinationSid,
  156. IN PSID SourceSid
  157. )
  158. {
  159. ULONG SidSize;
  160. DsysAssert(RtlValidSid(SourceSid));
  161. SidSize = RtlLengthSid(SourceSid);
  162. *DestinationSid = (PSID) LsapAllocatePrivateHeap( SidSize );
  163. if (*DestinationSid == NULL)
  164. {
  165. return(STATUS_INSUFFICIENT_RESOURCES);
  166. }
  167. RtlCopyMemory(
  168. *DestinationSid,
  169. SourceSid,
  170. SidSize
  171. );
  172. return(STATUS_SUCCESS);
  173. }
  174. //+---------------------------------------------------------------------------
  175. //
  176. // Function: LsapCaptureSamInfo
  177. //
  178. // Synopsis: Capture current SAM info for building a PAC
  179. //
  180. // Arguments: [DomainSid] -- Returns domain SID
  181. // [DomainName] -- returns domain name
  182. // [MachineName] -- returns current machine name
  183. //
  184. // History: 3-14-97 RichardW Created
  185. //
  186. // Notes:
  187. //
  188. //----------------------------------------------------------------------------
  189. NTSTATUS
  190. LsapCaptureSamInfo(
  191. PSID * DomainSid,
  192. PUNICODE_STRING DomainName,
  193. PUNICODE_STRING MachineName
  194. )
  195. {
  196. NTSTATUS Status;
  197. PLSAPR_POLICY_INFORMATION PolicyInformation = NULL;
  198. UNICODE_STRING String;
  199. WCHAR LocalMachineName[ CNLEN + 1 ];
  200. DWORD Size ;
  201. PSID Sid ;
  202. Size = CNLEN + 1;
  203. if ( GetComputerName( LocalMachineName, &Size ) )
  204. {
  205. RtlInitUnicodeString( &String, LocalMachineName );
  206. Status = LsapDuplicateString( MachineName, &String );
  207. }
  208. else
  209. {
  210. MachineName->Buffer = (PWSTR) LsapAllocateLsaHeap( Size *
  211. sizeof(WCHAR) + 2 );
  212. if ( MachineName->Buffer )
  213. {
  214. MachineName->MaximumLength = (USHORT) (Size * sizeof(WCHAR) + 2);
  215. GetComputerName( MachineName->Buffer, &Size );
  216. MachineName->Length = (USHORT) (Size * sizeof( WCHAR ) );;
  217. Status = STATUS_SUCCESS ;
  218. }
  219. else
  220. {
  221. Status = STATUS_NO_MEMORY ;
  222. }
  223. }
  224. if ( !NT_SUCCESS( Status ) )
  225. {
  226. DebugLog(( DEB_ERROR, "Failed to get computer name, %x\n", Status ));
  227. goto Cleanup;
  228. }
  229. Status = LsarQueryInformationPolicy(
  230. LsapPolicyHandle,
  231. PolicyAccountDomainInformation,
  232. &PolicyInformation
  233. );
  234. if (!NT_SUCCESS(Status))
  235. {
  236. DebugLog((DEB_ERROR,"Failed to query information policy: 0x%x\n",Status));
  237. goto Cleanup;
  238. }
  239. Status = LsapDuplicateString(
  240. DomainName,
  241. (PUNICODE_STRING) &PolicyInformation->PolicyAccountDomainInfo.DomainName
  242. );
  243. if (!NT_SUCCESS(Status))
  244. {
  245. goto Cleanup;
  246. }
  247. Sid = (PSID) LocalAlloc(0, RtlLengthSid(
  248. PolicyInformation->PolicyAccountDomainInfo.DomainSid)
  249. );
  250. if ( Sid == NULL )
  251. {
  252. Status = STATUS_INSUFFICIENT_RESOURCES;
  253. goto Cleanup;
  254. }
  255. RtlCopyMemory(
  256. Sid,
  257. PolicyInformation->PolicyAccountDomainInfo.DomainSid,
  258. RtlLengthSid(PolicyInformation->PolicyAccountDomainInfo.DomainSid)
  259. );
  260. *DomainSid = Sid ;
  261. Cleanup:
  262. if (PolicyInformation != NULL)
  263. {
  264. LsaIFree_LSAPR_POLICY_INFORMATION(
  265. PolicyPrimaryDomainInformation,
  266. PolicyInformation
  267. );
  268. }
  269. return( Status );
  270. }
  271. //+---------------------------------------------------------------------------
  272. //
  273. // Function: LsaOpenSamUser
  274. //
  275. // Synopsis: Opens a handle to the SAM user as specified by Name and NameType
  276. //
  277. // Arguments: [Name] -- Name of user to find
  278. // [NameType] -- SAM or AlternateId
  279. // [Prefix] -- Prefix for AlternateId lookup
  280. // [AllowGuest] -- Open guest if user not found
  281. // [Reserved] --
  282. // [UserHandle] -- Returned user handle
  283. //
  284. // History: 3-14-97 RichardW Created
  285. //
  286. // Notes:
  287. //
  288. //----------------------------------------------------------------------------
  289. NTSTATUS
  290. NTAPI
  291. LsaOpenSamUser(
  292. PSECURITY_STRING Name,
  293. SECPKG_NAME_TYPE NameType,
  294. PSECURITY_STRING Prefix,
  295. BOOLEAN AllowGuest,
  296. ULONG Reserved,
  297. PVOID * UserHandle
  298. )
  299. {
  300. NTSTATUS Status = STATUS_NOT_IMPLEMENTED ;
  301. SECURITY_STRING CombinedName ;
  302. PSECURITY_STRING EffectiveName ;
  303. SAMPR_ULONG_ARRAY RelativeIdArray;
  304. SAMPR_ULONG_ARRAY UseArray;
  305. UNICODE_STRING TempString;
  306. RelativeIdArray.Element = NULL;
  307. UseArray.Element = NULL;
  308. if ( NameType == SecNameAlternateId )
  309. {
  310. if ( !Prefix )
  311. {
  312. return STATUS_INVALID_PARAMETER ;
  313. }
  314. CombinedName.MaximumLength = Name->Length + Prefix->Length +
  315. 2 * sizeof( WCHAR );
  316. CombinedName.Length = CombinedName.MaximumLength - sizeof( WCHAR );
  317. CombinedName.Buffer = (PWSTR) LsapAllocateLsaHeap( CombinedName.MaximumLength );
  318. if ( CombinedName.Buffer )
  319. {
  320. CopyMemory( CombinedName.Buffer, Prefix->Buffer, Prefix->Length );
  321. CombinedName.Buffer[ Prefix->Length / sizeof( WCHAR ) ] = L':';
  322. CopyMemory( &CombinedName.Buffer[ Prefix->Length / sizeof( WCHAR ) + 1],
  323. Name->Buffer,
  324. Name->Length + sizeof( WCHAR ) );
  325. EffectiveName = &CombinedName ;
  326. }
  327. else
  328. {
  329. return SEC_E_INSUFFICIENT_MEMORY ;
  330. }
  331. }
  332. else
  333. {
  334. EffectiveName = Name ;
  335. }
  336. if ( NameType == SecNameSamCompatible )
  337. {
  338. Status = SamrLookupNamesInDomain(
  339. LsapAccountDomainHandle,
  340. 1,
  341. (PRPC_UNICODE_STRING) Name,
  342. &RelativeIdArray,
  343. &UseArray
  344. );
  345. if (!NT_SUCCESS(Status))
  346. {
  347. DebugLog((DEB_ERROR,"Failed to lookup name %wZ in domain: 0x%x\n",
  348. Name, Status));
  349. goto CheckGuest ;
  350. }
  351. if (UseArray.Element[0] != SidTypeUser)
  352. {
  353. Status = STATUS_NO_SUCH_USER;
  354. goto CheckGuest ;
  355. }
  356. Status = SamrOpenUser(
  357. LsapAccountDomainHandle,
  358. USER_ALL_ACCESS,
  359. RelativeIdArray.Element[0],
  360. UserHandle
  361. );
  362. SamIFree_SAMPR_ULONG_ARRAY( &RelativeIdArray );
  363. SamIFree_SAMPR_ULONG_ARRAY( &UseArray );
  364. RelativeIdArray.Element = NULL;
  365. UseArray.Element = NULL;
  366. if (!NT_SUCCESS(Status))
  367. {
  368. DebugLog((DEB_ERROR,"Failed to open user by relative ID: 0x%x\n",Status));
  369. goto CheckGuest ;
  370. }
  371. }
  372. else if ( NameType == SecNameAlternateId )
  373. {
  374. Status = SamIOpenUserByAlternateId(
  375. LsapAccountDomainHandle,
  376. USER_ALL_ACCESS,
  377. EffectiveName,
  378. UserHandle );
  379. if ( !NT_SUCCESS( Status ) )
  380. {
  381. DebugLog(( DEB_TRACE_SAM, "Failed to find user by alternate id, %x\n", Status ));
  382. goto CheckGuest ;
  383. }
  384. }
  385. else
  386. {
  387. Status = STATUS_NOT_IMPLEMENTED ;
  388. AllowGuest = FALSE ;
  389. }
  390. if ( RelativeIdArray.Element )
  391. {
  392. SamIFree_SAMPR_ULONG_ARRAY( &RelativeIdArray );
  393. RelativeIdArray.Element = NULL;
  394. }
  395. if ( UseArray.Element )
  396. {
  397. SamIFree_SAMPR_ULONG_ARRAY( &UseArray );
  398. UseArray.Element = NULL;
  399. }
  400. if ( EffectiveName == &CombinedName )
  401. {
  402. LsapFreeLsaHeap( EffectiveName->Buffer );
  403. }
  404. return Status ;
  405. CheckGuest:
  406. if ( RelativeIdArray.Element )
  407. {
  408. SamIFree_SAMPR_ULONG_ARRAY( &RelativeIdArray );
  409. RelativeIdArray.Element = NULL;
  410. }
  411. if ( UseArray.Element )
  412. {
  413. SamIFree_SAMPR_ULONG_ARRAY( &UseArray );
  414. UseArray.Element = NULL;
  415. }
  416. if ( AllowGuest )
  417. {
  418. Status = SamrOpenUser(
  419. LsapAccountDomainHandle,
  420. USER_ALL_ACCESS,
  421. DOMAIN_USER_RID_GUEST,
  422. UserHandle );
  423. }
  424. if ( EffectiveName == &CombinedName )
  425. {
  426. LsapFreeLsaHeap( EffectiveName->Buffer );
  427. }
  428. return Status ;
  429. }
  430. //+---------------------------------------------------------------------------
  431. //
  432. // Function: LsaCloseSamUser
  433. //
  434. // Synopsis: Close a SAM user opened by LsaOpenSamUser
  435. //
  436. // Arguments: [UserHandle] --
  437. //
  438. // History: 3-14-97 RichardW Created
  439. //
  440. // Notes:
  441. //
  442. //----------------------------------------------------------------------------
  443. NTSTATUS
  444. NTAPI
  445. LsaCloseSamUser(
  446. PVOID UserHandle
  447. )
  448. {
  449. return SamrCloseHandle( &((SAMPR_HANDLE) UserHandle) );
  450. }
  451. //+---------------------------------------------------------------------------
  452. //
  453. // Function: LsaGetUserCredentials
  454. //
  455. // Synopsis: Pull the creds for the user
  456. //
  457. // Arguments: [UserHandle] --
  458. // [PrimaryCreds] --
  459. // [PrimaryCredsSize] --
  460. // [SupplementalCreds] --
  461. // [SupplementalCredsSize] --
  462. //
  463. // Requires:
  464. //
  465. // Returns:
  466. //
  467. // Signals:
  468. //
  469. // Modifies:
  470. //
  471. // Algorithm:
  472. //
  473. // History: 3-14-97 RichardW Created
  474. //
  475. // Notes:
  476. //
  477. //----------------------------------------------------------------------------
  478. NTSTATUS
  479. NTAPI
  480. LsaGetUserCredentials(
  481. PVOID UserHandle,
  482. PVOID * PrimaryCreds,
  483. PULONG PrimaryCredsSize,
  484. PVOID * SupplementalCreds,
  485. PULONG SupplementalCredsSize
  486. )
  487. {
  488. return SEC_E_UNSUPPORTED_FUNCTION ;
  489. }
  490. NTSTATUS
  491. NTAPI
  492. LsaGetUserAuthData(
  493. PVOID UserHandle,
  494. PUCHAR * UserAuthData,
  495. PULONG UserAuthDataSize
  496. )
  497. {
  498. PSAMPR_USER_ALL_INFORMATION UserAll = NULL ;
  499. PSAMPR_USER_INFO_BUFFER UserAllInfo = NULL ;
  500. NTSTATUS Status ;
  501. PPACTYPE pNewPac = NULL ;
  502. PSAMPR_GET_GROUPS_BUFFER GroupsBuffer = NULL ;
  503. PPACTYPE Pac ;
  504. UNICODE_STRING Domain ;
  505. UNICODE_STRING Machine ;
  506. PSID Sid ;
  507. Sid = NULL ;
  508. Machine.Buffer = NULL ;
  509. Domain.Buffer = NULL ;
  510. *UserAuthData = NULL ;
  511. Status = SamrQueryInformationUser(
  512. (SAMPR_HANDLE) UserHandle,
  513. UserAllInformation,
  514. &UserAllInfo );
  515. if ( !NT_SUCCESS( Status ) )
  516. {
  517. return( Status );
  518. }
  519. UserAll = &UserAllInfo->All ;
  520. if ( UserAll->UserAccountControl & USER_ACCOUNT_DISABLED )
  521. {
  522. Status = STATUS_ACCOUNT_DISABLED ;
  523. goto GetPac_Cleanup;
  524. }
  525. Status = SamrGetGroupsForUser(
  526. (SAMPR_HANDLE) UserHandle,
  527. &GroupsBuffer );
  528. if ( !NT_SUCCESS( Status ) )
  529. {
  530. goto GetPac_Cleanup ;
  531. }
  532. Status = LsapCaptureSamInfo( &Sid, &Domain, &Machine );
  533. if ( !NT_SUCCESS( Status ) )
  534. {
  535. goto GetPac_Cleanup ;
  536. }
  537. Status = PAC_Init( UserAll,
  538. GroupsBuffer,
  539. NULL, // no extra groups
  540. Sid,
  541. &Domain,
  542. &Machine,
  543. 0, // no signature
  544. 0, // no additional data
  545. NULL, // no additional data
  546. &Pac );
  547. if ( !NT_SUCCESS( Status ) )
  548. {
  549. goto GetPac_Cleanup ;
  550. }
  551. *UserAuthDataSize = PAC_GetSize( Pac );
  552. *UserAuthData = (PUCHAR) LsapAllocateLsaHeap( *UserAuthDataSize );
  553. if ( *UserAuthData )
  554. {
  555. PAC_Marshal( Pac, *UserAuthDataSize, *UserAuthData );
  556. }
  557. else
  558. {
  559. Status = SEC_E_INSUFFICIENT_MEMORY ;
  560. }
  561. MIDL_user_free( Pac );
  562. GetPac_Cleanup:
  563. if ( UserAllInfo )
  564. {
  565. SamIFree_SAMPR_USER_INFO_BUFFER( UserAllInfo, UserAllInformation );
  566. }
  567. if ( GroupsBuffer )
  568. {
  569. SamIFree_SAMPR_GET_GROUPS_BUFFER( GroupsBuffer );
  570. }
  571. if ( Sid )
  572. {
  573. LsapFreeLsaHeap( Sid );
  574. }
  575. if ( Domain.Buffer )
  576. {
  577. LsapFreeLsaHeap( Domain.Buffer );
  578. }
  579. if ( Machine.Buffer )
  580. {
  581. LsapFreeLsaHeap( Machine.Buffer );
  582. }
  583. return( Status );
  584. }
  585. //+-------------------------------------------------------------------------
  586. //
  587. // Function: LsapMakeTokenInformationV1
  588. //
  589. // Synopsis: This routine makes copies of all the pertinent
  590. // information from the UserInfo and generates a
  591. // LSA_TOKEN_INFORMATION_V1 data structure.
  592. //
  593. // Effects:
  594. //
  595. // Arguments:
  596. //
  597. // UserInfo - Contains the validation information which is
  598. // to be copied into the TokenInformation.
  599. //
  600. // TokenInformation - Returns a pointer to a properly Version 1 token
  601. // information structures. The structure and individual fields are
  602. // allocated properly as described in ntlsa.h.
  603. //
  604. // Requires:
  605. //
  606. // Returns: STATUS_SUCCESS - Indicates the service completed successfully.
  607. //
  608. // STATUS_INSUFFICIENT_RESOURCES - This error indicates that
  609. // the logon could not be completed because the client
  610. // does not have sufficient quota to allocate the return
  611. // buffer.
  612. //
  613. // Notes: stolen from kerberos\client2\krbtoken.cxx, where it was
  614. // stolen from msv1_0\nlp.c:NlpMakeTokenInformationV1
  615. //
  616. //
  617. //--------------------------------------------------------------------------
  618. NTSTATUS
  619. LsapMakeTokenInformationV1(
  620. IN PNETLOGON_VALIDATION_SAM_INFO3 UserInfo,
  621. OUT PLSA_TOKEN_INFORMATION_V1 *TokenInformation
  622. )
  623. {
  624. NTSTATUS Status;
  625. PLSA_TOKEN_INFORMATION_V1 V1;
  626. ULONG Size, i;
  627. //
  628. // Allocate the structure itself
  629. //
  630. Size = (ULONG)sizeof(LSA_TOKEN_INFORMATION_V1);
  631. V1 = (PLSA_TOKEN_INFORMATION_V1) LsapAllocateLsaHeap( Size );
  632. if ( V1 == NULL ) {
  633. return STATUS_INSUFFICIENT_RESOURCES;
  634. }
  635. RtlZeroMemory(
  636. V1,
  637. Size
  638. );
  639. V1->User.User.Sid = NULL;
  640. V1->Groups = NULL;
  641. V1->PrimaryGroup.PrimaryGroup = NULL;
  642. OLD_TO_NEW_LARGE_INTEGER( UserInfo->KickOffTime, V1->ExpirationTime );
  643. //
  644. // Make a copy of the user SID (a required field)
  645. //
  646. V1->User.User.Attributes = 0;
  647. //
  648. // Allocate an array to hold the groups
  649. //
  650. Size = ( (ULONG)sizeof(TOKEN_GROUPS)
  651. + (UserInfo->GroupCount * (ULONG)sizeof(SID_AND_ATTRIBUTES))
  652. - (ANYSIZE_ARRAY * (ULONG)sizeof(SID_AND_ATTRIBUTES))
  653. );
  654. //
  655. // If there are extra SIDs, add space for them
  656. //
  657. if (UserInfo->UserFlags & LOGON_EXTRA_SIDS) {
  658. Size += UserInfo->SidCount * (ULONG)sizeof(SID_AND_ATTRIBUTES);
  659. }
  660. //
  661. // If there are resource groups, add space for them
  662. //
  663. if (UserInfo->UserFlags & LOGON_RESOURCE_GROUPS) {
  664. Size += UserInfo->ResourceGroupCount * (ULONG)sizeof(SID_AND_ATTRIBUTES);
  665. if ((UserInfo->ResourceGroupCount != 0) &&
  666. ((UserInfo->ResourceGroupIds == NULL) ||
  667. (UserInfo->ResourceGroupDomainSid == NULL)))
  668. {
  669. Status = STATUS_INVALID_PARAMETER;
  670. goto Cleanup;
  671. }
  672. }
  673. V1->Groups = (PTOKEN_GROUPS) LsapAllocatePrivateHeap( Size );
  674. if ( V1->Groups == NULL ) {
  675. Status = STATUS_INSUFFICIENT_RESOURCES;
  676. goto Cleanup;
  677. }
  678. RtlZeroMemory(
  679. V1->Groups,
  680. Size
  681. );
  682. V1->Groups->GroupCount = 0;
  683. //
  684. // Start copying SIDs into the structure
  685. //
  686. //
  687. // If the UserId is non-zero, then it contians the users RID.
  688. //
  689. if ( UserInfo->UserId ) {
  690. V1->User.User.Sid =
  691. LsapMakeDomainRelativeSid( UserInfo->LogonDomainId,
  692. UserInfo->UserId );
  693. if( V1->User.User.Sid == NULL ) {
  694. Status = STATUS_INSUFFICIENT_RESOURCES;
  695. goto Cleanup;
  696. }
  697. }
  698. //
  699. // Make a copy of the primary group (a required field).
  700. //
  701. V1->PrimaryGroup.PrimaryGroup = LsapMakeDomainRelativeSid(
  702. UserInfo->LogonDomainId,
  703. UserInfo->PrimaryGroupId );
  704. if ( V1->PrimaryGroup.PrimaryGroup == NULL ) {
  705. Status = STATUS_INSUFFICIENT_RESOURCES;
  706. goto Cleanup;
  707. }
  708. //
  709. // Copy over all the groups passed as RIDs
  710. //
  711. for ( i=0; i < UserInfo->GroupCount; i++ ) {
  712. V1->Groups->Groups[V1->Groups->GroupCount].Attributes = UserInfo->GroupIds[i].Attributes;
  713. V1->Groups->Groups[V1->Groups->GroupCount].Sid = LsapMakeDomainRelativeSid2(
  714. UserInfo->LogonDomainId,
  715. UserInfo->GroupIds[i].RelativeId );
  716. if( V1->Groups->Groups[V1->Groups->GroupCount].Sid == NULL ) {
  717. Status = STATUS_INSUFFICIENT_RESOURCES;
  718. goto Cleanup;
  719. }
  720. V1->Groups->GroupCount++;
  721. }
  722. //
  723. // Add in the extra SIDs
  724. //
  725. if (UserInfo->UserFlags & LOGON_EXTRA_SIDS) {
  726. ULONG index = 0;
  727. //
  728. // If the user SID wasn't passed as a RID, it is the first
  729. // SID.
  730. //
  731. if ( !V1->User.User.Sid ) {
  732. if ( UserInfo->SidCount <= index ) {
  733. Status = STATUS_INSUFFICIENT_LOGON_INFO;
  734. goto Cleanup;
  735. }
  736. Status = LsapDuplicateSid(
  737. &V1->User.User.Sid,
  738. UserInfo->ExtraSids[index].Sid
  739. );
  740. if (!NT_SUCCESS(Status)) {
  741. goto Cleanup;
  742. }
  743. index++;
  744. }
  745. //
  746. // Copy over all additional SIDs as groups.
  747. //
  748. for ( ; index < UserInfo->SidCount; index++ ) {
  749. V1->Groups->Groups[V1->Groups->GroupCount].Attributes =
  750. UserInfo->ExtraSids[index].Attributes;
  751. Status = LsapDuplicateSid2(
  752. &V1->Groups->Groups[V1->Groups->GroupCount].Sid,
  753. UserInfo->ExtraSids[index].Sid
  754. );
  755. if (!NT_SUCCESS(Status) ) {
  756. goto Cleanup;
  757. }
  758. V1->Groups->GroupCount++;
  759. }
  760. }
  761. //
  762. // Check to see if any resouce groups exist
  763. //
  764. if (UserInfo->UserFlags & LOGON_RESOURCE_GROUPS) {
  765. for ( i=0; i < UserInfo->ResourceGroupCount; i++ ) {
  766. V1->Groups->Groups[V1->Groups->GroupCount].Attributes = UserInfo->ResourceGroupIds[i].Attributes;
  767. V1->Groups->Groups[V1->Groups->GroupCount].Sid = LsapMakeDomainRelativeSid2(
  768. UserInfo->ResourceGroupDomainSid,
  769. UserInfo->ResourceGroupIds[i].RelativeId );
  770. if( V1->Groups->Groups[V1->Groups->GroupCount].Sid == NULL ) {
  771. Status = STATUS_INSUFFICIENT_RESOURCES;
  772. goto Cleanup;
  773. }
  774. V1->Groups->GroupCount++;
  775. }
  776. }
  777. if (!V1->User.User.Sid) {
  778. Status = STATUS_INSUFFICIENT_LOGON_INFO;
  779. goto Cleanup;
  780. }
  781. //
  782. // There are no default privileges supplied.
  783. // We don't have an explicit owner SID.
  784. // There is no default DACL.
  785. //
  786. V1->Privileges = NULL;
  787. V1->Owner.Owner = NULL;
  788. V1->DefaultDacl.DefaultDacl = NULL;
  789. //
  790. // Return the Validation Information to the caller.
  791. //
  792. *TokenInformation = V1;
  793. return STATUS_SUCCESS;
  794. //
  795. // Deallocate any memory we've allocated
  796. //
  797. Cleanup:
  798. if ( V1->User.User.Sid != NULL ) {
  799. LsapFreeLsaHeap( V1->User.User.Sid );
  800. }
  801. if ( V1->Groups != NULL ) {
  802. LsapFreeTokenGroups( V1->Groups );
  803. }
  804. if ( V1->PrimaryGroup.PrimaryGroup != NULL ) {
  805. LsapFreeLsaHeap( V1->PrimaryGroup.PrimaryGroup );
  806. }
  807. LsapFreeLsaHeap( V1 );
  808. return Status;
  809. }
  810. //+---------------------------------------------------------------------------
  811. //
  812. // Function: LsaFreeTokenInfo
  813. //
  814. // Synopsis: Frees a TokenInformation structure that was allocated by
  815. // the LSA
  816. //
  817. // Arguments: [TokenInfoType] --
  818. // [TokenInformation] --
  819. //
  820. // History: 3-14-97 RichardW Created
  821. //
  822. // Notes:
  823. //
  824. //----------------------------------------------------------------------------
  825. NTSTATUS
  826. NTAPI
  827. LsaFreeTokenInfo(
  828. LSA_TOKEN_INFORMATION_TYPE TokenInfoType,
  829. PVOID TokenInformation
  830. )
  831. {
  832. switch (TokenInfoType) {
  833. case LsaTokenInformationNull:
  834. LsapFreeTokenInformationNull( (PLSA_TOKEN_INFORMATION_NULL) TokenInformation );
  835. break;
  836. case LsaTokenInformationV1:
  837. LsapFreeTokenInformationV1( (PLSA_TOKEN_INFORMATION_V1) TokenInformation );
  838. break;
  839. case LsaTokenInformationV2:
  840. LsapFreeTokenInformationV2( (PLSA_TOKEN_INFORMATION_V2) TokenInformation );
  841. break;
  842. }
  843. return STATUS_SUCCESS ;
  844. }
  845. //+---------------------------------------------------------------------------
  846. //
  847. // Function: LsaConvertAuthDataToToken
  848. //
  849. // Synopsis: Convert an opaque PAC structure into a token.
  850. //
  851. // Arguments: [UserAuthData] --
  852. // [UserAuthDataSize] --
  853. // [TokenInformation] --
  854. // [TokenInformationType] --
  855. //
  856. // History: 3-14-97 RichardW Created
  857. //
  858. // Notes:
  859. //
  860. //----------------------------------------------------------------------------
  861. NTSTATUS
  862. NTAPI
  863. LsaConvertAuthDataToToken(
  864. IN PVOID UserAuthData,
  865. IN ULONG UserAuthDataSize,
  866. IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
  867. IN PTOKEN_SOURCE TokenSource,
  868. IN SECURITY_LOGON_TYPE LogonType,
  869. IN PUNICODE_STRING AuthorityName,
  870. OUT PHANDLE TokenHandle,
  871. OUT PLUID LogonId,
  872. OUT PUNICODE_STRING AccountName,
  873. OUT PNTSTATUS SubStatus
  874. )
  875. {
  876. NTSTATUS Status ;
  877. PPACTYPE Pac = NULL ;
  878. PPAC_INFO_BUFFER LogonInfo = NULL ;
  879. PNETLOGON_VALIDATION_SAM_INFO3 ValidationInfo = NULL ;
  880. PLSA_TOKEN_INFORMATION_V1 TokenInfo = NULL ;
  881. LogonId->HighPart = LogonId->LowPart = 0;
  882. *TokenHandle = NULL;
  883. RtlInitUnicodeString(
  884. AccountName,
  885. NULL
  886. );
  887. *SubStatus = STATUS_SUCCESS;
  888. Pac = (PPACTYPE) UserAuthData ;
  889. if ( PAC_UnMarshal( Pac, UserAuthDataSize ) == 0 )
  890. {
  891. DebugLog(( DEB_ERROR, "Failed to unmarshall pac\n" ));
  892. Status = STATUS_INVALID_PARAMETER ;
  893. goto CreateToken_Cleanup ;
  894. }
  895. LogonInfo = PAC_Find( Pac, PAC_LOGON_INFO, NULL );
  896. if ( !LogonInfo )
  897. {
  898. DebugLog(( DEB_ERROR, "Failed to find logon info in pac\n" ));
  899. Status = STATUS_INVALID_PARAMETER ;
  900. goto CreateToken_Cleanup ;
  901. }
  902. Status = PAC_UnmarshallValidationInfo(
  903. &ValidationInfo,
  904. LogonInfo->Data,
  905. LogonInfo->cbBufferSize
  906. );
  907. if (!NT_SUCCESS(Status))
  908. {
  909. DebugLog((DEB_ERROR,"Failed to unmarshall validation info: 0x%x\n",
  910. Status));
  911. goto CreateToken_Cleanup;
  912. }
  913. //
  914. // Now we need to build a LSA_TOKEN_INFORMATION_V1 from the validation
  915. // information
  916. //
  917. Status = LsapMakeTokenInformationV1(
  918. ValidationInfo,
  919. &TokenInfo
  920. );
  921. if (!NT_SUCCESS(Status))
  922. {
  923. DebugLog((DEB_ERROR,"Failed to make token informatin v1: 0x%x\n",
  924. Status));
  925. goto CreateToken_Cleanup;
  926. }
  927. //
  928. // Now, copy the user name.
  929. //
  930. Status = LsapDuplicateString( AccountName, &ValidationInfo->EffectiveName );
  931. if ( !NT_SUCCESS( Status ) )
  932. {
  933. goto CreateToken_Cleanup ;
  934. }
  935. //
  936. // Now create a logon session
  937. //
  938. Status = LsapCreateLogonSession( LogonId );
  939. if (!NT_SUCCESS(Status))
  940. {
  941. goto CreateToken_Cleanup;
  942. }
  943. //
  944. // Now create the token
  945. //
  946. Status = LsapCreateToken(
  947. LogonId,
  948. TokenSource,
  949. LogonType,
  950. ImpersonationLevel,
  951. LsaTokenInformationV1,
  952. TokenInfo,
  953. NULL, // no token groups
  954. AccountName,
  955. AuthorityName,
  956. NULL,
  957. &ValidationInfo->ProfilePath,
  958. TokenHandle,
  959. SubStatus
  960. );
  961. //
  962. // NULL out the TokenInfo pointer. LsapCreateToken will
  963. // free the memory under all conditions
  964. //
  965. TokenInfo = NULL ;
  966. if (!NT_SUCCESS(Status))
  967. {
  968. goto CreateToken_Cleanup;
  969. }
  970. //
  971. // We don't need to free the token information because CreateToken does
  972. // that for us.
  973. //
  974. MIDL_user_free(ValidationInfo);
  975. return Status ;
  976. CreateToken_Cleanup:
  977. if ( TokenInfo )
  978. {
  979. LsaFreeTokenInfo( LsaTokenInformationV1, TokenInfo );
  980. }
  981. if ((LogonId->LowPart != 0) || (LogonId->HighPart != 0))
  982. {
  983. LsapDeleteLogonSession(LogonId);
  984. }
  985. LsapFreeString(
  986. AccountName
  987. );
  988. if (ValidationInfo != NULL)
  989. {
  990. MIDL_user_free(ValidationInfo);
  991. }
  992. return Status ;
  993. }
  994. //+---------------------------------------------------------------------------
  995. //
  996. // Function: LsaGetAuthDataForUser
  997. //
  998. // Synopsis: Helper function - retrieves all auth data for a user
  999. // based on Name, NameType, and prefix
  1000. //
  1001. // Arguments: [Name] -- Name to search for
  1002. // [NameType] -- Type of name supplied
  1003. // [Prefix] -- String prefix for name
  1004. // [UserAuthData] --
  1005. // [UserAuthDataSize] --
  1006. //
  1007. // History: 6-08-98 RichardW Created
  1008. //
  1009. // Notes:
  1010. //
  1011. //----------------------------------------------------------------------------
  1012. NTSTATUS
  1013. LsaGetAuthDataForUser(
  1014. PSECURITY_STRING Name,
  1015. SECPKG_NAME_TYPE NameType,
  1016. PSECURITY_STRING Prefix OPTIONAL,
  1017. PUCHAR * UserAuthData,
  1018. PULONG UserAuthDataSize,
  1019. PUNICODE_STRING UserFlatName OPTIONAL
  1020. )
  1021. {
  1022. NTSTATUS Status ;
  1023. ULONG SamFlags ;
  1024. PUNICODE_STRING AccountName ;
  1025. UNICODE_STRING CombinedName = { 0 };
  1026. SID_AND_ATTRIBUTES_LIST ReverseMembership ;
  1027. PSAMPR_USER_ALL_INFORMATION UserAll = NULL ;
  1028. PSAMPR_USER_INFO_BUFFER UserAllInfo = NULL ;
  1029. PPACTYPE pNewPac = NULL ;
  1030. PPACTYPE Pac ;
  1031. UNICODE_STRING Domain ;
  1032. UNICODE_STRING Machine ;
  1033. PSID Sid ;
  1034. Sid = NULL ;
  1035. Machine.Buffer = NULL ;
  1036. Domain.Buffer = NULL ;
  1037. ReverseMembership.Count = 0 ;
  1038. *UserAuthData = NULL ;
  1039. if ( UserFlatName )
  1040. {
  1041. ZeroMemory( UserFlatName, sizeof( UNICODE_STRING ) );
  1042. }
  1043. SamFlags = 0 ;
  1044. switch ( NameType )
  1045. {
  1046. case SecNameSamCompatible:
  1047. AccountName = Name ;
  1048. break;
  1049. case SecNameAlternateId:
  1050. SamFlags |= SAM_OPEN_BY_ALTERNATE_ID ;
  1051. if ( !Prefix )
  1052. {
  1053. return STATUS_INVALID_PARAMETER ;
  1054. }
  1055. CombinedName.MaximumLength = Name->Length + Prefix->Length +
  1056. 2 * sizeof( WCHAR );
  1057. CombinedName.Length = CombinedName.MaximumLength - sizeof( WCHAR );
  1058. CombinedName.Buffer = (PWSTR) LsapAllocateLsaHeap( CombinedName.MaximumLength );
  1059. if ( CombinedName.Buffer )
  1060. {
  1061. CopyMemory( CombinedName.Buffer, Prefix->Buffer, Prefix->Length );
  1062. CombinedName.Buffer[ Prefix->Length / sizeof( WCHAR ) ] = L':';
  1063. CopyMemory( &CombinedName.Buffer[ Prefix->Length / sizeof( WCHAR ) + 1],
  1064. Name->Buffer,
  1065. Name->Length + sizeof( WCHAR ) );
  1066. AccountName = &CombinedName ;
  1067. }
  1068. else
  1069. {
  1070. return SEC_E_INSUFFICIENT_MEMORY ;
  1071. }
  1072. break;
  1073. case SecNameFlat:
  1074. SamFlags |= SAM_OPEN_BY_UPN ;
  1075. AccountName = Name ;
  1076. break;
  1077. default:
  1078. return STATUS_INVALID_PARAMETER ;
  1079. }
  1080. Status = SamIGetUserLogonInformation(
  1081. LsapAccountDomainHandle,
  1082. SamFlags,
  1083. AccountName,
  1084. &UserAllInfo,
  1085. &ReverseMembership,
  1086. NULL );
  1087. //
  1088. // Free the combined name (if appropriate)
  1089. //
  1090. if ( CombinedName.Buffer )
  1091. {
  1092. LsapFreeLsaHeap( CombinedName.Buffer );
  1093. }
  1094. if ( !NT_SUCCESS( Status ) )
  1095. {
  1096. return( Status );
  1097. }
  1098. UserAll = &UserAllInfo->All ;
  1099. if ( UserFlatName )
  1100. {
  1101. Status = LsapDuplicateString(
  1102. UserFlatName,
  1103. (PUNICODE_STRING) &UserAll->UserName );
  1104. if ( !NT_SUCCESS( Status ) )
  1105. {
  1106. goto GetPac_Cleanup;
  1107. }
  1108. }
  1109. if ( UserAll->UserAccountControl & USER_ACCOUNT_DISABLED )
  1110. {
  1111. Status = STATUS_ACCOUNT_DISABLED ;
  1112. goto GetPac_Cleanup;
  1113. }
  1114. if ( UserAll->UserAccountControl & USER_ACCOUNT_AUTO_LOCKED )
  1115. {
  1116. Status = STATUS_ACCOUNT_LOCKED_OUT ;
  1117. goto GetPac_Cleanup ;
  1118. }
  1119. Status = LsapCaptureSamInfo( &Sid, &Domain, &Machine );
  1120. if ( !NT_SUCCESS( Status ) )
  1121. {
  1122. goto GetPac_Cleanup ;
  1123. }
  1124. Status = PAC_Init( UserAll,
  1125. NULL,
  1126. &ReverseMembership, // no extra groups
  1127. Sid,
  1128. &Domain,
  1129. &Machine,
  1130. 0, // no signature
  1131. 0, // no additional data
  1132. NULL, // no additional data
  1133. &Pac );
  1134. if ( !NT_SUCCESS( Status ) )
  1135. {
  1136. goto GetPac_Cleanup ;
  1137. }
  1138. *UserAuthDataSize = PAC_GetSize( Pac );
  1139. *UserAuthData = (PUCHAR) LsapAllocateLsaHeap( *UserAuthDataSize );
  1140. if ( *UserAuthData )
  1141. {
  1142. PAC_Marshal( Pac, *UserAuthDataSize, *UserAuthData );
  1143. }
  1144. else
  1145. {
  1146. Status = SEC_E_INSUFFICIENT_MEMORY ;
  1147. }
  1148. MIDL_user_free( Pac );
  1149. GetPac_Cleanup:
  1150. if ( UserAllInfo )
  1151. {
  1152. SamIFree_SAMPR_USER_INFO_BUFFER( UserAllInfo, UserAllInformation );
  1153. }
  1154. if ( ReverseMembership.Count )
  1155. {
  1156. SamIFreeSidAndAttributesList( &ReverseMembership );
  1157. }
  1158. if ( Sid )
  1159. {
  1160. LsapFreeLsaHeap( Sid );
  1161. }
  1162. if ( Domain.Buffer )
  1163. {
  1164. LsapFreeLsaHeap( Domain.Buffer );
  1165. }
  1166. if ( Machine.Buffer )
  1167. {
  1168. LsapFreeLsaHeap( Machine.Buffer );
  1169. }
  1170. return( Status );
  1171. }
  1172. NTSTATUS
  1173. NTAPI
  1174. LsaCrackSingleName(
  1175. ULONG FormatOffered,
  1176. BOOLEAN PerformAtGC,
  1177. PUNICODE_STRING NameInput,
  1178. PUNICODE_STRING Prefix OPTIONAL,
  1179. ULONG RequestedFormat,
  1180. PUNICODE_STRING CrackedName,
  1181. PUNICODE_STRING DnsDomainName,
  1182. PULONG SubStatus
  1183. )
  1184. {
  1185. NTSTATUS Status = STATUS_SUCCESS ;
  1186. UNICODE_STRING DnsDomain ;
  1187. UNICODE_STRING Name ;
  1188. DWORD Ret ;
  1189. DWORD DnsDomainLength ;
  1190. DWORD NameLength ;
  1191. UNICODE_STRING CombinedName = { 0 };
  1192. PUNICODE_STRING AccountName ;
  1193. if ( !SampUsingDsData() )
  1194. {
  1195. return SEC_E_UNSUPPORTED_FUNCTION ;
  1196. }
  1197. //
  1198. // Cruft up the call to the DS
  1199. //
  1200. Name.Buffer = (PWSTR) LsapAllocateLsaHeap( MAX_PATH * sizeof(WCHAR) * 2 );
  1201. DnsDomain.Buffer = (PWSTR) LsapAllocateLsaHeap( MAX_PATH * sizeof(WCHAR) );
  1202. if ( Name.Buffer && DnsDomain.Buffer )
  1203. {
  1204. Name.MaximumLength = MAX_PATH * sizeof(WCHAR) * 2 ;
  1205. Name.Length = 0 ;
  1206. DnsDomain.MaximumLength = MAX_PATH * sizeof(WCHAR) ;
  1207. DnsDomain.Length = 0 ;
  1208. NameLength = MAX_PATH * 2 ;
  1209. DnsDomainLength = MAX_PATH ;
  1210. Name.Buffer[ 0 ] = L'\0';
  1211. DnsDomain.Buffer[ 0 ] = L'\0';
  1212. if ( Prefix )
  1213. {
  1214. CombinedName.MaximumLength = NameInput->Length + Prefix->Length +
  1215. 2 * sizeof( WCHAR );
  1216. CombinedName.Length = CombinedName.MaximumLength - sizeof( WCHAR );
  1217. CombinedName.Buffer = (PWSTR) LsapAllocatePrivateHeap( CombinedName.MaximumLength );
  1218. if ( CombinedName.Buffer )
  1219. {
  1220. CopyMemory( CombinedName.Buffer, Prefix->Buffer, Prefix->Length );
  1221. CombinedName.Buffer[ Prefix->Length / sizeof( WCHAR ) ] = L':';
  1222. CopyMemory( &CombinedName.Buffer[ Prefix->Length / sizeof( WCHAR ) + 1],
  1223. NameInput->Buffer,
  1224. NameInput->Length + sizeof( WCHAR ) );
  1225. AccountName = &CombinedName ;
  1226. }
  1227. else
  1228. {
  1229. AccountName = NULL ;
  1230. }
  1231. }
  1232. else
  1233. {
  1234. AccountName = NameInput ;
  1235. }
  1236. if ( AccountName )
  1237. {
  1238. __try
  1239. {
  1240. Ret = CrackSingleName(
  1241. FormatOffered,
  1242. PerformAtGC ?
  1243. DS_NAME_FLAG_GCVERIFY : 0,
  1244. AccountName->Buffer,
  1245. RequestedFormat,
  1246. &DnsDomainLength,
  1247. DnsDomain.Buffer,
  1248. &NameLength,
  1249. Name.Buffer,
  1250. SubStatus );
  1251. if ( Ret != 0 )
  1252. {
  1253. Status = STATUS_UNSUCCESSFUL ;
  1254. }
  1255. else
  1256. {
  1257. Status = STATUS_SUCCESS ;
  1258. RtlInitUnicodeString( &DnsDomain, DnsDomain.Buffer );
  1259. RtlInitUnicodeString( &Name, Name.Buffer );
  1260. *CrackedName = Name ;
  1261. *DnsDomainName = DnsDomain ;
  1262. }
  1263. }
  1264. __except( EXCEPTION_EXECUTE_HANDLER )
  1265. {
  1266. Status = STATUS_UNSUCCESSFUL ;
  1267. }
  1268. if ( CombinedName.Buffer )
  1269. {
  1270. LsapFreePrivateHeap( CombinedName.Buffer );
  1271. }
  1272. }
  1273. }
  1274. else
  1275. {
  1276. Status = SEC_E_INSUFFICIENT_MEMORY ;
  1277. }
  1278. if ( !NT_SUCCESS( Status ) )
  1279. {
  1280. if ( Name.Buffer )
  1281. {
  1282. LsapFreeLsaHeap( Name.Buffer );
  1283. }
  1284. if ( DnsDomain.Buffer )
  1285. {
  1286. LsapFreeLsaHeap( DnsDomain.Buffer );
  1287. }
  1288. }
  1289. return Status ;
  1290. }
  1291. NTSTATUS
  1292. LsapBuildPacSidList(
  1293. IN PNETLOGON_VALIDATION_SAM_INFO3 UserInfo,
  1294. OUT PSAMPR_PSID_ARRAY Sids
  1295. )
  1296. {
  1297. ULONG Size = 0, i;
  1298. NTSTATUS Status = STATUS_SUCCESS ;
  1299. Sids->Count = 0;
  1300. Sids->Sids = NULL;
  1301. if (UserInfo->UserId != 0)
  1302. {
  1303. Size += sizeof( SAMPR_SID_INFORMATION );
  1304. }
  1305. Size += UserInfo->GroupCount * (ULONG)sizeof( SAMPR_SID_INFORMATION );
  1306. //
  1307. // If there are extra SIDs, add space for them
  1308. //
  1309. if (UserInfo->UserFlags & LOGON_EXTRA_SIDS)
  1310. {
  1311. Size += UserInfo->SidCount * (ULONG)sizeof(SAMPR_SID_INFORMATION);
  1312. }
  1313. Sids->Sids = (PSAMPR_SID_INFORMATION) MIDL_user_allocate( Size );
  1314. if ( Sids->Sids == NULL )
  1315. {
  1316. Status = STATUS_NO_MEMORY ;
  1317. goto Cleanup;
  1318. }
  1319. RtlZeroMemory(
  1320. Sids->Sids,
  1321. Size
  1322. );
  1323. //
  1324. // Start copying SIDs into the structure
  1325. //
  1326. i = 0;
  1327. //
  1328. // If the UserId is non-zero, then it contians the users RID.
  1329. //
  1330. if ( UserInfo->UserId )
  1331. {
  1332. Sids->Sids[0].SidPointer = (PRPC_SID)
  1333. LsapMakeDomainRelativeSid( UserInfo->LogonDomainId,
  1334. UserInfo->UserId );
  1335. if( Sids->Sids[0].SidPointer == NULL )
  1336. {
  1337. Status = STATUS_NO_MEMORY ;
  1338. goto Cleanup;
  1339. }
  1340. Sids->Count++;
  1341. }
  1342. //
  1343. // Copy over all the groups passed as RIDs
  1344. //
  1345. for ( i=0; i < UserInfo->GroupCount; i++ )
  1346. {
  1347. Sids->Sids[Sids->Count].SidPointer = (PRPC_SID)
  1348. LsapMakeDomainRelativeSid(
  1349. UserInfo->LogonDomainId,
  1350. UserInfo->GroupIds[i].RelativeId );
  1351. if( Sids->Sids[Sids->Count].SidPointer == NULL )
  1352. {
  1353. Status = STATUS_NO_MEMORY ;
  1354. goto Cleanup;
  1355. }
  1356. Sids->Count++;
  1357. }
  1358. //
  1359. // Add in the extra SIDs
  1360. //
  1361. //
  1362. // No need to allocate these, but...
  1363. //
  1364. if (UserInfo->UserFlags & LOGON_EXTRA_SIDS)
  1365. {
  1366. for ( i = 0; i < UserInfo->SidCount; i++ )
  1367. {
  1368. Status = LsapDuplicateSid(
  1369. (PSID *) &Sids->Sids[Sids->Count].SidPointer,
  1370. UserInfo->ExtraSids[i].Sid );
  1371. if ( !NT_SUCCESS( Status ) )
  1372. {
  1373. goto Cleanup ;
  1374. }
  1375. Sids->Count++;
  1376. }
  1377. }
  1378. //
  1379. // Deallocate any memory we've allocated
  1380. //
  1381. Cleanup:
  1382. if (!NT_SUCCESS( Status ))
  1383. {
  1384. if (Sids->Sids != NULL)
  1385. {
  1386. for (i = 0; i < Sids->Count ;i++ )
  1387. {
  1388. if (Sids->Sids[i].SidPointer != NULL)
  1389. {
  1390. MIDL_user_free(Sids->Sids[i].SidPointer);
  1391. }
  1392. }
  1393. MIDL_user_free(Sids->Sids);
  1394. Sids->Sids = NULL;
  1395. Sids->Count = 0;
  1396. }
  1397. }
  1398. return Status ;
  1399. }
  1400. NTSTATUS
  1401. NTAPI
  1402. LsaExpandAuthDataForDomain(
  1403. IN PUCHAR UserAuthData,
  1404. IN ULONG UserAuthDataSize,
  1405. IN PVOID Reserved,
  1406. OUT PUCHAR * ExpandedAuthData,
  1407. OUT PULONG ExpandedAuthDataSize
  1408. )
  1409. {
  1410. NTSTATUS Status = STATUS_SUCCESS ;
  1411. PPACTYPE Pac = NULL ;
  1412. PPAC_INFO_BUFFER LogonInfo = NULL ;
  1413. PNETLOGON_VALIDATION_SAM_INFO3 ValidationInfo = NULL ;
  1414. PLSA_TOKEN_INFORMATION_V1 TokenInfo = NULL ;
  1415. SAMPR_PSID_ARRAY SidList = {0};
  1416. PSAMPR_PSID_ARRAY ResourceGroups = NULL;
  1417. PPACTYPE NewPac = NULL ;
  1418. ULONG Index ;
  1419. Pac = (PPACTYPE) UserAuthData ;
  1420. if ( PAC_UnMarshal( Pac, UserAuthDataSize ) == 0 )
  1421. {
  1422. DebugLog(( DEB_ERROR, "Failed to unmarshall pac\n" ));
  1423. Status = STATUS_INVALID_PARAMETER ;
  1424. goto Expand_Cleanup ;
  1425. }
  1426. LogonInfo = PAC_Find( Pac, PAC_LOGON_INFO, NULL );
  1427. if ( !LogonInfo )
  1428. {
  1429. DebugLog(( DEB_ERROR, "Failed to find logon info in pac\n" ));
  1430. Status = STATUS_INVALID_PARAMETER ;
  1431. goto Expand_Cleanup ;
  1432. }
  1433. Status = PAC_UnmarshallValidationInfo(
  1434. &ValidationInfo,
  1435. LogonInfo->Data,
  1436. LogonInfo->cbBufferSize
  1437. );
  1438. if (!NT_SUCCESS(Status))
  1439. {
  1440. DebugLog((DEB_ERROR,"Failed to unmarshall validation info: 0x%x\n",
  1441. Status));
  1442. goto Expand_Cleanup;
  1443. }
  1444. Status = LsapBuildPacSidList(
  1445. ValidationInfo,
  1446. &SidList );
  1447. if ( !NT_SUCCESS( Status ) )
  1448. {
  1449. goto Expand_Cleanup ;
  1450. }
  1451. //
  1452. // Call SAM to get the sids
  1453. //
  1454. Status = SamIGetResourceGroupMembershipsTransitive(
  1455. LsapAccountDomainHandle,
  1456. &SidList,
  1457. 0, // no flags
  1458. &ResourceGroups
  1459. );
  1460. if (!NT_SUCCESS(Status))
  1461. {
  1462. DebugLog((DEB_ERROR,"Failed to get resource groups: 0x%x\n",Status));
  1463. goto Expand_Cleanup;
  1464. }
  1465. //
  1466. // Now build a new pac
  1467. //
  1468. Status = PAC_InitAndUpdateGroups(
  1469. ValidationInfo,
  1470. ResourceGroups,
  1471. Pac,
  1472. &NewPac
  1473. );
  1474. if ( !NT_SUCCESS( Status ) )
  1475. {
  1476. goto Expand_Cleanup ;
  1477. }
  1478. *ExpandedAuthDataSize = PAC_GetSize( NewPac );
  1479. *ExpandedAuthData = (PUCHAR) LsapAllocateLsaHeap( *ExpandedAuthDataSize );
  1480. if ( *ExpandedAuthData )
  1481. {
  1482. PAC_Marshal( NewPac, *ExpandedAuthDataSize, *ExpandedAuthData );
  1483. }
  1484. else
  1485. {
  1486. Status = STATUS_NO_MEMORY ;
  1487. }
  1488. MIDL_user_free( NewPac );
  1489. Expand_Cleanup:
  1490. if ( ValidationInfo )
  1491. {
  1492. MIDL_user_free( ValidationInfo );
  1493. }
  1494. if (SidList.Sids != NULL)
  1495. {
  1496. for (Index = 0; Index < SidList.Count ;Index++ )
  1497. {
  1498. if (SidList.Sids[Index].SidPointer != NULL)
  1499. {
  1500. MIDL_user_free(SidList.Sids[Index].SidPointer);
  1501. }
  1502. }
  1503. MIDL_user_free(SidList.Sids);
  1504. }
  1505. SamIFreeSidArray(
  1506. ResourceGroups
  1507. );
  1508. return Status ;
  1509. }