2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * PURPOSE: Security manager
6 * PROGRAMER: David Welch <welch@cwcom.net>
9 /* INCLUDES *****************************************************************/
15 #define TAG_SID 'diSp'
17 /* FUNCTIONS ***************************************************************/
21 RtlValidSid(IN PSID Sid_
)
26 /* Use SEH in case any pointer is invalid */
29 /* Validate the revision and subauthority count */
31 (((Sid
->Revision
& 0xF) != SID_REVISION
) ||
32 (Sid
->SubAuthorityCount
> SID_MAX_SUB_AUTHORITIES
)))
35 _SEH2_YIELD(return FALSE
);
38 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
40 /* Access violation, SID is not valid */
41 _SEH2_YIELD(return FALSE
);
54 RtlLengthRequiredSid(IN ULONG SubAuthorityCount
)
58 /* Return the required length */
59 return (ULONG
)FIELD_OFFSET(SID
,
60 SubAuthority
[SubAuthorityCount
]);
68 RtlInitializeSid(IN PSID Sid_
,
69 IN PSID_IDENTIFIER_AUTHORITY IdentifierAuthority
,
70 IN UCHAR SubAuthorityCount
)
75 /* Fill out the header */
76 Sid
->Revision
= SID_REVISION
;
77 Sid
->SubAuthorityCount
= SubAuthorityCount
;
78 Sid
->IdentifierAuthority
= *IdentifierAuthority
;
81 return STATUS_SUCCESS
;
89 RtlSubAuthoritySid(IN PSID Sid_
,
90 IN ULONG SubAuthority
)
95 /* Return the offset */
96 return (PULONG
)&Sid
->SubAuthority
[SubAuthority
];
104 RtlSubAuthorityCountSid(IN PSID Sid_
)
109 /* Return the offset to the count */
110 return &Sid
->SubAuthorityCount
;
116 PSID_IDENTIFIER_AUTHORITY
118 RtlIdentifierAuthoritySid(IN PSID Sid_
)
123 /* Return the offset to the identifier authority */
124 return &Sid
->IdentifierAuthority
;
132 RtlEqualSid(IN PSID Sid1_
,
135 PISID Sid1
= Sid1_
, Sid2
= Sid2_
;
138 /* Quick compare of the revision and the count */
139 if (*(PUSHORT
)&Sid1
->Revision
!= *(PUSHORT
)&Sid2
->Revision
) return FALSE
;
141 /* Get the length and compare it the long way */
142 return RtlEqualMemory(Sid1
, Sid2
, RtlLengthSid(Sid1
));
150 RtlLengthSid(IN PSID Sid_
)
155 /* The offset to the last index + 1 (since it's a count) is the length */
156 return (ULONG
)FIELD_OFFSET(SID
,
157 SubAuthority
[Sid
->SubAuthorityCount
]);
165 RtlCopySid(IN ULONG BufferLength
,
172 /* Make sure the buffer is large enough*/
173 SidLength
= RtlLengthSid(Src
);
174 if (SidLength
> BufferLength
) return STATUS_BUFFER_TOO_SMALL
;
176 /* And then copy the SID */
177 RtlMoveMemory(Dest
, Src
, SidLength
);
178 return STATUS_SUCCESS
;
186 RtlFreeSid(IN PSID Sid
)
190 /* Free the SID and always return NULL */
191 RtlpFreeMemory(Sid
, TAG_SID
);
200 RtlEqualPrefixSid(IN PSID Sid1_
,
203 PISID Sid1
= Sid1_
, Sid2
= Sid2_
;
207 /* Revisions have to match */
208 if (Sid1
->Revision
!= Sid2
->Revision
) return FALSE
;
210 /* The identifier authorities have to match */
211 if ((Sid1
->IdentifierAuthority
.Value
[0] == Sid2
->IdentifierAuthority
.Value
[0]) &&
212 (Sid1
->IdentifierAuthority
.Value
[1] == Sid2
->IdentifierAuthority
.Value
[1]) &&
213 (Sid1
->IdentifierAuthority
.Value
[2] == Sid2
->IdentifierAuthority
.Value
[2]) &&
214 (Sid1
->IdentifierAuthority
.Value
[3] == Sid2
->IdentifierAuthority
.Value
[3]) &&
215 (Sid1
->IdentifierAuthority
.Value
[4] == Sid2
->IdentifierAuthority
.Value
[4]) &&
216 (Sid1
->IdentifierAuthority
.Value
[5] == Sid2
->IdentifierAuthority
.Value
[5]))
218 /* The subauthority counts have to match */
219 if (Sid1
->SubAuthorityCount
== Sid2
->SubAuthorityCount
)
221 /* If there aren't any in SID1, means none in SID2 either, so equal */
222 if (!Sid1
->SubAuthorityCount
) return TRUE
;
224 /* Now compare all the subauthority values BUT the last one */
225 for (i
= 0; (i
+ 1) < Sid1
->SubAuthorityCount
; i
++)
227 /* Does any mismatch? */
228 if (Sid1
->SubAuthority
[i
] != Sid2
->SubAuthority
[i
])
230 /* Prefix doesn't match, fail */
235 /* Everything that should matches, does, return success */
240 /* Identifiers don't match, fail */
249 RtlCopySidAndAttributesArray(IN ULONG Count
,
250 IN PSID_AND_ATTRIBUTES Src
,
251 IN ULONG SidAreaSize
,
252 IN PSID_AND_ATTRIBUTES Dest
,
254 OUT PVOID
* RemainingSidArea
,
255 OUT PULONG RemainingSidAreaSize
)
260 /* Loop all the attributes */
261 for (i
= 0; i
< Count
; i
++)
263 /* Make sure this SID can fit in the buffer */
264 SidLength
= RtlLengthSid(Src
[i
].Sid
);
265 if (SidLength
> SidAreaSize
) return STATUS_BUFFER_TOO_SMALL
;
267 /* Consume remaining buffer space for this SID */
268 SidAreaSize
-= SidLength
;
270 /* Copy the SID and attributes */
271 Dest
[i
].Sid
= SidArea
;
272 Dest
[i
].Attributes
= Src
[i
].Attributes
;
273 RtlCopySid(SidLength
, SidArea
, Src
[i
].Sid
);
275 /* Push the buffer area where the SID will reset */
276 SidArea
= (PVOID
)((ULONG_PTR
)SidArea
+ SidLength
);
279 /* Return how much space is left, and where the buffer is at now */
280 *RemainingSidArea
= SidArea
;
281 *RemainingSidAreaSize
= SidAreaSize
;
282 return STATUS_SUCCESS
;
290 RtlAllocateAndInitializeSid(IN PSID_IDENTIFIER_AUTHORITY IdentifierAuthority
,
291 IN UCHAR SubAuthorityCount
,
292 IN ULONG SubAuthority0
,
293 IN ULONG SubAuthority1
,
294 IN ULONG SubAuthority2
,
295 IN ULONG SubAuthority3
,
296 IN ULONG SubAuthority4
,
297 IN ULONG SubAuthority5
,
298 IN ULONG SubAuthority6
,
299 IN ULONG SubAuthority7
,
305 /* SIDs can only have up to 8 subauthorities */
306 if (SubAuthorityCount
> 8) return STATUS_INVALID_SID
;
308 /* Allocate memory to hold the SID */
309 pSid
= RtlpAllocateMemory(RtlLengthRequiredSid(SubAuthorityCount
), TAG_SID
);
310 if (!pSid
) return STATUS_NO_MEMORY
;
312 /* Fill out the header */
313 pSid
->Revision
= SID_REVISION
;
314 pSid
->SubAuthorityCount
= SubAuthorityCount
;
315 pSid
->IdentifierAuthority
= *IdentifierAuthority
;
317 /* Iteraratively drop into each successive lower count */
318 switch (SubAuthorityCount
)
320 /* And copy the needed subahority */
321 case 8: pSid
->SubAuthority
[7] = SubAuthority7
;
322 case 7: pSid
->SubAuthority
[6] = SubAuthority6
;
323 case 6: pSid
->SubAuthority
[5] = SubAuthority5
;
324 case 5: pSid
->SubAuthority
[4] = SubAuthority4
;
325 case 4: pSid
->SubAuthority
[3] = SubAuthority3
;
326 case 3: pSid
->SubAuthority
[2] = SubAuthority2
;
327 case 2: pSid
->SubAuthority
[1] = SubAuthority1
;
328 case 1: pSid
->SubAuthority
[0] = SubAuthority0
;
332 /* Return the allocated SID */
334 return STATUS_SUCCESS
;
342 RtlConvertSidToUnicodeString(IN PUNICODE_STRING String
,
344 IN BOOLEAN AllocateBuffer
)
353 if (!RtlValidSid(Sid
)) return STATUS_INVALID_SID
;
356 wcs
+= swprintf(wcs
, L
"S-1-");
358 if ((Sid
->IdentifierAuthority
.Value
[0] == 0) &&
359 (Sid
->IdentifierAuthority
.Value
[1] == 0))
363 (ULONG
)Sid
->IdentifierAuthority
.Value
[2] << 24 |
364 (ULONG
)Sid
->IdentifierAuthority
.Value
[3] << 16 |
365 (ULONG
)Sid
->IdentifierAuthority
.Value
[4] << 8 |
366 (ULONG
)Sid
->IdentifierAuthority
.Value
[5]);
371 L
"0x%02hx%02hx%02hx%02hx%02hx%02hx",
372 Sid
->IdentifierAuthority
.Value
[0],
373 Sid
->IdentifierAuthority
.Value
[1],
374 Sid
->IdentifierAuthority
.Value
[2],
375 Sid
->IdentifierAuthority
.Value
[3],
376 Sid
->IdentifierAuthority
.Value
[4],
377 Sid
->IdentifierAuthority
.Value
[5]);
380 for (i
= 0; i
< Sid
->SubAuthorityCount
; i
++)
382 wcs
+= swprintf(wcs
, L
"-%u", Sid
->SubAuthority
[i
]);
387 if (!RtlCreateUnicodeString(String
, Buffer
)) return STATUS_NO_MEMORY
;
391 Length
= (wcs
- Buffer
) * sizeof(WCHAR
);
393 if (Length
> String
->MaximumLength
) return STATUS_BUFFER_TOO_SMALL
;
395 String
->Length
= (USHORT
)Length
;
396 RtlCopyMemory(String
->Buffer
, Buffer
, Length
);
398 if (Length
< String
->MaximumLength
)
400 String
->Buffer
[Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
404 return STATUS_SUCCESS
;