Commit 8638dd48 authored by David Dykstra's avatar David Dykstra

Add "use chroot" and "pid file" rsyncd.conf options. The former allows one

to disable the use of chroot so rsync --daemon can be run as a non-root
user (if a non-privileged --port is used).  The latter allows one to
specify a file in which to write the process id of the daemon, which is
useful when rsync --daemon is not run from inetd.
parent 2bca43f6
......@@ -29,6 +29,7 @@ static char *cleanup_new_fname;
static struct file_struct *cleanup_file;
static int cleanup_fd1, cleanup_fd2;
static struct map_struct *cleanup_buf;
static int cleanup_pid = 0;
void exit_cleanup(int code)
{
......@@ -50,6 +51,8 @@ void exit_cleanup(int code)
if (code) {
kill_all(SIGUSR1);
}
if ((cleanup_pid != 0) && (cleanup_pid == (int) getpid()))
unlink(lp_pid_file());
exit(code);
}
......@@ -70,3 +73,8 @@ void cleanup_set(char *fnametmp, char *fname, struct file_struct *file,
cleanup_fd1 = fd1;
cleanup_fd2 = fd2;
}
void cleanup_set_pid(int pid)
{
cleanup_pid = pid;
}
......@@ -122,6 +122,7 @@ static int rsync_module(int fd, int i)
char *host = client_name(fd);
char *name = lp_name(i);
char *user;
int use_chroot = lp_use_chroot(i);
int start_glob=0;
int ret;
char *request=NULL;
......@@ -194,28 +195,37 @@ static int rsync_module(int fd, int i)
log_open();
if (chroot(lp_path(i))) {
rprintf(FERROR,"chroot %s failed\n", lp_path(i));
io_printf(fd,"@ERROR: chroot failed\n");
return -1;
}
if (use_chroot) {
if (chroot(lp_path(i))) {
rprintf(FERROR,"chroot %s failed\n", lp_path(i));
io_printf(fd,"@ERROR: chroot failed\n");
return -1;
}
if (chdir("/")) {
rprintf(FERROR,"chdir %s failed\n", lp_path(i));
io_printf(fd,"@ERROR: chdir failed\n");
return -1;
}
if (chdir("/")) {
rprintf(FERROR,"chdir %s failed\n", lp_path(i));
io_printf(fd,"@ERROR: chdir failed\n");
return -1;
}
if (setgid(gid) || getgid() != gid) {
rprintf(FERROR,"setgid %d failed\n", gid);
io_printf(fd,"@ERROR: setgid failed\n");
return -1;
}
if (setgid(gid) || getgid() != gid) {
rprintf(FERROR,"setgid %d failed\n", gid);
io_printf(fd,"@ERROR: setgid failed\n");
return -1;
}
if (setuid(uid) || getuid() != uid) {
rprintf(FERROR,"setuid %d failed\n", uid);
io_printf(fd,"@ERROR: setuid failed\n");
return -1;
if (setuid(uid) || getuid() != uid) {
rprintf(FERROR,"setuid %d failed\n", uid);
io_printf(fd,"@ERROR: setuid failed\n");
return -1;
}
} else {
if (!push_dir(lp_path(i), 0)) {
rprintf(FERROR,"chdir %s failed\n", lp_path(i));
io_printf(fd,"@ERROR: chdir failed\n");
return -1;
}
}
am_root = (getuid() == 0);
......@@ -257,6 +267,21 @@ static int rsync_module(int fd, int i)
}
}
if (!use_chroot) {
/*
* Note that this is applied to all parameters, whether or not
* they are filenames, but no other legal parameters contain
* the forms that need to be sanitized so it doesn't hurt;
* it is not known at this point which parameters are files
* and which aren't.
*/
for (i = 1; i < argc; i++) {
char *copy = sanitize_path(argv[i]);
free((void *)argv[i]);
argv[i] = copy;
}
}
ret = parse_arguments(argc, argv);
if (request) {
......@@ -381,6 +406,7 @@ static int start_daemon(int fd)
int daemon_main(void)
{
extern char *config_file;
char *pid_file;
/* this ensures that we don't call getcwd after the chroot,
which doesn't work on platforms that use popen("pwd","r")
......@@ -414,6 +440,19 @@ int daemon_main(void)
rprintf(FINFO,"rsyncd version %s starting\n",VERSION);
if (((pid_file = lp_pid_file()) != NULL) && (*pid_file != '\0')) {
FILE *f;
int pid = (int) getpid();
cleanup_set_pid(pid);
if ((f = fopen(lp_pid_file(), "w")) == NULL) {
cleanup_set_pid(0);
fprintf(stderr,"failed to create pid file %s\n", pid_file);
exit_cleanup(1);
}
fprintf(f, "%d\n", pid);
fclose(f);
}
start_accept_loop(rsync_port, start_daemon);
return -1;
}
......
......@@ -99,6 +99,7 @@ typedef struct
char *motd_file;
char *lock_file;
char *log_file;
char *pid_file;
int syslog_facility;
int max_connections;
char *socket_options;
......@@ -118,6 +119,7 @@ typedef struct
char *comment;
BOOL read_only;
BOOL list;
BOOL use_chroot;
char *uid;
char *gid;
char *hosts_allow;
......@@ -137,6 +139,7 @@ static service sDefault =
NULL, /* comment */
True, /* read only */
True, /* list */
True, /* use chroot */
"nobody",/* uid */
"nobody",/* gid */
NULL, /* hosts allow */
......@@ -233,12 +236,14 @@ static struct parm_struct parm_table[] =
{"syslog facility", P_ENUM, P_GLOBAL, &Globals.syslog_facility, enum_facilities,0},
{"socket options", P_STRING, P_GLOBAL, &Globals.socket_options,NULL, 0},
{"log file", P_STRING, P_GLOBAL, &Globals.log_file, NULL, 0},
{"pid file", P_STRING, P_GLOBAL, &Globals.pid_file, NULL, 0},
{"name", P_STRING, P_LOCAL, &sDefault.name, NULL, 0},
{"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL, 0},
{"path", P_STRING, P_LOCAL, &sDefault.path, NULL, 0},
{"read only", P_BOOL, P_LOCAL, &sDefault.read_only, NULL, 0},
{"list", P_BOOL, P_LOCAL, &sDefault.list, NULL, 0},
{"use chroot", P_BOOL, P_LOCAL, &sDefault.use_chroot, NULL, 0},
{"uid", P_STRING, P_LOCAL, &sDefault.uid, NULL, 0},
{"gid", P_STRING, P_LOCAL, &sDefault.gid, NULL, 0},
{"hosts allow", P_STRING, P_LOCAL, &sDefault.hosts_allow, NULL, 0},
......@@ -298,6 +303,7 @@ static void init_locals(void)
FN_GLOBAL_STRING(lp_motd_file, &Globals.motd_file)
FN_GLOBAL_STRING(lp_lock_file, &Globals.lock_file)
FN_GLOBAL_STRING(lp_log_file, &Globals.log_file)
FN_GLOBAL_STRING(lp_pid_file, &Globals.pid_file)
FN_GLOBAL_STRING(lp_socket_options, &Globals.socket_options)
FN_GLOBAL_INTEGER(lp_max_connections, &Globals.max_connections)
FN_GLOBAL_INTEGER(lp_syslog_facility, &Globals.syslog_facility)
......@@ -307,6 +313,7 @@ FN_LOCAL_STRING(lp_comment, comment)
FN_LOCAL_STRING(lp_path, path)
FN_LOCAL_BOOL(lp_read_only, read_only)
FN_LOCAL_BOOL(lp_list, list)
FN_LOCAL_BOOL(lp_use_chroot, use_chroot)
FN_LOCAL_STRING(lp_uid, uid)
FN_LOCAL_STRING(lp_gid, gid)
FN_LOCAL_STRING(lp_hosts_allow, hosts_allow)
......
......@@ -584,6 +584,7 @@ int main(int argc,char *argv[])
signal(SIGINT,SIGNAL_CAST sig_int);
signal(SIGPIPE,SIGNAL_CAST sig_int);
signal(SIGHUP,SIGNAL_CAST sig_int);
signal(SIGTERM,SIGNAL_CAST sig_int);
if (am_daemon) {
return daemon_main();
......
......@@ -94,7 +94,10 @@ exceeded. The default is tt(/var/run/rsyncd.lock).
dit(bf(log file)) The "log file" option tells the rsync daemon to log
messages to that file rather than using syslog. This is particularly
useful on systems (such as AIX) where syslog() doesn't work for
chrooted programs like rsync.
chrooted programs.
dit(bf(pid file)) The "pid file" option tells the rsync daemon to write
its process id to that file.
dit(bf(syslog facility)) The "syslog facility" option allows you to
specify the syslog facility name to use when logging messages from the
......@@ -128,9 +131,15 @@ that is displayed next to the module name when clients obtain a list
of available modules. The default is no comment.
dit(bf(path)) The "path" option specifies the directory in the servers
filesystem to make available in this module. The rsync server will
chroot to this path before starting the file transfer with the
client. You must specify this option for each module in tt(/etc/rsyncd.conf).
filesystem to make available in this module. You must specify this option
for each module in tt(/etc/rsyncd.conf).
dit(bf(use chroot)) If "use chroot" is true, the rsync server will chroot
to the "path" before starting the file transfer with the client. This has
the advantage of extra protection against possible implementation security
holes, but it has the disadvantages of requiring super-user privileges and
of not being able to follow symbolic links outside of the new root path.
The default is to use chroot.
dit(bf(read only)) The "read only" option determines whether clients
will be able to upload files or not. If "read only" is true then any
......@@ -272,8 +281,10 @@ A more sophisticated example would be:
uid = nobody nl()
gid = nobody nl()
use chroot = no nl()
max connections = 4 nl()
syslog facility = local5 nl()
pid file = /etc/rsyncd.pid
verb([ftp]
path = /var/ftp/pub
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment