s4-torture: Add tests for the smb2 copychunk ioctl
[Samba/gebeck_regimport.git] / source4 / torture / smb2 / ioctl.c
blob67dabe8737dc6bc60aac31bbb2419fdf78c817e8
1 /*
2 Unix SMB/CIFS implementation.
4 test suite for SMB2 ioctl operations
6 Copyright (C) David Disseldorp 2011
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "includes.h"
23 #include "librpc/gen_ndr/security.h"
24 #include "libcli/smb2/smb2.h"
25 #include "libcli/smb2/smb2_calls.h"
26 #include "torture/torture.h"
27 #include "torture/smb2/proto.h"
28 #include "librpc/gen_ndr/ndr_ioctl.h"
30 #define FNAME "testfsctl.dat"
31 #define FNAME2 "testfsctl2.dat"
34 basic testing of SMB2 shadow copy calls
36 static bool test_ioctl_get_shadow_copy(struct torture_context *torture,
37 struct smb2_tree *tree)
39 struct smb2_handle h;
40 uint8_t buf[100];
41 NTSTATUS status;
42 union smb_ioctl ioctl;
43 TALLOC_CTX *tmp_ctx = talloc_new(tree);
45 smb2_util_unlink(tree, FNAME);
47 status = torture_smb2_testfile(tree, FNAME, &h);
48 if (!NT_STATUS_IS_OK(status)) {
49 printf("create write\n");
50 return false;
53 ZERO_ARRAY(buf);
54 status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
55 if (!NT_STATUS_IS_OK(status)) {
56 printf("failed write\n");
57 return false;
60 ZERO_STRUCT(ioctl);
61 ioctl.smb2.level = RAW_IOCTL_SMB2;
62 ioctl.smb2.in.file.handle = h;
63 ioctl.smb2.in.function = FSCTL_SRV_ENUM_SNAPS;
64 ioctl.smb2.in.max_response_size = 16;
65 ioctl.smb2.in.flags = SMB2_IOCTL_FLAG_IS_FSCTL;
67 status = smb2_ioctl(tree, tmp_ctx, &ioctl.smb2);
68 if (!NT_STATUS_IS_OK(status)) {
69 printf("FSCTL_SRV_ENUM_SNAPS failed\n");
70 return false;
73 return true;
77 basic testing of the SMB2 server side copy ioctls
79 static bool test_ioctl_req_resume_key(struct torture_context *torture,
80 struct smb2_tree *tree)
82 struct smb2_handle h;
83 uint8_t buf[100];
84 NTSTATUS status;
85 union smb_ioctl ioctl;
86 TALLOC_CTX *tmp_ctx = talloc_new(tree);
87 struct req_resume_key_rsp res_key;
88 enum ndr_err_code ndr_ret;
90 smb2_util_unlink(tree, FNAME);
92 status = torture_smb2_testfile(tree, FNAME, &h);
93 if (!NT_STATUS_IS_OK(status)) {
94 printf("create write\n");
95 return false;
98 ZERO_ARRAY(buf);
99 status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
100 if (!NT_STATUS_IS_OK(status)) {
101 printf("failed write\n");
102 return false;
105 ZERO_STRUCT(ioctl);
106 ioctl.smb2.level = RAW_IOCTL_SMB2;
107 ioctl.smb2.in.file.handle = h;
108 ioctl.smb2.in.function = FSCTL_SRV_REQUEST_RESUME_KEY;
109 ioctl.smb2.in.max_response_size = 32;
110 ioctl.smb2.in.flags = SMB2_IOCTL_FLAG_IS_FSCTL;
112 status = smb2_ioctl(tree, tmp_ctx, &ioctl.smb2);
113 if (!NT_STATUS_IS_OK(status)) {
114 printf("FSCTL_SRV_REQUEST_RESUME_KEY failed\n");
115 return false;
118 ndr_ret = ndr_pull_struct_blob(&ioctl.smb2.out.out, tmp_ctx, &res_key,
119 (ndr_pull_flags_fn_t)ndr_pull_req_resume_key_rsp);
120 if (ndr_ret != NDR_ERR_SUCCESS) {
121 return false;
124 ndr_print_debug((ndr_print_fn_t)ndr_print_req_resume_key_rsp, "yo", &res_key);
126 talloc_free(tmp_ctx);
127 return true;
130 static bool test_ioctl_copy_chunk(struct torture_context *torture,
131 struct smb2_tree *tree)
133 struct smb2_handle h;
134 struct smb2_handle h2;
135 uint8_t buf[100];
136 NTSTATUS status;
137 union smb_ioctl ioctl;
138 TALLOC_CTX *tmp_ctx = talloc_new(tree);
139 struct req_resume_key_rsp res_key;
140 struct srv_copychunk chunk;
141 struct srv_copychunk_copy cc_copy;
142 struct srv_copychunk_rsp cc_rsp;
143 enum ndr_err_code ndr_ret;
145 smb2_util_unlink(tree, FNAME);
146 smb2_util_unlink(tree, FNAME2);
148 status = torture_smb2_testfile(tree, FNAME, &h);
149 if (!NT_STATUS_IS_OK(status)) {
150 printf("create write\n");
151 return false;
154 ZERO_ARRAY(buf);
155 status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
156 if (!NT_STATUS_IS_OK(status)) {
157 printf("failed write\n");
158 return false;
161 ZERO_STRUCT(ioctl);
162 ioctl.smb2.level = RAW_IOCTL_SMB2;
163 ioctl.smb2.in.file.handle = h;
164 ioctl.smb2.in.function = FSCTL_SRV_REQUEST_RESUME_KEY;
165 /* Allow for Key + ContextLength + Context */
166 ioctl.smb2.in.max_response_size = 32;
167 ioctl.smb2.in.flags = SMB2_IOCTL_FLAG_IS_FSCTL;
169 status = smb2_ioctl(tree, tmp_ctx, &ioctl.smb2);
170 if (!NT_STATUS_IS_OK(status)) {
171 printf("FSCTL_SRV_REQUEST_RESUME_KEY failed\n");
172 return false;
175 ndr_ret = ndr_pull_struct_blob(&ioctl.smb2.out.out, tmp_ctx, &res_key,
176 (ndr_pull_flags_fn_t)ndr_pull_req_resume_key_rsp);
177 if (ndr_ret != NDR_ERR_SUCCESS) {
178 return false;
181 status = torture_smb2_testfile(tree, FNAME2, &h2);
182 if (!NT_STATUS_IS_OK(status)) {
183 printf("create write\n");
184 return false;
187 ZERO_STRUCT(ioctl);
188 ioctl.smb2.level = RAW_IOCTL_SMB2;
189 ioctl.smb2.in.file.handle = h2;
190 ioctl.smb2.in.function = FSCTL_SRV_COPYCHUNK;
191 ioctl.smb2.in.max_response_size = 12; /* FIXME */
192 ioctl.smb2.in.flags = SMB2_IOCTL_FLAG_IS_FSCTL;
194 ZERO_STRUCT(chunk);
195 chunk.source_off = 0;
196 chunk.target_off = 0;
197 chunk.length = 100;
199 ZERO_STRUCT(cc_copy);
200 memcpy(cc_copy.source_key, res_key.resume_key, ARRAY_SIZE(cc_copy.source_key));
201 cc_copy.chunk_count = 1;
202 cc_copy.chunks = &chunk;
204 ndr_ret = ndr_push_struct_blob(&ioctl.smb2.in.out, tmp_ctx,
205 &cc_copy,
206 (ndr_push_flags_fn_t)ndr_push_srv_copychunk_copy);
207 if (ndr_ret != NDR_ERR_SUCCESS) {
208 return false;
211 /* request a copy of all src file data (via a single chunk desc) */
212 status = smb2_ioctl(tree, tmp_ctx, &ioctl.smb2);
213 if (!NT_STATUS_IS_OK(status)) {
214 printf("FSCTL_SRV_COPYCHUNK failed\n");
215 return false;
218 ndr_ret = ndr_pull_struct_blob(&ioctl.smb2.out.out, tmp_ctx,
219 &cc_rsp,
220 (ndr_pull_flags_fn_t)ndr_pull_srv_copychunk_rsp);
221 if (ndr_ret != NDR_ERR_SUCCESS) {
222 return false;
224 if (cc_rsp.chunks_written != 1) {
225 printf("fail, expected 1 chunk, got %u\n", cc_rsp.chunks_written);
226 return false;
228 if (cc_rsp.chunk_bytes_written != 0) {
229 printf("fail, expected 0 chunk bytes remaining, got %u\n",
230 cc_rsp.chunk_bytes_written);
231 return false;
233 if (cc_rsp.total_bytes_written != 100) {
234 printf("fail, expected 100 total bytes, got %u\n",
235 cc_rsp.total_bytes_written);
236 return false;
239 talloc_free(tmp_ctx);
240 return true;
244 basic testing of SMB2 ioctls
246 struct torture_suite *torture_smb2_ioctl_init(void)
248 struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "ioctl");
250 torture_suite_add_1smb2_test(suite, "shadow_copy", test_ioctl_get_shadow_copy);
251 torture_suite_add_1smb2_test(suite, "req_resume_key", test_ioctl_req_resume_key);
252 torture_suite_add_1smb2_test(suite, "copy_chunk", test_ioctl_copy_chunk);
254 suite->description = talloc_strdup(suite, "SMB2-IOCTL tests");
256 return suite;