smb2.acls.ownerrights failure

Shilpa K shilpa.krishnareddy at gmail.com
Fri Nov 18 12:51:58 UTC 2016


Hello,

We have a smbtorture test smb2.acls.onwerrights for testing for permissions
for owner SID. Test case is given below. In one scenario, owner is denied
WRITE_DAC and the administrator has full access. I am executing the test
using administrator credentials. In one instance, create request is sent
with access_mask SEC_RIGHTS_FILE_READ while the owner is denied WRITE_DAC.
In Samba 4.5, this test case fails. Upon some investigation, I found the
issue to be in:


/* The owner always gets owner rights as defined above. */
if (security_token_has_sid(token, sd->owner_sid)) {
if (owner_rights_default) {
/*
* Just remove them, no need to check if they are
* there.
*/
bits_remaining &= ~(SEC_STD_WRITE_DAC |
SEC_STD_READ_CONTROL);
} else {
bits_remaining &= ~owner_rights_allowed;
bits_remaining |= owner_rights_denied;      ---> issue here
}
}

Because I am executing the test administrator, bits_remaining becomes 0
until the above code path is reached. At the following line, bits_remaining
becomes 0x40000:

bits_remaining |= owner_rights_denied;

And following message is logged in the Samba log file:

[2016/11/18 03:22:44.464327, 10, pid=9742, effective(586678772, 586678784),
real(0, 0)] ../source3/smbd/open.c:168(smbd_check_access_rights)
  smbd_check_access_rights: file smb2-testsd/inheritance requesting 0x10000
returning 0x40000 (NT_STATUS_ACCESS_DENIED)

If I change the above code to below line, this issue is resolved:

bits_remaining |= (owner_rights_denied & access_desired);


Can you comment on the above fix?

Thanks,
Shilpa

-----------------------------------------------------------------------------------------------------------------------------------

/*
  test dynamic acl inheritance
  Note: This test was copied from raw/acls.c.
*/
static bool test_owner_rights(struct torture_context *tctx,
    struct smb2_tree *tree)
{
        NTSTATUS status;
        struct smb2_create io;
        const char *dname = BASEDIR "\\inheritance";
        const char *fname1 = BASEDIR "\\inheritance\\testfile";
        bool ret = true;
        struct smb2_handle handle, handle2;
        union smb_fileinfo q;
        union smb_setfileinfo set;
        struct security_descriptor *sd, *sd_orig=NULL;
        const char *owner_sid;
         const char *owner_rights_sid = "S-1-3-4";

        torture_comment(tctx, "TESTING DYNAMIC ACL INHERITANCE\n");

        if (!smb2_util_setup_dir(tctx, tree, BASEDIR))
                return false;

        ZERO_STRUCT(io);
        io.level = RAW_OPEN_SMB2;
        io.in.create_flags = 0;
        io.in.desired_access = SEC_RIGHTS_FILE_ALL;
        io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
        io.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
        io.in.share_access = 0;
        io.in.alloc_size = 0;
        io.in.create_disposition = NTCREATEX_DISP_CREATE;
        io.in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS;
        io.in.security_flags = 0;
        io.in.fname = dname;

        status = smb2_create(tree, tctx, &io);
        CHECK_STATUS(status, NT_STATUS_OK);
        handle = io.out.file.handle;

        torture_comment(tctx, "get the original sd\n");
        q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
        q.query_secdesc.in.file.handle = handle;
        q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
        status = smb2_getinfo_file(tree, tctx, &q);
        CHECK_STATUS(status, NT_STATUS_OK);
        sd_orig = q.query_secdesc.out.sd;

        owner_sid = dom_sid_string(tctx, sd_orig->owner_sid);

        torture_comment(tctx, "owner_sid is %s\n", owner_sid);
        int i = 0;
        const struct {
                uint32_t owner_flags;
                uint32_t owner_rights;
        } test_perm[] = {
                {
                        0,
                        0
                },
                {
                        SEC_ACE_TYPE_ACCESS_ALLOWED,
                        SEC_STD_WRITE_DAC | SEC_STD_READ_CONTROL,
                },
                {
                        SEC_ACE_TYPE_ACCESS_ALLOWED,
                        SEC_STD_WRITE_DAC,
                },
                {
                        SEC_ACE_TYPE_ACCESS_DENIED,
                        SEC_STD_WRITE_DAC,
                },
        };
        for (i=0;i<ARRAY_SIZE(test_perm);i++) {
                sd = security_descriptor_dacl_create(tctx,
                                                0, NULL, NULL,
                                                owner_rights_sid,
                                                test_perm[i].owner_flags,
                                                test_perm[i].owner_rights,
                                                0,
                                                owner_sid,
                                                SEC_ACE_TYPE_ACCESS_ALLOWED,
                                                SEC_RIGHTS_FILE_ALL,
                                                0,
                                                NULL);
                //sd->type |= SEC_DESC_DACL_AUTO_INHERITED |
SEC_DESC_DACL_AUTO_INHERIT_REQ;

                set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
                set.set_secdesc.in.file.handle = handle;
                set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
                set.set_secdesc.in.sd = sd;
                status = smb2_setinfo_file(tree, &set);
                printf("Iteration is %d\n", i);
                CHECK_STATUS(status, NT_STATUS_OK);

                q.query_secdesc.in.file.handle = handle;
                q.query_secdesc.in.secinfo_flags = SECINFO_DACL;
                status = smb2_getinfo_file(tree, tctx, &q);
                if (test_perm[i].owner_rights & (SEC_STD_WRITE_DAC |
SEC_STD_READ_CONTROL)) {
                        CHECK_STATUS(status, NT_STATUS_OK);
                } else if (test_perm[i].owner_rights & SEC_STD_WRITE_DAC) {
                        CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
                }

                if((test_perm[i].owner_flags & SEC_ACE_TYPE_ACCESS_DENIED))
{
                        smb2_util_close(tree, handle);
                        io.in.desired_access = 0x00020080;
                        io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
                        status = smb2_create(tree, tctx, &io);
                        CHECK_STATUS(status, NT_STATUS_OK);
                        handle = io.out.file.handle;

                        sd = q.query_secdesc.out.sd;
                        sd->dacl->aces[1].access_mask =
SEC_RIGHTS_FILE_READ;
                        set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
                        set.set_secdesc.in.file.handle = handle;
                        set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
                        set.set_secdesc.in.sd = sd;
                        status = smb2_setinfo_file(tree, &set);
                        CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
                }

        }
done:
        torture_comment(tctx, "put back original sd\n");
        set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
        set.set_secdesc.in.file.handle = handle;
        set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
        set.set_secdesc.in.sd = sd_orig;
        status = smb2_setinfo_file(tree, &set);
        smb2_util_close(tree, handle);
        smb2_util_rmdir(tree, dname);
        smb2_deltree(tree, BASEDIR);
        smb2_tdis(tree);
        smb2_logoff(tree->session);

        return ret;
}


More information about the samba-technical mailing list