heimdal_build: Remove memset_s from roken, already in libreplace
[samba.git] / source3 / rpc_server / fss / srv_fss_agent.c
1 /*
2  * File Server Remote VSS Protocol (FSRVP) server
3  *
4  * Copyright (C) David Disseldorp       2012-2015
5  *
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.
10  *
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.
15  *
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/>.
18  */
19
20 #include "includes.h"
21 #include "ntdomain.h"
22 #include "include/messages.h"
23 #include "serverid.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"
36
37 #undef DBGC_CLASS
38 #define DBGC_CLASS DBGC_RPC_SRV
39
40 static struct fss_global fss_global;
41
42 /* errmap NTSTATUS->fsrvp */
43 static const struct {
44         NTSTATUS status;
45         uint32_t fsrvp_err;
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},
55 };
56
57 /* errmap NTSTATUS->hresult */
58 static const struct {
59         NTSTATUS status;
60         HRESULT hres;
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},
65 };
66
67 static uint32_t fss_ntstatus_map(NTSTATUS status)
68 {
69         size_t i;
70
71         if (NT_STATUS_IS_OK(status))
72                 return 0;
73
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;
78                 }
79         }
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);
84                 }
85         }
86
87         return HRES_ERROR_V(HRES_E_FAIL);
88 }
89
90 static NTSTATUS fss_unc_parse(TALLOC_CTX *mem_ctx,
91                               const char *unc,
92                               char **_server,
93                               char **_share)
94 {
95         char *s;
96         char *server;
97         char *share;
98
99         if (unc == NULL) {
100                 return NT_STATUS_INVALID_PARAMETER;
101         }
102
103         s = strstr_m(unc, "\\\\");
104         if (s == NULL) {
105                 return NT_STATUS_INVALID_PARAMETER;
106         }
107
108         server = talloc_strdup(mem_ctx, s + 2);
109         if (server == NULL) {
110                 return NT_STATUS_NO_MEMORY;
111         }
112         s = strchr_m(server, '\\');
113         if ((s == NULL) || (s == server)) {
114                 return NT_STATUS_INVALID_PARAMETER;
115         }
116         *s = '\0';
117         share = s + 1;
118
119         s = strchr_m(share, '\\');
120         if (s != NULL) {
121                 /* diskshadow.exe adds a trailing '\' to the share-name */
122                 *s = '\0';
123         }
124         if (strlen(share) == 0) {
125                 return NT_STATUS_INVALID_PARAMETER;
126         }
127
128         if (_server != NULL) {
129                 *_server = server;
130         }
131         if (_share != NULL) {
132                 *_share = share;
133         }
134
135         return NT_STATUS_OK;
136 }
137
138 static NTSTATUS fss_conn_create_tos(struct messaging_context *msg_ctx,
139                                     struct auth_session_info *session_info,
140                                     int snum,
141                                     struct connection_struct **conn_out);
142
143 /* test if system path exists */
144 static bool snap_path_exists(TALLOC_CTX *ctx, struct messaging_context *msg_ctx,
145                              struct fss_sc *sc)
146 {
147         TALLOC_CTX *frame = talloc_stackframe();
148         SMB_STRUCT_STAT st;
149         struct connection_struct *conn = NULL;
150         struct smb_filename *smb_fname = NULL;
151         char *service = NULL;
152         char *share;
153         int snum;
154         int ret;
155         NTSTATUS status;
156         bool result = false;
157
158         ZERO_STRUCT(st);
159
160         if ((sc->smaps_count == 0) || (sc->sc_path == NULL)) {
161                 goto out;
162         }
163
164         share = sc->smaps->share_name;
165         snum = find_service(frame, share, &service);
166
167         if ((snum == -1) || (service == NULL)) {
168                 goto out;
169         }
170
171         status = fss_conn_create_tos(msg_ctx, NULL, snum, &conn);
172         if(!NT_STATUS_IS_OK(status)) {
173                 goto out;
174         }
175
176         smb_fname = synthetic_smb_fname(service,
177                                         sc->sc_path,
178                                         NULL,
179                                         NULL,
180                                         0,
181                                         0);
182         if (smb_fname == NULL) {
183                 goto out;
184         }
185
186         ret = SMB_VFS_STAT(conn, smb_fname);
187         if ((ret == -1) && (errno == ENOENT)) {
188                 goto out;
189         }
190         result = true;
191 out:
192         TALLOC_FREE(frame);
193         return result;
194 }
195
196 static NTSTATUS sc_smap_unexpose(struct messaging_context *msg_ctx,
197                                  struct fss_sc_smap *sc_smap, bool delete_all);
198
199 static NTSTATUS fss_prune_stale(struct messaging_context *msg_ctx,
200                                 const char *db_path)
201 {
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);
209
210         if (!ctx) {
211                 return NT_STATUS_NO_MEMORY;
212         }
213
214         /* work with temporary state for simple cleanup on failure */
215         become_root();
216         status = fss_state_retrieve(ctx, &sc_sets, &sc_sets_count, db_path);
217         unbecome_root();
218         if (!NT_STATUS_IS_OK(status)) {
219                 DEBUG(1, ("failed to retrieve fss server state: %s\n",
220                           nt_errstr(status)));
221                 goto out;
222         }
223
224         /* walk the cache and pick up any entries to be deleted */
225         sc_set = sc_sets;
226         DEBUG(10, ("pruning shared shadow copies\n"));
227         while (sc_set) {
228                 struct fss_sc *sc;
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;
233                         goto out;
234                 }
235                 DEBUGADD(10, ("\tprocessing shadow set id %s\n", set_id));
236                 sc = sc_set->scs;
237                 while (sc) {
238                         struct fss_sc_smap *sc_smap;
239                         struct fss_sc *sc_next = sc->next;
240                         DEBUGADD(10, ("\tprocessing shadow copy path %s\n",
241                                  sc->sc_path));
242                         if (snap_path_exists(ctx, msg_ctx, sc)) {
243                                 sc = sc_next;
244                                 continue;
245                         }
246
247                         /* move missing snapshot state to purge list */
248                         sc_smap = sc->smaps;
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);
253                                 sc->smaps_count--;
254                                 sc_smap = smap_next;
255                         }
256
257                         DLIST_REMOVE(sc_set->scs, sc);
258                         sc_set->scs_count--;
259                         is_modified = true;
260                         sc = sc_next;
261                 }
262                 if (sc_set->scs_count == 0) {
263                         DLIST_REMOVE(sc_sets, sc_set);
264                         sc_sets_count--;
265                 }
266                 sc_set = sc_set_next;
267         }
268
269         if (is_modified) {
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 */
274                         goto out;
275                 }
276
277                 become_root();
278                 status = fss_state_store(ctx, sc_sets, sc_sets_count, db_path);
279                 unbecome_root();
280                 if (!NT_STATUS_IS_OK(status)) {
281                         DEBUG(1, ("pruning failed to store fss server state: %s\n",
282                                   nt_errstr(status)));
283                         goto out;
284                 }
285         }
286         status = NT_STATUS_OK;
287 out:
288         TALLOC_FREE(ctx);
289         return status;
290 }
291
292 static NTSTATUS fss_conn_create_tos(struct messaging_context *msg_ctx,
293                                     struct auth_session_info *session_info,
294                                     int snum,
295                                     struct connection_struct **conn_out)
296 {
297         const struct loadparm_substitution *lp_sub =
298                 loadparm_s3_global_substitution();
299         struct conn_struct_tos *c = NULL;
300         NTSTATUS status;
301
302         status = create_conn_struct_tos(msg_ctx,
303                                         snum,
304                                         lp_path(talloc_tos(), lp_sub, snum),
305                                         session_info,
306                                         &c);
307         if (!NT_STATUS_IS_OK(status)) {
308                 DEBUG(0,("failed to create conn for vfs: %s\n",
309                          nt_errstr(status)));
310                 return status;
311         }
312
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"));
316                 TALLOC_FREE(c);
317                 return status;
318         }
319
320         *conn_out = c->conn;
321         return NT_STATUS_OK;
322 }
323
324 static struct fss_sc_set *sc_set_lookup(struct fss_sc_set *sc_set_head,
325                                         struct GUID *sc_set_id)
326 {
327
328         struct fss_sc_set *sc_set;
329         char *guid_str;
330
331         for (sc_set = sc_set_head; sc_set; sc_set = sc_set->next) {
332                 if (GUID_equal(&sc_set->id, sc_set_id)) {
333                         return sc_set;
334                 }
335         }
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);
340
341         return NULL;
342 }
343
344 static struct fss_sc *sc_lookup(struct fss_sc *sc_head, struct GUID *sc_id)
345 {
346
347         struct fss_sc *sc;
348         char *guid_str;
349
350         for (sc = sc_head; sc; sc = sc->next) {
351                 if (GUID_equal(&sc->id, sc_id)) {
352                         return sc;
353                 }
354         }
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);
359
360         return NULL;
361 }
362
363 static struct fss_sc *sc_lookup_volname(struct fss_sc *sc_head,
364                                         const char *volname)
365 {
366         struct fss_sc *sc;
367
368         for (sc = sc_head; sc; sc = sc->next) {
369                 if (!strcmp(sc->volume_name, volname)) {
370                         return sc;
371                 }
372         }
373         DEBUG(4, ("shadow copy with base volume %s not found\n", volname));
374         return NULL;
375 }
376
377 /* lookup is case-insensitive */
378 static struct fss_sc_smap *sc_smap_lookup(struct fss_sc_smap *smaps_head,
379                                           const char *share)
380 {
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)) {
384                         return sc_smap;
385                 }
386         }
387         DEBUG(4, ("shadow copy share mapping for %s not found\n", share));
388         return NULL;
389 }
390
391 static void srv_fssa_cleanup(void)
392 {
393         talloc_free(fss_global.db_path);
394         talloc_free(fss_global.mem_ctx);
395         ZERO_STRUCT(fss_global);
396 }
397
398 static NTSTATUS srv_fssa_start(struct messaging_context *msg_ctx)
399 {
400         NTSTATUS status;
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;
405         }
406
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;
411         }
412
413         fss_global.min_vers = FSRVP_RPC_VERSION_1;
414         fss_global.max_vers = FSRVP_RPC_VERSION_1;
415         /*
416          * The server MUST populate the GlobalShadowCopySetTable with the
417          * ShadowCopySet entries read from the configuration store.
418          */
419         if (lp_parm_bool(GLOBAL_SECTION_SNUM, "fss", "prune stale", false)) {
420                 fss_prune_stale(msg_ctx, fss_global.db_path);
421         }
422         become_root();
423         status = fss_state_retrieve(fss_global.mem_ctx, &fss_global.sc_sets,
424                                     &fss_global.sc_sets_count,
425                                     fss_global.db_path);
426         unbecome_root();
427         if (!NT_STATUS_IS_OK(status)) {
428                 DEBUG(1, ("failed to retrieve fss server state: %s\n",
429                           nt_errstr(status)));
430         }
431         return NT_STATUS_OK;
432 }
433
434 /*
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.
438  */
439 static bool fss_permitted(struct pipes_struct *p)
440 {
441         if (p->session_info->unix_token->uid == sec_initial_uid()) {
442                 DEBUG(6, ("Granting FSRVP op, user started smbd\n"));
443                 return true;
444         }
445
446         if (nt_token_check_sid(&global_sid_Builtin_Administrators,
447                                p->session_info->security_token)) {
448                 DEBUG(6, ("Granting FSRVP op, administrators group member\n"));
449                 return true;
450         }
451         if (nt_token_check_sid(&global_sid_Builtin_Backup_Operators,
452                                p->session_info->security_token)) {
453                 DEBUG(6, ("Granting FSRVP op, backup operators group member\n"));
454                 return true;
455         }
456         if (security_token_has_privilege(p->session_info->security_token,
457                                          SEC_PRIV_BACKUP)) {
458                 DEBUG(6, ("Granting FSRVP op, backup privilege present\n"));
459                 return true;
460         }
461
462         DEBUG(2, ("FSRVP operation blocked due to lack of backup privilege "
463                   "or Administrators/Backup Operators group membership\n"));
464
465         return false;
466 }
467
468 static void fss_seq_tout_handler(struct tevent_context *ev,
469                                  struct tevent_timer *te,
470                                  struct timeval t,
471                                  void *private_data)
472 {
473         struct GUID *sc_set_id = NULL;
474         struct fss_sc_set *sc_set;
475
476         /*
477          * MS-FSRVP: 3.1.5 Timer Events
478          * Message Sequence Timer elapses: When the Message Sequence Timer
479          * elapses, the server MUST delete the ShadowCopySet in the
480          * GlobalShadowCopySetTable where ShadowCopySet.Status is not equal to
481          * "Recovered", ContextSet MUST be set to FALSE, and the ShadowCopySet
482          * object MUST be freed.
483          */
484         DEBUG(2, ("FSRVP msg seq timeout fired\n"));
485
486         if (private_data == NULL) {
487                 DEBUG(4, ("timeout without sc_set\n"));
488                 goto out_init_ctx;
489         }
490
491         sc_set_id = talloc_get_type_abort(private_data, struct GUID);
492         sc_set = sc_set_lookup(fss_global.sc_sets, sc_set_id);
493         if (sc_set == NULL) {
494                 DEBUG(0, ("timeout for unknown sc_set\n"));
495                 goto out_init_ctx;
496         } else if ((sc_set->state == FSS_SC_EXPOSED)
497                         || (sc_set->state == FSS_SC_RECOVERED)) {
498                 DEBUG(2, ("timeout for finished sc_set %s\n", sc_set->id_str));
499                 goto out_init_ctx;
500         }
501         DEBUG(2, ("cleaning up sc_set %s\n", sc_set->id_str));
502         SMB_ASSERT(fss_global.sc_sets_count > 0);
503         DLIST_REMOVE(fss_global.sc_sets, sc_set);
504         fss_global.sc_sets_count--;
505         talloc_free(sc_set);
506
507 out_init_ctx:
508         fss_global.ctx_set = false;
509         fss_global.seq_tmr = NULL;
510         talloc_free(sc_set_id);
511 }
512
513 static void fss_seq_tout_set(TALLOC_CTX *mem_ctx,
514                              uint32_t timeout_s,
515                              struct fss_sc_set *sc_set,
516                              struct tevent_timer **tmr_out)
517 {
518         struct tevent_timer *tmr;
519         struct GUID *sc_set_id = NULL;
520         uint32_t tout;
521
522         /* allow changes to timeout for testing/debugging purposes */
523         tout = lp_parm_int(GLOBAL_SECTION_SNUM, "fss",
524                            "sequence timeout", timeout_s);
525         if (tout == 0) {
526                 DEBUG(2, ("FSRVP message sequence timeout disabled\n"));
527                 *tmr_out = NULL;
528                 return;
529         }
530
531         if (sc_set) {
532                 /* don't use talloc_memdup(), need explicit type for callback */
533                 sc_set_id = talloc(mem_ctx, struct GUID);
534                 if (sc_set_id == NULL) {
535                         smb_panic("no memory");
536                 }
537                 memcpy(sc_set_id, &sc_set->id, sizeof(*sc_set_id));
538         }
539
540         tmr = tevent_add_timer(global_event_context(),
541                               mem_ctx,
542                               timeval_current_ofs(tout, 0),
543                               fss_seq_tout_handler, sc_set_id);
544         if (tmr == NULL) {
545                 talloc_free(sc_set_id);
546                 smb_panic("no memory");
547         }
548
549         *tmr_out = tmr;
550 }
551
552 uint32_t _fss_GetSupportedVersion(struct pipes_struct *p,
553                                   struct fss_GetSupportedVersion *r)
554 {
555         if (!fss_permitted(p)) {
556                 return HRES_ERROR_V(HRES_E_ACCESSDENIED);
557         }
558
559         *r->out.MinVersion = fss_global.min_vers;
560         *r->out.MaxVersion = fss_global.max_vers;
561
562         return 0;
563 }
564
565 uint32_t _fss_SetContext(struct pipes_struct *p,
566                          struct fss_SetContext *r)
567 {
568         if (!fss_permitted(p)) {
569                 return HRES_ERROR_V(HRES_E_ACCESSDENIED);
570         }
571
572         /* ATTR_AUTO_RECOVERY flag can be applied to any */
573         switch (r->in.Context & (~ATTR_AUTO_RECOVERY)) {
574         case FSRVP_CTX_BACKUP:
575                 DEBUG(6, ("fss ctx set backup\n"));
576                 break;
577         case FSRVP_CTX_FILE_SHARE_BACKUP:
578                 DEBUG(6, ("fss ctx set file share backup\n"));
579                 break;
580         case FSRVP_CTX_NAS_ROLLBACK:
581                 DEBUG(6, ("fss ctx set nas rollback\n"));
582                 break;
583         case FSRVP_CTX_APP_ROLLBACK:
584                 DEBUG(6, ("fss ctx set app rollback\n"));
585                 break;
586         default:
587                 DEBUG(0, ("invalid fss ctx set value: 0x%x\n", r->in.Context));
588                 return HRES_ERROR_V(HRES_E_INVALIDARG);
589                 break;  /* not reached */
590         }
591
592         fss_global.ctx_set = true;
593         fss_global.cur_ctx = r->in.Context;
594
595         TALLOC_FREE(fss_global.seq_tmr);        /* kill timer if running */
596         fss_seq_tout_set(fss_global.mem_ctx, 180, NULL, &fss_global.seq_tmr);
597
598         fss_global.cur_ctx = r->in.Context;
599
600         return 0;
601 }
602
603 static bool sc_set_active(struct fss_sc_set *sc_set_head)
604 {
605
606         struct fss_sc_set *sc_set;
607
608         for (sc_set = sc_set_head; sc_set; sc_set = sc_set->next) {
609                 if ((sc_set->state != FSS_SC_EXPOSED)
610                  && (sc_set->state != FSS_SC_RECOVERED)) {
611                         return true;
612                 }
613         }
614
615         return false;
616 }
617
618 uint32_t _fss_StartShadowCopySet(struct pipes_struct *p,
619                                  struct fss_StartShadowCopySet *r)
620 {
621         struct fss_sc_set *sc_set;
622         uint32_t ret;
623
624         if (!fss_permitted(p)) {
625                 ret = HRES_ERROR_V(HRES_E_ACCESSDENIED);
626                 goto err_out;
627         }
628
629         if (!fss_global.ctx_set) {
630                 DEBUG(3, ("invalid sequence: start sc set requested without "
631                           "prior context set\n"));
632                 ret = FSRVP_E_BAD_STATE;
633                 goto err_out;
634         }
635
636         /*
637          * At any given time, Windows servers allow only one shadow copy set to
638          * be going through the creation process.
639          */
640         if (sc_set_active(fss_global.sc_sets)) {
641                 DEBUG(3, ("StartShadowCopySet called while in progress\n"));
642                 ret = FSRVP_E_SHADOW_COPY_SET_IN_PROGRESS;
643                 goto err_out;
644         }
645
646         /* stop msg seq timer */
647         TALLOC_FREE(fss_global.seq_tmr);
648
649         sc_set = talloc_zero(fss_global.mem_ctx, struct fss_sc_set);
650         if (sc_set == NULL) {
651                 ret = HRES_ERROR_V(HRES_E_OUTOFMEMORY);
652                 goto err_tmr_restart;
653         }
654
655         sc_set->id = GUID_random();     /* Windows servers ignore client ids */
656         sc_set->id_str = GUID_string(sc_set, &sc_set->id);
657         if (sc_set->id_str == NULL) {
658                 ret = HRES_ERROR_V(HRES_E_OUTOFMEMORY);
659                 goto err_sc_set_free;
660         }
661         sc_set->state = FSS_SC_STARTED;
662         sc_set->context = fss_global.cur_ctx;
663         DLIST_ADD_END(fss_global.sc_sets, sc_set);
664         fss_global.sc_sets_count++;
665         DEBUG(6, ("%s: shadow-copy set %u added\n",
666                   sc_set->id_str, fss_global.sc_sets_count));
667
668         /* start msg seq timer */
669         fss_seq_tout_set(fss_global.mem_ctx, 180, sc_set, &fss_global.seq_tmr);
670
671         r->out.pShadowCopySetId = &sc_set->id;
672
673         return 0;
674
675 err_sc_set_free:
676         talloc_free(sc_set);
677 err_tmr_restart:
678         fss_seq_tout_set(fss_global.mem_ctx, 180, NULL, &fss_global.seq_tmr);
679 err_out:
680         return ret;
681 }
682
683 static uint32_t map_share_name(struct fss_sc_smap *sc_smap,
684                                const struct fss_sc *sc)
685 {
686         bool hidden_base = false;
687
688         if (*(sc_smap->share_name + strlen(sc_smap->share_name) - 1) == '$') {
689                 /*
690                  * If MappedShare.ShareName ends with a $ character (meaning
691                  * that the share is hidden), then the exposed share name will
692                  * have the $ suffix appended.
693                  * FIXME: turns out Windows doesn't do this, contrary to docs
694                  */
695                 hidden_base = true;
696         }
697
698         sc_smap->sc_share_name = talloc_asprintf(sc_smap, "%s@{%s}%s",
699                                                 sc_smap->share_name,
700                                                 sc->id_str,
701                                                 hidden_base ? "$" : "");
702         if (sc_smap->sc_share_name == NULL) {
703                 return HRES_ERROR_V(HRES_E_OUTOFMEMORY);
704         }
705
706         return 0;
707 }
708
709 static uint32_t map_share_comment(struct fss_sc_smap *sc_smap,
710                                   const struct fss_sc *sc)
711 {
712         char *time_str;
713
714         time_str = http_timestring(sc_smap, sc->create_ts);
715         if (time_str == NULL) {
716                 return HRES_ERROR_V(HRES_E_OUTOFMEMORY);
717         }
718
719         sc_smap->sc_share_comment = talloc_asprintf(sc_smap, "Shadow copy of %s taken %s",
720                                                    sc_smap->share_name, time_str);
721         if (sc_smap->sc_share_comment == NULL) {
722                 return HRES_ERROR_V(HRES_E_OUTOFMEMORY);
723         }
724
725         return 0;
726 }
727
728 uint32_t _fss_AddToShadowCopySet(struct pipes_struct *p,
729                                  struct fss_AddToShadowCopySet *r)
730 {
731         uint32_t ret;
732         struct fss_sc_set *sc_set;
733         struct fss_sc *sc;
734         struct fss_sc_smap *sc_smap;
735         int snum;
736         char *service;
737         char *base_vol;
738         char *share;
739         char *path_name;
740         struct connection_struct *conn;
741         NTSTATUS status;
742         TALLOC_CTX *frame = talloc_stackframe();
743         const struct loadparm_substitution *lp_sub =
744                 loadparm_s3_global_substitution();
745
746         if (!fss_permitted(p)) {
747                 ret = HRES_ERROR_V(HRES_E_ACCESSDENIED);
748                 goto err_tmp_free;
749         }
750
751         sc_set = sc_set_lookup(fss_global.sc_sets, &r->in.ShadowCopySetId);
752         if (sc_set == NULL) {
753                 ret = HRES_ERROR_V(HRES_E_INVALIDARG);
754                 goto err_tmp_free;
755         }
756
757         status = fss_unc_parse(frame, r->in.ShareName, NULL, &share);
758         if (!NT_STATUS_IS_OK(status)) {
759                 ret = fss_ntstatus_map(status);
760                 goto err_tmp_free;
761         }
762
763         snum = find_service(frame, share, &service);
764         if ((snum == -1) || (service == NULL)) {
765                 DEBUG(0, ("share at %s not found\n", r->in.ShareName));
766                 ret = HRES_ERROR_V(HRES_E_INVALIDARG);
767                 goto err_tmp_free;
768         }
769
770         path_name = lp_path(frame, lp_sub, snum);
771         if (path_name == NULL) {
772                 ret = HRES_ERROR_V(HRES_E_OUTOFMEMORY);
773                 goto err_tmp_free;
774         }
775
776         status = fss_conn_create_tos(p->msg_ctx, p->session_info, snum, &conn);
777         if (!NT_STATUS_IS_OK(status)) {
778                 ret = HRES_ERROR_V(HRES_E_ACCESSDENIED);
779                 goto err_tmp_free;
780         }
781         if (!become_user_without_service_by_session(conn, p->session_info)) {
782                 DEBUG(0, ("failed to become user\n"));
783                 ret = HRES_ERROR_V(HRES_E_ACCESSDENIED);
784                 goto err_tmp_free;
785         }
786
787         status = SMB_VFS_SNAP_CHECK_PATH(conn, frame, path_name, &base_vol);
788         unbecome_user_without_service();
789         if (!NT_STATUS_IS_OK(status)) {
790                 ret = FSRVP_E_NOT_SUPPORTED;
791                 goto err_tmp_free;
792         }
793
794         if ((sc_set->state != FSS_SC_STARTED)
795          && (sc_set->state != FSS_SC_ADDED)) {
796                 ret = FSRVP_E_BAD_STATE;
797                 goto err_tmp_free;
798         }
799
800         /* stop msg seq timer */
801         TALLOC_FREE(fss_global.seq_tmr);
802
803         /*
804          * server MUST look up the ShadowCopy in ShadowCopySet.ShadowCopyList
805          * where ShadowCopy.VolumeName matches the file store on which the
806          * share identified by ShareName is hosted. If an entry is found, the
807          * server MUST fail the call with FSRVP_E_OBJECT_ALREADY_EXISTS.
808          * If no entry is found, the server MUST create a new ShadowCopy
809          * object
810          * XXX Windows appears to allow multiple mappings for the same vol!
811          */
812         sc = sc_lookup_volname(sc_set->scs, base_vol);
813         if (sc != NULL) {
814                 ret = FSRVP_E_OBJECT_ALREADY_EXISTS;
815                 goto err_tmr_restart;
816         }
817
818         sc = talloc_zero(sc_set, struct fss_sc);
819         if (sc == NULL) {
820                 ret = HRES_ERROR_V(HRES_E_OUTOFMEMORY);
821                 goto err_tmr_restart;
822         }
823         talloc_steal(sc, base_vol);
824         sc->volume_name = base_vol;
825         sc->sc_set = sc_set;
826         sc->create_ts = time(NULL);
827
828         sc->id = GUID_random(); /* Windows servers ignore client ids */
829         sc->id_str = GUID_string(sc, &sc->id);
830         if (sc->id_str == NULL) {
831                 ret = HRES_ERROR_V(HRES_E_OUTOFMEMORY);
832                 goto err_sc_free;
833         }
834
835         sc_smap = talloc_zero(sc, struct fss_sc_smap);
836         if (sc_smap == NULL) {
837                 ret = HRES_ERROR_V(HRES_E_OUTOFMEMORY);
838                 goto err_sc_free;
839         }
840
841         talloc_steal(sc_smap, service);
842         sc_smap->share_name = service;
843         sc_smap->is_exposed = false;
844         /*
845          * generate the sc_smap share name now. It is a unique identifier for
846          * the smap used as a tdb key for state storage.
847          */
848         ret = map_share_name(sc_smap, sc);
849         if (ret) {
850                 goto err_sc_free;
851         }
852
853         /* add share map to shadow-copy */
854         DLIST_ADD_END(sc->smaps, sc_smap);
855         sc->smaps_count++;
856         /* add shadow-copy to shadow-copy set */
857         DLIST_ADD_END(sc_set->scs, sc);
858         sc_set->scs_count++;
859         DEBUG(4, ("added volume %s to shadow copy set with GUID %s\n",
860                   sc->volume_name, sc_set->id_str));
861
862         /* start the Message Sequence Timer with timeout of 1800 seconds */
863         fss_seq_tout_set(fss_global.mem_ctx, 1800, sc_set, &fss_global.seq_tmr);
864
865         sc_set->state = FSS_SC_ADDED;
866         r->out.pShadowCopyId = &sc->id;
867
868         TALLOC_FREE(frame);
869         return 0;
870
871 err_sc_free:
872         talloc_free(sc);
873 err_tmr_restart:
874         fss_seq_tout_set(fss_global.mem_ctx, 180, sc_set, &fss_global.seq_tmr);
875 err_tmp_free:
876         TALLOC_FREE(frame);
877         return ret;
878 }
879
880 static NTSTATUS commit_sc_with_conn(TALLOC_CTX *mem_ctx,
881                                     struct tevent_context *ev,
882                                     struct messaging_context *msg_ctx,
883                                     struct auth_session_info *session_info,
884                                     struct fss_sc *sc,
885                                     char **base_path,
886                                     char **snap_path)
887 {
888         TALLOC_CTX *frame = talloc_stackframe();
889         NTSTATUS status;
890         bool rw;
891         struct connection_struct *conn;
892         int snum;
893         char *service;
894
895         snum = find_service(frame, sc->smaps->share_name, &service);
896         if ((snum == -1) || (service == NULL)) {
897                 DEBUG(0, ("share at %s not found\n", sc->smaps->share_name));
898                 TALLOC_FREE(frame);
899                 return NT_STATUS_UNSUCCESSFUL;
900         }
901
902         status = fss_conn_create_tos(msg_ctx, session_info, snum, &conn);
903         if (!NT_STATUS_IS_OK(status)) {
904                 TALLOC_FREE(frame);
905                 return status;
906         }
907
908         if (!become_user_without_service_by_session(conn, session_info)) {
909                 DEBUG(0, ("failed to become user\n"));
910                 TALLOC_FREE(frame);
911                 return NT_STATUS_ACCESS_DENIED;
912         }
913         rw = ((sc->sc_set->context & ATTR_AUTO_RECOVERY) == ATTR_AUTO_RECOVERY);
914         status = SMB_VFS_SNAP_CREATE(conn, mem_ctx,
915                                      sc->volume_name,
916                                      &sc->create_ts, rw,
917                                      base_path, snap_path);
918         unbecome_user_without_service();
919         if (!NT_STATUS_IS_OK(status)) {
920                 DEBUG(0, ("snap create failed: %s\n", nt_errstr(status)));
921                 TALLOC_FREE(frame);
922                 return status;
923         }
924
925         TALLOC_FREE(frame);
926         return status;
927 }
928
929 uint32_t _fss_CommitShadowCopySet(struct pipes_struct *p,
930                                   struct fss_CommitShadowCopySet *r)
931 {
932         struct fss_sc_set *sc_set;
933         struct fss_sc *sc;
934         uint32_t commit_count;
935         NTSTATUS status;
936         NTSTATUS saved_status;
937         TALLOC_CTX *frame = talloc_stackframe();
938
939         if (!fss_permitted(p)) {
940                 status = NT_STATUS_ACCESS_DENIED;
941                 goto err_tmp_free;
942         }
943
944         sc_set = sc_set_lookup(fss_global.sc_sets, &r->in.ShadowCopySetId);
945         if (sc_set == NULL) {
946                 status = NT_STATUS_INVALID_PARAMETER;
947                 goto err_tmp_free;
948         }
949
950         if (sc_set->state != FSS_SC_ADDED) {
951                 status = NT_STATUS_INVALID_SERVER_STATE;
952                 goto err_tmp_free;
953         }
954
955         /* stop Message Sequence Timer */
956         TALLOC_FREE(fss_global.seq_tmr);
957         sc_set->state = FSS_SC_CREATING;
958         commit_count = 0;
959         saved_status = NT_STATUS_OK;
960         for (sc = sc_set->scs; sc; sc = sc->next) {
961                 char *base_path;
962                 char *snap_path;
963                 status = commit_sc_with_conn(frame, global_event_context(),
964                                              p->msg_ctx, p->session_info, sc,
965                                              &base_path, &snap_path);
966                 if (!NT_STATUS_IS_OK(status)) {
967                         DEBUG(0, ("snap create failed for shadow copy of "
968                                   "%s\n", sc->volume_name));
969                         /* dispatch all scs in set, but retain last error */
970                         saved_status = status;
971                         continue;
972                 }
973                 /* XXX set timeout r->in.TimeOutInMilliseconds */
974                 commit_count++;
975                 DEBUG(10, ("good snap create %d\n",
976                            commit_count));
977                 sc->sc_path = talloc_steal(sc, snap_path);
978         }
979         if (!NT_STATUS_IS_OK(saved_status)) {
980                 status = saved_status;
981                 goto err_state_revert;
982         }
983
984         sc_set->state = FSS_SC_COMMITED;
985         become_root();
986         status = fss_state_store(fss_global.mem_ctx, fss_global.sc_sets,
987                                  fss_global.sc_sets_count,
988                                  fss_global.db_path);
989         unbecome_root();
990         if (!NT_STATUS_IS_OK(status)) {
991                 DEBUG(1, ("failed to store fss server state: %s\n",
992                           nt_errstr(status)));
993         }
994
995         fss_seq_tout_set(fss_global.mem_ctx, 180, sc_set,
996                          &fss_global.seq_tmr);
997         TALLOC_FREE(frame);
998         return 0;
999
1000 err_state_revert:
1001         sc_set->state = FSS_SC_ADDED;
1002         fss_seq_tout_set(fss_global.mem_ctx, 180, sc_set,
1003                          &fss_global.seq_tmr);
1004 err_tmp_free:
1005         TALLOC_FREE(frame);
1006         return fss_ntstatus_map(status);
1007 }
1008
1009 static sbcErr fss_conf_get_share_def(struct smbconf_ctx *fconf_ctx,
1010                                      struct smbconf_ctx *rconf_ctx,
1011                                      TALLOC_CTX *mem_ctx,
1012                                      char *share,
1013                                      struct smbconf_service **service_def)
1014 {
1015         sbcErr cerr;
1016         struct smbconf_service *def;
1017
1018         *service_def = NULL;
1019         cerr = smbconf_get_share(fconf_ctx, mem_ctx, share, &def);
1020         if (SBC_ERROR_IS_OK(cerr)) {
1021                 *service_def = def;
1022                 return SBC_ERR_OK;
1023         }
1024
1025         cerr = smbconf_get_share(rconf_ctx, mem_ctx, share, &def);
1026         if (SBC_ERROR_IS_OK(cerr)) {
1027                 *service_def = def;
1028                 return SBC_ERR_OK;
1029         }
1030         return cerr;
1031 }
1032
1033 /*
1034  * Expose a new share using libsmbconf, cloning the existing configuration
1035  * from the base share. The base share may be defined in either the registry
1036  * or smb.conf.
1037  * XXX this is called as root
1038  */
1039 static uint32_t fss_sc_expose(struct smbconf_ctx *fconf_ctx,
1040                               struct smbconf_ctx *rconf_ctx,
1041                               TALLOC_CTX *mem_ctx,
1042                               struct fss_sc *sc)
1043 {
1044         struct fss_sc_smap *sc_smap;
1045         uint32_t err = 0;
1046
1047         for (sc_smap = sc->smaps; sc_smap; sc_smap = sc_smap->next) {
1048                 sbcErr cerr;
1049                 struct smbconf_service *base_service = NULL;
1050                 struct security_descriptor *sd;
1051                 size_t sd_size;
1052
1053                 cerr = fss_conf_get_share_def(fconf_ctx, rconf_ctx, mem_ctx,
1054                                             sc_smap->share_name, &base_service);
1055                 if (!SBC_ERROR_IS_OK(cerr)) {
1056                         DEBUG(0, ("failed to get base share %s definition: "
1057                                   "%s\n", sc_smap->share_name,
1058                                   sbcErrorString(cerr)));
1059                         err = HRES_ERROR_V(HRES_E_FAIL);
1060                         break;
1061                 }
1062
1063                 /* smap share name already defined when added */
1064                 err = map_share_comment(sc_smap, sc);
1065                 if (err) {
1066                         DEBUG(0, ("failed to map share comment\n"));
1067                         break;
1068                 }
1069
1070                 base_service->name = sc_smap->sc_share_name;
1071
1072                 cerr = smbconf_create_set_share(rconf_ctx, base_service);
1073                 if (!SBC_ERROR_IS_OK(cerr)) {
1074                         DEBUG(0, ("failed to create share %s: %s\n",
1075                                   base_service->name, sbcErrorString(cerr)));
1076                         err = HRES_ERROR_V(HRES_E_FAIL);
1077                         break;
1078                 }
1079                 cerr = smbconf_set_parameter(rconf_ctx, sc_smap->sc_share_name,
1080                                              "path", sc->sc_path);
1081                 if (!SBC_ERROR_IS_OK(cerr)) {
1082                         DEBUG(0, ("failed to set path param: %s\n",
1083                                   sbcErrorString(cerr)));
1084                         err = HRES_ERROR_V(HRES_E_FAIL);
1085                         break;
1086                 }
1087                 if (sc_smap->sc_share_comment != NULL) {
1088                         cerr = smbconf_set_parameter(rconf_ctx,
1089                                                     sc_smap->sc_share_name,
1090                                                     "comment",
1091                                                     sc_smap->sc_share_comment);
1092                         if (!SBC_ERROR_IS_OK(cerr)) {
1093                                 DEBUG(0, ("failed to set comment param: %s\n",
1094                                           sbcErrorString(cerr)));
1095                                 err = HRES_ERROR_V(HRES_E_FAIL);
1096                                 break;
1097                         }
1098                 }
1099                 talloc_free(base_service);
1100
1101                 /*
1102                  * Obtain the base share SD, which also needs to be cloned.
1103                  * Share SDs are stored in share_info.tdb, so are not covered by
1104                  * the registry transaction.
1105                  * The base share SD should be cloned at the time of exposure,
1106                  * rather than when the snapshot is taken. This matches Windows
1107                  * Server 2012 behaviour.
1108                  */
1109                 sd = get_share_security(mem_ctx, sc_smap->share_name, &sd_size);
1110                 if (sd == NULL) {
1111                         DEBUG(2, ("no share SD to clone for %s snapshot\n",
1112                                   sc_smap->share_name));
1113                 } else {
1114                         NTSTATUS status;
1115                         status = set_share_security(sc_smap->sc_share_name, sd);
1116                         TALLOC_FREE(sd);
1117                         if (!NT_STATUS_IS_OK(status)) {
1118                                 DEBUG(0, ("failed to set %s share SD\n",
1119                                           sc_smap->sc_share_name));
1120                                 err = HRES_ERROR_V(HRES_E_FAIL);
1121                                 break;
1122                         }
1123                 }
1124         }
1125
1126         return err;
1127 }
1128
1129 uint32_t _fss_ExposeShadowCopySet(struct pipes_struct *p,
1130                                   struct fss_ExposeShadowCopySet *r)
1131 {
1132         NTSTATUS status;
1133         struct fss_sc_set *sc_set;
1134         struct fss_sc *sc;
1135         uint32_t ret;
1136         struct smbconf_ctx *fconf_ctx;
1137         struct smbconf_ctx *rconf_ctx;
1138         sbcErr cerr;
1139         char *fconf_path;
1140         TALLOC_CTX *frame = talloc_stackframe();
1141
1142         if (!fss_permitted(p)) {
1143                 ret = HRES_ERROR_V(HRES_E_ACCESSDENIED);
1144                 goto err_out;
1145         }
1146
1147         sc_set = sc_set_lookup(fss_global.sc_sets, &r->in.ShadowCopySetId);
1148         if (sc_set == NULL) {
1149                 ret = HRES_ERROR_V(HRES_E_INVALIDARG);
1150                 goto err_out;
1151         }
1152
1153         if (sc_set->state != FSS_SC_COMMITED) {
1154                 ret = FSRVP_E_BAD_STATE;
1155                 goto err_out;
1156         }
1157
1158         /* stop message sequence timer */
1159         TALLOC_FREE(fss_global.seq_tmr);
1160
1161         /*
1162          * Prepare to clone the base share definition for the snapshot share.
1163          * Create both registry and file conf contexts, as the base share
1164          * definition may be located in either. The snapshot share definition
1165          * is always written to the registry.
1166          */
1167         cerr = smbconf_init(frame, &rconf_ctx, "registry");
1168         if (!SBC_ERROR_IS_OK(cerr)) {
1169                 DEBUG(0, ("failed registry smbconf init: %s\n",
1170                           sbcErrorString(cerr)));
1171                 ret = HRES_ERROR_V(HRES_E_FAIL);
1172                 goto err_tmr_restart;
1173         }
1174         fconf_path = talloc_asprintf(frame, "file:%s", get_dyn_CONFIGFILE());
1175         if (fconf_path == NULL) {
1176                 ret = HRES_ERROR_V(HRES_E_OUTOFMEMORY);
1177                 goto err_tmr_restart;
1178         }
1179         cerr = smbconf_init(frame, &fconf_ctx, fconf_path);
1180         if (!SBC_ERROR_IS_OK(cerr)) {
1181                 DEBUG(0, ("failed %s smbconf init: %s\n",
1182                           fconf_path, sbcErrorString(cerr)));
1183                 ret = HRES_ERROR_V(HRES_E_FAIL);
1184                 goto err_tmr_restart;
1185         }
1186
1187         /* registry IO must be done as root */
1188         become_root();
1189         cerr = smbconf_transaction_start(rconf_ctx);
1190         if (!SBC_ERROR_IS_OK(cerr)) {
1191                 DEBUG(0, ("error starting transaction: %s\n",
1192                          sbcErrorString(cerr)));
1193                 ret = HRES_ERROR_V(HRES_E_FAIL);
1194                 unbecome_root();
1195                 goto err_tmr_restart;
1196         }
1197
1198         for (sc = sc_set->scs; sc; sc = sc->next) {
1199                 ret = fss_sc_expose(fconf_ctx, rconf_ctx, frame, sc);
1200                 if (ret) {
1201                         DEBUG(0,("failed to expose shadow copy of %s\n",
1202                                  sc->volume_name));
1203                         goto err_cancel;
1204                 }
1205         }
1206
1207         cerr = smbconf_transaction_commit(rconf_ctx);
1208         if (!SBC_ERROR_IS_OK(cerr)) {
1209                 DEBUG(0, ("error committing transaction: %s\n",
1210                           sbcErrorString(cerr)));
1211                 ret = HRES_ERROR_V(HRES_E_FAIL);
1212                 goto err_cancel;
1213         }
1214         unbecome_root();
1215
1216         messaging_send_all(p->msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0);
1217         for (sc = sc_set->scs; sc; sc = sc->next) {
1218                 struct fss_sc_smap *sm;
1219                 for (sm = sc->smaps; sm; sm = sm->next)
1220                         sm->is_exposed = true;
1221         }
1222         sc_set->state = FSS_SC_EXPOSED;
1223         become_root();
1224         status = fss_state_store(fss_global.mem_ctx, fss_global.sc_sets,
1225                                  fss_global.sc_sets_count, fss_global.db_path);
1226         unbecome_root();
1227         if (!NT_STATUS_IS_OK(status)) {
1228                 DEBUG(1, ("failed to store fss server state: %s\n",
1229                           nt_errstr(status)));
1230         }
1231         /* start message sequence timer */
1232         fss_seq_tout_set(fss_global.mem_ctx, 180, sc_set, &fss_global.seq_tmr);
1233         TALLOC_FREE(frame);
1234         return 0;
1235
1236 err_cancel:
1237         smbconf_transaction_cancel(rconf_ctx);
1238         unbecome_root();
1239 err_tmr_restart:
1240         fss_seq_tout_set(fss_global.mem_ctx, 180, sc_set, &fss_global.seq_tmr);
1241 err_out:
1242         TALLOC_FREE(frame);
1243         return ret;
1244 }
1245
1246 uint32_t _fss_RecoveryCompleteShadowCopySet(struct pipes_struct *p,
1247                                 struct fss_RecoveryCompleteShadowCopySet *r)
1248 {
1249         NTSTATUS status;
1250         struct fss_sc_set *sc_set;
1251
1252         if (!fss_permitted(p)) {
1253                 return HRES_ERROR_V(HRES_E_ACCESSDENIED);
1254         }
1255
1256         sc_set = sc_set_lookup(fss_global.sc_sets, &r->in.ShadowCopySetId);
1257         if (sc_set == NULL) {
1258                 return HRES_ERROR_V(HRES_E_INVALIDARG);
1259         }
1260
1261         if (sc_set->state != FSS_SC_EXPOSED) {
1262                 return FSRVP_E_BAD_STATE;
1263         }
1264
1265         /* stop msg sequence timer */
1266         TALLOC_FREE(fss_global.seq_tmr);
1267
1268         if (sc_set->context & ATTR_NO_AUTO_RECOVERY) {
1269                 /* TODO set read-only */
1270         }
1271
1272         sc_set->state = FSS_SC_RECOVERED;
1273         fss_global.cur_ctx = 0;
1274         fss_global.ctx_set = false;
1275
1276         become_root();
1277         status = fss_state_store(fss_global.mem_ctx, fss_global.sc_sets,
1278                                  fss_global.sc_sets_count, fss_global.db_path);
1279         unbecome_root();
1280         if (!NT_STATUS_IS_OK(status)) {
1281                 DEBUG(1, ("failed to store fss server state: %s\n",
1282                           nt_errstr(status)));
1283         }
1284
1285         return 0;
1286 }
1287
1288 uint32_t _fss_AbortShadowCopySet(struct pipes_struct *p,
1289                                  struct fss_AbortShadowCopySet *r)
1290 {
1291         NTSTATUS status;
1292         struct fss_sc_set *sc_set;
1293
1294         if (!fss_permitted(p)) {
1295                 return HRES_ERROR_V(HRES_E_ACCESSDENIED);
1296         }
1297
1298         sc_set = sc_set_lookup(fss_global.sc_sets, &r->in.ShadowCopySetId);
1299         if (sc_set == NULL) {
1300                 return HRES_ERROR_V(HRES_E_INVALIDARG);
1301         }
1302
1303         DEBUG(6, ("%s: aborting shadow-copy set\n", sc_set->id_str));
1304
1305         if ((sc_set->state == FSS_SC_COMMITED)
1306          || (sc_set->state == FSS_SC_EXPOSED)
1307          || (sc_set->state == FSS_SC_RECOVERED)) {
1308                 return 0;
1309         }
1310
1311         if (sc_set->state == FSS_SC_CREATING) {
1312                 return FSRVP_E_BAD_STATE;
1313         }
1314
1315         DLIST_REMOVE(fss_global.sc_sets, sc_set);
1316         talloc_free(sc_set);
1317         fss_global.sc_sets_count--;
1318         become_root();
1319         status = fss_state_store(fss_global.mem_ctx, fss_global.sc_sets,
1320                                  fss_global.sc_sets_count, fss_global.db_path);
1321         unbecome_root();
1322         if (!NT_STATUS_IS_OK(status)) {
1323                 DEBUG(1, ("failed to store fss server state: %s\n",
1324                           nt_errstr(status)));
1325         }
1326
1327         return 0;
1328 }
1329
1330 uint32_t _fss_IsPathSupported(struct pipes_struct *p,
1331                               struct fss_IsPathSupported *r)
1332 {
1333         int snum;
1334         char *service;
1335         char *base_vol;
1336         NTSTATUS status;
1337         struct connection_struct *conn;
1338         char *share;
1339         TALLOC_CTX *frame = talloc_stackframe();
1340         const struct loadparm_substitution *lp_sub =
1341                 loadparm_s3_global_substitution();
1342
1343         if (!fss_permitted(p)) {
1344                 TALLOC_FREE(frame);
1345                 return HRES_ERROR_V(HRES_E_ACCESSDENIED);
1346         }
1347
1348         status = fss_unc_parse(frame, r->in.ShareName, NULL, &share);
1349         if (!NT_STATUS_IS_OK(status)) {
1350                 TALLOC_FREE(frame);
1351                 return fss_ntstatus_map(status);
1352         }
1353
1354         snum = find_service(frame, share, &service);
1355         if ((snum == -1) || (service == NULL)) {
1356                 DEBUG(0, ("share at %s not found\n", r->in.ShareName));
1357                 TALLOC_FREE(frame);
1358                 return HRES_ERROR_V(HRES_E_INVALIDARG);
1359         }
1360
1361         status = fss_conn_create_tos(p->msg_ctx, p->session_info, snum, &conn);
1362         if (!NT_STATUS_IS_OK(status)) {
1363                 TALLOC_FREE(frame);
1364                 return HRES_ERROR_V(HRES_E_ACCESSDENIED);
1365         }
1366         if (!become_user_without_service_by_session(conn, p->session_info)) {
1367                 DEBUG(0, ("failed to become user\n"));
1368                 TALLOC_FREE(frame);
1369                 return HRES_ERROR_V(HRES_E_ACCESSDENIED);
1370         }
1371         status = SMB_VFS_SNAP_CHECK_PATH(conn, frame,
1372                                          lp_path(frame, lp_sub, snum),
1373                                          &base_vol);
1374         unbecome_user_without_service();
1375         if (!NT_STATUS_IS_OK(status)) {
1376                 TALLOC_FREE(frame);
1377                 return FSRVP_E_NOT_SUPPORTED;
1378         }
1379
1380         *r->out.OwnerMachineName = lp_netbios_name();
1381         *r->out.SupportedByThisProvider = 1;
1382         TALLOC_FREE(frame);
1383         return 0;
1384 }
1385
1386 uint32_t _fss_IsPathShadowCopied(struct pipes_struct *p,
1387                                  struct fss_IsPathShadowCopied *r)
1388 {
1389         if (!fss_permitted(p)) {
1390                 return HRES_ERROR_V(HRES_E_ACCESSDENIED);
1391         }
1392
1393         /* not yet supported */
1394         return FSRVP_E_NOT_SUPPORTED;
1395 }
1396
1397 uint32_t _fss_GetShareMapping(struct pipes_struct *p,
1398                               struct fss_GetShareMapping *r)
1399 {
1400         NTSTATUS status;
1401         struct fss_sc_set *sc_set;
1402         struct fss_sc *sc;
1403         struct fss_sc_smap *sc_smap;
1404         char *share;
1405         struct fssagent_share_mapping_1 *sm_out;
1406         TALLOC_CTX *frame = talloc_stackframe();
1407
1408         if (!fss_permitted(p)) {
1409                 TALLOC_FREE(frame);
1410                 return HRES_ERROR_V(HRES_E_ACCESSDENIED);
1411         }
1412
1413         sc_set = sc_set_lookup(fss_global.sc_sets, &r->in.ShadowCopySetId);
1414         if (sc_set == NULL) {
1415                 TALLOC_FREE(frame);
1416                 return HRES_ERROR_V(HRES_E_INVALIDARG);
1417         }
1418
1419         /*
1420          * If ShadowCopySet.Status is not "Exposed", the server SHOULD<9> fail
1421          * the call with FSRVP_E_BAD_STATE.
1422          * <9> If ShadowCopySet.Status is "Started", "Added",
1423          * "CreationInProgress", or "Committed", Windows Server 2012 FSRVP
1424          * servers return an error value of 0x80042311.
1425          */
1426         if ((sc_set->state == FSS_SC_STARTED)
1427          || (sc_set->state == FSS_SC_ADDED)
1428          || (sc_set->state == FSS_SC_CREATING)
1429          || (sc_set->state == FSS_SC_COMMITED)) {
1430                 TALLOC_FREE(frame);
1431                 return 0x80042311;      /* documented magic value */
1432         }
1433
1434         sc = sc_lookup(sc_set->scs, &r->in.ShadowCopyId);
1435         if (sc == NULL) {
1436                 TALLOC_FREE(frame);
1437                 return HRES_ERROR_V(HRES_E_INVALIDARG);
1438         }
1439
1440         status = fss_unc_parse(frame, r->in.ShareName, NULL, &share);
1441         if (!NT_STATUS_IS_OK(status)) {
1442                 TALLOC_FREE(frame);
1443                 return fss_ntstatus_map(status);
1444         }
1445
1446         sc_smap = sc_smap_lookup(sc->smaps, share);
1447         if (sc_smap == NULL) {
1448                 TALLOC_FREE(frame);
1449                 return HRES_ERROR_V(HRES_E_INVALIDARG);
1450         }
1451
1452         if (r->in.Level != 1) {
1453                 TALLOC_FREE(frame);
1454                 return HRES_ERROR_V(HRES_E_INVALIDARG);
1455         }
1456
1457         sm_out = talloc_zero(p->mem_ctx, struct fssagent_share_mapping_1);
1458         if (sm_out == NULL) {
1459                 TALLOC_FREE(frame);
1460                 return HRES_ERROR_V(HRES_E_OUTOFMEMORY);
1461         }
1462         sm_out->ShadowCopySetId = sc_set->id;
1463         sm_out->ShadowCopyId = sc->id;
1464         sm_out->ShareNameUNC = talloc_asprintf(sm_out, "\\\\%s\\%s",
1465                                                lp_netbios_name(),
1466                                                sc_smap->share_name);
1467         if (sm_out->ShareNameUNC == NULL) {
1468                 talloc_free(sm_out);
1469                 TALLOC_FREE(frame);
1470                 return HRES_ERROR_V(HRES_E_OUTOFMEMORY);
1471         }
1472         sm_out->ShadowCopyShareName = sc_smap->sc_share_name;
1473         unix_to_nt_time(&sm_out->tstamp, sc->create_ts);
1474         r->out.ShareMapping->ShareMapping1 = sm_out;
1475         TALLOC_FREE(frame);
1476
1477         /* reset msg sequence timer */
1478         TALLOC_FREE(fss_global.seq_tmr);
1479         fss_seq_tout_set(fss_global.mem_ctx, 1800, sc_set, &fss_global.seq_tmr);
1480
1481         return 0;
1482 }
1483
1484 static NTSTATUS sc_smap_unexpose(struct messaging_context *msg_ctx,
1485                                  struct fss_sc_smap *sc_smap, bool delete_all)
1486 {
1487         NTSTATUS ret;
1488         struct smbconf_ctx *conf_ctx;
1489         sbcErr cerr;
1490         bool is_modified = false;
1491         TALLOC_CTX *frame = talloc_stackframe();
1492
1493         cerr = smbconf_init(frame, &conf_ctx, "registry");
1494         if (!SBC_ERROR_IS_OK(cerr)) {
1495                 DEBUG(0, ("failed registry smbconf init: %s\n",
1496                           sbcErrorString(cerr)));
1497                 ret = NT_STATUS_UNSUCCESSFUL;
1498                 goto err_tmp;
1499         }
1500
1501         /* registry IO must be done as root */
1502         become_root();
1503
1504         cerr = smbconf_transaction_start(conf_ctx);
1505         if (!SBC_ERROR_IS_OK(cerr)) {
1506                 DEBUG(0, ("error starting transaction: %s\n",
1507                          sbcErrorString(cerr)));
1508                 ret = NT_STATUS_UNSUCCESSFUL;
1509                 goto err_conf;
1510         }
1511
1512         while (sc_smap) {
1513                 struct fss_sc_smap *sc_map_next = sc_smap->next;
1514                 if (!smbconf_share_exists(conf_ctx, sc_smap->sc_share_name)) {
1515                         DEBUG(2, ("no such share: %s\n", sc_smap->sc_share_name));
1516                         if (!delete_all) {
1517                                 ret = NT_STATUS_OK;
1518                                 goto err_cancel;
1519                         }
1520                         sc_smap = sc_map_next;
1521                         continue;
1522                 }
1523
1524                 cerr = smbconf_delete_share(conf_ctx, sc_smap->sc_share_name);
1525                 if (!SBC_ERROR_IS_OK(cerr)) {
1526                         DEBUG(0, ("error deleting share: %s\n",
1527                                  sbcErrorString(cerr)));
1528                         ret = NT_STATUS_UNSUCCESSFUL;
1529                         goto err_cancel;
1530                 }
1531                 is_modified = true;
1532                 sc_smap->is_exposed = false;
1533                 if (delete_all) {
1534                         sc_smap = sc_map_next;
1535                 } else {
1536                         sc_smap = NULL; /* only process single sc_map entry */
1537                 }
1538         }
1539         if (is_modified) {
1540                 cerr = smbconf_transaction_commit(conf_ctx);
1541                 if (!SBC_ERROR_IS_OK(cerr)) {
1542                         DEBUG(0, ("error committing transaction: %s\n",
1543                                   sbcErrorString(cerr)));
1544                         ret = NT_STATUS_UNSUCCESSFUL;
1545                         goto err_cancel;
1546                 }
1547                 messaging_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0);
1548         } else {
1549                 ret = NT_STATUS_OK;
1550                 goto err_cancel;
1551         }
1552         ret = NT_STATUS_OK;
1553
1554 err_conf:
1555         talloc_free(conf_ctx);
1556         unbecome_root();
1557 err_tmp:
1558         TALLOC_FREE(frame);
1559         return ret;
1560
1561 err_cancel:
1562         smbconf_transaction_cancel(conf_ctx);
1563         talloc_free(conf_ctx);
1564         unbecome_root();
1565         TALLOC_FREE(frame);
1566         return ret;
1567 }
1568
1569 uint32_t _fss_DeleteShareMapping(struct pipes_struct *p,
1570                                  struct fss_DeleteShareMapping *r)
1571 {
1572         struct fss_sc_set *sc_set;
1573         struct fss_sc *sc;
1574         struct fss_sc_smap *sc_smap;
1575         char *share;
1576         NTSTATUS status;
1577         TALLOC_CTX *frame = talloc_stackframe();
1578         struct connection_struct *conn;
1579         int snum;
1580         char *service;
1581
1582         if (!fss_permitted(p)) {
1583                 status = NT_STATUS_ACCESS_DENIED;
1584                 goto err_tmp_free;
1585         }
1586
1587         sc_set = sc_set_lookup(fss_global.sc_sets, &r->in.ShadowCopySetId);
1588         if (sc_set == NULL) {
1589                 /* docs say HRES_E_INVALIDARG */
1590                 status = NT_STATUS_OBJECTID_NOT_FOUND;
1591                 goto err_tmp_free;
1592         }
1593
1594         if ((sc_set->state != FSS_SC_EXPOSED)
1595          && (sc_set->state != FSS_SC_RECOVERED)) {
1596                 status = NT_STATUS_INVALID_SERVER_STATE;
1597                 goto err_tmp_free;
1598         }
1599
1600         sc = sc_lookup(sc_set->scs, &r->in.ShadowCopyId);
1601         if (sc == NULL) {
1602                 status = NT_STATUS_INVALID_PARAMETER;
1603                 goto err_tmp_free;
1604         }
1605
1606         status = fss_unc_parse(frame, r->in.ShareName, NULL, &share);
1607         if (!NT_STATUS_IS_OK(status)) {
1608                 goto err_tmp_free;
1609         }
1610
1611         sc_smap = sc_smap_lookup(sc->smaps, share);
1612         if (sc_smap == NULL) {
1613                 status = NT_STATUS_INVALID_PARAMETER;
1614                 goto err_tmp_free;
1615         }
1616
1617         status = sc_smap_unexpose(p->msg_ctx, sc_smap, false);
1618         if (!NT_STATUS_IS_OK(status)) {
1619                 DEBUG(0, ("failed to remove share %s: %s\n",
1620                           sc_smap->sc_share_name, nt_errstr(status)));
1621                 goto err_tmp_free;
1622         }
1623
1624         messaging_send_all(p->msg_ctx, MSG_SMB_FORCE_TDIS,
1625                            sc_smap->sc_share_name,
1626                            strlen(sc_smap->sc_share_name) + 1);
1627
1628         if (sc->smaps_count > 1) {
1629                 /* do not delete the underlying snapshot - still in use */
1630                 status = NT_STATUS_OK;
1631                 goto err_tmp_free;
1632         }
1633
1634         snum = find_service(frame, sc_smap->share_name, &service);
1635         if ((snum == -1) || (service == NULL)) {
1636                 DEBUG(0, ("share at %s not found\n", sc_smap->share_name));
1637                 status = NT_STATUS_UNSUCCESSFUL;
1638                 goto err_tmp_free;
1639         }
1640
1641         status = fss_conn_create_tos(p->msg_ctx, p->session_info, snum, &conn);
1642         if (!NT_STATUS_IS_OK(status)) {
1643                 goto err_tmp_free;
1644         }
1645         if (!become_user_without_service_by_session(conn, p->session_info)) {
1646                 DEBUG(0, ("failed to become user\n"));
1647                 status = NT_STATUS_ACCESS_DENIED;
1648                 goto err_tmp_free;
1649         }
1650
1651         status = SMB_VFS_SNAP_DELETE(conn, frame, sc->volume_name,
1652                                      sc->sc_path);
1653         unbecome_user_without_service();
1654         if (!NT_STATUS_IS_OK(status)) {
1655                 goto err_tmp_free;
1656         }
1657
1658         /* XXX set timeout r->in.TimeOutInMilliseconds */
1659         DEBUG(6, ("good snap delete\n"));
1660         DLIST_REMOVE(sc->smaps, sc_smap);
1661         sc->smaps_count--;
1662         talloc_free(sc_smap);
1663         if (sc->smaps_count == 0) {
1664                 DLIST_REMOVE(sc_set->scs, sc);
1665                 sc_set->scs_count--;
1666                 talloc_free(sc);
1667
1668                 if (sc_set->scs_count == 0) {
1669                         DLIST_REMOVE(fss_global.sc_sets, sc_set);
1670                         fss_global.sc_sets_count--;
1671                         talloc_free(sc_set);
1672                 }
1673         }
1674
1675         become_root();
1676         status = fss_state_store(fss_global.mem_ctx, fss_global.sc_sets,
1677                                  fss_global.sc_sets_count, fss_global.db_path);
1678         unbecome_root();
1679         if (!NT_STATUS_IS_OK(status)) {
1680                 DEBUG(1, ("failed to store fss server state: %s\n",
1681                           nt_errstr(status)));
1682         }
1683
1684         status = NT_STATUS_OK;
1685 err_tmp_free:
1686         TALLOC_FREE(frame);
1687         return fss_ntstatus_map(status);
1688 }
1689
1690 uint32_t _fss_PrepareShadowCopySet(struct pipes_struct *p,
1691                                    struct fss_PrepareShadowCopySet *r)
1692 {
1693         struct fss_sc_set *sc_set;
1694
1695         if (!fss_permitted(p)) {
1696                 return HRES_ERROR_V(HRES_E_ACCESSDENIED);
1697         }
1698
1699         sc_set = sc_set_lookup(fss_global.sc_sets, &r->in.ShadowCopySetId);
1700         if (sc_set == NULL) {
1701                 return HRES_ERROR_V(HRES_E_INVALIDARG);
1702         }
1703
1704         if (sc_set->state != FSS_SC_ADDED) {
1705                 return FSRVP_E_BAD_STATE;
1706         }
1707
1708         /* stop msg sequence timer */
1709         TALLOC_FREE(fss_global.seq_tmr);
1710
1711         /*
1712          * Windows Server "8" Beta takes ~60s here, presumably flushing
1713          * everything to disk. We may want to do something similar.
1714          */
1715
1716         /* start msg sequence timer, 1800 on success */
1717         fss_seq_tout_set(fss_global.mem_ctx, 1800, sc_set, &fss_global.seq_tmr);
1718
1719         return 0;
1720 }
1721
1722 static NTSTATUS FileServerVssAgent__op_init_server(
1723                 struct dcesrv_context *dce_ctx,
1724                 const struct dcesrv_endpoint_server *ep_server);
1725
1726 static NTSTATUS FileServerVssAgent__op_shutdown_server(
1727                 struct dcesrv_context *dce_ctx,
1728                 const struct dcesrv_endpoint_server *ep_server);
1729
1730 #define DCESRV_INTERFACE_FILESERVERVSSAGENT_INIT_SERVER \
1731         fileservervssagent_init_server
1732
1733 #define DCESRV_INTERFACE_FILESERVERVSSAGENT_SHUTDOWN_SERVER \
1734         fileservervssagent_shutdown_server
1735
1736 static NTSTATUS fileservervssagent_shutdown_server(
1737                 struct dcesrv_context *dce_ctx,
1738                 const struct dcesrv_endpoint_server *ep_server)
1739 {
1740         srv_fssa_cleanup();
1741         return FileServerVssAgent__op_shutdown_server(dce_ctx, ep_server);
1742 }
1743
1744 static NTSTATUS fileservervssagent_init_server(
1745                 struct dcesrv_context *dce_ctx,
1746                 const struct dcesrv_endpoint_server *ep_server)
1747 {
1748         NTSTATUS status;
1749         struct messaging_context *msg_ctx = global_messaging_context();
1750
1751         status = srv_fssa_start(msg_ctx);
1752         if (!NT_STATUS_IS_OK(status)) {
1753                 return status;
1754         }
1755
1756         return FileServerVssAgent__op_init_server(dce_ctx, ep_server);
1757 }
1758
1759 /* include the generated boilerplate */
1760 #include "librpc/gen_ndr/ndr_fsrvp_scompat.c"