Beispiel #1
0
/*
 * @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;
}
Beispiel #2
0
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;
}
Beispiel #3
0
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;
}
Beispiel #4
0
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;
}
Beispiel #5
0
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;
}
Beispiel #7
0
BOOLEAN
RtlEqualSid(
    IN PSID Sid1,
    IN PSID Sid2
    )
{
    return ((Sid1->SubAuthorityCount == Sid2->SubAuthorityCount) &&
            RtlEqualMemory(Sid1, Sid2, RtlLengthSid(Sid1)));
}
Beispiel #8
0
/*
 * @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;
}
Beispiel #9
0
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;
}
Beispiel #10
0
/*++
 * @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;
}
Beispiel #11
0
/**************************************************************************
 *                 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;
}
Beispiel #12
0
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 );
}
Beispiel #13
0
/******************************************************************************
 *  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;
}
Beispiel #14
0
/*
 * @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);
}
Beispiel #15
0
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;
}
Beispiel #16
0
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;
}
Beispiel #17
0
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;
}
Beispiel #18
0
/*
 * @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;
}
Beispiel #19
0
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;
}
Beispiel #20
0
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));
}
Beispiel #21
0
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;
}
Beispiel #22
0
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;
}
Beispiel #23
0
/******************************************************************************
 *  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;
}
Beispiel #24
0
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;
}
Beispiel #25
0
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;
}
Beispiel #26
0
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;
}
Beispiel #28
0
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;
}
Beispiel #29
0
/*++
 * @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;
}
Beispiel #30
0
/*++
 * @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;
}