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/rpc/dcesrv_core.h"
31 #include "librpc/gen_ndr/ndr_fsrvp_scompat.h"
32 #include "librpc/gen_ndr/ndr_fsrvp.h"
33 #include "rpc_server/rpc_server.h"
34 #include "srv_fss_private.h"
35 #include "lib/global_contexts.h"
38 #define DBGC_CLASS DBGC_RPC_SRV
40 static struct fss_global fss_global
;
42 /* errmap NTSTATUS->fsrvp */
46 } ntstatus_to_fsrvp_map
[] = {
47 {NT_STATUS_INVALID_SERVER_STATE
, FSRVP_E_BAD_STATE
},
48 {NT_STATUS_INVALID_DISPOSITION
, FSRVP_E_SHADOW_COPY_SET_IN_PROGRESS
},
49 {NT_STATUS_NOT_SUPPORTED
, FSRVP_E_NOT_SUPPORTED
},
50 {NT_STATUS_IO_TIMEOUT
, FSRVP_E_WAIT_TIMEOUT
},
51 {NT_STATUS_CANT_WAIT
, FSRVP_E_WAIT_FAILED
},
52 {NT_STATUS_OBJECTID_EXISTS
, FSRVP_E_OBJECT_ALREADY_EXISTS
},
53 {NT_STATUS_OBJECTID_NOT_FOUND
, FSRVP_E_OBJECT_NOT_FOUND
},
54 {NT_STATUS_OBJECT_NAME_INVALID
, FSRVP_E_BAD_ID
},
57 /* errmap NTSTATUS->hresult */
61 } ntstatus_to_hres_map
[] = {
62 {NT_STATUS_ACCESS_DENIED
, HRES_E_ACCESSDENIED
},
63 {NT_STATUS_INVALID_PARAMETER
, HRES_E_INVALIDARG
},
64 {NT_STATUS_NO_MEMORY
, HRES_E_OUTOFMEMORY
},
67 static uint32_t fss_ntstatus_map(NTSTATUS status
)
71 if (NT_STATUS_IS_OK(status
))
74 /* check fsrvp specific errors first */
75 for (i
= 0; i
< ARRAY_SIZE(ntstatus_to_fsrvp_map
); i
++) {
76 if (NT_STATUS_EQUAL(status
, ntstatus_to_fsrvp_map
[i
].status
)) {
77 return ntstatus_to_fsrvp_map
[i
].fsrvp_err
;
80 /* fall-back to generic hresult values */
81 for (i
= 0; i
< ARRAY_SIZE(ntstatus_to_hres_map
); i
++) {
82 if (NT_STATUS_EQUAL(status
, ntstatus_to_hres_map
[i
].status
)) {
83 return HRES_ERROR_V(ntstatus_to_hres_map
[i
].hres
);
87 return HRES_ERROR_V(HRES_E_FAIL
);
90 static NTSTATUS
fss_unc_parse(TALLOC_CTX
*mem_ctx
,
100 return NT_STATUS_INVALID_PARAMETER
;
103 s
= strstr_m(unc
, "\\\\");
105 return NT_STATUS_INVALID_PARAMETER
;
108 server
= talloc_strdup(mem_ctx
, s
+ 2);
109 if (server
== NULL
) {
110 return NT_STATUS_NO_MEMORY
;
112 s
= strchr_m(server
, '\\');
113 if ((s
== NULL
) || (s
== server
)) {
114 return NT_STATUS_INVALID_PARAMETER
;
119 s
= strchr_m(share
, '\\');
121 /* diskshadow.exe adds a trailing '\' to the share-name */
124 if (strlen(share
) == 0) {
125 return NT_STATUS_INVALID_PARAMETER
;
128 if (_server
!= NULL
) {
131 if (_share
!= NULL
) {
138 static NTSTATUS
fss_conn_create_tos(struct messaging_context
*msg_ctx
,
139 struct auth_session_info
*session_info
,
141 struct connection_struct
**conn_out
);
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_conn_create_tos(msg_ctx
, NULL
, snum
, &conn
);
172 if(!NT_STATUS_IS_OK(status
)) {
176 smb_fname
= synthetic_smb_fname(service
,
182 if (smb_fname
== NULL
) {
186 ret
= SMB_VFS_STAT(conn
, smb_fname
);
187 if ((ret
== -1) && (errno
== ENOENT
)) {
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_conn_create_tos(struct messaging_context
*msg_ctx
,
293 struct auth_session_info
*session_info
,
295 struct connection_struct
**conn_out
)
297 const struct loadparm_substitution
*lp_sub
=
298 loadparm_s3_global_substitution();
299 struct conn_struct_tos
*c
= NULL
;
302 status
= create_conn_struct_tos(msg_ctx
,
304 lp_path(talloc_tos(), lp_sub
, snum
),
307 if (!NT_STATUS_IS_OK(status
)) {
308 DEBUG(0,("failed to create conn for vfs: %s\n",
313 status
= set_conn_force_user_group(c
->conn
, snum
);
314 if (!NT_STATUS_IS_OK(status
)) {
315 DEBUG(0, ("failed set force user / group\n"));
324 static struct fss_sc_set
*sc_set_lookup(struct fss_sc_set
*sc_set_head
,
325 struct GUID
*sc_set_id
)
328 struct fss_sc_set
*sc_set
;
331 for (sc_set
= sc_set_head
; sc_set
; sc_set
= sc_set
->next
) {
332 if (GUID_equal(&sc_set
->id
, sc_set_id
)) {
336 guid_str
= GUID_string(sc_set_head
, sc_set_id
);
337 DEBUG(4, ("shadow copy set with GUID %s not found\n",
338 guid_str
? guid_str
: "NO MEM"));
339 talloc_free(guid_str
);
344 static struct fss_sc
*sc_lookup(struct fss_sc
*sc_head
, struct GUID
*sc_id
)
350 for (sc
= sc_head
; sc
; sc
= sc
->next
) {
351 if (GUID_equal(&sc
->id
, sc_id
)) {
355 guid_str
= GUID_string(sc_head
, sc_id
);
356 DEBUG(4, ("shadow copy with GUID %s not found\n",
357 guid_str
? guid_str
: "NO MEM"));
358 talloc_free(guid_str
);
363 static struct fss_sc
*sc_lookup_volname(struct fss_sc
*sc_head
,
368 for (sc
= sc_head
; sc
; sc
= sc
->next
) {
369 if (!strcmp(sc
->volume_name
, volname
)) {
373 DEBUG(4, ("shadow copy with base volume %s not found\n", volname
));
377 /* lookup is case-insensitive */
378 static struct fss_sc_smap
*sc_smap_lookup(struct fss_sc_smap
*smaps_head
,
381 struct fss_sc_smap
*sc_smap
;
382 for (sc_smap
= smaps_head
; sc_smap
; sc_smap
= sc_smap
->next
) {
383 if (!strcasecmp_m(sc_smap
->share_name
, share
)) {
387 DEBUG(4, ("shadow copy share mapping for %s not found\n", share
));
391 static void srv_fssa_cleanup(void)
393 talloc_free(fss_global
.db_path
);
394 talloc_free(fss_global
.mem_ctx
);
395 ZERO_STRUCT(fss_global
);
398 static NTSTATUS
srv_fssa_start(struct messaging_context
*msg_ctx
)
401 fss_global
.mem_ctx
= talloc_named_const(NULL
, 0,
402 "parent fss rpc server ctx");
403 if (fss_global
.mem_ctx
== NULL
) {
404 return NT_STATUS_NO_MEMORY
;
407 fss_global
.db_path
= lock_path(talloc_tos(), FSS_DB_NAME
);
408 if (fss_global
.db_path
== NULL
) {
409 talloc_free(fss_global
.mem_ctx
);
410 return NT_STATUS_NO_MEMORY
;
413 fss_global
.min_vers
= FSRVP_RPC_VERSION_1
;
414 fss_global
.max_vers
= FSRVP_RPC_VERSION_1
;
416 * The server MUST populate the GlobalShadowCopySetTable with the
417 * ShadowCopySet entries read from the configuration store.
419 if (lp_parm_bool(GLOBAL_SECTION_SNUM
, "fss", "prune stale", false)) {
420 fss_prune_stale(msg_ctx
, fss_global
.db_path
);
423 status
= fss_state_retrieve(fss_global
.mem_ctx
, &fss_global
.sc_sets
,
424 &fss_global
.sc_sets_count
,
427 if (!NT_STATUS_IS_OK(status
)) {
428 DEBUG(1, ("failed to retrieve fss server state: %s\n",
435 * Determine whether to process an FSRVP operation from connected user @p.
436 * Windows checks for Administrators or Backup Operators group membership. We
437 * also allow for the SEC_PRIV_BACKUP privilege.
439 static bool fss_permitted(struct pipes_struct
*p
)
441 struct dcesrv_call_state
*dce_call
= p
->dce_call
;
442 struct auth_session_info
*session_info
=
443 dcesrv_call_session_info(dce_call
);
445 if (session_info
->unix_token
->uid
== sec_initial_uid()) {
446 DEBUG(6, ("Granting FSRVP op, user started smbd\n"));
450 if (nt_token_check_sid(&global_sid_Builtin_Administrators
,
451 session_info
->security_token
)) {
452 DEBUG(6, ("Granting FSRVP op, administrators group member\n"));
455 if (nt_token_check_sid(&global_sid_Builtin_Backup_Operators
,
456 session_info
->security_token
)) {
457 DEBUG(6, ("Granting FSRVP op, backup operators group member\n"));
460 if (security_token_has_privilege(session_info
->security_token
,
462 DEBUG(6, ("Granting FSRVP op, backup privilege present\n"));
466 DEBUG(2, ("FSRVP operation blocked due to lack of backup privilege "
467 "or Administrators/Backup Operators group membership\n"));
472 static void fss_seq_tout_handler(struct tevent_context
*ev
,
473 struct tevent_timer
*te
,
477 struct GUID
*sc_set_id
= NULL
;
478 struct fss_sc_set
*sc_set
;
481 * MS-FSRVP: 3.1.5 Timer Events
482 * Message Sequence Timer elapses: When the Message Sequence Timer
483 * elapses, the server MUST delete the ShadowCopySet in the
484 * GlobalShadowCopySetTable where ShadowCopySet.Status is not equal to
485 * "Recovered", ContextSet MUST be set to FALSE, and the ShadowCopySet
486 * object MUST be freed.
488 DEBUG(2, ("FSRVP msg seq timeout fired\n"));
490 if (private_data
== NULL
) {
491 DEBUG(4, ("timeout without sc_set\n"));
495 sc_set_id
= talloc_get_type_abort(private_data
, struct GUID
);
496 sc_set
= sc_set_lookup(fss_global
.sc_sets
, sc_set_id
);
497 if (sc_set
== NULL
) {
498 DEBUG(0, ("timeout for unknown sc_set\n"));
500 } else if ((sc_set
->state
== FSS_SC_EXPOSED
)
501 || (sc_set
->state
== FSS_SC_RECOVERED
)) {
502 DEBUG(2, ("timeout for finished sc_set %s\n", sc_set
->id_str
));
505 DEBUG(2, ("cleaning up sc_set %s\n", sc_set
->id_str
));
506 SMB_ASSERT(fss_global
.sc_sets_count
> 0);
507 DLIST_REMOVE(fss_global
.sc_sets
, sc_set
);
508 fss_global
.sc_sets_count
--;
512 fss_global
.ctx_set
= false;
513 fss_global
.seq_tmr
= NULL
;
514 talloc_free(sc_set_id
);
517 static void fss_seq_tout_set(TALLOC_CTX
*mem_ctx
,
519 struct fss_sc_set
*sc_set
,
520 struct tevent_timer
**tmr_out
)
522 struct tevent_timer
*tmr
;
523 struct GUID
*sc_set_id
= NULL
;
526 /* allow changes to timeout for testing/debugging purposes */
527 tout
= lp_parm_int(GLOBAL_SECTION_SNUM
, "fss",
528 "sequence timeout", timeout_s
);
530 DEBUG(2, ("FSRVP message sequence timeout disabled\n"));
536 /* don't use talloc_memdup(), need explicit type for callback */
537 sc_set_id
= talloc(mem_ctx
, struct GUID
);
538 if (sc_set_id
== NULL
) {
539 smb_panic("no memory");
541 memcpy(sc_set_id
, &sc_set
->id
, sizeof(*sc_set_id
));
544 tmr
= tevent_add_timer(global_event_context(),
546 timeval_current_ofs(tout
, 0),
547 fss_seq_tout_handler
, sc_set_id
);
549 talloc_free(sc_set_id
);
550 smb_panic("no memory");
556 uint32_t _fss_GetSupportedVersion(struct pipes_struct
*p
,
557 struct fss_GetSupportedVersion
*r
)
559 if (!fss_permitted(p
)) {
560 return HRES_ERROR_V(HRES_E_ACCESSDENIED
);
563 *r
->out
.MinVersion
= fss_global
.min_vers
;
564 *r
->out
.MaxVersion
= fss_global
.max_vers
;
569 uint32_t _fss_SetContext(struct pipes_struct
*p
,
570 struct fss_SetContext
*r
)
572 if (!fss_permitted(p
)) {
573 return HRES_ERROR_V(HRES_E_ACCESSDENIED
);
576 /* ATTR_AUTO_RECOVERY flag can be applied to any */
577 switch (r
->in
.Context
& (~ATTR_AUTO_RECOVERY
)) {
578 case FSRVP_CTX_BACKUP
:
579 DEBUG(6, ("fss ctx set backup\n"));
581 case FSRVP_CTX_FILE_SHARE_BACKUP
:
582 DEBUG(6, ("fss ctx set file share backup\n"));
584 case FSRVP_CTX_NAS_ROLLBACK
:
585 DEBUG(6, ("fss ctx set nas rollback\n"));
587 case FSRVP_CTX_APP_ROLLBACK
:
588 DEBUG(6, ("fss ctx set app rollback\n"));
591 DEBUG(0, ("invalid fss ctx set value: 0x%x\n", r
->in
.Context
));
592 return HRES_ERROR_V(HRES_E_INVALIDARG
);
593 break; /* not reached */
596 fss_global
.ctx_set
= true;
597 fss_global
.cur_ctx
= r
->in
.Context
;
599 TALLOC_FREE(fss_global
.seq_tmr
); /* kill timer if running */
600 fss_seq_tout_set(fss_global
.mem_ctx
, 180, NULL
, &fss_global
.seq_tmr
);
602 fss_global
.cur_ctx
= r
->in
.Context
;
607 static bool sc_set_active(struct fss_sc_set
*sc_set_head
)
610 struct fss_sc_set
*sc_set
;
612 for (sc_set
= sc_set_head
; sc_set
; sc_set
= sc_set
->next
) {
613 if ((sc_set
->state
!= FSS_SC_EXPOSED
)
614 && (sc_set
->state
!= FSS_SC_RECOVERED
)) {
622 uint32_t _fss_StartShadowCopySet(struct pipes_struct
*p
,
623 struct fss_StartShadowCopySet
*r
)
625 struct fss_sc_set
*sc_set
;
628 if (!fss_permitted(p
)) {
629 ret
= HRES_ERROR_V(HRES_E_ACCESSDENIED
);
633 if (!fss_global
.ctx_set
) {
634 DEBUG(3, ("invalid sequence: start sc set requested without "
635 "prior context set\n"));
636 ret
= FSRVP_E_BAD_STATE
;
641 * At any given time, Windows servers allow only one shadow copy set to
642 * be going through the creation process.
644 if (sc_set_active(fss_global
.sc_sets
)) {
645 DEBUG(3, ("StartShadowCopySet called while in progress\n"));
646 ret
= FSRVP_E_SHADOW_COPY_SET_IN_PROGRESS
;
650 /* stop msg seq timer */
651 TALLOC_FREE(fss_global
.seq_tmr
);
653 sc_set
= talloc_zero(fss_global
.mem_ctx
, struct fss_sc_set
);
654 if (sc_set
== NULL
) {
655 ret
= HRES_ERROR_V(HRES_E_OUTOFMEMORY
);
656 goto err_tmr_restart
;
659 sc_set
->id
= GUID_random(); /* Windows servers ignore client ids */
660 sc_set
->id_str
= GUID_string(sc_set
, &sc_set
->id
);
661 if (sc_set
->id_str
== NULL
) {
662 ret
= HRES_ERROR_V(HRES_E_OUTOFMEMORY
);
663 goto err_sc_set_free
;
665 sc_set
->state
= FSS_SC_STARTED
;
666 sc_set
->context
= fss_global
.cur_ctx
;
667 DLIST_ADD_END(fss_global
.sc_sets
, sc_set
);
668 fss_global
.sc_sets_count
++;
669 DEBUG(6, ("%s: shadow-copy set %u added\n",
670 sc_set
->id_str
, fss_global
.sc_sets_count
));
672 /* start msg seq timer */
673 fss_seq_tout_set(fss_global
.mem_ctx
, 180, sc_set
, &fss_global
.seq_tmr
);
675 r
->out
.pShadowCopySetId
= &sc_set
->id
;
682 fss_seq_tout_set(fss_global
.mem_ctx
, 180, NULL
, &fss_global
.seq_tmr
);
687 static uint32_t map_share_name(struct fss_sc_smap
*sc_smap
,
688 const struct fss_sc
*sc
)
690 bool hidden_base
= false;
692 if (*(sc_smap
->share_name
+ strlen(sc_smap
->share_name
) - 1) == '$') {
694 * If MappedShare.ShareName ends with a $ character (meaning
695 * that the share is hidden), then the exposed share name will
696 * have the $ suffix appended.
697 * FIXME: turns out Windows doesn't do this, contrary to docs
702 sc_smap
->sc_share_name
= talloc_asprintf(sc_smap
, "%s@{%s}%s",
705 hidden_base
? "$" : "");
706 if (sc_smap
->sc_share_name
== NULL
) {
707 return HRES_ERROR_V(HRES_E_OUTOFMEMORY
);
713 static uint32_t map_share_comment(struct fss_sc_smap
*sc_smap
,
714 const struct fss_sc
*sc
)
718 time_str
= http_timestring(sc_smap
, sc
->create_ts
);
719 if (time_str
== NULL
) {
720 return HRES_ERROR_V(HRES_E_OUTOFMEMORY
);
723 sc_smap
->sc_share_comment
= talloc_asprintf(sc_smap
, "Shadow copy of %s taken %s",
724 sc_smap
->share_name
, time_str
);
725 if (sc_smap
->sc_share_comment
== NULL
) {
726 return HRES_ERROR_V(HRES_E_OUTOFMEMORY
);
732 uint32_t _fss_AddToShadowCopySet(struct pipes_struct
*p
,
733 struct fss_AddToShadowCopySet
*r
)
735 struct dcesrv_call_state
*dce_call
= p
->dce_call
;
736 struct auth_session_info
*session_info
=
737 dcesrv_call_session_info(dce_call
);
739 struct fss_sc_set
*sc_set
;
741 struct fss_sc_smap
*sc_smap
;
747 struct connection_struct
*conn
;
749 TALLOC_CTX
*frame
= talloc_stackframe();
750 const struct loadparm_substitution
*lp_sub
=
751 loadparm_s3_global_substitution();
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
, lp_sub
, snum
);
778 if (path_name
== NULL
) {
779 ret
= HRES_ERROR_V(HRES_E_OUTOFMEMORY
);
783 status
= fss_conn_create_tos(p
->msg_ctx
, session_info
, snum
, &conn
);
784 if (!NT_STATUS_IS_OK(status
)) {
785 ret
= HRES_ERROR_V(HRES_E_ACCESSDENIED
);
788 if (!become_user_without_service_by_session(conn
, session_info
)) {
789 DEBUG(0, ("failed to become user\n"));
790 ret
= HRES_ERROR_V(HRES_E_ACCESSDENIED
);
794 status
= SMB_VFS_SNAP_CHECK_PATH(conn
, frame
, path_name
, &base_vol
);
795 unbecome_user_without_service();
796 if (!NT_STATUS_IS_OK(status
)) {
797 ret
= FSRVP_E_NOT_SUPPORTED
;
801 if ((sc_set
->state
!= FSS_SC_STARTED
)
802 && (sc_set
->state
!= FSS_SC_ADDED
)) {
803 ret
= FSRVP_E_BAD_STATE
;
807 /* stop msg seq timer */
808 TALLOC_FREE(fss_global
.seq_tmr
);
811 * server MUST look up the ShadowCopy in ShadowCopySet.ShadowCopyList
812 * where ShadowCopy.VolumeName matches the file store on which the
813 * share identified by ShareName is hosted. If an entry is found, the
814 * server MUST fail the call with FSRVP_E_OBJECT_ALREADY_EXISTS.
815 * If no entry is found, the server MUST create a new ShadowCopy
817 * XXX Windows appears to allow multiple mappings for the same vol!
819 sc
= sc_lookup_volname(sc_set
->scs
, base_vol
);
821 ret
= FSRVP_E_OBJECT_ALREADY_EXISTS
;
822 goto err_tmr_restart
;
825 sc
= talloc_zero(sc_set
, struct fss_sc
);
827 ret
= HRES_ERROR_V(HRES_E_OUTOFMEMORY
);
828 goto err_tmr_restart
;
830 talloc_steal(sc
, base_vol
);
831 sc
->volume_name
= base_vol
;
833 sc
->create_ts
= time(NULL
);
835 sc
->id
= GUID_random(); /* Windows servers ignore client ids */
836 sc
->id_str
= GUID_string(sc
, &sc
->id
);
837 if (sc
->id_str
== NULL
) {
838 ret
= HRES_ERROR_V(HRES_E_OUTOFMEMORY
);
842 sc_smap
= talloc_zero(sc
, struct fss_sc_smap
);
843 if (sc_smap
== NULL
) {
844 ret
= HRES_ERROR_V(HRES_E_OUTOFMEMORY
);
848 talloc_steal(sc_smap
, service
);
849 sc_smap
->share_name
= service
;
850 sc_smap
->is_exposed
= false;
852 * generate the sc_smap share name now. It is a unique identifier for
853 * the smap used as a tdb key for state storage.
855 ret
= map_share_name(sc_smap
, sc
);
860 /* add share map to shadow-copy */
861 DLIST_ADD_END(sc
->smaps
, sc_smap
);
863 /* add shadow-copy to shadow-copy set */
864 DLIST_ADD_END(sc_set
->scs
, sc
);
866 DEBUG(4, ("added volume %s to shadow copy set with GUID %s\n",
867 sc
->volume_name
, sc_set
->id_str
));
869 /* start the Message Sequence Timer with timeout of 1800 seconds */
870 fss_seq_tout_set(fss_global
.mem_ctx
, 1800, sc_set
, &fss_global
.seq_tmr
);
872 sc_set
->state
= FSS_SC_ADDED
;
873 r
->out
.pShadowCopyId
= &sc
->id
;
881 fss_seq_tout_set(fss_global
.mem_ctx
, 180, sc_set
, &fss_global
.seq_tmr
);
887 static NTSTATUS
commit_sc_with_conn(TALLOC_CTX
*mem_ctx
,
888 struct tevent_context
*ev
,
889 struct messaging_context
*msg_ctx
,
890 struct auth_session_info
*session_info
,
895 TALLOC_CTX
*frame
= talloc_stackframe();
898 struct connection_struct
*conn
;
902 snum
= find_service(frame
, sc
->smaps
->share_name
, &service
);
903 if ((snum
== -1) || (service
== NULL
)) {
904 DEBUG(0, ("share at %s not found\n", sc
->smaps
->share_name
));
906 return NT_STATUS_UNSUCCESSFUL
;
909 status
= fss_conn_create_tos(msg_ctx
, session_info
, snum
, &conn
);
910 if (!NT_STATUS_IS_OK(status
)) {
915 if (!become_user_without_service_by_session(conn
, session_info
)) {
916 DEBUG(0, ("failed to become user\n"));
918 return NT_STATUS_ACCESS_DENIED
;
920 rw
= ((sc
->sc_set
->context
& ATTR_AUTO_RECOVERY
) == ATTR_AUTO_RECOVERY
);
921 status
= SMB_VFS_SNAP_CREATE(conn
, mem_ctx
,
924 base_path
, snap_path
);
925 unbecome_user_without_service();
926 if (!NT_STATUS_IS_OK(status
)) {
927 DEBUG(0, ("snap create failed: %s\n", nt_errstr(status
)));
936 uint32_t _fss_CommitShadowCopySet(struct pipes_struct
*p
,
937 struct fss_CommitShadowCopySet
*r
)
939 struct dcesrv_call_state
*dce_call
= p
->dce_call
;
940 struct auth_session_info
*session_info
=
941 dcesrv_call_session_info(dce_call
);
942 struct fss_sc_set
*sc_set
;
944 uint32_t commit_count
;
946 NTSTATUS saved_status
;
947 TALLOC_CTX
*frame
= talloc_stackframe();
949 if (!fss_permitted(p
)) {
950 status
= NT_STATUS_ACCESS_DENIED
;
954 sc_set
= sc_set_lookup(fss_global
.sc_sets
, &r
->in
.ShadowCopySetId
);
955 if (sc_set
== NULL
) {
956 status
= NT_STATUS_INVALID_PARAMETER
;
960 if (sc_set
->state
!= FSS_SC_ADDED
) {
961 status
= NT_STATUS_INVALID_SERVER_STATE
;
965 /* stop Message Sequence Timer */
966 TALLOC_FREE(fss_global
.seq_tmr
);
967 sc_set
->state
= FSS_SC_CREATING
;
969 saved_status
= NT_STATUS_OK
;
970 for (sc
= sc_set
->scs
; sc
; sc
= sc
->next
) {
973 status
= commit_sc_with_conn(frame
, global_event_context(),
974 p
->msg_ctx
, session_info
, sc
,
975 &base_path
, &snap_path
);
976 if (!NT_STATUS_IS_OK(status
)) {
977 DEBUG(0, ("snap create failed for shadow copy of "
978 "%s\n", sc
->volume_name
));
979 /* dispatch all scs in set, but retain last error */
980 saved_status
= status
;
983 /* XXX set timeout r->in.TimeOutInMilliseconds */
985 DEBUG(10, ("good snap create %d\n",
987 sc
->sc_path
= talloc_steal(sc
, snap_path
);
989 if (!NT_STATUS_IS_OK(saved_status
)) {
990 status
= saved_status
;
991 goto err_state_revert
;
994 sc_set
->state
= FSS_SC_COMMITED
;
996 status
= fss_state_store(fss_global
.mem_ctx
, fss_global
.sc_sets
,
997 fss_global
.sc_sets_count
,
1000 if (!NT_STATUS_IS_OK(status
)) {
1001 DEBUG(1, ("failed to store fss server state: %s\n",
1002 nt_errstr(status
)));
1005 fss_seq_tout_set(fss_global
.mem_ctx
, 180, sc_set
,
1006 &fss_global
.seq_tmr
);
1011 sc_set
->state
= FSS_SC_ADDED
;
1012 fss_seq_tout_set(fss_global
.mem_ctx
, 180, sc_set
,
1013 &fss_global
.seq_tmr
);
1016 return fss_ntstatus_map(status
);
1019 static sbcErr
fss_conf_get_share_def(struct smbconf_ctx
*fconf_ctx
,
1020 struct smbconf_ctx
*rconf_ctx
,
1021 TALLOC_CTX
*mem_ctx
,
1023 struct smbconf_service
**service_def
)
1026 struct smbconf_service
*def
;
1028 *service_def
= NULL
;
1029 cerr
= smbconf_get_share(fconf_ctx
, mem_ctx
, share
, &def
);
1030 if (SBC_ERROR_IS_OK(cerr
)) {
1035 cerr
= smbconf_get_share(rconf_ctx
, mem_ctx
, share
, &def
);
1036 if (SBC_ERROR_IS_OK(cerr
)) {
1044 * Expose a new share using libsmbconf, cloning the existing configuration
1045 * from the base share. The base share may be defined in either the registry
1047 * XXX this is called as root
1049 static uint32_t fss_sc_expose(struct smbconf_ctx
*fconf_ctx
,
1050 struct smbconf_ctx
*rconf_ctx
,
1051 TALLOC_CTX
*mem_ctx
,
1054 struct fss_sc_smap
*sc_smap
;
1057 for (sc_smap
= sc
->smaps
; sc_smap
; sc_smap
= sc_smap
->next
) {
1059 struct smbconf_service
*base_service
= NULL
;
1060 struct security_descriptor
*sd
;
1063 cerr
= fss_conf_get_share_def(fconf_ctx
, rconf_ctx
, mem_ctx
,
1064 sc_smap
->share_name
, &base_service
);
1065 if (!SBC_ERROR_IS_OK(cerr
)) {
1066 DEBUG(0, ("failed to get base share %s definition: "
1067 "%s\n", sc_smap
->share_name
,
1068 sbcErrorString(cerr
)));
1069 err
= HRES_ERROR_V(HRES_E_FAIL
);
1073 /* smap share name already defined when added */
1074 err
= map_share_comment(sc_smap
, sc
);
1076 DEBUG(0, ("failed to map share comment\n"));
1080 base_service
->name
= sc_smap
->sc_share_name
;
1082 cerr
= smbconf_create_set_share(rconf_ctx
, base_service
);
1083 if (!SBC_ERROR_IS_OK(cerr
)) {
1084 DEBUG(0, ("failed to create share %s: %s\n",
1085 base_service
->name
, sbcErrorString(cerr
)));
1086 err
= HRES_ERROR_V(HRES_E_FAIL
);
1089 cerr
= smbconf_set_parameter(rconf_ctx
, sc_smap
->sc_share_name
,
1090 "path", sc
->sc_path
);
1091 if (!SBC_ERROR_IS_OK(cerr
)) {
1092 DEBUG(0, ("failed to set path param: %s\n",
1093 sbcErrorString(cerr
)));
1094 err
= HRES_ERROR_V(HRES_E_FAIL
);
1097 if (sc_smap
->sc_share_comment
!= NULL
) {
1098 cerr
= smbconf_set_parameter(rconf_ctx
,
1099 sc_smap
->sc_share_name
,
1101 sc_smap
->sc_share_comment
);
1102 if (!SBC_ERROR_IS_OK(cerr
)) {
1103 DEBUG(0, ("failed to set comment param: %s\n",
1104 sbcErrorString(cerr
)));
1105 err
= HRES_ERROR_V(HRES_E_FAIL
);
1109 talloc_free(base_service
);
1112 * Obtain the base share SD, which also needs to be cloned.
1113 * Share SDs are stored in share_info.tdb, so are not covered by
1114 * the registry transaction.
1115 * The base share SD should be cloned at the time of exposure,
1116 * rather than when the snapshot is taken. This matches Windows
1117 * Server 2012 behaviour.
1119 sd
= get_share_security(mem_ctx
, sc_smap
->share_name
, &sd_size
);
1121 DEBUG(2, ("no share SD to clone for %s snapshot\n",
1122 sc_smap
->share_name
));
1125 status
= set_share_security(sc_smap
->sc_share_name
, sd
);
1127 if (!NT_STATUS_IS_OK(status
)) {
1128 DEBUG(0, ("failed to set %s share SD\n",
1129 sc_smap
->sc_share_name
));
1130 err
= HRES_ERROR_V(HRES_E_FAIL
);
1139 uint32_t _fss_ExposeShadowCopySet(struct pipes_struct
*p
,
1140 struct fss_ExposeShadowCopySet
*r
)
1143 struct fss_sc_set
*sc_set
;
1146 struct smbconf_ctx
*fconf_ctx
;
1147 struct smbconf_ctx
*rconf_ctx
;
1150 TALLOC_CTX
*frame
= talloc_stackframe();
1152 if (!fss_permitted(p
)) {
1153 ret
= HRES_ERROR_V(HRES_E_ACCESSDENIED
);
1157 sc_set
= sc_set_lookup(fss_global
.sc_sets
, &r
->in
.ShadowCopySetId
);
1158 if (sc_set
== NULL
) {
1159 ret
= HRES_ERROR_V(HRES_E_INVALIDARG
);
1163 if (sc_set
->state
!= FSS_SC_COMMITED
) {
1164 ret
= FSRVP_E_BAD_STATE
;
1168 /* stop message sequence timer */
1169 TALLOC_FREE(fss_global
.seq_tmr
);
1172 * Prepare to clone the base share definition for the snapshot share.
1173 * Create both registry and file conf contexts, as the base share
1174 * definition may be located in either. The snapshot share definition
1175 * is always written to the registry.
1177 cerr
= smbconf_init(frame
, &rconf_ctx
, "registry");
1178 if (!SBC_ERROR_IS_OK(cerr
)) {
1179 DEBUG(0, ("failed registry smbconf init: %s\n",
1180 sbcErrorString(cerr
)));
1181 ret
= HRES_ERROR_V(HRES_E_FAIL
);
1182 goto err_tmr_restart
;
1184 fconf_path
= talloc_asprintf(frame
, "file:%s", get_dyn_CONFIGFILE());
1185 if (fconf_path
== NULL
) {
1186 ret
= HRES_ERROR_V(HRES_E_OUTOFMEMORY
);
1187 goto err_tmr_restart
;
1189 cerr
= smbconf_init(frame
, &fconf_ctx
, fconf_path
);
1190 if (!SBC_ERROR_IS_OK(cerr
)) {
1191 DEBUG(0, ("failed %s smbconf init: %s\n",
1192 fconf_path
, sbcErrorString(cerr
)));
1193 ret
= HRES_ERROR_V(HRES_E_FAIL
);
1194 goto err_tmr_restart
;
1197 /* registry IO must be done as root */
1199 cerr
= smbconf_transaction_start(rconf_ctx
);
1200 if (!SBC_ERROR_IS_OK(cerr
)) {
1201 DEBUG(0, ("error starting transaction: %s\n",
1202 sbcErrorString(cerr
)));
1203 ret
= HRES_ERROR_V(HRES_E_FAIL
);
1205 goto err_tmr_restart
;
1208 for (sc
= sc_set
->scs
; sc
; sc
= sc
->next
) {
1209 ret
= fss_sc_expose(fconf_ctx
, rconf_ctx
, frame
, sc
);
1211 DEBUG(0,("failed to expose shadow copy of %s\n",
1217 cerr
= smbconf_transaction_commit(rconf_ctx
);
1218 if (!SBC_ERROR_IS_OK(cerr
)) {
1219 DEBUG(0, ("error committing transaction: %s\n",
1220 sbcErrorString(cerr
)));
1221 ret
= HRES_ERROR_V(HRES_E_FAIL
);
1226 messaging_send_all(p
->msg_ctx
, MSG_SMB_CONF_UPDATED
, NULL
, 0);
1227 for (sc
= sc_set
->scs
; sc
; sc
= sc
->next
) {
1228 struct fss_sc_smap
*sm
;
1229 for (sm
= sc
->smaps
; sm
; sm
= sm
->next
)
1230 sm
->is_exposed
= true;
1232 sc_set
->state
= FSS_SC_EXPOSED
;
1234 status
= fss_state_store(fss_global
.mem_ctx
, fss_global
.sc_sets
,
1235 fss_global
.sc_sets_count
, fss_global
.db_path
);
1237 if (!NT_STATUS_IS_OK(status
)) {
1238 DEBUG(1, ("failed to store fss server state: %s\n",
1239 nt_errstr(status
)));
1241 /* start message sequence timer */
1242 fss_seq_tout_set(fss_global
.mem_ctx
, 180, sc_set
, &fss_global
.seq_tmr
);
1247 smbconf_transaction_cancel(rconf_ctx
);
1250 fss_seq_tout_set(fss_global
.mem_ctx
, 180, sc_set
, &fss_global
.seq_tmr
);
1256 uint32_t _fss_RecoveryCompleteShadowCopySet(struct pipes_struct
*p
,
1257 struct fss_RecoveryCompleteShadowCopySet
*r
)
1260 struct fss_sc_set
*sc_set
;
1262 if (!fss_permitted(p
)) {
1263 return HRES_ERROR_V(HRES_E_ACCESSDENIED
);
1266 sc_set
= sc_set_lookup(fss_global
.sc_sets
, &r
->in
.ShadowCopySetId
);
1267 if (sc_set
== NULL
) {
1268 return HRES_ERROR_V(HRES_E_INVALIDARG
);
1271 if (sc_set
->state
!= FSS_SC_EXPOSED
) {
1272 return FSRVP_E_BAD_STATE
;
1275 /* stop msg sequence timer */
1276 TALLOC_FREE(fss_global
.seq_tmr
);
1278 if (sc_set
->context
& ATTR_NO_AUTO_RECOVERY
) {
1279 /* TODO set read-only */
1282 sc_set
->state
= FSS_SC_RECOVERED
;
1283 fss_global
.cur_ctx
= 0;
1284 fss_global
.ctx_set
= false;
1287 status
= fss_state_store(fss_global
.mem_ctx
, fss_global
.sc_sets
,
1288 fss_global
.sc_sets_count
, fss_global
.db_path
);
1290 if (!NT_STATUS_IS_OK(status
)) {
1291 DEBUG(1, ("failed to store fss server state: %s\n",
1292 nt_errstr(status
)));
1298 uint32_t _fss_AbortShadowCopySet(struct pipes_struct
*p
,
1299 struct fss_AbortShadowCopySet
*r
)
1302 struct fss_sc_set
*sc_set
;
1304 if (!fss_permitted(p
)) {
1305 return HRES_ERROR_V(HRES_E_ACCESSDENIED
);
1308 sc_set
= sc_set_lookup(fss_global
.sc_sets
, &r
->in
.ShadowCopySetId
);
1309 if (sc_set
== NULL
) {
1310 return HRES_ERROR_V(HRES_E_INVALIDARG
);
1313 DEBUG(6, ("%s: aborting shadow-copy set\n", sc_set
->id_str
));
1315 if ((sc_set
->state
== FSS_SC_COMMITED
)
1316 || (sc_set
->state
== FSS_SC_EXPOSED
)
1317 || (sc_set
->state
== FSS_SC_RECOVERED
)) {
1321 if (sc_set
->state
== FSS_SC_CREATING
) {
1322 return FSRVP_E_BAD_STATE
;
1325 DLIST_REMOVE(fss_global
.sc_sets
, sc_set
);
1326 talloc_free(sc_set
);
1327 fss_global
.sc_sets_count
--;
1329 status
= fss_state_store(fss_global
.mem_ctx
, fss_global
.sc_sets
,
1330 fss_global
.sc_sets_count
, fss_global
.db_path
);
1332 if (!NT_STATUS_IS_OK(status
)) {
1333 DEBUG(1, ("failed to store fss server state: %s\n",
1334 nt_errstr(status
)));
1340 uint32_t _fss_IsPathSupported(struct pipes_struct
*p
,
1341 struct fss_IsPathSupported
*r
)
1343 struct dcesrv_call_state
*dce_call
= p
->dce_call
;
1344 struct auth_session_info
*session_info
=
1345 dcesrv_call_session_info(dce_call
);
1350 struct connection_struct
*conn
;
1352 TALLOC_CTX
*frame
= talloc_stackframe();
1353 const struct loadparm_substitution
*lp_sub
=
1354 loadparm_s3_global_substitution();
1356 if (!fss_permitted(p
)) {
1358 return HRES_ERROR_V(HRES_E_ACCESSDENIED
);
1361 status
= fss_unc_parse(frame
, r
->in
.ShareName
, NULL
, &share
);
1362 if (!NT_STATUS_IS_OK(status
)) {
1364 return fss_ntstatus_map(status
);
1367 snum
= find_service(frame
, share
, &service
);
1368 if ((snum
== -1) || (service
== NULL
)) {
1369 DEBUG(0, ("share at %s not found\n", r
->in
.ShareName
));
1371 return HRES_ERROR_V(HRES_E_INVALIDARG
);
1374 status
= fss_conn_create_tos(p
->msg_ctx
, session_info
, snum
, &conn
);
1375 if (!NT_STATUS_IS_OK(status
)) {
1377 return HRES_ERROR_V(HRES_E_ACCESSDENIED
);
1379 if (!become_user_without_service_by_session(conn
, session_info
)) {
1380 DEBUG(0, ("failed to become user\n"));
1382 return HRES_ERROR_V(HRES_E_ACCESSDENIED
);
1384 status
= SMB_VFS_SNAP_CHECK_PATH(conn
, frame
,
1385 lp_path(frame
, lp_sub
, snum
),
1387 unbecome_user_without_service();
1388 if (!NT_STATUS_IS_OK(status
)) {
1390 return FSRVP_E_NOT_SUPPORTED
;
1393 *r
->out
.OwnerMachineName
= lp_netbios_name();
1394 *r
->out
.SupportedByThisProvider
= 1;
1399 uint32_t _fss_IsPathShadowCopied(struct pipes_struct
*p
,
1400 struct fss_IsPathShadowCopied
*r
)
1402 if (!fss_permitted(p
)) {
1403 return HRES_ERROR_V(HRES_E_ACCESSDENIED
);
1406 /* not yet supported */
1407 return FSRVP_E_NOT_SUPPORTED
;
1410 uint32_t _fss_GetShareMapping(struct pipes_struct
*p
,
1411 struct fss_GetShareMapping
*r
)
1414 struct fss_sc_set
*sc_set
;
1416 struct fss_sc_smap
*sc_smap
;
1418 struct fssagent_share_mapping_1
*sm_out
;
1419 TALLOC_CTX
*frame
= talloc_stackframe();
1421 if (!fss_permitted(p
)) {
1423 return HRES_ERROR_V(HRES_E_ACCESSDENIED
);
1426 sc_set
= sc_set_lookup(fss_global
.sc_sets
, &r
->in
.ShadowCopySetId
);
1427 if (sc_set
== NULL
) {
1429 return HRES_ERROR_V(HRES_E_INVALIDARG
);
1433 * If ShadowCopySet.Status is not "Exposed", the server SHOULD<9> fail
1434 * the call with FSRVP_E_BAD_STATE.
1435 * <9> If ShadowCopySet.Status is "Started", "Added",
1436 * "CreationInProgress", or "Committed", Windows Server 2012 FSRVP
1437 * servers return an error value of 0x80042311.
1439 if ((sc_set
->state
== FSS_SC_STARTED
)
1440 || (sc_set
->state
== FSS_SC_ADDED
)
1441 || (sc_set
->state
== FSS_SC_CREATING
)
1442 || (sc_set
->state
== FSS_SC_COMMITED
)) {
1444 return 0x80042311; /* documented magic value */
1447 sc
= sc_lookup(sc_set
->scs
, &r
->in
.ShadowCopyId
);
1450 return HRES_ERROR_V(HRES_E_INVALIDARG
);
1453 status
= fss_unc_parse(frame
, r
->in
.ShareName
, NULL
, &share
);
1454 if (!NT_STATUS_IS_OK(status
)) {
1456 return fss_ntstatus_map(status
);
1459 sc_smap
= sc_smap_lookup(sc
->smaps
, share
);
1460 if (sc_smap
== NULL
) {
1462 return HRES_ERROR_V(HRES_E_INVALIDARG
);
1465 if (r
->in
.Level
!= 1) {
1467 return HRES_ERROR_V(HRES_E_INVALIDARG
);
1470 sm_out
= talloc_zero(p
->mem_ctx
, struct fssagent_share_mapping_1
);
1471 if (sm_out
== NULL
) {
1473 return HRES_ERROR_V(HRES_E_OUTOFMEMORY
);
1475 sm_out
->ShadowCopySetId
= sc_set
->id
;
1476 sm_out
->ShadowCopyId
= sc
->id
;
1477 sm_out
->ShareNameUNC
= talloc_asprintf(sm_out
, "\\\\%s\\%s",
1479 sc_smap
->share_name
);
1480 if (sm_out
->ShareNameUNC
== NULL
) {
1481 talloc_free(sm_out
);
1483 return HRES_ERROR_V(HRES_E_OUTOFMEMORY
);
1485 sm_out
->ShadowCopyShareName
= sc_smap
->sc_share_name
;
1486 unix_to_nt_time(&sm_out
->tstamp
, sc
->create_ts
);
1487 r
->out
.ShareMapping
->ShareMapping1
= sm_out
;
1490 /* reset msg sequence timer */
1491 TALLOC_FREE(fss_global
.seq_tmr
);
1492 fss_seq_tout_set(fss_global
.mem_ctx
, 1800, sc_set
, &fss_global
.seq_tmr
);
1497 static NTSTATUS
sc_smap_unexpose(struct messaging_context
*msg_ctx
,
1498 struct fss_sc_smap
*sc_smap
, bool delete_all
)
1501 struct smbconf_ctx
*conf_ctx
;
1503 bool is_modified
= false;
1504 TALLOC_CTX
*frame
= talloc_stackframe();
1506 cerr
= smbconf_init(frame
, &conf_ctx
, "registry");
1507 if (!SBC_ERROR_IS_OK(cerr
)) {
1508 DEBUG(0, ("failed registry smbconf init: %s\n",
1509 sbcErrorString(cerr
)));
1510 ret
= NT_STATUS_UNSUCCESSFUL
;
1514 /* registry IO must be done as root */
1517 cerr
= smbconf_transaction_start(conf_ctx
);
1518 if (!SBC_ERROR_IS_OK(cerr
)) {
1519 DEBUG(0, ("error starting transaction: %s\n",
1520 sbcErrorString(cerr
)));
1521 ret
= NT_STATUS_UNSUCCESSFUL
;
1526 struct fss_sc_smap
*sc_map_next
= sc_smap
->next
;
1527 if (!smbconf_share_exists(conf_ctx
, sc_smap
->sc_share_name
)) {
1528 DEBUG(2, ("no such share: %s\n", sc_smap
->sc_share_name
));
1533 sc_smap
= sc_map_next
;
1537 cerr
= smbconf_delete_share(conf_ctx
, sc_smap
->sc_share_name
);
1538 if (!SBC_ERROR_IS_OK(cerr
)) {
1539 DEBUG(0, ("error deleting share: %s\n",
1540 sbcErrorString(cerr
)));
1541 ret
= NT_STATUS_UNSUCCESSFUL
;
1545 sc_smap
->is_exposed
= false;
1547 sc_smap
= sc_map_next
;
1549 sc_smap
= NULL
; /* only process single sc_map entry */
1553 cerr
= smbconf_transaction_commit(conf_ctx
);
1554 if (!SBC_ERROR_IS_OK(cerr
)) {
1555 DEBUG(0, ("error committing transaction: %s\n",
1556 sbcErrorString(cerr
)));
1557 ret
= NT_STATUS_UNSUCCESSFUL
;
1560 messaging_send_all(msg_ctx
, MSG_SMB_CONF_UPDATED
, NULL
, 0);
1568 talloc_free(conf_ctx
);
1575 smbconf_transaction_cancel(conf_ctx
);
1576 talloc_free(conf_ctx
);
1582 uint32_t _fss_DeleteShareMapping(struct pipes_struct
*p
,
1583 struct fss_DeleteShareMapping
*r
)
1585 struct dcesrv_call_state
*dce_call
= p
->dce_call
;
1586 struct auth_session_info
*session_info
=
1587 dcesrv_call_session_info(dce_call
);
1588 struct fss_sc_set
*sc_set
;
1590 struct fss_sc_smap
*sc_smap
;
1593 TALLOC_CTX
*frame
= talloc_stackframe();
1594 struct connection_struct
*conn
;
1598 if (!fss_permitted(p
)) {
1599 status
= NT_STATUS_ACCESS_DENIED
;
1603 sc_set
= sc_set_lookup(fss_global
.sc_sets
, &r
->in
.ShadowCopySetId
);
1604 if (sc_set
== NULL
) {
1605 /* docs say HRES_E_INVALIDARG */
1606 status
= NT_STATUS_OBJECTID_NOT_FOUND
;
1610 if ((sc_set
->state
!= FSS_SC_EXPOSED
)
1611 && (sc_set
->state
!= FSS_SC_RECOVERED
)) {
1612 status
= NT_STATUS_INVALID_SERVER_STATE
;
1616 sc
= sc_lookup(sc_set
->scs
, &r
->in
.ShadowCopyId
);
1618 status
= NT_STATUS_INVALID_PARAMETER
;
1622 status
= fss_unc_parse(frame
, r
->in
.ShareName
, NULL
, &share
);
1623 if (!NT_STATUS_IS_OK(status
)) {
1627 sc_smap
= sc_smap_lookup(sc
->smaps
, share
);
1628 if (sc_smap
== NULL
) {
1629 status
= NT_STATUS_INVALID_PARAMETER
;
1633 status
= sc_smap_unexpose(p
->msg_ctx
, sc_smap
, false);
1634 if (!NT_STATUS_IS_OK(status
)) {
1635 DEBUG(0, ("failed to remove share %s: %s\n",
1636 sc_smap
->sc_share_name
, nt_errstr(status
)));
1640 messaging_send_all(p
->msg_ctx
, MSG_SMB_FORCE_TDIS
,
1641 sc_smap
->sc_share_name
,
1642 strlen(sc_smap
->sc_share_name
) + 1);
1644 if (sc
->smaps_count
> 1) {
1645 /* do not delete the underlying snapshot - still in use */
1646 status
= NT_STATUS_OK
;
1650 snum
= find_service(frame
, sc_smap
->share_name
, &service
);
1651 if ((snum
== -1) || (service
== NULL
)) {
1652 DEBUG(0, ("share at %s not found\n", sc_smap
->share_name
));
1653 status
= NT_STATUS_UNSUCCESSFUL
;
1657 status
= fss_conn_create_tos(p
->msg_ctx
, session_info
, snum
, &conn
);
1658 if (!NT_STATUS_IS_OK(status
)) {
1661 if (!become_user_without_service_by_session(conn
, session_info
)) {
1662 DEBUG(0, ("failed to become user\n"));
1663 status
= NT_STATUS_ACCESS_DENIED
;
1667 status
= SMB_VFS_SNAP_DELETE(conn
, frame
, sc
->volume_name
,
1669 unbecome_user_without_service();
1670 if (!NT_STATUS_IS_OK(status
)) {
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
;
1703 return fss_ntstatus_map(status
);
1706 uint32_t _fss_PrepareShadowCopySet(struct pipes_struct
*p
,
1707 struct fss_PrepareShadowCopySet
*r
)
1709 struct fss_sc_set
*sc_set
;
1711 if (!fss_permitted(p
)) {
1712 return HRES_ERROR_V(HRES_E_ACCESSDENIED
);
1715 sc_set
= sc_set_lookup(fss_global
.sc_sets
, &r
->in
.ShadowCopySetId
);
1716 if (sc_set
== NULL
) {
1717 return HRES_ERROR_V(HRES_E_INVALIDARG
);
1720 if (sc_set
->state
!= FSS_SC_ADDED
) {
1721 return FSRVP_E_BAD_STATE
;
1724 /* stop msg sequence timer */
1725 TALLOC_FREE(fss_global
.seq_tmr
);
1728 * Windows Server "8" Beta takes ~60s here, presumably flushing
1729 * everything to disk. We may want to do something similar.
1732 /* start msg sequence timer, 1800 on success */
1733 fss_seq_tout_set(fss_global
.mem_ctx
, 1800, sc_set
, &fss_global
.seq_tmr
);
1738 static NTSTATUS
FileServerVssAgent__op_init_server(
1739 struct dcesrv_context
*dce_ctx
,
1740 const struct dcesrv_endpoint_server
*ep_server
);
1742 static NTSTATUS
FileServerVssAgent__op_shutdown_server(
1743 struct dcesrv_context
*dce_ctx
,
1744 const struct dcesrv_endpoint_server
*ep_server
);
1746 #define DCESRV_INTERFACE_FILESERVERVSSAGENT_INIT_SERVER \
1747 fileservervssagent_init_server
1749 #define DCESRV_INTERFACE_FILESERVERVSSAGENT_SHUTDOWN_SERVER \
1750 fileservervssagent_shutdown_server
1752 static NTSTATUS
fileservervssagent_shutdown_server(
1753 struct dcesrv_context
*dce_ctx
,
1754 const struct dcesrv_endpoint_server
*ep_server
)
1757 return FileServerVssAgent__op_shutdown_server(dce_ctx
, ep_server
);
1760 static NTSTATUS
fileservervssagent_init_server(
1761 struct dcesrv_context
*dce_ctx
,
1762 const struct dcesrv_endpoint_server
*ep_server
)
1765 struct messaging_context
*msg_ctx
= global_messaging_context();
1767 status
= srv_fssa_start(msg_ctx
);
1768 if (!NT_STATUS_IS_OK(status
)) {
1772 return FileServerVssAgent__op_init_server(dce_ctx
, ep_server
);
1775 /* include the generated boilerplate */
1776 #include "librpc/gen_ndr/ndr_fsrvp_scompat.c"