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"
23 #include "include/auth.h"
24 #include "../libcli/security/security.h"
25 #include "../libcli/util/hresult.h"
26 #include "../lib/smbconf/smbconf.h"
27 #include "smbd/proto.h"
28 #include "lib/smbconf/smbconf_init.h"
29 #include "librpc/gen_ndr/srv_fsrvp.h"
30 #include "srv_fss_private.h"
31 #include "srv_fss_agent.h"
34 #define DBGC_CLASS DBGC_RPC_SRV
36 static struct fss_global fss_global
;
38 /* errmap NTSTATUS->fsrvp */
42 } ntstatus_to_fsrvp_map
[] = {
43 {NT_STATUS_INVALID_SERVER_STATE
, FSRVP_E_BAD_STATE
},
44 {NT_STATUS_INVALID_DISPOSITION
, FSRVP_E_SHADOW_COPY_SET_IN_PROGRESS
},
45 {NT_STATUS_NOT_SUPPORTED
, FSRVP_E_NOT_SUPPORTED
},
46 {NT_STATUS_IO_TIMEOUT
, FSRVP_E_WAIT_TIMEOUT
},
47 {NT_STATUS_CANT_WAIT
, FSRVP_E_WAIT_FAILED
},
48 {NT_STATUS_OBJECTID_EXISTS
, FSRVP_E_OBJECT_ALREADY_EXISTS
},
49 {NT_STATUS_OBJECTID_NOT_FOUND
, FSRVP_E_OBJECT_NOT_FOUND
},
50 {NT_STATUS_OBJECT_NAME_INVALID
, FSRVP_E_BAD_ID
},
53 /* errmap NTSTATUS->hresult */
57 } ntstatus_to_hres_map
[] = {
58 {NT_STATUS_ACCESS_DENIED
, HRES_E_ACCESSDENIED
},
59 {NT_STATUS_INVALID_PARAMETER
, HRES_E_INVALIDARG
},
60 {NT_STATUS_NO_MEMORY
, HRES_E_OUTOFMEMORY
},
63 static uint32_t fss_ntstatus_map(NTSTATUS status
)
67 if (NT_STATUS_IS_OK(status
))
70 /* check fsrvp specific errors first */
71 for (i
= 0; i
< ARRAY_SIZE(ntstatus_to_fsrvp_map
); i
++) {
72 if (NT_STATUS_EQUAL(status
, ntstatus_to_fsrvp_map
[i
].status
)) {
73 return ntstatus_to_fsrvp_map
[i
].fsrvp_err
;
76 /* fall-back to generic hresult values */
77 for (i
= 0; i
< ARRAY_SIZE(ntstatus_to_hres_map
); i
++) {
78 if (NT_STATUS_EQUAL(status
, ntstatus_to_hres_map
[i
].status
)) {
79 return HRES_ERROR_V(ntstatus_to_hres_map
[i
].hres
);
83 return HRES_ERROR_V(HRES_E_FAIL
);
86 static NTSTATUS
fss_unc_parse(TALLOC_CTX
*mem_ctx
,
96 return NT_STATUS_INVALID_PARAMETER
;
99 s
= strstr_m(unc
, "\\\\");
101 return NT_STATUS_INVALID_PARAMETER
;
104 server
= talloc_strdup(mem_ctx
, s
+ 2);
105 if (server
== NULL
) {
106 return NT_STATUS_NO_MEMORY
;
108 s
= strchr_m(server
, '\\');
109 if ((s
== NULL
) || (s
== server
)) {
110 return NT_STATUS_INVALID_PARAMETER
;
115 s
= strchr_m(share
, '\\');
117 /* diskshadow.exe adds a trailing '\' to the share-name */
120 if (strlen(share
) == 0) {
121 return NT_STATUS_INVALID_PARAMETER
;
124 if (_server
!= NULL
) {
127 if (_share
!= NULL
) {
134 static NTSTATUS
fss_vfs_conn_create(TALLOC_CTX
*mem_ctx
,
135 struct tevent_context
*ev
,
136 struct messaging_context
*msg_ctx
,
137 struct auth_session_info
*session_info
,
139 struct connection_struct
**conn_out
);
140 static void fss_vfs_conn_destroy(struct connection_struct
*conn
);
142 /* test if system path exists */
143 static bool snap_path_exists(TALLOC_CTX
*ctx
, struct messaging_context
*msg_ctx
,
147 struct connection_struct
*conn
= NULL
;
148 struct smb_filename
*smb_fname
= NULL
;
149 char *service
= NULL
;
158 if ((sc
->smaps_count
== 0) || (sc
->sc_path
== NULL
)) {
162 share
= sc
->smaps
->share_name
;
163 snum
= find_service(ctx
, share
, &service
);
165 if ((snum
== -1) || (service
== NULL
)) {
169 status
= fss_vfs_conn_create(ctx
, server_event_context(),
170 msg_ctx
, NULL
, snum
, &conn
);
172 if(!NT_STATUS_IS_OK(status
)) {
176 smb_fname
= synthetic_smb_fname(service
, sc
->sc_path
, NULL
, NULL
);
177 if (smb_fname
== NULL
) {
181 ret
= SMB_VFS_STAT(conn
, smb_fname
);
182 if ((ret
== -1) && (errno
== ENOENT
)) {
188 fss_vfs_conn_destroy(conn
);
190 TALLOC_FREE(service
);
194 static NTSTATUS
sc_smap_unexpose(struct messaging_context
*msg_ctx
,
195 struct fss_sc_smap
*sc_smap
, bool delete_all
);
197 static NTSTATUS
fss_prune_stale(struct messaging_context
*msg_ctx
,
200 struct fss_sc_set
*sc_sets
;
201 uint32_t sc_sets_count
= 0;
202 struct fss_sc_set
*sc_set
;
203 struct fss_sc_smap
*prunable_sc_smaps
= NULL
;
204 bool is_modified
= false;
205 NTSTATUS status
= NT_STATUS_UNSUCCESSFUL
;
206 TALLOC_CTX
*ctx
= talloc_new(NULL
);
209 return NT_STATUS_NO_MEMORY
;
212 /* work with temporary state for simple cleanup on failure */
214 status
= fss_state_retrieve(ctx
, &sc_sets
, &sc_sets_count
, db_path
);
216 if (!NT_STATUS_IS_OK(status
)) {
217 DEBUG(1, ("failed to retrieve fss server state: %s\n",
222 /* walk the cache and pick up any entries to be deleted */
224 DEBUG(10, ("pruning shared shadow copies\n"));
227 struct fss_sc_set
*sc_set_next
= sc_set
->next
;
228 char *set_id
= GUID_string(ctx
, &sc_set
->id
);
229 if (set_id
== NULL
) {
230 status
= NT_STATUS_NO_MEMORY
;
233 DEBUGADD(10, ("\tprocessing shadow set id %s\n", set_id
));
236 struct fss_sc_smap
*sc_smap
;
237 struct fss_sc
*sc_next
= sc
->next
;
238 DEBUGADD(10, ("\tprocessing shadow copy path %s\n",
240 if (snap_path_exists(ctx
, msg_ctx
, sc
)) {
245 /* move missing snapshot state to purge list */
247 while (sc_smap
!= NULL
) {
248 struct fss_sc_smap
*smap_next
= sc_smap
->next
;
249 DLIST_REMOVE(sc
->smaps
, sc_smap
);
250 DLIST_ADD_END(prunable_sc_smaps
, sc_smap
,
251 struct fss_sc_smap
*);
256 DLIST_REMOVE(sc_set
->scs
, sc
);
261 if (sc_set
->scs_count
== 0) {
262 DLIST_REMOVE(sc_sets
, sc_set
);
265 sc_set
= sc_set_next
;
269 /* unexpose all shares in a single transaction */
270 status
= sc_smap_unexpose(msg_ctx
, prunable_sc_smaps
, true);
271 if (!NT_STATUS_IS_OK(status
)) {
272 /* exit without storing updated state */
277 status
= fss_state_store(ctx
, sc_sets
, sc_sets_count
, db_path
);
279 if (!NT_STATUS_IS_OK(status
)) {
280 DEBUG(1, ("pruning failed to store fss server state: %s\n",
285 status
= NT_STATUS_OK
;
291 static NTSTATUS
fss_vfs_conn_create(TALLOC_CTX
*mem_ctx
,
292 struct tevent_context
*ev
,
293 struct messaging_context
*msg_ctx
,
294 struct auth_session_info
*session_info
,
296 struct connection_struct
**conn_out
)
298 struct connection_struct
*conn
= NULL
;
301 status
= create_conn_struct(mem_ctx
, ev
, msg_ctx
, &conn
,
302 snum
, lp_path(mem_ctx
, snum
),
304 if (!NT_STATUS_IS_OK(status
)) {
305 DEBUG(0,("failed to create conn for vfs: %s\n",
310 status
= set_conn_force_user_group(conn
, snum
);
311 if (!NT_STATUS_IS_OK(status
)) {
312 DEBUG(0, ("failed set force user / group\n"));
321 SMB_VFS_DISCONNECT(conn
);
326 static void fss_vfs_conn_destroy(struct connection_struct
*conn
)
328 SMB_VFS_DISCONNECT(conn
);
332 static struct fss_sc_set
*sc_set_lookup(struct fss_sc_set
*sc_set_head
,
333 struct GUID
*sc_set_id
)
336 struct fss_sc_set
*sc_set
;
339 for (sc_set
= sc_set_head
; sc_set
; sc_set
= sc_set
->next
) {
340 if (GUID_equal(&sc_set
->id
, sc_set_id
)) {
344 guid_str
= GUID_string(sc_set_head
, sc_set_id
);
345 DEBUG(4, ("shadow copy set with GUID %s not found\n",
346 guid_str
? guid_str
: "NO MEM"));
347 talloc_free(guid_str
);
352 static struct fss_sc
*sc_lookup(struct fss_sc
*sc_head
, struct GUID
*sc_id
)
358 for (sc
= sc_head
; sc
; sc
= sc
->next
) {
359 if (GUID_equal(&sc
->id
, sc_id
)) {
363 guid_str
= GUID_string(sc_head
, sc_id
);
364 DEBUG(4, ("shadow copy with GUID %s not found\n",
365 guid_str
? guid_str
: "NO MEM"));
366 talloc_free(guid_str
);
371 static struct fss_sc
*sc_lookup_volname(struct fss_sc
*sc_head
,
376 for (sc
= sc_head
; sc
; sc
= sc
->next
) {
377 if (!strcmp(sc
->volume_name
, volname
)) {
381 DEBUG(4, ("shadow copy with base volume %s not found\n", volname
));
385 /* lookup is case-insensitive */
386 static struct fss_sc_smap
*sc_smap_lookup(struct fss_sc_smap
*smaps_head
,
389 struct fss_sc_smap
*sc_smap
;
390 for (sc_smap
= smaps_head
; sc_smap
; sc_smap
= sc_smap
->next
) {
391 if (!strcasecmp_m(sc_smap
->share_name
, share
)) {
395 DEBUG(4, ("shadow copy share mapping for %s not found\n", share
));
399 void srv_fssa_cleanup(void)
401 talloc_free(fss_global
.db_path
);
402 talloc_free(fss_global
.mem_ctx
);
403 ZERO_STRUCT(fss_global
);
406 NTSTATUS
srv_fssa_start(struct messaging_context
*msg_ctx
)
409 fss_global
.mem_ctx
= talloc_named_const(NULL
, 0,
410 "parent fss rpc server ctx");
411 if (fss_global
.mem_ctx
== NULL
) {
412 return NT_STATUS_NO_MEMORY
;
415 fss_global
.db_path
= lock_path(FSS_DB_NAME
);
416 if (fss_global
.db_path
== NULL
) {
417 talloc_free(fss_global
.mem_ctx
);
418 return NT_STATUS_NO_MEMORY
;
421 fss_global
.min_vers
= FSRVP_RPC_VERSION_1
;
422 fss_global
.max_vers
= FSRVP_RPC_VERSION_1
;
424 * The server MUST populate the GlobalShadowCopySetTable with the
425 * ShadowCopySet entries read from the configuration store.
427 if (lp_parm_bool(GLOBAL_SECTION_SNUM
, "fss", "prune stale", false)) {
428 fss_prune_stale(msg_ctx
, fss_global
.db_path
);
431 status
= fss_state_retrieve(fss_global
.mem_ctx
, &fss_global
.sc_sets
,
432 &fss_global
.sc_sets_count
,
435 if (!NT_STATUS_IS_OK(status
)) {
436 DEBUG(1, ("failed to retrieve fss server state: %s\n",
443 * Determine whether to process an FSRVP operation from connected user @p.
444 * Windows checks for Administrators or Backup Operators group membership. We
445 * also allow for the SEC_PRIV_BACKUP privilege.
447 static bool fss_permitted(struct pipes_struct
*p
)
449 if (p
->session_info
->unix_token
->uid
== sec_initial_uid()) {
450 DEBUG(6, ("Granting FSRVP op, user started smbd\n"));
454 if (nt_token_check_sid(&global_sid_Builtin_Administrators
,
455 p
->session_info
->security_token
)) {
456 DEBUG(6, ("Granting FSRVP op, administrators group member\n"));
459 if (nt_token_check_sid(&global_sid_Builtin_Backup_Operators
,
460 p
->session_info
->security_token
)) {
461 DEBUG(6, ("Granting FSRVP op, backup operators group member\n"));
464 if (security_token_has_privilege(p
->session_info
->security_token
,
466 DEBUG(6, ("Granting FSRVP op, backup privilege present\n"));
470 DEBUG(2, ("FSRVP operation blocked due to lack of backup privilege "
471 "or Administrators/Backup Operators group membership\n"));
476 static void fss_seq_tout_handler(struct tevent_context
*ev
,
477 struct tevent_timer
*te
,
481 struct GUID
*sc_set_id
= NULL
;
482 struct fss_sc_set
*sc_set
;
485 * MS-FSRVP: 3.1.5 Timer Events
486 * Message Sequence Timer elapses: When the Message Sequence Timer
487 * elapses, the server MUST delete the ShadowCopySet in the
488 * GlobalShadowCopySetTable where ShadowCopySet.Status is not equal to
489 * "Recovered", ContextSet MUST be set to FALSE, and the ShadowCopySet
490 * object MUST be freed.
492 DEBUG(2, ("FSRVP msg seq timeout fired\n"));
494 if (private_data
== NULL
) {
495 DEBUG(4, ("timeout without sc_set\n"));
499 sc_set_id
= talloc_get_type_abort(private_data
, struct GUID
);
500 sc_set
= sc_set_lookup(fss_global
.sc_sets
, sc_set_id
);
501 if (sc_set
== NULL
) {
502 DEBUG(0, ("timeout for unknown sc_set\n"));
504 } else if ((sc_set
->state
== FSS_SC_EXPOSED
)
505 || (sc_set
->state
== FSS_SC_RECOVERED
)) {
506 DEBUG(2, ("timeout for finished sc_set %s\n", sc_set
->id_str
));
509 DEBUG(2, ("cleaning up sc_set %s\n", sc_set
->id_str
));
510 SMB_ASSERT(fss_global
.sc_sets_count
> 0);
511 DLIST_REMOVE(fss_global
.sc_sets
, sc_set
);
512 fss_global
.sc_sets_count
--;
516 fss_global
.ctx_set
= false;
517 fss_global
.seq_tmr
= NULL
;
518 talloc_free(sc_set_id
);
521 static void fss_seq_tout_set(TALLOC_CTX
*mem_ctx
,
523 struct fss_sc_set
*sc_set
,
524 struct tevent_timer
**tmr_out
)
526 struct tevent_timer
*tmr
;
527 struct GUID
*sc_set_id
= NULL
;
530 /* allow changes to timeout for testing/debugging purposes */
531 tout
= lp_parm_int(GLOBAL_SECTION_SNUM
, "fss",
532 "sequence timeout", timeout_s
);
534 DEBUG(2, ("FSRVP message sequence timeout disabled\n"));
540 /* don't use talloc_memdup(), need explicit type for callback */
541 sc_set_id
= talloc(mem_ctx
, struct GUID
);
542 if (sc_set_id
== NULL
) {
543 smb_panic("no memory");
545 memcpy(sc_set_id
, &sc_set
->id
, sizeof(*sc_set_id
));
548 tmr
= tevent_add_timer(server_event_context(),
550 timeval_current_ofs(tout
, 0),
551 fss_seq_tout_handler
, sc_set_id
);
553 talloc_free(sc_set_id
);
554 smb_panic("no memory");
560 uint32_t _fss_GetSupportedVersion(struct pipes_struct
*p
,
561 struct fss_GetSupportedVersion
*r
)
563 if (!fss_permitted(p
)) {
564 return HRES_ERROR_V(HRES_E_ACCESSDENIED
);
567 *r
->out
.MinVersion
= fss_global
.min_vers
;
568 *r
->out
.MaxVersion
= fss_global
.max_vers
;
573 uint32_t _fss_SetContext(struct pipes_struct
*p
,
574 struct fss_SetContext
*r
)
576 if (!fss_permitted(p
)) {
577 return HRES_ERROR_V(HRES_E_ACCESSDENIED
);
580 /* ATTR_AUTO_RECOVERY flag can be applied to any */
581 switch (r
->in
.Context
& (~ATTR_AUTO_RECOVERY
)) {
582 case FSRVP_CTX_BACKUP
:
583 DEBUG(6, ("fss ctx set backup\n"));
585 case FSRVP_CTX_FILE_SHARE_BACKUP
:
586 DEBUG(6, ("fss ctx set file share backup\n"));
588 case FSRVP_CTX_NAS_ROLLBACK
:
589 DEBUG(6, ("fss ctx set nas rollback\n"));
591 case FSRVP_CTX_APP_ROLLBACK
:
592 DEBUG(6, ("fss ctx set app rollback\n"));
595 DEBUG(0, ("invalid fss ctx set value: 0x%x\n", r
->in
.Context
));
596 return HRES_ERROR_V(HRES_E_INVALIDARG
);
597 break; /* not reached */
600 fss_global
.ctx_set
= true;
601 fss_global
.cur_ctx
= r
->in
.Context
;
603 TALLOC_FREE(fss_global
.seq_tmr
); /* kill timer if running */
604 fss_seq_tout_set(fss_global
.mem_ctx
, 180, NULL
, &fss_global
.seq_tmr
);
606 fss_global
.cur_ctx
= r
->in
.Context
;
611 static bool sc_set_active(struct fss_sc_set
*sc_set_head
)
614 struct fss_sc_set
*sc_set
;
616 for (sc_set
= sc_set_head
; sc_set
; sc_set
= sc_set
->next
) {
617 if ((sc_set
->state
!= FSS_SC_EXPOSED
)
618 && (sc_set
->state
!= FSS_SC_RECOVERED
)) {
626 uint32_t _fss_StartShadowCopySet(struct pipes_struct
*p
,
627 struct fss_StartShadowCopySet
*r
)
629 struct fss_sc_set
*sc_set
;
632 if (!fss_permitted(p
)) {
633 ret
= HRES_ERROR_V(HRES_E_ACCESSDENIED
);
637 if (!fss_global
.ctx_set
) {
638 DEBUG(3, ("invalid sequence: start sc set requested without "
639 "prior context set\n"));
640 ret
= FSRVP_E_BAD_STATE
;
645 * At any given time, Windows servers allow only one shadow copy set to
646 * be going through the creation process.
648 if (sc_set_active(fss_global
.sc_sets
)) {
649 DEBUG(3, ("StartShadowCopySet called while in progress\n"));
650 ret
= FSRVP_E_SHADOW_COPY_SET_IN_PROGRESS
;
654 /* stop msg seq timer */
655 TALLOC_FREE(fss_global
.seq_tmr
);
657 sc_set
= talloc_zero(fss_global
.mem_ctx
, struct fss_sc_set
);
658 if (sc_set
== NULL
) {
659 ret
= HRES_ERROR_V(HRES_E_OUTOFMEMORY
);
660 goto err_tmr_restart
;
663 sc_set
->id
= GUID_random(); /* Windows servers ignore client ids */
664 sc_set
->id_str
= GUID_string(sc_set
, &sc_set
->id
);
665 if (sc_set
->id_str
== NULL
) {
666 ret
= HRES_ERROR_V(HRES_E_OUTOFMEMORY
);
667 goto err_sc_set_free
;
669 sc_set
->state
= FSS_SC_STARTED
;
670 sc_set
->context
= fss_global
.cur_ctx
;
671 DLIST_ADD_END(fss_global
.sc_sets
, sc_set
, struct fss_sc_set
*);
672 fss_global
.sc_sets_count
++;
673 DEBUG(6, ("%s: shadow-copy set %u added\n",
674 sc_set
->id_str
, fss_global
.sc_sets_count
));
676 /* start msg seq timer */
677 fss_seq_tout_set(fss_global
.mem_ctx
, 180, sc_set
, &fss_global
.seq_tmr
);
679 r
->out
.pShadowCopySetId
= &sc_set
->id
;
686 fss_seq_tout_set(fss_global
.mem_ctx
, 180, NULL
, &fss_global
.seq_tmr
);
691 static uint32_t map_share_name(struct fss_sc_smap
*sc_smap
,
692 const struct fss_sc
*sc
)
694 bool hidden_base
= false;
696 if (*(sc_smap
->share_name
+ strlen(sc_smap
->share_name
) - 1) == '$') {
698 * If MappedShare.ShareName ends with a $ character (meaning
699 * that the share is hidden), then the exposed share name will
700 * have the $ suffix appended.
701 * FIXME: turns out Windows doesn't do this, contrary to docs
706 sc_smap
->sc_share_name
= talloc_asprintf(sc_smap
, "%s@{%s}%s",
709 hidden_base
? "$" : "");
710 if (sc_smap
->sc_share_name
== NULL
) {
711 return HRES_ERROR_V(HRES_E_OUTOFMEMORY
);
717 static uint32_t map_share_comment(struct fss_sc_smap
*sc_smap
,
718 const struct fss_sc
*sc
)
722 time_str
= http_timestring(sc_smap
, sc
->create_ts
);
723 if (time_str
== NULL
) {
724 return HRES_ERROR_V(HRES_E_OUTOFMEMORY
);
727 sc_smap
->sc_share_comment
= talloc_asprintf(sc_smap
, "Shadow copy of %s taken %s",
728 sc_smap
->share_name
, time_str
);
729 if (sc_smap
->sc_share_comment
== NULL
) {
730 return HRES_ERROR_V(HRES_E_OUTOFMEMORY
);
736 uint32_t _fss_AddToShadowCopySet(struct pipes_struct
*p
,
737 struct fss_AddToShadowCopySet
*r
)
740 struct fss_sc_set
*sc_set
;
742 struct fss_sc_smap
*sc_smap
;
748 struct connection_struct
*conn
;
750 TALLOC_CTX
*tmp_ctx
= talloc_new(p
->mem_ctx
);
751 if (tmp_ctx
== NULL
) {
752 ret
= HRES_ERROR_V(HRES_E_OUTOFMEMORY
);
756 if (!fss_permitted(p
)) {
757 ret
= HRES_ERROR_V(HRES_E_ACCESSDENIED
);
761 sc_set
= sc_set_lookup(fss_global
.sc_sets
, &r
->in
.ShadowCopySetId
);
762 if (sc_set
== NULL
) {
763 ret
= HRES_ERROR_V(HRES_E_INVALIDARG
);
767 status
= fss_unc_parse(tmp_ctx
, r
->in
.ShareName
, NULL
, &share
);
768 if (!NT_STATUS_IS_OK(status
)) {
769 ret
= fss_ntstatus_map(status
);
773 snum
= find_service(tmp_ctx
, share
, &service
);
774 if ((snum
== -1) || (service
== NULL
)) {
775 DEBUG(0, ("share at %s not found\n", r
->in
.ShareName
));
776 ret
= HRES_ERROR_V(HRES_E_INVALIDARG
);
780 path_name
= lp_path(tmp_ctx
, snum
);
781 if (path_name
== NULL
) {
782 ret
= HRES_ERROR_V(HRES_E_OUTOFMEMORY
);
786 status
= fss_vfs_conn_create(tmp_ctx
, server_event_context(),
787 p
->msg_ctx
, p
->session_info
, snum
, &conn
);
788 if (!NT_STATUS_IS_OK(status
)) {
789 ret
= HRES_ERROR_V(HRES_E_ACCESSDENIED
);
792 if (!become_user_by_session(conn
, p
->session_info
)) {
793 DEBUG(0, ("failed to become user\n"));
794 fss_vfs_conn_destroy(conn
);
795 ret
= HRES_ERROR_V(HRES_E_ACCESSDENIED
);
799 status
= SMB_VFS_SNAP_CHECK_PATH(conn
, tmp_ctx
, path_name
, &base_vol
);
801 fss_vfs_conn_destroy(conn
);
802 if (!NT_STATUS_IS_OK(status
)) {
803 ret
= FSRVP_E_NOT_SUPPORTED
;
807 if ((sc_set
->state
!= FSS_SC_STARTED
)
808 && (sc_set
->state
!= FSS_SC_ADDED
)) {
809 ret
= FSRVP_E_BAD_STATE
;
813 /* stop msg seq timer */
814 TALLOC_FREE(fss_global
.seq_tmr
);
817 * server MUST look up the ShadowCopy in ShadowCopySet.ShadowCopyList
818 * where ShadowCopy.VolumeName matches the file store on which the
819 * share identified by ShareName is hosted. If an entry is found, the
820 * server MUST fail the call with FSRVP_E_OBJECT_ALREADY_EXISTS.
821 * If no entry is found, the server MUST create a new ShadowCopy
823 * XXX Windows appears to allow multiple mappings for the same vol!
825 sc
= sc_lookup_volname(sc_set
->scs
, base_vol
);
827 ret
= FSRVP_E_OBJECT_ALREADY_EXISTS
;
828 goto err_tmr_restart
;
831 sc
= talloc_zero(sc_set
, struct fss_sc
);
833 ret
= HRES_ERROR_V(HRES_E_OUTOFMEMORY
);
834 goto err_tmr_restart
;
836 talloc_steal(sc
, base_vol
);
837 sc
->volume_name
= base_vol
;
839 sc
->create_ts
= time(NULL
);
841 sc
->id
= GUID_random(); /* Windows servers ignore client ids */
842 sc
->id_str
= GUID_string(sc
, &sc
->id
);
843 if (sc
->id_str
== NULL
) {
844 ret
= HRES_ERROR_V(HRES_E_OUTOFMEMORY
);
848 sc_smap
= talloc_zero(sc
, struct fss_sc_smap
);
849 if (sc_smap
== NULL
) {
850 ret
= HRES_ERROR_V(HRES_E_OUTOFMEMORY
);
854 talloc_steal(sc_smap
, service
);
855 sc_smap
->share_name
= service
;
856 sc_smap
->is_exposed
= false;
858 * generate the sc_smap share name now. It is a unique identifier for
859 * the smap used as a tdb key for state storage.
861 ret
= map_share_name(sc_smap
, sc
);
866 /* add share map to shadow-copy */
867 DLIST_ADD_END(sc
->smaps
, sc_smap
, struct fss_sc_smap
*);
869 /* add shadow-copy to shadow-copy set */
870 DLIST_ADD_END(sc_set
->scs
, sc
, struct fss_sc
*);
872 DEBUG(4, ("added volume %s to shadow copy set with GUID %s\n",
873 sc
->volume_name
, sc_set
->id_str
));
875 /* start the Message Sequence Timer with timeout of 1800 seconds */
876 fss_seq_tout_set(fss_global
.mem_ctx
, 1800, sc_set
, &fss_global
.seq_tmr
);
878 sc_set
->state
= FSS_SC_ADDED
;
879 r
->out
.pShadowCopyId
= &sc
->id
;
881 talloc_free(tmp_ctx
);
887 fss_seq_tout_set(fss_global
.mem_ctx
, 180, sc_set
, &fss_global
.seq_tmr
);
889 talloc_free(tmp_ctx
);
894 static NTSTATUS
commit_sc_with_conn(TALLOC_CTX
*mem_ctx
,
895 struct tevent_context
*ev
,
896 struct messaging_context
*msg_ctx
,
897 struct auth_session_info
*session_info
,
904 struct connection_struct
*conn
;
908 snum
= find_service(mem_ctx
, sc
->smaps
->share_name
, &service
);
909 if ((snum
== -1) || (service
== NULL
)) {
910 DEBUG(0, ("share at %s not found\n", sc
->smaps
->share_name
));
911 return NT_STATUS_UNSUCCESSFUL
;
914 status
= fss_vfs_conn_create(mem_ctx
,
915 ev
, msg_ctx
, session_info
,
917 if (!NT_STATUS_IS_OK(status
)) {
921 if (!become_user_by_session(conn
, session_info
)) {
922 DEBUG(0, ("failed to become user\n"));
923 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
)));
941 uint32_t _fss_CommitShadowCopySet(struct pipes_struct
*p
,
942 struct fss_CommitShadowCopySet
*r
)
944 struct fss_sc_set
*sc_set
;
946 uint32_t commit_count
;
948 NTSTATUS saved_status
;
951 if (!fss_permitted(p
)) {
952 status
= NT_STATUS_ACCESS_DENIED
;
956 tmp_ctx
= talloc_new(p
->mem_ctx
);
957 if (tmp_ctx
== NULL
) {
958 status
= NT_STATUS_NO_MEMORY
;
962 sc_set
= sc_set_lookup(fss_global
.sc_sets
, &r
->in
.ShadowCopySetId
);
963 if (sc_set
== NULL
) {
964 status
= NT_STATUS_INVALID_PARAMETER
;
968 if (sc_set
->state
!= FSS_SC_ADDED
) {
969 status
= NT_STATUS_INVALID_SERVER_STATE
;
973 /* stop Message Sequence Timer */
974 TALLOC_FREE(fss_global
.seq_tmr
);
975 sc_set
->state
= FSS_SC_CREATING
;
977 saved_status
= NT_STATUS_OK
;
978 for (sc
= sc_set
->scs
; sc
; sc
= sc
->next
) {
981 status
= commit_sc_with_conn(tmp_ctx
, server_event_context(),
982 p
->msg_ctx
, p
->session_info
, sc
,
983 &base_path
, &snap_path
);
984 if (!NT_STATUS_IS_OK(status
)) {
985 DEBUG(0, ("snap create failed for shadow copy of "
986 "%s\n", sc
->volume_name
));
987 /* dispatch all scs in set, but retain last error */
988 saved_status
= status
;
991 /* XXX set timeout r->in.TimeOutInMilliseconds */
993 DEBUG(10, ("good snap create %d\n",
995 sc
->sc_path
= talloc_steal(sc
, snap_path
);
997 if (!NT_STATUS_IS_OK(saved_status
)) {
998 status
= saved_status
;
999 goto err_state_revert
;
1002 sc_set
->state
= FSS_SC_COMMITED
;
1004 status
= fss_state_store(fss_global
.mem_ctx
, fss_global
.sc_sets
,
1005 fss_global
.sc_sets_count
,
1006 fss_global
.db_path
);
1008 if (!NT_STATUS_IS_OK(status
)) {
1009 DEBUG(1, ("failed to store fss server state: %s\n",
1010 nt_errstr(status
)));
1013 fss_seq_tout_set(fss_global
.mem_ctx
, 180, sc_set
,
1014 &fss_global
.seq_tmr
);
1015 talloc_free(tmp_ctx
);
1019 sc_set
->state
= FSS_SC_ADDED
;
1020 fss_seq_tout_set(fss_global
.mem_ctx
, 180, sc_set
,
1021 &fss_global
.seq_tmr
);
1023 talloc_free(tmp_ctx
);
1025 return fss_ntstatus_map(status
);
1028 static sbcErr
fss_conf_get_share_def(struct smbconf_ctx
*fconf_ctx
,
1029 struct smbconf_ctx
*rconf_ctx
,
1030 TALLOC_CTX
*mem_ctx
,
1032 struct smbconf_service
**service_def
)
1035 struct smbconf_service
*def
;
1037 *service_def
= NULL
;
1038 cerr
= smbconf_get_share(fconf_ctx
, mem_ctx
, share
, &def
);
1039 if (SBC_ERROR_IS_OK(cerr
)) {
1044 cerr
= smbconf_get_share(rconf_ctx
, mem_ctx
, share
, &def
);
1045 if (SBC_ERROR_IS_OK(cerr
)) {
1053 * Expose a new share using libsmbconf, cloning the existing configuration
1054 * from the base share. The base share may be defined in either the registry
1056 * XXX this is called as root
1058 static uint32_t fss_sc_expose(struct smbconf_ctx
*fconf_ctx
,
1059 struct smbconf_ctx
*rconf_ctx
,
1060 TALLOC_CTX
*mem_ctx
,
1063 struct fss_sc_smap
*sc_smap
;
1066 for (sc_smap
= sc
->smaps
; sc_smap
; sc_smap
= sc_smap
->next
) {
1068 struct smbconf_service
*base_service
= NULL
;
1069 struct security_descriptor
*sd
;
1072 cerr
= fss_conf_get_share_def(fconf_ctx
, rconf_ctx
, mem_ctx
,
1073 sc_smap
->share_name
, &base_service
);
1074 if (!SBC_ERROR_IS_OK(cerr
)) {
1075 DEBUG(0, ("failed to get base share %s definition: "
1076 "%s\n", sc_smap
->share_name
,
1077 sbcErrorString(cerr
)));
1078 err
= HRES_ERROR_V(HRES_E_FAIL
);
1082 /* smap share name already defined when added */
1083 err
= map_share_comment(sc_smap
, sc
);
1085 DEBUG(0, ("failed to map share comment\n"));
1089 base_service
->name
= sc_smap
->sc_share_name
;
1091 cerr
= smbconf_create_set_share(rconf_ctx
, base_service
);
1092 if (!SBC_ERROR_IS_OK(cerr
)) {
1093 DEBUG(0, ("failed to create share %s: %s\n",
1094 base_service
->name
, sbcErrorString(cerr
)));
1095 err
= HRES_ERROR_V(HRES_E_FAIL
);
1098 cerr
= smbconf_set_parameter(rconf_ctx
, sc_smap
->sc_share_name
,
1099 "path", sc
->sc_path
);
1100 if (!SBC_ERROR_IS_OK(cerr
)) {
1101 DEBUG(0, ("failed to set path param: %s\n",
1102 sbcErrorString(cerr
)));
1103 err
= HRES_ERROR_V(HRES_E_FAIL
);
1106 if (sc_smap
->sc_share_comment
!= NULL
) {
1107 cerr
= smbconf_set_parameter(rconf_ctx
,
1108 sc_smap
->sc_share_name
,
1110 sc_smap
->sc_share_comment
);
1111 if (!SBC_ERROR_IS_OK(cerr
)) {
1112 DEBUG(0, ("failed to set comment param: %s\n",
1113 sbcErrorString(cerr
)));
1114 err
= HRES_ERROR_V(HRES_E_FAIL
);
1118 talloc_free(base_service
);
1121 * Obtain the base share SD, which also needs to be cloned.
1122 * Share SDs are stored in share_info.tdb, so are not covered by
1123 * the registry transaction.
1124 * The base share SD should be cloned at the time of exposure,
1125 * rather than when the snapshot is taken. This matches Windows
1126 * Server 2012 behaviour.
1128 sd
= get_share_security(mem_ctx
, sc_smap
->share_name
, &sd_size
);
1130 DEBUG(2, ("no share SD to clone for %s snapshot\n",
1131 sc_smap
->share_name
));
1134 ok
= set_share_security(sc_smap
->sc_share_name
, sd
);
1137 DEBUG(0, ("failed to set %s share SD\n",
1138 sc_smap
->sc_share_name
));
1139 err
= HRES_ERROR_V(HRES_E_FAIL
);
1148 uint32_t _fss_ExposeShadowCopySet(struct pipes_struct
*p
,
1149 struct fss_ExposeShadowCopySet
*r
)
1152 struct fss_sc_set
*sc_set
;
1155 struct smbconf_ctx
*fconf_ctx
;
1156 struct smbconf_ctx
*rconf_ctx
;
1159 TALLOC_CTX
*tmp_ctx
= talloc_new(p
->mem_ctx
);
1160 if (tmp_ctx
== NULL
) {
1161 return HRES_ERROR_V(HRES_E_OUTOFMEMORY
);
1164 if (!fss_permitted(p
)) {
1165 ret
= HRES_ERROR_V(HRES_E_ACCESSDENIED
);
1169 sc_set
= sc_set_lookup(fss_global
.sc_sets
, &r
->in
.ShadowCopySetId
);
1170 if (sc_set
== NULL
) {
1171 ret
= HRES_ERROR_V(HRES_E_INVALIDARG
);
1175 if (sc_set
->state
!= FSS_SC_COMMITED
) {
1176 ret
= FSRVP_E_BAD_STATE
;
1180 /* stop message sequence timer */
1181 TALLOC_FREE(fss_global
.seq_tmr
);
1184 * Prepare to clone the base share definition for the snapshot share.
1185 * Create both registry and file conf contexts, as the base share
1186 * definition may be located in either. The snapshot share definition
1187 * is always written to the registry.
1189 cerr
= smbconf_init(tmp_ctx
, &rconf_ctx
, "registry");
1190 if (!SBC_ERROR_IS_OK(cerr
)) {
1191 DEBUG(0, ("failed registry smbconf init: %s\n",
1192 sbcErrorString(cerr
)));
1193 ret
= HRES_ERROR_V(HRES_E_FAIL
);
1194 goto err_tmr_restart
;
1196 fconf_path
= talloc_asprintf(tmp_ctx
, "file:%s", get_dyn_CONFIGFILE());
1197 if (fconf_path
== NULL
) {
1198 ret
= HRES_ERROR_V(HRES_E_OUTOFMEMORY
);
1199 goto err_tmr_restart
;
1201 cerr
= smbconf_init(tmp_ctx
, &fconf_ctx
, fconf_path
);
1202 if (!SBC_ERROR_IS_OK(cerr
)) {
1203 DEBUG(0, ("failed %s smbconf init: %s\n",
1204 fconf_path
, sbcErrorString(cerr
)));
1205 ret
= HRES_ERROR_V(HRES_E_FAIL
);
1206 goto err_tmr_restart
;
1209 /* registry IO must be done as root */
1211 cerr
= smbconf_transaction_start(rconf_ctx
);
1212 if (!SBC_ERROR_IS_OK(cerr
)) {
1213 DEBUG(0, ("error starting transaction: %s\n",
1214 sbcErrorString(cerr
)));
1215 ret
= HRES_ERROR_V(HRES_E_FAIL
);
1217 goto err_tmr_restart
;
1220 for (sc
= sc_set
->scs
; sc
; sc
= sc
->next
) {
1221 ret
= fss_sc_expose(fconf_ctx
, rconf_ctx
, tmp_ctx
, sc
);
1223 DEBUG(0,("failed to expose shadow copy of %s\n",
1229 cerr
= smbconf_transaction_commit(rconf_ctx
);
1230 if (!SBC_ERROR_IS_OK(cerr
)) {
1231 DEBUG(0, ("error committing transaction: %s\n",
1232 sbcErrorString(cerr
)));
1233 ret
= HRES_ERROR_V(HRES_E_FAIL
);
1238 message_send_all(p
->msg_ctx
, MSG_SMB_CONF_UPDATED
, NULL
, 0, NULL
);
1239 for (sc
= sc_set
->scs
; sc
; sc
= sc
->next
) {
1240 struct fss_sc_smap
*sm
;
1241 for (sm
= sc
->smaps
; sm
; sm
= sm
->next
)
1242 sm
->is_exposed
= true;
1244 sc_set
->state
= FSS_SC_EXPOSED
;
1246 status
= fss_state_store(fss_global
.mem_ctx
, fss_global
.sc_sets
,
1247 fss_global
.sc_sets_count
, fss_global
.db_path
);
1249 if (!NT_STATUS_IS_OK(status
)) {
1250 DEBUG(1, ("failed to store fss server state: %s\n",
1251 nt_errstr(status
)));
1253 /* start message sequence timer */
1254 fss_seq_tout_set(fss_global
.mem_ctx
, 180, sc_set
, &fss_global
.seq_tmr
);
1255 talloc_free(tmp_ctx
);
1259 smbconf_transaction_cancel(rconf_ctx
);
1262 fss_seq_tout_set(fss_global
.mem_ctx
, 180, sc_set
, &fss_global
.seq_tmr
);
1264 talloc_free(tmp_ctx
);
1268 uint32_t _fss_RecoveryCompleteShadowCopySet(struct pipes_struct
*p
,
1269 struct fss_RecoveryCompleteShadowCopySet
*r
)
1272 struct fss_sc_set
*sc_set
;
1274 if (!fss_permitted(p
)) {
1275 return HRES_ERROR_V(HRES_E_ACCESSDENIED
);
1278 sc_set
= sc_set_lookup(fss_global
.sc_sets
, &r
->in
.ShadowCopySetId
);
1279 if (sc_set
== NULL
) {
1280 return HRES_ERROR_V(HRES_E_INVALIDARG
);
1283 if (sc_set
->state
!= FSS_SC_EXPOSED
) {
1284 return FSRVP_E_BAD_STATE
;
1287 /* stop msg sequence timer */
1288 TALLOC_FREE(fss_global
.seq_tmr
);
1290 if (sc_set
->context
& ATTR_NO_AUTO_RECOVERY
) {
1291 /* TODO set read-only */
1294 sc_set
->state
= FSS_SC_RECOVERED
;
1295 fss_global
.cur_ctx
= 0;
1296 fss_global
.ctx_set
= false;
1299 status
= fss_state_store(fss_global
.mem_ctx
, fss_global
.sc_sets
,
1300 fss_global
.sc_sets_count
, fss_global
.db_path
);
1302 if (!NT_STATUS_IS_OK(status
)) {
1303 DEBUG(1, ("failed to store fss server state: %s\n",
1304 nt_errstr(status
)));
1310 uint32_t _fss_AbortShadowCopySet(struct pipes_struct
*p
,
1311 struct fss_AbortShadowCopySet
*r
)
1314 struct fss_sc_set
*sc_set
;
1316 if (!fss_permitted(p
)) {
1317 return HRES_ERROR_V(HRES_E_ACCESSDENIED
);
1320 sc_set
= sc_set_lookup(fss_global
.sc_sets
, &r
->in
.ShadowCopySetId
);
1321 if (sc_set
== NULL
) {
1322 return HRES_ERROR_V(HRES_E_INVALIDARG
);
1325 DEBUG(6, ("%s: aborting shadow-copy set\n", sc_set
->id_str
));
1327 if ((sc_set
->state
== FSS_SC_COMMITED
)
1328 || (sc_set
->state
== FSS_SC_EXPOSED
)
1329 || (sc_set
->state
== FSS_SC_RECOVERED
)) {
1333 if (sc_set
->state
== FSS_SC_CREATING
) {
1334 return FSRVP_E_BAD_STATE
;
1337 DLIST_REMOVE(fss_global
.sc_sets
, sc_set
);
1338 talloc_free(sc_set
);
1339 fss_global
.sc_sets_count
--;
1341 status
= fss_state_store(fss_global
.mem_ctx
, fss_global
.sc_sets
,
1342 fss_global
.sc_sets_count
, fss_global
.db_path
);
1344 if (!NT_STATUS_IS_OK(status
)) {
1345 DEBUG(1, ("failed to store fss server state: %s\n",
1346 nt_errstr(status
)));
1352 uint32_t _fss_IsPathSupported(struct pipes_struct
*p
,
1353 struct fss_IsPathSupported
*r
)
1359 struct connection_struct
*conn
;
1361 TALLOC_CTX
*tmp_ctx
= talloc_new(p
->mem_ctx
);
1362 if (tmp_ctx
== NULL
) {
1363 return HRES_ERROR_V(HRES_E_OUTOFMEMORY
);
1366 if (!fss_permitted(p
)) {
1367 talloc_free(tmp_ctx
);
1368 return HRES_ERROR_V(HRES_E_ACCESSDENIED
);
1371 status
= fss_unc_parse(tmp_ctx
, r
->in
.ShareName
, NULL
, &share
);
1372 if (!NT_STATUS_IS_OK(status
)) {
1373 talloc_free(tmp_ctx
);
1374 return fss_ntstatus_map(status
);
1377 snum
= find_service(tmp_ctx
, share
, &service
);
1378 if ((snum
== -1) || (service
== NULL
)) {
1379 DEBUG(0, ("share at %s not found\n", r
->in
.ShareName
));
1380 talloc_free(tmp_ctx
);
1381 return HRES_ERROR_V(HRES_E_INVALIDARG
);
1384 status
= fss_vfs_conn_create(tmp_ctx
, server_event_context(),
1385 p
->msg_ctx
, p
->session_info
, snum
, &conn
);
1386 if (!NT_STATUS_IS_OK(status
)) {
1387 talloc_free(tmp_ctx
);
1388 return HRES_ERROR_V(HRES_E_ACCESSDENIED
);
1390 if (!become_user_by_session(conn
, p
->session_info
)) {
1391 DEBUG(0, ("failed to become user\n"));
1392 talloc_free(tmp_ctx
);
1393 fss_vfs_conn_destroy(conn
);
1394 return HRES_ERROR_V(HRES_E_ACCESSDENIED
);
1396 status
= SMB_VFS_SNAP_CHECK_PATH(conn
, tmp_ctx
,
1397 lp_path(tmp_ctx
, snum
),
1400 fss_vfs_conn_destroy(conn
);
1401 if (!NT_STATUS_IS_OK(status
)) {
1402 talloc_free(tmp_ctx
);
1403 return FSRVP_E_NOT_SUPPORTED
;
1406 *r
->out
.OwnerMachineName
= lp_netbios_name();
1407 *r
->out
.SupportedByThisProvider
= 1;
1408 talloc_free(tmp_ctx
);
1412 uint32_t _fss_IsPathShadowCopied(struct pipes_struct
*p
,
1413 struct fss_IsPathShadowCopied
*r
)
1415 if (!fss_permitted(p
)) {
1416 return HRES_ERROR_V(HRES_E_ACCESSDENIED
);
1419 /* not yet supported */
1420 return FSRVP_E_NOT_SUPPORTED
;
1423 uint32_t _fss_GetShareMapping(struct pipes_struct
*p
,
1424 struct fss_GetShareMapping
*r
)
1427 struct fss_sc_set
*sc_set
;
1429 struct fss_sc_smap
*sc_smap
;
1431 struct fssagent_share_mapping_1
*sm_out
;
1433 TALLOC_CTX
*tmp_ctx
= talloc_new(p
->mem_ctx
);
1434 if (tmp_ctx
== NULL
) {
1435 return HRES_ERROR_V(HRES_E_OUTOFMEMORY
);
1438 if (!fss_permitted(p
)) {
1439 talloc_free(tmp_ctx
);
1440 return HRES_ERROR_V(HRES_E_ACCESSDENIED
);
1443 sc_set
= sc_set_lookup(fss_global
.sc_sets
, &r
->in
.ShadowCopySetId
);
1444 if (sc_set
== NULL
) {
1445 talloc_free(tmp_ctx
);
1446 return HRES_ERROR_V(HRES_E_INVALIDARG
);
1450 * If ShadowCopySet.Status is not "Exposed", the server SHOULD<9> fail
1451 * the call with FSRVP_E_BAD_STATE.
1452 * <9> If ShadowCopySet.Status is "Started", "Added",
1453 * "CreationInProgress", or "Committed", Windows Server 2012 FSRVP
1454 * servers return an error value of 0x80042311.
1456 if ((sc_set
->state
== FSS_SC_STARTED
)
1457 || (sc_set
->state
== FSS_SC_ADDED
)
1458 || (sc_set
->state
== FSS_SC_CREATING
)
1459 || (sc_set
->state
== FSS_SC_COMMITED
)) {
1460 talloc_free(tmp_ctx
);
1461 return 0x80042311; /* documented magic value */
1464 sc
= sc_lookup(sc_set
->scs
, &r
->in
.ShadowCopyId
);
1466 talloc_free(tmp_ctx
);
1467 return HRES_ERROR_V(HRES_E_INVALIDARG
);
1470 status
= fss_unc_parse(tmp_ctx
, r
->in
.ShareName
, NULL
, &share
);
1471 if (!NT_STATUS_IS_OK(status
)) {
1472 talloc_free(tmp_ctx
);
1473 return fss_ntstatus_map(status
);
1476 sc_smap
= sc_smap_lookup(sc
->smaps
, share
);
1477 if (sc_smap
== NULL
) {
1478 talloc_free(tmp_ctx
);
1479 return HRES_ERROR_V(HRES_E_INVALIDARG
);
1482 if (r
->in
.Level
!= 1) {
1483 talloc_free(tmp_ctx
);
1484 return HRES_ERROR_V(HRES_E_INVALIDARG
);
1487 sm_out
= talloc_zero(p
->mem_ctx
, struct fssagent_share_mapping_1
);
1488 if (sm_out
== NULL
) {
1489 talloc_free(tmp_ctx
);
1490 return HRES_ERROR_V(HRES_E_OUTOFMEMORY
);
1492 sm_out
->ShadowCopySetId
= sc_set
->id
;
1493 sm_out
->ShadowCopyId
= sc
->id
;
1494 sm_out
->ShareNameUNC
= talloc_asprintf(sm_out
, "\\\\%s\\%s",
1496 sc_smap
->share_name
);
1497 if (sm_out
->ShareNameUNC
== NULL
) {
1498 talloc_free(sm_out
);
1499 talloc_free(tmp_ctx
);
1500 return HRES_ERROR_V(HRES_E_OUTOFMEMORY
);
1502 sm_out
->ShadowCopyShareName
= sc_smap
->sc_share_name
;
1503 unix_to_nt_time(&sm_out
->tstamp
, sc
->create_ts
);
1504 r
->out
.ShareMapping
->ShareMapping1
= sm_out
;
1505 talloc_free(tmp_ctx
);
1507 /* reset msg sequence timer */
1508 TALLOC_FREE(fss_global
.seq_tmr
);
1509 fss_seq_tout_set(fss_global
.mem_ctx
, 1800, sc_set
, &fss_global
.seq_tmr
);
1514 static NTSTATUS
sc_smap_unexpose(struct messaging_context
*msg_ctx
,
1515 struct fss_sc_smap
*sc_smap
, bool delete_all
)
1518 struct smbconf_ctx
*conf_ctx
;
1520 bool is_modified
= false;
1521 TALLOC_CTX
*tmp_ctx
= talloc_new(sc_smap
);
1522 if (tmp_ctx
== NULL
) {
1523 return NT_STATUS_NO_MEMORY
;
1526 cerr
= smbconf_init(tmp_ctx
, &conf_ctx
, "registry");
1527 if (!SBC_ERROR_IS_OK(cerr
)) {
1528 DEBUG(0, ("failed registry smbconf init: %s\n",
1529 sbcErrorString(cerr
)));
1530 ret
= NT_STATUS_UNSUCCESSFUL
;
1534 /* registry IO must be done as root */
1537 cerr
= smbconf_transaction_start(conf_ctx
);
1538 if (!SBC_ERROR_IS_OK(cerr
)) {
1539 DEBUG(0, ("error starting transaction: %s\n",
1540 sbcErrorString(cerr
)));
1541 ret
= NT_STATUS_UNSUCCESSFUL
;
1546 struct fss_sc_smap
*sc_map_next
= sc_smap
->next
;
1547 if (!smbconf_share_exists(conf_ctx
, sc_smap
->sc_share_name
)) {
1548 DEBUG(2, ("no such share: %s\n", sc_smap
->sc_share_name
));
1553 sc_smap
= sc_map_next
;
1557 cerr
= smbconf_delete_share(conf_ctx
, sc_smap
->sc_share_name
);
1558 if (!SBC_ERROR_IS_OK(cerr
)) {
1559 DEBUG(0, ("error deleting share: %s\n",
1560 sbcErrorString(cerr
)));
1561 ret
= NT_STATUS_UNSUCCESSFUL
;
1565 sc_smap
->is_exposed
= false;
1567 sc_smap
= sc_map_next
;
1569 sc_smap
= NULL
; /* only process single sc_map entry */
1573 cerr
= smbconf_transaction_commit(conf_ctx
);
1574 if (!SBC_ERROR_IS_OK(cerr
)) {
1575 DEBUG(0, ("error committing transaction: %s\n",
1576 sbcErrorString(cerr
)));
1577 ret
= NT_STATUS_UNSUCCESSFUL
;
1580 message_send_all(msg_ctx
, MSG_SMB_CONF_UPDATED
, NULL
, 0, NULL
);
1588 talloc_free(conf_ctx
);
1591 talloc_free(tmp_ctx
);
1595 smbconf_transaction_cancel(conf_ctx
);
1596 talloc_free(conf_ctx
);
1598 talloc_free(tmp_ctx
);
1602 uint32_t _fss_DeleteShareMapping(struct pipes_struct
*p
,
1603 struct fss_DeleteShareMapping
*r
)
1605 struct fss_sc_set
*sc_set
;
1607 struct fss_sc_smap
*sc_smap
;
1610 TALLOC_CTX
*tmp_ctx
;
1611 struct connection_struct
*conn
;
1615 if (!fss_permitted(p
)) {
1616 status
= NT_STATUS_ACCESS_DENIED
;
1620 tmp_ctx
= talloc_new(p
->mem_ctx
);
1621 if (tmp_ctx
== NULL
) {
1622 status
= NT_STATUS_NO_MEMORY
;
1626 sc_set
= sc_set_lookup(fss_global
.sc_sets
, &r
->in
.ShadowCopySetId
);
1627 if (sc_set
== NULL
) {
1628 /* docs say HRES_E_INVALIDARG */
1629 status
= NT_STATUS_OBJECTID_NOT_FOUND
;
1633 if ((sc_set
->state
!= FSS_SC_EXPOSED
)
1634 && (sc_set
->state
!= FSS_SC_RECOVERED
)) {
1635 status
= NT_STATUS_INVALID_SERVER_STATE
;
1639 sc
= sc_lookup(sc_set
->scs
, &r
->in
.ShadowCopyId
);
1641 status
= NT_STATUS_INVALID_PARAMETER
;
1645 status
= fss_unc_parse(tmp_ctx
, r
->in
.ShareName
, NULL
, &share
);
1646 if (!NT_STATUS_IS_OK(status
)) {
1650 sc_smap
= sc_smap_lookup(sc
->smaps
, share
);
1651 if (sc_smap
== NULL
) {
1652 status
= NT_STATUS_INVALID_PARAMETER
;
1656 status
= sc_smap_unexpose(p
->msg_ctx
, sc_smap
, false);
1657 if (!NT_STATUS_IS_OK(status
)) {
1658 DEBUG(0, ("failed to remove share %s: %s\n",
1659 sc_smap
->sc_share_name
, nt_errstr(status
)));
1663 message_send_all(p
->msg_ctx
, MSG_SMB_FORCE_TDIS
, sc_smap
->sc_share_name
,
1664 strlen(sc_smap
->sc_share_name
) + 1, NULL
);
1666 if (sc
->smaps_count
> 1) {
1667 /* do not delete the underlying snapshot - still in use */
1668 status
= NT_STATUS_OK
;
1672 snum
= find_service(tmp_ctx
, sc_smap
->share_name
, &service
);
1673 if ((snum
== -1) || (service
== NULL
)) {
1674 DEBUG(0, ("share at %s not found\n", sc_smap
->share_name
));
1675 status
= NT_STATUS_UNSUCCESSFUL
;
1679 status
= fss_vfs_conn_create(tmp_ctx
, server_event_context(),
1680 p
->msg_ctx
, p
->session_info
, snum
, &conn
);
1681 if (!NT_STATUS_IS_OK(status
)) {
1684 if (!become_user_by_session(conn
, p
->session_info
)) {
1685 DEBUG(0, ("failed to become user\n"));
1686 status
= NT_STATUS_ACCESS_DENIED
;
1687 goto err_conn_destroy
;
1690 status
= SMB_VFS_SNAP_DELETE(conn
, tmp_ctx
, sc
->volume_name
,
1693 if (!NT_STATUS_IS_OK(status
)) {
1694 goto err_conn_destroy
;
1697 /* XXX set timeout r->in.TimeOutInMilliseconds */
1698 DEBUG(6, ("good snap delete\n"));
1699 DLIST_REMOVE(sc
->smaps
, sc_smap
);
1701 talloc_free(sc_smap
);
1702 if (sc
->smaps_count
== 0) {
1703 DLIST_REMOVE(sc_set
->scs
, sc
);
1704 sc_set
->scs_count
--;
1707 if (sc_set
->scs_count
== 0) {
1708 DLIST_REMOVE(fss_global
.sc_sets
, sc_set
);
1709 fss_global
.sc_sets_count
--;
1710 talloc_free(sc_set
);
1715 status
= fss_state_store(fss_global
.mem_ctx
, fss_global
.sc_sets
,
1716 fss_global
.sc_sets_count
, fss_global
.db_path
);
1718 if (!NT_STATUS_IS_OK(status
)) {
1719 DEBUG(1, ("failed to store fss server state: %s\n",
1720 nt_errstr(status
)));
1723 status
= NT_STATUS_OK
;
1725 fss_vfs_conn_destroy(conn
);
1727 talloc_free(tmp_ctx
);
1729 return fss_ntstatus_map(status
);
1732 uint32_t _fss_PrepareShadowCopySet(struct pipes_struct
*p
,
1733 struct fss_PrepareShadowCopySet
*r
)
1735 struct fss_sc_set
*sc_set
;
1737 if (!fss_permitted(p
)) {
1738 return HRES_ERROR_V(HRES_E_ACCESSDENIED
);
1741 sc_set
= sc_set_lookup(fss_global
.sc_sets
, &r
->in
.ShadowCopySetId
);
1742 if (sc_set
== NULL
) {
1743 return HRES_ERROR_V(HRES_E_INVALIDARG
);
1746 if (sc_set
->state
!= FSS_SC_ADDED
) {
1747 return FSRVP_E_BAD_STATE
;
1750 /* stop msg sequence timer */
1751 TALLOC_FREE(fss_global
.seq_tmr
);
1754 * Windows Server "8" Beta takes ~60s here, presumably flushing
1755 * everything to disk. We may want to do something similar.
1758 /* start msg sequence timer, 1800 on success */
1759 fss_seq_tout_set(fss_global
.mem_ctx
, 1800, sc_set
, &fss_global
.seq_tmr
);