static bool test_read_dir(struct torture_context *torture, struct smb2_tree *tree) { bool ret = true; NTSTATUS status; struct smb2_handle h; struct smb2_read rd; TALLOC_CTX *tmp_ctx = talloc_new(tree); status = torture_smb2_testdir(tree, DNAME, &h); if (!NT_STATUS_IS_OK(status)) { printf(__location__ " Unable to create test directory '%s' - %s\n", DNAME, nt_errstr(status)); return false; } ZERO_STRUCT(rd); rd.in.file.handle = h; rd.in.length = 10; rd.in.offset = 0; rd.in.min_count = 1; status = smb2_read(tree, tmp_ctx, &rd); CHECK_STATUS(status, NT_STATUS_INVALID_DEVICE_REQUEST); rd.in.min_count = 11; status = smb2_read(tree, tmp_ctx, &rd); CHECK_STATUS(status, NT_STATUS_INVALID_DEVICE_REQUEST); rd.in.length = 0; rd.in.min_count = 2592; status = smb2_read(tree, tmp_ctx, &rd); if (torture_setting_bool(torture, "windows", false)) { CHECK_STATUS(status, NT_STATUS_END_OF_FILE); } else { CHECK_STATUS(status, NT_STATUS_INVALID_DEVICE_REQUEST); } rd.in.length = 0; rd.in.min_count = 0; rd.in.channel = 0; status = smb2_read(tree, tmp_ctx, &rd); if (torture_setting_bool(torture, "windows", false)) { CHECK_STATUS(status, NT_STATUS_OK); } else { CHECK_STATUS(status, NT_STATUS_INVALID_DEVICE_REQUEST); } done: talloc_free(tmp_ctx); return ret; }
static bool test_read_position(struct torture_context *torture, struct smb2_tree *tree) { bool ret = true; NTSTATUS status; struct smb2_handle h; uint8_t buf[70000]; struct smb2_read rd; TALLOC_CTX *tmp_ctx = talloc_new(tree); union smb_fileinfo info; ZERO_STRUCT(buf); status = torture_smb2_testfile(tree, FNAME, &h); CHECK_STATUS(status, NT_STATUS_OK); status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf)); CHECK_STATUS(status, NT_STATUS_OK); ZERO_STRUCT(rd); rd.in.file.handle = h; rd.in.length = 10; rd.in.offset = 0; rd.in.min_count = 1; status = smb2_read(tree, tmp_ctx, &rd); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(rd.out.data.length, 10); info.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION; info.generic.in.file.handle = h; status = smb2_getinfo_file(tree, tmp_ctx, &info); CHECK_STATUS(status, NT_STATUS_OK); if (torture_setting_bool(torture, "windows", false)) { CHECK_VALUE(info.all_info2.out.position, 0); } else { CHECK_VALUE(info.all_info2.out.position, 10); } done: talloc_free(tmp_ctx); return ret; }
/* test writing */ static NTSTATUS torture_smb2_write(struct smb2_tree *tree, struct smb2_handle handle) { struct smb2_write w; struct smb2_read r; struct smb2_flush f; NTSTATUS status; DATA_BLOB data; int i; if (lp_parm_bool(-1, "torture", "dangerous", False)) { data = data_blob_talloc(tree, NULL, 160000); } else if (lp_parm_bool(-1, "torture", "samba4", False)) { data = data_blob_talloc(tree, NULL, UINT16_MAX); } else { data = data_blob_talloc(tree, NULL, 120000); } for (i=0;i<data.length;i++) { data.data[i] = i; } ZERO_STRUCT(w); w.in.file.handle = handle; w.in.offset = 0; w.in.data = data; status = smb2_write(tree, &w); if (!NT_STATUS_IS_OK(status)) { printf("write failed - %s\n", nt_errstr(status)); return status; } torture_smb2_all_info(tree, handle); status = smb2_write(tree, &w); if (!NT_STATUS_IS_OK(status)) { printf("write failed - %s\n", nt_errstr(status)); return status; } torture_smb2_all_info(tree, handle); ZERO_STRUCT(f); f.in.file.handle = handle; status = smb2_flush(tree, &f); if (!NT_STATUS_IS_OK(status)) { printf("flush failed - %s\n", nt_errstr(status)); return status; } ZERO_STRUCT(r); r.in.file.handle = handle; r.in.length = data.length; r.in.offset = 0; status = smb2_read(tree, tree, &r); if (!NT_STATUS_IS_OK(status)) { printf("read failed - %s\n", nt_errstr(status)); return status; } if (data.length != r.out.data.length || memcmp(data.data, r.out.data.data, data.length) != 0) { printf("read data mismatch\n"); return NT_STATUS_NET_WRITE_FAULT; } return status; }
/* test writing */ static NTSTATUS torture_smb2_write(TALLOC_CTX *mem_ctx, struct smb2_tree *tree, struct smb2_handle handle) { struct smb2_write w; struct smb2_read r; NTSTATUS status; int i, len; int max = 80000000; int min = 1; while (max > min) { TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); len = 1+(min+max)/2; ZERO_STRUCT(w); w.in.file.handle = handle; w.in.offset = 0; w.in.data = data_blob_talloc(tmp_ctx, NULL, len); for (i=0;i<len;i++) { w.in.data.data[i] = i % 256; } printf("trying to write %d bytes (min=%d max=%d)\n", len, min, max); status = smb2_write(tree, &w); if (!NT_STATUS_IS_OK(status)) { printf("write failed - %s\n", nt_errstr(status)); max = len-1; status = smb2_util_close(tree, handle); if (!NT_STATUS_IS_OK(status)) { /* vista bug */ printf("coping with server disconnect\n"); talloc_free(tree); if (!torture_smb2_connection(mem_ctx, &tree)) { printf("failed to reconnect\n"); return NT_STATUS_NET_WRITE_FAULT; } } handle = torture_smb2_create(tree, FNAME); continue; } else { min = len; } ZERO_STRUCT(r); r.in.file.handle = handle; r.in.length = len; r.in.offset = 0; printf("reading %d bytes\n", len); status = smb2_read(tree, tmp_ctx, &r); if (!NT_STATUS_IS_OK(status)) { printf("read failed - %s\n", nt_errstr(status)); } else if (w.in.data.length != r.out.data.length || memcmp(w.in.data.data, r.out.data.data, len) != 0) { printf("read data mismatch\n"); } talloc_free(tmp_ctx); } printf("converged: len=%d\n", max); smb2_util_close(tree, handle); smb2_util_unlink(tree, FNAME); return NT_STATUS_OK; }
static bool test_read_eof(struct torture_context *torture, struct smb2_tree *tree) { bool ret = true; NTSTATUS status; struct smb2_handle h; uint8_t buf[70000]; struct smb2_read rd; TALLOC_CTX *tmp_ctx = talloc_new(tree); ZERO_STRUCT(buf); smb2_util_unlink(tree, FNAME); status = torture_smb2_testfile(tree, FNAME, &h); CHECK_STATUS(status, NT_STATUS_OK); ZERO_STRUCT(rd); rd.in.file.handle = h; rd.in.length = 5; rd.in.offset = 0; status = smb2_read(tree, tree, &rd); CHECK_STATUS(status, NT_STATUS_END_OF_FILE); status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf)); CHECK_STATUS(status, NT_STATUS_OK); ZERO_STRUCT(rd); rd.in.file.handle = h; rd.in.length = 10; rd.in.offset = 0; rd.in.min_count = 1; status = smb2_read(tree, tmp_ctx, &rd); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(rd.out.data.length, 10); rd.in.min_count = 0; rd.in.length = 10; rd.in.offset = sizeof(buf); status = smb2_read(tree, tmp_ctx, &rd); CHECK_STATUS(status, NT_STATUS_END_OF_FILE); rd.in.min_count = 0; rd.in.length = 0; rd.in.offset = sizeof(buf); status = smb2_read(tree, tmp_ctx, &rd); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(rd.out.data.length, 0); rd.in.min_count = 1; rd.in.length = 0; rd.in.offset = sizeof(buf); status = smb2_read(tree, tmp_ctx, &rd); CHECK_STATUS(status, NT_STATUS_END_OF_FILE); rd.in.min_count = 0; rd.in.length = 2; rd.in.offset = sizeof(buf) - 1; status = smb2_read(tree, tmp_ctx, &rd); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(rd.out.data.length, 1); rd.in.min_count = 2; rd.in.length = 1; rd.in.offset = sizeof(buf) - 1; status = smb2_read(tree, tmp_ctx, &rd); CHECK_STATUS(status, NT_STATUS_END_OF_FILE); rd.in.min_count = 0x10000; rd.in.length = 1; rd.in.offset = 0; status = smb2_read(tree, tmp_ctx, &rd); CHECK_STATUS(status, NT_STATUS_END_OF_FILE); rd.in.min_count = 0x10000 - 2; rd.in.length = 1; rd.in.offset = 0; status = smb2_read(tree, tmp_ctx, &rd); CHECK_STATUS(status, NT_STATUS_END_OF_FILE); rd.in.min_count = 10; rd.in.length = 5; rd.in.offset = 0; status = smb2_read(tree, tmp_ctx, &rd); CHECK_STATUS(status, NT_STATUS_END_OF_FILE); done: talloc_free(tmp_ctx); return ret; }