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