]> git.ipfire.org Git - thirdparty/rsync.git/commitdiff
Add "use chroot" and "pid file" rsyncd.conf options. The former allows one
authorDavid Dykstra <dwd@samba.org>
Mon, 26 Oct 1998 21:51:47 +0000 (21:51 +0000)
committerDavid Dykstra <dwd@samba.org>
Mon, 26 Oct 1998 21:51:47 +0000 (21:51 +0000)
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.

cleanup.c
clientserver.c
loadparm.c
main.c
rsyncd.conf.yo

index 57fce18f272f5a87da8a1b11df1e0da096e690c2..abd7b0dfb4ad57698a12d7c8138f4d80f81886ba 100644 (file)
--- a/cleanup.c
+++ b/cleanup.c
@@ -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;
+}
index cf10b12fb7a7ccd96ea6b07650ae8245df891472..debc4fec310bd3ffcb07b9c120157df65ba13eeb 100644 (file)
@@ -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;
 }
index 24ef7c67c31da5553ab9605f03fe93ddf89addc0..aba7d30ec08195723a8aca414b96781f91cd5940 100644 (file)
@@ -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)
diff --git a/main.c b/main.c
index c87dd7be64aac6772bc25d335d5bca379b43aa69..94e358fb589b78d594820c8c82f086333ad59f69 100644 (file)
--- a/main.c
+++ b/main.c
@@ -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();
index 9e9de5e7e9f3d50ffe7ddae189668a11cfc0daec..3725fd5f87e0393a329b7a3ca61edf453dbe9974 100644 (file)
@@ -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