Beispiel #1
0
NTSTATUS
PvfsQuerySecurityFile(
    PPVFS_IRP_CONTEXT pIrpContext
    )
{
    NTSTATUS ntError = STATUS_NOT_SUPPORTED;
    PIRP pIrp = pIrpContext->pIrp;
    PPVFS_CCB pCcb = NULL;
    PSECURITY_DESCRIPTOR_RELATIVE pReturnSecDesc = NULL;
    ULONG SecDescLength = 0;
    SECURITY_INFORMATION SecInfo = 0;
    IRP_ARGS_QUERY_SET_SECURITY Args = pIrpContext->pIrp->Args.QuerySetSecurity;

    /* Sanity checks */

    ntError =  PvfsAcquireCCB(pIrp->FileHandle, &pCcb);
    BAIL_ON_NT_STATUS(ntError);

    if (!IsSetFlag(pCcb->Flags, PVFS_CCB_FLAG_CREATE_COMPLETE))
    {
        ntError = STATUS_INVALID_PARAMETER;
        BAIL_ON_NT_STATUS(ntError);
    }

    BAIL_ON_INVALID_PTR(Args.SecurityDescriptor, ntError);

    ntError = PvfsAccessCheckFileHandle(pCcb, READ_CONTROL);
    BAIL_ON_NT_STATUS(ntError);

    pReturnSecDesc = Args.SecurityDescriptor;
    SecDescLength = Args.Length;
    SecInfo  = Args.SecurityInformation;

    /* Real work starts here */

    ntError = PvfsGetSecurityDescriptorFile(pCcb,
                                            SecInfo,
                                            pReturnSecDesc,
                                            &SecDescLength);
    BAIL_ON_NT_STATUS(ntError);

    pIrp->IoStatusBlock.BytesTransferred = SecDescLength;
    ntError = STATUS_SUCCESS;

cleanup:
    if (pCcb) {
        PvfsReleaseCCB(pCcb);
    }

    return ntError;

error:
    goto cleanup;
}
Beispiel #2
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;
}