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