bool torture_samba3_caseinsensitive(struct torture_context *torture, struct smbcli_state *cli) { TALLOC_CTX *mem_ctx; const char *dirname = "insensitive"; const char *ucase_dirname = "InSeNsItIvE"; const char *fname = "foo"; char *fpath; int fnum; int counter = 0; bool ret = false; if (!(mem_ctx = talloc_init("torture_samba3_caseinsensitive"))) { torture_result(torture, TORTURE_FAIL, "talloc_init failed\n"); return false; } torture_assert(torture, torture_setup_dir(cli, dirname), "creating test directory"); if (!(fpath = talloc_asprintf(mem_ctx, "%s\\%s", dirname, fname))) { goto done; } fnum = smbcli_open(cli->tree, fpath, O_RDWR | O_CREAT, DENY_NONE); if (fnum == -1) { torture_result(torture, TORTURE_FAIL, "Could not create file %s: %s", fpath, smbcli_errstr(cli->tree)); goto done; } smbcli_close(cli->tree, fnum); smbcli_list(cli->tree, talloc_asprintf( mem_ctx, "%s\\*", ucase_dirname), FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_HIDDEN |FILE_ATTRIBUTE_SYSTEM, count_fn, (void *)&counter); if (counter == 3) { ret = true; } else { torture_result(torture, TORTURE_FAIL, "expected 3 entries, got %d", counter); ret = false; } done: talloc_free(mem_ctx); return ret; }
static bool check_unix_info2(struct torture_context *torture, struct unix_info2 *info2) { printf("\tcreate_time=0x%016llu flags=0x%08x mask=0x%08x\n", (unsigned long long)info2->create_time, info2->file_flags, info2->flags_mask); if (info2->file_flags == 0) { return true; } /* If we have any file_flags set, they must be within the range * defined by flags_mask. */ if ((info2->flags_mask & info2->file_flags) == 0) { torture_result(torture, TORTURE_FAIL, __location__": UNIX_INFO2 flags field 0x%08x, " "does not match mask 0x%08x\n", info2->file_flags, info2->flags_mask); } return true; }
bool torture_samba3_badpath(struct torture_context *torture) { struct smbcli_state *cli_nt = NULL; struct smbcli_state *cli_dos = NULL; const char *fname = "test.txt"; const char *fname1 = "test1.txt"; const char *dirname = "testdir"; char *fpath; char *fpath1; int fnum; NTSTATUS status; bool ret = true; TALLOC_CTX *mem_ctx; bool nt_status_support; torture_assert(torture, mem_ctx = talloc_init("torture_samba3_badpath"), "talloc_init failed"); nt_status_support = lpcfg_nt_status_support(torture->lp_ctx); torture_assert_goto(torture, lpcfg_set_cmdline(torture->lp_ctx, "nt status support", "yes"), ret, fail, "Could not set 'nt status support = yes'\n"); torture_assert_goto(torture, torture_open_connection(&cli_nt, torture, 0), ret, fail, "Could not open NTSTATUS connection\n"); torture_assert_goto(torture, lpcfg_set_cmdline(torture->lp_ctx, "nt status support", "no"), ret, fail, "Could not set 'nt status support = no'\n"); torture_assert_goto(torture, torture_open_connection(&cli_dos, torture, 1), ret, fail, "Could not open DOS connection\n"); torture_assert_goto(torture, lpcfg_set_cmdline(torture->lp_ctx, "nt status support", nt_status_support ? "yes":"no"), ret, fail, "Could not set 'nt status support' back to where it was\n"); torture_assert(torture, torture_setup_dir(cli_nt, dirname), "creating test directory"); status = smbcli_chkpath(cli_nt->tree, dirname); CHECK_STATUS(torture, status, NT_STATUS_OK); status = smbcli_chkpath(cli_nt->tree, talloc_asprintf(mem_ctx, "%s\\bla", dirname)); CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_NOT_FOUND); status = smbcli_chkpath(cli_dos->tree, talloc_asprintf(mem_ctx, "%s\\bla", dirname)); CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRbadpath)); status = smbcli_chkpath(cli_nt->tree, talloc_asprintf(mem_ctx, "%s\\bla\\blub", dirname)); CHECK_STATUS(torture, status, NT_STATUS_OBJECT_PATH_NOT_FOUND); status = smbcli_chkpath(cli_dos->tree, talloc_asprintf(mem_ctx, "%s\\bla\\blub", dirname)); CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRbadpath)); torture_assert_goto(torture, fpath = talloc_asprintf(mem_ctx, "%s\\%s", dirname, fname), ret, fail, "Could not allocate fpath\n"); fnum = smbcli_open(cli_nt->tree, fpath, O_RDWR | O_CREAT, DENY_NONE); if (fnum == -1) { torture_result(torture, TORTURE_FAIL, "Could not create file %s: %s\n", fpath, smbcli_errstr(cli_nt->tree)); goto fail; } smbcli_close(cli_nt->tree, fnum); if (!(fpath1 = talloc_asprintf(mem_ctx, "%s\\%s", dirname, fname1))) { goto fail; } fnum = smbcli_open(cli_nt->tree, fpath1, O_RDWR | O_CREAT, DENY_NONE); if (fnum == -1) { torture_result(torture, TORTURE_FAIL, "Could not create file %s: %s\n", fpath1, smbcli_errstr(cli_nt->tree)); goto fail; } smbcli_close(cli_nt->tree, fnum); /* * Do a whole bunch of error code checks on chkpath */ status = smbcli_chkpath(cli_nt->tree, fpath); CHECK_STATUS(torture, status, NT_STATUS_NOT_A_DIRECTORY); status = smbcli_chkpath(cli_dos->tree, fpath); CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRbadpath)); status = smbcli_chkpath(cli_nt->tree, ".."); CHECK_STATUS(torture, status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD); status = smbcli_chkpath(cli_dos->tree, ".."); CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidpath)); status = smbcli_chkpath(cli_nt->tree, "."); CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID); status = smbcli_chkpath(cli_dos->tree, "."); CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRbadpath)); status = smbcli_chkpath(cli_nt->tree, "\t"); CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID); status = smbcli_chkpath(cli_dos->tree, "\t"); CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRbadpath)); status = smbcli_chkpath(cli_nt->tree, "\t\\bla"); CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID); status = smbcli_chkpath(cli_dos->tree, "\t\\bla"); CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRbadpath)); status = smbcli_chkpath(cli_nt->tree, "<"); CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID); status = smbcli_chkpath(cli_dos->tree, "<"); CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRbadpath)); status = smbcli_chkpath(cli_nt->tree, "<\\bla"); CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID); status = smbcli_chkpath(cli_dos->tree, "<\\bla"); CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRbadpath)); /* * .... And the same gang against getatr. Note that the DOS error codes * differ.... */ status = smbcli_getatr(cli_nt->tree, fpath, NULL, NULL, NULL); CHECK_STATUS(torture, status, NT_STATUS_OK); status = smbcli_getatr(cli_dos->tree, fpath, NULL, NULL, NULL); CHECK_STATUS(torture, status, NT_STATUS_OK); status = smbcli_getatr(cli_nt->tree, "..", NULL, NULL, NULL); CHECK_STATUS(torture, status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD); status = smbcli_getatr(cli_dos->tree, "..", NULL, NULL, NULL); CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidpath)); status = smbcli_getatr(cli_nt->tree, ".", NULL, NULL, NULL); CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID); status = smbcli_getatr(cli_dos->tree, ".", NULL, NULL, NULL); CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidname)); status = smbcli_getatr(cli_nt->tree, "\t", NULL, NULL, NULL); CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID); status = smbcli_getatr(cli_dos->tree, "\t", NULL, NULL, NULL); CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidname)); status = smbcli_getatr(cli_nt->tree, "\t\\bla", NULL, NULL, NULL); CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID); status = smbcli_getatr(cli_dos->tree, "\t\\bla", NULL, NULL, NULL); CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidname)); status = smbcli_getatr(cli_nt->tree, "<", NULL, NULL, NULL); CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID); status = smbcli_getatr(cli_dos->tree, "<", NULL, NULL, NULL); CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidname)); status = smbcli_getatr(cli_nt->tree, "<\\bla", NULL, NULL, NULL); CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID); status = smbcli_getatr(cli_dos->tree, "<\\bla", NULL, NULL, NULL); CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidname)); /* Try the same set with openX. */ status = raw_smbcli_open(cli_nt->tree, "..", O_RDONLY, DENY_NONE, NULL); CHECK_STATUS(torture, status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD); status = raw_smbcli_open(cli_dos->tree, "..", O_RDONLY, DENY_NONE, NULL); CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidpath)); status = raw_smbcli_open(cli_nt->tree, ".", O_RDONLY, DENY_NONE, NULL); CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID); status = raw_smbcli_open(cli_dos->tree, ".", O_RDONLY, DENY_NONE, NULL); CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidname)); status = raw_smbcli_open(cli_nt->tree, "\t", O_RDONLY, DENY_NONE, NULL); CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID); status = raw_smbcli_open(cli_dos->tree, "\t", O_RDONLY, DENY_NONE, NULL); CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidname)); status = raw_smbcli_open(cli_nt->tree, "\t\\bla", O_RDONLY, DENY_NONE, NULL); CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID); status = raw_smbcli_open(cli_dos->tree, "\t\\bla", O_RDONLY, DENY_NONE, NULL); CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidname)); status = raw_smbcli_open(cli_nt->tree, "<", O_RDONLY, DENY_NONE, NULL); CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID); status = raw_smbcli_open(cli_dos->tree, "<", O_RDONLY, DENY_NONE, NULL); CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidname)); status = raw_smbcli_open(cli_nt->tree, "<\\bla", O_RDONLY, DENY_NONE, NULL); CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID); status = raw_smbcli_open(cli_dos->tree, "<\\bla", O_RDONLY, DENY_NONE, NULL); CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidname)); /* Let's test EEXIST error code mapping. */ status = raw_smbcli_open(cli_nt->tree, fpath, O_RDONLY | O_CREAT| O_EXCL, DENY_NONE, NULL); CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_COLLISION); status = raw_smbcli_open(cli_dos->tree, fpath, O_RDONLY | O_CREAT| O_EXCL, DENY_NONE, NULL); CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS,ERRfilexists)); status = raw_smbcli_t2open(cli_nt->tree, fpath, O_RDONLY | O_CREAT| O_EXCL, DENY_NONE, NULL); if (!NT_STATUS_EQUAL(status, NT_STATUS_EAS_NOT_SUPPORTED) || !torture_setting_bool(torture, "samba3", false)) { /* Against samba3, treat EAS_NOT_SUPPORTED as acceptable */ CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_COLLISION); } status = raw_smbcli_t2open(cli_dos->tree, fpath, O_RDONLY | O_CREAT| O_EXCL, DENY_NONE, NULL); if (!NT_STATUS_EQUAL(status, NT_STATUS_DOS(ERRDOS,ERReasnotsupported)) || !torture_setting_bool(torture, "samba3", false)) { /* Against samba3, treat EAS_NOT_SUPPORTED as acceptable */ CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS,ERRfilexists)); } status = raw_smbcli_ntcreate(cli_nt->tree, fpath, NULL); CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_COLLISION); status = raw_smbcli_ntcreate(cli_dos->tree, fpath, NULL); CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS,ERRfilexists)); /* Try the rename test. */ { union smb_rename io; memset(&io, '\0', sizeof(io)); io.rename.in.pattern1 = fpath1; io.rename.in.pattern2 = fpath; /* Try with SMBmv rename. */ status = smb_raw_rename(cli_nt->tree, &io); CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_COLLISION); status = smb_raw_rename(cli_dos->tree, &io); CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS,ERRrename)); /* Try with NT rename. */ io.generic.level = RAW_RENAME_NTRENAME; io.ntrename.in.old_name = fpath1; io.ntrename.in.new_name = fpath; io.ntrename.in.attrib = 0; io.ntrename.in.cluster_size = 0; io.ntrename.in.flags = RENAME_FLAG_RENAME; status = smb_raw_rename(cli_nt->tree, &io); CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_COLLISION); status = smb_raw_rename(cli_dos->tree, &io); CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS,ERRrename)); } goto done; fail: ret = false; done: if (cli_nt != NULL) { smbcli_deltree(cli_nt->tree, dirname); torture_close_connection(cli_nt); } if (cli_dos != NULL) { torture_close_connection(cli_dos); } talloc_free(mem_ctx); return ret; }
bool torture_samba3_checkfsp(struct torture_context *torture, struct smbcli_state *cli) { const char *fname = "test.txt"; const char *dirname = "testdir"; int fnum; NTSTATUS status; bool ret = true; TALLOC_CTX *mem_ctx; ssize_t nread; char buf[16]; struct smbcli_tree *tree2; torture_assert(torture, mem_ctx = talloc_init("torture_samba3_checkfsp"), "talloc_init failed\n"); torture_assert_ntstatus_equal(torture, torture_second_tcon(torture, cli->session, torture_setting_string(torture, "share", NULL), &tree2), NT_STATUS_OK, "creating second tcon"); /* Try a read on an invalid FID */ nread = smbcli_read(cli->tree, 4711, buf, 0, sizeof(buf)); CHECK_STATUS(torture, smbcli_nt_error(cli->tree), NT_STATUS_INVALID_HANDLE); /* Try a read on a directory handle */ torture_assert(torture, torture_setup_dir(cli, dirname), "creating test directory"); /* Open the directory */ { union smb_open io; io.generic.level = RAW_OPEN_NTCREATEX; io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED; io.ntcreatex.in.root_fid.fnum = 0; io.ntcreatex.in.security_flags = 0; io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE; io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL; io.ntcreatex.in.alloc_size = 0; io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY; io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE; io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN; io.ntcreatex.in.create_options = 0; io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS; io.ntcreatex.in.fname = dirname; status = smb_raw_open(cli->tree, mem_ctx, &io); if (!NT_STATUS_IS_OK(status)) { torture_result(torture, TORTURE_FAIL, "smb_open on the directory failed: %s\n", nt_errstr(status)); ret = false; goto done; } fnum = io.ntcreatex.out.file.fnum; } /* Try a read on the directory */ nread = smbcli_read(cli->tree, fnum, buf, 0, sizeof(buf)); if (nread >= 0) { torture_result(torture, TORTURE_FAIL, "smbcli_read on a directory succeeded, expected " "failure\n"); ret = false; } CHECK_STATUS(torture, smbcli_nt_error(cli->tree), NT_STATUS_INVALID_DEVICE_REQUEST); /* Same test on the second tcon */ nread = smbcli_read(tree2, fnum, buf, 0, sizeof(buf)); if (nread >= 0) { torture_result(torture, TORTURE_FAIL, "smbcli_read on a directory succeeded, expected " "failure\n"); ret = false; } CHECK_STATUS(torture, smbcli_nt_error(tree2), NT_STATUS_INVALID_HANDLE); smbcli_close(cli->tree, fnum); /* Try a normal file read on a second tcon */ fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE); if (fnum == -1) { torture_result(torture, TORTURE_FAIL, "Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree)); ret = false; goto done; } nread = smbcli_read(tree2, fnum, buf, 0, sizeof(buf)); CHECK_STATUS(torture, smbcli_nt_error(tree2), NT_STATUS_INVALID_HANDLE); smbcli_close(cli->tree, fnum); done: smbcli_deltree(cli->tree, dirname); talloc_free(mem_ctx); return ret; }
/* test tdb speed */ static bool test_tdb_speed(struct torture_context *torture, const void *_data) { struct timeval tv; struct tdb_wrap *tdbw; int timelimit = torture_setting_int(torture, "timelimit", 10); int i, count; TALLOC_CTX *tmp_ctx = talloc_new(torture); unlink("test.tdb"); torture_comment(torture, "Testing tdb speed for sidmap\n"); tdbw = tdb_wrap_open(tmp_ctx, "test.tdb", 10000, 0, O_RDWR|O_CREAT|O_TRUNC, 0600); if (!tdbw) { unlink("test.tdb"); talloc_free(tmp_ctx); torture_fail(torture, "Failed to open test.tdb"); } torture_comment(torture, "Adding %d SID records\n", torture_entries); for (i=0;i<torture_entries;i++) { if (!tdb_add_record(tdbw, "S-1-5-21-53173311-3623041448-2049097239-%u", "UID %u", i)) { torture_result(torture, TORTURE_FAIL, "Failed to add SID %d\n", i); goto failed; } if (!tdb_add_record(tdbw, "UID %u", "S-1-5-21-53173311-3623041448-2049097239-%u", i)) { torture_result(torture, TORTURE_FAIL, "Failed to add UID %d\n", i); goto failed; } } torture_comment(torture, "Testing for %d seconds\n", timelimit); tv = timeval_current(); for (count=0;timeval_elapsed(&tv) < timelimit;count++) { TDB_DATA key, data; i = random() % torture_entries; key.dptr = (uint8_t *)talloc_asprintf(tmp_ctx, "S-1-5-21-53173311-3623041448-2049097239-%u", i); key.dsize = strlen((char *)key.dptr)+1; data = tdb_fetch(tdbw->tdb, key); talloc_free(key.dptr); if (data.dptr == NULL) { torture_result(torture, TORTURE_FAIL, "Failed to fetch SID %d\n", i); goto failed; } free(data.dptr); key.dptr = (uint8_t *)talloc_asprintf(tmp_ctx, "UID %u", i); key.dsize = strlen((char *)key.dptr)+1; data = tdb_fetch(tdbw->tdb, key); talloc_free(key.dptr); if (data.dptr == NULL) { torture_result(torture, TORTURE_FAIL, "Failed to fetch UID %d\n", i); goto failed; } free(data.dptr); } tdb_speed = count/timeval_elapsed(&tv); torture_comment(torture, "tdb speed %.2f ops/sec\n", tdb_speed); unlink("test.tdb"); talloc_free(tmp_ctx); return true; failed: unlink("test.tdb"); talloc_free(tmp_ctx); return false; }
/* * 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 ldb speed */ static bool test_ldb_speed(struct torture_context *torture, const void *_data) { struct timeval tv; struct ldb_context *ldb; int timelimit = torture_setting_int(torture, "timelimit", 10); int i, count; TALLOC_CTX *tmp_ctx = talloc_new(torture); struct ldb_ldif *ldif; const char *init_ldif = "dn: @INDEXLIST\n" \ "@IDXATTR: UID\n"; float ldb_speed; unlink("./test.ldb"); torture_comment(torture, "Testing ldb speed for sidmap\n"); ldb = ldb_wrap_connect(tmp_ctx, torture->ev, torture->lp_ctx, "tdb://test.ldb", NULL, NULL, LDB_FLG_NOSYNC, NULL); if (!ldb) { unlink("./test.ldb"); talloc_free(tmp_ctx); torture_fail(torture, "Failed to open test.ldb"); } /* add an index */ ldif = ldb_ldif_read_string(ldb, &init_ldif); if (ldif == NULL) goto failed; if (ldb_add(ldb, ldif->msg) != LDB_SUCCESS) goto failed; talloc_free(ldif); torture_comment(torture, "Adding %d SID records\n", torture_entries); for (i=0;i<torture_entries;i++) { if (!ldb_add_record(ldb, i)) { torture_result(torture, TORTURE_FAIL, "Failed to add SID %d\n", i); goto failed; } } if (talloc_total_blocks(torture) > 100) { torture_result(torture, TORTURE_FAIL, "memory leak in ldb add\n"); goto failed; } torture_comment(torture, "Testing for %d seconds\n", timelimit); tv = timeval_current(); for (count=0;timeval_elapsed(&tv) < timelimit;count++) { struct ldb_dn *dn; struct ldb_result *res; i = random() % torture_entries; dn = ldb_dn_new_fmt(tmp_ctx, ldb, "SID=S-1-5-21-53173311-3623041448-2049097239-%u", i); if (ldb_search(ldb, tmp_ctx, &res, dn, LDB_SCOPE_BASE, NULL, NULL) != LDB_SUCCESS || res->count != 1) { torture_fail(torture, talloc_asprintf(torture, "Failed to find SID %d", i)); } talloc_free(res); talloc_free(dn); if (ldb_search(ldb, tmp_ctx, &res, NULL, LDB_SCOPE_SUBTREE, NULL, "(UID=%u)", i) != LDB_SUCCESS || res->count != 1) { torture_fail(torture, talloc_asprintf(torture, "Failed to find UID %d", i)); } talloc_free(res); } if (talloc_total_blocks(torture) > 100) { unlink("./test.ldb"); talloc_free(tmp_ctx); torture_fail(torture, "memory leak in ldb search"); } ldb_speed = count/timeval_elapsed(&tv); torture_comment(torture, "ldb speed %.2f ops/sec\n", ldb_speed); torture_comment(torture, "ldb/tdb speed ratio is %.2f%%\n", (100*ldb_speed/tdb_speed)); unlink("./test.ldb"); talloc_free(tmp_ctx); return true; failed: unlink("./test.ldb"); talloc_free(tmp_ctx); return false; }
/** * Removes user by RDN through SAMR interface. * * @param domain_handle [in] Domain handle * @param user_rdn [in] User's RDN in ldap database */ bool test_user_cleanup(struct torture_context *tctx, struct dcerpc_binding_handle *b, TALLOC_CTX *mem_ctx, struct policy_handle *domain_handle, const char *user_rdn) { struct samr_LookupNames r1; struct samr_OpenUser r2; struct samr_DeleteUser r3; struct lsa_String names[2]; uint32_t rid; struct policy_handle user_handle; struct samr_Ids rids, types; const char *account_name; if (!_get_account_name_for_user_rdn(tctx, user_rdn, mem_ctx, &account_name)) { torture_result(tctx, TORTURE_FAIL, __location__": Failed to find samAccountName for %s", user_rdn); return false; } names[0].string = account_name; r1.in.domain_handle = domain_handle; r1.in.num_names = 1; r1.in.names = names; r1.out.rids = &rids; r1.out.types = &types; torture_comment(tctx, "user account lookup '%s'\n", account_name); torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupNames_r(b, mem_ctx, &r1), "LookupNames failed"); torture_assert_ntstatus_ok(tctx, r1.out.result, "LookupNames failed"); rid = r1.out.rids->ids[0]; r2.in.domain_handle = domain_handle; r2.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; r2.in.rid = rid; r2.out.user_handle = &user_handle; torture_comment(tctx, "opening user account\n"); torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, mem_ctx, &r2), "OpenUser failed"); torture_assert_ntstatus_ok(tctx, r2.out.result, "OpenUser failed"); r3.in.user_handle = &user_handle; r3.out.user_handle = &user_handle; torture_comment(tctx, "deleting user account\n"); torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, mem_ctx, &r3), "DeleteUser failed"); torture_assert_ntstatus_ok(tctx, r3.out.result, "DeleteUser failed"); return true; }
static bool test_fixed(struct torture_context *tctx, struct smb2_tree *tree) { TALLOC_CTX *mem_ctx = talloc_new(tctx); struct smb2_create create; struct smb2_handle h, h2; struct smb2_find f; union smb_search_data *d; struct file_elem files[NFILES] = {}; NTSTATUS status; bool ret = true; unsigned int count; int i; status = populate_tree(tctx, mem_ctx, tree, files, NFILES, &h); ZERO_STRUCT(create); create.in.desired_access = SEC_RIGHTS_DIR_ALL; create.in.create_options = NTCREATEX_OPTIONS_DIRECTORY; create.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY; create.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE; create.in.create_disposition = NTCREATEX_DISP_OPEN; create.in.fname = DNAME; status = smb2_create(tree, mem_ctx, &create); torture_assert_ntstatus_ok_goto(tctx, status, ret, done, ""); h2 = create.out.file.handle; ZERO_STRUCT(f); f.in.file.handle = h; f.in.pattern = "*"; f.in.continue_flags = SMB2_CONTINUE_FLAG_SINGLE; f.in.max_response_size = 0x100; f.in.level = SMB2_FIND_BOTH_DIRECTORY_INFO; /* Start enumeration on h, then delete all from h2 */ status = smb2_find_level(tree, tree, &f, &count, &d); torture_assert_ntstatus_ok_goto(tctx, status, ret, done, ""); f.in.file.handle = h2; do { status = smb2_find_level(tree, tree, &f, &count, &d); if (NT_STATUS_EQUAL(status, STATUS_NO_MORE_FILES)) break; torture_assert_ntstatus_ok_goto(tctx, status, ret, done, ""); for (i = 0; i < count; i++) { const char *found = d[i].both_directory_info.name.s; char *path = talloc_asprintf(mem_ctx, "%s\\%s", DNAME, found); if (!strcmp(found, ".") || !strcmp(found, "..")) continue; status = smb2_util_unlink(tree, path); torture_assert_ntstatus_ok_goto(tctx, status, ret, done, ""); talloc_free(path); } f.in.continue_flags = 0; f.in.max_response_size = 4096; } while (count != 0); /* Now finish h enumeration. */ f.in.file.handle = h; do { status = smb2_find_level(tree, tree, &f, &count, &d); if (NT_STATUS_EQUAL(status, STATUS_NO_MORE_FILES)) break; torture_assert_ntstatus_ok_goto(tctx, status, ret, done, ""); for (i = 0; i < count; i++) { const char *found = d[i].both_directory_info.name.s; if (!strcmp(found, ".") || !strcmp(found, "..")) continue; torture_result(tctx, TORTURE_FAIL, "(%s): didn't expect %s\n", __location__, found); ret = false; goto done; } f.in.continue_flags = 0; f.in.max_response_size = 4096; } while (count != 0); done: smb2_util_close(tree, h); smb2_util_close(tree, h2); smb2_deltree(tree, DNAME); talloc_free(mem_ctx); return ret; }
static bool test_find(struct torture_context *tctx, struct smb2_tree *tree) { TALLOC_CTX *mem_ctx = talloc_new(tctx); struct smb2_handle h; struct smb2_find f; union smb_search_data *d; struct file_elem files[NFILES] = {}; NTSTATUS status; bool ret = true; unsigned int count; int i, j, file_count = 0; status = populate_tree(tctx, mem_ctx, tree, files, NFILES, &h); ZERO_STRUCT(f); f.in.file.handle = h; f.in.pattern = "*"; f.in.continue_flags = SMB2_CONTINUE_FLAG_SINGLE; f.in.max_response_size = 0x100; f.in.level = SMB2_FIND_BOTH_DIRECTORY_INFO; do { status = smb2_find_level(tree, tree, &f, &count, &d); if (NT_STATUS_EQUAL(status, STATUS_NO_MORE_FILES)) break; torture_assert_ntstatus_ok_goto(tctx, status, ret, done, ""); for (i = 0; i < count; i++) { bool expected; const char *found = d[i].both_directory_info.name.s; if (!strcmp(found, ".") || !strcmp(found, "..")) continue; expected = false; for (j = 0; j < NFILES; j++) { if (!strcmp(files[j].name, found)) { files[j].found = true; expected = true; break; } } if (expected) continue; torture_result(tctx, TORTURE_FAIL, "(%s): didn't expect %s\n", __location__, found); ret = false; goto done; } file_count = file_count + i; f.in.continue_flags = 0; f.in.max_response_size = 4096; } while (count != 0); torture_assert_int_equal_goto(tctx, file_count, NFILES + 2, ret, done, ""); for (i = 0; i < NFILES; i++) { if (files[j].found) continue; torture_result(tctx, TORTURE_FAIL, "(%s): expected to find %s, but didn't\n", __location__, files[j].name); ret = false; goto done; } done: smb2_deltree(tree, DNAME); talloc_free(mem_ctx); return ret; }
/* basic testing of all SMB2 setinfo calls for each call we test that it succeeds, and where possible test for consistency between the calls. */ bool torture_smb2_setinfo(struct torture_context *tctx) { struct smb2_tree *tree; bool ret = true; struct smb2_handle handle; char *fname; union smb_fileinfo finfo2; union smb_setfileinfo sfinfo; struct security_ace ace; struct security_descriptor *sd; struct dom_sid *test_sid; NTSTATUS status, status2=NT_STATUS_OK; const char *call_name; time_t basetime = (time(NULL) - 86400) & ~1; int n = time(NULL) % 100; struct ea_struct ea; ZERO_STRUCT(handle); fname = talloc_asprintf(tctx, BASEDIR "fnum_test_%d.txt", n); if (!torture_smb2_connection(tctx, &tree)) { return false; } #define RECREATE_FILE(fname) do { \ smb2_util_close(tree, handle); \ status = smb2_create_complex_file(tree, fname, &handle); \ if (!NT_STATUS_IS_OK(status)) { \ torture_result(tctx, TORTURE_FAIL, "(%s) ERROR: open of %s failed (%s)\n", \ __location__, fname, nt_errstr(status)); \ ret = false; \ goto done; \ }} while (0) #define RECREATE_BOTH do { \ RECREATE_FILE(fname); \ } while (0) RECREATE_BOTH; #define CHECK_CALL(call, rightstatus) do { \ call_name = #call; \ sfinfo.generic.level = RAW_SFILEINFO_ ## call; \ sfinfo.generic.in.file.handle = handle; \ status = smb2_setinfo_file(tree, &sfinfo); \ if (!NT_STATUS_EQUAL(status, rightstatus)) { \ torture_result(tctx, TORTURE_FAIL, "(%s) %s - %s (should be %s)\n", __location__, #call, \ nt_errstr(status), nt_errstr(rightstatus)); \ ret = false; \ goto done; \ } \ } while (0) #define CHECK1(call) \ do { if (NT_STATUS_IS_OK(status)) { \ finfo2.generic.level = RAW_FILEINFO_ ## call; \ finfo2.generic.in.file.handle = handle; \ status2 = smb2_getinfo_file(tree, tctx, &finfo2); \ if (!NT_STATUS_IS_OK(status2)) { \ torture_result(tctx, TORTURE_FAIL, "(%s) %s - %s\n", __location__, #call, nt_errstr(status2)); \ ret = false; \ goto done; \ } \ }} while (0) #define CHECK_VALUE(call, stype, field, value) do { \ CHECK1(call); \ if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(status2) && finfo2.stype.out.field != value) { \ torture_result(tctx, TORTURE_FAIL, "(%s) %s - %s/%s should be 0x%x - 0x%x\n", __location__, \ call_name, #stype, #field, \ (unsigned int)value, (unsigned int)finfo2.stype.out.field); \ torture_smb2_all_info(tree, handle); \ ret = false; \ goto done; \ }} while (0) #define CHECK_TIME(call, stype, field, value) do { \ CHECK1(call); \ if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(status2) && nt_time_to_unix(finfo2.stype.out.field) != value) { \ torture_result(tctx, TORTURE_FAIL, "(%s) %s - %s/%s should be 0x%x - 0x%x\n", __location__, \ call_name, #stype, #field, \ (unsigned int)value, \ (unsigned int)nt_time_to_unix(finfo2.stype.out.field)); \ torture_warning(tctx, "\t%s", timestring(tctx, value)); \ torture_warning(tctx, "\t%s\n", nt_time_string(tctx, finfo2.stype.out.field)); \ torture_smb2_all_info(tree, handle); \ ret = false; \ goto done; \ }} while (0) #define CHECK_STATUS(status, correct) do { \ if (!NT_STATUS_EQUAL(status, correct)) { \ torture_result(tctx, TORTURE_FAIL, "(%s) Incorrect status %s - should be %s\n", \ __location__, nt_errstr(status), nt_errstr(correct)); \ ret = false; \ goto done; \ }} while (0) torture_smb2_all_info(tree, handle); torture_comment(tctx, "Test basic_information level\n"); basetime += 86400; unix_to_nt_time(&sfinfo.basic_info.in.create_time, basetime + 100); unix_to_nt_time(&sfinfo.basic_info.in.access_time, basetime + 200); unix_to_nt_time(&sfinfo.basic_info.in.write_time, basetime + 300); unix_to_nt_time(&sfinfo.basic_info.in.change_time, basetime + 400); sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_READONLY; CHECK_CALL(BASIC_INFORMATION, NT_STATUS_OK); CHECK_TIME(SMB2_ALL_INFORMATION, all_info2, create_time, basetime + 100); CHECK_TIME(SMB2_ALL_INFORMATION, all_info2, access_time, basetime + 200); CHECK_TIME(SMB2_ALL_INFORMATION, all_info2, write_time, basetime + 300); CHECK_TIME(SMB2_ALL_INFORMATION, all_info2, change_time, basetime + 400); CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, attrib, FILE_ATTRIBUTE_READONLY); torture_comment(tctx, "a zero time means don't change\n"); unix_to_nt_time(&sfinfo.basic_info.in.create_time, 0); unix_to_nt_time(&sfinfo.basic_info.in.access_time, 0); unix_to_nt_time(&sfinfo.basic_info.in.write_time, 0); unix_to_nt_time(&sfinfo.basic_info.in.change_time, 0); sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_NORMAL; CHECK_CALL(BASIC_INFORMATION, NT_STATUS_OK); CHECK_TIME(SMB2_ALL_INFORMATION, all_info2, create_time, basetime + 100); CHECK_TIME(SMB2_ALL_INFORMATION, all_info2, access_time, basetime + 200); CHECK_TIME(SMB2_ALL_INFORMATION, all_info2, write_time, basetime + 300); CHECK_TIME(SMB2_ALL_INFORMATION, all_info2, change_time, basetime + 400); CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, attrib, FILE_ATTRIBUTE_NORMAL); torture_comment(tctx, "change the attribute\n"); sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_HIDDEN; CHECK_CALL(BASIC_INFORMATION, NT_STATUS_OK); CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, attrib, FILE_ATTRIBUTE_HIDDEN); torture_comment(tctx, "zero attrib means don't change\n"); sfinfo.basic_info.in.attrib = 0; CHECK_CALL(BASIC_INFORMATION, NT_STATUS_OK); CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, attrib, FILE_ATTRIBUTE_HIDDEN); torture_comment(tctx, "can't change a file to a directory\n"); sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_DIRECTORY; CHECK_CALL(BASIC_INFORMATION, NT_STATUS_INVALID_PARAMETER); torture_comment(tctx, "restore attribute\n"); sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_NORMAL; CHECK_CALL(BASIC_INFORMATION, NT_STATUS_OK); CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, attrib, FILE_ATTRIBUTE_NORMAL); torture_comment(tctx, "Test disposition_information level\n"); sfinfo.disposition_info.in.delete_on_close = 1; CHECK_CALL(DISPOSITION_INFORMATION, NT_STATUS_OK); CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, delete_pending, 1); CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, nlink, 0); sfinfo.disposition_info.in.delete_on_close = 0; CHECK_CALL(DISPOSITION_INFORMATION, NT_STATUS_OK); CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, delete_pending, 0); CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, nlink, 1); torture_comment(tctx, "Test allocation_information level\n"); sfinfo.allocation_info.in.alloc_size = 0; CHECK_CALL(ALLOCATION_INFORMATION, NT_STATUS_OK); CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, size, 0); CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, alloc_size, 0); sfinfo.allocation_info.in.alloc_size = 4096; CHECK_CALL(ALLOCATION_INFORMATION, NT_STATUS_OK); CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, alloc_size, 4096); CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, size, 0); torture_comment(tctx, "Test end_of_file_info level\n"); sfinfo.end_of_file_info.in.size = 37; CHECK_CALL(END_OF_FILE_INFORMATION, NT_STATUS_OK); CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, size, 37); sfinfo.end_of_file_info.in.size = 7; CHECK_CALL(END_OF_FILE_INFORMATION, NT_STATUS_OK); CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, size, 7); torture_comment(tctx, "Test position_information level\n"); sfinfo.position_information.in.position = 123456; CHECK_CALL(POSITION_INFORMATION, NT_STATUS_OK); CHECK_VALUE(POSITION_INFORMATION, position_information, position, 123456); CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, position, 123456); torture_comment(tctx, "Test mode_information level\n"); sfinfo.mode_information.in.mode = 2; CHECK_CALL(MODE_INFORMATION, NT_STATUS_OK); CHECK_VALUE(MODE_INFORMATION, mode_information, mode, 2); CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, mode, 2); sfinfo.mode_information.in.mode = 1; CHECK_CALL(MODE_INFORMATION, NT_STATUS_INVALID_PARAMETER); sfinfo.mode_information.in.mode = 0; CHECK_CALL(MODE_INFORMATION, NT_STATUS_OK); CHECK_VALUE(MODE_INFORMATION, mode_information, mode, 0); torture_comment(tctx, "Test sec_desc level\n"); ZERO_STRUCT(finfo2); finfo2.query_secdesc.in.secinfo_flags = SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL; CHECK1(SEC_DESC); sd = finfo2.query_secdesc.out.sd; test_sid = dom_sid_parse_talloc(tctx, SID_NT_AUTHENTICATED_USERS); ZERO_STRUCT(ace); ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED; ace.flags = 0; ace.access_mask = SEC_STD_ALL; ace.trustee = *test_sid; status = security_descriptor_dacl_add(sd, &ace); CHECK_STATUS(status, NT_STATUS_OK); torture_comment(tctx, "add a new ACE to the DACL\n"); sfinfo.set_secdesc.in.secinfo_flags = finfo2.query_secdesc.in.secinfo_flags; sfinfo.set_secdesc.in.sd = sd; CHECK_CALL(SEC_DESC, NT_STATUS_OK); FAIL_UNLESS(smb2_util_verify_sd(tctx, tree, handle, sd)); torture_comment(tctx, "remove it again\n"); status = security_descriptor_dacl_del(sd, test_sid); CHECK_STATUS(status, NT_STATUS_OK); sfinfo.set_secdesc.in.secinfo_flags = finfo2.query_secdesc.in.secinfo_flags; sfinfo.set_secdesc.in.sd = sd; CHECK_CALL(SEC_DESC, NT_STATUS_OK); FAIL_UNLESS(smb2_util_verify_sd(tctx, tree, handle, sd)); torture_comment(tctx, "Check zero length EA's behavior\n"); /* Set a new EA. */ sfinfo.full_ea_information.in.eas.num_eas = 1; ea.flags = 0; ea.name.private_length = 6; ea.name.s = "NewEA"; ea.value = data_blob_string_const("testme"); sfinfo.full_ea_information.in.eas.eas = &ea; CHECK_CALL(FULL_EA_INFORMATION, NT_STATUS_OK); /* Does it still exist ? */ finfo2.generic.level = RAW_FILEINFO_SMB2_ALL_EAS; finfo2.generic.in.file.handle = handle; finfo2.all_eas.in.continue_flags = 1; status2 = smb2_getinfo_file(tree, tctx, &finfo2); if (!NT_STATUS_IS_OK(status2)) { torture_result(tctx, TORTURE_FAIL, "(%s) %s - %s\n", __location__, "SMB2_ALL_EAS", nt_errstr(status2)); ret = false; goto done; } /* Note on Windows EA name is returned capitalized. */ if (!find_returned_ea(&finfo2, "NewEA", "testme")) { torture_result(tctx, TORTURE_FAIL, "(%s) Missing EA 'NewEA'\n", __location__); ret = false; } /* Now zero it out (should delete it) */ sfinfo.full_ea_information.in.eas.num_eas = 1; ea.flags = 0; ea.name.private_length = 6; ea.name.s = "NewEA"; ea.value = data_blob_null; sfinfo.full_ea_information.in.eas.eas = &ea; CHECK_CALL(FULL_EA_INFORMATION, NT_STATUS_OK); /* Does it still exist ? */ finfo2.generic.level = RAW_FILEINFO_SMB2_ALL_EAS; finfo2.generic.in.file.handle = handle; finfo2.all_eas.in.continue_flags = 1; status2 = smb2_getinfo_file(tree, tctx, &finfo2); if (!NT_STATUS_IS_OK(status2)) { torture_result(tctx, TORTURE_FAIL, "(%s) %s - %s\n", __location__, "SMB2_ALL_EAS", nt_errstr(status2)); ret = false; goto done; } if (find_returned_ea(&finfo2, "NewEA", NULL)) { torture_result(tctx, TORTURE_FAIL, "(%s) EA 'NewEA' should be deleted\n", __location__); ret = false; } /* Set a zero length EA. */ sfinfo.full_ea_information.in.eas.num_eas = 1; ea.flags = 0; ea.name.private_length = 6; ea.name.s = "ZeroEA"; ea.value = data_blob_null; sfinfo.full_ea_information.in.eas.eas = &ea; CHECK_CALL(FULL_EA_INFORMATION, NT_STATUS_OK); /* Does it still exist ? */ finfo2.generic.level = RAW_FILEINFO_SMB2_ALL_EAS; finfo2.generic.in.file.handle = handle; finfo2.all_eas.in.continue_flags = 1; status2 = smb2_getinfo_file(tree, tctx, &finfo2); if (!NT_STATUS_IS_OK(status2)) { torture_result(tctx, TORTURE_FAIL, "(%s) %s - %s\n", __location__, "SMB2_ALL_EAS", nt_errstr(status2)); ret = false; goto done; } /* Over SMB2 ZeroEA should not exist. */ if (!find_returned_ea(&finfo2, "EAONE", "VALUE1")) { torture_result(tctx, TORTURE_FAIL, "(%s) Missing EA 'EAONE'\n", __location__); ret = false; } if (!find_returned_ea(&finfo2, "SECONDEA", "ValueTwo")) { torture_result(tctx, TORTURE_FAIL, "(%s) Missing EA 'SECONDEA'\n", __location__); ret = false; } if (find_returned_ea(&finfo2, "ZeroEA", NULL)) { torture_result(tctx, TORTURE_FAIL, "(%s) Found null EA 'ZeroEA'\n", __location__); ret = false; } done: status = smb2_util_close(tree, handle); if (NT_STATUS_IS_ERR(status)) { torture_warning(tctx, "Failed to delete %s - %s\n", fname, nt_errstr(status)); } smb2_util_unlink(tree, fname); return ret; }