示例#1
0
static
DWORD
MapBuiltinSidToName(
    PWSTR *ppwszName,
    PSID pSid
    )
{
    DWORD dwError = 0;
    union
    {
        SID sid;
        BYTE buffer[SID_MAX_SIZE];
    } Sid;
    ULONG SidSize = sizeof(Sid.buffer);
    PWSTR pwszEveryone = NULL;

    dwError = LwNtStatusToWin32Error(
        RtlCreateWellKnownSid(
            WinWorldSid,
            NULL,
            &Sid.sid,
            &SidSize));
    BAIL_ON_LTNET_ERROR(dwError);

    if (RtlEqualSid(&Sid.sid, pSid))
    {
        dwError = LwNtStatusToWin32Error(
            RtlWC16StringAllocateFromCString(
                &pwszEveryone,
                "Everyone"));
        BAIL_ON_LTNET_ERROR(dwError);

    }

    *ppwszName = pwszEveryone;

cleanup:

    return dwError;

error:
    LwNetWC16StringFree(pwszEveryone);

    goto cleanup;
}
示例#2
0
static
DWORD
MapBuiltinNameToSid(
    PSID *ppSid,
    PCWSTR pwszName
    )
{
    DWORD dwError = 0;
    union
    {
        SID sid;
        BYTE buffer[SID_MAX_SIZE];
    } Sid;
    ULONG SidSize = sizeof(Sid.buffer);
    PWSTR pwszEveryone = NULL;

    dwError = LwNtStatusToWin32Error(
                  RtlWC16StringAllocateFromCString(
                      &pwszEveryone,
                      "Everyone"));
    BAIL_ON_SRVSVC_ERROR(dwError);


    if (LwRtlWC16StringIsEqual(pwszName, pwszEveryone, FALSE))
    {
        dwError = LwNtStatusToWin32Error(
                      RtlCreateWellKnownSid(
                          WinWorldSid,
                          NULL,
                          &Sid.sid,
                          &SidSize));
    }
    BAIL_ON_SRVSVC_ERROR(dwError);

    dwError = LwNtStatusToWin32Error(
                  RtlDuplicateSid(ppSid, &Sid.sid));

cleanup:
    LW_RTL_FREE(&pwszEveryone);

    return dwError;

error:
    goto cleanup;
}
示例#3
0
NTSTATUS
SrvShareSetDefaultSecurity(
    PSRV_SHARE_INFO pShareInfo
    )
{
    NTSTATUS ntStatus = STATUS_SUCCESS;
    PSECURITY_DESCRIPTOR_RELATIVE pRelSecDesc = NULL;
    ULONG ulRelSecDescLen = 0;
    PSECURITY_DESCRIPTOR_ABSOLUTE pAbsSecDesc = NULL;
    DWORD dwAceCount = 0;
    PSID pOwnerSid = NULL;
    PSID pGroupSid = NULL;
    PACL pDacl = NULL;
    DWORD dwSizeDacl = 0;
    union
    {
        SID sid;
        BYTE buffer[SID_MAX_SIZE];
    } administratorsSid;
    union
    {
        SID sid;
        BYTE buffer[SID_MAX_SIZE];
    } powerUsersSid;
    union
    {
        SID sid;
        BYTE buffer[SID_MAX_SIZE];
    } everyoneSid;
    ULONG ulAdministratorsSidSize = sizeof(administratorsSid.buffer);
    ULONG ulPowerUsersSidSize = sizeof(powerUsersSid.buffer);
    ULONG ulEveryoneSidSize = sizeof(everyoneSid.buffer);
    ACCESS_MASK worldAccessMask = 0;

    /* Clear out any existing SecDesc's.  This is not a normal
       use case, but be paranoid */

    if (pShareInfo->ulSecDescLen)
    {
        SrvShareFreeSecurity(pShareInfo);
    }

    /* Build the new Absolute Security Descriptor */

    ntStatus = RTL_ALLOCATE(
                   &pAbsSecDesc,
                   VOID,
                   SECURITY_DESCRIPTOR_ABSOLUTE_MIN_SIZE);
    BAIL_ON_NT_STATUS(ntStatus);

    ntStatus = RtlCreateSecurityDescriptorAbsolute(
                  pAbsSecDesc,
                  SECURITY_DESCRIPTOR_REVISION);
    BAIL_ON_NT_STATUS(ntStatus);

    /* Create some SIDs */

    ntStatus = RtlCreateWellKnownSid(
                   WinBuiltinAdministratorsSid,
                   NULL,
                   (PSID)administratorsSid.buffer,
                   &ulAdministratorsSidSize);
    BAIL_ON_NT_STATUS(ntStatus);

    ntStatus = RtlCreateWellKnownSid(
                   WinBuiltinPowerUsersSid,
                   NULL,
                   (PSID)powerUsersSid.buffer,
                   &ulPowerUsersSidSize);
    BAIL_ON_NT_STATUS(ntStatus);

    ntStatus = RtlCreateWellKnownSid(
                   WinWorldSid,
                   NULL,
                   (PSID)everyoneSid.buffer,
                   &ulEveryoneSidSize);
    BAIL_ON_NT_STATUS(ntStatus);

    /* Owner: Administrators */

    ntStatus = RtlDuplicateSid(&pOwnerSid, &administratorsSid.sid);
    BAIL_ON_NT_STATUS(ntStatus);

    ntStatus = RtlSetOwnerSecurityDescriptor(
                   pAbsSecDesc,
                   pOwnerSid,
                   FALSE);
    BAIL_ON_NT_STATUS(ntStatus);

    /* Group: Power Users */

    ntStatus = RtlDuplicateSid(&pGroupSid, &powerUsersSid.sid);
    BAIL_ON_NT_STATUS(ntStatus);

    ntStatus = RtlSetGroupSecurityDescriptor(
                   pAbsSecDesc,
                   pGroupSid,
                   FALSE);
    BAIL_ON_NT_STATUS(ntStatus);

    /* DACL:
       Administrators - (Full Control)
       Everyone - (Read) for disk shares, (Read/Write) to IPC shares */

    dwAceCount = 2;

    dwSizeDacl = ACL_HEADER_SIZE +
        dwAceCount * sizeof(ACCESS_ALLOWED_ACE) +
        RtlLengthSid(&administratorsSid.sid) +
        RtlLengthSid(&everyoneSid.sid) -
        dwAceCount * sizeof(ULONG);

    ntStatus= RTL_ALLOCATE(&pDacl, VOID, dwSizeDacl);
    BAIL_ON_NT_STATUS(ntStatus);

    ntStatus = RtlCreateAcl(pDacl, dwSizeDacl, ACL_REVISION);
    BAIL_ON_NT_STATUS(ntStatus);

    ntStatus = RtlAddAccessAllowedAceEx(
                  pDacl,
                  ACL_REVISION,
                  0,
                  FILE_ALL_ACCESS,
                  &administratorsSid.sid);
    BAIL_ON_NT_STATUS(ntStatus);

    worldAccessMask = FILE_GENERIC_READ | FILE_GENERIC_EXECUTE;
    if (pShareInfo->service == SHARE_SERVICE_NAMED_PIPE)
    {
        worldAccessMask |= FILE_GENERIC_WRITE;
    }

    ntStatus = RtlAddAccessAllowedAceEx(
                  pDacl,
                  ACL_REVISION,
                  0,
                  worldAccessMask,
                  &everyoneSid.sid);
    BAIL_ON_NT_STATUS(ntStatus);

    ntStatus = RtlSetDaclSecurityDescriptor(
                  pAbsSecDesc,
                  TRUE,
                  pDacl,
                  FALSE);
    BAIL_ON_NT_STATUS(ntStatus);

    /* Create the SelfRelative SD and assign them to the Share */

    ntStatus = RtlAbsoluteToSelfRelativeSD(
                   pAbsSecDesc,
                   NULL,
                   &ulRelSecDescLen);
    if (ntStatus == STATUS_BUFFER_TOO_SMALL)
    {
        ntStatus = SrvAllocateMemory(ulRelSecDescLen, (PVOID*)&pRelSecDesc);
        BAIL_ON_NT_STATUS(ntStatus);

        ntStatus = RtlAbsoluteToSelfRelativeSD(
                       pAbsSecDesc,
                       pRelSecDesc,
                       &ulRelSecDescLen);
    }
    BAIL_ON_NT_STATUS(ntStatus);

    pShareInfo->pSecDesc = pRelSecDesc;
    pShareInfo->ulSecDescLen = ulRelSecDescLen;
    pShareInfo->pAbsSecDesc = pAbsSecDesc;

    ntStatus = STATUS_SUCCESS;


cleanup:

    return ntStatus;

error:
    RTL_FREE(&pAbsSecDesc);
    RTL_FREE(&pOwnerSid);
    RTL_FREE(&pGroupSid);
    RTL_FREE(&pDacl);

    if (pRelSecDesc)
    {
        SrvFreeMemory(pRelSecDesc);
    }

    goto cleanup;
}
示例#4
0
static
DWORD
ConstructSecurityDescriptor(
    DWORD dwAllowUserCount,
    PWSTR* ppwszAllowUsers,
    DWORD dwDenyUserCount,
    PWSTR* ppwszDenyUsers,
    BOOLEAN bReadOnly,
    PSECURITY_DESCRIPTOR_RELATIVE* ppRelative,
    PDWORD pdwRelativeSize
    )
{
    DWORD dwError = 0;
    PSECURITY_DESCRIPTOR_ABSOLUTE pAbsolute = NULL;
    PSECURITY_DESCRIPTOR_RELATIVE pRelative = NULL;
    union
    {
        SID sid;
        BYTE buffer[SID_MAX_SIZE];
    } Owner;
    union
    {
        SID sid;
        BYTE buffer[SID_MAX_SIZE];
    } Group;
    ULONG OwnerSidSize = sizeof(Owner.buffer);
    ULONG GroupSidSize = sizeof(Group.buffer);
    DWORD dwDaclSize = 0;
    PACL pDacl = NULL;
    DWORD dwIndex = 0;
    PSID pSid = NULL;
    ULONG ulRelativeSize = 0;
    HANDLE hLsa = NULL;
    ACCESS_MASK mask = bReadOnly ?
        (FILE_GENERIC_READ|FILE_GENERIC_EXECUTE) :
        FILE_ALL_ACCESS;

    dwError = LsaOpenServer(&hLsa);
    BAIL_ON_LTNET_ERROR(dwError);

    dwError = LwNtStatusToWin32Error(
        RtlCreateWellKnownSid(
            WinBuiltinAdministratorsSid,
            NULL,
            &Owner.sid,
            &OwnerSidSize));
    BAIL_ON_LTNET_ERROR(dwError);

    dwError = LwNtStatusToWin32Error(
        RtlCreateWellKnownSid(
            WinBuiltinPowerUsersSid,
            NULL,
            &Group.sid,
            &GroupSidSize));
    BAIL_ON_LTNET_ERROR(dwError);

    dwDaclSize = ACL_HEADER_SIZE +
        dwAllowUserCount * (sizeof(ACCESS_ALLOWED_ACE) + SID_MAX_SIZE) +
        dwDenyUserCount * (sizeof(ACCESS_DENIED_ACE) + SID_MAX_SIZE) +
        RtlLengthSid(&Owner.sid) + RtlLengthSid(&Group.sid);

    dwError = LwNetAllocateMemory(
        dwDaclSize,
        OUT_PPVOID(&pDacl));
    BAIL_ON_LTNET_ERROR(dwError);

    dwError = LwNtStatusToWin32Error(
        RtlCreateAcl(pDacl, dwDaclSize, ACL_REVISION));
    BAIL_ON_LTNET_ERROR(dwError);

    for (dwIndex = 0; dwIndex < dwDenyUserCount; dwIndex++)
    {
        dwError = MapNameToSid(hLsa, ppwszDenyUsers[dwIndex], &pSid);
        if (dwError != LW_ERROR_SUCCESS)
        {
            dwError = MapBuiltinNameToSid(&pSid, ppwszDenyUsers[dwIndex]);
        }

        BAIL_ON_LTNET_ERROR(dwError);

        dwError = LwNtStatusToWin32Error(
            RtlAddAccessDeniedAceEx(
                pDacl,
                ACL_REVISION,
                0,
                FILE_ALL_ACCESS,
                pSid));
        BAIL_ON_LTNET_ERROR(dwError);

        RTL_FREE(&pSid);
    }

    for (dwIndex = 0; dwIndex < dwAllowUserCount; dwIndex++)
    {
        dwError = MapNameToSid(hLsa, ppwszAllowUsers[dwIndex], &pSid);
        if (dwError != LW_ERROR_SUCCESS)
        {
            dwError = MapBuiltinNameToSid(&pSid, ppwszAllowUsers[dwIndex]);
        }
        BAIL_ON_LTNET_ERROR(dwError);

        dwError = LwNtStatusToWin32Error(
            RtlAddAccessAllowedAceEx(
                pDacl,
                ACL_REVISION,
                0,
                mask,
                pSid));
        BAIL_ON_LTNET_ERROR(dwError);

        RTL_FREE(&pSid);
    }

    dwError = LwNetAllocateMemory(
        SECURITY_DESCRIPTOR_ABSOLUTE_MIN_SIZE,
        OUT_PPVOID(&pAbsolute));
    BAIL_ON_LTNET_ERROR(dwError);

    dwError = LwNtStatusToWin32Error(
        RtlCreateSecurityDescriptorAbsolute(
            pAbsolute,
            SECURITY_DESCRIPTOR_REVISION));
    BAIL_ON_LTNET_ERROR(dwError);

    dwError = LwNtStatusToWin32Error(
        RtlSetOwnerSecurityDescriptor(
            pAbsolute,
            &Owner.sid,
            FALSE));
    BAIL_ON_LTNET_ERROR(dwError);

    dwError = LwNtStatusToWin32Error(
        RtlSetGroupSecurityDescriptor(
            pAbsolute,
            &Group.sid,
            FALSE));
    BAIL_ON_LTNET_ERROR(dwError);

    dwError = LwNtStatusToWin32Error(
        RtlSetDaclSecurityDescriptor(
            pAbsolute,
            TRUE,
            pDacl,
            FALSE));
    BAIL_ON_LTNET_ERROR(dwError);

    RtlAbsoluteToSelfRelativeSD(
        pAbsolute,
        NULL,
        &ulRelativeSize);

    dwError = LwNetAllocateMemory(ulRelativeSize, OUT_PPVOID(&pRelative));
    BAIL_ON_LTNET_ERROR(dwError);

    dwError = LwNtStatusToWin32Error(
        RtlAbsoluteToSelfRelativeSD(
            pAbsolute,
            pRelative,
            &ulRelativeSize));
    BAIL_ON_LTNET_ERROR(dwError);

    *ppRelative = pRelative;
    *pdwRelativeSize = ulRelativeSize;

cleanup:

    if (hLsa)
    {
        LsaCloseServer(hLsa);
    }

    LTNET_SAFE_FREE_MEMORY(pSid);
    LTNET_SAFE_FREE_MEMORY(pDacl);
    LTNET_SAFE_FREE_MEMORY(pAbsolute);

    return dwError;

error:

    *ppRelative = NULL;
    *pdwRelativeSize = 0;

    LTNET_SAFE_FREE_MEMORY(pRelative);

    goto cleanup;
}
示例#5
0
static
NTSTATUS
SrvBuildDefaultShareSID(
    PSECURITY_DESCRIPTOR_RELATIVE* ppSecDesc
    )
{
    NTSTATUS ntStatus = STATUS_SUCCESS;
    PSECURITY_DESCRIPTOR_RELATIVE pRelSecDesc = NULL;
    ULONG ulRelSecDescLen = 0;
    PSECURITY_DESCRIPTOR_ABSOLUTE pAbsSecDesc = NULL;
    DWORD dwAceCount = 0;
    PSID pOwnerSid = NULL;
    PSID pGroupSid = NULL;
    PACL pDacl = NULL;
    DWORD dwSizeDacl = 0;
    union
    {
        SID sid;
        BYTE buffer[SID_MAX_SIZE];
    } localSystemSid;
    union
    {
        SID sid;
        BYTE buffer[SID_MAX_SIZE];
    } administratorsSid;
    union
    {
        SID sid;
        BYTE buffer[SID_MAX_SIZE];
    } builtinUsersSid;
    ULONG ulLocalSystemSidSize = sizeof(localSystemSid.buffer);
    ULONG ulAdministratorsSidSize = sizeof(administratorsSid.buffer);
    ULONG ulBuiltinUsersSidSize = sizeof(builtinUsersSid.buffer);
    ACCESS_MASK builtinUsersAccessMask = 0;
    ULONG ulAceFlags = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE;

    /* Build the new Absolute Security Descriptor */

    ntStatus = RTL_ALLOCATE(
                   &pAbsSecDesc,
                   VOID,
                   SECURITY_DESCRIPTOR_ABSOLUTE_MIN_SIZE);
    BAIL_ON_NT_STATUS(ntStatus);

    ntStatus = RtlCreateSecurityDescriptorAbsolute(
                  pAbsSecDesc,
                  SECURITY_DESCRIPTOR_REVISION);
    BAIL_ON_NT_STATUS(ntStatus);

    /* Create some SIDs */

    ntStatus = RtlCreateWellKnownSid(
                   WinLocalSystemSid,
                   NULL,
                   (PSID)localSystemSid.buffer,
                   &ulLocalSystemSidSize);
    BAIL_ON_NT_STATUS(ntStatus);

    ntStatus = RtlCreateWellKnownSid(
                   WinBuiltinAdministratorsSid,
                   NULL,
                   (PSID)administratorsSid.buffer,
                   &ulAdministratorsSidSize);
    BAIL_ON_NT_STATUS(ntStatus);

    ntStatus = RtlCreateWellKnownSid(
                    WinBuiltinUsersSid,
                    NULL,
                    (PSID)builtinUsersSid.buffer,
                    &ulBuiltinUsersSidSize);
    BAIL_ON_NT_STATUS(ntStatus);

    /* Owner: Local System */

    ntStatus = RtlDuplicateSid(&pOwnerSid, &localSystemSid.sid);
    BAIL_ON_NT_STATUS(ntStatus);

    ntStatus = RtlSetOwnerSecurityDescriptor(
                   pAbsSecDesc,
                   pOwnerSid,
                   FALSE);
    BAIL_ON_NT_STATUS(ntStatus);

    /* Group: Administrators */

    ntStatus = RtlDuplicateSid(&pGroupSid, &administratorsSid.sid);
    BAIL_ON_NT_STATUS(ntStatus);

    ntStatus = RtlSetGroupSecurityDescriptor(
                   pAbsSecDesc,
                   pGroupSid,
                   FALSE);
    BAIL_ON_NT_STATUS(ntStatus);

    /* DACL:
       Administrators - (Full Control)
       LocalSystem    - (Full Control)
       Builtin Users  - (Read && Execute && List Directory Contents)
     */

    dwAceCount = 3;

    dwSizeDacl = ACL_HEADER_SIZE +
        dwAceCount * sizeof(ACCESS_ALLOWED_ACE) +
        RtlLengthSid(&localSystemSid.sid) +
        RtlLengthSid(&administratorsSid.sid) +
        RtlLengthSid(&builtinUsersSid.sid) -
        dwAceCount * sizeof(ULONG);

    ntStatus= RTL_ALLOCATE(&pDacl, VOID, dwSizeDacl);
    BAIL_ON_NT_STATUS(ntStatus);

    ntStatus = RtlCreateAcl(pDacl, dwSizeDacl, ACL_REVISION);
    BAIL_ON_NT_STATUS(ntStatus);

    ntStatus = RtlAddAccessAllowedAceEx(
                  pDacl,
                  ACL_REVISION,
                  ulAceFlags,
                  FILE_ALL_ACCESS,
                  &localSystemSid.sid);
    BAIL_ON_NT_STATUS(ntStatus);

    ntStatus = RtlAddAccessAllowedAceEx(
                  pDacl,
                  ACL_REVISION,
                  ulAceFlags,
                  FILE_ALL_ACCESS,
                  &administratorsSid.sid);
    BAIL_ON_NT_STATUS(ntStatus);

    builtinUsersAccessMask = FILE_GENERIC_READ | FILE_GENERIC_EXECUTE;

    ntStatus = RtlAddAccessAllowedAceEx(
                  pDacl,
                  ACL_REVISION,
                  ulAceFlags,
                  builtinUsersAccessMask,
                  &builtinUsersSid.sid);
    BAIL_ON_NT_STATUS(ntStatus);

    ntStatus = RtlSetDaclSecurityDescriptor(
                  pAbsSecDesc,
                  TRUE,
                  pDacl,
                  FALSE);
    BAIL_ON_NT_STATUS(ntStatus);

    /* Create the SelfRelative SD */

    ntStatus = RtlAbsoluteToSelfRelativeSD(
                   pAbsSecDesc,
                   NULL,
                   &ulRelSecDescLen);
    if (ntStatus == STATUS_BUFFER_TOO_SMALL)
    {
        ntStatus = SrvAllocateMemory(ulRelSecDescLen, (PVOID*)&pRelSecDesc);
        BAIL_ON_NT_STATUS(ntStatus);

        ntStatus = RtlAbsoluteToSelfRelativeSD(
                       pAbsSecDesc,
                       pRelSecDesc,
                       &ulRelSecDescLen);
    }
    BAIL_ON_NT_STATUS(ntStatus);

    *ppSecDesc = pRelSecDesc;

cleanup:

    RTL_FREE(&pAbsSecDesc);
    RTL_FREE(&pOwnerSid);
    RTL_FREE(&pGroupSid);
    RTL_FREE(&pDacl);

    return ntStatus;

error:

    *ppSecDesc = NULL;

    if (pRelSecDesc)
    {
        SrvFreeMemory(pRelSecDesc);
    }

    goto cleanup;
}
示例#6
0
BOOLEAN
RtlAccessCheckEx(
    IN PSECURITY_DESCRIPTOR_ABSOLUTE SecurityDescriptor,
    IN PACCESS_TOKEN AccessToken,
    IN ACCESS_MASK DesiredAccess,
    IN ACCESS_MASK PreviouslyGrantedAccess,
    IN PGENERIC_MAPPING GenericMapping,
    OUT PACCESS_MASK RemainingDesiredAccess,
    OUT PACCESS_MASK GrantedAccess,
    OUT PNTSTATUS AccessStatus
    )
{
    NTSTATUS status = STATUS_ACCESS_DENIED;
    BOOLEAN isLocked = FALSE;
    ACCESS_MASK grantedAccess = PreviouslyGrantedAccess;
    ACCESS_MASK deniedAccess = 0;
    ACCESS_MASK desiredAccess = DesiredAccess;
    BOOLEAN wantMaxAllowed = FALSE;
    USHORT aclSizeUsed = 0;
    USHORT aceOffset = 0;
    PACE_HEADER aceHeader = NULL;
    union {
        SID Sid;
        BYTE Buffer[SID_MAX_SIZE];
    } sidBuffer;
    ULONG ulSidSize = sizeof(sidBuffer);

    if (!SecurityDescriptor || !AccessToken || !GenericMapping)
    {
        status = STATUS_INVALID_PARAMETER;
        GOTO_CLEANUP();
    }

    if (!LW_IS_VALID_FLAGS(DesiredAccess, VALID_DESIRED_ACCESS_MASK))
    {
        status = STATUS_INVALID_PARAMETER;
        GOTO_CLEANUP();
    }

    if (!LW_IS_VALID_FLAGS(PreviouslyGrantedAccess, VALID_GRANTED_ACCESS_MASK))
    {
        status = STATUS_INVALID_PARAMETER;
        GOTO_CLEANUP();
    }

    if ((SecurityDescriptor->Owner == NULL) || 
        (SecurityDescriptor->Group == NULL))
    {
        status = STATUS_INVALID_SECURITY_DESCR;
        GOTO_CLEANUP();
    }

    wantMaxAllowed = IsSetFlag(desiredAccess, MAXIMUM_ALLOWED);
    ClearFlag(desiredAccess, MAXIMUM_ALLOWED);

    RtlMapGenericMask(&desiredAccess, GenericMapping);

    //
    // NT AUTHORITY\SYSTEM is always allowed an access
    //
    status = RtlCreateWellKnownSid(WinLocalSystemSid,
                                   NULL,
                                   &sidBuffer.Sid,
                                   &ulSidSize);
    GOTO_CLEANUP_ON_STATUS(status);

    SHARED_LOCK_RWLOCK(&AccessToken->RwLock, isLocked);

    if (RtlIsSidMemberOfToken(AccessToken, &sidBuffer.Sid))
    {
        if (wantMaxAllowed)
        {
            SetFlag(desiredAccess, STANDARD_RIGHTS_ALL);
            SetFlag(desiredAccess, GENERIC_ALL);
            RtlMapGenericMask(&desiredAccess, GenericMapping);
        }
        SetFlag(grantedAccess, desiredAccess);
        desiredAccess = 0;

        status = STATUS_SUCCESS;
        GOTO_CLEANUP();
    }

    if (wantMaxAllowed || IsSetFlag(desiredAccess, ACCESS_SYSTEM_SECURITY))
    {
        // TODO-Handle ACCESS_SYSTEM_SECURITY by checking SE_SECURITY_NAME
        // privilege.  For now, requesting ACCESS_SYSTEM_SECURITY is not
        // allowed.

        ulSidSize = sizeof(sidBuffer);
        status = RtlCreateWellKnownSid(
                     WinBuiltinAdministratorsSid,
                     NULL,
                     &sidBuffer.Sid,
                     &ulSidSize);
        GOTO_CLEANUP_ON_STATUS(status);

        if (RtlIsSidMemberOfToken(AccessToken, &sidBuffer.Sid))
        {
            SetFlag(grantedAccess, ACCESS_SYSTEM_SECURITY);
            ClearFlag(desiredAccess, ACCESS_SYSTEM_SECURITY);
        }
        else if (IsSetFlag(desiredAccess, ACCESS_SYSTEM_SECURITY))
        {
            status = STATUS_PRIVILEGE_NOT_HELD;
            GOTO_CLEANUP();
        }
    }

    if (wantMaxAllowed || IsSetFlag(desiredAccess, WRITE_OWNER))
    {
        // TODO-Allow WRITE_OWNER if have SE_TAKE_OWNERSHIP_NAME regardless
        // of DACL.

        //
        // BUILTIN\Administrators are always allowed WRITE_OWNER
        //

        ulSidSize = sizeof(sidBuffer);
        status = RtlCreateWellKnownSid(
                     WinBuiltinAdministratorsSid,
                     NULL,
                     &sidBuffer.Sid,
                     &ulSidSize);
        GOTO_CLEANUP_ON_STATUS(status);

        if (RtlIsSidMemberOfToken(AccessToken, &sidBuffer.Sid))
        {
            SetFlag(grantedAccess, WRITE_OWNER);
            ClearFlag(desiredAccess, WRITE_OWNER);
        }
    }

    //
    // Owner can always read the SD and write the DACL.
    //

    if (wantMaxAllowed || IsSetFlag(desiredAccess, READ_CONTROL | WRITE_DAC))
    {
        if (RtlIsSidMemberOfToken(AccessToken, SecurityDescriptor->Owner))
        {
            if (wantMaxAllowed)
            {
                desiredAccess |= (READ_CONTROL | WRITE_DAC);
            }
                
            SetFlag(grantedAccess, (READ_CONTROL | WRITE_DAC) & desiredAccess);
            ClearFlag(desiredAccess, grantedAccess);
        }
    }

    // TODO-MAXIMUM_ALLOWED wrt privileges and WRITE_OWNER and
    // ACCESS_SYSTEM_SECURITY above.

    if (!SecurityDescriptor->Dacl)
    {
        // TODO-Interplay with special bits above?
        if (wantMaxAllowed)
        {
            SetFlag(desiredAccess, STANDARD_RIGHTS_ALL);
            SetFlag(desiredAccess, GENERIC_ALL);
            RtlMapGenericMask(&desiredAccess, GenericMapping);
        }
        SetFlag(grantedAccess, desiredAccess);
        desiredAccess = 0;

        status = STATUS_SUCCESS;
        GOTO_CLEANUP();
    }

    if (!RtlValidAcl(SecurityDescriptor->Dacl, &aclSizeUsed))
    {
        status = STATUS_INVALID_ACL;
        GOTO_CLEANUP();
    }

    while (wantMaxAllowed || desiredAccess)
    {
        status = RtlIterateAce(SecurityDescriptor->Dacl,
                               aclSizeUsed,
                               &aceOffset,
                               &aceHeader);
        if (STATUS_NO_MORE_ENTRIES == status)
        {
            break;
        }
        GOTO_CLEANUP_ON_STATUS(status);

        // Check ACE
        switch (aceHeader->AceType)
        {
            case ACCESS_ALLOWED_ACE_TYPE:
            {
                PACCESS_ALLOWED_ACE ace = (PACCESS_ALLOWED_ACE) aceHeader;
                ACCESS_MASK mask = ace->Mask;

                RtlMapGenericMask(&mask, GenericMapping);

                if (wantMaxAllowed || IsSetFlag(desiredAccess, mask))
                {
                    // SID in token => add bits to granted bits
                    PSID sid = RtlpGetSidAccessAllowedAce(ace);

                    if (RtlIsSidMemberOfToken(AccessToken, sid))
                    {
                        if (wantMaxAllowed)
                        {
                            SetFlag(grantedAccess, mask & ~deniedAccess);
                        }
                        else
                        {
                            SetFlag(grantedAccess, mask & desiredAccess);
                        }

                        ClearFlag(desiredAccess, grantedAccess);
                    }
                }
                break;
            }
            case ACCESS_DENIED_ACE_TYPE:
            {
                // Allowed and deny ACEs are isomorphic.
                PACCESS_ALLOWED_ACE ace = (PACCESS_ALLOWED_ACE) aceHeader;
                ACCESS_MASK mask = ace->Mask;

                RtlMapGenericMask(&mask, GenericMapping);

                if (wantMaxAllowed || IsSetFlag(desiredAccess, mask))
                {
                    // SID in token => exit with STATUS_ACCESS_DENIED
                    PSID sid = RtlpGetSidAccessAllowedAce(ace);

                    if (RtlIsSidMemberOfToken(AccessToken, sid))
                    {
                        if (wantMaxAllowed)
                        {
                            SetFlag(deniedAccess, mask);
                        }
                        else
                        {
                            status = STATUS_ACCESS_DENIED;
                            GOTO_CLEANUP();
                        }

                        ClearFlag(desiredAccess, deniedAccess);
                    }
                }
                break;
            }
            default:
                // ignore
                break;
        }
    }

    status = desiredAccess ? STATUS_ACCESS_DENIED : STATUS_SUCCESS;

cleanup:
    UNLOCK_RWLOCK(&AccessToken->RwLock, isLocked);

    if (NT_SUCCESS(status) &&
        !LW_IS_VALID_FLAGS(grantedAccess, VALID_GRANTED_ACCESS_MASK))
    {
        status = STATUS_ASSERTION_FAILURE;
    }
    if (!NT_SUCCESS(status))
    {
        grantedAccess = PreviouslyGrantedAccess;
    }

    if (RemainingDesiredAccess)
    {
        *RemainingDesiredAccess = desiredAccess;
    }

    *GrantedAccess = grantedAccess;
    *AccessStatus = status;

    return NT_SUCCESS(status) ? TRUE : FALSE;
}
示例#7
0
NTSTATUS
PvfsSetSecurityDescriptorFile(
    IN PPVFS_CCB pCcb,
    IN SECURITY_INFORMATION SecInfo,
    IN PSECURITY_DESCRIPTOR_RELATIVE pSecDesc,
    IN ULONG SecDescLength
    )
{
    NTSTATUS ntError = STATUS_ACCESS_DENIED;
    PSECURITY_DESCRIPTOR_RELATIVE pFinalSecDesc = NULL;
    ULONG ulFinalSecDescLength = 0;
    SECURITY_INFORMATION SecInfoAll = (OWNER_SECURITY_INFORMATION |
                                       GROUP_SECURITY_INFORMATION |
                                       DACL_SECURITY_INFORMATION |
                                       SACL_SECURITY_INFORMATION);
    BYTE pCurrentSecDescBuffer[SECURITY_DESCRIPTOR_RELATIVE_MAX_SIZE];
    ULONG ulCurrentSecDescLength = SECURITY_DESCRIPTOR_RELATIVE_MAX_SIZE;
    BYTE pNewSecDescBuffer[SECURITY_DESCRIPTOR_RELATIVE_MAX_SIZE];
    ULONG ulNewSecDescLength = SECURITY_DESCRIPTOR_RELATIVE_MAX_SIZE;
    PSECURITY_DESCRIPTOR_ABSOLUTE pIncAbsSecDesc = NULL;
    union {
        TOKEN_OWNER TokenOwnerInfo;
        BYTE Buffer[SID_MAX_SIZE];
    } TokenOwnerBuffer;
    PTOKEN_OWNER pTokenOwnerInformation = (PTOKEN_OWNER)&TokenOwnerBuffer;
    ULONG ulTokenOwnerLength = 0;
    union {
        SID Sid;
        BYTE Buffer[SID_MAX_SIZE];
    } LocalSystemSidBuffer;
    PSID pLocalSystemSid = (PSID)&LocalSystemSidBuffer;
    ULONG ulLocalSystemSidLength = sizeof(LocalSystemSidBuffer);

    memset(pCurrentSecDescBuffer, 0, SECURITY_DESCRIPTOR_RELATIVE_MAX_SIZE);
    memset(pNewSecDescBuffer, 0, SECURITY_DESCRIPTOR_RELATIVE_MAX_SIZE);
    memset(TokenOwnerBuffer.Buffer, 0, SID_MAX_SIZE);

    /* Sanity checks */

    if (SecInfo == 0)
    {
        ntError = STATUS_INVALID_PARAMETER;
        BAIL_ON_NT_STATUS(ntError);
    }

    /* If the new Security Descriptor contains owner or group SID
       information, berify that the user's ACCESS_TOKEN contains the
       SID as a member */

    if (SecInfo & (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION))
    {
        PSID pOwner = NULL;
        PSID pGroup = NULL;
        BOOLEAN bDefaulted = FALSE;

        ntError = PvfsSecurityAclSelfRelativeToAbsoluteSD(
                      &pIncAbsSecDesc,
                      pSecDesc);
        BAIL_ON_NT_STATUS(ntError);

        ntError = RtlQueryAccessTokenInformation(
                      pCcb->pUserToken,
                      TokenOwner,
                      (PVOID)pTokenOwnerInformation,
                      sizeof(TokenOwnerBuffer),
                      &ulTokenOwnerLength);
        BAIL_ON_NT_STATUS(ntError);

        ntError = RtlCreateWellKnownSid(
                      WinLocalSystemSid,
                      NULL,
                      pLocalSystemSid,
                      &ulLocalSystemSidLength);
        BAIL_ON_NT_STATUS(ntError);

        if (SecInfo & OWNER_SECURITY_INFORMATION)
        {
            ntError = RtlGetOwnerSecurityDescriptor(
                          pIncAbsSecDesc,
                          &pOwner,
                          &bDefaulted);
            BAIL_ON_NT_STATUS(ntError);

            if (!RtlIsSidMemberOfToken(pCcb->pUserToken, pOwner) &&
                !RtlEqualSid(pLocalSystemSid, pTokenOwnerInformation->Owner))
            {
                ntError = STATUS_ACCESS_DENIED;
                BAIL_ON_NT_STATUS(ntError);
            }
        }

        if (SecInfo & GROUP_SECURITY_INFORMATION)
        {
            ntError = RtlGetGroupSecurityDescriptor(
                          pIncAbsSecDesc,
                          &pGroup,
                          &bDefaulted);
            BAIL_ON_NT_STATUS(ntError);

            if (!RtlIsSidMemberOfToken(pCcb->pUserToken, pGroup) &&
                !RtlEqualSid(pLocalSystemSid, pTokenOwnerInformation->Owner))
            {
                ntError = STATUS_ACCESS_DENIED;
                BAIL_ON_NT_STATUS(ntError);
            }
        }
    }


    if (SecInfo == SecInfoAll)
    {
        /* We already have a fully formed Security Descriptor */

        pFinalSecDesc = pSecDesc;
        ulFinalSecDescLength = SecDescLength;
    }
    else
    {
        /* Retrieve the existing SD and merge with the incoming one */

        ntError = PvfsGetSecurityDescriptorFile(
                      pCcb,
                      SecInfoAll,
                      (PSECURITY_DESCRIPTOR_RELATIVE)pCurrentSecDescBuffer,
                      &ulCurrentSecDescLength);
        BAIL_ON_NT_STATUS(ntError);

        /* Assume that the new SD is <= the combined size of the current
           SD and the incoming one */

        ntError = RtlSetSecurityDescriptorInfo(
                      SecInfo,
                      pSecDesc,
                      (PSECURITY_DESCRIPTOR_RELATIVE)pCurrentSecDescBuffer,
                      (PSECURITY_DESCRIPTOR_RELATIVE)pNewSecDescBuffer,
                      &ulNewSecDescLength,
                      &gPvfsFileGenericMapping);
        BAIL_ON_NT_STATUS(ntError);

        pFinalSecDesc = (PSECURITY_DESCRIPTOR_RELATIVE)pNewSecDescBuffer;
        ulFinalSecDescLength = ulNewSecDescLength;

    }


    /* Save the combined SD */

#ifdef HAVE_EA_SUPPORT
    ntError = PvfsSetSecurityDescriptorFileXattr(
                  pCcb,
                  pFinalSecDesc,
                  ulFinalSecDescLength);
#else
    ntError = PvfsSetSecurityDescriptorPosix(
                  pCcb,
                  pFinalSecDesc,
                  ulFinalSecDescLength);
#endif

    BAIL_ON_NT_STATUS(ntError);

    PvfsNotifyScheduleFullReport(
        pCcb->pFcb,
        FILE_NOTIFY_CHANGE_SECURITY,
        FILE_ACTION_MODIFIED,
        pCcb->pszFilename);


cleanup:
    if (pIncAbsSecDesc)
    {
        PvfsFreeAbsoluteSecurityDescriptor(&pIncAbsSecDesc);
    }

    return ntError;

error:
    goto cleanup;
}