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.

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