static bool test_default_acl_posix(struct torture_context *tctx, struct smb2_tree *tree_unused) { struct smb2_tree *tree = NULL; NTSTATUS status; bool ok; bool ret = true; const char *dname = BASEDIR "\\testdir"; const char *fname = BASEDIR "\\testdir\\testfile"; struct smb2_handle fhandle = {{0}}; struct smb2_handle dhandle = {{0}}; union smb_fileinfo q; union smb_setfileinfo set; struct security_descriptor *sd = NULL; struct security_descriptor *exp_sd = NULL; char *owner_sid = NULL; char *group_sid = NULL; ok = torture_smb2_con_share(tctx, "acl_xattr_ign_sysacl_posix", &tree); torture_assert_goto(tctx, ok == true, ret, done, "Unable to connect to 'acl_xattr_ign_sysacl_posix'\n"); ok = smb2_util_setup_dir(tctx, tree, BASEDIR); torture_assert_goto(tctx, ok == true, ret, done, "Unable to setup testdir\n"); ZERO_STRUCT(dhandle); status = torture_smb2_testdir(tree, dname, &dhandle); torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir\n"); torture_comment(tctx, "Get the original sd\n"); ZERO_STRUCT(q); q.query_secdesc.level = RAW_FILEINFO_SEC_DESC; q.query_secdesc.in.file.handle = dhandle; q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER | SECINFO_GROUP; status = smb2_getinfo_file(tree, tctx, &q); torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_getinfo_file\n"); sd = q.query_secdesc.out.sd; owner_sid = dom_sid_string(tctx, sd->owner_sid); group_sid = dom_sid_string(tctx, sd->group_sid); torture_comment(tctx, "owner [%s] group [%s]\n", owner_sid, group_sid); torture_comment(tctx, "Set ACL with no inheritable ACE\n"); sd = security_descriptor_dacl_create(tctx, 0, NULL, NULL, owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_RIGHTS_DIR_ALL, 0, NULL); ZERO_STRUCT(set); set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC; set.set_secdesc.in.file.handle = dhandle; set.set_secdesc.in.secinfo_flags = SECINFO_DACL; set.set_secdesc.in.sd = sd; status = smb2_setinfo_file(tree, &set); torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_setinfo_file\n"); TALLOC_FREE(sd); smb2_util_close(tree, dhandle); torture_comment(tctx, "Create file\n"); ZERO_STRUCT(fhandle); status = torture_smb2_testfile(tree, fname, &fhandle); torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create_complex_file\n"); torture_comment(tctx, "Query file SD\n"); ZERO_STRUCT(q); q.query_secdesc.level = RAW_FILEINFO_SEC_DESC; q.query_secdesc.in.file.handle = fhandle; q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER | SECINFO_GROUP; status = smb2_getinfo_file(tree, tctx, &q); torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_getinfo_file\n"); sd = q.query_secdesc.out.sd; smb2_util_close(tree, fhandle); ZERO_STRUCT(fhandle); torture_comment(tctx, "Checking actual file SD against expected SD\n"); exp_sd = security_descriptor_dacl_create( tctx, 0, owner_sid, group_sid, owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_RIGHTS_FILE_ALL, 0, group_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, FILE_GENERIC_READ|FILE_GENERIC_WRITE|FILE_GENERIC_EXECUTE, 0, SID_WORLD, SEC_ACE_TYPE_ACCESS_ALLOWED, FILE_GENERIC_READ|FILE_GENERIC_WRITE|FILE_GENERIC_EXECUTE, 0, SID_NT_SYSTEM, SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_RIGHTS_FILE_ALL, 0, NULL); CHECK_SECURITY_DESCRIPTOR(sd, exp_sd); done: if (!smb2_util_handle_empty(fhandle)) { smb2_util_close(tree, fhandle); } if (!smb2_util_handle_empty(dhandle)) { smb2_util_close(tree, dhandle); } if (tree != NULL) { smb2_deltree(tree, BASEDIR); smb2_tdis(tree); } return ret; }
/** * test renaming after reauth. * compare security descriptors before and after rename/reauth */ bool test_session_reauth5(struct torture_context *tctx, struct smb2_tree *tree) { NTSTATUS status; TALLOC_CTX *mem_ctx = talloc_new(tctx); char dname[256]; char fname[256]; char fname2[256]; struct smb2_handle _dh1; struct smb2_handle *dh1 = NULL; struct smb2_handle _h1; struct smb2_handle *h1 = NULL; struct smb2_create io1; bool ret = true; bool ok; union smb_fileinfo qfinfo; union smb_setfileinfo sfinfo; struct cli_credentials *anon_creds = NULL; uint32_t secinfo_flags = SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL | SECINFO_PROTECTED_DACL | SECINFO_UNPROTECTED_DACL; struct security_descriptor *f_sd1; struct security_descriptor *d_sd1 = NULL; struct security_ace ace; struct dom_sid *extra_sid; /* Add some random component to the file name. */ snprintf(dname, 256, "session_reauth5_%s.d", generate_random_str(tctx, 8)); snprintf(fname, 256, "%s\\file.dat", dname); ok = smb2_util_setup_dir(tctx, tree, dname); CHECK_VAL(ok, true); status = torture_smb2_testdir(tree, dname, &_dh1); CHECK_STATUS(status, NT_STATUS_OK); dh1 = &_dh1; smb2_oplock_create_share(&io1, fname, smb2_util_share_access(""), smb2_util_oplock_level("b")); status = smb2_create(tree, mem_ctx, &io1); CHECK_STATUS(status, NT_STATUS_OK); _h1 = io1.out.file.handle; h1 = &_h1; CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE); CHECK_VAL(io1.out.oplock_level, smb2_util_oplock_level("b")); /* get the security descriptor */ ZERO_STRUCT(qfinfo); qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC; qfinfo.query_secdesc.in.file.handle = _h1; qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags; status = smb2_getinfo_file(tree, mem_ctx, &qfinfo); CHECK_STATUS(status, NT_STATUS_OK); f_sd1 = qfinfo.query_secdesc.out.sd; /* re-authenticate as anonymous */ anon_creds = cli_credentials_init_anon(mem_ctx); torture_assert(tctx, (anon_creds != NULL), "talloc error"); status = smb2_session_setup_spnego(tree->session, anon_creds, 0 /* previous_session_id */); CHECK_STATUS(status, NT_STATUS_OK); /* try to rename the file: fails */ snprintf(fname2, 256, "%s\\file2.dat", dname); smb2_util_unlink(tree, fname2); ZERO_STRUCT(sfinfo); sfinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION; sfinfo.rename_information.in.file.handle = _h1; sfinfo.rename_information.in.overwrite = true; sfinfo.rename_information.in.new_name = fname2; status = smb2_setinfo_file(tree, &sfinfo); CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED); /* re-authenticate as original user again */ status = smb2_session_setup_spnego(tree->session, cmdline_credentials, 0 /* previous_session_id */); CHECK_STATUS(status, NT_STATUS_OK); /* give full access on the file to anonymous */ extra_sid = dom_sid_parse_talloc(tctx, SID_NT_ANONYMOUS); ZERO_STRUCT(ace); ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED; ace.flags = 0; ace.access_mask = SEC_RIGHTS_FILE_ALL; ace.trustee = *extra_sid; status = security_descriptor_dacl_add(f_sd1, &ace); CHECK_STATUS(status, NT_STATUS_OK); ZERO_STRUCT(sfinfo); sfinfo.set_secdesc.level = RAW_SFILEINFO_SEC_DESC; sfinfo.set_secdesc.in.file.handle = _h1; sfinfo.set_secdesc.in.secinfo_flags = secinfo_flags; sfinfo.set_secdesc.in.sd = f_sd1; status = smb2_setinfo_file(tree, &sfinfo); CHECK_STATUS(status, NT_STATUS_OK); /* re-get the security descriptor */ ZERO_STRUCT(qfinfo); qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC; qfinfo.query_secdesc.in.file.handle = _h1; qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags; status = smb2_getinfo_file(tree, mem_ctx, &qfinfo); CHECK_STATUS(status, NT_STATUS_OK); /* re-authenticate as anonymous - again */ anon_creds = cli_credentials_init_anon(mem_ctx); torture_assert(tctx, (anon_creds != NULL), "talloc error"); status = smb2_session_setup_spnego(tree->session, anon_creds, 0 /* previous_session_id */); CHECK_STATUS(status, NT_STATUS_OK); /* try to rename the file: fails */ ZERO_STRUCT(sfinfo); sfinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION; sfinfo.rename_information.in.file.handle = _h1; sfinfo.rename_information.in.overwrite = true; sfinfo.rename_information.in.new_name = fname2; status = smb2_setinfo_file(tree, &sfinfo); CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED); /* give full access on the parent dir to anonymous */ ZERO_STRUCT(qfinfo); qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC; qfinfo.query_secdesc.in.file.handle = _dh1; qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags; status = smb2_getinfo_file(tree, mem_ctx, &qfinfo); CHECK_STATUS(status, NT_STATUS_OK); d_sd1 = qfinfo.query_secdesc.out.sd; ZERO_STRUCT(ace); ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED; ace.flags = 0; ace.access_mask = SEC_RIGHTS_FILE_ALL; ace.trustee = *extra_sid; status = security_descriptor_dacl_add(d_sd1, &ace); CHECK_STATUS(status, NT_STATUS_OK); ZERO_STRUCT(sfinfo); sfinfo.set_secdesc.level = RAW_SFILEINFO_SEC_DESC; sfinfo.set_secdesc.in.file.handle = _dh1; sfinfo.set_secdesc.in.secinfo_flags = secinfo_flags; sfinfo.set_secdesc.in.secinfo_flags = SECINFO_DACL; sfinfo.set_secdesc.in.sd = d_sd1; status = smb2_setinfo_file(tree, &sfinfo); CHECK_STATUS(status, NT_STATUS_OK); ZERO_STRUCT(qfinfo); qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC; qfinfo.query_secdesc.in.file.handle = _dh1; qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags; status = smb2_getinfo_file(tree, mem_ctx, &qfinfo); CHECK_STATUS(status, NT_STATUS_OK); smb2_util_close(tree, _dh1); dh1 = NULL; /* try to rename the file: still fails */ ZERO_STRUCT(sfinfo); sfinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION; sfinfo.rename_information.in.file.handle = _h1; sfinfo.rename_information.in.overwrite = true; sfinfo.rename_information.in.new_name = fname2; status = smb2_setinfo_file(tree, &sfinfo); CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED); /* re-authenticate as original user - again */ status = smb2_session_setup_spnego(tree->session, cmdline_credentials, 0 /* previous_session_id */); CHECK_STATUS(status, NT_STATUS_OK); /* rename the file - for verification that it works */ ZERO_STRUCT(sfinfo); sfinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION; sfinfo.rename_information.in.file.handle = _h1; sfinfo.rename_information.in.overwrite = true; sfinfo.rename_information.in.new_name = fname2; status = smb2_setinfo_file(tree, &sfinfo); CHECK_STATUS(status, NT_STATUS_OK); /* closs the file, check it is gone and reopen under the new name */ smb2_util_close(tree, _h1); ZERO_STRUCT(io1); smb2_generic_create_share(&io1, NULL /* lease */, false /* dir */, fname, NTCREATEX_DISP_OPEN, smb2_util_share_access(""), smb2_util_oplock_level("b"), 0 /* leasekey */, 0 /* leasestate */); status = smb2_create(tree, mem_ctx, &io1); CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND); ZERO_STRUCT(io1); smb2_generic_create_share(&io1, NULL /* lease */, false /* dir */, fname2, NTCREATEX_DISP_OPEN, smb2_util_share_access(""), smb2_util_oplock_level("b"), 0 /* leasekey */, 0 /* leasestate */); status = smb2_create(tree, mem_ctx, &io1); CHECK_STATUS(status, NT_STATUS_OK); _h1 = io1.out.file.handle; h1 = &_h1; CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE); CHECK_VAL(io1.out.oplock_level, smb2_util_oplock_level("b")); /* try to access the file via the old handle */ ZERO_STRUCT(qfinfo); qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC; qfinfo.query_secdesc.in.file.handle = _h1; qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags; status = smb2_getinfo_file(tree, mem_ctx, &qfinfo); CHECK_STATUS(status, NT_STATUS_OK); done: if (dh1 != NULL) { smb2_util_close(tree, *dh1); } if (h1 != NULL) { smb2_util_close(tree, *h1); } smb2_deltree(tree, dname); talloc_free(tree); talloc_free(mem_ctx); return ret; }
/* * Test creating a file with a NULL DACL. */ static bool test_create_null_dacl(struct torture_context *tctx, struct smb2_tree *tree) { NTSTATUS status; struct smb2_create io; const char *fname = "nulldacl.txt"; bool ret = true; struct smb2_handle handle; union smb_fileinfo q; union smb_setfileinfo s; struct security_descriptor *sd = security_descriptor_initialise(tctx); struct security_acl dacl; torture_comment(tctx, "TESTING SEC_DESC WITH A NULL DACL\n"); smb2_util_unlink(tree, fname); ZERO_STRUCT(io); io.level = RAW_OPEN_SMB2; io.in.create_flags = 0; io.in.desired_access = SEC_STD_READ_CONTROL | SEC_STD_WRITE_DAC | SEC_STD_WRITE_OWNER; io.in.create_options = 0; io.in.file_attributes = FILE_ATTRIBUTE_NORMAL; io.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE; 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 = fname; io.in.sec_desc = sd; /* XXX create_options ? */ io.in.create_options = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY | NTCREATEX_OPTIONS_ASYNC_ALERT | NTCREATEX_OPTIONS_NON_DIRECTORY_FILE | 0x00200000; torture_comment(tctx, "creating a file with a empty sd\n"); 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_OWNER | SECINFO_GROUP | SECINFO_DACL; status = smb2_getinfo_file(tree, tctx, &q); CHECK_STATUS(status, NT_STATUS_OK); /* * Testing the created DACL, * the server should add the inherited DACL * when SEC_DESC_DACL_PRESENT isn't specified */ if (!(q.query_secdesc.out.sd->type & SEC_DESC_DACL_PRESENT)) { ret = false; torture_fail_goto(tctx, done, "DACL_PRESENT flag not set by the server!\n"); } if (q.query_secdesc.out.sd->dacl == NULL) { ret = false; torture_fail_goto(tctx, done, "no DACL has been created on the server!\n"); } torture_comment(tctx, "set NULL DACL\n"); sd->type |= SEC_DESC_DACL_PRESENT; s.set_secdesc.level = RAW_SFILEINFO_SEC_DESC; s.set_secdesc.in.file.handle = handle; s.set_secdesc.in.secinfo_flags = SECINFO_DACL; s.set_secdesc.in.sd = sd; status = smb2_setinfo_file(tree, &s); CHECK_STATUS(status, NT_STATUS_OK); torture_comment(tctx, "get the sd\n"); q.query_secdesc.level = RAW_FILEINFO_SEC_DESC; q.query_secdesc.in.file.handle = handle; q.query_secdesc.in.secinfo_flags = SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL; status = smb2_getinfo_file(tree, tctx, &q); CHECK_STATUS(status, NT_STATUS_OK); /* Testing the modified DACL */ if (!(q.query_secdesc.out.sd->type & SEC_DESC_DACL_PRESENT)) { ret = false; torture_fail_goto(tctx, done, "DACL_PRESENT flag not set by the server!\n"); } if (q.query_secdesc.out.sd->dacl != NULL) { ret = false; torture_fail_goto(tctx, done, "DACL has been created on the server!\n"); } io.in.create_disposition = NTCREATEX_DISP_OPEN; torture_comment(tctx, "try open for read control\n"); io.in.desired_access = SEC_STD_READ_CONTROL; status = smb2_create(tree, tctx, &io); CHECK_STATUS(status, NT_STATUS_OK); CHECK_ACCESS_FLAGS(io.out.file.handle, SEC_STD_READ_CONTROL); smb2_util_close(tree, io.out.file.handle); torture_comment(tctx, "try open for write\n"); io.in.desired_access = SEC_FILE_WRITE_DATA; status = smb2_create(tree, tctx, &io); CHECK_STATUS(status, NT_STATUS_OK); CHECK_ACCESS_FLAGS(io.out.file.handle, SEC_FILE_WRITE_DATA); smb2_util_close(tree, io.out.file.handle); torture_comment(tctx, "try open for read\n"); io.in.desired_access = SEC_FILE_READ_DATA; status = smb2_create(tree, tctx, &io); CHECK_STATUS(status, NT_STATUS_OK); CHECK_ACCESS_FLAGS(io.out.file.handle, SEC_FILE_READ_DATA); smb2_util_close(tree, io.out.file.handle); torture_comment(tctx, "try open for generic write\n"); io.in.desired_access = SEC_GENERIC_WRITE; status = smb2_create(tree, tctx, &io); CHECK_STATUS(status, NT_STATUS_OK); CHECK_ACCESS_FLAGS(io.out.file.handle, SEC_RIGHTS_FILE_WRITE); smb2_util_close(tree, io.out.file.handle); torture_comment(tctx, "try open for generic read\n"); io.in.desired_access = SEC_GENERIC_READ; status = smb2_create(tree, tctx, &io); CHECK_STATUS(status, NT_STATUS_OK); CHECK_ACCESS_FLAGS(io.out.file.handle, SEC_RIGHTS_FILE_READ); smb2_util_close(tree, io.out.file.handle); torture_comment(tctx, "set DACL with 0 aces\n"); ZERO_STRUCT(dacl); dacl.revision = SECURITY_ACL_REVISION_NT4; dacl.num_aces = 0; sd->dacl = &dacl; s.set_secdesc.level = RAW_SFILEINFO_SEC_DESC; s.set_secdesc.in.file.handle = handle; s.set_secdesc.in.secinfo_flags = SECINFO_DACL; s.set_secdesc.in.sd = sd; status = smb2_setinfo_file(tree, &s); CHECK_STATUS(status, NT_STATUS_OK); torture_comment(tctx, "get the sd\n"); q.query_secdesc.level = RAW_FILEINFO_SEC_DESC; q.query_secdesc.in.file.handle = handle; q.query_secdesc.in.secinfo_flags = SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL; status = smb2_getinfo_file(tree, tctx, &q); CHECK_STATUS(status, NT_STATUS_OK); /* Testing the modified DACL */ if (!(q.query_secdesc.out.sd->type & SEC_DESC_DACL_PRESENT)) { ret = false; torture_fail_goto(tctx, done, "DACL_PRESENT flag not set by the server!\n"); } if (q.query_secdesc.out.sd->dacl == NULL) { ret = false; torture_fail_goto(tctx, done, "no DACL has been created on the server!\n"); } if (q.query_secdesc.out.sd->dacl->num_aces != 0) { torture_result(tctx, TORTURE_FAIL, "DACL has %u aces!\n", q.query_secdesc.out.sd->dacl->num_aces); ret = false; goto done; } torture_comment(tctx, "try open for read control\n"); io.in.desired_access = SEC_STD_READ_CONTROL; status = smb2_create(tree, tctx, &io); CHECK_STATUS(status, NT_STATUS_OK); CHECK_ACCESS_FLAGS(io.out.file.handle, SEC_STD_READ_CONTROL); smb2_util_close(tree, io.out.file.handle); torture_comment(tctx, "try open for write => access_denied\n"); io.in.desired_access = SEC_FILE_WRITE_DATA; status = smb2_create(tree, tctx, &io); if (torture_setting_bool(tctx, "hide_on_access_denied", false)) { CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND); } else { CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED); } torture_comment(tctx, "try open for read => access_denied\n"); io.in.desired_access = SEC_FILE_READ_DATA; status = smb2_create(tree, tctx, &io); if (torture_setting_bool(tctx, "hide_on_access_denied", false)) { CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND); } else { CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED); } torture_comment(tctx, "try open for generic write => access_denied\n"); io.in.desired_access = SEC_GENERIC_WRITE; status = smb2_create(tree, tctx, &io); if (torture_setting_bool(tctx, "hide_on_access_denied", false)) { CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND); } else { CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED); } torture_comment(tctx, "try open for generic read => access_denied\n"); io.in.desired_access = SEC_GENERIC_READ; status = smb2_create(tree, tctx, &io); if (torture_setting_bool(tctx, "hide_on_access_denied", false)) { CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND); } else { CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED); } torture_comment(tctx, "set empty sd\n"); sd->type &= ~SEC_DESC_DACL_PRESENT; sd->dacl = NULL; s.set_secdesc.level = RAW_SFILEINFO_SEC_DESC; s.set_secdesc.in.file.handle = handle; s.set_secdesc.in.secinfo_flags = SECINFO_DACL; s.set_secdesc.in.sd = sd; status = smb2_setinfo_file(tree, &s); CHECK_STATUS(status, NT_STATUS_OK); torture_comment(tctx, "get the sd\n"); q.query_secdesc.level = RAW_FILEINFO_SEC_DESC; q.query_secdesc.in.file.handle = handle; q.query_secdesc.in.secinfo_flags = SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL; status = smb2_getinfo_file(tree, tctx, &q); CHECK_STATUS(status, NT_STATUS_OK); /* Testing the modified DACL */ if (!(q.query_secdesc.out.sd->type & SEC_DESC_DACL_PRESENT)) { ret = false; torture_fail_goto(tctx, done, "DACL_PRESENT flag not set by the server!\n"); } if (q.query_secdesc.out.sd->dacl != NULL) { ret = false; torture_fail_goto(tctx, done, "DACL has been created on the server!\n"); } done: smb2_util_close(tree, handle); smb2_util_unlink(tree, fname); smb2_tdis(tree); smb2_logoff(tree->session); return ret; }
/** * test setting security descriptor after reauth. */ bool test_session_reauth4(struct torture_context *tctx, struct smb2_tree *tree) { NTSTATUS status; TALLOC_CTX *mem_ctx = talloc_new(tctx); char fname[256]; struct smb2_handle _h1; struct smb2_handle *h1 = NULL; struct smb2_create io1; bool ret = true; union smb_fileinfo qfinfo; union smb_setfileinfo sfinfo; struct cli_credentials *anon_creds = NULL; uint32_t secinfo_flags = SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL | SECINFO_PROTECTED_DACL | SECINFO_UNPROTECTED_DACL; struct security_descriptor *sd1; struct security_ace ace; struct dom_sid *extra_sid; /* Add some random component to the file name. */ snprintf(fname, 256, "session_reauth4_%s.dat", generate_random_str(tctx, 8)); smb2_util_unlink(tree, fname); smb2_oplock_create_share(&io1, fname, smb2_util_share_access(""), smb2_util_oplock_level("b")); status = smb2_create(tree, mem_ctx, &io1); CHECK_STATUS(status, NT_STATUS_OK); _h1 = io1.out.file.handle; h1 = &_h1; CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE); CHECK_VAL(io1.out.oplock_level, smb2_util_oplock_level("b")); /* get the security descriptor */ ZERO_STRUCT(qfinfo); qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC; qfinfo.query_secdesc.in.file.handle = _h1; qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags; status = smb2_getinfo_file(tree, mem_ctx, &qfinfo); CHECK_STATUS(status, NT_STATUS_OK); sd1 = qfinfo.query_secdesc.out.sd; /* re-authenticate as anonymous */ anon_creds = cli_credentials_init_anon(mem_ctx); torture_assert(tctx, (anon_creds != NULL), "talloc error"); status = smb2_session_setup_spnego(tree->session, anon_creds, 0 /* previous_session_id */); CHECK_STATUS(status, NT_STATUS_OK); /* give full access on the file to anonymous */ extra_sid = dom_sid_parse_talloc(tctx, SID_NT_ANONYMOUS); ZERO_STRUCT(ace); ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED; ace.flags = 0; ace.access_mask = SEC_STD_ALL | SEC_FILE_ALL; ace.trustee = *extra_sid; status = security_descriptor_dacl_add(sd1, &ace); CHECK_STATUS(status, NT_STATUS_OK); ZERO_STRUCT(sfinfo); sfinfo.set_secdesc.level = RAW_SFILEINFO_SEC_DESC; sfinfo.set_secdesc.in.file.handle = _h1; sfinfo.set_secdesc.in.secinfo_flags = SECINFO_DACL; sfinfo.set_secdesc.in.sd = sd1; status = smb2_setinfo_file(tree, &sfinfo); CHECK_STATUS(status, NT_STATUS_OK); /* re-authenticate as original user again */ status = smb2_session_setup_spnego(tree->session, cmdline_credentials, 0 /* previous_session_id */); CHECK_STATUS(status, NT_STATUS_OK); /* re-get the security descriptor */ ZERO_STRUCT(qfinfo); qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC; qfinfo.query_secdesc.in.file.handle = _h1; qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags; status = smb2_getinfo_file(tree, mem_ctx, &qfinfo); CHECK_STATUS(status, NT_STATUS_OK); ret = true; done: if (h1 != NULL) { smb2_util_close(tree, *h1); } smb2_util_unlink(tree, fname); talloc_free(tree); talloc_free(mem_ctx); return ret; }
/* basic testing of SMB2 durable opens regarding the position information on the handle */ bool test_durable_open_file_position(struct torture_context *tctx, struct smb2_tree *tree1, struct smb2_tree *tree2) { TALLOC_CTX *mem_ctx = talloc_new(tctx); struct smb2_handle h1, h2; struct smb2_create io1, io2; NTSTATUS status; const char *fname = "durable_open_position.dat"; union smb_fileinfo qfinfo; union smb_setfileinfo sfinfo; bool ret = true; uint64_t pos; smb2_util_unlink(tree1, fname); ZERO_STRUCT(io1); io1.in.security_flags = 0x00; io1.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH; io1.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION; io1.in.create_flags = 0x00000000; io1.in.reserved = 0x00000000; io1.in.desired_access = SEC_RIGHTS_FILE_ALL; io1.in.file_attributes = FILE_ATTRIBUTE_NORMAL; io1.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE; io1.in.create_disposition = NTCREATEX_DISP_OPEN_IF; io1.in.create_options = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY | NTCREATEX_OPTIONS_ASYNC_ALERT | NTCREATEX_OPTIONS_NON_DIRECTORY_FILE | 0x00200000; io1.in.durable_open = true; io1.in.fname = fname; status = smb2_create(tree1, mem_ctx, &io1); CHECK_STATUS(status, NT_STATUS_OK); h1 = io1.out.file.handle; CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE); CHECK_VAL(io1.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH); /* TODO: check extra blob content */ ZERO_STRUCT(qfinfo); qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION; qfinfo.generic.in.file.handle = h1; status = smb2_getinfo_file(tree1, mem_ctx, &qfinfo); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VAL(qfinfo.position_information.out.position, 0); pos = qfinfo.position_information.out.position; torture_comment(tctx, "position: %llu\n", (unsigned long long)pos); ZERO_STRUCT(sfinfo); sfinfo.generic.level = RAW_SFILEINFO_POSITION_INFORMATION; sfinfo.generic.in.file.handle = h1; sfinfo.position_information.in.position = 0x1000; status = smb2_setinfo_file(tree1, &sfinfo); CHECK_STATUS(status, NT_STATUS_OK); ZERO_STRUCT(qfinfo); qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION; qfinfo.generic.in.file.handle = h1; status = smb2_getinfo_file(tree1, mem_ctx, &qfinfo); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VAL(qfinfo.position_information.out.position, 0x1000); pos = qfinfo.position_information.out.position; torture_comment(tctx, "position: %llu\n", (unsigned long long)pos); talloc_free(tree1); tree1 = NULL; ZERO_STRUCT(qfinfo); qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION; qfinfo.generic.in.file.handle = h1; status = smb2_getinfo_file(tree2, mem_ctx, &qfinfo); CHECK_STATUS(status, NT_STATUS_FILE_CLOSED); ZERO_STRUCT(io2); io2.in.fname = fname; io2.in.durable_handle = &h1; status = smb2_create(tree2, mem_ctx, &io2); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VAL(io2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH); CHECK_VAL(io2.out.reserved, 0x00); CHECK_VAL(io2.out.create_action, NTCREATEX_ACTION_EXISTED); CHECK_VAL(io2.out.alloc_size, 0); CHECK_VAL(io2.out.size, 0); CHECK_VAL(io2.out.file_attr, FILE_ATTRIBUTE_ARCHIVE); CHECK_VAL(io2.out.reserved2, 0); h2 = io2.out.file.handle; ZERO_STRUCT(qfinfo); qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION; qfinfo.generic.in.file.handle = h2; status = smb2_getinfo_file(tree2, mem_ctx, &qfinfo); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VAL(qfinfo.position_information.out.position, 0x1000); pos = qfinfo.position_information.out.position; torture_comment(tctx, "position: %llu\n", (unsigned long long)pos); smb2_util_close(tree2, h2); talloc_free(mem_ctx); smb2_util_unlink(tree2, fname); done: return ret; }