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 v4-17-test 1498b464 Lines: 0 903 0.0 %
Date: 2024-06-13 04:01:37 Functions: 0 36 0.0 %

          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           0 : static uint32_t fss_ntstatus_map(NTSTATUS status)
      68             : {
      69             :         size_t i;
      70             : 
      71           0 :         if (NT_STATUS_IS_OK(status))
      72           0 :                 return 0;
      73             : 
      74             :         /* check fsrvp specific errors first */
      75           0 :         for (i = 0; i < ARRAY_SIZE(ntstatus_to_fsrvp_map); i++) {
      76           0 :                 if (NT_STATUS_EQUAL(status, ntstatus_to_fsrvp_map[i].status)) {
      77           0 :                         return ntstatus_to_fsrvp_map[i].fsrvp_err;
      78             :                 }
      79             :         }
      80             :         /* fall-back to generic hresult values */
      81           0 :         for (i = 0; i < ARRAY_SIZE(ntstatus_to_hres_map); i++) {
      82           0 :                 if (NT_STATUS_EQUAL(status, ntstatus_to_hres_map[i].status)) {
      83           0 :                         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           0 : static NTSTATUS fss_unc_parse(TALLOC_CTX *mem_ctx,
      91             :                               const char *unc,
      92             :                               char **_server,
      93             :                               char **_share)
      94             : {
      95             :         char *s;
      96             :         char *server;
      97             :         char *share;
      98             : 
      99           0 :         if (unc == NULL) {
     100           0 :                 return NT_STATUS_INVALID_PARAMETER;
     101             :         }
     102             : 
     103           0 :         s = strstr_m(unc, "\\\\");
     104           0 :         if (s == NULL) {
     105           0 :                 return NT_STATUS_INVALID_PARAMETER;
     106             :         }
     107             : 
     108           0 :         server = talloc_strdup(mem_ctx, s + 2);
     109           0 :         if (server == NULL) {
     110           0 :                 return NT_STATUS_NO_MEMORY;
     111             :         }
     112           0 :         s = strchr_m(server, '\\');
     113           0 :         if ((s == NULL) || (s == server)) {
     114           0 :                 return NT_STATUS_INVALID_PARAMETER;
     115             :         }
     116           0 :         *s = '\0';
     117           0 :         share = s + 1;
     118             : 
     119           0 :         s = strchr_m(share, '\\');
     120           0 :         if (s != NULL) {
     121             :                 /* diskshadow.exe adds a trailing '\' to the share-name */
     122           0 :                 *s = '\0';
     123             :         }
     124           0 :         if (strlen(share) == 0) {
     125           0 :                 return NT_STATUS_INVALID_PARAMETER;
     126             :         }
     127             : 
     128           0 :         if (_server != NULL) {
     129           0 :                 *_server = server;
     130             :         }
     131           0 :         if (_share != NULL) {
     132           0 :                 *_share = share;
     133             :         }
     134             : 
     135           0 :         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             :         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             :         char *share;
     153             :         int snum;
     154             :         int ret;
     155             :         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             :         struct fss_sc_set *sc_sets;
     203           0 :         uint32_t sc_sets_count = 0;
     204             :         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             :                 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             :                         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           0 : 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           0 :                 loadparm_s3_global_substitution();
     299           0 :         struct conn_struct_tos *c = NULL;
     300             :         NTSTATUS status;
     301             : 
     302           0 :         status = create_conn_struct_tos(msg_ctx,
     303             :                                         snum,
     304           0 :                                         lp_path(talloc_tos(), lp_sub, snum),
     305             :                                         session_info,
     306             :                                         &c);
     307           0 :         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           0 :         status = set_conn_force_user_group(c->conn, snum);
     314           0 :         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           0 :         *conn_out = c->conn;
     321           0 :         return NT_STATUS_OK;
     322             : }
     323             : 
     324           0 : static struct fss_sc_set *sc_set_lookup(struct fss_sc_set *sc_set_head,
     325             :                                         struct GUID *sc_set_id)
     326             : {
     327             : 
     328             :         struct fss_sc_set *sc_set;
     329             :         char *guid_str;
     330             : 
     331           0 :         for (sc_set = sc_set_head; sc_set; sc_set = sc_set->next) {
     332           0 :                 if (GUID_equal(&sc_set->id, sc_set_id)) {
     333           0 :                         return sc_set;
     334             :                 }
     335             :         }
     336           0 :         guid_str = GUID_string(sc_set_head, sc_set_id);
     337           0 :         DEBUG(4, ("shadow copy set with GUID %s not found\n",
     338             :                   guid_str ? guid_str : "NO MEM"));
     339           0 :         talloc_free(guid_str);
     340             : 
     341           0 :         return NULL;
     342             : }
     343             : 
     344           0 : static struct fss_sc *sc_lookup(struct fss_sc *sc_head, struct GUID *sc_id)
     345             : {
     346             : 
     347             :         struct fss_sc *sc;
     348             :         char *guid_str;
     349             : 
     350           0 :         for (sc = sc_head; sc; sc = sc->next) {
     351           0 :                 if (GUID_equal(&sc->id, sc_id)) {
     352           0 :                         return sc;
     353             :                 }
     354             :         }
     355           0 :         guid_str = GUID_string(sc_head, sc_id);
     356           0 :         DEBUG(4, ("shadow copy with GUID %s not found\n",
     357             :                   guid_str ? guid_str : "NO MEM"));
     358           0 :         talloc_free(guid_str);
     359             : 
     360           0 :         return NULL;
     361             : }
     362             : 
     363           0 : static struct fss_sc *sc_lookup_volname(struct fss_sc *sc_head,
     364             :                                         const char *volname)
     365             : {
     366             :         struct fss_sc *sc;
     367             : 
     368           0 :         for (sc = sc_head; sc; sc = sc->next) {
     369           0 :                 if (!strcmp(sc->volume_name, volname)) {
     370           0 :                         return sc;
     371             :                 }
     372             :         }
     373           0 :         DEBUG(4, ("shadow copy with base volume %s not found\n", volname));
     374           0 :         return NULL;
     375             : }
     376             : 
     377             : /* lookup is case-insensitive */
     378           0 : static struct fss_sc_smap *sc_smap_lookup(struct fss_sc_smap *smaps_head,
     379             :                                           const char *share)
     380             : {
     381             :         struct fss_sc_smap *sc_smap;
     382           0 :         for (sc_smap = smaps_head; sc_smap; sc_smap = sc_smap->next) {
     383           0 :                 if (!strcasecmp_m(sc_smap->share_name, share)) {
     384           0 :                         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           0 : static void srv_fssa_cleanup(void)
     392             : {
     393           0 :         talloc_free(fss_global.db_path);
     394           0 :         talloc_free(fss_global.mem_ctx);
     395           0 :         ZERO_STRUCT(fss_global);
     396           0 : }
     397             : 
     398           0 : static NTSTATUS srv_fssa_start(struct messaging_context *msg_ctx)
     399             : {
     400             :         NTSTATUS status;
     401           0 :         fss_global.mem_ctx = talloc_named_const(NULL, 0,
     402             :                                                 "parent fss rpc server ctx");
     403           0 :         if (fss_global.mem_ctx == NULL) {
     404           0 :                 return NT_STATUS_NO_MEMORY;
     405             :         }
     406             : 
     407           0 :         fss_global.db_path = lock_path(talloc_tos(), FSS_DB_NAME);
     408           0 :         if (fss_global.db_path == NULL) {
     409           0 :                 talloc_free(fss_global.mem_ctx);
     410           0 :                 return NT_STATUS_NO_MEMORY;
     411             :         }
     412             : 
     413           0 :         fss_global.min_vers = FSRVP_RPC_VERSION_1;
     414           0 :         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           0 :         if (lp_parm_bool(GLOBAL_SECTION_SNUM, "fss", "prune stale", false)) {
     420           0 :                 fss_prune_stale(msg_ctx, fss_global.db_path);
     421             :         }
     422           0 :         become_root();
     423           0 :         status = fss_state_retrieve(fss_global.mem_ctx, &fss_global.sc_sets,
     424             :                                     &fss_global.sc_sets_count,
     425           0 :                                     fss_global.db_path);
     426           0 :         unbecome_root();
     427           0 :         if (!NT_STATUS_IS_OK(status)) {
     428           0 :                 DEBUG(1, ("failed to retrieve fss server state: %s\n",
     429             :                           nt_errstr(status)));
     430             :         }
     431           0 :         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           0 : static bool fss_permitted(struct pipes_struct *p)
     440             : {
     441           0 :         struct dcesrv_call_state *dce_call = p->dce_call;
     442           0 :         struct auth_session_info *session_info =
     443           0 :                 dcesrv_call_session_info(dce_call);
     444             : 
     445           0 :         if (session_info->unix_token->uid == sec_initial_uid()) {
     446           0 :                 DEBUG(6, ("Granting FSRVP op, user started smbd\n"));
     447           0 :                 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           0 : 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           0 :         struct GUID *sc_set_id = NULL;
     478             :         struct fss_sc_set *sc_set;
     479             : 
     480             :         /*
     481             :          * MS-FSRVP: 3.1.5 Timer Events
     482             :          * Message Sequence Timer elapses: When the Message Sequence Timer
     483             :          * elapses, the server MUST delete the ShadowCopySet in the
     484             :          * GlobalShadowCopySetTable where ShadowCopySet.Status is not equal to
     485             :          * "Recovered", ContextSet MUST be set to FALSE, and the ShadowCopySet
     486             :          * object MUST be freed.
     487             :          */
     488           0 :         DEBUG(2, ("FSRVP msg seq timeout fired\n"));
     489             : 
     490           0 :         if (private_data == NULL) {
     491           0 :                 DEBUG(4, ("timeout without sc_set\n"));
     492           0 :                 goto out_init_ctx;
     493             :         }
     494             : 
     495           0 :         sc_set_id = talloc_get_type_abort(private_data, struct GUID);
     496           0 :         sc_set = sc_set_lookup(fss_global.sc_sets, sc_set_id);
     497           0 :         if (sc_set == NULL) {
     498           0 :                 DEBUG(0, ("timeout for unknown sc_set\n"));
     499           0 :                 goto out_init_ctx;
     500           0 :         } else if ((sc_set->state == FSS_SC_EXPOSED)
     501           0 :                         || (sc_set->state == FSS_SC_RECOVERED)) {
     502           0 :                 DEBUG(2, ("timeout for finished sc_set %s\n", sc_set->id_str));
     503           0 :                 goto out_init_ctx;
     504             :         }
     505           0 :         DEBUG(2, ("cleaning up sc_set %s\n", sc_set->id_str));
     506           0 :         SMB_ASSERT(fss_global.sc_sets_count > 0);
     507           0 :         DLIST_REMOVE(fss_global.sc_sets, sc_set);
     508           0 :         fss_global.sc_sets_count--;
     509           0 :         talloc_free(sc_set);
     510             : 
     511           0 : out_init_ctx:
     512           0 :         fss_global.ctx_set = false;
     513           0 :         fss_global.seq_tmr = NULL;
     514           0 :         talloc_free(sc_set_id);
     515           0 : }
     516             : 
     517           0 : static void fss_seq_tout_set(TALLOC_CTX *mem_ctx,
     518             :                              uint32_t timeout_s,
     519             :                              struct fss_sc_set *sc_set,
     520             :                              struct tevent_timer **tmr_out)
     521             : {
     522             :         struct tevent_timer *tmr;
     523           0 :         struct GUID *sc_set_id = NULL;
     524             :         uint32_t tout;
     525             : 
     526             :         /* allow changes to timeout for testing/debugging purposes */
     527           0 :         tout = lp_parm_int(GLOBAL_SECTION_SNUM, "fss",
     528             :                            "sequence timeout", timeout_s);
     529           0 :         if (tout == 0) {
     530           0 :                 DEBUG(2, ("FSRVP message sequence timeout disabled\n"));
     531           0 :                 *tmr_out = NULL;
     532           0 :                 return;
     533             :         }
     534             : 
     535           0 :         if (sc_set) {
     536             :                 /* don't use talloc_memdup(), need explicit type for callback */
     537           0 :                 sc_set_id = talloc(mem_ctx, struct GUID);
     538           0 :                 if (sc_set_id == NULL) {
     539           0 :                         smb_panic("no memory");
     540             :                 }
     541           0 :                 memcpy(sc_set_id, &sc_set->id, sizeof(*sc_set_id));
     542             :         }
     543             : 
     544           0 :         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           0 :         if (tmr == NULL) {
     549           0 :                 talloc_free(sc_set_id);
     550           0 :                 smb_panic("no memory");
     551             :         }
     552             : 
     553           0 :         *tmr_out = tmr;
     554             : }
     555             : 
     556           0 : uint32_t _fss_GetSupportedVersion(struct pipes_struct *p,
     557             :                                   struct fss_GetSupportedVersion *r)
     558             : {
     559           0 :         if (!fss_permitted(p)) {
     560           0 :                 return HRES_ERROR_V(HRES_E_ACCESSDENIED);
     561             :         }
     562             : 
     563           0 :         *r->out.MinVersion = fss_global.min_vers;
     564           0 :         *r->out.MaxVersion = fss_global.max_vers;
     565             : 
     566           0 :         return 0;
     567             : }
     568             : 
     569           0 : uint32_t _fss_SetContext(struct pipes_struct *p,
     570             :                          struct fss_SetContext *r)
     571             : {
     572           0 :         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           0 :         switch (r->in.Context & (~ATTR_AUTO_RECOVERY)) {
     578           0 :         case FSRVP_CTX_BACKUP:
     579           0 :                 DEBUG(6, ("fss ctx set backup\n"));
     580           0 :                 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             :                 break;  /* not reached */
     594             :         }
     595             : 
     596           0 :         fss_global.ctx_set = true;
     597           0 :         fss_global.cur_ctx = r->in.Context;
     598             : 
     599           0 :         TALLOC_FREE(fss_global.seq_tmr);        /* kill timer if running */
     600           0 :         fss_seq_tout_set(fss_global.mem_ctx, 180, NULL, &fss_global.seq_tmr);
     601             : 
     602           0 :         fss_global.cur_ctx = r->in.Context;
     603             : 
     604           0 :         return 0;
     605             : }
     606             : 
     607           0 : static bool sc_set_active(struct fss_sc_set *sc_set_head)
     608             : {
     609             : 
     610             :         struct fss_sc_set *sc_set;
     611             : 
     612           0 :         for (sc_set = sc_set_head; sc_set; sc_set = sc_set->next) {
     613           0 :                 if ((sc_set->state != FSS_SC_EXPOSED)
     614           0 :                  && (sc_set->state != FSS_SC_RECOVERED)) {
     615           0 :                         return true;
     616             :                 }
     617             :         }
     618             : 
     619           0 :         return false;
     620             : }
     621             : 
     622           0 : uint32_t _fss_StartShadowCopySet(struct pipes_struct *p,
     623             :                                  struct fss_StartShadowCopySet *r)
     624             : {
     625             :         struct fss_sc_set *sc_set;
     626             :         uint32_t ret;
     627             : 
     628           0 :         if (!fss_permitted(p)) {
     629           0 :                 ret = HRES_ERROR_V(HRES_E_ACCESSDENIED);
     630           0 :                 goto err_out;
     631             :         }
     632             : 
     633           0 :         if (!fss_global.ctx_set) {
     634           0 :                 DEBUG(3, ("invalid sequence: start sc set requested without "
     635             :                           "prior context set\n"));
     636           0 :                 ret = FSRVP_E_BAD_STATE;
     637           0 :                 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           0 :         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           0 :         TALLOC_FREE(fss_global.seq_tmr);
     652             : 
     653           0 :         sc_set = talloc_zero(fss_global.mem_ctx, struct fss_sc_set);
     654           0 :         if (sc_set == NULL) {
     655           0 :                 ret = HRES_ERROR_V(HRES_E_OUTOFMEMORY);
     656           0 :                 goto err_tmr_restart;
     657             :         }
     658             : 
     659           0 :         sc_set->id = GUID_random();  /* Windows servers ignore client ids */
     660           0 :         sc_set->id_str = GUID_string(sc_set, &sc_set->id);
     661           0 :         if (sc_set->id_str == NULL) {
     662           0 :                 ret = HRES_ERROR_V(HRES_E_OUTOFMEMORY);
     663           0 :                 goto err_sc_set_free;
     664             :         }
     665           0 :         sc_set->state = FSS_SC_STARTED;
     666           0 :         sc_set->context = fss_global.cur_ctx;
     667           0 :         DLIST_ADD_END(fss_global.sc_sets, sc_set);
     668           0 :         fss_global.sc_sets_count++;
     669           0 :         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           0 :         fss_seq_tout_set(fss_global.mem_ctx, 180, sc_set, &fss_global.seq_tmr);
     674             : 
     675           0 :         r->out.pShadowCopySetId = &sc_set->id;
     676             : 
     677           0 :         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           0 : err_out:
     684           0 :         return ret;
     685             : }
     686             : 
     687           0 : static uint32_t map_share_name(struct fss_sc_smap *sc_smap,
     688             :                                const struct fss_sc *sc)
     689             : {
     690           0 :         bool hidden_base = false;
     691             : 
     692           0 :         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           0 :         sc_smap->sc_share_name = talloc_asprintf(sc_smap, "%s@{%s}%s",
     703             :                                                 sc_smap->share_name,
     704           0 :                                                 sc->id_str,
     705             :                                                 hidden_base ? "$" : "");
     706           0 :         if (sc_smap->sc_share_name == NULL) {
     707           0 :                 return HRES_ERROR_V(HRES_E_OUTOFMEMORY);
     708             :         }
     709             : 
     710           0 :         return 0;
     711             : }
     712             : 
     713           0 : static uint32_t map_share_comment(struct fss_sc_smap *sc_smap,
     714             :                                   const struct fss_sc *sc)
     715             : {
     716             :         char *time_str;
     717             : 
     718           0 :         time_str = http_timestring(sc_smap, sc->create_ts);
     719           0 :         if (time_str == NULL) {
     720           0 :                 return HRES_ERROR_V(HRES_E_OUTOFMEMORY);
     721             :         }
     722             : 
     723           0 :         sc_smap->sc_share_comment = talloc_asprintf(sc_smap, "Shadow copy of %s taken %s",
     724             :                                                    sc_smap->share_name, time_str);
     725           0 :         if (sc_smap->sc_share_comment == NULL) {
     726           0 :                 return HRES_ERROR_V(HRES_E_OUTOFMEMORY);
     727             :         }
     728             : 
     729           0 :         return 0;
     730             : }
     731             : 
     732           0 : uint32_t _fss_AddToShadowCopySet(struct pipes_struct *p,
     733             :                                  struct fss_AddToShadowCopySet *r)
     734             : {
     735           0 :         struct dcesrv_call_state *dce_call = p->dce_call;
     736           0 :         struct auth_session_info *session_info =
     737           0 :                 dcesrv_call_session_info(dce_call);
     738             :         uint32_t ret;
     739             :         struct fss_sc_set *sc_set;
     740             :         struct fss_sc *sc;
     741             :         struct fss_sc_smap *sc_smap;
     742             :         int snum;
     743             :         char *service;
     744             :         char *base_vol;
     745             :         char *share;
     746             :         char *path_name;
     747             :         struct connection_struct *conn;
     748             :         NTSTATUS status;
     749           0 :         TALLOC_CTX *frame = talloc_stackframe();
     750           0 :         const struct loadparm_substitution *lp_sub =
     751           0 :                 loadparm_s3_global_substitution();
     752             : 
     753           0 :         if (!fss_permitted(p)) {
     754           0 :                 ret = HRES_ERROR_V(HRES_E_ACCESSDENIED);
     755           0 :                 goto err_tmp_free;
     756             :         }
     757             : 
     758           0 :         sc_set = sc_set_lookup(fss_global.sc_sets, &r->in.ShadowCopySetId);
     759           0 :         if (sc_set == NULL) {
     760           0 :                 ret = HRES_ERROR_V(HRES_E_INVALIDARG);
     761           0 :                 goto err_tmp_free;
     762             :         }
     763             : 
     764           0 :         status = fss_unc_parse(frame, r->in.ShareName, NULL, &share);
     765           0 :         if (!NT_STATUS_IS_OK(status)) {
     766           0 :                 ret = fss_ntstatus_map(status);
     767           0 :                 goto err_tmp_free;
     768             :         }
     769             : 
     770           0 :         snum = find_service(frame, share, &service);
     771           0 :         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           0 :         path_name = lp_path(frame, lp_sub, snum);
     778           0 :         if (path_name == NULL) {
     779           0 :                 ret = HRES_ERROR_V(HRES_E_OUTOFMEMORY);
     780           0 :                 goto err_tmp_free;
     781             :         }
     782             : 
     783           0 :         status = fss_conn_create_tos(p->msg_ctx, session_info, snum, &conn);
     784           0 :         if (!NT_STATUS_IS_OK(status)) {
     785           0 :                 ret = HRES_ERROR_V(HRES_E_ACCESSDENIED);
     786           0 :                 goto err_tmp_free;
     787             :         }
     788           0 :         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           0 :         status = SMB_VFS_SNAP_CHECK_PATH(conn, frame, path_name, &base_vol);
     795           0 :         unbecome_user_without_service();
     796           0 :         if (!NT_STATUS_IS_OK(status)) {
     797           0 :                 ret = FSRVP_E_NOT_SUPPORTED;
     798           0 :                 goto err_tmp_free;
     799             :         }
     800             : 
     801           0 :         if ((sc_set->state != FSS_SC_STARTED)
     802           0 :          && (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           0 :         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           0 :         sc = sc_lookup_volname(sc_set->scs, base_vol);
     820           0 :         if (sc != NULL) {
     821           0 :                 ret = FSRVP_E_OBJECT_ALREADY_EXISTS;
     822           0 :                 goto err_tmr_restart;
     823             :         }
     824             : 
     825           0 :         sc = talloc_zero(sc_set, struct fss_sc);
     826           0 :         if (sc == NULL) {
     827           0 :                 ret = HRES_ERROR_V(HRES_E_OUTOFMEMORY);
     828           0 :                 goto err_tmr_restart;
     829             :         }
     830           0 :         talloc_steal(sc, base_vol);
     831           0 :         sc->volume_name = base_vol;
     832           0 :         sc->sc_set = sc_set;
     833           0 :         sc->create_ts = time(NULL);
     834             : 
     835           0 :         sc->id = GUID_random();      /* Windows servers ignore client ids */
     836           0 :         sc->id_str = GUID_string(sc, &sc->id);
     837           0 :         if (sc->id_str == NULL) {
     838           0 :                 ret = HRES_ERROR_V(HRES_E_OUTOFMEMORY);
     839           0 :                 goto err_sc_free;
     840             :         }
     841             : 
     842           0 :         sc_smap = talloc_zero(sc, struct fss_sc_smap);
     843           0 :         if (sc_smap == NULL) {
     844           0 :                 ret = HRES_ERROR_V(HRES_E_OUTOFMEMORY);
     845           0 :                 goto err_sc_free;
     846             :         }
     847             : 
     848           0 :         talloc_steal(sc_smap, service);
     849           0 :         sc_smap->share_name = service;
     850           0 :         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           0 :         ret = map_share_name(sc_smap, sc);
     856           0 :         if (ret) {
     857           0 :                 goto err_sc_free;
     858             :         }
     859             : 
     860             :         /* add share map to shadow-copy */
     861           0 :         DLIST_ADD_END(sc->smaps, sc_smap);
     862           0 :         sc->smaps_count++;
     863             :         /* add shadow-copy to shadow-copy set */
     864           0 :         DLIST_ADD_END(sc_set->scs, sc);
     865           0 :         sc_set->scs_count++;
     866           0 :         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           0 :         fss_seq_tout_set(fss_global.mem_ctx, 1800, sc_set, &fss_global.seq_tmr);
     871             : 
     872           0 :         sc_set->state = FSS_SC_ADDED;
     873           0 :         r->out.pShadowCopyId = &sc->id;
     874             : 
     875           0 :         TALLOC_FREE(frame);
     876           0 :         return 0;
     877             : 
     878           0 : err_sc_free:
     879           0 :         talloc_free(sc);
     880           0 : err_tmr_restart:
     881           0 :         fss_seq_tout_set(fss_global.mem_ctx, 180, sc_set, &fss_global.seq_tmr);
     882           0 : err_tmp_free:
     883           0 :         TALLOC_FREE(frame);
     884           0 :         return ret;
     885             : }
     886             : 
     887           0 : 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           0 :         TALLOC_CTX *frame = talloc_stackframe();
     896             :         NTSTATUS status;
     897             :         bool rw;
     898             :         struct connection_struct *conn;
     899             :         int snum;
     900             :         char *service;
     901             : 
     902           0 :         snum = find_service(frame, sc->smaps->share_name, &service);
     903           0 :         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           0 :         status = fss_conn_create_tos(msg_ctx, session_info, snum, &conn);
     910           0 :         if (!NT_STATUS_IS_OK(status)) {
     911           0 :                 TALLOC_FREE(frame);
     912           0 :                 return status;
     913             :         }
     914             : 
     915           0 :         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           0 :         rw = ((sc->sc_set->context & ATTR_AUTO_RECOVERY) == ATTR_AUTO_RECOVERY);
     921           0 :         status = SMB_VFS_SNAP_CREATE(conn, mem_ctx,
     922             :                                      sc->volume_name,
     923             :                                      &sc->create_ts, rw,
     924             :                                      base_path, snap_path);
     925           0 :         unbecome_user_without_service();
     926           0 :         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           0 :         TALLOC_FREE(frame);
     933           0 :         return status;
     934             : }
     935             : 
     936           0 : uint32_t _fss_CommitShadowCopySet(struct pipes_struct *p,
     937             :                                   struct fss_CommitShadowCopySet *r)
     938             : {
     939           0 :         struct dcesrv_call_state *dce_call = p->dce_call;
     940           0 :         struct auth_session_info *session_info =
     941           0 :                 dcesrv_call_session_info(dce_call);
     942             :         struct fss_sc_set *sc_set;
     943             :         struct fss_sc *sc;
     944             :         uint32_t commit_count;
     945             :         NTSTATUS status;
     946             :         NTSTATUS saved_status;
     947           0 :         TALLOC_CTX *frame = talloc_stackframe();
     948             : 
     949           0 :         if (!fss_permitted(p)) {
     950           0 :                 status = NT_STATUS_ACCESS_DENIED;
     951           0 :                 goto err_tmp_free;
     952             :         }
     953             : 
     954           0 :         sc_set = sc_set_lookup(fss_global.sc_sets, &r->in.ShadowCopySetId);
     955           0 :         if (sc_set == NULL) {
     956           0 :                 status = NT_STATUS_INVALID_PARAMETER;
     957           0 :                 goto err_tmp_free;
     958             :         }
     959             : 
     960           0 :         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           0 :         TALLOC_FREE(fss_global.seq_tmr);
     967           0 :         sc_set->state = FSS_SC_CREATING;
     968           0 :         commit_count = 0;
     969           0 :         saved_status = NT_STATUS_OK;
     970           0 :         for (sc = sc_set->scs; sc; sc = sc->next) {
     971             :                 char *base_path;
     972             :                 char *snap_path;
     973           0 :                 status = commit_sc_with_conn(frame, global_event_context(),
     974             :                                              p->msg_ctx, session_info, sc,
     975             :                                              &base_path, &snap_path);
     976           0 :                 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           0 :                 commit_count++;
     985           0 :                 DEBUG(10, ("good snap create %d\n",
     986             :                            commit_count));
     987           0 :                 sc->sc_path = talloc_steal(sc, snap_path);
     988             :         }
     989           0 :         if (!NT_STATUS_IS_OK(saved_status)) {
     990           0 :                 status = saved_status;
     991           0 :                 goto err_state_revert;
     992             :         }
     993             : 
     994           0 :         sc_set->state = FSS_SC_COMMITED;
     995           0 :         become_root();
     996           0 :         status = fss_state_store(fss_global.mem_ctx, fss_global.sc_sets,
     997             :                                  fss_global.sc_sets_count,
     998           0 :                                  fss_global.db_path);
     999           0 :         unbecome_root();
    1000           0 :         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           0 :         fss_seq_tout_set(fss_global.mem_ctx, 180, sc_set,
    1006             :                          &fss_global.seq_tmr);
    1007           0 :         TALLOC_FREE(frame);
    1008           0 :         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           0 : err_tmp_free:
    1015           0 :         TALLOC_FREE(frame);
    1016           0 :         return fss_ntstatus_map(status);
    1017             : }
    1018             : 
    1019           0 : static sbcErr fss_conf_get_share_def(struct smbconf_ctx *fconf_ctx,
    1020             :                                      struct smbconf_ctx *rconf_ctx,
    1021             :                                      TALLOC_CTX *mem_ctx,
    1022             :                                      char *share,
    1023             :                                      struct smbconf_service **service_def)
    1024             : {
    1025             :         sbcErr cerr;
    1026             :         struct smbconf_service *def;
    1027             : 
    1028           0 :         *service_def = NULL;
    1029           0 :         cerr = smbconf_get_share(fconf_ctx, mem_ctx, share, &def);
    1030           0 :         if (SBC_ERROR_IS_OK(cerr)) {
    1031           0 :                 *service_def = def;
    1032           0 :                 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           0 : static uint32_t fss_sc_expose(struct smbconf_ctx *fconf_ctx,
    1050             :                               struct smbconf_ctx *rconf_ctx,
    1051             :                               TALLOC_CTX *mem_ctx,
    1052             :                               struct fss_sc *sc)
    1053             : {
    1054             :         struct fss_sc_smap *sc_smap;
    1055           0 :         uint32_t err = 0;
    1056             : 
    1057           0 :         for (sc_smap = sc->smaps; sc_smap; sc_smap = sc_smap->next) {
    1058             :                 sbcErr cerr;
    1059           0 :                 struct smbconf_service *base_service = NULL;
    1060             :                 struct security_descriptor *sd;
    1061             :                 size_t sd_size;
    1062             : 
    1063           0 :                 cerr = fss_conf_get_share_def(fconf_ctx, rconf_ctx, mem_ctx,
    1064             :                                             sc_smap->share_name, &base_service);
    1065           0 :                 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           0 :                 err = map_share_comment(sc_smap, sc);
    1075           0 :                 if (err) {
    1076           0 :                         DEBUG(0, ("failed to map share comment\n"));
    1077           0 :                         break;
    1078             :                 }
    1079             : 
    1080           0 :                 base_service->name = sc_smap->sc_share_name;
    1081             : 
    1082           0 :                 cerr = smbconf_create_set_share(rconf_ctx, base_service);
    1083           0 :                 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           0 :                 cerr = smbconf_set_parameter(rconf_ctx, sc_smap->sc_share_name,
    1090           0 :                                              "path", sc->sc_path);
    1091           0 :                 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           0 :                 if (sc_smap->sc_share_comment != NULL) {
    1098           0 :                         cerr = smbconf_set_parameter(rconf_ctx,
    1099           0 :                                                     sc_smap->sc_share_name,
    1100             :                                                     "comment",
    1101           0 :                                                     sc_smap->sc_share_comment);
    1102           0 :                         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           0 :                 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           0 :                 sd = get_share_security(mem_ctx, sc_smap->share_name, &sd_size);
    1120           0 :                 if (sd == NULL) {
    1121           0 :                         DEBUG(2, ("no share SD to clone for %s snapshot\n",
    1122             :                                   sc_smap->share_name));
    1123             :                 } else {
    1124             :                         NTSTATUS status;
    1125           0 :                         status = set_share_security(sc_smap->sc_share_name, sd);
    1126           0 :                         TALLOC_FREE(sd);
    1127           0 :                         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           0 :         return err;
    1137             : }
    1138             : 
    1139           0 : uint32_t _fss_ExposeShadowCopySet(struct pipes_struct *p,
    1140             :                                   struct fss_ExposeShadowCopySet *r)
    1141             : {
    1142             :         NTSTATUS status;
    1143             :         struct fss_sc_set *sc_set;
    1144             :         struct fss_sc *sc;
    1145             :         uint32_t ret;
    1146             :         struct smbconf_ctx *fconf_ctx;
    1147             :         struct smbconf_ctx *rconf_ctx;
    1148             :         sbcErr cerr;
    1149             :         char *fconf_path;
    1150           0 :         TALLOC_CTX *frame = talloc_stackframe();
    1151             : 
    1152           0 :         if (!fss_permitted(p)) {
    1153           0 :                 ret = HRES_ERROR_V(HRES_E_ACCESSDENIED);
    1154           0 :                 goto err_out;
    1155             :         }
    1156             : 
    1157           0 :         sc_set = sc_set_lookup(fss_global.sc_sets, &r->in.ShadowCopySetId);
    1158           0 :         if (sc_set == NULL) {
    1159           0 :                 ret = HRES_ERROR_V(HRES_E_INVALIDARG);
    1160           0 :                 goto err_out;
    1161             :         }
    1162             : 
    1163           0 :         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           0 :         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           0 :         cerr = smbconf_init(frame, &rconf_ctx, "registry");
    1178           0 :         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           0 :         fconf_path = talloc_asprintf(frame, "file:%s", get_dyn_CONFIGFILE());
    1185           0 :         if (fconf_path == NULL) {
    1186           0 :                 ret = HRES_ERROR_V(HRES_E_OUTOFMEMORY);
    1187           0 :                 goto err_tmr_restart;
    1188             :         }
    1189           0 :         cerr = smbconf_init(frame, &fconf_ctx, fconf_path);
    1190           0 :         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           0 :         become_root();
    1199           0 :         cerr = smbconf_transaction_start(rconf_ctx);
    1200           0 :         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           0 :         for (sc = sc_set->scs; sc; sc = sc->next) {
    1209           0 :                 ret = fss_sc_expose(fconf_ctx, rconf_ctx, frame, sc);
    1210           0 :                 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           0 :         cerr = smbconf_transaction_commit(rconf_ctx);
    1218           0 :         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           0 :         unbecome_root();
    1225             : 
    1226           0 :         messaging_send_all(p->msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0);
    1227           0 :         for (sc = sc_set->scs; sc; sc = sc->next) {
    1228             :                 struct fss_sc_smap *sm;
    1229           0 :                 for (sm = sc->smaps; sm; sm = sm->next)
    1230           0 :                         sm->is_exposed = true;
    1231             :         }
    1232           0 :         sc_set->state = FSS_SC_EXPOSED;
    1233           0 :         become_root();
    1234           0 :         status = fss_state_store(fss_global.mem_ctx, fss_global.sc_sets,
    1235           0 :                                  fss_global.sc_sets_count, fss_global.db_path);
    1236           0 :         unbecome_root();
    1237           0 :         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           0 :         fss_seq_tout_set(fss_global.mem_ctx, 180, sc_set, &fss_global.seq_tmr);
    1243           0 :         TALLOC_FREE(frame);
    1244           0 :         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           0 : err_out:
    1252           0 :         TALLOC_FREE(frame);
    1253           0 :         return ret;
    1254             : }
    1255             : 
    1256           0 : uint32_t _fss_RecoveryCompleteShadowCopySet(struct pipes_struct *p,
    1257             :                                 struct fss_RecoveryCompleteShadowCopySet *r)
    1258             : {
    1259             :         NTSTATUS status;
    1260             :         struct fss_sc_set *sc_set;
    1261             : 
    1262           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             :         }
    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           0 : uint32_t _fss_AbortShadowCopySet(struct pipes_struct *p,
    1299             :                                  struct fss_AbortShadowCopySet *r)
    1300             : {
    1301             :         NTSTATUS status;
    1302             :         struct fss_sc_set *sc_set;
    1303             : 
    1304           0 :         if (!fss_permitted(p)) {
    1305           0 :                 return HRES_ERROR_V(HRES_E_ACCESSDENIED);
    1306             :         }
    1307             : 
    1308           0 :         sc_set = sc_set_lookup(fss_global.sc_sets, &r->in.ShadowCopySetId);
    1309           0 :         if (sc_set == NULL) {
    1310           0 :                 return HRES_ERROR_V(HRES_E_INVALIDARG);
    1311             :         }
    1312             : 
    1313           0 :         DEBUG(6, ("%s: aborting shadow-copy set\n", sc_set->id_str));
    1314             : 
    1315           0 :         if ((sc_set->state == FSS_SC_COMMITED)
    1316           0 :          || (sc_set->state == FSS_SC_EXPOSED)
    1317           0 :          || (sc_set->state == FSS_SC_RECOVERED)) {
    1318           0 :                 return 0;
    1319             :         }
    1320             : 
    1321           0 :         if (sc_set->state == FSS_SC_CREATING) {
    1322           0 :                 return FSRVP_E_BAD_STATE;
    1323             :         }
    1324             : 
    1325           0 :         DLIST_REMOVE(fss_global.sc_sets, sc_set);
    1326           0 :         talloc_free(sc_set);
    1327           0 :         fss_global.sc_sets_count--;
    1328           0 :         become_root();
    1329           0 :         status = fss_state_store(fss_global.mem_ctx, fss_global.sc_sets,
    1330           0 :                                  fss_global.sc_sets_count, fss_global.db_path);
    1331           0 :         unbecome_root();
    1332           0 :         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           0 :         return 0;
    1338             : }
    1339             : 
    1340           0 : uint32_t _fss_IsPathSupported(struct pipes_struct *p,
    1341             :                               struct fss_IsPathSupported *r)
    1342             : {
    1343           0 :         struct dcesrv_call_state *dce_call = p->dce_call;
    1344           0 :         struct auth_session_info *session_info =
    1345           0 :                 dcesrv_call_session_info(dce_call);
    1346             :         int snum;
    1347             :         char *service;
    1348             :         char *base_vol;
    1349             :         NTSTATUS status;
    1350             :         struct connection_struct *conn;
    1351             :         char *share;
    1352           0 :         TALLOC_CTX *frame = talloc_stackframe();
    1353           0 :         const struct loadparm_substitution *lp_sub =
    1354           0 :                 loadparm_s3_global_substitution();
    1355             : 
    1356           0 :         if (!fss_permitted(p)) {
    1357           0 :                 TALLOC_FREE(frame);
    1358           0 :                 return HRES_ERROR_V(HRES_E_ACCESSDENIED);
    1359             :         }
    1360             : 
    1361           0 :         status = fss_unc_parse(frame, r->in.ShareName, NULL, &share);
    1362           0 :         if (!NT_STATUS_IS_OK(status)) {
    1363           0 :                 TALLOC_FREE(frame);
    1364           0 :                 return fss_ntstatus_map(status);
    1365             :         }
    1366             : 
    1367           0 :         snum = find_service(frame, share, &service);
    1368           0 :         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           0 :         status = fss_conn_create_tos(p->msg_ctx, session_info, snum, &conn);
    1375           0 :         if (!NT_STATUS_IS_OK(status)) {
    1376           0 :                 TALLOC_FREE(frame);
    1377           0 :                 return HRES_ERROR_V(HRES_E_ACCESSDENIED);
    1378             :         }
    1379           0 :         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           0 :         status = SMB_VFS_SNAP_CHECK_PATH(conn, frame,
    1385             :                                          lp_path(frame, lp_sub, snum),
    1386             :                                          &base_vol);
    1387           0 :         unbecome_user_without_service();
    1388           0 :         if (!NT_STATUS_IS_OK(status)) {
    1389           0 :                 TALLOC_FREE(frame);
    1390           0 :                 return FSRVP_E_NOT_SUPPORTED;
    1391             :         }
    1392             : 
    1393           0 :         *r->out.OwnerMachineName = lp_netbios_name();
    1394           0 :         *r->out.SupportedByThisProvider = 1;
    1395           0 :         TALLOC_FREE(frame);
    1396           0 :         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           0 : uint32_t _fss_GetShareMapping(struct pipes_struct *p,
    1411             :                               struct fss_GetShareMapping *r)
    1412             : {
    1413             :         NTSTATUS status;
    1414             :         struct fss_sc_set *sc_set;
    1415             :         struct fss_sc *sc;
    1416             :         struct fss_sc_smap *sc_smap;
    1417             :         char *share;
    1418             :         struct fssagent_share_mapping_1 *sm_out;
    1419           0 :         TALLOC_CTX *frame = talloc_stackframe();
    1420             : 
    1421           0 :         if (!fss_permitted(p)) {
    1422           0 :                 TALLOC_FREE(frame);
    1423           0 :                 return HRES_ERROR_V(HRES_E_ACCESSDENIED);
    1424             :         }
    1425             : 
    1426           0 :         sc_set = sc_set_lookup(fss_global.sc_sets, &r->in.ShadowCopySetId);
    1427           0 :         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           0 :         if ((sc_set->state == FSS_SC_STARTED)
    1440           0 :          || (sc_set->state == FSS_SC_ADDED)
    1441           0 :          || (sc_set->state == FSS_SC_CREATING)
    1442           0 :          || (sc_set->state == FSS_SC_COMMITED)) {
    1443           0 :                 TALLOC_FREE(frame);
    1444           0 :                 return 0x80042311;      /* documented magic value */
    1445             :         }
    1446             : 
    1447           0 :         sc = sc_lookup(sc_set->scs, &r->in.ShadowCopyId);
    1448           0 :         if (sc == NULL) {
    1449           0 :                 TALLOC_FREE(frame);
    1450           0 :                 return HRES_ERROR_V(HRES_E_INVALIDARG);
    1451             :         }
    1452             : 
    1453           0 :         status = fss_unc_parse(frame, r->in.ShareName, NULL, &share);
    1454           0 :         if (!NT_STATUS_IS_OK(status)) {
    1455           0 :                 TALLOC_FREE(frame);
    1456           0 :                 return fss_ntstatus_map(status);
    1457             :         }
    1458             : 
    1459           0 :         sc_smap = sc_smap_lookup(sc->smaps, share);
    1460           0 :         if (sc_smap == NULL) {
    1461           0 :                 TALLOC_FREE(frame);
    1462           0 :                 return HRES_ERROR_V(HRES_E_INVALIDARG);
    1463             :         }
    1464             : 
    1465           0 :         if (r->in.Level != 1) {
    1466           0 :                 TALLOC_FREE(frame);
    1467           0 :                 return HRES_ERROR_V(HRES_E_INVALIDARG);
    1468             :         }
    1469             : 
    1470           0 :         sm_out = talloc_zero(p->mem_ctx, struct fssagent_share_mapping_1);
    1471           0 :         if (sm_out == NULL) {
    1472           0 :                 TALLOC_FREE(frame);
    1473           0 :                 return HRES_ERROR_V(HRES_E_OUTOFMEMORY);
    1474             :         }
    1475           0 :         sm_out->ShadowCopySetId = sc_set->id;
    1476           0 :         sm_out->ShadowCopyId = sc->id;
    1477           0 :         sm_out->ShareNameUNC = talloc_asprintf(sm_out, "\\\\%s\\%s",
    1478             :                                                lp_netbios_name(),
    1479             :                                                sc_smap->share_name);
    1480           0 :         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           0 :         sm_out->ShadowCopyShareName = sc_smap->sc_share_name;
    1486           0 :         unix_to_nt_time(&sm_out->tstamp, sc->create_ts);
    1487           0 :         r->out.ShareMapping->ShareMapping1 = sm_out;
    1488           0 :         TALLOC_FREE(frame);
    1489             : 
    1490             :         /* reset msg sequence timer */
    1491           0 :         TALLOC_FREE(fss_global.seq_tmr);
    1492           0 :         fss_seq_tout_set(fss_global.mem_ctx, 1800, sc_set, &fss_global.seq_tmr);
    1493             : 
    1494           0 :         return 0;
    1495             : }
    1496             : 
    1497           0 : static NTSTATUS sc_smap_unexpose(struct messaging_context *msg_ctx,
    1498             :                                  struct fss_sc_smap *sc_smap, bool delete_all)
    1499             : {
    1500             :         NTSTATUS ret;
    1501             :         struct smbconf_ctx *conf_ctx;
    1502             :         sbcErr cerr;
    1503           0 :         bool is_modified = false;
    1504           0 :         TALLOC_CTX *frame = talloc_stackframe();
    1505             : 
    1506           0 :         cerr = smbconf_init(frame, &conf_ctx, "registry");
    1507           0 :         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           0 :         become_root();
    1516             : 
    1517           0 :         cerr = smbconf_transaction_start(conf_ctx);
    1518           0 :         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           0 :         while (sc_smap) {
    1526           0 :                 struct fss_sc_smap *sc_map_next = sc_smap->next;
    1527           0 :                 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           0 :                 cerr = smbconf_delete_share(conf_ctx, sc_smap->sc_share_name);
    1538           0 :                 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           0 :                 is_modified = true;
    1545           0 :                 sc_smap->is_exposed = false;
    1546           0 :                 if (delete_all) {
    1547           0 :                         sc_smap = sc_map_next;
    1548             :                 } else {
    1549           0 :                         sc_smap = NULL; /* only process single sc_map entry */
    1550             :                 }
    1551             :         }
    1552           0 :         if (is_modified) {
    1553           0 :                 cerr = smbconf_transaction_commit(conf_ctx);
    1554           0 :                 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           0 :                 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           0 :         ret = NT_STATUS_OK;
    1566             : 
    1567           0 : err_conf:
    1568           0 :         talloc_free(conf_ctx);
    1569           0 :         unbecome_root();
    1570           0 : err_tmp:
    1571           0 :         TALLOC_FREE(frame);
    1572           0 :         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           0 : uint32_t _fss_DeleteShareMapping(struct pipes_struct *p,
    1583             :                                  struct fss_DeleteShareMapping *r)
    1584             : {
    1585           0 :         struct dcesrv_call_state *dce_call = p->dce_call;
    1586           0 :         struct auth_session_info *session_info =
    1587           0 :                 dcesrv_call_session_info(dce_call);
    1588             :         struct fss_sc_set *sc_set;
    1589             :         struct fss_sc *sc;
    1590             :         struct fss_sc_smap *sc_smap;
    1591             :         char *share;
    1592             :         NTSTATUS status;
    1593           0 :         TALLOC_CTX *frame = talloc_stackframe();
    1594             :         struct connection_struct *conn;
    1595             :         int snum;
    1596             :         char *service;
    1597             : 
    1598           0 :         if (!fss_permitted(p)) {
    1599           0 :                 status = NT_STATUS_ACCESS_DENIED;
    1600           0 :                 goto err_tmp_free;
    1601             :         }
    1602             : 
    1603           0 :         sc_set = sc_set_lookup(fss_global.sc_sets, &r->in.ShadowCopySetId);
    1604           0 :         if (sc_set == NULL) {
    1605             :                 /* docs say HRES_E_INVALIDARG */
    1606           0 :                 status = NT_STATUS_OBJECTID_NOT_FOUND;
    1607           0 :                 goto err_tmp_free;
    1608             :         }
    1609             : 
    1610           0 :         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           0 :         sc = sc_lookup(sc_set->scs, &r->in.ShadowCopyId);
    1617           0 :         if (sc == NULL) {
    1618           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    1619           0 :                 goto err_tmp_free;
    1620             :         }
    1621             : 
    1622           0 :         status = fss_unc_parse(frame, r->in.ShareName, NULL, &share);
    1623           0 :         if (!NT_STATUS_IS_OK(status)) {
    1624           0 :                 goto err_tmp_free;
    1625             :         }
    1626             : 
    1627           0 :         sc_smap = sc_smap_lookup(sc->smaps, share);
    1628           0 :         if (sc_smap == NULL) {
    1629           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    1630           0 :                 goto err_tmp_free;
    1631             :         }
    1632             : 
    1633           0 :         status = sc_smap_unexpose(p->msg_ctx, sc_smap, false);
    1634           0 :         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           0 :         messaging_send_all(p->msg_ctx, MSG_SMB_FORCE_TDIS,
    1641           0 :                            sc_smap->sc_share_name,
    1642           0 :                            strlen(sc_smap->sc_share_name) + 1);
    1643             : 
    1644           0 :         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           0 :         snum = find_service(frame, sc_smap->share_name, &service);
    1651           0 :         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           0 :         status = fss_conn_create_tos(p->msg_ctx, session_info, snum, &conn);
    1658           0 :         if (!NT_STATUS_IS_OK(status)) {
    1659           0 :                 goto err_tmp_free;
    1660             :         }
    1661           0 :         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           0 :         status = SMB_VFS_SNAP_DELETE(conn, frame, sc->volume_name,
    1668             :                                      sc->sc_path);
    1669           0 :         unbecome_user_without_service();
    1670           0 :         if (!NT_STATUS_IS_OK(status)) {
    1671           0 :                 goto err_tmp_free;
    1672             :         }
    1673             : 
    1674             :         /* XXX set timeout r->in.TimeOutInMilliseconds */
    1675           0 :         DEBUG(6, ("good snap delete\n"));
    1676           0 :         DLIST_REMOVE(sc->smaps, sc_smap);
    1677           0 :         sc->smaps_count--;
    1678           0 :         talloc_free(sc_smap);
    1679           0 :         if (sc->smaps_count == 0) {
    1680           0 :                 DLIST_REMOVE(sc_set->scs, sc);
    1681           0 :                 sc_set->scs_count--;
    1682           0 :                 talloc_free(sc);
    1683             : 
    1684           0 :                 if (sc_set->scs_count == 0) {
    1685           0 :                         DLIST_REMOVE(fss_global.sc_sets, sc_set);
    1686           0 :                         fss_global.sc_sets_count--;
    1687           0 :                         talloc_free(sc_set);
    1688             :                 }
    1689             :         }
    1690             : 
    1691           0 :         become_root();
    1692           0 :         status = fss_state_store(fss_global.mem_ctx, fss_global.sc_sets,
    1693           0 :                                  fss_global.sc_sets_count, fss_global.db_path);
    1694           0 :         unbecome_root();
    1695           0 :         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           0 :         status = NT_STATUS_OK;
    1701           0 : err_tmp_free:
    1702           0 :         TALLOC_FREE(frame);
    1703           0 :         return fss_ntstatus_map(status);
    1704             : }
    1705             : 
    1706           0 : uint32_t _fss_PrepareShadowCopySet(struct pipes_struct *p,
    1707             :                                    struct fss_PrepareShadowCopySet *r)
    1708             : {
    1709             :         struct fss_sc_set *sc_set;
    1710             : 
    1711           0 :         if (!fss_permitted(p)) {
    1712           0 :                 return HRES_ERROR_V(HRES_E_ACCESSDENIED);
    1713             :         }
    1714             : 
    1715           0 :         sc_set = sc_set_lookup(fss_global.sc_sets, &r->in.ShadowCopySetId);
    1716           0 :         if (sc_set == NULL) {
    1717           0 :                 return HRES_ERROR_V(HRES_E_INVALIDARG);
    1718             :         }
    1719             : 
    1720           0 :         if (sc_set->state != FSS_SC_ADDED) {
    1721           0 :                 return FSRVP_E_BAD_STATE;
    1722             :         }
    1723             : 
    1724             :         /* stop msg sequence timer */
    1725           0 :         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           0 :         fss_seq_tout_set(fss_global.mem_ctx, 1800, sc_set, &fss_global.seq_tmr);
    1734             : 
    1735           0 :         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           0 : static NTSTATUS fileservervssagent_shutdown_server(
    1753             :                 struct dcesrv_context *dce_ctx,
    1754             :                 const struct dcesrv_endpoint_server *ep_server)
    1755             : {
    1756           0 :         srv_fssa_cleanup();
    1757           0 :         return FileServerVssAgent__op_shutdown_server(dce_ctx, ep_server);
    1758             : }
    1759             : 
    1760           0 : static NTSTATUS fileservervssagent_init_server(
    1761             :                 struct dcesrv_context *dce_ctx,
    1762             :                 const struct dcesrv_endpoint_server *ep_server)
    1763             : {
    1764             :         NTSTATUS status;
    1765           0 :         struct messaging_context *msg_ctx = global_messaging_context();
    1766             : 
    1767           0 :         status = srv_fssa_start(msg_ctx);
    1768           0 :         if (!NT_STATUS_IS_OK(status)) {
    1769           0 :                 return status;
    1770             :         }
    1771             : 
    1772           0 :         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.13