* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* PURPOSE: Security manager
* FILE: lib/rtl/sid.c
* PROGRAMER: David Welch <welch@cwcom.net>
*/
#include <rtl.h>
#define NDEBUG
#include <debug.h>
#define TAG_SID 'diSp'
BOOLEAN
NTAPI
RtlValidSid(IN PSID Sid_)
{
PISID Sid = Sid_;
PAGED_CODE_RTL();
_SEH2_TRY
{
if ((Sid) &&
(((Sid->Revision & 0xF) != SID_REVISION) ||
(Sid->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES)))
{
_SEH2_YIELD(return FALSE);
}
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
_SEH2_YIELD(return FALSE);
}
_SEH2_END;
return TRUE;
}
* @implemented
*/
ULONG
NTAPI
RtlLengthRequiredSid(IN ULONG SubAuthorityCount)
{
PAGED_CODE_RTL();
return (ULONG)FIELD_OFFSET(SID,
SubAuthority[SubAuthorityCount]);
}
* @implemented
*/
NTSTATUS
NTAPI
RtlInitializeSid(IN PSID Sid_,
IN PSID_IDENTIFIER_AUTHORITY IdentifierAuthority,
IN UCHAR SubAuthorityCount)
{
PISID Sid = Sid_;
PAGED_CODE_RTL();
Sid->Revision = SID_REVISION;
Sid->SubAuthorityCount = SubAuthorityCount;
Sid->IdentifierAuthority = *IdentifierAuthority;
return STATUS_SUCCESS;
}
* @implemented
*/
PULONG
NTAPI
RtlSubAuthoritySid(IN PSID Sid_,
IN ULONG SubAuthority)
{
PISID Sid = Sid_;
PAGED_CODE_RTL();
return (PULONG)&Sid->SubAuthority[SubAuthority];
}
* @implemented
*/
PUCHAR
NTAPI
RtlSubAuthorityCountSid(IN PSID Sid_)
{
PISID Sid = Sid_;
PAGED_CODE_RTL();
return &Sid->SubAuthorityCount;
}
* @implemented
*/
PSID_IDENTIFIER_AUTHORITY
NTAPI
RtlIdentifierAuthoritySid(IN PSID Sid_)
{
PISID Sid = Sid_;
PAGED_CODE_RTL();
return &Sid->IdentifierAuthority;
}
* @implemented
*/
BOOLEAN
NTAPI
RtlEqualSid(IN PSID Sid1_,
IN PSID Sid2_)
{
PISID Sid1 = Sid1_, Sid2 = Sid2_;
PAGED_CODE_RTL();
if (*(PUSHORT)&Sid1->Revision != *(PUSHORT)&Sid2->Revision) return FALSE;
return RtlEqualMemory(Sid1, Sid2, RtlLengthSid(Sid1));
}
* @implemented
*/
ULONG
NTAPI
RtlLengthSid(IN PSID Sid_)
{
PISID Sid = Sid_;
PAGED_CODE_RTL();
return (ULONG)FIELD_OFFSET(SID,
SubAuthority[Sid->SubAuthorityCount]);
}
* @implemented
*/
NTSTATUS
NTAPI
RtlCopySid(IN ULONG BufferLength,
IN PSID Dest,
IN PSID Src)
{
ULONG SidLength;
PAGED_CODE_RTL();
SidLength = RtlLengthSid(Src);
if (SidLength > BufferLength) return STATUS_BUFFER_TOO_SMALL;
RtlMoveMemory(Dest, Src, SidLength);
return STATUS_SUCCESS;
}
* @implemented
*/
PVOID
NTAPI
RtlFreeSid(IN PSID Sid)
{
PAGED_CODE_RTL();
RtlpFreeMemory(Sid, TAG_SID);
return NULL;
}
* @implemented
*/
BOOLEAN
NTAPI
RtlEqualPrefixSid(IN PSID Sid1_,
IN PSID Sid2_)
{
PISID Sid1 = Sid1_, Sid2 = Sid2_;
ULONG i;
PAGED_CODE_RTL();
if (Sid1->Revision != Sid2->Revision) return FALSE;
if ((Sid1->IdentifierAuthority.Value[0] == Sid2->IdentifierAuthority.Value[0]) &&
(Sid1->IdentifierAuthority.Value[1] == Sid2->IdentifierAuthority.Value[1]) &&
(Sid1->IdentifierAuthority.Value[2] == Sid2->IdentifierAuthority.Value[2]) &&
(Sid1->IdentifierAuthority.Value[3] == Sid2->IdentifierAuthority.Value[3]) &&
(Sid1->IdentifierAuthority.Value[4] == Sid2->IdentifierAuthority.Value[4]) &&
(Sid1->IdentifierAuthority.Value[5] == Sid2->IdentifierAuthority.Value[5]))
{
if (Sid1->SubAuthorityCount == Sid2->SubAuthorityCount)
{
if (!Sid1->SubAuthorityCount) return TRUE;
for (i = 0; (i + 1) < Sid1->SubAuthorityCount; i++)
{
if (Sid1->SubAuthority[i] != Sid2->SubAuthority[i])
{
return FALSE;
}
}
return TRUE;
}
}
return FALSE;
}
* @implemented
*/
NTSTATUS
NTAPI
RtlCopySidAndAttributesArray(IN ULONG Count,
IN PSID_AND_ATTRIBUTES Src,
IN ULONG SidAreaSize,
IN PSID_AND_ATTRIBUTES Dest,
IN PSID SidArea,
OUT PSID* RemainingSidArea,
OUT PULONG RemainingSidAreaSize)
{
ULONG SidLength, i;
PAGED_CODE_RTL();
for (i = 0; i < Count; i++)
{
SidLength = RtlLengthSid(Src[i].Sid);
if (SidLength > SidAreaSize) return STATUS_BUFFER_TOO_SMALL;
SidAreaSize -= SidLength;
Dest[i].Sid = SidArea;
Dest[i].Attributes = Src[i].Attributes;
RtlCopySid(SidLength, SidArea, Src[i].Sid);
SidArea = (PSID)((ULONG_PTR)SidArea + SidLength);
}
*RemainingSidArea = SidArea;
*RemainingSidAreaSize = SidAreaSize;
return STATUS_SUCCESS;
}
* @implemented
*/
NTSTATUS
NTAPI
RtlAllocateAndInitializeSid(IN PSID_IDENTIFIER_AUTHORITY IdentifierAuthority,
IN UCHAR SubAuthorityCount,
IN ULONG SubAuthority0,
IN ULONG SubAuthority1,
IN ULONG SubAuthority2,
IN ULONG SubAuthority3,
IN ULONG SubAuthority4,
IN ULONG SubAuthority5,
IN ULONG SubAuthority6,
IN ULONG SubAuthority7,
OUT PSID *Sid)
{
PISID pSid;
PAGED_CODE_RTL();
if (SubAuthorityCount > 8) return STATUS_INVALID_SID;
pSid = RtlpAllocateMemory(RtlLengthRequiredSid(SubAuthorityCount), TAG_SID);
if (!pSid) return STATUS_NO_MEMORY;
pSid->Revision = SID_REVISION;
pSid->SubAuthorityCount = SubAuthorityCount;
pSid->IdentifierAuthority = *IdentifierAuthority;
switch (SubAuthorityCount)
{
case 8: pSid->SubAuthority[7] = SubAuthority7;
case 7: pSid->SubAuthority[6] = SubAuthority6;
case 6: pSid->SubAuthority[5] = SubAuthority5;
case 5: pSid->SubAuthority[4] = SubAuthority4;
case 4: pSid->SubAuthority[3] = SubAuthority3;
case 3: pSid->SubAuthority[2] = SubAuthority2;
case 2: pSid->SubAuthority[1] = SubAuthority1;
case 1: pSid->SubAuthority[0] = SubAuthority0;
default: break;
}
*Sid = pSid;
return STATUS_SUCCESS;
}
* @implemented
*/
NTSTATUS
NTAPI
RtlConvertSidToUnicodeString(IN PUNICODE_STRING String,
IN PSID Sid_,
IN BOOLEAN AllocateBuffer)
{
WCHAR Buffer[256];
PWSTR wcs;
SIZE_T Length;
ULONG i;
PISID Sid = Sid_;
PAGED_CODE_RTL();
if (!RtlValidSid(Sid)) return STATUS_INVALID_SID;
wcs = Buffer;
wcs += _swprintf(wcs, L"S-1-");
if ((Sid->IdentifierAuthority.Value[0] == 0) &&
(Sid->IdentifierAuthority.Value[1] == 0))
{
wcs += _swprintf(wcs,
L"%lu",
(ULONG)Sid->IdentifierAuthority.Value[2] << 24 |
(ULONG)Sid->IdentifierAuthority.Value[3] << 16 |
(ULONG)Sid->IdentifierAuthority.Value[4] << 8 |
(ULONG)Sid->IdentifierAuthority.Value[5]);
}
else
{
wcs += _swprintf(wcs,
L"0x%02hx%02hx%02hx%02hx%02hx%02hx",
Sid->IdentifierAuthority.Value[0],
Sid->IdentifierAuthority.Value[1],
Sid->IdentifierAuthority.Value[2],
Sid->IdentifierAuthority.Value[3],
Sid->IdentifierAuthority.Value[4],
Sid->IdentifierAuthority.Value[5]);
}
for (i = 0; i < Sid->SubAuthorityCount; i++)
{
wcs += _swprintf(wcs, L"-%u", Sid->SubAuthority[i]);
}
if (AllocateBuffer)
{
if (!RtlCreateUnicodeString(String, Buffer)) return STATUS_NO_MEMORY;
}
else
{
Length = (wcs - Buffer) * sizeof(WCHAR);
if (Length > String->MaximumLength) return STATUS_BUFFER_TOO_SMALL;
String->Length = (USHORT)Length;
RtlCopyMemory(String->Buffer, Buffer, Length);
if (Length < String->MaximumLength)
{
String->Buffer[Length / sizeof(WCHAR)] = UNICODE_NULL;
}
}
return STATUS_SUCCESS;
}
* @unimplemented
*/
NTSTATUS
NTAPI
RtlCreateServiceSid(
_In_ PUNICODE_STRING ServiceName,
_Out_writes_bytes_opt_(*ServiceSidLength) PSID ServiceSid,
_Inout_ PULONG ServiceSidLength)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}