1
0
mirror of https://github.com/samba-team/samba.git synced 2025-03-27 22:50:26 +03:00

fsrvp: add remote snapshot RPC server

The Samba fss_agent RPC server is an implementation of the File Server
Remote VSS (Volume Shadow Copy Service) Protocol, or FSRVP for short.

FSRVP is new with Windows Server 2012, and allows authenticated clients
to remotely request the creation, exposure and deletion of share
snapshots.

The fss_agent RPC server processes requests on the FssAgentRpc named
pipe, and dispatches relevant snapshot creation and deletion requests
through to the VFS.
The registry smb.conf back-end is used to expose snapshot shares, with
configuration parameters and share ACLs cloned from the base share.

There are three FSRVP client implementations that I'm aware of:
- Samba rpcclient includes fss_X commands.
- Windows Server 2012 includes diskshadow.exe.
- System Center 2012.

FSRVP operations are only processed for users with:
- Built-in Administrators group membership, or
- Built-in Backup Operators group membership, or
- Backup Operator privileges, or
- Security token matches the initial process UID

MS-FSRVP specifies that server state should be stored persistently
during operation and retrieved on startup. Use the existing fss_srv.tdb
FSRVP state storage back-end to satisfy this requirement.

Signed-off-by: David Disseldorp <ddiss@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
This commit is contained in:
David Disseldorp 2012-04-10 14:32:41 +02:00 committed by Jeremy Allison
parent 9f7dd07d26
commit b6e034069f
8 changed files with 1856 additions and 4 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,26 @@
/*
* File Server Remote VSS Protocol (FSRVP) server
*
* Copyright (C) David Disseldorp 2012-2015
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _SRV_FSS_AGENT_H_
#define _SRV_FSS_AGENT_H_
NTSTATUS srv_fssa_start(void);
void srv_fssa_cleanup(void);
#endif /*_SRV_FSS_AGENT_H_ */

221
source3/rpc_server/fssd.c Normal file
View File

