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.

682 lines
17 KiB

  1. /*++
  2. Copyright (c) 1987-1996 Microsoft Corporation
  3. Module Name:
  4. rgroups.c
  5. Abstract:
  6. Routines to expand transitive group membership.
  7. Author:
  8. Mike Swift (mikesw) 8-May-1998
  9. Environment:
  10. User mode only.
  11. Contains NT-specific code.
  12. Requires ANSI C extensions: slash-slash comments, long external names.
  13. Revision History:
  14. --*/
  15. //
  16. // Common include files.
  17. //
  18. #include "logonsrv.h" // Include files common to entire service
  19. #pragma hdrstop
  20. PSID
  21. NlpCopySid(
  22. IN PSID Sid
  23. )
  24. /*++
  25. Routine Description:
  26. Given a SID allocatees space for a new SID from the LSA heap and copies
  27. the original SID.
  28. Arguments:
  29. Sid - The original SID.
  30. Return Value:
  31. Sid - Returns a pointer to a buffer allocated from the LsaHeap
  32. containing the resultant Sid.
  33. --*/
  34. {
  35. PSID NewSid;
  36. ULONG Size;
  37. Size = RtlLengthSid( Sid );
  38. if ((NewSid = MIDL_user_allocate( Size )) == NULL ) {
  39. return NULL;
  40. }
  41. if ( !NT_SUCCESS( RtlCopySid( Size, NewSid, Sid ) ) ) {
  42. MIDL_user_free( NewSid );
  43. return NULL;
  44. }
  45. return NewSid;
  46. }
  47. NTSTATUS
  48. NlpBuildPacSidList(
  49. IN PNETLOGON_VALIDATION_SAM_INFO4 UserInfo,
  50. OUT PSAMPR_PSID_ARRAY Sids
  51. )
  52. /*++
  53. Routine Description:
  54. Given the validation information for a user, expands the group member-
  55. ships and user id into a list of sids
  56. Arguments:
  57. UserInfo - user's validation information
  58. Sids - receives an array of all the user's group sids and user id
  59. Return Value:
  60. STATUS_INSUFFICIENT_RESOURCES - there wasn't enough memory to
  61. create the list of sids.
  62. --*/
  63. {
  64. NTSTATUS Status = STATUS_SUCCESS;
  65. NET_API_STATUS NetStatus;
  66. ULONG Size = 0, i;
  67. Sids->Count = 0;
  68. Sids->Sids = NULL;
  69. if (UserInfo->UserId != 0) {
  70. Size += sizeof(SAMPR_SID_INFORMATION);
  71. }
  72. Size += UserInfo->GroupCount * (ULONG)sizeof(SAMPR_SID_INFORMATION);
  73. //
  74. // If there are extra SIDs, add space for them
  75. //
  76. if (UserInfo->UserFlags & LOGON_EXTRA_SIDS) {
  77. Size += UserInfo->SidCount * (ULONG)sizeof(SAMPR_SID_INFORMATION);
  78. }
  79. Sids->Sids = (PSAMPR_SID_INFORMATION) MIDL_user_allocate( Size );
  80. if ( Sids->Sids == NULL ) {
  81. Status = STATUS_INSUFFICIENT_RESOURCES;
  82. goto Cleanup;
  83. }
  84. RtlZeroMemory(
  85. Sids->Sids,
  86. Size
  87. );
  88. //
  89. // Start copying SIDs into the structure
  90. //
  91. i = 0;
  92. //
  93. // If the UserId is non-zero, then it contians the users RID.
  94. //
  95. if ( UserInfo->UserId ) {
  96. NetStatus = NetpDomainIdToSid(
  97. UserInfo->LogonDomainId,
  98. UserInfo->UserId,
  99. (PSID *) &Sids->Sids[0].SidPointer
  100. );
  101. if( NetStatus != ERROR_SUCCESS ) {
  102. Status = STATUS_INSUFFICIENT_RESOURCES;
  103. goto Cleanup;
  104. }
  105. Sids->Count++;
  106. }
  107. //
  108. // Copy over all the groups passed as RIDs
  109. //
  110. for ( i=0; i < UserInfo->GroupCount; i++ ) {
  111. NetStatus = NetpDomainIdToSid(
  112. UserInfo->LogonDomainId,
  113. UserInfo->GroupIds[i].RelativeId,
  114. (PSID *) &Sids->Sids[Sids->Count].SidPointer
  115. );
  116. if( NetStatus != ERROR_SUCCESS ) {
  117. Status = STATUS_INSUFFICIENT_RESOURCES;
  118. goto Cleanup;
  119. }
  120. Sids->Count++;
  121. }
  122. //
  123. // Add in the extra SIDs
  124. //
  125. //
  126. // ???: no need to allocate these
  127. //
  128. if (UserInfo->UserFlags & LOGON_EXTRA_SIDS) {
  129. for ( i = 0; i < UserInfo->SidCount; i++ ) {
  130. Sids->Sids[Sids->Count].SidPointer = NlpCopySid(
  131. UserInfo->ExtraSids[i].Sid
  132. );
  133. if (Sids->Sids[Sids->Count].SidPointer == NULL) {
  134. Status = STATUS_INSUFFICIENT_RESOURCES;
  135. goto Cleanup;
  136. }
  137. Sids->Count++;
  138. }
  139. }
  140. //
  141. // Deallocate any memory we've allocated
  142. //
  143. Cleanup:
  144. if (!NT_SUCCESS(Status)) {
  145. if (Sids->Sids != NULL) {
  146. for (i = 0; i < Sids->Count ;i++ ) {
  147. if (Sids->Sids[i].SidPointer != NULL) {
  148. MIDL_user_free(Sids->Sids[i].SidPointer);
  149. }
  150. }
  151. MIDL_user_free(Sids->Sids);
  152. Sids->Sids = NULL;
  153. Sids->Count = 0;
  154. }
  155. }
  156. return Status;
  157. }
  158. NTSTATUS
  159. NlpAddResourceGroupsToSamInfo (
  160. IN NETLOGON_VALIDATION_INFO_CLASS ValidationLevel,
  161. IN OUT PNETLOGON_VALIDATION_SAM_INFO4 *ValidationInformation,
  162. IN PSAMPR_PSID_ARRAY ResourceGroups
  163. )
  164. /*++
  165. Routine Description:
  166. This function converts a NETLOGON_VALIDATION_SAM_INFO version 1, 2, or 4 to
  167. a NETLOGON_VALIDATION_SAM_INFO version 4 and optionally adds in an array of
  168. ResourceGroup sids.
  169. Since version 4 is a superset of the other two levels, the returned structure can
  170. be used even though one of the other info levels are needed.
  171. Arguments:
  172. ValidationLevel -- Specifies the level of information passed as input in
  173. ValidationInformation. Must be NetlogonValidationSamInfo or
  174. NetlogonValidationSamInfo2, NetlogonValidationSamInfo4
  175. NetlogonValidationSamInfo4 is always returned on output.
  176. ValidationInformation -- Specifies the NETLOGON_VALIDATION_SAM_INFO
  177. to convert.
  178. ResourceGroups - The list of resource groups to add to the structure.
  179. If NULL, no resource groups are added.
  180. Return Value:
  181. STATUS_INSUFFICIENT_RESOURCES: not enough memory to allocate the new
  182. structure.
  183. --*/
  184. {
  185. ULONG Length;
  186. PNETLOGON_VALIDATION_SAM_INFO4 SamInfo = *ValidationInformation;
  187. PNETLOGON_VALIDATION_SAM_INFO4 SamInfo4;
  188. PBYTE Where;
  189. ULONG Index;
  190. ULONG GroupIndex;
  191. ULONG ExtraSids = 0;
  192. //
  193. // Calculate the size of the new structure
  194. //
  195. Length = sizeof( NETLOGON_VALIDATION_SAM_INFO4 )
  196. + SamInfo->GroupCount * sizeof(GROUP_MEMBERSHIP)
  197. + RtlLengthSid( SamInfo->LogonDomainId );
  198. //
  199. // Add space for extra sids & resource groups
  200. //
  201. if ( ValidationLevel != NetlogonValidationSamInfo &&
  202. (SamInfo->UserFlags & LOGON_EXTRA_SIDS) != 0 ) {
  203. for (Index = 0; Index < SamInfo->SidCount ; Index++ ) {
  204. Length += sizeof(NETLOGON_SID_AND_ATTRIBUTES) + RtlLengthSid(SamInfo->ExtraSids[Index].Sid);
  205. }
  206. ExtraSids += SamInfo->SidCount;
  207. }
  208. if ( ResourceGroups != NULL ) {
  209. for (Index = 0; Index < ResourceGroups->Count ; Index++ ) {
  210. Length += sizeof(NETLOGON_SID_AND_ATTRIBUTES) + RtlLengthSid(ResourceGroups->Sids[Index].SidPointer);
  211. }
  212. ExtraSids += ResourceGroups->Count;
  213. }
  214. //
  215. // Round up now to take into account the round up in the
  216. // middle of marshalling
  217. //
  218. Length = ROUND_UP_COUNT(Length, sizeof(WCHAR))
  219. + SamInfo->LogonDomainName.Length + sizeof(WCHAR)
  220. + SamInfo->LogonServer.Length + sizeof(WCHAR)
  221. + SamInfo->EffectiveName.Length + sizeof(WCHAR)
  222. + SamInfo->FullName.Length + sizeof(WCHAR)
  223. + SamInfo->LogonScript.Length + sizeof(WCHAR)
  224. + SamInfo->ProfilePath.Length + sizeof(WCHAR)
  225. + SamInfo->HomeDirectory.Length + sizeof(WCHAR)
  226. + SamInfo->HomeDirectoryDrive.Length + sizeof(WCHAR);
  227. if ( ValidationLevel == NetlogonValidationSamInfo4 ) {
  228. Length += SamInfo->DnsLogonDomainName.Length + sizeof(WCHAR)
  229. + SamInfo->Upn.Length + sizeof(WCHAR);
  230. //
  231. // The ExpansionStrings may be used to transport byte aligned data
  232. Length = ROUND_UP_COUNT(Length, sizeof(WCHAR))
  233. + SamInfo->ExpansionString1.Length + sizeof(WCHAR);
  234. Length = ROUND_UP_COUNT(Length, sizeof(WCHAR))
  235. + SamInfo->ExpansionString2.Length + sizeof(WCHAR);
  236. Length = ROUND_UP_COUNT(Length, sizeof(WCHAR))
  237. + SamInfo->ExpansionString3.Length + sizeof(WCHAR);
  238. Length = ROUND_UP_COUNT(Length, sizeof(WCHAR))
  239. + SamInfo->ExpansionString4.Length + sizeof(WCHAR);
  240. Length = ROUND_UP_COUNT(Length, sizeof(WCHAR))
  241. + SamInfo->ExpansionString5.Length + sizeof(WCHAR);
  242. Length = ROUND_UP_COUNT(Length, sizeof(WCHAR))
  243. + SamInfo->ExpansionString6.Length + sizeof(WCHAR);
  244. Length = ROUND_UP_COUNT(Length, sizeof(WCHAR))
  245. + SamInfo->ExpansionString7.Length + sizeof(WCHAR);
  246. Length = ROUND_UP_COUNT(Length, sizeof(WCHAR))
  247. + SamInfo->ExpansionString8.Length + sizeof(WCHAR);
  248. Length = ROUND_UP_COUNT(Length, sizeof(WCHAR))
  249. + SamInfo->ExpansionString9.Length + sizeof(WCHAR);
  250. Length = ROUND_UP_COUNT(Length, sizeof(WCHAR))
  251. + SamInfo->ExpansionString10.Length + sizeof(WCHAR);
  252. }
  253. Length = ROUND_UP_COUNT( Length, sizeof(WCHAR) );
  254. SamInfo4 = (PNETLOGON_VALIDATION_SAM_INFO4) MIDL_user_allocate( Length );
  255. if ( !SamInfo4 ) {
  256. *ValidationInformation = NULL;
  257. return STATUS_INSUFFICIENT_RESOURCES;
  258. }
  259. //
  260. // First copy the whole structure, since most parts are the same
  261. //
  262. RtlCopyMemory( SamInfo4, SamInfo, sizeof(NETLOGON_VALIDATION_SAM_INFO));
  263. RtlZeroMemory( &((LPBYTE)SamInfo4)[sizeof(NETLOGON_VALIDATION_SAM_INFO)],
  264. sizeof(NETLOGON_VALIDATION_SAM_INFO4) - sizeof(NETLOGON_VALIDATION_SAM_INFO) );
  265. //
  266. // Copy all the variable length data
  267. //
  268. Where = (PBYTE) (SamInfo4 + 1);
  269. RtlCopyMemory(
  270. Where,
  271. SamInfo->GroupIds,
  272. SamInfo->GroupCount * sizeof( GROUP_MEMBERSHIP) );
  273. SamInfo4->GroupIds = (PGROUP_MEMBERSHIP) Where;
  274. Where += SamInfo->GroupCount * sizeof( GROUP_MEMBERSHIP );
  275. //
  276. // Copy the extra groups
  277. //
  278. if (ExtraSids != 0) {
  279. ULONG SidLength;
  280. SamInfo4->ExtraSids = (PNETLOGON_SID_AND_ATTRIBUTES) Where;
  281. Where += sizeof(NETLOGON_SID_AND_ATTRIBUTES) * ExtraSids;
  282. GroupIndex = 0;
  283. if ( ValidationLevel != NetlogonValidationSamInfo &&
  284. (SamInfo->UserFlags & LOGON_EXTRA_SIDS) != 0 ) {
  285. for (Index = 0; Index < SamInfo->SidCount ; Index++ ) {
  286. SamInfo4->ExtraSids[GroupIndex].Attributes = SamInfo->ExtraSids[Index].Attributes;
  287. SamInfo4->ExtraSids[GroupIndex].Sid = (PSID) Where;
  288. SidLength = RtlLengthSid(SamInfo->ExtraSids[Index].Sid);
  289. RtlCopyMemory(
  290. Where,
  291. SamInfo->ExtraSids[Index].Sid,
  292. SidLength
  293. );
  294. Where += SidLength;
  295. GroupIndex++;
  296. }
  297. }
  298. //
  299. // Add the resource groups
  300. //
  301. if ( ResourceGroups != NULL ) {
  302. for (Index = 0; Index < ResourceGroups->Count ; Index++ ) {
  303. SamInfo4->ExtraSids[GroupIndex].Attributes = SE_GROUP_MANDATORY |
  304. SE_GROUP_ENABLED |
  305. SE_GROUP_ENABLED_BY_DEFAULT;
  306. SamInfo4->ExtraSids[GroupIndex].Sid = (PSID) Where;
  307. SidLength = RtlLengthSid(ResourceGroups->Sids[Index].SidPointer);
  308. RtlCopyMemory(
  309. Where,
  310. ResourceGroups->Sids[Index].SidPointer,
  311. SidLength
  312. );
  313. Where += SidLength;
  314. GroupIndex++;
  315. }
  316. }
  317. SamInfo4->SidCount = GroupIndex;
  318. NlAssert(GroupIndex == ExtraSids);
  319. }
  320. RtlCopyMemory(
  321. Where,
  322. SamInfo->LogonDomainId,
  323. RtlLengthSid( SamInfo->LogonDomainId ) );
  324. SamInfo4->LogonDomainId = (PSID) Where;
  325. Where += RtlLengthSid( SamInfo->LogonDomainId );
  326. //
  327. // Copy the WCHAR-aligned data
  328. //
  329. Where = ROUND_UP_POINTER(Where, sizeof(WCHAR) );
  330. NlpPutString( &SamInfo4->EffectiveName,
  331. &SamInfo->EffectiveName,
  332. &Where );
  333. NlpPutString( &SamInfo4->FullName,
  334. &SamInfo->FullName,
  335. &Where );
  336. NlpPutString( &SamInfo4->LogonScript,
  337. &SamInfo->LogonScript,
  338. &Where );
  339. NlpPutString( &SamInfo4->ProfilePath,
  340. &SamInfo->ProfilePath,
  341. &Where );
  342. NlpPutString( &SamInfo4->HomeDirectory,
  343. &SamInfo->HomeDirectory,
  344. &Where );
  345. NlpPutString( &SamInfo4->HomeDirectoryDrive,
  346. &SamInfo->HomeDirectoryDrive,
  347. &Where );
  348. NlpPutString( &SamInfo4->LogonServer,
  349. &SamInfo->LogonServer,
  350. &Where );
  351. NlpPutString( &SamInfo4->LogonDomainName,
  352. &SamInfo->LogonDomainName,
  353. &Where );
  354. if ( ValidationLevel == NetlogonValidationSamInfo4 ) {
  355. NlpPutString( &SamInfo4->DnsLogonDomainName,
  356. &SamInfo->DnsLogonDomainName,
  357. &Where );
  358. NlpPutString( &SamInfo4->Upn,
  359. &SamInfo->Upn,
  360. &Where );
  361. NlpPutString( &SamInfo4->ExpansionString1,
  362. &SamInfo->ExpansionString1,
  363. &Where );
  364. Where = ROUND_UP_POINTER(Where, sizeof(WCHAR) );
  365. NlpPutString( &SamInfo4->ExpansionString2,
  366. &SamInfo->ExpansionString2,
  367. &Where );
  368. Where = ROUND_UP_POINTER(Where, sizeof(WCHAR) );
  369. NlpPutString( &SamInfo4->ExpansionString3,
  370. &SamInfo->ExpansionString3,
  371. &Where );
  372. Where = ROUND_UP_POINTER(Where, sizeof(WCHAR) );
  373. NlpPutString( &SamInfo4->ExpansionString4,
  374. &SamInfo->ExpansionString4,
  375. &Where );
  376. Where = ROUND_UP_POINTER(Where, sizeof(WCHAR) );
  377. NlpPutString( &SamInfo4->ExpansionString5,
  378. &SamInfo->ExpansionString5,
  379. &Where );
  380. Where = ROUND_UP_POINTER(Where, sizeof(WCHAR) );
  381. NlpPutString( &SamInfo4->ExpansionString6,
  382. &SamInfo->ExpansionString6,
  383. &Where );
  384. Where = ROUND_UP_POINTER(Where, sizeof(WCHAR) );
  385. NlpPutString( &SamInfo4->ExpansionString7,
  386. &SamInfo->ExpansionString7,
  387. &Where );
  388. Where = ROUND_UP_POINTER(Where, sizeof(WCHAR) );
  389. NlpPutString( &SamInfo4->ExpansionString8,
  390. &SamInfo->ExpansionString8,
  391. &Where );
  392. Where = ROUND_UP_POINTER(Where, sizeof(WCHAR) );
  393. NlpPutString( &SamInfo4->ExpansionString9,
  394. &SamInfo->ExpansionString9,
  395. &Where );
  396. Where = ROUND_UP_POINTER(Where, sizeof(WCHAR) );
  397. NlpPutString( &SamInfo4->ExpansionString10,
  398. &SamInfo->ExpansionString10,
  399. &Where );
  400. Where = ROUND_UP_POINTER(Where, sizeof(WCHAR) );
  401. }
  402. MIDL_user_free(SamInfo);
  403. *ValidationInformation = SamInfo4;
  404. return STATUS_SUCCESS;
  405. }
  406. NTSTATUS
  407. NlpExpandResourceGroupMembership(
  408. IN NETLOGON_VALIDATION_INFO_CLASS ValidationLevel,
  409. IN OUT PNETLOGON_VALIDATION_SAM_INFO4 * UserInfo,
  410. IN PDOMAIN_INFO DomainInfo
  411. )
  412. /*++
  413. Routine Description:
  414. Given the validation information for a user, expands the group member-
  415. ships and user id into a list of sids
  416. Arguments:
  417. ValidationLevel -- Specifies the level of information passed as input in
  418. UserInfo. Must be NetlogonValidationSamInfo or
  419. NetlogonValidationSamInfo2, NetlogonValidationSamInfo4
  420. NetlogonValidationSamInfo4 is always returned on output.
  421. UserInfo - user's validation information
  422. This structure is updated to include the resource groups that the user is a member of
  423. DomainInfo - Structure identifying the hosted domain used to determine the group membership.
  424. Return Value:
  425. STATUS_INSUFFICIENT_RESOURCES - there wasn't enough memory to
  426. create the list of sids.
  427. --*/
  428. {
  429. NTSTATUS Status = STATUS_SUCCESS;
  430. SAMPR_PSID_ARRAY SidList = {0};
  431. PSAMPR_PSID_ARRAY ResourceGroups = NULL;
  432. ULONG Index;
  433. Status = NlpBuildPacSidList(
  434. *UserInfo,
  435. &SidList
  436. );
  437. if (!NT_SUCCESS(Status)) {
  438. goto Cleanup;
  439. }
  440. //
  441. // Call SAM to get the sids
  442. //
  443. Status = SamIGetResourceGroupMembershipsTransitive(
  444. DomainInfo->DomSamAccountDomainHandle,
  445. &SidList,
  446. 0, // no flags
  447. &ResourceGroups
  448. );
  449. if (!NT_SUCCESS(Status)) {
  450. goto Cleanup;
  451. }
  452. //
  453. // Build a new validation information structure
  454. //
  455. if (ResourceGroups->Count != 0) {
  456. Status = NlpAddResourceGroupsToSamInfo(
  457. ValidationLevel,
  458. UserInfo,
  459. ResourceGroups
  460. );
  461. if (!NT_SUCCESS(Status)) {
  462. goto Cleanup;
  463. }
  464. }
  465. Cleanup:
  466. SamIFreeSidArray(
  467. ResourceGroups
  468. );
  469. if (SidList.Sids != NULL) {
  470. for (Index = 0; Index < SidList.Count ;Index++ ) {
  471. if (SidList.Sids[Index].SidPointer != NULL) {
  472. MIDL_user_free(SidList.Sids[Index].SidPointer);
  473. }
  474. }
  475. MIDL_user_free(SidList.Sids);
  476. }
  477. return(Status);
  478. }