LCOV - code coverage report
Current view: top level - source3/rpc_server/fss - srv_fss_agent.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 522 1001 52.1 %
Date: 2024-02-28 12:06:22 Functions: 32 36 88.9 %

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

Generated by: LCOV version 1.14