Allow some pre-/post-xfer exec shell restrictions.
authorWayne Davison <wayned@samba.org>
Sun, 25 Mar 2018 18:02:50 +0000 (11:02 -0700)
committerWayne Davison <wayned@samba.org>
Sun, 25 Mar 2018 18:02:50 +0000 (11:02 -0700)
Support both RSYNC_SHELL & RSYNC_NO_XFER_EXEC environment variables.

NEWS
clientserver.c
main.c
rsync.yo
rsyncd.conf.yo
socket.c

diff --git a/NEWS b/NEWS
index fd3c314d9a6bc5f425eaf030aa583448fb598c69..4fe6d9cb5b47f34fbdef761c4ef0e921062f79c2 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -8,4 +8,5 @@ Changes since 3.1.3:
 
   ENHANCEMENTS:
 
-    - ...
+    - Added support for RSYNC_SHELL & RSYNC_NO_XFER_EXEC environment variables
+      that affect the pre-xfer exec and post-xfer exec rsync daemon options.
index e2e2dc025d86a304e15a2a8d08cb974c5ee6ffe9..93c4457ffacf891a786a8da0fff5af02be7e8712 100644 (file)
@@ -688,7 +688,7 @@ static int rsync_module(int f_in, int f_out, int i, const char *addr, const char
        log_init(1);
 
 #ifdef HAVE_PUTENV
-       if (*lp_prexfer_exec(i) || *lp_postxfer_exec(i)) {
+       if ((*lp_prexfer_exec(i) || *lp_postxfer_exec(i)) && !getenv("RSYNC_NO_XFER_EXEC")) {
                int status;
 
                /* For post-xfer exec, fork a new process to run the rsync
@@ -714,7 +714,7 @@ static int rsync_module(int f_in, int f_out, int i, const char *addr, const char
                                else
                                        status = -1;
                                set_env_num("RSYNC_EXIT_STATUS", status);
-                               if (system(lp_postxfer_exec(i)) < 0)
+                               if (shell_exec(lp_postxfer_exec(i)) < 0)
                                        status = -1;
                                _exit(status);
                        }
@@ -758,7 +758,7 @@ static int rsync_module(int f_in, int f_out, int i, const char *addr, const char
                                close(STDIN_FILENO);
                                dup2(pre_exec_error_fd, STDOUT_FILENO);
                                close(pre_exec_error_fd);
-                               status = system(lp_prexfer_exec(i));
+                               status = shell_exec(lp_prexfer_exec(i));
                                if (!WIFEXITED(status))
                                        _exit(1);
                                _exit(WEXITSTATUS(status));
diff --git a/main.c b/main.c
index ee9630fc51d64e03fd196023890b412af0d92fa3..99dae1c1998562b1a371cb21464016a5482c9880 100644 (file)
--- a/main.c
+++ b/main.c
@@ -154,6 +154,27 @@ pid_t wait_process(pid_t pid, int *status_ptr, int flags)
        return waited_pid;
 }
 
+int shell_exec(const char *cmd)
+{
+       char *shell = getenv("RSYNC_SHELL");
+       int status;
+       pid_t pid;
+
+       if (!shell)
+               return system(cmd);
+
+       if ((pid = fork()) < 0)
+               return -1;
+
+       if (pid == 0) {
+               execlp(shell, shell, "-c", cmd, NULL);
+               _exit(1);
+       }
+
+       int ret = wait_process(pid, &status, 0);
+       return ret < 0 ? -1 : status;
+}
+
 /* Wait for a process to exit, calling io_flush while waiting. */
 static void wait_process_with_flush(pid_t pid, int *exit_code_ptr)
 {
@@ -1497,9 +1518,7 @@ const char *get_panic_action(void)
 
        if (cmd_fmt)
                return cmd_fmt;
-       else
-               return "xterm -display :0 -T Panic -n Panic "
-                       "-e gdb /proc/%d/exe %d";
+       return "xterm -display :0 -T Panic -n Panic -e gdb /proc/%d/exe %d";
 }
 
 
@@ -1520,7 +1539,7 @@ static void rsync_panic_handler(UNUSED(int whatsig))
 
        /* Unless we failed to execute gdb, we allow the process to
         * continue.  I'm not sure if that's right. */
-       ret = system(cmd_buf);
+       ret = shell_exec(cmd_buf);
        if (ret)
                _exit(ret);
 }
index 48d5da1d287534c8569272b6b8663329217000f8..71008576c4b437b183b6cd46ba481e3e855dce6a 100644 (file)
--- a/rsync.yo
+++ b/rsync.yo
@@ -236,6 +236,10 @@ The command specified above uses ssh to run nc (netcat) on a proxyhost,
 which forwards all data to port 873 (the rsync daemon) on the targethost
 (%H).
 
+Note also that if the RSYNC_SHELL environment varibable is set, that
+program will be used to run the RSYNC_CONNECT_PROG command instead of
+using the default shell of the system() call.
+
 manpagesection(USING RSYNC-DAEMON FEATURES VIA A REMOTE-SHELL CONNECTION)
 
 It is sometimes useful to use various features of an rsync daemon (such as
index 7326b42d031470dc0e370d547e2a939837e292a5..3076a492fe941d99fa416586386becdd33627c5d 100644 (file)
@@ -812,6 +812,10 @@ Even though the commands can be associated with a particular module, they
 are run using the permissions of the user that started the daemon (not the
 module's uid/gid setting) without any chroot restrictions.
 
+These settings honor 2 environment variables: use RSYNC_SHELL to set a shell to
+use when running the command (which otherwise uses your system() call's default
+shell), and use RSYNC_NO_XFER_EXEC to disable both options completely.
+
 )
 
 manpagesection(CONFIG DIRECTIVES)
index 16c3c5f4dcda92fbe8ada0be320fbe5d9ea9d17d..4cc88fde52dd7928b1499a57404fc1be06fac500 100644 (file)
--- a/socket.c
+++ b/socket.c
@@ -847,7 +847,7 @@ static int sock_exec(const char *prog)
                        fprintf(stderr, "Failed to run \"%s\"\n", prog);
                        exit(1);
                }
-               exit(system(prog));
+               exit(shell_exec(prog));
        }
 
        close(fd[1]);