/* * @implemented */ ULONG NTAPI RtlLengthSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor) { PISECURITY_DESCRIPTOR Sd; PSID Owner, Group; PACL Sacl, Dacl; ULONG Length; PAGED_CODE_RTL(); /* Start with the initial length of the SD itself */ Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor; if (Sd->Control & SE_SELF_RELATIVE) { Length = sizeof(SECURITY_DESCRIPTOR_RELATIVE); } else { Length = sizeof(SECURITY_DESCRIPTOR); } /* Add the length of the individual subcomponents */ Owner = SepGetOwnerFromDescriptor(Sd); if (Owner) Length += ROUND_UP(RtlLengthSid(Owner), sizeof(ULONG)); Group = SepGetGroupFromDescriptor(Sd); if (Group) Length += ROUND_UP(RtlLengthSid(Group), sizeof(ULONG)); Dacl = SepGetDaclFromDescriptor(Sd); if (Dacl) Length += ROUND_UP(Dacl->AclSize, sizeof(ULONG)); Sacl = SepGetSaclFromDescriptor(Sd); if (Sacl) Length += ROUND_UP(Sacl->AclSize, sizeof(ULONG)); /* Return the final length */ return Length; }
static ULONG RtlAccessTokenRelativeSize( PACCESS_TOKEN pToken ) { BOOLEAN isLocked = FALSE; ULONG ulRelativeSize = 0; ULONG i = 0; ulRelativeSize += sizeof(ACCESS_TOKEN_SELF_RELATIVE); Align32(&ulRelativeSize); SHARED_LOCK_RWLOCK(&pToken->RwLock, isLocked); ulRelativeSize += RtlLengthSid(pToken->User.Sid); Align32(&ulRelativeSize); if (pToken->Groups) { ulRelativeSize += sizeof(SID_AND_ATTRIBUTES_SELF_RELATIVE) * pToken->GroupCount; Align32(&ulRelativeSize); for (i = 0; i < pToken->GroupCount; i++) { ulRelativeSize += RtlLengthSid(pToken->Groups[i].Sid); Align32(&ulRelativeSize); } } if (pToken->Privileges) { ulRelativeSize += sizeof(pToken->Privileges[0]) * pToken->PrivilegeCount; Align32(&ulRelativeSize); } if (pToken->Owner) { ulRelativeSize += RtlLengthSid(pToken->Owner); Align32(&ulRelativeSize); } if (pToken->PrimaryGroup) { ulRelativeSize += RtlLengthSid(pToken->PrimaryGroup); Align32(&ulRelativeSize); } if (pToken->DefaultDacl) { ulRelativeSize += RtlGetAclSize(pToken->DefaultDacl); Align32(&ulRelativeSize); } UNLOCK_RWLOCK(&pToken->RwLock, isLocked); return ulRelativeSize; }
NTSTATUS LsaSrvDuplicateSid( PSID *ppSidOut, PSID pSidIn ) { NTSTATUS ntStatus = STATUS_SUCCESS; PSID pSid = NULL; ULONG ulSidSize = 0; ulSidSize = RtlLengthSid(pSidIn); ntStatus = LsaSrvAllocateMemory((void**)&pSid, ulSidSize); BAIL_ON_NTSTATUS_ERROR(ntStatus); ntStatus = RtlCopySid(ulSidSize, pSid, pSidIn); BAIL_ON_NTSTATUS_ERROR(ntStatus); *ppSidOut = pSid; cleanup: return ntStatus; error: if (pSid) { LsaSrvFreeMemory(pSid); } *ppSidOut = NULL; goto cleanup; }
NTSTATUS PhSvcCallAddAccountRight( _In_ PSID AccountSid, _In_ PUNICODE_STRING UserRight ) { NTSTATUS status; PHSVC_API_MSG m; PVOID accountSid = NULL; PVOID userRight = NULL; if (!PhSvcClPortHandle) return STATUS_PORT_DISCONNECTED; m.ApiNumber = PhSvcAddAccountRightApiNumber; status = STATUS_NO_MEMORY; if (!(accountSid = PhSvcpCreateString(AccountSid, RtlLengthSid(AccountSid), &m.u.AddAccountRight.i.AccountSid))) goto CleanupExit; if (!(userRight = PhSvcpCreateString(UserRight->Buffer, UserRight->Length, &m.u.AddAccountRight.i.UserRight))) goto CleanupExit; status = PhSvcpCallServer(&m); CleanupExit: if (userRight) PhSvcpFreeHeap(userRight); if (accountSid) PhSvcpFreeHeap(accountSid); 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; }
static DWORD NetAllocateLocalGroupMembersInfo0( PVOID *ppCursor, PDWORD pdwSpaceLeft, PVOID pSource, PDWORD pdwSize, NET_VALIDATION_LEVEL eValidation ) { DWORD err = ERROR_SUCCESS; PVOID pCursor = NULL; DWORD dwSpaceLeft = 0; DWORD dwSize = 0; PSID pSid = (PSID)pSource; DWORD dwSidLen = 0; if (pdwSpaceLeft) { dwSpaceLeft = *pdwSpaceLeft; } if (pdwSize) { dwSize = *pdwSize; } if (ppCursor) { pCursor = *ppCursor; } dwSidLen = RtlLengthSid(pSid); /* lgrmi0_sid */ err = NetAllocBufferSid(&pCursor, &dwSpaceLeft, pSid, dwSidLen, &dwSize, eValidation); BAIL_ON_WIN_ERROR(err); if (pdwSpaceLeft) { *pdwSpaceLeft = dwSpaceLeft; } if (pdwSize) { *pdwSize = dwSize; } cleanup: return err; error: goto cleanup; }
BOOLEAN RtlEqualSid( IN PSID Sid1, IN PSID Sid2 ) { return ((Sid1->SubAuthorityCount == Sid2->SubAuthorityCount) && RtlEqualMemory(Sid1, Sid2, RtlLengthSid(Sid1))); }
/* * @implemented */ NTSTATUS NTAPI RtlCopySid(ULONG BufferLength, PSID Dest, PSID Src) { PAGED_CODE_RTL(); if (BufferLength < RtlLengthSid(Src)) { return STATUS_UNSUCCESSFUL; } memmove(Dest, Src, RtlLengthSid(Src)); return STATUS_SUCCESS; }
NTSTATUS NTAPI SepCreateImpersonationTokenDacl(PTOKEN Token, PTOKEN PrimaryToken, PACL *Dacl) { ULONG AclLength; PVOID TokenDacl; PAGED_CODE(); AclLength = sizeof(ACL) + (sizeof(ACE) + RtlLengthSid(SeAliasAdminsSid)) + (sizeof(ACE) + RtlLengthSid(SeRestrictedCodeSid)) + (sizeof(ACE) + RtlLengthSid(SeLocalSystemSid)) + (sizeof(ACE) + RtlLengthSid(Token->UserAndGroups->Sid)) + (sizeof(ACE) + RtlLengthSid(PrimaryToken->UserAndGroups->Sid)); TokenDacl = ExAllocatePoolWithTag(PagedPool, AclLength, TAG_ACL); if (TokenDacl == NULL) { return STATUS_INSUFFICIENT_RESOURCES; } RtlCreateAcl(TokenDacl, AclLength, ACL_REVISION); RtlAddAccessAllowedAce(TokenDacl, ACL_REVISION, GENERIC_ALL, Token->UserAndGroups->Sid); RtlAddAccessAllowedAce(TokenDacl, ACL_REVISION, GENERIC_ALL, PrimaryToken->UserAndGroups->Sid); RtlAddAccessAllowedAce(TokenDacl, ACL_REVISION, GENERIC_ALL, SeAliasAdminsSid); RtlAddAccessAllowedAce(TokenDacl, ACL_REVISION, GENERIC_ALL, SeLocalSystemSid); /* FIXME */ #if 0 if (Token->RestrictedSids != NULL || PrimaryToken->RestrictedSids != NULL) { RtlAddAccessAllowedAce(TokenDacl, ACL_REVISION, GENERIC_ALL, SeRestrictedCodeSid); } #endif return STATUS_SUCCESS; }
/*++ * @name CsrCreateLocalSystemSD * * The CsrCreateLocalSystemSD routine creates a Security Descriptor for * the local account with PORT_ALL_ACCESS. * * @param LocalSystemSd * Pointer to a pointer to the security descriptor to create. * * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise. * * @remarks None. * *--*/ NTSTATUS NTAPI CsrCreateLocalSystemSD(OUT PSECURITY_DESCRIPTOR *LocalSystemSd) { SID_IDENTIFIER_AUTHORITY NtSidAuthority = {SECURITY_NT_AUTHORITY}; PSID SystemSid; ULONG Length; PSECURITY_DESCRIPTOR SystemSd; PACL Dacl; NTSTATUS Status; /* Initialize the System SID */ RtlAllocateAndInitializeSid(&NtSidAuthority, 1, SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0, &SystemSid); /* Get the length of the SID */ Length = RtlLengthSid(SystemSid) + sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE); /* Allocate a buffer for the Security Descriptor, with SID and DACL */ SystemSd = RtlAllocateHeap(CsrHeap, 0, SECURITY_DESCRIPTOR_MIN_LENGTH + Length); /* Set the pointer to the DACL */ Dacl = (PACL)((ULONG_PTR)SystemSd + SECURITY_DESCRIPTOR_MIN_LENGTH); /* Now create the SD itself */ Status = RtlCreateSecurityDescriptor(SystemSd, SECURITY_DESCRIPTOR_REVISION); if (!NT_SUCCESS(Status)) goto Quit; /* Create the DACL for it */ RtlCreateAcl(Dacl, Length, ACL_REVISION2); /* Create the ACE */ Status = RtlAddAccessAllowedAce(Dacl, ACL_REVISION, PORT_ALL_ACCESS, SystemSid); if (!NT_SUCCESS(Status)) goto Quit; /* Clear the DACL in the SD */ Status = RtlSetDaclSecurityDescriptor(SystemSd, TRUE, Dacl, FALSE); if (!NT_SUCCESS(Status)) goto Quit; Quit: if (!NT_SUCCESS(Status)) { RtlFreeHeap(CsrHeap, 0, SystemSd); SystemSd = NULL; } /* Free the SID and return*/ RtlFreeSid(SystemSid); *LocalSystemSd = SystemSd; return Status; }
/************************************************************************** * RtlCopySid [NTDLL.@] */ DWORD WINAPI RtlCopySid( DWORD nDestinationSidLength, PSID pDestinationSid, PSID pSourceSid ) { if (!pSourceSid || !RtlValidSid(pSourceSid) || (nDestinationSidLength < RtlLengthSid(pSourceSid))) return FALSE; if (nDestinationSidLength < (pSourceSid->SubAuthorityCount*4+8)) return FALSE; memmove(pDestinationSid, pSourceSid, pSourceSid->SubAuthorityCount*4+8); return TRUE; }
NTSTATUS LsapRpcCopySid( IN OPTIONAL PLSAP_MM_FREE_LIST FreeList, OUT PSID *DestinationSid, IN PSID SourceSid ) /*++ Routine Description: This function makes a copy of a Sid in which memory is allocated via MIDL user allocate. It is called to return Sids via RPC to the client. Arguments: FreeList - Optional pointer to Free List. DestinationSid - Receives a pointer to the Sid copy. SourceSid - Pointer to the Sid to be copied. Return Value: NTSTATUS - Standard Nt Result Code STATUS_SUCCESS - The call completed successfully. STATUS_INSUFFICIENT_RESOURCES - Insufficient system resources, such as memory, to complete the call. --*/ { NTSTATUS Status; ULONG SidLength = RtlLengthSid( SourceSid ); Status = LsapMmAllocateMidl( FreeList, DestinationSid, SidLength ); if (NT_SUCCESS(Status)) { RtlCopyMemory( *DestinationSid, SourceSid, SidLength ); } return( Status ); }
/****************************************************************************** * RtlEqualSid [NTDLL.@] * */ BOOL WINAPI RtlEqualSid( PSID pSid1, PSID pSid2 ) { if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2)) return FALSE; if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2)) return FALSE; if (memcmp(pSid1, pSid2, RtlLengthSid(pSid1)) != 0) return FALSE; return TRUE; }
/* * @implemented */ NTSTATUS NTAPI RtlCopySidAndAttributesArray(ULONG Count, PSID_AND_ATTRIBUTES Src, ULONG SidAreaSize, PSID_AND_ATTRIBUTES Dest, PVOID SidArea, PVOID* RemainingSidArea, PULONG RemainingSidAreaSize) { ULONG SidLength; ULONG Length; ULONG i; PAGED_CODE_RTL(); Length = SidAreaSize; for (i=0; i<Count; i++) { if (RtlLengthSid(Src[i].Sid) > Length) { return(STATUS_BUFFER_TOO_SMALL); } SidLength = RtlLengthSid(Src[i].Sid); Length = Length - SidLength; Dest[i].Sid = SidArea; Dest[i].Attributes = Src[i].Attributes; RtlCopySid(SidLength, SidArea, Src[i].Sid); SidArea = (PVOID)((ULONG_PTR)SidArea + SidLength); } *RemainingSidArea = SidArea; *RemainingSidAreaSize = Length; return(STATUS_SUCCESS); }
static NTSTATUS GetAccountDomainSid(PRPC_SID *Sid) { LSAPR_HANDLE PolicyHandle = NULL; PLSAPR_POLICY_INFORMATION PolicyInfo = NULL; ULONG Length = 0; NTSTATUS Status; Status = LsaIOpenPolicyTrusted(&PolicyHandle); if (!NT_SUCCESS(Status)) { TRACE("LsaIOpenPolicyTrusted() failed (Status 0x%08lx)\n", Status); return Status; } Status = LsarQueryInformationPolicy(PolicyHandle, PolicyAccountDomainInformation, &PolicyInfo); if (!NT_SUCCESS(Status)) { TRACE("LsarQueryInformationPolicy() failed (Status 0x%08lx)\n", Status); goto done; } Length = RtlLengthSid(PolicyInfo->PolicyAccountDomainInfo.Sid); *Sid = RtlAllocateHeap(RtlGetProcessHeap(), 0, Length); if (*Sid == NULL) { ERR("Failed to allocate SID\n"); Status = STATUS_INSUFFICIENT_RESOURCES; goto done; } memcpy(*Sid, PolicyInfo->PolicyAccountDomainInfo.Sid, Length); done: if (PolicyInfo != NULL) LsaIFree_LSAPR_POLICY_INFORMATION(PolicyAccountDomainInformation, PolicyInfo); if (PolicyHandle != NULL) LsarClose(&PolicyHandle); return Status; }
DWORD VmDirRESTCacheGetBuiltInAdminsGroupSid( PVDIR_REST_HEAD_CACHE pRestCache, PSID* ppBuiltInAdminsGroupSid ) { DWORD dwError = 0; ULONG ulSidLen = 0; BOOLEAN bInLock = FALSE; PSID pSid = NULL; if (!pRestCache || !ppBuiltInAdminsGroupSid) { BAIL_WITH_VMDIR_ERROR(dwError, VMDIR_ERROR_INVALID_PARAMETER); } VMDIR_RWLOCK_READLOCK(bInLock, gpVdirRestCache->pRWLock, 0); if (!RtlValidSid(pRestCache->pBuiltInAdminsGroupSid)) { BAIL_WITH_VMDIR_ERROR(dwError, VMDIR_ERROR_NOT_FOUND); } ulSidLen = RtlLengthSid(pRestCache->pBuiltInAdminsGroupSid); dwError = VmDirAllocateMemory(ulSidLen, (PVOID*)&pSid); BAIL_ON_VMDIR_ERROR(dwError); dwError = RtlCopySid(ulSidLen, pSid, pRestCache->pBuiltInAdminsGroupSid); BAIL_ON_VMDIR_ERROR(dwError); *ppBuiltInAdminsGroupSid = pSid; cleanup: VMDIR_RWLOCK_UNLOCK(bInLock, gpVdirRestCache->pRWLock); return dwError; error: VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "%s failed, error (%d)", __FUNCTION__, dwError); VMDIR_SAFE_FREE_MEMORY(pSid); goto cleanup; }
NTSTATUS LsarSetAccountDomain(PLSA_DB_OBJECT PolicyObject, PLSAPR_POLICY_ACCOUNT_DOM_INFO Info) { PUNICODE_STRING Buffer; ULONG Length = 0; NTSTATUS Status; LPWSTR Ptr; TRACE("(%p %p)\n", PolicyObject, Info); Length = sizeof(UNICODE_STRING) + Info->DomainName.MaximumLength; Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, Length); if (Buffer == NULL) return STATUS_INSUFFICIENT_RESOURCES; Buffer->Length = Info->DomainName.Length; Buffer->MaximumLength = Info->DomainName.MaximumLength; Buffer->Buffer = (LPWSTR)sizeof(UNICODE_STRING); Ptr = (LPWSTR)((ULONG_PTR)Buffer + sizeof(UNICODE_STRING)); memcpy(Ptr, Info->DomainName.Buffer, Info->DomainName.MaximumLength); Status = LsapSetObjectAttribute(PolicyObject, L"PolAcDmN", Buffer, Length); RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer); if (!NT_SUCCESS(Status)) return Status; Length = 0; if (Info->Sid != NULL) Length = RtlLengthSid(Info->Sid); Status = LsapSetObjectAttribute(PolicyObject, L"PolAcDmS", (LPBYTE)Info->Sid, Length); return Status; }
/* * @implemented */ BOOLEAN NTAPI RtlEqualSid(IN PSID Sid1_, IN PSID Sid2_) { PISID Sid1 = Sid1_; PISID Sid2 = Sid2_; SIZE_T SidLen; PAGED_CODE_RTL(); if (Sid1->Revision != Sid2->Revision || (*RtlSubAuthorityCountSid(Sid1)) != (*RtlSubAuthorityCountSid(Sid2))) { return(FALSE); } SidLen = RtlLengthSid(Sid1); return RtlCompareMemory(Sid1, Sid2, SidLen) == SidLen; }
static NTSTATUS RtlValidateSelfRelativeSid( PSID pSid, ULONG ulOffset, ULONG ulRelativeSize ) { NTSTATUS status = STATUS_SUCCESS; status = CheckOffset(ulOffset, SID_MIN_SIZE, ulRelativeSize); GOTO_CLEANUP_ON_STATUS(status); status = CheckOffset(ulOffset, RtlLengthSid(pSid), ulRelativeSize); GOTO_CLEANUP_ON_STATUS(status); cleanup: return status; }
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 LsaSrvAllocateSidFromWC16String( PSID *ppSid, PCWSTR pwszSidStr ) { NTSTATUS ntStatus = STATUS_SUCCESS; PSID pSid = NULL; ULONG ulSidSize = 0; PSID pSidCopy = NULL; ntStatus = RtlAllocateSidFromWC16String(&pSid, pwszSidStr); BAIL_ON_NTSTATUS_ERROR(ntStatus); ulSidSize = RtlLengthSid(pSid); ntStatus = LsaSrvAllocateMemory((void**)&pSidCopy, ulSidSize); BAIL_ON_NTSTATUS_ERROR(ntStatus); ntStatus = RtlCopySid(ulSidSize, pSidCopy, pSid); BAIL_ON_NTSTATUS_ERROR(ntStatus); *ppSid = pSidCopy; cleanup: if (pSid) { RTL_FREE(&pSid); } return ntStatus; error: if (pSidCopy) { LsaSrvFreeMemory(pSidCopy); } *ppSid = NULL; goto cleanup; }
/****************************************************************************** * RtlAddAccessDeniedAce [NTDLL.@] */ NTSTATUS WINAPI RtlAddAccessDeniedAce( IN OUT PACL pAcl, IN DWORD dwAceRevision, IN DWORD AccessMask, IN PSID pSid) { DWORD dwSidLength; ACCESS_DENIED_ACE* lpADA; TRACE("(%p,0x%08lx,0x%08lx,%p)!\n", pAcl, dwAceRevision, AccessMask, pSid); if( !RtlValidSid( pSid ) ) { return STATUS_INVALID_SID; } dwSidLength = RtlLengthSid( pSid ) - sizeof( DWORD ); if( !RtlFirstFreeAce( pAcl, (PACE_HEADER*)&lpADA) ) { if( lpADA == NULL ) return STATUS_INVALID_ACL; else return STATUS_ALLOTTED_SPACE_EXCEEDED; } if( ((BYTE*)lpADA + sizeof( *lpADA ) + dwSidLength ) > ((BYTE*)pAcl + pAcl->AclSize) ) { return STATUS_ALLOTTED_SPACE_EXCEEDED; } lpADA->Header.AceType = ACCESS_DENIED_ACE_TYPE; lpADA->Header.AceFlags = 0; /* Not set with RtlAddAccessDeniedAce. */ lpADA->Header.AceSize = sizeof( *lpADA ); lpADA->Mask = AccessMask; memcpy( &lpADA->SidStart, pSid, dwSidLength ); pAcl->AceCount++; return STATUS_SUCCESS; }
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; }
BOOLEAN INIT_FUNCTION NTAPI SepInitDACLs(VOID) { ULONG AclLength; /* create PublicDefaultDacl */ AclLength = sizeof(ACL) + (sizeof(ACE) + RtlLengthSid(SeWorldSid)) + (sizeof(ACE) + RtlLengthSid(SeLocalSystemSid)); SePublicDefaultDacl = ExAllocatePoolWithTag(PagedPool, AclLength, TAG_ACL); if (SePublicDefaultDacl == NULL) return FALSE; RtlCreateAcl(SePublicDefaultDacl, AclLength, ACL_REVISION); RtlAddAccessAllowedAce(SePublicDefaultDacl, ACL_REVISION, GENERIC_EXECUTE, SeWorldSid); RtlAddAccessAllowedAce(SePublicDefaultDacl, ACL_REVISION, GENERIC_ALL, SeLocalSystemSid); /* create PublicDefaultUnrestrictedDacl */ AclLength = sizeof(ACL) + (sizeof(ACE) + RtlLengthSid(SeWorldSid)) + (sizeof(ACE) + RtlLengthSid(SeLocalSystemSid)) + (sizeof(ACE) + RtlLengthSid(SeAliasAdminsSid)) + (sizeof(ACE) + RtlLengthSid(SeRestrictedCodeSid)); SePublicDefaultUnrestrictedDacl = ExAllocatePoolWithTag(PagedPool, AclLength, TAG_ACL); if (SePublicDefaultUnrestrictedDacl == NULL) return FALSE; RtlCreateAcl(SePublicDefaultUnrestrictedDacl, AclLength, ACL_REVISION); RtlAddAccessAllowedAce(SePublicDefaultUnrestrictedDacl, ACL_REVISION, GENERIC_EXECUTE, SeWorldSid); RtlAddAccessAllowedAce(SePublicDefaultUnrestrictedDacl, ACL_REVISION, GENERIC_ALL, SeLocalSystemSid); RtlAddAccessAllowedAce(SePublicDefaultUnrestrictedDacl, ACL_REVISION, GENERIC_ALL, SeAliasAdminsSid); RtlAddAccessAllowedAce(SePublicDefaultUnrestrictedDacl, ACL_REVISION, GENERIC_READ | GENERIC_EXECUTE | READ_CONTROL, SeRestrictedCodeSid); /* create PublicOpenDacl */ AclLength = sizeof(ACL) + (sizeof(ACE) + RtlLengthSid(SeWorldSid)) + (sizeof(ACE) + RtlLengthSid(SeLocalSystemSid)) + (sizeof(ACE) + RtlLengthSid(SeAliasAdminsSid)); SePublicOpenDacl = ExAllocatePoolWithTag(PagedPool, AclLength, TAG_ACL); if (SePublicOpenDacl == NULL) return FALSE; RtlCreateAcl(SePublicOpenDacl, AclLength, ACL_REVISION); RtlAddAccessAllowedAce(SePublicOpenDacl, ACL_REVISION, GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE, SeWorldSid); RtlAddAccessAllowedAce(SePublicOpenDacl, ACL_REVISION, GENERIC_ALL, SeLocalSystemSid); RtlAddAccessAllowedAce(SePublicOpenDacl, ACL_REVISION, GENERIC_ALL, SeAliasAdminsSid); /* create PublicOpenUnrestrictedDacl */ AclLength = sizeof(ACL) + (sizeof(ACE) + RtlLengthSid(SeWorldSid)) + (sizeof(ACE) + RtlLengthSid(SeLocalSystemSid)) + (sizeof(ACE) + RtlLengthSid(SeAliasAdminsSid)) + (sizeof(ACE) + RtlLengthSid(SeRestrictedCodeSid)); SePublicOpenUnrestrictedDacl = ExAllocatePoolWithTag(PagedPool, AclLength, TAG_ACL); if (SePublicOpenUnrestrictedDacl == NULL) return FALSE; RtlCreateAcl(SePublicOpenUnrestrictedDacl, AclLength, ACL_REVISION); RtlAddAccessAllowedAce(SePublicOpenUnrestrictedDacl, ACL_REVISION, GENERIC_ALL, SeWorldSid); RtlAddAccessAllowedAce(SePublicOpenUnrestrictedDacl, ACL_REVISION, GENERIC_ALL, SeLocalSystemSid); RtlAddAccessAllowedAce(SePublicOpenUnrestrictedDacl, ACL_REVISION, GENERIC_ALL, SeAliasAdminsSid); RtlAddAccessAllowedAce(SePublicOpenUnrestrictedDacl, ACL_REVISION, GENERIC_READ | GENERIC_EXECUTE, SeRestrictedCodeSid); /* create SystemDefaultDacl */ AclLength = sizeof(ACL) + (sizeof(ACE) + RtlLengthSid(SeLocalSystemSid)) + (sizeof(ACE) + RtlLengthSid(SeAliasAdminsSid)); SeSystemDefaultDacl = ExAllocatePoolWithTag(PagedPool, AclLength, TAG_ACL); if (SeSystemDefaultDacl == NULL) return FALSE; RtlCreateAcl(SeSystemDefaultDacl, AclLength, ACL_REVISION); RtlAddAccessAllowedAce(SeSystemDefaultDacl, ACL_REVISION, GENERIC_ALL, SeLocalSystemSid); RtlAddAccessAllowedAce(SeSystemDefaultDacl, ACL_REVISION, GENERIC_READ | GENERIC_EXECUTE | READ_CONTROL, SeAliasAdminsSid); /* create UnrestrictedDacl */ AclLength = sizeof(ACL) + (sizeof(ACE) + RtlLengthSid(SeWorldSid)) + (sizeof(ACE) + RtlLengthSid(SeRestrictedCodeSid)); SeUnrestrictedDacl = ExAllocatePoolWithTag(PagedPool, AclLength, TAG_ACL); if (SeUnrestrictedDacl == NULL) return FALSE; RtlCreateAcl(SeUnrestrictedDacl, AclLength, ACL_REVISION); RtlAddAccessAllowedAce(SeUnrestrictedDacl, ACL_REVISION, GENERIC_ALL, SeWorldSid); RtlAddAccessAllowedAce(SeUnrestrictedDacl, ACL_REVISION, GENERIC_READ | GENERIC_EXECUTE, SeRestrictedCodeSid); return TRUE; }
NTSTATUS PhSvcApiPortInitialization( _In_ PUNICODE_STRING PortName ) { static SID_IDENTIFIER_AUTHORITY ntAuthority = SECURITY_NT_AUTHORITY; NTSTATUS status; OBJECT_ATTRIBUTES objectAttributes; PSECURITY_DESCRIPTOR securityDescriptor; ULONG sdAllocationLength; UCHAR administratorsSidBuffer[FIELD_OFFSET(SID, SubAuthority) + sizeof(ULONG) * 2]; PSID administratorsSid; PACL dacl; ULONG i; // Create the API port. administratorsSid = (PSID)administratorsSidBuffer; RtlInitializeSid(administratorsSid, &ntAuthority, 2); *RtlSubAuthoritySid(administratorsSid, 0) = SECURITY_BUILTIN_DOMAIN_RID; *RtlSubAuthoritySid(administratorsSid, 1) = DOMAIN_ALIAS_RID_ADMINS; sdAllocationLength = SECURITY_DESCRIPTOR_MIN_LENGTH + (ULONG)sizeof(ACL) + (ULONG)sizeof(ACCESS_ALLOWED_ACE) + RtlLengthSid(administratorsSid) + (ULONG)sizeof(ACCESS_ALLOWED_ACE) + RtlLengthSid(&PhSeEveryoneSid); securityDescriptor = PhAllocate(sdAllocationLength); dacl = (PACL)PTR_ADD_OFFSET(securityDescriptor, SECURITY_DESCRIPTOR_MIN_LENGTH); RtlCreateSecurityDescriptor(securityDescriptor, SECURITY_DESCRIPTOR_REVISION); RtlCreateAcl(dacl, sdAllocationLength - SECURITY_DESCRIPTOR_MIN_LENGTH, ACL_REVISION); RtlAddAccessAllowedAce(dacl, ACL_REVISION, PORT_ALL_ACCESS, administratorsSid); RtlAddAccessAllowedAce(dacl, ACL_REVISION, PORT_CONNECT, &PhSeEveryoneSid); RtlSetDaclSecurityDescriptor(securityDescriptor, TRUE, dacl, FALSE); InitializeObjectAttributes( &objectAttributes, PortName, OBJ_CASE_INSENSITIVE, NULL, securityDescriptor ); status = NtCreatePort( &PhSvcApiPortHandle, &objectAttributes, sizeof(PHSVC_API_CONNECTINFO), PhIsExecutingInWow64() ? sizeof(PHSVC_API_MSG64) : sizeof(PHSVC_API_MSG), 0 ); PhFree(securityDescriptor); if (!NT_SUCCESS(status)) return status; // Start the API threads. PhSvcApiThreadContextTlsIndex = TlsAlloc(); for (i = 0; i < 2; i++) { PhCreateThread2(PhSvcApiRequestThreadStart, NULL); } return status; }
// Sets the access-control list for a handle to "Everyone:AccessMask" // The handle must be open for WRITE_DAC access static NTSTATUS NtSetObjectAccessForEveryone( IN HANDLE ObjectHandle, IN ACCESS_MASK AccessMask) { SID_IDENTIFIER_AUTHORITY SiaEveryone = SECURITY_WORLD_SID_AUTHORITY; SECURITY_DESCRIPTOR sd; NTSTATUS Status; ULONG cbAclLength = 0; PSID pSidEveryone = NULL; PACL pAcl = NULL; // Get the SID of Everyone Status = RtlAllocateAndInitializeSid(&SiaEveryone, 1, 0, 0, 0, 0, 0, 0, 0, 0, &pSidEveryone); // Allocate space for ACL if(NT_SUCCESS(Status)) { ULONG dwSidLength = RtlLengthSid(pSidEveryone); // Create ACL for full access to the file cbAclLength = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + dwSidLength - sizeof(DWORD); pAcl = (PACL)RtlAllocateHeap(RtlProcessHeap(), 0, cbAclLength); if(pAcl == NULL) Status = STATUS_INSUFFICIENT_RESOURCES; } // Create the Access control list with one ACE if(NT_SUCCESS(Status)) { Status = RtlCreateAcl(pAcl, cbAclLength, ACL_REVISION); } // Add the ACE to the ACL if(NT_SUCCESS(Status)) { Status = RtlAddAccessAllowedAce(pAcl, ACL_REVISION, AccessMask, pSidEveryone); } // Initialize the blank security descriptor if(NT_SUCCESS(Status)) { Status = RtlCreateSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION); } // Set the ACL to the security descriptor if(NT_SUCCESS(Status)) { Status = RtlSetDaclSecurityDescriptor(&sd, TRUE, pAcl, FALSE); } // Apply the security information to the handle if(NT_SUCCESS(Status)) { Status = NtSetSecurityObject(ObjectHandle, DACL_SECURITY_INFORMATION, &sd); } // Free buffers if(pAcl != NULL) RtlFreeHeap(RtlProcessHeap(), 0, pAcl); if(pSidEveryone != NULL) RtlFreeSid(pSidEveryone); return Status; }
static NTSTATUS RtlpSysVolCreateSecurityDescriptor(OUT PISECURITY_DESCRIPTOR *SecurityDescriptor, OUT PSID *SystemSid) { PSECURITY_DESCRIPTOR AbsSD = NULL; PSID LocalSystemSid = NULL; PACL Dacl = NULL; ULONG DaclSize; NTSTATUS Status; /* create the local SYSTEM SID */ Status = RtlAllocateAndInitializeSid(&LocalSystemAuthority, 1, SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0, &LocalSystemSid); if (!NT_SUCCESS(Status)) { return Status; } /* allocate and initialize the security descriptor */ AbsSD = RtlpAllocateMemory(sizeof(SECURITY_DESCRIPTOR), 'dSeS'); if (AbsSD == NULL) { Status = STATUS_NO_MEMORY; goto Cleanup; } Status = RtlCreateSecurityDescriptor(AbsSD, SECURITY_DESCRIPTOR_REVISION); if (!NT_SUCCESS(Status)) { goto Cleanup; } /* allocate and create the DACL */ DaclSize = sizeof(ACL) + sizeof(ACE) + RtlLengthSid(LocalSystemSid); Dacl = RtlpAllocateMemory(DaclSize, 'cAeS'); if (Dacl == NULL) { Status = STATUS_NO_MEMORY; goto Cleanup; } Status = RtlCreateAcl(Dacl, DaclSize, ACL_REVISION); if (!NT_SUCCESS(Status)) { goto Cleanup; } Status = RtlAddAccessAllowedAceEx(Dacl, ACL_REVISION, OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE, STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL, LocalSystemSid); if (!NT_SUCCESS(Status)) { goto Cleanup; } /* set the DACL in the security descriptor */ Status = RtlSetDaclSecurityDescriptor(AbsSD, TRUE, Dacl, FALSE); /* all done */ if (NT_SUCCESS(Status)) { *SecurityDescriptor = AbsSD; *SystemSid = LocalSystemSid; } else { Cleanup: if (LocalSystemSid != NULL) { RtlFreeSid(LocalSystemSid); } if (Dacl != NULL) { RtlpFreeMemory(Dacl, 'cAeS'); } if (AbsSD != NULL) { RtlpFreeMemory(AbsSD, 'dSeS'); } } return Status; }
/*++ * @name CsrSetProcessSecurity * * The CsrSetProcessSecurity routine protects access to the CSRSS process * from unauthorized tampering. * * @param None. * * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise. * * @remarks None. * *--*/ NTSTATUS NTAPI CsrSetProcessSecurity(VOID) { NTSTATUS Status; HANDLE hToken, hProcess = NtCurrentProcess(); ULONG Length; PTOKEN_USER TokenInfo = NULL; PSECURITY_DESCRIPTOR ProcSd = NULL; PACL Dacl; PSID UserSid; /* Open our token */ Status = NtOpenProcessToken(hProcess, TOKEN_QUERY, &hToken); if (!NT_SUCCESS(Status)) goto Quickie; /* Get the Token User Length */ NtQueryInformationToken(hToken, TokenUser, NULL, 0, &Length); /* Allocate space for it */ TokenInfo = RtlAllocateHeap(CsrHeap, HEAP_ZERO_MEMORY, Length); if (!TokenInfo) { Status = STATUS_NO_MEMORY; goto Quickie; } /* Now query the data */ Status = NtQueryInformationToken(hToken, TokenUser, TokenInfo, Length, &Length); NtClose(hToken); if (!NT_SUCCESS(Status)) goto Quickie; /* Now check the SID Length */ UserSid = TokenInfo->User.Sid; Length = RtlLengthSid(UserSid) + sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE); /* Allocate a buffer for the Security Descriptor, with SID and DACL */ ProcSd = RtlAllocateHeap(CsrHeap, HEAP_ZERO_MEMORY, SECURITY_DESCRIPTOR_MIN_LENGTH + Length); if (!ProcSd) { Status = STATUS_NO_MEMORY; goto Quickie; } /* Set the pointer to the DACL */ Dacl = (PACL)((ULONG_PTR)ProcSd + SECURITY_DESCRIPTOR_MIN_LENGTH); /* Now create the SD itself */ Status = RtlCreateSecurityDescriptor(ProcSd, SECURITY_DESCRIPTOR_REVISION); if (!NT_SUCCESS(Status)) { DPRINT1("CSRSS: SD creation failed - status = %lx\n", Status); goto Quickie; } /* Create the DACL for it*/ Status = RtlCreateAcl(Dacl, Length, ACL_REVISION2); if (!NT_SUCCESS(Status)) { DPRINT1("CSRSS: DACL creation failed - status = %lx\n", Status); goto Quickie; } /* Create the ACE */ Status = RtlAddAccessAllowedAce(Dacl, ACL_REVISION, PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION | PROCESS_DUP_HANDLE | PROCESS_TERMINATE | PROCESS_SUSPEND_RESUME | PROCESS_QUERY_INFORMATION | READ_CONTROL, UserSid); if (!NT_SUCCESS(Status)) { DPRINT1("CSRSS: ACE creation failed - status = %lx\n", Status); goto Quickie; } /* Clear the DACL in the SD */ Status = RtlSetDaclSecurityDescriptor(ProcSd, TRUE, Dacl, FALSE); if (!NT_SUCCESS(Status)) { DPRINT1("CSRSS: set DACL failed - status = %lx\n", Status); goto Quickie; } /* Write the SD into the Process */ Status = NtSetSecurityObject(hProcess, DACL_SECURITY_INFORMATION, ProcSd); if (!NT_SUCCESS(Status)) { DPRINT1("CSRSS: set process DACL failed - status = %lx\n", Status); goto Quickie; } /* Free the memory and return */ Quickie: if (ProcSd) RtlFreeHeap(CsrHeap, 0, ProcSd); RtlFreeHeap(CsrHeap, 0, TokenInfo); return Status; }
/*++ * @name GetDosDevicesProtection * * The GetDosDevicesProtection creates a security descriptor for the DOS Devices * Object Directory. * * @param DosDevicesSd * Pointer to the Security Descriptor to return. * * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise. * * @remarks Depending on the DOS Devices Protection Mode (set in the registry), * regular users may or may not have full access to the directory. * *--*/ NTSTATUS NTAPI GetDosDevicesProtection(OUT PSECURITY_DESCRIPTOR DosDevicesSd) { SID_IDENTIFIER_AUTHORITY WorldAuthority = {SECURITY_WORLD_SID_AUTHORITY}; SID_IDENTIFIER_AUTHORITY CreatorAuthority = {SECURITY_CREATOR_SID_AUTHORITY}; SID_IDENTIFIER_AUTHORITY NtSidAuthority = {SECURITY_NT_AUTHORITY}; PSID WorldSid, CreatorSid, AdminSid, SystemSid; UCHAR KeyValueBuffer[0x40]; PKEY_VALUE_PARTIAL_INFORMATION KeyValuePartialInfo; UNICODE_STRING KeyName; ULONG ProtectionMode = 0; OBJECT_ATTRIBUTES ObjectAttributes; PACL Dacl; PACCESS_ALLOWED_ACE Ace; HANDLE hKey; NTSTATUS Status; ULONG ResultLength, SidLength, AclLength; /* Create the SD */ Status = RtlCreateSecurityDescriptor(DosDevicesSd, SECURITY_DESCRIPTOR_REVISION); ASSERT(NT_SUCCESS(Status)); /* Initialize the System SID */ Status = RtlAllocateAndInitializeSid(&NtSidAuthority, 1, SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0, &SystemSid); ASSERT(NT_SUCCESS(Status)); /* Initialize the World SID */ Status = RtlAllocateAndInitializeSid(&WorldAuthority, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &WorldSid); ASSERT(NT_SUCCESS(Status)); /* Initialize the Admin SID */ Status = RtlAllocateAndInitializeSid(&NtSidAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &AdminSid); ASSERT(NT_SUCCESS(Status)); /* Initialize the Creator SID */ Status = RtlAllocateAndInitializeSid(&CreatorAuthority, 1, SECURITY_CREATOR_OWNER_RID, 0, 0, 0, 0, 0, 0, 0, &CreatorSid); ASSERT(NT_SUCCESS(Status)); /* Open the Session Manager Key */ RtlInitUnicodeString(&KeyName, SM_REG_KEY); InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE, NULL, NULL); Status = NtOpenKey(&hKey, KEY_READ, &ObjectAttributes); if (NT_SUCCESS(Status)) { /* Read the key value */ RtlInitUnicodeString(&KeyName, L"ProtectionMode"); Status = NtQueryValueKey(hKey, &KeyName, KeyValuePartialInformation, KeyValueBuffer, sizeof(KeyValueBuffer), &ResultLength); /* Make sure it's what we expect it to be */ KeyValuePartialInfo = (PKEY_VALUE_PARTIAL_INFORMATION)KeyValueBuffer; if ((NT_SUCCESS(Status)) && (KeyValuePartialInfo->Type == REG_DWORD) && (*(PULONG)KeyValuePartialInfo->Data)) { /* Save the Protection Mode */ ProtectionMode = *(PULONG)KeyValuePartialInfo->Data; } /* Close the handle */ NtClose(hKey); } /* Check the Protection Mode */ if (ProtectionMode & 3) { /* Calculate SID Lengths */ SidLength = RtlLengthSid(CreatorSid) + RtlLengthSid(SystemSid) + RtlLengthSid(AdminSid); AclLength = sizeof(ACL) + 3 * sizeof(ACCESS_ALLOWED_ACE) + SidLength; /* Allocate memory for the DACL */ Dacl = RtlAllocateHeap(CsrHeap, HEAP_ZERO_MEMORY, AclLength); ASSERT(Dacl != NULL); /* Build the ACL and add 3 ACEs */ Status = RtlCreateAcl(Dacl, AclLength, ACL_REVISION2); ASSERT(NT_SUCCESS(Status)); Status = RtlAddAccessAllowedAce(Dacl, ACL_REVISION, GENERIC_ALL, SystemSid); ASSERT(NT_SUCCESS(Status)); Status = RtlAddAccessAllowedAce(Dacl, ACL_REVISION, GENERIC_ALL, AdminSid); ASSERT(NT_SUCCESS(Status)); Status = RtlAddAccessAllowedAce(Dacl, ACL_REVISION, GENERIC_ALL, CreatorSid); ASSERT(NT_SUCCESS(Status)); /* Edit the ACEs to make them inheritable */ Status = RtlGetAce(Dacl, 0, (PVOID*)&Ace); ASSERT(NT_SUCCESS(Status)); Ace->Header.AceFlags |= OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE; Status = RtlGetAce(Dacl, 1, (PVOID*)&Ace); ASSERT(NT_SUCCESS(Status)); Ace->Header.AceFlags |= OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE; Status = RtlGetAce(Dacl, 2, (PVOID*)&Ace); ASSERT(NT_SUCCESS(Status)); Ace->Header.AceFlags |= OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE; /* Set this DACL with the SD */ Status = RtlSetDaclSecurityDescriptor(DosDevicesSd, TRUE, Dacl, FALSE); ASSERT(NT_SUCCESS(Status)); goto Quickie; } else { /* Calculate SID Lengths */ SidLength = RtlLengthSid(WorldSid) + RtlLengthSid(SystemSid); AclLength = sizeof(ACL) + 3 * sizeof(ACCESS_ALLOWED_ACE) + SidLength; /* Allocate memory for the DACL */ Dacl = RtlAllocateHeap(CsrHeap, HEAP_ZERO_MEMORY, AclLength); ASSERT(Dacl != NULL); /* Build the ACL and add 3 ACEs */ Status = RtlCreateAcl(Dacl, AclLength, ACL_REVISION2); ASSERT(NT_SUCCESS(Status)); Status = RtlAddAccessAllowedAce(Dacl, ACL_REVISION, GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE, WorldSid); ASSERT(NT_SUCCESS(Status)); Status = RtlAddAccessAllowedAce(Dacl, ACL_REVISION, GENERIC_ALL, SystemSid); ASSERT(NT_SUCCESS(Status)); Status = RtlAddAccessAllowedAce(Dacl, ACL_REVISION, GENERIC_ALL, WorldSid); ASSERT(NT_SUCCESS(Status)); /* Edit the last ACE to make it inheritable */ Status = RtlGetAce(Dacl, 2, (PVOID*)&Ace); ASSERT(NT_SUCCESS(Status)); Ace->Header.AceFlags |= OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE; /* Set this DACL with the SD */ Status = RtlSetDaclSecurityDescriptor(DosDevicesSd, TRUE, Dacl, FALSE); ASSERT(NT_SUCCESS(Status)); goto Quickie; } /* FIXME: failure cases! Fail: */ /* Free the memory */ RtlFreeHeap(CsrHeap, 0, Dacl); /* FIXME: semi-failure cases! Quickie: */ Quickie: /* Free the SIDs */ RtlFreeSid(CreatorSid); RtlFreeSid(AdminSid); RtlFreeSid(WorldSid); RtlFreeSid(SystemSid); /* Return */ return Status; }