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)
{
if (code) {
kill_all(SIGUSR1);
}
+ if ((cleanup_pid != 0) && (cleanup_pid == (int) getpid()))
+ unlink(lp_pid_file());
exit(code);
}
cleanup_fd1 = fd1;
cleanup_fd2 = fd2;
}
+
+void cleanup_set_pid(int pid)
+{
+ cleanup_pid = pid;
+}
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;
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);
}
}
+ 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) {
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")
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;
}
char *motd_file;
char *lock_file;
char *log_file;
+ char *pid_file;
int syslog_facility;
int max_connections;
char *socket_options;
char *comment;
BOOL read_only;
BOOL list;
+ BOOL use_chroot;
char *uid;
char *gid;
char *hosts_allow;
NULL, /* comment */
True, /* read only */
True, /* list */
+ True, /* use chroot */
"nobody",/* uid */
"nobody",/* gid */
NULL, /* hosts allow */
{"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},
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)
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)
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();
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
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
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