Line data Source code
1 : /*
2 : * Unix SMB/CIFS implementation.
3 : *
4 : * File Server Remote VSS Protocol (FSRVP) client
5 : *
6 : * Copyright (C) David Disseldorp 2012
7 : *
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.
12 : *
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.
17 : *
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/>.
20 : */
21 :
22 : #include "includes.h"
23 : #include "rpcclient.h"
24 : #include "../librpc/gen_ndr/ndr_fsrvp.h"
25 : #include "../librpc/gen_ndr/ndr_fsrvp_c.h"
26 : #include "../libcli/util/hresult.h"
27 :
28 : static const struct {
29 : uint32_t error_code;
30 : const char *error_str;
31 : } fss_errors[] = {
32 : {
33 : FSRVP_E_BAD_STATE,
34 : "A method call was invalid because of the state of the server."
35 : },
36 : {
37 : FSRVP_E_SHADOW_COPY_SET_IN_PROGRESS,
38 : "A call was made to either \'SetContext\' or \'StartShadowCopySet\' while the creation of another shadow copy set is in progress."
39 : },
40 : {
41 : FSRVP_E_NOT_SUPPORTED,
42 : "The file store which contains the share to be shadow copied is not supported by the server."
43 : },
44 : {
45 : FSRVP_E_WAIT_TIMEOUT,
46 : "The wait for a shadow copy commit or expose operation has timed out."
47 : },
48 : {
49 : FSRVP_E_WAIT_FAILED,
50 : "The wait for a shadow copy commit expose operation has failed."
51 : },
52 : {
53 : FSRVP_E_OBJECT_NOT_FOUND,
54 : "The specified object does not exist."
55 : },
56 : {
57 : FSRVP_E_UNSUPPORTED_CONTEXT,
58 : "The specified context value is invalid."
59 : },
60 : {
61 : FSRVP_E_SHADOWCOPYSET_ID_MISMATCH,
62 : "The provided ShadowCopySetId does not exist."
63 : },
64 : };
65 :
66 : struct fss_context_map {
67 : uint32_t ctx_val;
68 : const char *ctx_str;
69 : const char *ctx_desc;
70 : };
71 : struct fss_context_map ctx_map[] = {
72 : {
73 : .ctx_val = FSRVP_CTX_BACKUP,
74 : .ctx_str = "backup",
75 : .ctx_desc = "auto-release, non-persistent shadow-copy.",
76 : },
77 : {
78 : .ctx_val = FSRVP_CTX_FILE_SHARE_BACKUP,
79 : .ctx_str = "file_share_backup",
80 : .ctx_desc = "auto-release, non-persistent shadow-copy created "
81 : "without writer involvement.",
82 : },
83 : {
84 : .ctx_val = FSRVP_CTX_NAS_ROLLBACK,
85 : .ctx_str = "nas_rollback",
86 : .ctx_desc = "non-auto-release, persistent shadow-copy created "
87 : "without writer involvement.",
88 : },
89 : {
90 : .ctx_val = FSRVP_CTX_APP_ROLLBACK,
91 : .ctx_str = "app_rollback",
92 : .ctx_desc = "non-auto-release, persistent shadow-copy.",
93 : },
94 : { 0, NULL, NULL },
95 : };
96 :
97 0 : static const char *get_error_str(uint32_t code)
98 : {
99 : static const char *default_err = "Unknown Error";
100 0 : const char *result = default_err;
101 : int i;
102 0 : for (i = 0; i < ARRAY_SIZE(fss_errors); ++i) {
103 0 : if (code == fss_errors[i].error_code) {
104 0 : result = fss_errors[i].error_str;
105 0 : break;
106 : }
107 : }
108 : /* error isn't specific fsrvp one, check hresult errors */
109 0 : if (result == default_err) {
110 0 : const char *hres_err = hresult_errstr_const(HRES_ERROR(code));
111 0 : if (hres_err) {
112 0 : result = hres_err;
113 : }
114 : }
115 0 : return result;
116 : };
117 :
118 0 : static bool map_fss_ctx_str(const char *ctx_str,
119 : uint32_t *ctx_val)
120 : {
121 : int i;
122 :
123 0 : for (i = 0; ctx_map[i].ctx_str != NULL; i++) {
124 0 : if (!strcmp(ctx_map[i].ctx_str, ctx_str)) {
125 0 : *ctx_val = ctx_map[i].ctx_val;
126 0 : return true;
127 : }
128 : }
129 0 : return false;
130 : }
131 :
132 0 : static void cmd_fss_is_path_sup_usage(const char *script_name)
133 : {
134 0 : printf("usage: %s [share_name]\n", script_name);
135 0 : }
136 :
137 0 : static NTSTATUS cmd_fss_is_path_sup(struct rpc_pipe_client *cli,
138 : TALLOC_CTX *mem_ctx, int argc,
139 : const char **argv)
140 : {
141 : NTSTATUS status;
142 : struct fss_IsPathSupported r;
143 0 : struct dcerpc_binding_handle *b = cli->binding_handle;
144 :
145 0 : if (argc != 2) {
146 0 : cmd_fss_is_path_sup_usage(argv[0]);
147 0 : return NT_STATUS_UNSUCCESSFUL;
148 : }
149 :
150 0 : ZERO_STRUCT(r);
151 0 : r.in.ShareName = talloc_asprintf(mem_ctx, "%s\\%s\\",
152 0 : cli->srv_name_slash, argv[1]);
153 0 : if (r.in.ShareName == NULL) {
154 0 : return NT_STATUS_NO_MEMORY;
155 : }
156 :
157 0 : status = dcerpc_fss_IsPathSupported_r(b, mem_ctx, &r);
158 0 : if (!NT_STATUS_IS_OK(status)) {
159 0 : DEBUG(0, ("IsPathSupported failed with UNC %s\n",
160 : r.in.ShareName));
161 0 : return NT_STATUS_UNSUCCESSFUL;
162 0 : } else if (r.out.result) {
163 0 : DEBUG(0, ("failed IsPathSupported response: 0x%x - \"%s\"\n",
164 : r.out.result, get_error_str(r.out.result)));
165 0 : return NT_STATUS_UNSUCCESSFUL;
166 : }
167 0 : printf("UNC %s %s shadow copy requests\n", r.in.ShareName,
168 0 : *r.out.SupportedByThisProvider ? "supports" : "does not support");
169 :
170 0 : return NT_STATUS_OK;
171 : }
172 :
173 0 : static void cmd_fss_get_sup_version_usage(const char *script_name)
174 : {
175 0 : printf("usage: %s\n", script_name);
176 0 : }
177 :
178 0 : static NTSTATUS cmd_fss_get_sup_version(struct rpc_pipe_client *cli,
179 : TALLOC_CTX *mem_ctx, int argc,
180 : const char **argv)
181 : {
182 : NTSTATUS status;
183 : struct fss_GetSupportedVersion r;
184 0 : struct dcerpc_binding_handle *b = cli->binding_handle;
185 :
186 0 : if (argc != 1) {
187 0 : cmd_fss_get_sup_version_usage(argv[0]);
188 0 : return NT_STATUS_UNSUCCESSFUL;
189 : }
190 :
191 0 : ZERO_STRUCT(r);
192 0 : status = dcerpc_fss_GetSupportedVersion_r(b, mem_ctx, &r);
193 0 : if (!NT_STATUS_IS_OK(status) || (r.out.result != 0)) {
194 0 : DEBUG(0, ("GetSupportedVersion failed: %s result: 0x%x\n",
195 : nt_errstr(status), r.out.result));
196 0 : return NT_STATUS_UNSUCCESSFUL;
197 : }
198 0 : printf("server %s supports FSRVP versions from %u to %u\n",
199 0 : cli->desthost, *r.out.MinVersion, *r.out.MaxVersion);
200 :
201 0 : return NT_STATUS_OK;
202 : }
203 :
204 0 : static void cmd_fss_create_expose_usage(const char *script_name)
205 : {
206 : int i;
207 :
208 0 : printf("usage: %s [fss_context] [ro|rw] [share1] <share2> ...\n"
209 : "[fss_context] values:\n", script_name);
210 0 : for (i = 0; ctx_map[i].ctx_str != NULL; i++) {
211 0 : printf("\t%s: %s\n", ctx_map[i].ctx_str, ctx_map[i].ctx_desc);
212 : }
213 0 : }
214 :
215 0 : static NTSTATUS cmd_fss_create_expose_parse(TALLOC_CTX *mem_ctx, int argc,
216 : const char **argv,
217 : const char *desthost,
218 : uint32_t *fss_ctx_val,
219 : int *num_maps,
220 : struct fssagent_share_mapping_1 **maps)
221 : {
222 0 : int num_non_share_args = 3;
223 : int num_share_args;
224 : int i;
225 : struct fssagent_share_mapping_1 *map_array;
226 :
227 0 : if (argc < 4) {
228 0 : return NT_STATUS_INVALID_PARAMETER;
229 : }
230 :
231 0 : if (!map_fss_ctx_str(argv[1], fss_ctx_val)) {
232 0 : return NT_STATUS_INVALID_PARAMETER;
233 : }
234 :
235 0 : if (!strcmp(argv[2], "rw")) {
236 : /* shadow-copy is created as read-write */
237 0 : *fss_ctx_val |= ATTR_AUTO_RECOVERY;
238 0 : } else if (strcmp(argv[2], "ro")) {
239 0 : return NT_STATUS_INVALID_PARAMETER;
240 : }
241 :
242 0 : num_share_args = argc - num_non_share_args;
243 0 : map_array = talloc_array(mem_ctx, struct fssagent_share_mapping_1,
244 : num_share_args);
245 0 : if (map_array == NULL) {
246 0 : return NT_STATUS_NO_MEMORY;
247 : }
248 :
249 0 : for (i = 0; i < num_share_args; i++) {
250 : /*
251 : * A trailing slash should to be present in the request UNC,
252 : * otherwise Windows Server 2012 FSRVP servers don't append
253 : * a '$' to exposed hidden share shadow-copies. E.g.
254 : * AddToShadowCopySet(UNC=\\server\hidden$)
255 : * CommitShadowCopySet()
256 : * ExposeShadowCopySet()
257 : * -> new share = \\server\hidden$@{ShadowCopy.ShadowCopyId}
258 : * But...
259 : * AddToShadowCopySet(UNC=\\server\hidden$\)
260 : * CommitShadowCopySet()
261 : * ExposeShadowCopySet()
262 : * -> new share = \\server\hidden$@{ShadowCopy.ShadowCopyId}$
263 : */
264 0 : map_array[i].ShareNameUNC = talloc_asprintf(mem_ctx,
265 : "\\\\%s\\%s\\",
266 : desthost,
267 0 : argv[i + num_non_share_args]);
268 0 : if (map_array[i].ShareNameUNC == NULL) {
269 0 : return NT_STATUS_NO_MEMORY;
270 : }
271 : }
272 0 : *num_maps = num_share_args;
273 0 : *maps = map_array;
274 :
275 0 : return NT_STATUS_OK;
276 : }
277 :
278 0 : static NTSTATUS cmd_fss_abort(TALLOC_CTX *mem_ctx,
279 : struct dcerpc_binding_handle *b,
280 : struct GUID *sc_set_id)
281 : {
282 : NTSTATUS status;
283 : struct fss_AbortShadowCopySet r_scset_abort;
284 :
285 0 : ZERO_STRUCT(r_scset_abort);
286 0 : r_scset_abort.in.ShadowCopySetId = *sc_set_id;
287 0 : status = dcerpc_fss_AbortShadowCopySet_r(b, mem_ctx, &r_scset_abort);
288 0 : if (!NT_STATUS_IS_OK(status) || (r_scset_abort.out.result != 0)) {
289 0 : DEBUG(0, ("AbortShadowCopySet failed: %s result: 0x%x\n",
290 : nt_errstr(status), r_scset_abort.out.result));
291 0 : return NT_STATUS_UNSUCCESSFUL;
292 : }
293 0 : return NT_STATUS_OK;
294 : }
295 :
296 0 : static NTSTATUS cmd_fss_create_expose(struct rpc_pipe_client *cli,
297 : TALLOC_CTX *mem_ctx, int argc,
298 : const char **argv)
299 : {
300 : NTSTATUS status;
301 : struct fss_GetSupportedVersion r_version_get;
302 : struct fss_SetContext r_context_set;
303 : struct fss_StartShadowCopySet r_scset_start;
304 : struct fss_PrepareShadowCopySet r_scset_prep;
305 : struct fss_CommitShadowCopySet r_scset_commit;
306 : struct fss_ExposeShadowCopySet r_scset_expose;
307 0 : struct dcerpc_binding_handle *b = cli->binding_handle;
308 : time_t start_time;
309 : TALLOC_CTX *tmp_ctx;
310 : uint32_t fss_ctx_val;
311 : int num_maps;
312 : struct fssagent_share_mapping_1 *req_maps;
313 : int i;
314 :
315 0 : tmp_ctx = talloc_new(mem_ctx);
316 0 : if (tmp_ctx == NULL) {
317 0 : return NT_STATUS_NO_MEMORY;
318 : }
319 :
320 0 : status = cmd_fss_create_expose_parse(tmp_ctx, argc, argv, cli->desthost,
321 : &fss_ctx_val, &num_maps, &req_maps);
322 0 : if (!NT_STATUS_IS_OK(status)) {
323 0 : cmd_fss_create_expose_usage(argv[0]);
324 0 : goto err_out;
325 : }
326 :
327 : /*
328 : * PrepareShadowCopySet & CommitShadowCopySet often exceed the default
329 : * 60 second dcerpc request timeout against Windows Server "8" Beta.
330 : * ACHTUNG! dcerpc_binding_handle_set_timeout() value is interpreted as
331 : * seconds on a source4 transport and as msecs here.
332 : */
333 0 : dcerpc_binding_handle_set_timeout(b, 240 * 1000);
334 :
335 0 : for (i = 0; i < num_maps; i++) {
336 : struct fss_IsPathSupported r_pathsupport_get;
337 0 : r_pathsupport_get.in.ShareName = req_maps[i].ShareNameUNC;
338 0 : status = dcerpc_fss_IsPathSupported_r(b, tmp_ctx, &r_pathsupport_get);
339 0 : if (!NT_STATUS_IS_OK(status) || (r_pathsupport_get.out.result != 0)) {
340 0 : DEBUG(0, ("IsPathSupported failed: %s result: 0x%x\n",
341 : nt_errstr(status), r_pathsupport_get.out.result));
342 0 : goto err_out;
343 : }
344 0 : if (!r_pathsupport_get.out.SupportedByThisProvider) {
345 0 : printf("path %s does not supported shadow-copies\n",
346 0 : req_maps[i].ShareNameUNC);
347 0 : status = NT_STATUS_NOT_SUPPORTED;
348 0 : goto err_out;
349 : }
350 : }
351 :
352 0 : ZERO_STRUCT(r_version_get);
353 0 : status = dcerpc_fss_GetSupportedVersion_r(b, tmp_ctx, &r_version_get);
354 0 : if (!NT_STATUS_IS_OK(status) || (r_version_get.out.result != 0)) {
355 0 : DEBUG(0, ("GetSupportedVersion failed: %s result: 0x%x\n",
356 : nt_errstr(status), r_version_get.out.result));
357 0 : goto err_out;
358 : }
359 :
360 0 : ZERO_STRUCT(r_context_set);
361 0 : r_context_set.in.Context = fss_ctx_val;
362 0 : status = dcerpc_fss_SetContext_r(b, tmp_ctx, &r_context_set);
363 0 : if (!NT_STATUS_IS_OK(status) || (r_context_set.out.result != 0)) {
364 0 : DEBUG(0, ("SetContext failed: %s result: 0x%x\n",
365 : nt_errstr(status), r_context_set.out.result));
366 0 : goto err_out;
367 : }
368 :
369 0 : ZERO_STRUCT(r_scset_start);
370 0 : r_scset_start.in.ClientShadowCopySetId = GUID_random();
371 0 : status = dcerpc_fss_StartShadowCopySet_r(b, tmp_ctx, &r_scset_start);
372 0 : if (!NT_STATUS_IS_OK(status) || (r_scset_start.out.result != 0)) {
373 0 : DEBUG(0, ("StartShadowCopySet failed: %s result: 0x%x\n",
374 : nt_errstr(status), r_scset_start.out.result));
375 0 : goto err_out;
376 : }
377 0 : printf("%s: shadow-copy set created\n",
378 0 : GUID_string(tmp_ctx, r_scset_start.out.pShadowCopySetId));
379 :
380 0 : for (i = 0; i < num_maps; i++) {
381 : struct fss_AddToShadowCopySet r_scset_add;
382 0 : r_scset_add.in.ClientShadowCopyId = GUID_random();
383 0 : r_scset_add.in.ShadowCopySetId = *r_scset_start.out.pShadowCopySetId;
384 0 : r_scset_add.in.ShareName = req_maps[i].ShareNameUNC;
385 0 : status = dcerpc_fss_AddToShadowCopySet_r(b, tmp_ctx, &r_scset_add);
386 0 : if (!NT_STATUS_IS_OK(status) || (r_scset_add.out.result != 0)) {
387 0 : DEBUG(0, ("AddToShadowCopySet failed: %s result: 0x%x\n",
388 : nt_errstr(status), r_scset_add.out.result));
389 0 : goto err_sc_set_abort;
390 : }
391 0 : printf("%s(%s): %s shadow-copy added to set\n",
392 0 : GUID_string(tmp_ctx, r_scset_start.out.pShadowCopySetId),
393 0 : GUID_string(tmp_ctx, r_scset_add.out.pShadowCopyId),
394 : r_scset_add.in.ShareName);
395 0 : req_maps[i].ShadowCopySetId = *r_scset_start.out.pShadowCopySetId;
396 0 : req_maps[i].ShadowCopyId = *r_scset_add.out.pShadowCopyId;
397 : }
398 :
399 0 : start_time = time_mono(NULL);
400 0 : ZERO_STRUCT(r_scset_prep);
401 0 : r_scset_prep.in.ShadowCopySetId = *r_scset_start.out.pShadowCopySetId;
402 0 : r_scset_prep.in.TimeOutInMilliseconds = (240 * 1000);
403 0 : status = dcerpc_fss_PrepareShadowCopySet_r(b, tmp_ctx, &r_scset_prep);
404 0 : if (!NT_STATUS_IS_OK(status) || (r_scset_prep.out.result != 0)) {
405 0 : DEBUG(0, ("PrepareShadowCopySet failed: %s result: 0x%x\n",
406 : nt_errstr(status), r_scset_prep.out.result));
407 0 : goto err_sc_set_abort;
408 : }
409 0 : printf("%s: prepare completed in %llu secs\n",
410 0 : GUID_string(tmp_ctx, r_scset_start.out.pShadowCopySetId),
411 0 : (long long unsigned int)(time_mono(NULL) - start_time));
412 :
413 0 : start_time = time_mono(NULL);
414 0 : ZERO_STRUCT(r_scset_commit);
415 0 : r_scset_commit.in.ShadowCopySetId = *r_scset_start.out.pShadowCopySetId;
416 0 : r_scset_commit.in.TimeOutInMilliseconds = (180 * 1000); /* win8 */
417 0 : status = dcerpc_fss_CommitShadowCopySet_r(b, tmp_ctx, &r_scset_commit);
418 0 : if (!NT_STATUS_IS_OK(status) || (r_scset_commit.out.result != 0)) {
419 0 : DEBUG(0, ("CommitShadowCopySet failed: %s result: 0x%x\n",
420 : nt_errstr(status), r_scset_commit.out.result));
421 0 : goto err_sc_set_abort;
422 : }
423 0 : printf("%s: commit completed in %llu secs\n",
424 0 : GUID_string(tmp_ctx, r_scset_start.out.pShadowCopySetId),
425 0 : (long long unsigned int)(time_mono(NULL) - start_time));
426 :
427 0 : ZERO_STRUCT(r_scset_expose);
428 0 : r_scset_expose.in.ShadowCopySetId = *r_scset_start.out.pShadowCopySetId;
429 0 : r_scset_expose.in.TimeOutInMilliseconds = (120 * 1000); /* win8 */
430 0 : status = dcerpc_fss_ExposeShadowCopySet_r(b, tmp_ctx, &r_scset_expose);
431 0 : if (!NT_STATUS_IS_OK(status) || (r_scset_expose.out.result != 0)) {
432 0 : DEBUG(0, ("ExposeShadowCopySet failed: %s result: 0x%x\n",
433 : nt_errstr(status), r_scset_expose.out.result));
434 0 : goto err_out;
435 : }
436 :
437 0 : for (i = 0; i < num_maps; i++) {
438 : struct fss_GetShareMapping r_sharemap_get;
439 : struct fssagent_share_mapping_1 *map;
440 0 : r_sharemap_get.in.ShadowCopyId = req_maps[i].ShadowCopyId;
441 0 : r_sharemap_get.in.ShadowCopySetId = req_maps[i].ShadowCopySetId;
442 0 : r_sharemap_get.in.ShareName = req_maps[i].ShareNameUNC;
443 0 : r_sharemap_get.in.Level = 1;
444 0 : status = dcerpc_fss_GetShareMapping_r(b, tmp_ctx, &r_sharemap_get);
445 0 : if (!NT_STATUS_IS_OK(status) || (r_sharemap_get.out.result != 0)) {
446 0 : DEBUG(0, ("GetShareMapping failed: %s result: 0x%x\n",
447 : nt_errstr(status), r_sharemap_get.out.result));
448 0 : goto err_out;
449 : }
450 0 : map = r_sharemap_get.out.ShareMapping->ShareMapping1;
451 0 : printf("%s(%s): share %s exposed as a snapshot of %s\n",
452 0 : GUID_string(tmp_ctx, &map->ShadowCopySetId),
453 0 : GUID_string(tmp_ctx, &map->ShadowCopyId),
454 : map->ShadowCopyShareName, map->ShareNameUNC);
455 : }
456 :
457 0 : talloc_free(tmp_ctx);
458 0 : return NT_STATUS_OK;
459 :
460 0 : err_sc_set_abort:
461 0 : cmd_fss_abort(tmp_ctx, b, r_scset_start.out.pShadowCopySetId);
462 0 : err_out:
463 0 : talloc_free(tmp_ctx);
464 0 : return status;
465 : }
466 :
467 0 : static void cmd_fss_delete_usage(const char *script_name)
468 : {
469 0 : printf("usage: %s [base_share] [shadow_copy_set_id] [shadow_copy_id]\n",
470 : script_name);
471 0 : }
472 :
473 0 : static NTSTATUS cmd_fss_delete(struct rpc_pipe_client *cli,
474 : TALLOC_CTX *mem_ctx, int argc,
475 : const char **argv)
476 : {
477 0 : struct dcerpc_binding_handle *b = cli->binding_handle;
478 : struct fss_DeleteShareMapping r_sharemap_del;
479 : const char *sc_set_id;
480 : const char *sc_id;
481 : NTSTATUS status;
482 : TALLOC_CTX *tmp_ctx;
483 :
484 0 : if (argc < 4) {
485 0 : cmd_fss_delete_usage(argv[0]);
486 0 : return NT_STATUS_UNSUCCESSFUL;
487 : }
488 0 : sc_set_id = argv[2];
489 0 : sc_id = argv[3];
490 :
491 0 : tmp_ctx = talloc_new(mem_ctx);
492 0 : if (tmp_ctx == NULL) {
493 0 : return NT_STATUS_NO_MEMORY;
494 : }
495 :
496 0 : ZERO_STRUCT(r_sharemap_del);
497 0 : r_sharemap_del.in.ShareName = talloc_asprintf(tmp_ctx, "\\\\%s\\%s\\",
498 0 : cli->desthost, argv[1]);
499 0 : if (r_sharemap_del.in.ShareName == NULL) {
500 0 : status = NT_STATUS_NO_MEMORY;
501 0 : goto err_out;
502 : }
503 0 : status = GUID_from_string(sc_set_id, &r_sharemap_del.in.ShadowCopySetId);
504 0 : if (!NT_STATUS_IS_OK(status)) {
505 0 : DEBUG(0, ("Invalid shadow_copy_set_id parameter\n"));
506 0 : goto err_out;
507 : }
508 0 : status = GUID_from_string(sc_id, &r_sharemap_del.in.ShadowCopyId);
509 0 : if (!NT_STATUS_IS_OK(status)) {
510 0 : DEBUG(0, ("Invalid shadow_copy_id parameter\n"));
511 0 : goto err_out;
512 : }
513 0 : status = dcerpc_fss_DeleteShareMapping_r(b, tmp_ctx, &r_sharemap_del);
514 0 : if (!NT_STATUS_IS_OK(status)) {
515 0 : DEBUG(0, ("DeleteShareMapping failed\n"));
516 0 : goto err_out;
517 0 : } else if (r_sharemap_del.out.result != 0) {
518 0 : DEBUG(0, ("failed DeleteShareMapping response: 0x%x\n",
519 : r_sharemap_del.out.result));
520 0 : status = NT_STATUS_UNSUCCESSFUL;
521 0 : goto err_out;
522 : }
523 :
524 0 : printf("%s(%s): %s shadow-copy deleted\n",
525 : sc_set_id, sc_id, r_sharemap_del.in.ShareName);
526 :
527 0 : err_out:
528 0 : talloc_free(tmp_ctx);
529 0 : return status;
530 : }
531 :
532 0 : static void cmd_fss_is_shadow_copied_usage(const char *script_name)
533 : {
534 0 : printf("usage: %s [share_name]\n", script_name);
535 0 : }
536 :
537 0 : static NTSTATUS cmd_fss_is_shadow_copied(struct rpc_pipe_client *cli,
538 : TALLOC_CTX *mem_ctx, int argc,
539 : const char **argv)
540 : {
541 : NTSTATUS status;
542 : struct fss_IsPathShadowCopied r;
543 0 : struct dcerpc_binding_handle *b = cli->binding_handle;
544 :
545 0 : if (argc != 2) {
546 0 : cmd_fss_is_shadow_copied_usage(argv[0]);
547 0 : return NT_STATUS_UNSUCCESSFUL;
548 : }
549 :
550 0 : ZERO_STRUCT(r);
551 0 : r.in.ShareName = talloc_asprintf(mem_ctx, "%s\\%s\\",
552 0 : cli->srv_name_slash, argv[1]);
553 0 : if (r.in.ShareName == NULL) {
554 0 : return NT_STATUS_NO_MEMORY;
555 : }
556 :
557 0 : status = dcerpc_fss_IsPathShadowCopied_r(b, mem_ctx, &r);
558 0 : if (!NT_STATUS_IS_OK(status)) {
559 0 : DEBUG(0, ("IsPathShadowCopied failed with UNC %s\n",
560 : r.in.ShareName));
561 0 : return NT_STATUS_UNSUCCESSFUL;
562 0 : } else if (r.out.result) {
563 0 : DEBUG(0, ("failed IsPathShadowCopied response: 0x%x\n",
564 : r.out.result));
565 0 : return NT_STATUS_UNSUCCESSFUL;
566 : }
567 0 : printf("UNC %s %s an associated shadow-copy with compatibility 0x%x\n",
568 : r.in.ShareName,
569 0 : *r.out.ShadowCopyPresent ? "has" : "does not have",
570 0 : *r.out.ShadowCopyCompatibility);
571 :
572 0 : return NT_STATUS_OK;
573 : }
574 :
575 0 : static void cmd_fss_get_mapping_usage(const char *script_name)
576 : {
577 0 : printf("usage: %s [base_share] [shadow_copy_set_id] [shadow_copy_id]\n",
578 : script_name);
579 0 : }
580 :
581 0 : static NTSTATUS cmd_fss_get_mapping(struct rpc_pipe_client *cli,
582 : TALLOC_CTX *mem_ctx, int argc,
583 : const char **argv)
584 : {
585 0 : struct dcerpc_binding_handle *b = cli->binding_handle;
586 : struct fss_GetShareMapping r_sharemap_get;
587 : const char *sc_set_id;
588 : const char *sc_id;
589 : struct fssagent_share_mapping_1 *map;
590 : NTSTATUS status;
591 : TALLOC_CTX *tmp_ctx;
592 :
593 0 : if (argc < 4) {
594 0 : cmd_fss_get_mapping_usage(argv[0]);
595 0 : return NT_STATUS_UNSUCCESSFUL;
596 : }
597 0 : sc_set_id = argv[2];
598 0 : sc_id = argv[3];
599 :
600 0 : tmp_ctx = talloc_new(mem_ctx);
601 0 : if (tmp_ctx == NULL) {
602 0 : return NT_STATUS_NO_MEMORY;
603 : }
604 :
605 0 : ZERO_STRUCT(r_sharemap_get);
606 0 : r_sharemap_get.in.ShareName = talloc_asprintf(tmp_ctx, "\\\\%s\\%s\\",
607 0 : cli->desthost, argv[1]);
608 0 : if (r_sharemap_get.in.ShareName == NULL) {
609 0 : status = NT_STATUS_NO_MEMORY;
610 0 : goto err_out;
611 : }
612 0 : status = GUID_from_string(sc_set_id, &r_sharemap_get.in.ShadowCopySetId);
613 0 : if (!NT_STATUS_IS_OK(status)) {
614 0 : DEBUG(0, ("Invalid shadow_copy_set_id parameter\n"));
615 0 : goto err_out;
616 : }
617 0 : status = GUID_from_string(sc_id, &r_sharemap_get.in.ShadowCopyId);
618 0 : if (!NT_STATUS_IS_OK(status)) {
619 0 : DEBUG(0, ("Invalid shadow_copy_id parameter\n"));
620 0 : goto err_out;
621 : }
622 0 : r_sharemap_get.in.Level = 1;
623 0 : status = dcerpc_fss_GetShareMapping_r(b, tmp_ctx, &r_sharemap_get);
624 0 : if (!NT_STATUS_IS_OK(status)) {
625 0 : DEBUG(0, ("GetShareMapping failed\n"));
626 0 : goto err_out;
627 0 : } else if (r_sharemap_get.out.result != 0) {
628 0 : DEBUG(0, ("failed GetShareMapping response: 0x%x\n",
629 : r_sharemap_get.out.result));
630 0 : status = NT_STATUS_UNSUCCESSFUL;
631 0 : goto err_out;
632 : }
633 :
634 0 : map = r_sharemap_get.out.ShareMapping->ShareMapping1;
635 0 : printf("%s(%s): share %s is a shadow-copy of %s at %s\n",
636 0 : GUID_string(tmp_ctx, &map->ShadowCopySetId),
637 0 : GUID_string(tmp_ctx, &map->ShadowCopyId),
638 : map->ShadowCopyShareName, map->ShareNameUNC,
639 : nt_time_string(tmp_ctx, map->tstamp));
640 :
641 0 : err_out:
642 0 : talloc_free(tmp_ctx);
643 0 : return status;
644 : }
645 :
646 0 : static void cmd_fss_recov_complete_usage(const char *script_name)
647 : {
648 0 : printf("usage: %s [shadow_copy_set_id]\n", script_name);
649 0 : }
650 :
651 0 : static NTSTATUS cmd_fss_recov_complete(struct rpc_pipe_client *cli,
652 : TALLOC_CTX *mem_ctx, int argc,
653 : const char **argv)
654 : {
655 : NTSTATUS status;
656 : struct fss_RecoveryCompleteShadowCopySet r;
657 0 : struct dcerpc_binding_handle *b = cli->binding_handle;
658 : const char *sc_set_id;
659 :
660 0 : if (argc != 2) {
661 0 : cmd_fss_recov_complete_usage(argv[0]);
662 0 : return NT_STATUS_UNSUCCESSFUL;
663 : }
664 0 : sc_set_id = argv[1];
665 :
666 0 : ZERO_STRUCT(r);
667 0 : status = GUID_from_string(sc_set_id, &r.in.ShadowCopySetId);
668 0 : if (!NT_STATUS_IS_OK(status)) {
669 0 : DEBUG(0, ("Invalid shadow_copy_set_id\n"));
670 0 : return NT_STATUS_INVALID_PARAMETER;
671 : }
672 :
673 0 : status = dcerpc_fss_RecoveryCompleteShadowCopySet_r(b, mem_ctx, &r);
674 0 : if (!NT_STATUS_IS_OK(status) || (r.out.result != 0)) {
675 0 : DEBUG(0, ("RecoveryCompleteShadowCopySet failed: %s "
676 : "result: 0x%x\n", nt_errstr(status), r.out.result));
677 0 : return status;
678 : }
679 0 : printf("%s: shadow-copy set marked recovery complete\n", sc_set_id);
680 :
681 0 : return NT_STATUS_OK;
682 : }
683 :
684 : /* List of commands exported by this module */
685 : struct cmd_set fss_commands[] = {
686 :
687 : {
688 : .name = "FSRVP",
689 : },
690 :
691 : {
692 : .name = "fss_is_path_sup",
693 : .returntype = RPC_RTYPE_NTSTATUS,
694 : .ntfn = cmd_fss_is_path_sup,
695 : .table = &ndr_table_FileServerVssAgent,
696 : .rpc_pipe = NULL,
697 : .description = "Check whether a share supports shadow-copy "
698 : "requests",
699 : .usage = "",
700 : },
701 : {
702 : .name = "fss_get_sup_version",
703 : .returntype = RPC_RTYPE_NTSTATUS,
704 : .ntfn = cmd_fss_get_sup_version,
705 : .table = &ndr_table_FileServerVssAgent,
706 : .rpc_pipe = NULL,
707 : .description = "Get supported FSRVP version from server",
708 : .usage = "",
709 : },
710 : {
711 : .name = "fss_create_expose",
712 : .returntype = RPC_RTYPE_NTSTATUS,
713 : .ntfn = cmd_fss_create_expose,
714 : .table = &ndr_table_FileServerVssAgent,
715 : .rpc_pipe = NULL,
716 : .description = "Request shadow-copy creation and exposure",
717 : .usage = "",
718 : },
719 : {
720 : .name = "fss_delete",
721 : .returntype = RPC_RTYPE_NTSTATUS,
722 : .ntfn = cmd_fss_delete,
723 : .table = &ndr_table_FileServerVssAgent,
724 : .rpc_pipe = NULL,
725 : .description = "Request shadow-copy share deletion",
726 : .usage = "",
727 : },
728 : {
729 : .name = "fss_has_shadow_copy",
730 : .returntype = RPC_RTYPE_NTSTATUS,
731 : .ntfn = cmd_fss_is_shadow_copied,
732 : .table = &ndr_table_FileServerVssAgent,
733 : .rpc_pipe = NULL,
734 : .description = "Check for an associated share shadow-copy",
735 : .usage = "",
736 : },
737 : {
738 : .name = "fss_get_mapping",
739 : .returntype = RPC_RTYPE_NTSTATUS,
740 : .ntfn = cmd_fss_get_mapping,
741 : .table = &ndr_table_FileServerVssAgent,
742 : .rpc_pipe = NULL,
743 : .description = "Get shadow-copy share mapping information",
744 : .usage = "",
745 : },
746 : {
747 : .name = "fss_recovery_complete",
748 : .returntype = RPC_RTYPE_NTSTATUS,
749 : .ntfn = cmd_fss_recov_complete,
750 : .table = &ndr_table_FileServerVssAgent,
751 : .rpc_pipe = NULL,
752 : .description = "Flag read-write snapshot as recovery complete, "
753 : "allowing further shadow-copy requests",
754 : .usage = "",
755 : },
756 : {
757 : .name = NULL,
758 : },
759 : };
|