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