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/>.
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
)
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");
54 status
= smb2_util_write(tree
, h
, buf
, 0, ARRAY_SIZE(buf
));
55 if (!NT_STATUS_IS_OK(status
)) {
56 printf("failed write\n");
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");
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
)
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");
99 status
= smb2_util_write(tree
, h
, buf
, 0, ARRAY_SIZE(buf
));
100 if (!NT_STATUS_IS_OK(status
)) {
101 printf("failed write\n");
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");
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
) {
124 ndr_print_debug((ndr_print_fn_t
)ndr_print_req_resume_key_rsp
, "yo", &res_key
);
126 talloc_free(tmp_ctx
);
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
;
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");
155 status
= smb2_util_write(tree
, h
, buf
, 0, ARRAY_SIZE(buf
));
156 if (!NT_STATUS_IS_OK(status
)) {
157 printf("failed write\n");
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");
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
) {
181 status
= torture_smb2_testfile(tree
, FNAME2
, &h2
);
182 if (!NT_STATUS_IS_OK(status
)) {
183 printf("create write\n");
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
;
195 chunk
.source_off
= 0;
196 chunk
.target_off
= 0;
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
,
206 (ndr_push_flags_fn_t
)ndr_push_srv_copychunk_copy
);
207 if (ndr_ret
!= NDR_ERR_SUCCESS
) {
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");
218 ndr_ret
= ndr_pull_struct_blob(&ioctl
.smb2
.out
.out
, tmp_ctx
,
220 (ndr_pull_flags_fn_t
)ndr_pull_srv_copychunk_rsp
);
221 if (ndr_ret
!= NDR_ERR_SUCCESS
) {
224 if (cc_rsp
.chunks_written
!= 1) {
225 printf("fail, expected 1 chunk, got %u\n", cc_rsp
.chunks_written
);
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
);
233 if (cc_rsp
.total_bytes_written
!= 100) {
234 printf("fail, expected 100 total bytes, got %u\n",
235 cc_rsp
.total_bytes_written
);
239 talloc_free(tmp_ctx
);
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");