2 * File Server Remote VSS Protocol (FSRVP) server
4 * Copyright (C) David Disseldorp 2012-2015
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "include/messages.h"
24 #include "include/auth.h"
25 #include "../libcli/security/security.h"
26 #include "../libcli/util/hresult.h"
27 #include "../lib/smbconf/smbconf.h"
28 #include "smbd/proto.h"
29 #include "lib/smbconf/smbconf_init.h"
30 #include "librpc/gen_ndr/srv_fsrvp.h"
31 #include "srv_fss_private.h"
32 #include "srv_fss_agent.h"
35 #define DBGC_CLASS DBGC_RPC_SRV
37 static struct fss_global fss_global;
39 /* errmap NTSTATUS->fsrvp */
43 } ntstatus_to_fsrvp_map[] = {
44 {NT_STATUS_INVALID_SERVER_STATE, FSRVP_E_BAD_STATE},
45 {NT_STATUS_INVALID_DISPOSITION, FSRVP_E_SHADOW_COPY_SET_IN_PROGRESS},
46 {NT_STATUS_NOT_SUPPORTED, FSRVP_E_NOT_SUPPORTED},
47 {NT_STATUS_IO_TIMEOUT, FSRVP_E_WAIT_TIMEOUT},
48 {NT_STATUS_CANT_WAIT, FSRVP_E_WAIT_FAILED},
49 {NT_STATUS_OBJECTID_EXISTS, FSRVP_E_OBJECT_ALREADY_EXISTS},
50 {NT_STATUS_OBJECTID_NOT_FOUND, FSRVP_E_OBJECT_NOT_FOUND},
51 {NT_STATUS_OBJECT_NAME_INVALID, FSRVP_E_BAD_ID},
54 /* errmap NTSTATUS->hresult */
58 } ntstatus_to_hres_map[] = {
59 {NT_STATUS_ACCESS_DENIED, HRES_E_ACCESSDENIED},
60 {NT_STATUS_INVALID_PARAMETER, HRES_E_INVALIDARG},
61 {NT_STATUS_NO_MEMORY, HRES_E_OUTOFMEMORY},
64 static uint32_t fss_ntstatus_map(NTSTATUS status)
68 if (NT_STATUS_IS_OK(status))
71 /* check fsrvp specific errors first */
72 for (i = 0; i < ARRAY_SIZE(ntstatus_to_fsrvp_map); i++) {
73 if (NT_STATUS_EQUAL(status, ntstatus_to_fsrvp_map[i].status)) {
74 return ntstatus_to_fsrvp_map[i].fsrvp_err;
77 /* fall-back to generic hresult values */
78 for (i = 0; i < ARRAY_SIZE(ntstatus_to_hres_map); i++) {
79 if (NT_STATUS_EQUAL(status, ntstatus_to_hres_map[i].status)) {
80 return HRES_ERROR_V(ntstatus_to_hres_map[i].hres);
84 return HRES_ERROR_V(HRES_E_FAIL);
87 static NTSTATUS fss_unc_parse(TALLOC_CTX *mem_ctx,
97 return NT_STATUS_INVALID_PARAMETER;
100 s = strstr_m(unc, "\\\\");
102 return NT_STATUS_INVALID_PARAMETER;
105 server = talloc_strdup(mem_ctx, s + 2);
106 if (server == NULL) {
107 return NT_STATUS_NO_MEMORY;
109 s = strchr_m(server, '\\');
110 if ((s == NULL) || (s == server)) {
111 return NT_STATUS_INVALID_PARAMETER;
116 s = strchr_m(share, '\\');
118 /* diskshadow.exe adds a trailing '\' to the share-name */
121 if (strlen(share) == 0) {
122 return NT_STATUS_INVALID_PARAMETER;
125 if (_server != NULL) {
128 if (_share != NULL) {
135 static NTSTATUS fss_vfs_conn_create(TALLOC_CTX *mem_ctx,
136 struct tevent_context *ev,
137 struct messaging_context *msg_ctx,
138 struct auth_session_info *session_info,
140 struct connection_struct **conn_out);
141 static void fss_vfs_conn_destroy(struct connection_struct *conn);
143 /* test if system path exists */
144 static bool snap_path_exists(TALLOC_CTX *ctx, struct messaging_context *msg_ctx,
147 TALLOC_CTX *frame = talloc_stackframe();
149 struct connection_struct *conn = NULL;
150 struct smb_filename *smb_fname = NULL;
151 char *service = NULL;
160 if ((sc->smaps_count == 0) || (sc->sc_path == NULL)) {
164 share = sc->smaps->share_name;
165 snum = find_service(frame, share, &service);
167 if ((snum == -1) || (service == NULL)) {
171 status = fss_vfs_conn_create(frame, server_event_context(),
172 msg_ctx, NULL, snum, &conn);
174 if(!NT_STATUS_IS_OK(status)) {
178 smb_fname = synthetic_smb_fname(service, sc->sc_path, NULL, NULL, 0);
179 if (smb_fname == NULL) {
183 ret = SMB_VFS_STAT(conn, smb_fname);
184 if ((ret == -1) && (errno == ENOENT)) {
190 fss_vfs_conn_destroy(conn);
196 static NTSTATUS sc_smap_unexpose(struct messaging_context *msg_ctx,
197 struct fss_sc_smap *sc_smap, bool delete_all);
199 static NTSTATUS fss_prune_stale(struct messaging_context *msg_ctx,
202 struct fss_sc_set *sc_sets;
203 uint32_t sc_sets_count = 0;
204 struct fss_sc_set *sc_set;
205 struct fss_sc_smap *prunable_sc_smaps = NULL;
206 bool is_modified = false;
207 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
208 TALLOC_CTX *ctx = talloc_new(NULL);
211 return NT_STATUS_NO_MEMORY;
214 /* work with temporary state for simple cleanup on failure */
216 status = fss_state_retrieve(ctx, &sc_sets, &sc_sets_count, db_path);
218 if (!NT_STATUS_IS_OK(status)) {
219 DEBUG(1, ("failed to retrieve fss server state: %s\n",
224 /* walk the cache and pick up any entries to be deleted */
226 DEBUG(10, ("pruning shared shadow copies\n"));
229 struct fss_sc_set *sc_set_next = sc_set->next;
230 char *set_id = GUID_string(ctx, &sc_set->id);
231 if (set_id == NULL) {
232 status = NT_STATUS_NO_MEMORY;
235 DEBUGADD(10, ("\tprocessing shadow set id %s\n", set_id));
238 struct fss_sc_smap *sc_smap;
239 struct fss_sc *sc_next = sc->next;
240 DEBUGADD(10, ("\tprocessing shadow copy path %s\n",
242 if (snap_path_exists(ctx, msg_ctx, sc)) {
247 /* move missing snapshot state to purge list */
249 while (sc_smap != NULL) {
250 struct fss_sc_smap *smap_next = sc_smap->next;
251 DLIST_REMOVE(sc->smaps, sc_smap);
252 DLIST_ADD_END(prunable_sc_smaps, sc_smap);
257 DLIST_REMOVE(sc_set->scs, sc);
262 if (sc_set->scs_count == 0) {
263 DLIST_REMOVE(sc_sets, sc_set);
266 sc_set = sc_set_next;
270 /* unexpose all shares in a single transaction */
271 status = sc_smap_unexpose(msg_ctx, prunable_sc_smaps, true);
272 if (!NT_STATUS_IS_OK(status)) {
273 /* exit without storing updated state */
278 status = fss_state_store(ctx, sc_sets, sc_sets_count, db_path);
280 if (!NT_STATUS_IS_OK(status)) {
281 DEBUG(1, ("pruning failed to store fss server state: %s\n",
286 status = NT_STATUS_OK;
292 static NTSTATUS fss_vfs_conn_create(TALLOC_CTX *mem_ctx,
293 struct tevent_context *ev,
294 struct messaging_context *msg_ctx,
295 struct auth_session_info *session_info,
297 struct connection_struct **conn_out)
299 struct connection_struct *conn = NULL;
302 status = create_conn_struct(mem_ctx, ev, msg_ctx, &conn,
303 snum, lp_path(mem_ctx, snum),
305 if (!NT_STATUS_IS_OK(status)) {
306 DEBUG(0,("failed to create conn for vfs: %s\n",
311 status = set_conn_force_user_group(conn, snum);
312 if (!NT_STATUS_IS_OK(status)) {
313 DEBUG(0, ("failed set force user / group\n"));
322 SMB_VFS_DISCONNECT(conn);
327 static void fss_vfs_conn_destroy(struct connection_struct *conn)
329 SMB_VFS_DISCONNECT(conn);
333 static struct fss_sc_set *sc_set_lookup(struct fss_sc_set *sc_set_head,
334 struct GUID *sc_set_id)
337 struct fss_sc_set *sc_set;
340 for (sc_set = sc_set_head; sc_set; sc_set = sc_set->next) {
341 if (GUID_equal(&sc_set->id, sc_set_id)) {
345 guid_str = GUID_string(sc_set_head, sc_set_id);
346 DEBUG(4, ("shadow copy set with GUID %s not found\n",
347 guid_str ? guid_str : "NO MEM"));
348 talloc_free(guid_str);
353 static struct fss_sc *sc_lookup(struct fss_sc *sc_head, struct GUID *sc_id)
359 for (sc = sc_head; sc; sc = sc->next) {
360 if (GUID_equal(&sc->id, sc_id)) {
364 guid_str = GUID_string(sc_head, sc_id);
365 DEBUG(4, ("shadow copy with GUID %s not found\n",
366 guid_str ? guid_str : "NO MEM"));
367 talloc_free(guid_str);
372 static struct fss_sc *sc_lookup_volname(struct fss_sc *sc_head,
377 for (sc = sc_head; sc; sc = sc->next) {
378 if (!strcmp(sc->volume_name, volname)) {
382 DEBUG(4, ("shadow copy with base volume %s not found\n", volname));
386 /* lookup is case-insensitive */
387 static struct fss_sc_smap *sc_smap_lookup(struct fss_sc_smap *smaps_head,
390 struct fss_sc_smap *sc_smap;
391 for (sc_smap = smaps_head; sc_smap; sc_smap = sc_smap->next) {
392 if (!strcasecmp_m(sc_smap->share_name, share)) {
396 DEBUG(4, ("shadow copy share mapping for %s not found\n", share));
400 void srv_fssa_cleanup(void)
402 talloc_free(fss_global.db_path);
403 talloc_free(fss_global.mem_ctx);
404 ZERO_STRUCT(fss_global);
407 NTSTATUS srv_fssa_start(struct messaging_context *msg_ctx)
410 fss_global.mem_ctx = talloc_named_const(NULL, 0,
411 "parent fss rpc server ctx");
412 if (fss_global.mem_ctx == NULL) {
413 return NT_STATUS_NO_MEMORY;
416 fss_global.db_path = lock_path(FSS_DB_NAME);
417 if (fss_global.db_path == NULL) {
418 talloc_free(fss_global.mem_ctx);
419 return NT_STATUS_NO_MEMORY;
422 fss_global.min_vers = FSRVP_RPC_VERSION_1;
423 fss_global.max_vers = FSRVP_RPC_VERSION_1;
425 * The server MUST populate the GlobalShadowCopySetTable with the
426 * ShadowCopySet entries read from the configuration store.
428 if (lp_parm_bool(GLOBAL_SECTION_SNUM, "fss", "prune stale", false)) {
429 fss_prune_stale(msg_ctx, fss_global.db_path);
432 status = fss_state_retrieve(fss_global.mem_ctx, &fss_global.sc_sets,
433 &fss_global.sc_sets_count,
436 if (!NT_STATUS_IS_OK(status)) {
437 DEBUG(1, ("failed to retrieve fss server state: %s\n",
444 * Determine whether to process an FSRVP operation from connected user @p.
445 * Windows checks for Administrators or Backup Operators group membership. We
446 * also allow for the SEC_PRIV_BACKUP privilege.
448 static bool fss_permitted(struct pipes_struct *p)
450 if (p->session_info->unix_token->uid == sec_initial_uid()) {
451 DEBUG(6, ("Granting FSRVP op, user started smbd\n"));
455 if (nt_token_check_sid(&global_sid_Builtin_Administrators,
456 p->session_info->security_token)) {
457 DEBUG(6, ("Granting FSRVP op, administrators group member\n"));
460 if (nt_token_check_sid(&global_sid_Builtin_Backup_Operators,
461 p->session_info->security_token)) {
462 DEBUG(6, ("Granting FSRVP op, backup operators group member\n"));
465 if (security_token_has_privilege(p->session_info->security_token,
467 DEBUG(6, ("Granting FSRVP op, backup privilege present\n"));
471 DEBUG(2, ("FSRVP operation blocked due to lack of backup privilege "
472 "or Administrators/Backup Operators group membership\n"));
477 static void fss_seq_tout_handler(struct tevent_context *ev,
478 struct tevent_timer *te,
482 struct GUID *sc_set_id = NULL;
483 struct fss_sc_set *sc_set;
486 * MS-FSRVP: 3.1.5 Timer Events
487 * Message Sequence Timer elapses: When the Message Sequence Timer
488 * elapses, the server MUST delete the ShadowCopySet in the
489 * GlobalShadowCopySetTable where ShadowCopySet.Status is not equal to
490 * "Recovered", ContextSet MUST be set to FALSE, and the ShadowCopySet
491 * object MUST be freed.
493 DEBUG(2, ("FSRVP msg seq timeout fired\n"));
495 if (private_data == NULL) {
496 DEBUG(4, ("timeout without sc_set\n"));
500 sc_set_id = talloc_get_type_abort(private_data, struct GUID);
501 sc_set = sc_set_lookup(fss_global.sc_sets, sc_set_id);
502 if (sc_set == NULL) {
503 DEBUG(0, ("timeout for unknown sc_set\n"));
505 } else if ((sc_set->state == FSS_SC_EXPOSED)
506 || (sc_set->state == FSS_SC_RECOVERED)) {
507 DEBUG(2, ("timeout for finished sc_set %s\n", sc_set->id_str));
510 DEBUG(2, ("cleaning up sc_set %s\n", sc_set->id_str));
511 SMB_ASSERT(fss_global.sc_sets_count > 0);
512 DLIST_REMOVE(fss_global.sc_sets, sc_set);
513 fss_global.sc_sets_count--;
517 fss_global.ctx_set = false;
518 fss_global.seq_tmr = NULL;
519 talloc_free(sc_set_id);
522 static void fss_seq_tout_set(TALLOC_CTX *mem_ctx,
524 struct fss_sc_set *sc_set,
525 struct tevent_timer **tmr_out)
527 struct tevent_timer *tmr;
528 struct GUID *sc_set_id = NULL;
531 /* allow changes to timeout for testing/debugging purposes */
532 tout = lp_parm_int(GLOBAL_SECTION_SNUM, "fss",
533 "sequence timeout", timeout_s);
535 DEBUG(2, ("FSRVP message sequence timeout disabled\n"));
541 /* don't use talloc_memdup(), need explicit type for callback */
542 sc_set_id = talloc(mem_ctx, struct GUID);
543 if (sc_set_id == NULL) {
544 smb_panic("no memory");
546 memcpy(sc_set_id, &sc_set->id, sizeof(*sc_set_id));
549 tmr = tevent_add_timer(server_event_context(),
551 timeval_current_ofs(tout, 0),
552 fss_seq_tout_handler, sc_set_id);
554 talloc_free(sc_set_id);
555 smb_panic("no memory");
561 uint32_t _fss_GetSupportedVersion(struct pipes_struct *p,
562 struct fss_GetSupportedVersion *r)
564 if (!fss_permitted(p)) {
565 return HRES_ERROR_V(HRES_E_ACCESSDENIED);
568 *r->out.MinVersion = fss_global.min_vers;
569 *r->out.MaxVersion = fss_global.max_vers;
574 uint32_t _fss_SetContext(struct pipes_struct *p,
575 struct fss_SetContext *r)
577 if (!fss_permitted(p)) {
578 return HRES_ERROR_V(HRES_E_ACCESSDENIED);
581 /* ATTR_AUTO_RECOVERY flag can be applied to any */
582 switch (r->in.Context & (~ATTR_AUTO_RECOVERY)) {
583 case FSRVP_CTX_BACKUP:
584 DEBUG(6, ("fss ctx set backup\n"));
586 case FSRVP_CTX_FILE_SHARE_BACKUP:
587 DEBUG(6, ("fss ctx set file share backup\n"));
589 case FSRVP_CTX_NAS_ROLLBACK:
590 DEBUG(6, ("fss ctx set nas rollback\n"));
592 case FSRVP_CTX_APP_ROLLBACK:
593 DEBUG(6, ("fss ctx set app rollback\n"));
596 DEBUG(0, ("invalid fss ctx set value: 0x%x\n", r->in.Context));
597 return HRES_ERROR_V(HRES_E_INVALIDARG);
598 break; /* not reached */
601 fss_global.ctx_set = true;
602 fss_global.cur_ctx = r->in.Context;
604 TALLOC_FREE(fss_global.seq_tmr); /* kill timer if running */
605 fss_seq_tout_set(fss_global.mem_ctx, 180, NULL, &fss_global.seq_tmr);
607 fss_global.cur_ctx = r->in.Context;
612 static bool sc_set_active(struct fss_sc_set *sc_set_head)
615 struct fss_sc_set *sc_set;
617 for (sc_set = sc_set_head; sc_set; sc_set = sc_set->next) {
618 if ((sc_set->state != FSS_SC_EXPOSED)
619 && (sc_set->state != FSS_SC_RECOVERED)) {
627 uint32_t _fss_StartShadowCopySet(struct pipes_struct *p,
628 struct fss_StartShadowCopySet *r)
630 struct fss_sc_set *sc_set;
633 if (!fss_permitted(p)) {
634 ret = HRES_ERROR_V(HRES_E_ACCESSDENIED);
638 if (!fss_global.ctx_set) {
639 DEBUG(3, ("invalid sequence: start sc set requested without "
640 "prior context set\n"));
641 ret = FSRVP_E_BAD_STATE;
646 * At any given time, Windows servers allow only one shadow copy set to
647 * be going through the creation process.
649 if (sc_set_active(fss_global.sc_sets)) {
650 DEBUG(3, ("StartShadowCopySet called while in progress\n"));
651 ret = FSRVP_E_SHADOW_COPY_SET_IN_PROGRESS;
655 /* stop msg seq timer */
656 TALLOC_FREE(fss_global.seq_tmr);
658 sc_set = talloc_zero(fss_global.mem_ctx, struct fss_sc_set);
659 if (sc_set == NULL) {
660 ret = HRES_ERROR_V(HRES_E_OUTOFMEMORY);
661 goto err_tmr_restart;
664 sc_set->id = GUID_random(); /* Windows servers ignore client ids */
665 sc_set->id_str = GUID_string(sc_set, &sc_set->id);
666 if (sc_set->id_str == NULL) {
667 ret = HRES_ERROR_V(HRES_E_OUTOFMEMORY);
668 goto err_sc_set_free;
670 sc_set->state = FSS_SC_STARTED;
671 sc_set->context = fss_global.cur_ctx;
672 DLIST_ADD_END(fss_global.sc_sets, sc_set);
673 fss_global.sc_sets_count++;
674 DEBUG(6, ("%s: shadow-copy set %u added\n",
675 sc_set->id_str, fss_global.sc_sets_count));
677 /* start msg seq timer */
678 fss_seq_tout_set(fss_global.mem_ctx, 180, sc_set, &fss_global.seq_tmr);
680 r->out.pShadowCopySetId = &sc_set->id;
687 fss_seq_tout_set(fss_global.mem_ctx, 180, NULL, &fss_global.seq_tmr);
692 static uint32_t map_share_name(struct fss_sc_smap *sc_smap,
693 const struct fss_sc *sc)
695 bool hidden_base = false;
697 if (*(sc_smap->share_name + strlen(sc_smap->share_name) - 1) == '$') {
699 * If MappedShare.ShareName ends with a $ character (meaning
700 * that the share is hidden), then the exposed share name will
701 * have the $ suffix appended.
702 * FIXME: turns out Windows doesn't do this, contrary to docs
707 sc_smap->sc_share_name = talloc_asprintf(sc_smap, "%s@{%s}%s",
710 hidden_base ? "$" : "");
711 if (sc_smap->sc_share_name == NULL) {
712 return HRES_ERROR_V(HRES_E_OUTOFMEMORY);
718 static uint32_t map_share_comment(struct fss_sc_smap *sc_smap,
719 const struct fss_sc *sc)
723 time_str = http_timestring(sc_smap, sc->create_ts);
724 if (time_str == NULL) {
725 return HRES_ERROR_V(HRES_E_OUTOFMEMORY);
728 sc_smap->sc_share_comment = talloc_asprintf(sc_smap, "Shadow copy of %s taken %s",
729 sc_smap->share_name, time_str);
730 if (sc_smap->sc_share_comment == NULL) {
731 return HRES_ERROR_V(HRES_E_OUTOFMEMORY);
737 uint32_t _fss_AddToShadowCopySet(struct pipes_struct *p,
738 struct fss_AddToShadowCopySet *r)
741 struct fss_sc_set *sc_set;
743 struct fss_sc_smap *sc_smap;
749 struct connection_struct *conn;
751 TALLOC_CTX *frame = talloc_stackframe();
753 if (!fss_permitted(p)) {
754 ret = HRES_ERROR_V(HRES_E_ACCESSDENIED);
758 sc_set = sc_set_lookup(fss_global.sc_sets, &r->in.ShadowCopySetId);
759 if (sc_set == NULL) {
760 ret = HRES_ERROR_V(HRES_E_INVALIDARG);
764 status = fss_unc_parse(frame, r->in.ShareName, NULL, &share);
765 if (!NT_STATUS_IS_OK(status)) {
766 ret = fss_ntstatus_map(status);
770 snum = find_service(frame, share, &service);
771 if ((snum == -1) || (service == NULL)) {
772 DEBUG(0, ("share at %s not found\n", r->in.ShareName));
773 ret = HRES_ERROR_V(HRES_E_INVALIDARG);
777 path_name = lp_path(frame, snum);
778 if (path_name == NULL) {
779 ret = HRES_ERROR_V(HRES_E_OUTOFMEMORY);
783 status = fss_vfs_conn_create(frame, server_event_context(),
784 p->msg_ctx, p->session_info, snum, &conn);
785 if (!NT_STATUS_IS_OK(status)) {
786 ret = HRES_ERROR_V(HRES_E_ACCESSDENIED);
789 if (!become_user_by_session(conn, p->session_info)) {
790 DEBUG(0, ("failed to become user\n"));
791 fss_vfs_conn_destroy(conn);
792 ret = HRES_ERROR_V(HRES_E_ACCESSDENIED);
796 status = SMB_VFS_SNAP_CHECK_PATH(conn, frame, path_name, &base_vol);
798 fss_vfs_conn_destroy(conn);
799 if (!NT_STATUS_IS_OK(status)) {
800 ret = FSRVP_E_NOT_SUPPORTED;
804 if ((sc_set->state != FSS_SC_STARTED)
805 && (sc_set->state != FSS_SC_ADDED)) {
806 ret = FSRVP_E_BAD_STATE;
810 /* stop msg seq timer */
811 TALLOC_FREE(fss_global.seq_tmr);
814 * server MUST look up the ShadowCopy in ShadowCopySet.ShadowCopyList
815 * where ShadowCopy.VolumeName matches the file store on which the
816 * share identified by ShareName is hosted. If an entry is found, the
817 * server MUST fail the call with FSRVP_E_OBJECT_ALREADY_EXISTS.
818 * If no entry is found, the server MUST create a new ShadowCopy
820 * XXX Windows appears to allow multiple mappings for the same vol!
822 sc = sc_lookup_volname(sc_set->scs, base_vol);
824 ret = FSRVP_E_OBJECT_ALREADY_EXISTS;
825 goto err_tmr_restart;
828 sc = talloc_zero(sc_set, struct fss_sc);
830 ret = HRES_ERROR_V(HRES_E_OUTOFMEMORY);
831 goto err_tmr_restart;
833 talloc_steal(sc, base_vol);
834 sc->volume_name = base_vol;
836 sc->create_ts = time(NULL);
838 sc->id = GUID_random(); /* Windows servers ignore client ids */
839 sc->id_str = GUID_string(sc, &sc->id);
840 if (sc->id_str == NULL) {
841 ret = HRES_ERROR_V(HRES_E_OUTOFMEMORY);
845 sc_smap = talloc_zero(sc, struct fss_sc_smap);
846 if (sc_smap == NULL) {
847 ret = HRES_ERROR_V(HRES_E_OUTOFMEMORY);
851 talloc_steal(sc_smap, service);
852 sc_smap->share_name = service;
853 sc_smap->is_exposed = false;
855 * generate the sc_smap share name now. It is a unique identifier for
856 * the smap used as a tdb key for state storage.
858 ret = map_share_name(sc_smap, sc);
863 /* add share map to shadow-copy */
864 DLIST_ADD_END(sc->smaps, sc_smap);
866 /* add shadow-copy to shadow-copy set */
867 DLIST_ADD_END(sc_set->scs, sc);
869 DEBUG(4, ("added volume %s to shadow copy set with GUID %s\n",
870 sc->volume_name, sc_set->id_str));
872 /* start the Message Sequence Timer with timeout of 1800 seconds */
873 fss_seq_tout_set(fss_global.mem_ctx, 1800, sc_set, &fss_global.seq_tmr);
875 sc_set->state = FSS_SC_ADDED;
876 r->out.pShadowCopyId = &sc->id;
884 fss_seq_tout_set(fss_global.mem_ctx, 180, sc_set, &fss_global.seq_tmr);
890 static NTSTATUS commit_sc_with_conn(TALLOC_CTX *mem_ctx,
891 struct tevent_context *ev,
892 struct messaging_context *msg_ctx,
893 struct auth_session_info *session_info,
898 TALLOC_CTX *frame = talloc_stackframe();
901 struct connection_struct *conn;
905 snum = find_service(frame, sc->smaps->share_name, &service);
906 if ((snum == -1) || (service == NULL)) {
907 DEBUG(0, ("share at %s not found\n", sc->smaps->share_name));
909 return NT_STATUS_UNSUCCESSFUL;
912 status = fss_vfs_conn_create(frame,
913 ev, msg_ctx, session_info,
915 if (!NT_STATUS_IS_OK(status)) {
920 if (!become_user_by_session(conn, session_info)) {
921 DEBUG(0, ("failed to become user\n"));
922 fss_vfs_conn_destroy(conn);
924 return NT_STATUS_ACCESS_DENIED;
926 rw = ((sc->sc_set->context & ATTR_AUTO_RECOVERY) == ATTR_AUTO_RECOVERY);
927 status = SMB_VFS_SNAP_CREATE(conn, mem_ctx,
930 base_path, snap_path);
932 fss_vfs_conn_destroy(conn);
933 if (!NT_STATUS_IS_OK(status)) {
934 DEBUG(0, ("snap create failed: %s\n", nt_errstr(status)));
943 uint32_t _fss_CommitShadowCopySet(struct pipes_struct *p,
944 struct fss_CommitShadowCopySet *r)
946 struct fss_sc_set *sc_set;
948 uint32_t commit_count;
950 NTSTATUS saved_status;
951 TALLOC_CTX *frame = talloc_stackframe();
953 if (!fss_permitted(p)) {
954 status = NT_STATUS_ACCESS_DENIED;
958 sc_set = sc_set_lookup(fss_global.sc_sets, &r->in.ShadowCopySetId);
959 if (sc_set == NULL) {
960 status = NT_STATUS_INVALID_PARAMETER;
964 if (sc_set->state != FSS_SC_ADDED) {
965 status = NT_STATUS_INVALID_SERVER_STATE;
969 /* stop Message Sequence Timer */
970 TALLOC_FREE(fss_global.seq_tmr);
971 sc_set->state = FSS_SC_CREATING;
973 saved_status = NT_STATUS_OK;
974 for (sc = sc_set->scs; sc; sc = sc->next) {
977 status = commit_sc_with_conn(frame, server_event_context(),
978 p->msg_ctx, p->session_info, sc,
979 &base_path, &snap_path);
980 if (!NT_STATUS_IS_OK(status)) {
981 DEBUG(0, ("snap create failed for shadow copy of "
982 "%s\n", sc->volume_name));
983 /* dispatch all scs in set, but retain last error */
984 saved_status = status;
987 /* XXX set timeout r->in.TimeOutInMilliseconds */
989 DEBUG(10, ("good snap create %d\n",
991 sc->sc_path = talloc_steal(sc, snap_path);
993 if (!NT_STATUS_IS_OK(saved_status)) {
994 status = saved_status;
995 goto err_state_revert;
998 sc_set->state = FSS_SC_COMMITED;
1000 status = fss_state_store(fss_global.mem_ctx, fss_global.sc_sets,
1001 fss_global.sc_sets_count,
1002 fss_global.db_path);
1004 if (!NT_STATUS_IS_OK(status)) {
1005 DEBUG(1, ("failed to store fss server state: %s\n",
1006 nt_errstr(status)));
1009 fss_seq_tout_set(fss_global.mem_ctx, 180, sc_set,
1010 &fss_global.seq_tmr);
1015 sc_set->state = FSS_SC_ADDED;
1016 fss_seq_tout_set(fss_global.mem_ctx, 180, sc_set,
1017 &fss_global.seq_tmr);
1020 return fss_ntstatus_map(status);
1023 static sbcErr fss_conf_get_share_def(struct smbconf_ctx *fconf_ctx,
1024 struct smbconf_ctx *rconf_ctx,
1025 TALLOC_CTX *mem_ctx,
1027 struct smbconf_service **service_def)
1030 struct smbconf_service *def;
1032 *service_def = NULL;
1033 cerr = smbconf_get_share(fconf_ctx, mem_ctx, share, &def);
1034 if (SBC_ERROR_IS_OK(cerr)) {
1039 cerr = smbconf_get_share(rconf_ctx, mem_ctx, share, &def);
1040 if (SBC_ERROR_IS_OK(cerr)) {
1048 * Expose a new share using libsmbconf, cloning the existing configuration
1049 * from the base share. The base share may be defined in either the registry
1051 * XXX this is called as root
1053 static uint32_t fss_sc_expose(struct smbconf_ctx *fconf_ctx,
1054 struct smbconf_ctx *rconf_ctx,
1055 TALLOC_CTX *mem_ctx,
1058 struct fss_sc_smap *sc_smap;
1061 for (sc_smap = sc->smaps; sc_smap; sc_smap = sc_smap->next) {
1063 struct smbconf_service *base_service = NULL;
1064 struct security_descriptor *sd;
1067 cerr = fss_conf_get_share_def(fconf_ctx, rconf_ctx, mem_ctx,
1068 sc_smap->share_name, &base_service);
1069 if (!SBC_ERROR_IS_OK(cerr)) {
1070 DEBUG(0, ("failed to get base share %s definition: "
1071 "%s\n", sc_smap->share_name,
1072 sbcErrorString(cerr)));
1073 err = HRES_ERROR_V(HRES_E_FAIL);
1077 /* smap share name already defined when added */
1078 err = map_share_comment(sc_smap, sc);
1080 DEBUG(0, ("failed to map share comment\n"));
1084 base_service->name = sc_smap->sc_share_name;
1086 cerr = smbconf_create_set_share(rconf_ctx, base_service);
1087 if (!SBC_ERROR_IS_OK(cerr)) {
1088 DEBUG(0, ("failed to create share %s: %s\n",
1089 base_service->name, sbcErrorString(cerr)));
1090 err = HRES_ERROR_V(HRES_E_FAIL);
1093 cerr = smbconf_set_parameter(rconf_ctx, sc_smap->sc_share_name,
1094 "path", sc->sc_path);
1095 if (!SBC_ERROR_IS_OK(cerr)) {
1096 DEBUG(0, ("failed to set path param: %s\n",
1097 sbcErrorString(cerr)));
1098 err = HRES_ERROR_V(HRES_E_FAIL);
1101 if (sc_smap->sc_share_comment != NULL) {
1102 cerr = smbconf_set_parameter(rconf_ctx,
1103 sc_smap->sc_share_name,
1105 sc_smap->sc_share_comment);
1106 if (!SBC_ERROR_IS_OK(cerr)) {
1107 DEBUG(0, ("failed to set comment param: %s\n",
1108 sbcErrorString(cerr)));
1109 err = HRES_ERROR_V(HRES_E_FAIL);
1113 talloc_free(base_service);
1116 * Obtain the base share SD, which also needs to be cloned.
1117 * Share SDs are stored in share_info.tdb, so are not covered by
1118 * the registry transaction.
1119 * The base share SD should be cloned at the time of exposure,
1120 * rather than when the snapshot is taken. This matches Windows
1121 * Server 2012 behaviour.
1123 sd = get_share_security(mem_ctx, sc_smap->share_name, &sd_size);
1125 DEBUG(2, ("no share SD to clone for %s snapshot\n",
1126 sc_smap->share_name));
1129 ok = set_share_security(sc_smap->sc_share_name, sd);
1132 DEBUG(0, ("failed to set %s share SD\n",
1133 sc_smap->sc_share_name));
1134 err = HRES_ERROR_V(HRES_E_FAIL);
1143 uint32_t _fss_ExposeShadowCopySet(struct pipes_struct *p,
1144 struct fss_ExposeShadowCopySet *r)
1147 struct fss_sc_set *sc_set;
1150 struct smbconf_ctx *fconf_ctx;
1151 struct smbconf_ctx *rconf_ctx;
1154 TALLOC_CTX *frame = talloc_stackframe();
1156 if (!fss_permitted(p)) {
1157 ret = HRES_ERROR_V(HRES_E_ACCESSDENIED);
1161 sc_set = sc_set_lookup(fss_global.sc_sets, &r->in.ShadowCopySetId);
1162 if (sc_set == NULL) {
1163 ret = HRES_ERROR_V(HRES_E_INVALIDARG);
1167 if (sc_set->state != FSS_SC_COMMITED) {
1168 ret = FSRVP_E_BAD_STATE;
1172 /* stop message sequence timer */
1173 TALLOC_FREE(fss_global.seq_tmr);
1176 * Prepare to clone the base share definition for the snapshot share.
1177 * Create both registry and file conf contexts, as the base share
1178 * definition may be located in either. The snapshot share definition
1179 * is always written to the registry.
1181 cerr = smbconf_init(frame, &rconf_ctx, "registry");
1182 if (!SBC_ERROR_IS_OK(cerr)) {
1183 DEBUG(0, ("failed registry smbconf init: %s\n",
1184 sbcErrorString(cerr)));
1185 ret = HRES_ERROR_V(HRES_E_FAIL);
1186 goto err_tmr_restart;
1188 fconf_path = talloc_asprintf(frame, "file:%s", get_dyn_CONFIGFILE());
1189 if (fconf_path == NULL) {
1190 ret = HRES_ERROR_V(HRES_E_OUTOFMEMORY);
1191 goto err_tmr_restart;
1193 cerr = smbconf_init(frame, &fconf_ctx, fconf_path);
1194 if (!SBC_ERROR_IS_OK(cerr)) {
1195 DEBUG(0, ("failed %s smbconf init: %s\n",
1196 fconf_path, sbcErrorString(cerr)));
1197 ret = HRES_ERROR_V(HRES_E_FAIL);
1198 goto err_tmr_restart;
1201 /* registry IO must be done as root */
1203 cerr = smbconf_transaction_start(rconf_ctx);
1204 if (!SBC_ERROR_IS_OK(cerr)) {
1205 DEBUG(0, ("error starting transaction: %s\n",
1206 sbcErrorString(cerr)));
1207 ret = HRES_ERROR_V(HRES_E_FAIL);
1209 goto err_tmr_restart;
1212 for (sc = sc_set->scs; sc; sc = sc->next) {
1213 ret = fss_sc_expose(fconf_ctx, rconf_ctx, frame, sc);
1215 DEBUG(0,("failed to expose shadow copy of %s\n",
1221 cerr = smbconf_transaction_commit(rconf_ctx);
1222 if (!SBC_ERROR_IS_OK(cerr)) {
1223 DEBUG(0, ("error committing transaction: %s\n",
1224 sbcErrorString(cerr)));
1225 ret = HRES_ERROR_V(HRES_E_FAIL);
1230 messaging_send_all(p->msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0);
1231 for (sc = sc_set->scs; sc; sc = sc->next) {
1232 struct fss_sc_smap *sm;
1233 for (sm = sc->smaps; sm; sm = sm->next)
1234 sm->is_exposed = true;
1236 sc_set->state = FSS_SC_EXPOSED;
1238 status = fss_state_store(fss_global.mem_ctx, fss_global.sc_sets,
1239 fss_global.sc_sets_count, fss_global.db_path);
1241 if (!NT_STATUS_IS_OK(status)) {
1242 DEBUG(1, ("failed to store fss server state: %s\n",
1243 nt_errstr(status)));
1245 /* start message sequence timer */
1246 fss_seq_tout_set(fss_global.mem_ctx, 180, sc_set, &fss_global.seq_tmr);
1251 smbconf_transaction_cancel(rconf_ctx);
1254 fss_seq_tout_set(fss_global.mem_ctx, 180, sc_set, &fss_global.seq_tmr);
1260 uint32_t _fss_RecoveryCompleteShadowCopySet(struct pipes_struct *p,
1261 struct fss_RecoveryCompleteShadowCopySet *r)
1264 struct fss_sc_set *sc_set;
1266 if (!fss_permitted(p)) {
1267 return HRES_ERROR_V(HRES_E_ACCESSDENIED);
1270 sc_set = sc_set_lookup(fss_global.sc_sets, &r->in.ShadowCopySetId);
1271 if (sc_set == NULL) {
1272 return HRES_ERROR_V(HRES_E_INVALIDARG);
1275 if (sc_set->state != FSS_SC_EXPOSED) {
1276 return FSRVP_E_BAD_STATE;
1279 /* stop msg sequence timer */
1280 TALLOC_FREE(fss_global.seq_tmr);
1282 if (sc_set->context & ATTR_NO_AUTO_RECOVERY) {
1283 /* TODO set read-only */
1286 sc_set->state = FSS_SC_RECOVERED;
1287 fss_global.cur_ctx = 0;
1288 fss_global.ctx_set = false;
1291 status = fss_state_store(fss_global.mem_ctx, fss_global.sc_sets,
1292 fss_global.sc_sets_count, fss_global.db_path);
1294 if (!NT_STATUS_IS_OK(status)) {
1295 DEBUG(1, ("failed to store fss server state: %s\n",
1296 nt_errstr(status)));
1302 uint32_t _fss_AbortShadowCopySet(struct pipes_struct *p,
1303 struct fss_AbortShadowCopySet *r)
1306 struct fss_sc_set *sc_set;
1308 if (!fss_permitted(p)) {
1309 return HRES_ERROR_V(HRES_E_ACCESSDENIED);
1312 sc_set = sc_set_lookup(fss_global.sc_sets, &r->in.ShadowCopySetId);
1313 if (sc_set == NULL) {
1314 return HRES_ERROR_V(HRES_E_INVALIDARG);
1317 DEBUG(6, ("%s: aborting shadow-copy set\n", sc_set->id_str));
1319 if ((sc_set->state == FSS_SC_COMMITED)
1320 || (sc_set->state == FSS_SC_EXPOSED)
1321 || (sc_set->state == FSS_SC_RECOVERED)) {
1325 if (sc_set->state == FSS_SC_CREATING) {
1326 return FSRVP_E_BAD_STATE;
1329 DLIST_REMOVE(fss_global.sc_sets, sc_set);
1330 talloc_free(sc_set);
1331 fss_global.sc_sets_count--;
1333 status = fss_state_store(fss_global.mem_ctx, fss_global.sc_sets,
1334 fss_global.sc_sets_count, fss_global.db_path);
1336 if (!NT_STATUS_IS_OK(status)) {
1337 DEBUG(1, ("failed to store fss server state: %s\n",
1338 nt_errstr(status)));
1344 uint32_t _fss_IsPathSupported(struct pipes_struct *p,
1345 struct fss_IsPathSupported *r)
1351 struct connection_struct *conn;
1353 TALLOC_CTX *frame = talloc_stackframe();
1355 if (!fss_permitted(p)) {
1357 return HRES_ERROR_V(HRES_E_ACCESSDENIED);
1360 status = fss_unc_parse(frame, r->in.ShareName, NULL, &share);
1361 if (!NT_STATUS_IS_OK(status)) {
1363 return fss_ntstatus_map(status);
1366 snum = find_service(frame, share, &service);
1367 if ((snum == -1) || (service == NULL)) {
1368 DEBUG(0, ("share at %s not found\n", r->in.ShareName));
1370 return HRES_ERROR_V(HRES_E_INVALIDARG);
1373 status = fss_vfs_conn_create(frame, server_event_context(),
1374 p->msg_ctx, p->session_info, snum, &conn);
1375 if (!NT_STATUS_IS_OK(status)) {
1377 return HRES_ERROR_V(HRES_E_ACCESSDENIED);
1379 if (!become_user_by_session(conn, p->session_info)) {
1380 DEBUG(0, ("failed to become user\n"));
1381 fss_vfs_conn_destroy(conn);
1383 return HRES_ERROR_V(HRES_E_ACCESSDENIED);
1385 status = SMB_VFS_SNAP_CHECK_PATH(conn, frame,
1386 lp_path(frame, snum),
1389 fss_vfs_conn_destroy(conn);
1390 if (!NT_STATUS_IS_OK(status)) {
1392 return FSRVP_E_NOT_SUPPORTED;
1395 *r->out.OwnerMachineName = lp_netbios_name();
1396 *r->out.SupportedByThisProvider = 1;
1401 uint32_t _fss_IsPathShadowCopied(struct pipes_struct *p,
1402 struct fss_IsPathShadowCopied *r)
1404 if (!fss_permitted(p)) {
1405 return HRES_ERROR_V(HRES_E_ACCESSDENIED);
1408 /* not yet supported */
1409 return FSRVP_E_NOT_SUPPORTED;
1412 uint32_t _fss_GetShareMapping(struct pipes_struct *p,
1413 struct fss_GetShareMapping *r)
1416 struct fss_sc_set *sc_set;
1418 struct fss_sc_smap *sc_smap;
1420 struct fssagent_share_mapping_1 *sm_out;
1421 TALLOC_CTX *frame = talloc_stackframe();
1423 if (!fss_permitted(p)) {
1425 return HRES_ERROR_V(HRES_E_ACCESSDENIED);
1428 sc_set = sc_set_lookup(fss_global.sc_sets, &r->in.ShadowCopySetId);
1429 if (sc_set == NULL) {
1431 return HRES_ERROR_V(HRES_E_INVALIDARG);
1435 * If ShadowCopySet.Status is not "Exposed", the server SHOULD<9> fail
1436 * the call with FSRVP_E_BAD_STATE.
1437 * <9> If ShadowCopySet.Status is "Started", "Added",
1438 * "CreationInProgress", or "Committed", Windows Server 2012 FSRVP
1439 * servers return an error value of 0x80042311.
1441 if ((sc_set->state == FSS_SC_STARTED)
1442 || (sc_set->state == FSS_SC_ADDED)
1443 || (sc_set->state == FSS_SC_CREATING)
1444 || (sc_set->state == FSS_SC_COMMITED)) {
1446 return 0x80042311; /* documented magic value */
1449 sc = sc_lookup(sc_set->scs, &r->in.ShadowCopyId);
1452 return HRES_ERROR_V(HRES_E_INVALIDARG);
1455 status = fss_unc_parse(frame, r->in.ShareName, NULL, &share);
1456 if (!NT_STATUS_IS_OK(status)) {
1458 return fss_ntstatus_map(status);
1461 sc_smap = sc_smap_lookup(sc->smaps, share);
1462 if (sc_smap == NULL) {
1464 return HRES_ERROR_V(HRES_E_INVALIDARG);
1467 if (r->in.Level != 1) {
1469 return HRES_ERROR_V(HRES_E_INVALIDARG);
1472 sm_out = talloc_zero(p->mem_ctx, struct fssagent_share_mapping_1);
1473 if (sm_out == NULL) {
1475 return HRES_ERROR_V(HRES_E_OUTOFMEMORY);
1477 sm_out->ShadowCopySetId = sc_set->id;
1478 sm_out->ShadowCopyId = sc->id;
1479 sm_out->ShareNameUNC = talloc_asprintf(sm_out, "\\\\%s\\%s",
1481 sc_smap->share_name);
1482 if (sm_out->ShareNameUNC == NULL) {
1483 talloc_free(sm_out);
1485 return HRES_ERROR_V(HRES_E_OUTOFMEMORY);
1487 sm_out->ShadowCopyShareName = sc_smap->sc_share_name;
1488 unix_to_nt_time(&sm_out->tstamp, sc->create_ts);
1489 r->out.ShareMapping->ShareMapping1 = sm_out;
1492 /* reset msg sequence timer */
1493 TALLOC_FREE(fss_global.seq_tmr);
1494 fss_seq_tout_set(fss_global.mem_ctx, 1800, sc_set, &fss_global.seq_tmr);
1499 static NTSTATUS sc_smap_unexpose(struct messaging_context *msg_ctx,
1500 struct fss_sc_smap *sc_smap, bool delete_all)
1503 struct smbconf_ctx *conf_ctx;
1505 bool is_modified = false;
1506 TALLOC_CTX *frame = talloc_stackframe();
1508 cerr = smbconf_init(frame, &conf_ctx, "registry");
1509 if (!SBC_ERROR_IS_OK(cerr)) {
1510 DEBUG(0, ("failed registry smbconf init: %s\n",
1511 sbcErrorString(cerr)));
1512 ret = NT_STATUS_UNSUCCESSFUL;
1516 /* registry IO must be done as root */
1519 cerr = smbconf_transaction_start(conf_ctx);
1520 if (!SBC_ERROR_IS_OK(cerr)) {
1521 DEBUG(0, ("error starting transaction: %s\n",
1522 sbcErrorString(cerr)));
1523 ret = NT_STATUS_UNSUCCESSFUL;
1528 struct fss_sc_smap *sc_map_next = sc_smap->next;
1529 if (!smbconf_share_exists(conf_ctx, sc_smap->sc_share_name)) {
1530 DEBUG(2, ("no such share: %s\n", sc_smap->sc_share_name));
1535 sc_smap = sc_map_next;
1539 cerr = smbconf_delete_share(conf_ctx, sc_smap->sc_share_name);
1540 if (!SBC_ERROR_IS_OK(cerr)) {
1541 DEBUG(0, ("error deleting share: %s\n",
1542 sbcErrorString(cerr)));
1543 ret = NT_STATUS_UNSUCCESSFUL;
1547 sc_smap->is_exposed = false;
1549 sc_smap = sc_map_next;
1551 sc_smap = NULL; /* only process single sc_map entry */
1555 cerr = smbconf_transaction_commit(conf_ctx);
1556 if (!SBC_ERROR_IS_OK(cerr)) {
1557 DEBUG(0, ("error committing transaction: %s\n",
1558 sbcErrorString(cerr)));
1559 ret = NT_STATUS_UNSUCCESSFUL;
1562 messaging_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0);
1570 talloc_free(conf_ctx);
1577 smbconf_transaction_cancel(conf_ctx);
1578 talloc_free(conf_ctx);
1584 uint32_t _fss_DeleteShareMapping(struct pipes_struct *p,
1585 struct fss_DeleteShareMapping *r)
1587 struct fss_sc_set *sc_set;
1589 struct fss_sc_smap *sc_smap;
1592 TALLOC_CTX *frame = talloc_stackframe();
1593 struct connection_struct *conn;
1597 if (!fss_permitted(p)) {
1598 status = NT_STATUS_ACCESS_DENIED;
1602 sc_set = sc_set_lookup(fss_global.sc_sets, &r->in.ShadowCopySetId);
1603 if (sc_set == NULL) {
1604 /* docs say HRES_E_INVALIDARG */
1605 status = NT_STATUS_OBJECTID_NOT_FOUND;
1609 if ((sc_set->state != FSS_SC_EXPOSED)
1610 && (sc_set->state != FSS_SC_RECOVERED)) {
1611 status = NT_STATUS_INVALID_SERVER_STATE;
1615 sc = sc_lookup(sc_set->scs, &r->in.ShadowCopyId);
1617 status = NT_STATUS_INVALID_PARAMETER;
1621 status = fss_unc_parse(frame, r->in.ShareName, NULL, &share);
1622 if (!NT_STATUS_IS_OK(status)) {
1626 sc_smap = sc_smap_lookup(sc->smaps, share);
1627 if (sc_smap == NULL) {
1628 status = NT_STATUS_INVALID_PARAMETER;
1632 status = sc_smap_unexpose(p->msg_ctx, sc_smap, false);
1633 if (!NT_STATUS_IS_OK(status)) {
1634 DEBUG(0, ("failed to remove share %s: %s\n",
1635 sc_smap->sc_share_name, nt_errstr(status)));
1639 messaging_send_all(p->msg_ctx, MSG_SMB_FORCE_TDIS,
1640 sc_smap->sc_share_name,
1641 strlen(sc_smap->sc_share_name) + 1);
1643 if (sc->smaps_count > 1) {
1644 /* do not delete the underlying snapshot - still in use */
1645 status = NT_STATUS_OK;
1649 snum = find_service(frame, sc_smap->share_name, &service);
1650 if ((snum == -1) || (service == NULL)) {
1651 DEBUG(0, ("share at %s not found\n", sc_smap->share_name));
1652 status = NT_STATUS_UNSUCCESSFUL;
1656 status = fss_vfs_conn_create(frame, server_event_context(),
1657 p->msg_ctx, p->session_info, snum, &conn);
1658 if (!NT_STATUS_IS_OK(status)) {
1661 if (!become_user_by_session(conn, p->session_info)) {
1662 DEBUG(0, ("failed to become user\n"));
1663 status = NT_STATUS_ACCESS_DENIED;
1664 goto err_conn_destroy;
1667 status = SMB_VFS_SNAP_DELETE(conn, frame, sc->volume_name,
1670 if (!NT_STATUS_IS_OK(status)) {
1671 goto err_conn_destroy;
1674 /* XXX set timeout r->in.TimeOutInMilliseconds */
1675 DEBUG(6, ("good snap delete\n"));
1676 DLIST_REMOVE(sc->smaps, sc_smap);
1678 talloc_free(sc_smap);
1679 if (sc->smaps_count == 0) {
1680 DLIST_REMOVE(sc_set->scs, sc);
1681 sc_set->scs_count--;
1684 if (sc_set->scs_count == 0) {
1685 DLIST_REMOVE(fss_global.sc_sets, sc_set);
1686 fss_global.sc_sets_count--;
1687 talloc_free(sc_set);
1692 status = fss_state_store(fss_global.mem_ctx, fss_global.sc_sets,
1693 fss_global.sc_sets_count, fss_global.db_path);
1695 if (!NT_STATUS_IS_OK(status)) {
1696 DEBUG(1, ("failed to store fss server state: %s\n",
1697 nt_errstr(status)));
1700 status = NT_STATUS_OK;
1702 fss_vfs_conn_destroy(conn);
1705 return fss_ntstatus_map(status);
1708 uint32_t _fss_PrepareShadowCopySet(struct pipes_struct *p,
1709 struct fss_PrepareShadowCopySet *r)
1711 struct fss_sc_set *sc_set;
1713 if (!fss_permitted(p)) {
1714 return HRES_ERROR_V(HRES_E_ACCESSDENIED);
1717 sc_set = sc_set_lookup(fss_global.sc_sets, &r->in.ShadowCopySetId);
1718 if (sc_set == NULL) {
1719 return HRES_ERROR_V(HRES_E_INVALIDARG);
1722 if (sc_set->state != FSS_SC_ADDED) {
1723 return FSRVP_E_BAD_STATE;
1726 /* stop msg sequence timer */
1727 TALLOC_FREE(fss_global.seq_tmr);
1730 * Windows Server "8" Beta takes ~60s here, presumably flushing
1731 * everything to disk. We may want to do something similar.
1734 /* start msg sequence timer, 1800 on success */
1735 fss_seq_tout_set(fss_global.mem_ctx, 1800, sc_set, &fss_global.seq_tmr);