2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/se/sid.c
5 * PURPOSE: Security manager
7 * PROGRAMMERS: David Welch <welch@cwcom.net>
10 /* INCLUDES *******************************************************************/
16 #define TAG_SID_AND_ATTRIBUTES 'aSeS'
18 #if defined (ALLOC_PRAGMA)
19 #pragma alloc_text(INIT, SepInitSecurityIDs)
22 /* GLOBALS ********************************************************************/
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
};
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
;
61 /* FUNCTIONS ******************************************************************/
65 FreeInitializedSids(VOID
)
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
);
100 SepInitSecurityIDs(VOID
)
107 SidLength0
= RtlLengthRequiredSid(0);
108 SidLength1
= RtlLengthRequiredSid(1);
109 SidLength2
= RtlLengthRequiredSid(2);
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
);
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
)
159 FreeInitializedSids();
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);
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
;
274 SepCaptureSid(IN PSID InputSid
,
275 IN KPROCESSOR_MODE AccessMode
,
276 IN POOL_TYPE PoolType
,
277 IN BOOLEAN CaptureIfKernel
,
278 OUT PSID
*CapturedSid
)
281 PISID NewSid
, Sid
= (PISID
)InputSid
;
285 if (AccessMode
!= KernelMode
)
289 ProbeForRead(Sid
, FIELD_OFFSET(SID
, SubAuthority
), sizeof(UCHAR
));
290 SidSize
= RtlLengthRequiredSid(Sid
->SubAuthorityCount
);
291 ProbeForRead(Sid
, SidSize
, sizeof(UCHAR
));
293 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
295 /* Return the exception code */
296 _SEH2_YIELD(return _SEH2_GetExceptionCode());
300 /* allocate a SID and copy it */
301 NewSid
= ExAllocatePoolWithTag(PoolType
, SidSize
, TAG_SID
);
303 return STATUS_INSUFFICIENT_RESOURCES
;
307 RtlCopyMemory(NewSid
, Sid
, SidSize
);
309 *CapturedSid
= NewSid
;
311 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
313 /* Free the SID and return the exception code */
314 ExFreePoolWithTag(NewSid
, TAG_SID
);
315 _SEH2_YIELD(return _SEH2_GetExceptionCode());
319 else if (!CaptureIfKernel
)
321 *CapturedSid
= InputSid
;
325 SidSize
= RtlLengthRequiredSid(Sid
->SubAuthorityCount
);
327 /* allocate a SID and copy it */
328 NewSid
= ExAllocatePoolWithTag(PoolType
, SidSize
, TAG_SID
);
330 return STATUS_INSUFFICIENT_RESOURCES
;
332 RtlCopyMemory(NewSid
, Sid
, SidSize
);
334 *CapturedSid
= NewSid
;
337 return STATUS_SUCCESS
;
342 SepReleaseSid(IN PSID CapturedSid
,
343 IN KPROCESSOR_MODE AccessMode
,
344 IN BOOLEAN CaptureIfKernel
)
348 if (CapturedSid
!= NULL
&&
349 (AccessMode
!= KernelMode
||
350 (AccessMode
== KernelMode
&& CaptureIfKernel
)))
352 ExFreePoolWithTag(CapturedSid
, TAG_SID
);
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
)
369 ULONG ArraySize
, RequiredLength
, SidLength
, i
;
370 PSID_AND_ATTRIBUTES SidAndAttributes
;
376 *CapturedSidAndAttributes
= NULL
;
379 if (AttributeCount
== 0)
381 return STATUS_SUCCESS
;
384 if (AttributeCount
> 0x1000)
386 return STATUS_INVALID_PARAMETER
;
389 if ((PreviousMode
== KernelMode
) && !CaptureIfKernel
)
391 *CapturedSidAndAttributes
= SrcSidAndAttributes
;
392 return STATUS_SUCCESS
;
395 ArraySize
= AttributeCount
* sizeof(SID_AND_ATTRIBUTES
);
396 RequiredLength
= ALIGN_UP_BY(ArraySize
, sizeof(ULONG
));
398 /* Check for user mode data */
399 if (PreviousMode
!= KernelMode
)
403 /* First probe the whole array */
404 ProbeForRead(SrcSidAndAttributes
, ArraySize
, sizeof(ULONG
));
406 /* Loop the array elements */
407 for (i
= 0; i
< AttributeCount
; i
++)
409 /* Get the SID and probe the minimal structure */
410 Sid
= SrcSidAndAttributes
[i
].Sid
;
411 ProbeForRead(Sid
, sizeof(*Sid
), sizeof(ULONG
));
413 /* Verify that the SID is valid */
414 if (((Sid
->Revision
& 0xF) != SID_REVISION
) ||
415 (Sid
->SubAuthorityCount
> SID_MAX_SUB_AUTHORITIES
))
417 return STATUS_INVALID_SID
;
420 /* Calculate the SID length and probe the full SID */
421 SidLength
= RtlLengthRequiredSid(Sid
->SubAuthorityCount
);
422 ProbeForRead(Sid
, SidLength
, sizeof(ULONG
));
424 /* Add the aligned length to the required length */
425 RequiredLength
+= ALIGN_UP_BY(SidLength
, sizeof(ULONG
));
428 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
430 return _SEH2_GetExceptionCode();
436 /* Loop the array elements */
437 for (i
= 0; i
< AttributeCount
; i
++)
439 /* Get the SID and it's length */
440 Sid
= SrcSidAndAttributes
[i
].Sid
;
441 SidLength
= RtlLengthRequiredSid(Sid
->SubAuthorityCount
);
443 /* Add the aligned length to the required length */
444 RequiredLength
+= ALIGN_UP_BY(SidLength
, sizeof(ULONG
));
449 Status
= STATUS_SUCCESS
;
450 *ResultLength
= RequiredLength
;
452 /* Check if we have no buffer */
453 if (AllocatedMem
== NULL
)
455 /* Allocate a new buffer */
456 SidAndAttributes
= ExAllocatePoolWithTag(PoolType
,
458 TAG_SID_AND_ATTRIBUTES
);
459 if (SidAndAttributes
== NULL
)
461 return STATUS_INSUFFICIENT_RESOURCES
;
464 /* Otherwise check if the buffer is large enough */
465 else if (AllocatedLength
>= RequiredLength
)
467 /* Buffer is large enough, use it */
468 SidAndAttributes
= AllocatedMem
;
472 /* Buffer is too small, fail */
473 return STATUS_BUFFER_TOO_SMALL
;
476 *CapturedSidAndAttributes
= SidAndAttributes
;
478 /* Check again for user mode */
479 if (PreviousMode
!= KernelMode
)
483 /* The rest of the data starts after the array */
484 CurrentDest
= (PUCHAR
)SidAndAttributes
;
485 CurrentDest
+= ALIGN_UP_BY(ArraySize
, sizeof(ULONG
));
487 /* Loop the array elements */
488 for (i
= 0; i
< AttributeCount
; i
++)
490 /* Get the SID and it's length */
491 Sid
= SrcSidAndAttributes
[i
].Sid
;
492 SidLength
= RtlLengthRequiredSid(Sid
->SubAuthorityCount
);
494 /* Copy attributes */
495 SidAndAttributes
[i
].Attributes
= SrcSidAndAttributes
[i
].Attributes
;
497 /* Copy the SID to the current destination address */
498 SidAndAttributes
[i
].Sid
= (PSID
)CurrentDest
;
499 RtlCopyMemory(CurrentDest
, SrcSidAndAttributes
[i
].Sid
, SidLength
);
502 NT_ASSERT(RtlLengthSid(SidAndAttributes
[i
].Sid
) == SidLength
);
503 NT_ASSERT(RtlValidSid(SidAndAttributes
[i
].Sid
));
505 /* Update the current destination address */
506 CurrentDest
+= ALIGN_UP_BY(SidLength
, sizeof(ULONG
));
509 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
511 Status
= _SEH2_GetExceptionCode();
517 /* The rest of the data starts after the array */
518 CurrentDest
= (PUCHAR
)SidAndAttributes
;
519 CurrentDest
+= ALIGN_UP_BY(ArraySize
, sizeof(ULONG
));
521 /* Loop the array elements */
522 for (i
= 0; i
< AttributeCount
; i
++)
524 /* Get the SID and it's length */
525 Sid
= SrcSidAndAttributes
[i
].Sid
;
526 SidLength
= RtlLengthRequiredSid(Sid
->SubAuthorityCount
);
528 /* Copy attributes */
529 SidAndAttributes
[i
].Attributes
= SrcSidAndAttributes
[i
].Attributes
;
531 /* Copy the SID to the current destination address */
532 SidAndAttributes
[i
].Sid
= (PSID
)CurrentDest
;
533 RtlCopyMemory(CurrentDest
, SrcSidAndAttributes
[i
].Sid
, SidLength
);
535 /* Update the current destination address */
536 CurrentDest
+= ALIGN_UP_BY(SidLength
, sizeof(ULONG
));
540 /* Check for failure */
541 if (!NT_SUCCESS(Status
))
543 /* Check if we allocated a new array */
544 if (SidAndAttributes
!= AllocatedMem
)
547 ExFreePoolWithTag(SidAndAttributes
, TAG_SID_AND_ATTRIBUTES
);
550 /* Set returned address to NULL */
551 *CapturedSidAndAttributes
= NULL
;
559 SeReleaseSidAndAttributesArray(
560 _In_ _Post_invalid_ PSID_AND_ATTRIBUTES CapturedSidAndAttributes
,
561 _In_ KPROCESSOR_MODE AccessMode
,
562 _In_ BOOLEAN CaptureIfKernel
)
566 if ((CapturedSidAndAttributes
!= NULL
) &&
567 ((AccessMode
!= KernelMode
) || CaptureIfKernel
))
569 ExFreePoolWithTag(CapturedSidAndAttributes
, TAG_SID_AND_ATTRIBUTES
);