X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/cbbd8e2e8bf72aa46c84c7de43e19da40f040fa7..99c3e591b201c28b8fe22c881332f8a4888e69b8:/clientserver.c diff --git a/clientserver.c b/clientserver.c index 6bcbc81e..47b29808 100644 --- a/clientserver.c +++ b/clientserver.c @@ -22,6 +22,7 @@ #include "rsync.h" #include "ifuncs.h" +extern int quiet; extern int verbose; extern int dry_run; extern int output_motd; @@ -31,6 +32,7 @@ extern int am_server; extern int am_daemon; extern int am_root; extern int rsync_port; +extern int protect_args; extern int ignore_errors; extern int preserve_xattrs; extern int kluge_around_eof; @@ -212,7 +214,7 @@ int start_inband_exchange(int f_in, int f_out, const char *user, int argc, char int sargc = 0; char *p, *modname; - assert(argc > 0); + assert(argc > 0 && *argv != NULL); if (**argv == '/') { rprintf(FERROR, @@ -314,6 +316,8 @@ int start_inband_exchange(int f_in, int f_out, const char *user, int argc, char if (rl_nulls) { for (i = 0; i < sargc; i++) { + if (!sargs[i]) /* stop at --protect-args NULL */ + break; write_sbuf(f_out, sargs[i]); write_byte(f_out, 0); } @@ -324,6 +328,9 @@ int start_inband_exchange(int f_in, int f_out, const char *user, int argc, char write_sbuf(f_out, "\n"); } + if (protect_args) + send_protected_args(f_out, sargs); + if (protocol_version < 23) { if (protocol_version == 22 || !am_sender) io_start_multiplex_in(); @@ -335,16 +342,24 @@ int start_inband_exchange(int f_in, int f_out, const char *user, int argc, char } static char *finish_pre_exec(pid_t pid, int fd, char *request, - int argc, char *argv[]) + char **early_argv, char **argv) { - int j, status = -1; + int j = 0, status = -1; if (!request) request = "(NONE)"; write_buf(fd, request, strlen(request)+1); - for (j = 0; j < argc; j++) + if (early_argv) { + for ( ; *early_argv; early_argv++) + write_buf(fd, *early_argv, strlen(*early_argv)+1); + j = 1; /* Skip arg0 name in argv. */ + } + for ( ; argv[j]; j++) { write_buf(fd, argv[j], strlen(argv[j])+1); + if (argv[j][0] == '.' && argv[j][1] == '\0') + break; + } write_byte(fd, 0); close(fd); @@ -384,8 +399,8 @@ static int read_arg_from_pipe(int fd, char *buf, int limit) static int rsync_module(int f_in, int f_out, int i, char *addr, char *host) { - int argc, opt_cnt; - char **argv, *chroot_path = NULL; + int argc; + char **argv, **orig_argv, **orig_early_argv, *chroot_path = NULL; char line[BIGPATHBUFLEN]; uid_t uid = (uid_t)-2; /* canonically "nobody" */ gid_t gid = (gid_t)-2; @@ -490,7 +505,7 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host) if ((p = strstr(module_dir, "/./")) != NULL) { *p = '\0'; p += 2; - } else if ((p = strdup("/")) == NULL) + } else if ((p = strdup("/")) == NULL) /* MEMORY LEAK */ out_of_memory("rsync_module"); } @@ -676,7 +691,7 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host) munge_symlinks = !use_chroot || module_dirlen; if (munge_symlinks) { STRUCT_STAT st; - if (stat(SYMLINK_PREFIX, &st) == 0 && S_ISDIR(st.st_mode)) { + if (do_stat(SYMLINK_PREFIX, &st) == 0 && S_ISDIR(st.st_mode)) { rprintf(FLOG, "Symlink munging is unsupported when a %s directory exists.\n", SYMLINK_PREFIX); io_printf(f_out, "@ERROR: daemon security issue -- contact admin\n", name); @@ -731,16 +746,30 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host) io_printf(f_out, "@RSYNCD: OK\n"); - opt_cnt = read_args(f_in, name, line, sizeof line, rl_nulls, &argv, &argc, &request); + read_args(f_in, name, line, sizeof line, rl_nulls, &argv, &argc, &request); + orig_argv = argv; + + verbose = 0; /* future verbosity is controlled by client options */ + ret = parse_arguments(&argc, (const char ***) &argv); + if (protect_args && ret) { + orig_early_argv = orig_argv; + protect_args = 2; + read_args(f_in, name, line, sizeof line, 1, &argv, &argc, &request); + orig_argv = argv; + ret = parse_arguments(&argc, (const char ***) &argv); + } else + orig_early_argv = NULL; if (pre_exec_pid) { err_msg = finish_pre_exec(pre_exec_pid, pre_exec_fd, request, - opt_cnt, argv); + orig_early_argv, orig_argv); } - verbose = 0; /* future verbosity is controlled by client options */ - ret = parse_arguments(&argc, (const char ***) &argv, 0); + if (orig_early_argv) + free(orig_early_argv); + am_server = 1; /* Don't let someone try to be tricky. */ + quiet = 0; if (lp_ignore_errors(module_id)) ignore_errors = 1; if (write_batch < 0)