@ -0,0 +1,221 @@
/*
* File Server Shadow-Copy Daemon
*
* Copyright (C) David Disseldorp 2012-2015
*
* Based on epmd.c:
* Copyright (c) 2011 Andreas Schneider <asn@samba.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include "includes.h"
#include "serverid.h"
#include "ntdomain.h"
#include "messages.h"
#include "librpc/rpc/dcerpc_ep.h"
#include "../librpc/gen_ndr/srv_fsrvp.h"
#include "rpc_server/rpc_server.h"
#include "rpc_server/rpc_sock_helper.h"
#include "rpc_server/fss/srv_fss_agent.h"
#define DAEMON_NAME "fssd"
void start_fssd(struct tevent_context *ev_ctx,
struct messaging_context *msg_ctx);
static void fssd_reopen_logs(void)
{
char *lfile = lp_logfile(NULL);
int rc;
if (lfile == NULL || lfile[0] == '\0') {
rc = asprintf(&lfile, "%s/log.%s", get_dyn_LOGFILEBASE(), DAEMON_NAME);
if (rc > 0) {
lp_set_logfile(lfile);
SAFE_FREE(lfile);
}
} else {
if (strstr(lfile, DAEMON_NAME) == NULL) {
rc = asprintf(&lfile, "%s.%s", lp_logfile(NULL), DAEMON_NAME);
if (rc > 0) {
lp_set_logfile(lfile);
SAFE_FREE(lfile);
}
}
}
reopen_logs();
}
static void fssd_smb_conf_updated(struct messaging_context *msg,
void *private_data,
uint32_t msg_type,
struct server_id server_id,
DATA_BLOB *data)
{
DEBUG(10, ("Got message saying smb.conf was updated. Reloading.\n"));
change_to_root_user();
fssd_reopen_logs();
}
static void fssd_sig_term_handler(struct tevent_context *ev,
struct tevent_signal *se,
int signum,
int count,
void *siginfo,
void *private_data)
{
rpc_FileServerVssAgent_shutdown();
exit_server_cleanly("termination signal");
}
static void fssd_setup_sig_term_handler(struct tevent_context *ev_ctx)
{
struct tevent_signal *se;
se = tevent_add_signal(ev_ctx,
ev_ctx,
SIGTERM, 0,
fssd_sig_term_handler,
NULL);
if (se == NULL) {
exit_server("failed to setup SIGTERM handler");
}
}
static void fssd_sig_hup_handler(struct tevent_context *ev,
struct tevent_signal *se,
int signum,
int count,
void *siginfo,
void *private_data)
{
change_to_root_user();
DEBUG(1,("reopening logs after SIGHUP\n"));
fssd_reopen_logs();
}
static void fssd_setup_sig_hup_handler(struct tevent_context *ev_ctx,
struct messaging_context *msg_ctx)
{
struct tevent_signal *se;
se = tevent_add_signal(ev_ctx,
ev_ctx,
SIGHUP, 0,
fssd_sig_hup_handler,
msg_ctx);
if (se == NULL) {
exit_server("failed to setup SIGHUP handler");
}
}
static bool fss_shutdown_cb(void *ptr)
{
srv_fssa_cleanup();
return true;
}
static bool fss_init_cb(void *ptr)
{
NTSTATUS status;
status = srv_fssa_start();
return NT_STATUS_IS_OK(status);
}
void start_fssd(struct tevent_context *ev_ctx,
struct messaging_context *msg_ctx)
{
struct rpc_srv_callbacks fss_cb;
NTSTATUS status;
pid_t pid;
bool ok;
int rc;
fss_cb.init = fss_init_cb;
fss_cb.shutdown = fss_shutdown_cb;
fss_cb.private_data = NULL;
DEBUG(1, ("Forking File Server Shadow-copy Daemon\n"));
pid = fork();
if (pid == -1) {
DEBUG(0, ("failed to fork file server shadow-copy daemon [%s], "
"aborting ...\n", strerror(errno)));
exit(1);
}
if (pid) {
/* parent */
return;
}
/* child */
status = reinit_after_fork(msg_ctx,
ev_ctx,
true);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("reinit_after_fork() failed\n"));
smb_panic("reinit_after_fork() failed");
}
fssd_reopen_logs();
fssd_setup_sig_term_handler(ev_ctx);
fssd_setup_sig_hup_handler(ev_ctx, msg_ctx);
ok = serverid_register(procid_self(),
FLAG_MSG_GENERAL |
FLAG_MSG_PRINT_GENERAL);
if (!ok) {
DEBUG(0, ("Failed to register serverid in fssd!\n"));
exit(1);
}
messaging_register(msg_ctx,
ev_ctx,
MSG_SMB_CONF_UPDATED,
fssd_smb_conf_updated);
status = rpc_FileServerVssAgent_init(&fss_cb);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0, ("Failed to register fssd rpc inteface! (%s)\n",
nt_errstr(status)));
exit(1);
}
/* case is normalized by smbd on connection */
ok = setup_named_pipe_socket("fssagentrpc", ev_ctx, msg_ctx);
if (!ok) {
DEBUG(0, ("Failed to open fssd named pipe!\n"));
exit(1);
}
DEBUG(1, ("File Server Shadow-copy Daemon Started (%d)\n", getpid()));
/* loop forever */
rc = tevent_loop_wait(ev_ctx);
/* should not be reached */
DEBUG(0,("tevent_loop_wait() exited with %d - %s\n",
rc, (rc == 0) ? "out of events" : strerror(errno)));
exit(1);
}

View File

@ -1,6 +1,6 @@
/*
Unix SMB/Netbios implementation.
Generic infrstructure for RPC Daemons
Generic infrastructure for RPC Daemons
Copyright (C) Simo Sorce 2011
Copyright (C) Andreas Schneider 2011
@ -35,6 +35,7 @@ struct rpc_service_defaults {
/* { "lsarpc", "embedded" }, */
/* { "samr", "embedded" }, */
/* { "netlogon", "embedded" }, */
{ "fssagentrpc", "external" },
{ NULL, NULL }
};
@ -96,6 +97,7 @@ struct rpc_daemon_defaults {
{ "epmd", "disabled" },
/* { "spoolssd", "embedded" }, */
/* { "lsasd", "embedded" }, */
{ "fssd", "disabled" },
{ NULL, NULL }
};

