2 Unix SMB/CIFS implementation.
4 test suite for File Server Remote VSS Protocol operations
6 Copyright (C) David Disseldorp 2012-2013
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 * Windows Server "8" Beta is very picky in how it accepts FSRVP requests, the
24 * client must be a member of the same AD domain, ndr64 and signing must be
25 * negotiated for the DCE/RPC bind. E.g.
27 * smbtorture ncacn_np:LUTZE[/pipe/FssagentRpc,smb2,ndr64,sign] \
28 * -U 'DOM\user%pw' rpc.fsrvp
30 * This test suite requires a snapshotable share named FSHARE (see #def below).
33 #include "librpc/gen_ndr/security.h"
34 #include "lib/param/param.h"
35 #include "libcli/smb2/smb2.h"
36 #include "libcli/smb2/smb2_calls.h"
37 #include "libcli/smb_composite/smb_composite.h"
38 #include "libcli/resolve/resolve.h"
39 #include "torture/torture.h"
40 #include "torture/smb2/proto.h"
41 #include "torture/rpc/torture_rpc.h"
42 #include "librpc/gen_ndr/ndr_fsrvp.h"
43 #include "librpc/gen_ndr/ndr_fsrvp_c.h"
45 #define FSHARE "fsrvp_share"
46 #define FNAME "testfss.dat"
48 uint8_t fsrvp_magic
[] = {0x8a, 0xe3, 0x13, 0x71, 0x02, 0xf4, 0x36, 0x71,
49 0x02, 0x40, 0x28, 0x00, 0x3c, 0x65, 0xe0, 0xa8,
50 0x44, 0x27, 0x89, 0x43, 0xa6, 0x1d, 0x73, 0x73,
51 0xdf, 0x8b, 0x22, 0x92, 0x01, 0x00, 0x00, 0x00,
52 0x33, 0x05, 0x71, 0x71, 0xba, 0xbe, 0x37, 0x49,
53 0x83, 0x19, 0xb5, 0xdb, 0xef, 0x9c, 0xcc, 0x36,
54 0x01, 0x00, 0x00, 0x00};
56 static bool test_fsrvp_is_path_supported(struct torture_context
*tctx
,
57 struct dcerpc_pipe
*p
)
59 struct fss_IsPathSupported r
;
60 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
64 r
.in
.ShareName
= talloc_asprintf(tctx
,"\\\\%s\\%s",
65 dcerpc_server_name(p
),
67 /* win8 beta sends this */
68 memcpy(r
.in
.magic
, fsrvp_magic
, sizeof(fsrvp_magic
));
69 status
= dcerpc_fss_IsPathSupported_r(b
, tctx
, &r
);
70 torture_assert_ntstatus_ok(tctx
, status
,
71 "IsPathSupported failed");
74 r
.in
.ShareName
= talloc_asprintf(tctx
,"\\\\%s\\%s",
75 dcerpc_server_name(p
),
77 /* also works without magic */
78 status
= dcerpc_fss_IsPathSupported_r(b
, tctx
, &r
);
79 torture_assert_ntstatus_ok(tctx
, status
,
80 "IsPathSupported failed");
82 torture_assert(tctx
, *r
.out
.SupportedByThisProvider
,
83 "path not supported");
85 torture_comment(tctx
, "path %s is supported by fsrvp server %s\n",
86 r
.in
.ShareName
, *r
.out
.OwnerMachineName
);
91 static bool test_fsrvp_get_version(struct torture_context
*tctx
,
92 struct dcerpc_pipe
*p
)
94 struct fss_GetSupportedVersion r
;
95 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
99 /* win8 beta sends this */
100 memcpy(r
.in
.magic
, fsrvp_magic
, sizeof(fsrvp_magic
));
101 status
= dcerpc_fss_GetSupportedVersion_r(b
, tctx
, &r
);
102 torture_assert_ntstatus_ok(tctx
, status
,
103 "GetSupportedVersion failed with magic");
106 /* also works without magic */
107 status
= dcerpc_fss_GetSupportedVersion_r(b
, tctx
, &r
);
108 torture_assert_ntstatus_ok(tctx
, status
,
109 "GetSupportedVersion failed without magic");
111 torture_comment(tctx
, "got MinVersion %u\n", *r
.out
.MinVersion
);
112 torture_comment(tctx
, "got MaxVersion %u\n", *r
.out
.MaxVersion
);
117 static bool test_fsrvp_set_ctx(struct torture_context
*tctx
,
118 struct dcerpc_pipe
*p
)
120 struct fss_SetContext r
;
121 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
125 r
.in
.Context
= FSRVP_CTX_BACKUP
;
126 status
= dcerpc_fss_SetContext_r(b
, tctx
, &r
);
127 torture_assert_ntstatus_ok(tctx
, status
, "SetContext failed");
132 static bool test_fsrvp_sc_create(struct torture_context
*tctx
,
133 struct dcerpc_pipe
*p
,
135 struct fssagent_share_mapping_1
**sc_map
)
137 struct fss_IsPathSupported r_pathsupport_get
;
138 struct fss_GetSupportedVersion r_version_get
;
139 struct fss_SetContext r_context_set
;
140 struct fss_StartShadowCopySet r_scset_start
;
141 struct fss_AddToShadowCopySet r_scset_add1
;
142 struct fss_AddToShadowCopySet r_scset_add2
;
143 struct fss_PrepareShadowCopySet r_scset_prep
;
144 struct fss_CommitShadowCopySet r_scset_commit
;
145 struct fss_ExposeShadowCopySet r_scset_expose
;
146 struct fss_GetShareMapping r_sharemap_get
;
147 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
150 TALLOC_CTX
*tmp_ctx
= talloc_new(tctx
);
151 struct fssagent_share_mapping_1
*map
;
154 * PrepareShadowCopySet & CommitShadowCopySet often exceed the default
155 * 60 second dcerpc request timeout against Windows Server "8" Beta.
157 dcerpc_binding_handle_set_timeout(b
, 240);
159 ZERO_STRUCT(r_pathsupport_get
); /* sending with zeroed magic */
160 r_pathsupport_get
.in
.ShareName
= share
;
161 status
= dcerpc_fss_IsPathSupported_r(b
, tmp_ctx
, &r_pathsupport_get
);
162 torture_assert_ntstatus_ok(tctx
, status
,
163 "IsPathSupported failed");
164 torture_assert_int_equal(tctx
, r_pathsupport_get
.out
.result
, 0,
165 "failed IsPathSupported response");
166 torture_assert(tctx
, r_pathsupport_get
.out
.SupportedByThisProvider
,
167 "path not supported");
169 ZERO_STRUCT(r_version_get
); /* sending with zeroed magic */
170 status
= dcerpc_fss_GetSupportedVersion_r(b
, tmp_ctx
, &r_version_get
);
171 torture_assert_ntstatus_ok(tctx
, status
,
172 "GetSupportedVersion failed without magic");
173 torture_assert_int_equal(tctx
, r_version_get
.out
.result
, 0,
174 "failed GetSupportedVersion response");
176 ZERO_STRUCT(r_context_set
);
177 r_context_set
.in
.Context
= FSRVP_CTX_BACKUP
;
178 status
= dcerpc_fss_SetContext_r(b
, tmp_ctx
, &r_context_set
);
179 torture_assert_ntstatus_ok(tctx
, status
, "SetContext failed");
180 torture_assert_int_equal(tctx
, r_context_set
.out
.result
, 0,
181 "failed SetContext response");
183 ZERO_STRUCT(r_scset_start
);
184 r_scset_start
.in
.ClientShadowCopySetId
= GUID_random();
185 status
= dcerpc_fss_StartShadowCopySet_r(b
, tmp_ctx
, &r_scset_start
);
186 torture_assert_ntstatus_ok(tctx
, status
,
187 "StartShadowCopySet failed");
188 torture_assert_int_equal(tctx
, r_scset_start
.out
.result
, 0,
189 "failed StartShadowCopySet response");
190 torture_comment(tctx
, "%s: shadow-copy set created\n",
191 GUID_string(tmp_ctx
, r_scset_start
.out
.pShadowCopySetId
));
193 ZERO_STRUCT(r_scset_add1
);
194 r_scset_add1
.in
.ClientShadowCopyId
= GUID_random();
195 r_scset_add1
.in
.ShadowCopySetId
= *r_scset_start
.out
.pShadowCopySetId
;
196 r_scset_add1
.in
.ShareName
= share
;
197 status
= dcerpc_fss_AddToShadowCopySet_r(b
, tmp_ctx
, &r_scset_add1
);
198 torture_assert_ntstatus_ok(tctx
, status
,
199 "AddToShadowCopySet failed");
200 torture_assert_int_equal(tctx
, r_scset_add1
.out
.result
, 0,
201 "failed AddToShadowCopySet response");
202 torture_comment(tctx
, "%s(%s): %s added to shadow-copy set\n",
203 GUID_string(tmp_ctx
, r_scset_start
.out
.pShadowCopySetId
),
204 GUID_string(tmp_ctx
, r_scset_add1
.out
.pShadowCopyId
),
205 r_scset_add1
.in
.ShareName
);
207 /* attempts to add the same share twice should fail */
208 ZERO_STRUCT(r_scset_add2
);
209 r_scset_add2
.in
.ClientShadowCopyId
= GUID_random();
210 r_scset_add2
.in
.ShadowCopySetId
= *r_scset_start
.out
.pShadowCopySetId
;
211 r_scset_add2
.in
.ShareName
= share
;
212 status
= dcerpc_fss_AddToShadowCopySet_r(b
, tmp_ctx
, &r_scset_add2
);
213 torture_assert_ntstatus_ok(tctx
, status
,
214 "AddToShadowCopySet failed");
215 torture_assert_int_equal(tctx
, r_scset_add2
.out
.result
,
216 FSRVP_E_OBJECT_ALREADY_EXISTS
,
217 "failed AddToShadowCopySet response");
219 start_time
= time_mono(NULL
);
220 ZERO_STRUCT(r_scset_prep
);
221 r_scset_prep
.in
.ShadowCopySetId
= *r_scset_start
.out
.pShadowCopySetId
;
222 // r_scset_prep.in.TimeOutInMilliseconds = (1800 * 1000); /* win8 */
223 r_scset_prep
.in
.TimeOutInMilliseconds
= (240 * 1000);
224 status
= dcerpc_fss_PrepareShadowCopySet_r(b
, tmp_ctx
, &r_scset_prep
);
225 torture_assert_ntstatus_ok(tctx
, status
,
226 "PrepareShadowCopySet failed");
227 torture_assert_int_equal(tctx
, r_scset_prep
.out
.result
, 0,
228 "failed PrepareShadowCopySet response");
229 torture_comment(tctx
, "%s: prepare completed in %llu secs\n",
230 GUID_string(tmp_ctx
, r_scset_start
.out
.pShadowCopySetId
),
231 (unsigned long long)(time_mono(NULL
) - start_time
));
233 start_time
= time_mono(NULL
);
234 ZERO_STRUCT(r_scset_commit
);
235 r_scset_commit
.in
.ShadowCopySetId
= *r_scset_start
.out
.pShadowCopySetId
;
236 r_scset_commit
.in
.TimeOutInMilliseconds
= (180 * 1000); /* win8 */
237 status
= dcerpc_fss_CommitShadowCopySet_r(b
, tmp_ctx
, &r_scset_commit
);
238 torture_assert_ntstatus_ok(tctx
, status
,
239 "CommitShadowCopySet failed");
240 torture_assert_int_equal(tctx
, r_scset_commit
.out
.result
, 0,
241 "failed CommitShadowCopySet response");
242 torture_comment(tctx
, "%s: commit completed in %llu secs\n",
243 GUID_string(tmp_ctx
, r_scset_start
.out
.pShadowCopySetId
),
244 (unsigned long long)(time_mono(NULL
) - start_time
));
246 start_time
= time_mono(NULL
);
247 ZERO_STRUCT(r_scset_expose
);
248 r_scset_expose
.in
.ShadowCopySetId
= *r_scset_start
.out
.pShadowCopySetId
;
249 r_scset_expose
.in
.TimeOutInMilliseconds
= (120 * 1000); /* win8 */
250 status
= dcerpc_fss_ExposeShadowCopySet_r(b
, tmp_ctx
, &r_scset_expose
);
251 torture_assert_ntstatus_ok(tctx
, status
,
252 "ExposeShadowCopySet failed");
253 torture_assert_int_equal(tctx
, r_scset_expose
.out
.result
, 0,
254 "failed ExposeShadowCopySet response");
255 torture_comment(tctx
, "%s: expose completed in %llu secs\n",
256 GUID_string(tmp_ctx
, r_scset_start
.out
.pShadowCopySetId
),
257 (unsigned long long)(time_mono(NULL
) - start_time
));
259 ZERO_STRUCT(r_sharemap_get
);
260 r_sharemap_get
.in
.ShadowCopyId
= *r_scset_add1
.out
.pShadowCopyId
;
261 r_sharemap_get
.in
.ShadowCopySetId
= *r_scset_start
.out
.pShadowCopySetId
;
262 r_sharemap_get
.in
.ShareName
= r_scset_add1
.in
.ShareName
;
263 r_sharemap_get
.in
.Level
= 1;
264 status
= dcerpc_fss_GetShareMapping_r(b
, tmp_ctx
, &r_sharemap_get
);
265 torture_assert_ntstatus_ok(tctx
, status
, "GetShareMapping failed");
266 torture_assert_int_equal(tctx
, r_sharemap_get
.out
.result
, 0,
267 "failed GetShareMapping response");
268 torture_comment(tctx
, "%s(%s): %s is a snapshot of %s at %s\n",
269 GUID_string(tmp_ctx
, &r_sharemap_get
.out
.ShareMapping
->ShareMapping1
->ShadowCopySetId
),
270 GUID_string(tmp_ctx
, &r_sharemap_get
.out
.ShareMapping
->ShareMapping1
->ShadowCopyId
),
271 r_sharemap_get
.out
.ShareMapping
->ShareMapping1
->ShadowCopyShareName
,
272 r_sharemap_get
.out
.ShareMapping
->ShareMapping1
->ShareNameUNC
,
273 nt_time_string(tmp_ctx
, r_sharemap_get
.out
.ShareMapping
->ShareMapping1
->tstamp
));
275 map
= talloc_zero(tctx
, struct fssagent_share_mapping_1
);
276 map
->ShadowCopySetId
= r_sharemap_get
.out
.ShareMapping
->ShareMapping1
->ShadowCopySetId
;
277 map
->ShadowCopyId
= r_sharemap_get
.out
.ShareMapping
->ShareMapping1
->ShadowCopyId
;
278 map
->ShadowCopyShareName
279 = talloc_strdup(tctx
, r_sharemap_get
.out
.ShareMapping
->ShareMapping1
->ShadowCopyShareName
);
281 = talloc_strdup(tctx
, r_sharemap_get
.out
.ShareMapping
->ShareMapping1
->ShareNameUNC
);
282 map
->tstamp
= r_sharemap_get
.out
.ShareMapping
->ShareMapping1
->tstamp
;
284 torture_assert(tctx
, !GUID_compare(&r_sharemap_get
.in
.ShadowCopySetId
,
285 &map
->ShadowCopySetId
),
286 "sc_set GUID missmatch in GetShareMapping");
287 torture_assert(tctx
, !GUID_compare(&r_sharemap_get
.in
.ShadowCopyId
,
289 "sc GUID missmatch in GetShareMapping");
291 talloc_free(tmp_ctx
);
297 static bool test_fsrvp_sc_delete(struct torture_context
*tctx
,
298 struct dcerpc_pipe
*p
,
299 struct fssagent_share_mapping_1
*sc_map
)
301 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
302 struct fss_DeleteShareMapping r_sharemap_del
;
305 ZERO_STRUCT(r_sharemap_del
);
306 r_sharemap_del
.in
.ShadowCopySetId
= sc_map
->ShadowCopySetId
;
307 r_sharemap_del
.in
.ShadowCopyId
= sc_map
->ShadowCopyId
;
308 r_sharemap_del
.in
.ShareName
= sc_map
->ShareNameUNC
;
309 status
= dcerpc_fss_DeleteShareMapping_r(b
, tctx
, &r_sharemap_del
);
310 torture_assert_ntstatus_ok(tctx
, status
, "DeleteShareMapping failed");
311 torture_assert_int_equal(tctx
, r_sharemap_del
.out
.result
, 0,
312 "failed DeleteShareMapping response");
317 static bool test_fsrvp_sc_create_simple(struct torture_context
*tctx
,
318 struct dcerpc_pipe
*p
)
320 struct fssagent_share_mapping_1
*sc_map
;
321 char *share_unc
= talloc_asprintf(tctx
, "\\\\%s\\%s",
322 dcerpc_server_name(p
), FSHARE
);
324 torture_assert(tctx
, test_fsrvp_sc_create(tctx
, p
, share_unc
, &sc_map
),
327 torture_assert(tctx
, test_fsrvp_sc_delete(tctx
, p
, sc_map
), "sc del");
332 static bool test_fsrvp_sc_set_abort(struct torture_context
*tctx
,
333 struct dcerpc_pipe
*p
)
335 char *share_unc
= talloc_asprintf(tctx
, "\\\\%s\\%s",
336 dcerpc_server_name(p
), FSHARE
);
337 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
338 struct fss_IsPathSupported r_pathsupport_get
;
339 struct fss_GetSupportedVersion r_version_get
;
340 struct fss_SetContext r_context_set
;
341 struct fss_StartShadowCopySet r_scset_start
;
342 struct fss_AbortShadowCopySet r_scset_abort
;
343 struct fss_AddToShadowCopySet r_scset_add
;
345 TALLOC_CTX
*tmp_ctx
= talloc_new(tctx
);
347 ZERO_STRUCT(r_pathsupport_get
); /* sending with zeroed magic */
348 r_pathsupport_get
.in
.ShareName
= share_unc
;
349 status
= dcerpc_fss_IsPathSupported_r(b
, tmp_ctx
, &r_pathsupport_get
);
350 torture_assert_ntstatus_ok(tctx
, status
,
351 "IsPathSupported failed");
352 torture_assert(tctx
, r_pathsupport_get
.out
.SupportedByThisProvider
,
353 "path not supported");
355 ZERO_STRUCT(r_version_get
); /* sending with zeroed magic */
356 status
= dcerpc_fss_GetSupportedVersion_r(b
, tmp_ctx
, &r_version_get
);
357 torture_assert_ntstatus_ok(tctx
, status
,
358 "GetSupportedVersion failed without magic");
360 ZERO_STRUCT(r_context_set
);
361 r_context_set
.in
.Context
= FSRVP_CTX_BACKUP
;
362 status
= dcerpc_fss_SetContext_r(b
, tmp_ctx
, &r_context_set
);
363 torture_assert_ntstatus_ok(tctx
, status
, "SetContext failed");
365 ZERO_STRUCT(r_scset_start
);
366 r_scset_start
.in
.ClientShadowCopySetId
= GUID_random();
367 status
= dcerpc_fss_StartShadowCopySet_r(b
, tmp_ctx
, &r_scset_start
);
368 torture_assert_ntstatus_ok(tctx
, status
,
369 "StartShadowCopySet failed");
371 ZERO_STRUCT(r_scset_abort
);
372 r_scset_abort
.in
.ShadowCopySetId
= *r_scset_start
.out
.pShadowCopySetId
;
373 status
= dcerpc_fss_AbortShadowCopySet_r(b
, tmp_ctx
, &r_scset_abort
);
374 torture_assert_ntstatus_ok(tctx
, status
,
375 "AbortShadowCopySet failed");
377 ZERO_STRUCT(r_scset_add
);
378 r_scset_add
.in
.ClientShadowCopyId
= GUID_random();
379 r_scset_add
.in
.ShadowCopySetId
= *r_scset_start
.out
.pShadowCopySetId
;
380 r_scset_add
.in
.ShareName
= share_unc
;
381 status
= dcerpc_fss_AddToShadowCopySet_r(b
, tmp_ctx
, &r_scset_add
);
382 torture_assert_ntstatus_ok(tctx
, status
, "AddToShadowCopySet failed "
385 * XXX Windows 8 server beta returns FSRVP_E_BAD_STATE here rather than
386 * FSRVP_E_BAD_ID / E_INVALIDARG.
388 torture_assert(tctx
, (r_scset_add
.out
.result
!= 0),
389 "incorrect AddToShadowCopySet response following abort");
391 talloc_free(tmp_ctx
);
395 static bool test_fsrvp_bad_id(struct torture_context
*tctx
,
396 struct dcerpc_pipe
*p
)
398 struct fssagent_share_mapping_1
*sc_map
;
399 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
400 struct fss_DeleteShareMapping r_sharemap_del
;
402 TALLOC_CTX
*tmp_ctx
= talloc_new(tctx
);
403 char *share_unc
= talloc_asprintf(tmp_ctx
, "\\\\%s\\%s",
404 dcerpc_server_name(p
), FSHARE
);
406 torture_assert(tctx
, test_fsrvp_sc_create(tctx
, p
, share_unc
, &sc_map
),
409 ZERO_STRUCT(r_sharemap_del
);
410 r_sharemap_del
.in
.ShadowCopySetId
= sc_map
->ShadowCopySetId
;
411 r_sharemap_del
.in
.ShadowCopySetId
.time_low
++; /* bogus */
412 r_sharemap_del
.in
.ShadowCopyId
= sc_map
->ShadowCopyId
;
413 r_sharemap_del
.in
.ShareName
= sc_map
->ShareNameUNC
;
414 status
= dcerpc_fss_DeleteShareMapping_r(b
, tmp_ctx
, &r_sharemap_del
);
415 torture_assert_ntstatus_ok(tctx
, status
,
416 "DeleteShareMapping failed");
417 torture_assert_int_equal(tctx
, r_sharemap_del
.out
.result
,
418 FSRVP_E_OBJECT_NOT_FOUND
,
419 "incorrect DeleteShareMapping response");
421 r_sharemap_del
.in
.ShadowCopySetId
= sc_map
->ShadowCopySetId
;
422 r_sharemap_del
.in
.ShadowCopyId
.time_mid
++; /* bogus */
423 status
= dcerpc_fss_DeleteShareMapping_r(b
, tmp_ctx
, &r_sharemap_del
);
424 torture_assert_ntstatus_ok(tctx
, status
,
425 "DeleteShareMapping failed");
426 torture_assert_int_equal(tctx
, r_sharemap_del
.out
.result
,
428 "incorrect DeleteShareMapping response");
430 torture_assert(tctx
, test_fsrvp_sc_delete(tctx
, p
, sc_map
), "sc del");
433 talloc_free(tmp_ctx
);
438 static bool test_fsrvp_sc_share_io(struct torture_context
*tctx
,
439 struct dcerpc_pipe
*p
)
441 struct fssagent_share_mapping_1
*sc_map
;
443 TALLOC_CTX
*tmp_ctx
= talloc_new(tctx
);
444 char *share_unc
= talloc_asprintf(tmp_ctx
, "\\\\%s\\%s",
445 dcerpc_server_name(p
), FSHARE
);
446 extern struct cli_credentials
*cmdline_credentials
;
447 struct smb2_tree
*tree_base
;
448 struct smb2_tree
*tree_snap
;
449 struct smbcli_options options
;
450 struct smb2_handle base_fh
;
452 struct smb2_create io
;
453 lpcfg_smbcli_options(tctx
->lp_ctx
, &options
);
455 status
= smb2_connect(tmp_ctx
,
456 dcerpc_server_name(p
),
457 lpcfg_smb_ports(tctx
->lp_ctx
),
459 lpcfg_resolve_context(tctx
->lp_ctx
),
464 lpcfg_socket_options(tctx
->lp_ctx
),
465 lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
));
466 torture_assert_ntstatus_ok(tctx
, status
,
467 "Failed to connect to SMB2 share");
469 smb2_util_unlink(tree_base
, FNAME
);
470 status
= torture_smb2_testfile(tree_base
, FNAME
, &base_fh
);
471 torture_assert_ntstatus_ok(tctx
, status
, "base write open");
473 status
= smb2_util_write(tree_base
, base_fh
, "pre-snap", 0,
475 torture_assert_ntstatus_ok(tctx
, status
, "src write");
478 torture_assert(tctx
, test_fsrvp_sc_create(tctx
, p
, share_unc
, &sc_map
),
481 status
= smb2_util_write(tree_base
, base_fh
, "post-snap", 0,
482 sizeof("post-snap"));
483 torture_assert_ntstatus_ok(tctx
, status
, "base write");
485 /* connect to snapshot share and verify pre-snapshot data */
486 status
= smb2_connect(tmp_ctx
,
487 dcerpc_server_name(p
),
488 lpcfg_smb_ports(tctx
->lp_ctx
),
489 sc_map
->ShadowCopyShareName
,
490 lpcfg_resolve_context(tctx
->lp_ctx
),
495 lpcfg_socket_options(tctx
->lp_ctx
),
496 lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
));
497 torture_assert_ntstatus_ok(tctx
, status
,
498 "Failed to connect to SMB2 shadow-copy share");
499 /* Windows server 8 allows RW open to succeed here for a ro snapshot */
501 io
.in
.desired_access
= SEC_RIGHTS_FILE_READ
;
502 io
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
503 io
.in
.create_disposition
= NTCREATEX_DISP_OPEN_IF
;
505 NTCREATEX_SHARE_ACCESS_DELETE
|
506 NTCREATEX_SHARE_ACCESS_READ
|
507 NTCREATEX_SHARE_ACCESS_WRITE
;
508 io
.in
.create_options
= 0;
510 status
= smb2_create(tree_snap
, tmp_ctx
, &io
);
511 torture_assert_ntstatus_ok(tctx
, status
, "snap read open");
514 r
.in
.file
.handle
= io
.out
.file
.handle
;
515 r
.in
.length
= sizeof("pre-snap");
516 status
= smb2_read(tree_snap
, tmp_ctx
, &r
);
517 torture_assert_ntstatus_ok(tctx
, status
, "read");
518 torture_assert_u64_equal(tctx
, r
.out
.data
.length
, r
.in
.length
,
519 "read data len mismatch");
520 torture_assert_str_equal(tctx
, (char *)r
.out
.data
.data
, "pre-snap",
521 "bad snapshot data");
523 torture_assert(tctx
, test_fsrvp_sc_delete(tctx
, p
, sc_map
), "sc del");
526 talloc_free(tmp_ctx
);
531 static bool test_fsrvp_enum_snaps(struct torture_context
*tctx
,
533 struct smb2_tree
*tree
,
534 struct smb2_handle fh
,
537 struct smb2_ioctl io
;
541 io
.level
= RAW_IOCTL_SMB2
;
542 io
.in
.file
.handle
= fh
;
543 io
.in
.function
= FSCTL_SRV_ENUM_SNAPS
;
544 io
.in
.max_response_size
= 16;
545 io
.in
.flags
= SMB2_IOCTL_FLAG_IS_FSCTL
;
547 status
= smb2_ioctl(tree
, mem_ctx
, &io
);
548 torture_assert_ntstatus_ok(tctx
, status
, "enum ioctl");
550 *_count
= IVAL(io
.out
.out
.data
, 0);
555 static bool test_fsrvp_enum_created(struct torture_context
*tctx
,
556 struct dcerpc_pipe
*p
)
558 struct fssagent_share_mapping_1
*sc_map
;
560 TALLOC_CTX
*tmp_ctx
= talloc_new(tctx
);
561 char *share_unc
= talloc_asprintf(tmp_ctx
, "\\\\%s\\%s",
562 dcerpc_server_name(p
), FSHARE
);
563 extern struct cli_credentials
*cmdline_credentials
;
564 struct smb2_tree
*tree_base
;
565 struct smbcli_options options
;
566 struct smb2_handle base_fh
;
568 lpcfg_smbcli_options(tctx
->lp_ctx
, &options
);
570 status
= smb2_connect(tmp_ctx
,
571 dcerpc_server_name(p
),
572 lpcfg_smb_ports(tctx
->lp_ctx
),
574 lpcfg_resolve_context(tctx
->lp_ctx
),
579 lpcfg_socket_options(tctx
->lp_ctx
),
580 lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
));
581 torture_assert_ntstatus_ok(tctx
, status
,
582 "Failed to connect to SMB2 share");
584 smb2_util_unlink(tree_base
, FNAME
);
585 status
= torture_smb2_testfile(tree_base
, FNAME
, &base_fh
);
586 torture_assert_ntstatus_ok(tctx
, status
, "base write open");
588 status
= smb2_util_write(tree_base
, base_fh
, "pre-snap", 0,
590 torture_assert_ntstatus_ok(tctx
, status
, "src write");
593 test_fsrvp_enum_snaps(tctx
, tmp_ctx
, tree_base
, base_fh
,
596 torture_assert_int_equal(tctx
, count
, 0, "num snaps");
598 torture_assert(tctx
, test_fsrvp_sc_create(tctx
, p
, share_unc
, &sc_map
),
603 test_fsrvp_enum_snaps(tctx
, tmp_ctx
, tree_base
, base_fh
,
607 * Snapshots created via FSRVP on Windows Server 2012 are not added to
608 * the previous versions list, so it will fail here...
610 torture_assert_int_equal(tctx
, count
, 1, "num snaps");
612 smb_msleep(1100); /* @GMT tokens have a 1 second resolution */
613 torture_assert(tctx
, test_fsrvp_sc_create(tctx
, p
, share_unc
, &sc_map
),
618 test_fsrvp_enum_snaps(tctx
, tmp_ctx
, tree_base
, base_fh
,
621 torture_assert_int_equal(tctx
, count
, 2, "num snaps");
623 talloc_free(tmp_ctx
);
628 static bool fsrvp_rpc_setup(struct torture_context
*tctx
, void **data
)
631 struct torture_rpc_tcase
*tcase
= talloc_get_type(
632 tctx
->active_tcase
, struct torture_rpc_tcase
);
633 struct torture_rpc_tcase_data
*tcase_data
;
634 extern struct cli_credentials
*cmdline_credentials
;
636 *data
= tcase_data
= talloc_zero(tctx
, struct torture_rpc_tcase_data
);
637 tcase_data
->credentials
= cmdline_credentials
;
639 status
= torture_rpc_connection(tctx
,
643 torture_assert_ntstatus_ok(tctx
, status
, "Error connecting to server");
645 /* XXX required, otherwise ndr out ptrs are not allocated */
646 tcase_data
->pipe
->conn
->flags
|= DCERPC_NDR_REF_ALLOC
;
652 testing of FSRVP (FSS agent)
654 struct torture_suite
*torture_rpc_fsrvp(TALLOC_CTX
*mem_ctx
)
656 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "fsrvp");
658 struct torture_rpc_tcase
*tcase
659 = torture_suite_add_rpc_iface_tcase(suite
, "fsrvp",
660 &ndr_table_FileServerVssAgent
);
661 /* override torture_rpc_setup() to set DCERPC_NDR_REF_ALLOC */
662 tcase
->tcase
.setup
= fsrvp_rpc_setup
;
664 torture_rpc_tcase_add_test(tcase
, "enum_created",
665 test_fsrvp_enum_created
);
666 torture_rpc_tcase_add_test(tcase
, "sc_share_io",
667 test_fsrvp_sc_share_io
);
668 torture_rpc_tcase_add_test(tcase
, "bad_id",
670 torture_rpc_tcase_add_test(tcase
, "sc_set_abort",
671 test_fsrvp_sc_set_abort
);
672 torture_rpc_tcase_add_test(tcase
, "create_simple",
673 test_fsrvp_sc_create_simple
);
674 torture_rpc_tcase_add_test(tcase
, "set_ctx",
676 torture_rpc_tcase_add_test(tcase
, "get_version",
677 test_fsrvp_get_version
);
678 torture_rpc_tcase_add_test(tcase
, "is_path_supported",
679 test_fsrvp_is_path_supported
);