* Sync to trunk r63845.
[reactos.git] / ntoskrnl / se / sid.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/se/sid.c
5 * PURPOSE: Security manager
6 *
7 * PROGRAMMERS: David Welch <welch@cwcom.net>
8 */
9
10 /* INCLUDES *******************************************************************/
11
12 #include <ntoskrnl.h>
13 #define NDEBUG
14 #include <debug.h>
15
16 #define TAG_SID_AND_ATTRIBUTES 'aSeS'
17
18 #if defined (ALLOC_PRAGMA)
19 #pragma alloc_text(INIT, SepInitSecurityIDs)
20 #endif
21
22 /* GLOBALS ********************************************************************/
23
24 SID_IDENTIFIER_AUTHORITY SeNullSidAuthority = {SECURITY_NULL_SID_AUTHORITY};
25 SID_IDENTIFIER_AUTHORITY SeWorldSidAuthority = {SECURITY_WORLD_SID_AUTHORITY};
26 SID_IDENTIFIER_AUTHORITY SeLocalSidAuthority = {SECURITY_LOCAL_SID_AUTHORITY};
27 SID_IDENTIFIER_AUTHORITY SeCreatorSidAuthority = {SECURITY_CREATOR_SID_AUTHORITY};
28 SID_IDENTIFIER_AUTHORITY SeNtSidAuthority = {SECURITY_NT_AUTHORITY};
29
30 PSID SeNullSid = NULL;
31 PSID SeWorldSid = NULL;
32 PSID SeLocalSid = NULL;
33 PSID SeCreatorOwnerSid = NULL;
34 PSID SeCreatorGroupSid = NULL;
35 PSID SeCreatorOwnerServerSid = NULL;
36 PSID SeCreatorGroupServerSid = NULL;
37 PSID SeNtAuthoritySid = NULL;
38 PSID SeDialupSid = NULL;
39 PSID SeNetworkSid = NULL;
40 PSID SeBatchSid = NULL;
41 PSID SeInteractiveSid = NULL;
42 PSID SeServiceSid = NULL;
43 PSID SePrincipalSelfSid = NULL;
44 PSID SeLocalSystemSid = NULL;
45 PSID SeAuthenticatedUserSid = NULL;
46 PSID SeRestrictedCodeSid = NULL;
47 PSID SeAliasAdminsSid = NULL;
48 PSID SeAliasUsersSid = NULL;
49 PSID SeAliasGuestsSid = NULL;
50 PSID SeAliasPowerUsersSid = NULL;
51 PSID SeAliasAccountOpsSid = NULL;
52 PSID SeAliasSystemOpsSid = NULL;
53 PSID SeAliasPrintOpsSid = NULL;
54 PSID SeAliasBackupOpsSid = NULL;
55 PSID SeAuthenticatedUsersSid = NULL;
56 PSID SeRestrictedSid = NULL;
57 PSID SeAnonymousLogonSid = NULL;
58 PSID SeLocalServiceSid = NULL;
59 PSID SeNetworkServiceSid = NULL;
60
61 /* FUNCTIONS ******************************************************************/
62
63 VOID
64 NTAPI
65 FreeInitializedSids(VOID)
66 {
67 if (SeNullSid) ExFreePoolWithTag(SeNullSid, TAG_SID);
68 if (SeWorldSid) ExFreePoolWithTag(SeWorldSid, TAG_SID);
69 if (SeLocalSid) ExFreePoolWithTag(SeLocalSid, TAG_SID);
70 if (SeCreatorOwnerSid) ExFreePoolWithTag(SeCreatorOwnerSid, TAG_SID);
71 if (SeCreatorGroupSid) ExFreePoolWithTag(SeCreatorGroupSid, TAG_SID);
72 if (SeCreatorOwnerServerSid) ExFreePoolWithTag(SeCreatorOwnerServerSid, TAG_SID);
73 if (SeCreatorGroupServerSid) ExFreePoolWithTag(SeCreatorGroupServerSid, TAG_SID);
74 if (SeNtAuthoritySid) ExFreePoolWithTag(SeNtAuthoritySid, TAG_SID);
75 if (SeDialupSid) ExFreePoolWithTag(SeDialupSid, TAG_SID);
76 if (SeNetworkSid) ExFreePoolWithTag(SeNetworkSid, TAG_SID);
77 if (SeBatchSid) ExFreePoolWithTag(SeBatchSid, TAG_SID);
78 if (SeInteractiveSid) ExFreePoolWithTag(SeInteractiveSid, TAG_SID);
79 if (SeServiceSid) ExFreePoolWithTag(SeServiceSid, TAG_SID);
80 if (SePrincipalSelfSid) ExFreePoolWithTag(SePrincipalSelfSid, TAG_SID);
81 if (SeLocalSystemSid) ExFreePoolWithTag(SeLocalSystemSid, TAG_SID);
82 if (SeAuthenticatedUserSid) ExFreePoolWithTag(SeAuthenticatedUserSid, TAG_SID);
83 if (SeRestrictedCodeSid) ExFreePoolWithTag(SeRestrictedCodeSid, TAG_SID);
84 if (SeAliasAdminsSid) ExFreePoolWithTag(SeAliasAdminsSid, TAG_SID);
85 if (SeAliasUsersSid) ExFreePoolWithTag(SeAliasUsersSid, TAG_SID);
86 if (SeAliasGuestsSid) ExFreePoolWithTag(SeAliasGuestsSid, TAG_SID);
87 if (SeAliasPowerUsersSid) ExFreePoolWithTag(SeAliasPowerUsersSid, TAG_SID);
88 if (SeAliasAccountOpsSid) ExFreePoolWithTag(SeAliasAccountOpsSid, TAG_SID);
89 if (SeAliasSystemOpsSid) ExFreePoolWithTag(SeAliasSystemOpsSid, TAG_SID);
90 if (SeAliasPrintOpsSid) ExFreePoolWithTag(SeAliasPrintOpsSid, TAG_SID);
91 if (SeAliasBackupOpsSid) ExFreePoolWithTag(SeAliasBackupOpsSid, TAG_SID);
92 if (SeAuthenticatedUsersSid) ExFreePoolWithTag(SeAuthenticatedUsersSid, TAG_SID);
93 if (SeRestrictedSid) ExFreePoolWithTag(SeRestrictedSid, TAG_SID);
94 if (SeAnonymousLogonSid) ExFreePoolWithTag(SeAnonymousLogonSid, TAG_SID);
95 }
96
97 BOOLEAN
98 INIT_FUNCTION
99 NTAPI
100 SepInitSecurityIDs(VOID)
101 {
102 ULONG SidLength0;
103 ULONG SidLength1;
104 ULONG SidLength2;
105 PULONG SubAuthority;
106
107 SidLength0 = RtlLengthRequiredSid(0);
108 SidLength1 = RtlLengthRequiredSid(1);
109 SidLength2 = RtlLengthRequiredSid(2);
110
111 /* create NullSid */
112 SeNullSid = ExAllocatePoolWithTag(PagedPool, SidLength1, TAG_SID);
113 SeWorldSid = ExAllocatePoolWithTag(PagedPool, SidLength1, TAG_SID);
114 SeLocalSid = ExAllocatePoolWithTag(PagedPool, SidLength1, TAG_SID);
115 SeCreatorOwnerSid = ExAllocatePoolWithTag(PagedPool, SidLength1, TAG_SID);
116 SeCreatorGroupSid = ExAllocatePoolWithTag(PagedPool, SidLength1, TAG_SID);
117 SeCreatorOwnerServerSid = ExAllocatePoolWithTag(PagedPool, SidLength1, TAG_SID);
118 SeCreatorGroupServerSid = ExAllocatePoolWithTag(PagedPool, SidLength1, TAG_SID);
119 SeNtAuthoritySid = ExAllocatePoolWithTag(PagedPool, SidLength0, TAG_SID);
120 SeDialupSid = ExAllocatePoolWithTag(PagedPool, SidLength1, TAG_SID);
121 SeNetworkSid = ExAllocatePoolWithTag(PagedPool, SidLength1, TAG_SID);
122 SeBatchSid = ExAllocatePoolWithTag(PagedPool, SidLength1, TAG_SID);
123 SeInteractiveSid = ExAllocatePoolWithTag(PagedPool, SidLength1, TAG_SID);
124 SeServiceSid = ExAllocatePoolWithTag(PagedPool, SidLength1, TAG_SID);
125 SePrincipalSelfSid = ExAllocatePoolWithTag(PagedPool, SidLength1, TAG_SID);
126 SeLocalSystemSid = ExAllocatePoolWithTag(PagedPool, SidLength1, TAG_SID);
127 SeAuthenticatedUserSid = ExAllocatePoolWithTag(PagedPool, SidLength1, TAG_SID);
128 SeRestrictedCodeSid = ExAllocatePoolWithTag(PagedPool, SidLength1, TAG_SID);
129 SeAliasAdminsSid = ExAllocatePoolWithTag(PagedPool, SidLength2, TAG_SID);
130 SeAliasUsersSid = ExAllocatePoolWithTag(PagedPool, SidLength2, TAG_SID);
131 SeAliasGuestsSid = ExAllocatePoolWithTag(PagedPool, SidLength2, TAG_SID);
132 SeAliasPowerUsersSid = ExAllocatePoolWithTag(PagedPool, SidLength2, TAG_SID);
133 SeAliasAccountOpsSid = ExAllocatePoolWithTag(PagedPool, SidLength2, TAG_SID);
134 SeAliasSystemOpsSid = ExAllocatePoolWithTag(PagedPool, SidLength2, TAG_SID);
135 SeAliasPrintOpsSid = ExAllocatePoolWithTag(PagedPool, SidLength2, TAG_SID);
136 SeAliasBackupOpsSid = ExAllocatePoolWithTag(PagedPool, SidLength2, TAG_SID);
137 SeAuthenticatedUsersSid = ExAllocatePoolWithTag(PagedPool, SidLength1, TAG_SID);
138 SeRestrictedSid = ExAllocatePoolWithTag(PagedPool, SidLength1, TAG_SID);
139 SeAnonymousLogonSid = ExAllocatePoolWithTag(PagedPool, SidLength1, TAG_SID);
140 SeLocalServiceSid = ExAllocatePoolWithTag(PagedPool, SidLength1, TAG_SID);
141 SeNetworkServiceSid = ExAllocatePoolWithTag(PagedPool, SidLength1, TAG_SID);
142
143 if (SeNullSid == NULL || SeWorldSid == NULL ||
144 SeLocalSid == NULL || SeCreatorOwnerSid == NULL ||
145 SeCreatorGroupSid == NULL || SeCreatorOwnerServerSid == NULL ||
146 SeCreatorGroupServerSid == NULL || SeNtAuthoritySid == NULL ||
147 SeDialupSid == NULL || SeNetworkSid == NULL || SeBatchSid == NULL ||
148 SeInteractiveSid == NULL || SeServiceSid == NULL ||
149 SePrincipalSelfSid == NULL || SeLocalSystemSid == NULL ||
150 SeAuthenticatedUserSid == NULL || SeRestrictedCodeSid == NULL ||
151 SeAliasAdminsSid == NULL || SeAliasUsersSid == NULL ||
152 SeAliasGuestsSid == NULL || SeAliasPowerUsersSid == NULL ||
153 SeAliasAccountOpsSid == NULL || SeAliasSystemOpsSid == NULL ||
154 SeAliasPrintOpsSid == NULL || SeAliasBackupOpsSid == NULL ||
155 SeAuthenticatedUsersSid == NULL || SeRestrictedSid == NULL ||
156 SeAnonymousLogonSid == NULL || SeLocalServiceSid == NULL ||
157 SeNetworkServiceSid == NULL)
158 {
159 FreeInitializedSids();
160 return FALSE;
161 }
162
163 RtlInitializeSid(SeNullSid, &SeNullSidAuthority, 1);
164 RtlInitializeSid(SeWorldSid, &SeWorldSidAuthority, 1);
165 RtlInitializeSid(SeLocalSid, &SeLocalSidAuthority, 1);
166 RtlInitializeSid(SeCreatorOwnerSid, &SeCreatorSidAuthority, 1);
167 RtlInitializeSid(SeCreatorGroupSid, &SeCreatorSidAuthority, 1);
168 RtlInitializeSid(SeCreatorOwnerServerSid, &SeCreatorSidAuthority, 1);
169 RtlInitializeSid(SeCreatorGroupServerSid, &SeCreatorSidAuthority, 1);
170 RtlInitializeSid(SeNtAuthoritySid, &SeNtSidAuthority, 0);
171 RtlInitializeSid(SeDialupSid, &SeNtSidAuthority, 1);
172 RtlInitializeSid(SeNetworkSid, &SeNtSidAuthority, 1);
173 RtlInitializeSid(SeBatchSid, &SeNtSidAuthority, 1);
174 RtlInitializeSid(SeInteractiveSid, &SeNtSidAuthority, 1);
175 RtlInitializeSid(SeServiceSid, &SeNtSidAuthority, 1);
176 RtlInitializeSid(SePrincipalSelfSid, &SeNtSidAuthority, 1);
177 RtlInitializeSid(SeLocalSystemSid, &SeNtSidAuthority, 1);
178 RtlInitializeSid(SeAuthenticatedUserSid, &SeNtSidAuthority, 1);
179 RtlInitializeSid(SeRestrictedCodeSid, &SeNtSidAuthority, 1);
180 RtlInitializeSid(SeAliasAdminsSid, &SeNtSidAuthority, 2);
181 RtlInitializeSid(SeAliasUsersSid, &SeNtSidAuthority, 2);
182 RtlInitializeSid(SeAliasGuestsSid, &SeNtSidAuthority, 2);
183 RtlInitializeSid(SeAliasPowerUsersSid, &SeNtSidAuthority, 2);
184 RtlInitializeSid(SeAliasAccountOpsSid, &SeNtSidAuthority, 2);
185 RtlInitializeSid(SeAliasSystemOpsSid, &SeNtSidAuthority, 2);
186 RtlInitializeSid(SeAliasPrintOpsSid, &SeNtSidAuthority, 2);
187 RtlInitializeSid(SeAliasBackupOpsSid, &SeNtSidAuthority, 2);
188 RtlInitializeSid(SeAuthenticatedUsersSid, &SeNtSidAuthority, 1);
189 RtlInitializeSid(SeRestrictedSid, &SeNtSidAuthority, 1);
190 RtlInitializeSid(SeAnonymousLogonSid, &SeNtSidAuthority, 1);
191 RtlInitializeSid(SeLocalServiceSid, &SeNtSidAuthority, 1);
192 RtlInitializeSid(SeNetworkServiceSid, &SeNtSidAuthority, 1);
193
194 SubAuthority = RtlSubAuthoritySid(SeNullSid, 0);
195 *SubAuthority = SECURITY_NULL_RID;
196 SubAuthority = RtlSubAuthoritySid(SeWorldSid, 0);
197 *SubAuthority = SECURITY_WORLD_RID;
198 SubAuthority = RtlSubAuthoritySid(SeLocalSid, 0);
199 *SubAuthority = SECURITY_LOCAL_RID;
200 SubAuthority = RtlSubAuthoritySid(SeCreatorOwnerSid, 0);
201 *SubAuthority = SECURITY_CREATOR_OWNER_RID;
202 SubAuthority = RtlSubAuthoritySid(SeCreatorGroupSid, 0);
203 *SubAuthority = SECURITY_CREATOR_GROUP_RID;
204 SubAuthority = RtlSubAuthoritySid(SeCreatorOwnerServerSid, 0);
205 *SubAuthority = SECURITY_CREATOR_OWNER_SERVER_RID;
206 SubAuthority = RtlSubAuthoritySid(SeCreatorGroupServerSid, 0);
207 *SubAuthority = SECURITY_CREATOR_GROUP_SERVER_RID;
208 SubAuthority = RtlSubAuthoritySid(SeDialupSid, 0);
209 *SubAuthority = SECURITY_DIALUP_RID;
210 SubAuthority = RtlSubAuthoritySid(SeNetworkSid, 0);
211 *SubAuthority = SECURITY_NETWORK_RID;
212 SubAuthority = RtlSubAuthoritySid(SeBatchSid, 0);
213 *SubAuthority = SECURITY_BATCH_RID;
214 SubAuthority = RtlSubAuthoritySid(SeInteractiveSid, 0);
215 *SubAuthority = SECURITY_INTERACTIVE_RID;
216 SubAuthority = RtlSubAuthoritySid(SeServiceSid, 0);
217 *SubAuthority = SECURITY_SERVICE_RID;
218 SubAuthority = RtlSubAuthoritySid(SePrincipalSelfSid, 0);
219 *SubAuthority = SECURITY_PRINCIPAL_SELF_RID;
220 SubAuthority = RtlSubAuthoritySid(SeLocalSystemSid, 0);
221 *SubAuthority = SECURITY_LOCAL_SYSTEM_RID;
222 SubAuthority = RtlSubAuthoritySid(SeAuthenticatedUserSid, 0);
223 *SubAuthority = SECURITY_AUTHENTICATED_USER_RID;
224 SubAuthority = RtlSubAuthoritySid(SeRestrictedCodeSid, 0);
225 *SubAuthority = SECURITY_RESTRICTED_CODE_RID;
226 SubAuthority = RtlSubAuthoritySid(SeAliasAdminsSid, 0);
227 *SubAuthority = SECURITY_BUILTIN_DOMAIN_RID;
228 SubAuthority = RtlSubAuthoritySid(SeAliasAdminsSid, 1);
229 *SubAuthority = DOMAIN_ALIAS_RID_ADMINS;
230 SubAuthority = RtlSubAuthoritySid(SeAliasUsersSid, 0);
231 *SubAuthority = SECURITY_BUILTIN_DOMAIN_RID;
232 SubAuthority = RtlSubAuthoritySid(SeAliasUsersSid, 1);
233 *SubAuthority = DOMAIN_ALIAS_RID_USERS;
234 SubAuthority = RtlSubAuthoritySid(SeAliasGuestsSid, 0);
235 *SubAuthority = SECURITY_BUILTIN_DOMAIN_RID;
236 SubAuthority = RtlSubAuthoritySid(SeAliasGuestsSid, 1);
237 *SubAuthority = DOMAIN_ALIAS_RID_GUESTS;
238 SubAuthority = RtlSubAuthoritySid(SeAliasPowerUsersSid, 0);
239 *SubAuthority = SECURITY_BUILTIN_DOMAIN_RID;
240 SubAuthority = RtlSubAuthoritySid(SeAliasPowerUsersSid, 1);
241 *SubAuthority = DOMAIN_ALIAS_RID_POWER_USERS;
242 SubAuthority = RtlSubAuthoritySid(SeAliasAccountOpsSid, 0);
243 *SubAuthority = SECURITY_BUILTIN_DOMAIN_RID;
244 SubAuthority = RtlSubAuthoritySid(SeAliasAccountOpsSid, 1);
245 *SubAuthority = DOMAIN_ALIAS_RID_ACCOUNT_OPS;
246 SubAuthority = RtlSubAuthoritySid(SeAliasSystemOpsSid, 0);
247 *SubAuthority = SECURITY_BUILTIN_DOMAIN_RID;
248 SubAuthority = RtlSubAuthoritySid(SeAliasSystemOpsSid, 1);
249 *SubAuthority = DOMAIN_ALIAS_RID_SYSTEM_OPS;
250 SubAuthority = RtlSubAuthoritySid(SeAliasPrintOpsSid, 0);
251 *SubAuthority = SECURITY_BUILTIN_DOMAIN_RID;
252 SubAuthority = RtlSubAuthoritySid(SeAliasPrintOpsSid, 1);
253 *SubAuthority = DOMAIN_ALIAS_RID_PRINT_OPS;
254 SubAuthority = RtlSubAuthoritySid(SeAliasBackupOpsSid, 0);
255 *SubAuthority = SECURITY_BUILTIN_DOMAIN_RID;
256 SubAuthority = RtlSubAuthoritySid(SeAliasBackupOpsSid, 1);
257 *SubAuthority = DOMAIN_ALIAS_RID_BACKUP_OPS;
258 SubAuthority = RtlSubAuthoritySid(SeAuthenticatedUsersSid, 0);
259 *SubAuthority = SECURITY_AUTHENTICATED_USER_RID;
260 SubAuthority = RtlSubAuthoritySid(SeRestrictedSid, 0);
261 *SubAuthority = SECURITY_RESTRICTED_CODE_RID;
262 SubAuthority = RtlSubAuthoritySid(SeAnonymousLogonSid, 0);
263 *SubAuthority = SECURITY_ANONYMOUS_LOGON_RID;
264 SubAuthority = RtlSubAuthoritySid(SeLocalServiceSid, 0);
265 *SubAuthority = SECURITY_LOCAL_SERVICE_RID;
266 SubAuthority = RtlSubAuthoritySid(SeNetworkServiceSid, 0);
267 *SubAuthority = SECURITY_NETWORK_SERVICE_RID;
268
269 return TRUE;
270 }
271
272 NTSTATUS
273 NTAPI
274 SepCaptureSid(IN PSID InputSid,
275 IN KPROCESSOR_MODE AccessMode,
276 IN POOL_TYPE PoolType,
277 IN BOOLEAN CaptureIfKernel,
278 OUT PSID *CapturedSid)
279 {
280 ULONG SidSize = 0;
281 PISID NewSid, Sid = (PISID)InputSid;
282
283 PAGED_CODE();
284
285 if (AccessMode != KernelMode)
286 {
287 _SEH2_TRY
288 {
289 ProbeForRead(Sid, FIELD_OFFSET(SID, SubAuthority), sizeof(UCHAR));
290 SidSize = RtlLengthRequiredSid(Sid->SubAuthorityCount);
291 ProbeForRead(Sid, SidSize, sizeof(UCHAR));
292 }
293 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
294 {
295 /* Return the exception code */
296 _SEH2_YIELD(return _SEH2_GetExceptionCode());
297 }
298 _SEH2_END;
299
300 /* allocate a SID and copy it */
301 NewSid = ExAllocatePoolWithTag(PoolType, SidSize, TAG_SID);
302 if (!NewSid)
303 return STATUS_INSUFFICIENT_RESOURCES;
304
305 _SEH2_TRY
306 {
307 RtlCopyMemory(NewSid, Sid, SidSize);
308
309 *CapturedSid = NewSid;
310 }
311 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
312 {
313 /* Free the SID and return the exception code */
314 ExFreePoolWithTag(NewSid, TAG_SID);
315 _SEH2_YIELD(return _SEH2_GetExceptionCode());
316 }
317 _SEH2_END;
318 }
319 else if (!CaptureIfKernel)
320 {
321 *CapturedSid = InputSid;
322 }
323 else
324 {
325 SidSize = RtlLengthRequiredSid(Sid->SubAuthorityCount);
326
327 /* allocate a SID and copy it */
328 NewSid = ExAllocatePoolWithTag(PoolType, SidSize, TAG_SID);
329 if (NewSid == NULL)
330 return STATUS_INSUFFICIENT_RESOURCES;
331
332 RtlCopyMemory(NewSid, Sid, SidSize);
333
334 *CapturedSid = NewSid;
335 }
336
337 return STATUS_SUCCESS;
338 }
339
340 VOID
341 NTAPI
342 SepReleaseSid(IN PSID CapturedSid,
343 IN KPROCESSOR_MODE AccessMode,
344 IN BOOLEAN CaptureIfKernel)
345 {
346 PAGED_CODE();
347
348 if (CapturedSid != NULL &&
349 (AccessMode != KernelMode ||
350 (AccessMode == KernelMode && CaptureIfKernel)))
351 {
352 ExFreePoolWithTag(CapturedSid, TAG_SID);
353 }
354 }
355
356 NTSTATUS
357 NTAPI
358 SeCaptureSidAndAttributesArray(
359 _In_ PSID_AND_ATTRIBUTES SrcSidAndAttributes,
360 _In_ ULONG AttributeCount,
361 _In_ KPROCESSOR_MODE PreviousMode,
362 _In_opt_ PVOID AllocatedMem,
363 _In_ ULONG AllocatedLength,
364 _In_ POOL_TYPE PoolType,
365 _In_ BOOLEAN CaptureIfKernel,
366 _Out_ PSID_AND_ATTRIBUTES *CapturedSidAndAttributes,
367 _Out_ PULONG ResultLength)
368 {
369 ULONG ArraySize, RequiredLength, SidLength, i;
370 PSID_AND_ATTRIBUTES SidAndAttributes;
371 PUCHAR CurrentDest;
372 PISID Sid;
373 NTSTATUS Status;
374 PAGED_CODE();
375
376 *CapturedSidAndAttributes = NULL;
377 *ResultLength = 0;
378
379 if (AttributeCount == 0)
380 {
381 return STATUS_SUCCESS;
382 }
383
384 if (AttributeCount > 0x1000)
385 {
386 return STATUS_INVALID_PARAMETER;
387 }
388
389 if ((PreviousMode == KernelMode) && !CaptureIfKernel)
390 {
391 *CapturedSidAndAttributes = SrcSidAndAttributes;
392 return STATUS_SUCCESS;
393 }
394
395 ArraySize = AttributeCount * sizeof(SID_AND_ATTRIBUTES);
396 RequiredLength = ALIGN_UP_BY(ArraySize, sizeof(ULONG));
397
398 /* Check for user mode data */
399 if (PreviousMode != KernelMode)
400 {
401 _SEH2_TRY
402 {
403 /* First probe the whole array */
404 ProbeForRead(SrcSidAndAttributes, ArraySize, sizeof(ULONG));
405
406 /* Loop the array elements */
407 for (i = 0; i < AttributeCount; i++)
408 {
409 /* Get the SID and probe the minimal structure */
410 Sid = SrcSidAndAttributes[i].Sid;
411 ProbeForRead(Sid, sizeof(*Sid), sizeof(ULONG));
412
413 /* Verify that the SID is valid */
414 if (((Sid->Revision & 0xF) != SID_REVISION) ||
415 (Sid->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES))
416 {
417 return STATUS_INVALID_SID;
418 }
419
420 /* Calculate the SID length and probe the full SID */
421 SidLength = RtlLengthRequiredSid(Sid->SubAuthorityCount);
422 ProbeForRead(Sid, SidLength, sizeof(ULONG));
423
424 /* Add the aligned length to the required length */
425 RequiredLength += ALIGN_UP_BY(SidLength, sizeof(ULONG));
426 }
427 }
428 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
429 {
430 return _SEH2_GetExceptionCode();
431 }
432 _SEH2_END;
433 }
434 else
435 {
436 /* Loop the array elements */
437 for (i = 0; i < AttributeCount; i++)
438 {
439 /* Get the SID and it's length */
440 Sid = SrcSidAndAttributes[i].Sid;
441 SidLength = RtlLengthRequiredSid(Sid->SubAuthorityCount);
442
443 /* Add the aligned length to the required length */
444 RequiredLength += ALIGN_UP_BY(SidLength, sizeof(ULONG));
445 }
446 }
447
448 /* Assume success */
449 Status = STATUS_SUCCESS;
450 *ResultLength = RequiredLength;
451
452 /* Check if we have no buffer */
453 if (AllocatedMem == NULL)
454 {
455 /* Allocate a new buffer */
456 SidAndAttributes = ExAllocatePoolWithTag(PoolType,
457 RequiredLength,
458 TAG_SID_AND_ATTRIBUTES);
459 if (SidAndAttributes == NULL)
460 {
461 return STATUS_INSUFFICIENT_RESOURCES;
462 }
463 }
464 /* Otherwise check if the buffer is large enough */
465 else if (AllocatedLength >= RequiredLength)
466 {
467 /* Buffer is large enough, use it */
468 SidAndAttributes = AllocatedMem;
469 }
470 else
471 {
472 /* Buffer is too small, fail */
473 return STATUS_BUFFER_TOO_SMALL;
474 }
475
476 *CapturedSidAndAttributes = SidAndAttributes;
477
478 /* Check again for user mode */
479 if (PreviousMode != KernelMode)
480 {
481 _SEH2_TRY
482 {
483 /* The rest of the data starts after the array */
484 CurrentDest = (PUCHAR)SidAndAttributes;
485 CurrentDest += ALIGN_UP_BY(ArraySize, sizeof(ULONG));
486
487 /* Loop the array elements */
488 for (i = 0; i < AttributeCount; i++)
489 {
490 /* Get the SID and it's length */
491 Sid = SrcSidAndAttributes[i].Sid;
492 SidLength = RtlLengthRequiredSid(Sid->SubAuthorityCount);
493
494 /* Copy attributes */
495 SidAndAttributes[i].Attributes = SrcSidAndAttributes[i].Attributes;
496
497 /* Copy the SID to the current destination address */
498 SidAndAttributes[i].Sid = (PSID)CurrentDest;
499 RtlCopyMemory(CurrentDest, SrcSidAndAttributes[i].Sid, SidLength);
500
501 /* Sanity checks */
502 NT_ASSERT(RtlLengthSid(SidAndAttributes[i].Sid) == SidLength);
503 NT_ASSERT(RtlValidSid(SidAndAttributes[i].Sid));
504
505 /* Update the current destination address */
506 CurrentDest += ALIGN_UP_BY(SidLength, sizeof(ULONG));
507 }
508 }
509 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
510 {
511 Status = _SEH2_GetExceptionCode();
512 }
513 _SEH2_END;
514 }
515 else
516 {
517 /* The rest of the data starts after the array */
518 CurrentDest = (PUCHAR)SidAndAttributes;
519 CurrentDest += ALIGN_UP_BY(ArraySize, sizeof(ULONG));
520
521 /* Loop the array elements */
522 for (i = 0; i < AttributeCount; i++)
523 {
524 /* Get the SID and it's length */
525 Sid = SrcSidAndAttributes[i].Sid;
526 SidLength = RtlLengthRequiredSid(Sid->SubAuthorityCount);
527
528 /* Copy attributes */
529 SidAndAttributes[i].Attributes = SrcSidAndAttributes[i].Attributes;
530
531 /* Copy the SID to the current destination address */
532 SidAndAttributes[i].Sid = (PSID)CurrentDest;
533 RtlCopyMemory(CurrentDest, SrcSidAndAttributes[i].Sid, SidLength);
534
535 /* Update the current destination address */
536 CurrentDest += ALIGN_UP_BY(SidLength, sizeof(ULONG));
537 }
538 }
539
540 /* Check for failure */
541 if (!NT_SUCCESS(Status))
542 {
543 /* Check if we allocated a new array */
544 if (SidAndAttributes != AllocatedMem)
545 {
546 /* Free the array */
547 ExFreePoolWithTag(SidAndAttributes, TAG_SID_AND_ATTRIBUTES);
548 }
549
550 /* Set returned address to NULL */
551 *CapturedSidAndAttributes = NULL ;
552 }
553
554 return Status;
555 }
556
557 VOID
558 NTAPI
559 SeReleaseSidAndAttributesArray(
560 _In_ _Post_invalid_ PSID_AND_ATTRIBUTES CapturedSidAndAttributes,
561 _In_ KPROCESSOR_MODE AccessMode,
562 _In_ BOOLEAN CaptureIfKernel)
563 {
564 PAGED_CODE();
565
566 if ((CapturedSidAndAttributes != NULL) &&
567 ((AccessMode != KernelMode) || CaptureIfKernel))
568 {
569 ExFreePoolWithTag(CapturedSidAndAttributes, TAG_SID_AND_ATTRIBUTES);
570 }
571 }
572
573
574 /* EOF */