View File

@ -33,7 +33,6 @@ enum rpc_service_mode_e {
* @brief Get the mode in which service pipes are configured.
*
* @param name Name of the service
* @param def_mode The default mode for the service
*
* @return The actual configured mode.
*/
@ -44,6 +43,7 @@ enum rpc_service_mode_e rpc_service_mode(const char *name);
#define rpc_lsarpc_mode() rpc_service_mode("lsarpc")
#define rpc_samr_mode() rpc_service_mode("samr")
#define rpc_netlogon_mode() rpc_service_mode("netlogon")
#define rpc_fssagentrpc_mode() rpc_service_mode("fssagentrpc")
@ -57,7 +57,6 @@ enum rpc_daemon_type_e {
* @brief Get the mode in which a server is started.
*
* @param name Name of the rpc server
* @param def_type The default type for the server
*
* @return The actual configured type.
*/
@ -66,5 +65,6 @@ enum rpc_daemon_type_e rpc_daemon_type(const char *name);
#define rpc_epmapper_daemon() rpc_daemon_type("epmd")
#define rpc_spoolss_daemon() rpc_daemon_type("spoolssd")
#define rpc_lsasd_daemon() rpc_daemon_type("lsasd")
#define rpc_fss_daemon() rpc_daemon_type("fssd")
#endif /* _RPC_CONFIG_H */

View File

@ -54,6 +54,11 @@ bld.SAMBA3_SUBSYSTEM('RPC_FSS_STATE',
source='''fss/srv_fss_state.c''',
deps='samba-util NDR_FSRVP_STATE')
bld.SAMBA3_SUBSYSTEM('RPC_FSS_AGENT',
source='''fss/srv_fss_agent.c
../../librpc/gen_ndr/srv_fsrvp.c''',
deps='samba-util RPC_FSS_STATE')
bld.SAMBA3_SUBSYSTEM('RPC_EVENTLOG',
source='''eventlog/srv_eventlog_nt.c
eventlog/srv_eventlog_reg.c
@ -149,6 +154,7 @@ bld.SAMBA3_SUBSYSTEM('RPC_SERVICE',
RPC_RPCECHO
RPC_SERVER
RPC_EPMAPPER
RPC_FSS_AGENT
''')
# RPC_DAEMONS
@ -163,3 +169,7 @@ bld.SAMBA3_SUBSYSTEM('EPMD',
bld.SAMBA3_SUBSYSTEM('LSASD',
source='lsasd.c',
deps='RPC_SOCK_HELPER samba-util')
bld.SAMBA3_SUBSYSTEM('FSSD',
source='fssd.c',
deps='samba-util')

View File

@ -86,6 +86,9 @@ extern void start_epmd(struct tevent_context *ev_ctx,
extern void start_lsasd(struct tevent_context *ev_ctx,
struct messaging_context *msg_ctx);
extern void start_fssd(struct tevent_context *ev_ctx,
struct messaging_context *msg_ctx);
#ifdef WITH_DFS
extern int dcelogin_atmost_once;
#endif /* WITH_DFS */
@ -1551,6 +1554,10 @@ extern void build_options(bool screen);
start_lsasd(ev_ctx, msg_ctx);
}
if (rpc_fss_daemon() == RPC_DAEMON_FORK) {
start_fssd(ev_ctx, msg_ctx);
}
if (!lp__disable_spoolss() &&
(rpc_spoolss_daemon() != RPC_DAEMON_DISABLED)) {
bool bgq = lp_parm_bool(-1, "smbd", "backgroundqueue", true);

View File

@ -855,7 +855,7 @@ bld.SAMBA3_SUBSYSTEM('LIBLSA',
bld.SAMBA3_BINARY('smbd/smbd',
source='smbd/server.c',
deps='smbd_base EPMD LSASD',
deps='smbd_base EPMD LSASD FSSD',
install_path='${SBINDIR}')
bld.SAMBA3_BINARY('nmbd/nmbd',