From 2bf627a69cf12c3fff9125d80f9b473c45962f86 Mon Sep 17 00:00:00 2001 From: David Disseldorp Date: Sat, 29 Mar 2014 02:18:18 +0100 Subject: [PATCH 1/2] rpcclient: append a trailing slash to FSRVP request UNCs The Windows Server 2012 FSRVP server exhibits strange behaviour when exposing hidden shadow copy shares. If the hidden share UNC in the AddToShadowCopySet request includes a trailing backslash (e.g. "\\server\share$\"), then the new shadow-copy share will also be hidden (e.g. "\\server\share$@{ShadowCopy.ShadowCopyId}$"). However, if the UNC does not include a trailing backslash, which until now was rpcclient's default behaviour, then the exposed shadow-copy share is not hidden. Thanks to the MS Open Specifications team for helping me track down this one. bug: https://bugzilla.samba.org/show_bug.cgi?id=10521 Signed-off-by: David Disseldorp Reviewed-by: Jeremy Allison (cherry picked from commit d9bc82d90d6c4425028e225cf470283dd3a98049) --- source3/rpcclient/cmd_fss.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/source3/rpcclient/cmd_fss.c b/source3/rpcclient/cmd_fss.c index af194e2..661b954 100644 --- a/source3/rpcclient/cmd_fss.c +++ b/source3/rpcclient/cmd_fss.c @@ -88,7 +88,7 @@ static NTSTATUS cmd_fss_is_path_sup(struct rpc_pipe_client *cli, } ZERO_STRUCT(r); - r.in.ShareName = talloc_asprintf(mem_ctx, "%s\\%s", + r.in.ShareName = talloc_asprintf(mem_ctx, "%s\\%s\\", cli->srv_name_slash, argv[1]); if (r.in.ShareName == NULL) { return NT_STATUS_NO_MEMORY; @@ -187,8 +187,24 @@ static NTSTATUS cmd_fss_create_expose_parse(TALLOC_CTX *mem_ctx, int argc, } for (i = 0; i < num_share_args; i++) { - map_array[i].ShareNameUNC = talloc_asprintf(mem_ctx, "\\\\%s\\%s", - desthost, argv[i + num_non_share_args]); + /* + * A trailing slash should to be present in the request UNC, + * otherwise Windows Server 2012 FSRVP servers don't append + * a '$' to exposed hidden share shadow-copies. E.g. + * AddToShadowCopySet(UNC=\\server\hidden$) + * CommitShadowCopySet() + * ExposeShadowCopySet() + * -> new share = \\server\hidden$@{ShadowCopy.ShadowCopyId} + * But... + * AddToShadowCopySet(UNC=\\server\hidden$\) + * CommitShadowCopySet() + * ExposeShadowCopySet() + * -> new share = \\server\hidden$@{ShadowCopy.ShadowCopyId}$ + */ + map_array[i].ShareNameUNC = talloc_asprintf(mem_ctx, + "\\\\%s\\%s\\", + desthost, + argv[i + num_non_share_args]); if (map_array[i].ShareNameUNC == NULL) { return NT_STATUS_NO_MEMORY; } @@ -395,7 +411,7 @@ static NTSTATUS cmd_fss_delete(struct rpc_pipe_client *cli, } ZERO_STRUCT(r_sharemap_del); - r_sharemap_del.in.ShareName = talloc_asprintf(tmp_ctx, "\\\\%s\\%s", + r_sharemap_del.in.ShareName = talloc_asprintf(tmp_ctx, "\\\\%s\\%s\\", cli->desthost, argv[1]); if (r_sharemap_del.in.ShareName == NULL) { status = NT_STATUS_NO_MEMORY; @@ -449,7 +465,7 @@ static NTSTATUS cmd_fss_is_shadow_copied(struct rpc_pipe_client *cli, } ZERO_STRUCT(r); - r.in.ShareName = talloc_asprintf(mem_ctx, "%s\\%s", + r.in.ShareName = talloc_asprintf(mem_ctx, "%s\\%s\\", cli->srv_name_slash, argv[1]); if (r.in.ShareName == NULL) { return NT_STATUS_NO_MEMORY; @@ -504,7 +520,7 @@ static NTSTATUS cmd_fss_get_mapping(struct rpc_pipe_client *cli, } ZERO_STRUCT(r_sharemap_get); - r_sharemap_get.in.ShareName = talloc_asprintf(tmp_ctx, "\\\\%s\\%s", + r_sharemap_get.in.ShareName = talloc_asprintf(tmp_ctx, "\\\\%s\\%s\\", cli->desthost, argv[1]); if (r_sharemap_get.in.ShareName == NULL) { status = NT_STATUS_NO_MEMORY; -- 1.8.4.5 From ffe7f258ad3891c2a8225322a7df0008eb99f7a5 Mon Sep 17 00:00:00 2001 From: David Disseldorp Date: Sat, 29 Mar 2014 02:18:20 +0100 Subject: [PATCH 2/2] rpcclient: abort shadow-copy set on commit failure Use similar behaviour to the diskshadow.exe FSRVP client, which aborts the shadow-copy set if it receives a failed commit response. Signed-off-by: David Disseldorp Reviewed-by: Jeremy Allison Autobuild-User(master): Jeremy Allison Autobuild-Date(master): Tue Apr 1 00:54:06 CEST 2014 on sn-devel-104 (cherry picked from commit d550acf24a8ec20e3e32891ed702c6cc42bc3dee) --- source3/rpcclient/cmd_fss.c | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/source3/rpcclient/cmd_fss.c b/source3/rpcclient/cmd_fss.c index 661b954..972fe9d 100644 --- a/source3/rpcclient/cmd_fss.c +++ b/source3/rpcclient/cmd_fss.c @@ -215,6 +215,24 @@ static NTSTATUS cmd_fss_create_expose_parse(TALLOC_CTX *mem_ctx, int argc, return NT_STATUS_OK; } +static NTSTATUS cmd_fss_abort(TALLOC_CTX *mem_ctx, + struct dcerpc_binding_handle *b, + struct GUID *sc_set_id) +{ + NTSTATUS status; + struct fss_AbortShadowCopySet r_scset_abort; + + ZERO_STRUCT(r_scset_abort); + r_scset_abort.in.ShadowCopySetId = *sc_set_id; + status = dcerpc_fss_AbortShadowCopySet_r(b, mem_ctx, &r_scset_abort); + if (!NT_STATUS_IS_OK(status) || (r_scset_abort.out.result != 0)) { + DEBUG(0, ("AbortShadowCopySet failed: %s result: 0x%x\n", + nt_errstr(status), r_scset_abort.out.result)); + return NT_STATUS_UNSUCCESSFUL; + } + return NT_STATUS_OK; +} + static NTSTATUS cmd_fss_create_expose(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) @@ -308,7 +326,7 @@ static NTSTATUS cmd_fss_create_expose(struct rpc_pipe_client *cli, if (!NT_STATUS_IS_OK(status) || (r_scset_add.out.result != 0)) { DEBUG(0, ("AddToShadowCopySet failed: %s result: 0x%x\n", nt_errstr(status), r_scset_add.out.result)); - goto err_out; + goto err_sc_set_abort; } printf("%s(%s): %s shadow-copy added to set\n", GUID_string(tmp_ctx, r_scset_start.out.pShadowCopySetId), @@ -326,7 +344,7 @@ static NTSTATUS cmd_fss_create_expose(struct rpc_pipe_client *cli, if (!NT_STATUS_IS_OK(status) || (r_scset_prep.out.result != 0)) { DEBUG(0, ("PrepareShadowCopySet failed: %s result: 0x%x\n", nt_errstr(status), r_scset_prep.out.result)); - goto err_out; + goto err_sc_set_abort; } printf("%s: prepare completed in %llu secs\n", GUID_string(tmp_ctx, r_scset_start.out.pShadowCopySetId), @@ -340,7 +358,7 @@ static NTSTATUS cmd_fss_create_expose(struct rpc_pipe_client *cli, if (!NT_STATUS_IS_OK(status) || (r_scset_commit.out.result != 0)) { DEBUG(0, ("CommitShadowCopySet failed: %s result: 0x%x\n", nt_errstr(status), r_scset_commit.out.result)); - goto err_out; + goto err_sc_set_abort; } printf("%s: commit completed in %llu secs\n", GUID_string(tmp_ctx, r_scset_start.out.pShadowCopySetId), @@ -376,6 +394,11 @@ static NTSTATUS cmd_fss_create_expose(struct rpc_pipe_client *cli, map->ShadowCopyShareName, map->ShareNameUNC); } + talloc_free(tmp_ctx); + return NT_STATUS_OK; + +err_sc_set_abort: + cmd_fss_abort(tmp_ctx, b, r_scset_start.out.pShadowCopySetId); err_out: talloc_free(tmp_ctx); return status; -- 1.8.4.5