/* * Copyright (c) Likewise Software. All rights Reserved. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the license, or (at * your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * General Public License for more details. You should have received a copy * of the GNU Lesser General Public License along with this program. If * not, see . * * LIKEWISE SOFTWARE MAKES THIS SOFTWARE AVAILABLE UNDER OTHER LICENSING * TERMS AS WELL. IF YOU HAVE ENTERED INTO A SEPARATE LICENSE AGREEMENT * WITH LIKEWISE SOFTWARE, THEN YOU MAY ELECT TO USE THE SOFTWARE UNDER THE * TERMS OF THAT SOFTWARE LICENSE AGREEMENT INSTEAD OF THE TERMS OF THE GNU * LESSER GENERAL PUBLIC LICENSE, NOTWITHSTANDING THE ABOVE NOTICE. IF YOU * HAVE QUESTIONS, OR WISH TO REQUEST A COPY OF THE ALTERNATE LICENSING * TERMS OFFERED BY LIKEWISE SOFTWARE, PLEASE CONTACT LIKEWISE SOFTWARE AT * license@likewisesoftware.com */ /* * Module Name: * * security-sid.c * * Abstract: * * SID Functions in Security Module. * * Authors: Danilo Almeida (dalmeida@likewise.com) * */ #include "security-includes.h" // TODO-Move s*printf replacement functions to rtlstring.h // For snprintf #include // // SID Functions // NTSTATUS RtlInitializeSid( OUT PSID Sid, IN PSID_IDENTIFIER_AUTHORITY IdentifierAuthority, IN UCHAR SubAuthorityCount ) { NTSTATUS status = STATUS_SUCCESS; if (!Sid || !IdentifierAuthority) { status = STATUS_INVALID_PARAMETER; GOTO_CLEANUP(); } if (SubAuthorityCount > SID_MAX_SUB_AUTHORITIES) { status = STATUS_INVALID_PARAMETER; GOTO_CLEANUP(); } Sid->Revision = SID_REVISION; Sid->SubAuthorityCount = SubAuthorityCount; memcpy(&Sid->IdentifierAuthority, IdentifierAuthority, sizeof(*IdentifierAuthority)); memset(Sid->SubAuthority, 0, sizeof(Sid->SubAuthority[0]) * SubAuthorityCount); cleanup: return status; } ULONG RtlLengthRequiredSid( IN ULONG SubAuthorityCount ) { return _SID_GET_SIZE_REQUIRED(SubAuthorityCount); } ULONG RtlLengthSid( IN PSID Sid ) { return RtlLengthRequiredSid(Sid->SubAuthorityCount); } BOOLEAN RtlValidSid( IN PSID Sid ) { return ((Sid != NULL) && (Sid->Revision == SID_REVISION) && (Sid->SubAuthorityCount <= SID_MAX_SUB_AUTHORITIES)); } BOOLEAN RtlEqualSid( IN PSID Sid1, IN PSID Sid2 ) { return ((Sid1->SubAuthorityCount == Sid2->SubAuthorityCount) && RtlEqualMemory(Sid1, Sid2, RtlLengthSid(Sid1))); } BOOLEAN RtlEqualPrefixSid( IN PSID Sid1, IN PSID Sid2 ) { BOOLEAN isEqual = FALSE; if (Sid1->SubAuthorityCount == Sid2->SubAuthorityCount) { UCHAR count = Sid1->SubAuthorityCount; if (count > 0) { count--; } isEqual = RtlEqualMemory(Sid1, Sid2, RtlLengthRequiredSid(count)); } return isEqual; } BOOLEAN RtlIsPrefixSid( IN PSID Prefix, IN PSID Sid ) { /* * memory-compare only the part starting from IdentifierAuthority * (basically, skip SubAuthorityCount which is different in both SIDs) */ ULONG ulAuthSidLength = RtlLengthSid(Prefix) - (sizeof(Prefix->Revision) + sizeof(Prefix->SubAuthorityCount)); return ((Prefix->SubAuthorityCount <= Sid->SubAuthorityCount) && (Prefix->Revision == Sid->Revision) && RtlEqualMemory(&Prefix->IdentifierAuthority, &Sid->IdentifierAuthority, ulAuthSidLength)); } NTSTATUS RtlCopySid( IN ULONG DestinationSidLength, OUT PSID DestinationSid, IN PSID SourceSid ) { NTSTATUS status = STATUS_SUCCESS; ULONG length = RtlLengthSid(SourceSid); if (DestinationSidLength < length) { status = STATUS_BUFFER_TOO_SMALL; GOTO_CLEANUP(); } RtlCopyMemory(DestinationSid, SourceSid, length); cleanup: return status; } NTSTATUS RtlAppendRidSid( IN ULONG SidLength, IN OUT PSID Sid, IN ULONG Rid ) { NTSTATUS status = STATUS_SUCCESS; ULONG length = 0; if (Sid->SubAuthorityCount >= SID_MAX_SUB_AUTHORITIES) { status = STATUS_INVALID_PARAMETER; GOTO_CLEANUP(); } length = RtlLengthRequiredSid(Sid->SubAuthorityCount + 1); if (SidLength < length) { status = STATUS_BUFFER_TOO_SMALL; GOTO_CLEANUP(); } Sid->SubAuthority[Sid->SubAuthorityCount] = Rid; Sid->SubAuthorityCount++; cleanup: return status; } NTSTATUS RtlDuplicateSid( OUT PSID* NewSid, IN PSID OriginalSid ) { NTSTATUS status = STATUS_SUCCESS; ULONG length = RtlLengthSid(OriginalSid); PSID resultSid = NULL; status = RTL_ALLOCATE(&resultSid, SID, length); GOTO_CLEANUP_ON_STATUS(status); RtlCopyMemory(resultSid, OriginalSid, length); cleanup: if (!NT_SUCCESS(status)) { RTL_FREE(&resultSid); } *NewSid = resultSid; return status; } BOOLEAN RtlpIsValidLittleEndianSidBuffer( IN PVOID Buffer, IN ULONG BufferSize, OUT PULONG BufferUsed ) { NTSTATUS status = STATUS_SUCCESS; PSID littleEndianSid = (PSID) Buffer; ULONG size = 0; if (BufferSize < SID_MIN_SIZE) { status = STATUS_INVALID_SID; GOTO_CLEANUP(); } size = RtlLengthRequiredSid(LW_LTOH8(littleEndianSid->SubAuthorityCount)); if (!RtlpIsBufferAvailable(BufferSize, 0, size)) { status = STATUS_INVALID_SID; GOTO_CLEANUP(); } // This is ok since it only looks at 1-byte fields: status = RtlValidSid(littleEndianSid) ? STATUS_SUCCESS : STATUS_INVALID_SID; cleanup: *BufferUsed = NT_SUCCESS(status) ? size : 0; return NT_SUCCESS(status); } NTSTATUS RtlpEncodeLittleEndianSid( IN PSID Sid, OUT PVOID Buffer, IN ULONG BufferSize, OUT PULONG BufferUsed ) { NTSTATUS status = STATUS_SUCCESS; PSID littleEndianSid = (PSID) Buffer; ULONG size = RtlLengthSid(Sid); ULONG i = 0; if (BufferSize < size) { status = STATUS_BUFFER_TOO_SMALL; GOTO_CLEANUP(); } littleEndianSid->Revision = LW_HTOL8(Sid->Revision); littleEndianSid->SubAuthorityCount = LW_HTOL8(Sid->SubAuthorityCount); // sequence of bytes littleEndianSid->IdentifierAuthority = Sid->IdentifierAuthority; for (i = 0; i < Sid->SubAuthorityCount; i++) { littleEndianSid->SubAuthority[i] = LW_HTOL32(Sid->SubAuthority[i]); } status = STATUS_SUCCESS; cleanup: *BufferUsed = NT_SUCCESS(status) ? size : 0; return status; } VOID RtlpDecodeLittleEndianSid( IN PSID LittleEndianSid, OUT PSID Sid ) { ULONG i = 0; Sid->Revision = LW_LTOH8(LittleEndianSid->Revision); Sid->SubAuthorityCount = LW_LTOH8(LittleEndianSid->SubAuthorityCount); // sequence of bytes Sid->IdentifierAuthority = LittleEndianSid->IdentifierAuthority; for (i = 0; i < Sid->SubAuthorityCount; i++) { Sid->SubAuthority[i] = LW_LTOH32(LittleEndianSid->SubAuthority[i]); } } // // SID <-> String Conversion Functions // // // A string SID is represented as: // // "S-" REV "-" AUTH ("-" SUB_AUTH ) * SubAuthorityCount // // where: // // - REV is a decimal UCHAR (max 3 characters). // // - AUTH is either a decimal ULONG (max 10 characters) or // "0x" followed by a 6-byte hex value (max 2 + 12 = 14 characters). // // - SUB_AUTH is a decimal ULONG (max 10 characters). // #define RTLP_STRING_SID_MAX_CHARS(SubAuthorityCount) \ (2 + 3 + 1 + 14 + (1 + 10) * (SubAuthorityCount) + 1) NTSTATUS RtlAllocateUnicodeStringFromSid( OUT PUNICODE_STRING StringSid, IN PSID Sid ) { NTSTATUS status = STATUS_SUCCESS; PWSTR resultBuffer = NULL; UNICODE_STRING result = { 0 }; if (!StringSid) { status = STATUS_INVALID_PARAMETER; GOTO_CLEANUP(); } status = RtlAllocateWC16StringFromSid(&resultBuffer, Sid); GOTO_CLEANUP_ON_STATUS(status); status = RtlUnicodeStringInitEx(&result, resultBuffer); GOTO_CLEANUP_ON_STATUS(status); resultBuffer = NULL; status = STATUS_SUCCESS; cleanup: if (!NT_SUCCESS(status)) { RtlUnicodeStringFree(&result); } RTL_FREE(&resultBuffer); if (StringSid) { *StringSid = result; } return status; } NTSTATUS RtlAllocateAnsiStringFromSid( OUT PANSI_STRING StringSid, IN PSID Sid ) { NTSTATUS status = STATUS_SUCCESS; PSTR resultBuffer = NULL; ANSI_STRING result = { 0 }; if (!StringSid) { status = STATUS_INVALID_PARAMETER; GOTO_CLEANUP(); } status = RtlAllocateCStringFromSid(&resultBuffer, Sid); GOTO_CLEANUP_ON_STATUS(status); status = RtlAnsiStringInitEx(&result, resultBuffer); GOTO_CLEANUP_ON_STATUS(status); resultBuffer = NULL; status = STATUS_SUCCESS; cleanup: if (!NT_SUCCESS(status)) { RtlAnsiStringFree(&result); } RTL_FREE(&resultBuffer); if (StringSid) { *StringSid = result; } return status; } NTSTATUS RtlAllocateWC16StringFromSid( OUT PWSTR* StringSid, IN PSID Sid ) { NTSTATUS status = STATUS_SUCCESS; PWSTR result = NULL; PSTR convertString = NULL; if (!StringSid) { status = STATUS_INVALID_PARAMETER; GOTO_CLEANUP(); } status = RtlAllocateCStringFromSid(&convertString, Sid); GOTO_CLEANUP_ON_STATUS(status); status = RtlWC16StringAllocateFromCString(&result, convertString); GOTO_CLEANUP_ON_STATUS(status); cleanup: if (!NT_SUCCESS(status)) { RTL_FREE(&result); } RTL_FREE(&convertString); if (StringSid) { *StringSid = result; } return status; } NTSTATUS RtlAllocateCStringFromSid( OUT PSTR* StringSid, IN PSID Sid ) { NTSTATUS status = STATUS_SUCCESS; PSTR result = NULL; size_t size = 0; int count = 0; ULONG i = 0; if (!StringSid || !RtlValidSid(Sid)) { status = STATUS_INVALID_PARAMETER; GOTO_CLEANUP(); } size = RTLP_STRING_SID_MAX_CHARS(Sid->SubAuthorityCount); status = RTL_ALLOCATE(&result, CHAR, size); GOTO_CLEANUP_ON_STATUS(status); if (Sid->IdentifierAuthority.Value[0] || Sid->IdentifierAuthority.Value[1]) { count += snprintf(result + count, size - count, "S-%u-0x%.2X%.2X%.2X%.2X%.2X%.2X", Sid->Revision, Sid->IdentifierAuthority.Value[0], Sid->IdentifierAuthority.Value[1], Sid->IdentifierAuthority.Value[2], Sid->IdentifierAuthority.Value[3], Sid->IdentifierAuthority.Value[4], Sid->IdentifierAuthority.Value[5]); } else { ULONG value = 0; value |= (ULONG) Sid->IdentifierAuthority.Value[5]; value |= (ULONG) Sid->IdentifierAuthority.Value[4] << 8; value |= (ULONG) Sid->IdentifierAuthority.Value[3] << 16; value |= (ULONG) Sid->IdentifierAuthority.Value[2] << 24; count += snprintf(result + count, size - count, "S-%u-%u", Sid->Revision, value); } for (i = 0; i < Sid->SubAuthorityCount; i++) { count += snprintf(result + count, size - count, "-%u", Sid->SubAuthority[i]); } status = STATUS_SUCCESS; cleanup: if (!NT_SUCCESS(status)) { RTL_FREE(&result); } if (StringSid) { *StringSid = result; } return status; } static NTSTATUS RtlpConvertUnicodeStringSidToSidEx( IN PUNICODE_STRING StringSid, OUT OPTIONAL PSID* AllocateSid, OUT OPTIONAL PSID SidBuffer, IN OUT OPTIONAL PULONG SidBufferSize ) { NTSTATUS status = STATUS_SUCCESS; UCHAR sidBuffer[SID_MAX_SIZE] = { 0 }; PSID sid = (PSID) sidBuffer; BOOLEAN haveRevision = FALSE; BOOLEAN haveAuthority = FALSE; UNICODE_STRING remaining = { 0 }; PSID newSid = NULL; ULONG sizeRequired = 0; if (!StringSid || (AllocateSid && (SidBuffer || SidBufferSize)) || !(AllocateSid || SidBufferSize)) { status = STATUS_INVALID_PARAMETER; GOTO_CLEANUP(); } // Must have at least 2 characters and they must be "S-" if (!((StringSid->Length > (2 * sizeof(StringSid->Buffer[0]))) && ((StringSid->Buffer[0] == 'S') || (StringSid->Buffer[0] == 's')) && (StringSid->Buffer[1] == '-'))) { status = STATUS_INVALID_SID; GOTO_CLEANUP(); } // Skip the "S-" prefix remaining.Buffer = &StringSid->Buffer[2]; remaining.Length = StringSid->Length - (2 * sizeof(StringSid->Buffer[0])); remaining.MaximumLength = remaining.Length; // TODO-Handle S-1-0xHEX-... for more than 4 bytes in IdentifierAuth. for (;;) { ULONG value = 0; status = LwRtlUnicodeStringParseULONG(&value, &remaining, &remaining); if (!NT_SUCCESS(status)) { break; } if (remaining.Length) { if (remaining.Buffer[0] != '-') { status = STATUS_INVALID_SID; GOTO_CLEANUP(); } remaining.Buffer++; remaining.Length -= sizeof(remaining.Buffer[0]); remaining.MaximumLength = remaining.Length; } if (!haveRevision) { if (value > MAXUCHAR) { status = STATUS_INVALID_SID; GOTO_CLEANUP(); } sid->Revision = (UCHAR) value; haveRevision = TRUE; } else if (!haveAuthority) { // Authority is represented as a 32-bit number. sid->IdentifierAuthority.Value[5] = (value & 0x000000FF); sid->IdentifierAuthority.Value[4] = (value & 0x0000FF00) >> 8; sid->IdentifierAuthority.Value[3] = (value & 0x00FF0000) >> 16; sid->IdentifierAuthority.Value[2] = (value & 0xFF000000) >> 24; haveAuthority = TRUE; } else { if (sid->SubAuthorityCount >= SID_MAX_SUB_AUTHORITIES) { status = STATUS_INVALID_SID; GOTO_CLEANUP(); } sid->SubAuthority[sid->SubAuthorityCount] = value; sid->SubAuthorityCount++; } } if (!haveAuthority || remaining.Length || !RtlValidSid(sid)) { status = STATUS_INVALID_SID; GOTO_CLEANUP(); } sizeRequired = RtlLengthSid(sid); if (AllocateSid) { status = RTL_ALLOCATE(&newSid, SID, sizeRequired); GOTO_CLEANUP_ON_STATUS(status); RtlCopyMemory(newSid, sid, sizeRequired); } else if (SidBufferSize) { if (*SidBufferSize < sizeRequired) { status = STATUS_BUFFER_TOO_SMALL; GOTO_CLEANUP(); } if (SidBuffer) { RtlCopyMemory(SidBuffer, sid, sizeRequired); } } else { status = STATUS_ASSERTION_FAILURE; GOTO_CLEANUP(); } status = STATUS_SUCCESS; cleanup: if (!NT_SUCCESS(status)) { RTL_FREE(&newSid); sid = NULL; } if (AllocateSid) { *AllocateSid = newSid; } if (SidBufferSize) { *SidBufferSize = sizeRequired; } return status; } static NTSTATUS RtlpConvertAnsiStringSidToSidEx( IN PANSI_STRING StringSid, OUT OPTIONAL PSID* AllocateSid, OUT OPTIONAL PSID SidBuffer, IN OUT OPTIONAL PULONG SidBufferSize ) { NTSTATUS status = STATUS_SUCCESS; UCHAR sidBuffer[SID_MAX_SIZE] = { 0 }; PSID sid = (PSID) sidBuffer; BOOLEAN haveRevision = FALSE; BOOLEAN haveAuthority = FALSE; ANSI_STRING remaining = { 0 }; PSID newSid = NULL; ULONG sizeRequired = 0; if (!StringSid || (AllocateSid && (SidBuffer || SidBufferSize)) || !(AllocateSid || SidBufferSize)) { status = STATUS_INVALID_PARAMETER; GOTO_CLEANUP(); } // Must have at least 2 characters and they must be "S-" if (!((StringSid->Length > (2 * sizeof(StringSid->Buffer[0]))) && ((StringSid->Buffer[0] == 'S') || (StringSid->Buffer[0] == 's')) && (StringSid->Buffer[1] == '-'))) { status = STATUS_INVALID_SID; GOTO_CLEANUP(); } // Skip the "S-" prefix remaining.Buffer = &StringSid->Buffer[2]; remaining.Length = StringSid->Length - (2 * sizeof(StringSid->Buffer[0])); remaining.MaximumLength = remaining.Length; // TODO-Handle S-1-0xHEX-... for more than 4 bytes in IdentifierAuth. for (;;) { ULONG value = 0; status = LwRtlAnsiStringParseULONG(&value, &remaining, &remaining); if (!NT_SUCCESS(status)) { break; } if (remaining.Length) { if (remaining.Buffer[0] != '-') { status = STATUS_INVALID_SID; GOTO_CLEANUP(); } remaining.Buffer++; remaining.Length -= sizeof(remaining.Buffer[0]); remaining.MaximumLength = remaining.Length; } if (!haveRevision) { if (value > MAXUCHAR) { status = STATUS_INVALID_SID; GOTO_CLEANUP(); } sid->Revision = (UCHAR) value; haveRevision = TRUE; } else if (!haveAuthority) { // Authority is represented as a 32-bit number. sid->IdentifierAuthority.Value[5] = (value & 0x000000FF); sid->IdentifierAuthority.Value[4] = (value & 0x0000FF00) >> 8; sid->IdentifierAuthority.Value[3] = (value & 0x00FF0000) >> 16; sid->IdentifierAuthority.Value[2] = (value & 0xFF000000) >> 24; haveAuthority = TRUE; } else { if (sid->SubAuthorityCount >= SID_MAX_SUB_AUTHORITIES) { status = STATUS_INVALID_SID; GOTO_CLEANUP(); } sid->SubAuthority[sid->SubAuthorityCount] = value; sid->SubAuthorityCount++; } } if (!haveAuthority || remaining.Length || !RtlValidSid(sid)) { status = STATUS_INVALID_SID; GOTO_CLEANUP(); } sizeRequired = RtlLengthSid(sid); if (AllocateSid) { status = RTL_ALLOCATE(&newSid, SID, sizeRequired); GOTO_CLEANUP_ON_STATUS(status); RtlCopyMemory(newSid, sid, sizeRequired); } else if (SidBufferSize) { if (*SidBufferSize < sizeRequired) { status = STATUS_BUFFER_TOO_SMALL; GOTO_CLEANUP(); } if (SidBuffer) { RtlCopyMemory(SidBuffer, sid, sizeRequired); } } else { status = STATUS_ASSERTION_FAILURE; GOTO_CLEANUP(); } status = STATUS_SUCCESS; cleanup: if (!NT_SUCCESS(status)) { RTL_FREE(&newSid); sid = NULL; } if (AllocateSid) { *AllocateSid = newSid; } if (SidBufferSize) { *SidBufferSize = sizeRequired; } return status; } NTSTATUS RtlAllocateSidFromUnicodeString( OUT PSID* Sid, IN PUNICODE_STRING StringSid ) { return RtlpConvertUnicodeStringSidToSidEx(StringSid, Sid, NULL, NULL); } NTSTATUS RtlAllocateSidFromAnsiString( OUT PSID* Sid, IN PANSI_STRING StringSid ) { return RtlpConvertAnsiStringSidToSidEx(StringSid, Sid, NULL, NULL); } NTSTATUS RtlAllocateSidFromCString( OUT PSID* Sid, IN PCSTR StringSid ) { NTSTATUS status = STATUS_SUCCESS; PSID sid = NULL; ANSI_STRING stringSid = { 0 }; status = RtlAnsiStringInitEx(&stringSid, StringSid); GOTO_CLEANUP_ON_STATUS(status); status = RtlpConvertAnsiStringSidToSidEx(&stringSid, &sid, NULL, NULL); GOTO_CLEANUP_ON_STATUS(status); cleanup: if (!NT_SUCCESS(status)) { RTL_FREE(&sid); } *Sid = sid; return status; } NTSTATUS RtlAllocateSidFromWC16String( OUT PSID* Sid, IN PCWSTR StringSid ) { NTSTATUS status = STATUS_SUCCESS; PSID sid = NULL; UNICODE_STRING stringSid = { 0 }; status = RtlUnicodeStringInitEx(&stringSid, StringSid); GOTO_CLEANUP_ON_STATUS(status); status = RtlAllocateSidFromUnicodeString(&sid, &stringSid); GOTO_CLEANUP_ON_STATUS(status); cleanup: if (!NT_SUCCESS(status)) { RTL_FREE(&sid); } *Sid = sid; return status; } // // Well-Known SID Functions // NTSTATUS RtlCreateWellKnownSid( IN WELL_KNOWN_SID_TYPE WellKnownSidType, IN OPTIONAL PSID DomainOrComputerSid, OUT OPTIONAL PSID Sid, IN OUT PULONG SidSize ) { NTSTATUS status = STATUS_SUCCESS; union { SID Sid; UCHAR Buffer[SID_MAX_SIZE]; } sidBuffer = { .Buffer = { 0 } }; ULONG size = *SidSize; ULONG sizeRequired = 0; ULONG i = 0; // Copy the domain (prefix) part of the SID switch (WellKnownSidType) { case WinWorldSid: { // S-1-1-0 SID_IDENTIFIER_AUTHORITY identifierAuthority = { SECURITY_WORLD_SID_AUTHORITY }; status = RtlInitializeSid(&sidBuffer.Sid, &identifierAuthority, 1); GOTO_CLEANUP_ON_STATUS(status); break; } case WinNetworkSid: { // S-1-1-2 SID_IDENTIFIER_AUTHORITY identifierAuthority = { SECURITY_WORLD_SID_AUTHORITY }; status = RtlInitializeSid(&sidBuffer.Sid, &identifierAuthority, 1); GOTO_CLEANUP_ON_STATUS(status); sidBuffer.Sid.SubAuthority[0] = SECURITY_NETWORK_RID; break; } case WinInteractiveSid: { // S-1-1-4 SID_IDENTIFIER_AUTHORITY identifierAuthority = { SECURITY_WORLD_SID_AUTHORITY }; status = RtlInitializeSid(&sidBuffer.Sid, &identifierAuthority, 1); GOTO_CLEANUP_ON_STATUS(status); sidBuffer.Sid.SubAuthority[0] = SECURITY_INTERACTIVE_RID; break; } case WinCreatorOwnerSid: { // S-1-3-0 SID_IDENTIFIER_AUTHORITY identifierAuthority = { SECURITY_CREATOR_SID_AUTHORITY }; status = RtlInitializeSid(&sidBuffer.Sid, &identifierAuthority, 1); GOTO_CLEANUP_ON_STATUS(status); sidBuffer.Sid.SubAuthority[0] = SECURITY_CREATOR_OWNER_RID; break; } case WinCreatorGroupSid: { // S-1-3-1 SID_IDENTIFIER_AUTHORITY identifierAuthority = { SECURITY_CREATOR_SID_AUTHORITY }; status = RtlInitializeSid(&sidBuffer.Sid, &identifierAuthority, 1); GOTO_CLEANUP_ON_STATUS(status); sidBuffer.Sid.SubAuthority[0] = SECURITY_CREATOR_GROUP_RID; break; } case WinAuthenticatedUserSid: { // S-1-5-11 SID_IDENTIFIER_AUTHORITY identifierAuthority = { SECURITY_NT_AUTHORITY }; status = RtlInitializeSid(&sidBuffer.Sid, &identifierAuthority, 1); GOTO_CLEANUP_ON_STATUS(status); sidBuffer.Sid.SubAuthority[0] = SECURITY_AUTHENTICATED_USER_RID; break; } case WinLocalSystemSid: { // S-1-5-18 SID_IDENTIFIER_AUTHORITY identifierAuthority = { SECURITY_NT_AUTHORITY }; status = RtlInitializeSid(&sidBuffer.Sid, &identifierAuthority, 1); GOTO_CLEANUP_ON_STATUS(status); sidBuffer.Sid.SubAuthority[0] = SECURITY_LOCAL_SYSTEM_RID; break; } case WinLocalServiceSid: { // S-1-5-19 SID_IDENTIFIER_AUTHORITY identifierAuthority = { SECURITY_NT_AUTHORITY }; status = RtlInitializeSid(&sidBuffer.Sid, &identifierAuthority, 1); GOTO_CLEANUP_ON_STATUS(status); sidBuffer.Sid.SubAuthority[0] = SECURITY_LOCAL_SERVICE_RID; break; } case WinBuiltinDomainSid: { // (S-1-5-32) SID_IDENTIFIER_AUTHORITY identifierAuthority = { SECURITY_NT_AUTHORITY }; status = RtlInitializeSid(&sidBuffer.Sid, &identifierAuthority, 1); GOTO_CLEANUP_ON_STATUS(status); sidBuffer.Sid.SubAuthority[i++] = SECURITY_BUILTIN_DOMAIN_RID; break; } case WinBuiltinAdministratorsSid: case WinBuiltinUsersSid: case WinBuiltinGuestsSid: case WinBuiltinPowerUsersSid: case WinBuiltinPrintOperatorsSid: case WinBuiltinBackupOperatorsSid: { // BUILTIN SIDs (S-1-5-32-X) SID_IDENTIFIER_AUTHORITY identifierAuthority = { SECURITY_NT_AUTHORITY }; status = RtlInitializeSid(&sidBuffer.Sid, &identifierAuthority, 2); GOTO_CLEANUP_ON_STATUS(status); sidBuffer.Sid.SubAuthority[i++] = SECURITY_BUILTIN_DOMAIN_RID; break; } case WinAccountAdministratorSid: case WinAccountGuestSid: case WinAccountDomainAdminsSid: case WinAccountDomainUsersSid: case WinAccountDomainGuestsSid: { SID_IDENTIFIER_AUTHORITY identifierAuthority = { SECURITY_NT_AUTHORITY }; status = RtlInitializeSid(&sidBuffer.Sid, &identifierAuthority, DomainOrComputerSid->SubAuthorityCount + 1); GOTO_CLEANUP_ON_STATUS(status); if (DomainOrComputerSid == NULL) { status = STATUS_INVALID_PARAMETER; GOTO_CLEANUP_ON_STATUS(status); } for (i = 0; i < DomainOrComputerSid->SubAuthorityCount; i++) { sidBuffer.Sid.SubAuthority[i] = DomainOrComputerSid->SubAuthority[i]; } break; } default: { status = STATUS_NOT_IMPLEMENTED; GOTO_CLEANUP(); } } // Append the RID switch (WellKnownSidType) { case WinBuiltinAdministratorsSid: { // S-1-5-32-544 sidBuffer.Sid.SubAuthority[i] = DOMAIN_ALIAS_RID_ADMINS; break; } case WinBuiltinUsersSid: { // S-1-5-32-545 sidBuffer.Sid.SubAuthority[i] = DOMAIN_ALIAS_RID_USERS; break; } case WinBuiltinGuestsSid: { // S-1-5-32-546 sidBuffer.Sid.SubAuthority[i] = DOMAIN_ALIAS_RID_GUESTS; break; } case WinBuiltinPowerUsersSid: { // S-1-5-32-545 sidBuffer.Sid.SubAuthority[i] = DOMAIN_ALIAS_RID_POWER_USERS; break; } case WinBuiltinPrintOperatorsSid: { // S-1-5-32-550 sidBuffer.Sid.SubAuthority[i] = DOMAIN_ALIAS_RID_PRINT_OPS; break; } case WinBuiltinBackupOperatorsSid: { // S-1-5-32-551 sidBuffer.Sid.SubAuthority[i] = DOMAIN_ALIAS_RID_BACKUP_OPS; break; } case WinAccountAdministratorSid: { // S-1-5-21-X-Y-Z-500 sidBuffer.Sid.SubAuthority[i] = DOMAIN_USER_RID_ADMIN; break; } case WinAccountGuestSid: { // S-1-5-21-X-Y-Z-501 sidBuffer.Sid.SubAuthority[i] = DOMAIN_USER_RID_GUEST; break; } case WinAccountDomainAdminsSid: { // S-1-5-21-X-Y-Z-512 sidBuffer.Sid.SubAuthority[i] = DOMAIN_GROUP_RID_ADMINS; break; } case WinAccountDomainUsersSid: { // S-1-5-21-X-Y-Z-513 sidBuffer.Sid.SubAuthority[i] = DOMAIN_GROUP_RID_USERS; break; } case WinAccountDomainGuestsSid: { // S-1-5-21-X-Y-Z-514 sidBuffer.Sid.SubAuthority[i] = DOMAIN_GROUP_RID_GUESTS; break; } } sizeRequired = RtlLengthSid(&sidBuffer.Sid); if (size < sizeRequired) { status = STATUS_BUFFER_TOO_SMALL; GOTO_CLEANUP(); } RtlCopyMemory(Sid, &sidBuffer.Sid, sizeRequired); status = STATUS_SUCCESS; cleanup: if (!NT_SUCCESS(status)) { if (Sid) { RtlZeroMemory(Sid, size); } } *SidSize = sizeRequired; return status; } /* local variables: mode: c c-basic-offset: 4 indent-tabs-mode: nil tab-width: 4 end: */