From 53936ef935e97d2036ad09b61b7040979d175469 Mon Sep 17 00:00:00 2001 From: Wayne Davison Date: Sat, 15 Mar 2008 11:25:01 -0700 Subject: [PATCH] Fixed the use of --protect-args (-s) with a daemon. --- clientserver.c | 47 +++++++++++++++++++++++++++++++++--------- io.c | 11 +++++----- main.c | 55 +++++++++----------------------------------------- options.c | 16 ++++++--------- rsync.c | 35 ++++++++++++++++++++++++++++++++ 5 files changed, 93 insertions(+), 71 deletions(-) diff --git a/clientserver.c b/clientserver.c index 6bcbc81e..6da1138f 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; @@ -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; @@ -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) diff --git a/io.c b/io.c index ce675d20..018dd282 100644 --- a/io.c +++ b/io.c @@ -874,8 +874,8 @@ int read_line(int fd, char *buf, size_t bufsiz, int flags) return s - buf; } -int read_args(int f_in, char *mod_name, char *buf, size_t bufsiz, int rl_nulls, - char ***argv_p, int *argc_p, char **request_p) +void read_args(int f_in, char *mod_name, char *buf, size_t bufsiz, int rl_nulls, + char ***argv_p, int *argc_p, char **request_p) { int maxargs = MAX_ARGS; int dot_pos = 0; @@ -889,14 +889,14 @@ int read_args(int f_in, char *mod_name, char *buf, size_t bufsiz, int rl_nulls, if (!(argv = new_array(char *, maxargs))) out_of_memory("read_args"); - if (mod_name) + if (mod_name && !protect_args) argv[argc++] = "rsyncd"; while (1) { if (read_line(f_in, buf, bufsiz, rl_flags) == 0) break; - if (argc == maxargs) { + if (argc == maxargs-1) { maxargs += MAX_ARGS; if (!(argv = realloc_array(argv, char *, maxargs))) out_of_memory("read_args"); @@ -919,11 +919,10 @@ int read_args(int f_in, char *mod_name, char *buf, size_t bufsiz, int rl_nulls, dot_pos = argc; } } + argv[argc] = NULL; *argc_p = argc; *argv_p = argv; - - return dot_pos ? dot_pos : argc; } int io_start_buffering_out(int f_out) diff --git a/main.c b/main.c index b06eeebe..8de7f1bd 100644 --- a/main.c +++ b/main.c @@ -79,9 +79,6 @@ extern char *password_file; extern char curr_dir[MAXPATHLEN]; extern struct file_list *first_flist; extern struct filter_list_struct server_filter_list; -#ifdef ICONV_OPTION -extern iconv_t ic_send; -#endif uid_t our_uid; int local_server = 0; @@ -334,7 +331,7 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char **remote_argv, in { int i, argc = 0; char *args[MAX_ARGS]; - pid_t ret; + pid_t pid; int dash_l_set = 0; if (!read_batch && !local_server) { @@ -453,7 +450,7 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char **remote_argv, in batch_gen_fd = from_gen_pipe[0]; *f_out_p = from_gen_pipe[1]; *f_in_p = batch_fd; - ret = -1; /* no child pid */ + pid = (pid_t)-1; /* no child pid */ #ifdef ICONV_CONST setup_iconv(); #endif @@ -463,54 +460,20 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char **remote_argv, in if (whole_file < 0 && !write_batch) whole_file = 1; set_allow_inc_recurse(); - ret = local_child(argc, args, f_in_p, f_out_p, child_main); + pid = local_child(argc, args, f_in_p, f_out_p, child_main); #ifdef ICONV_CONST setup_iconv(); #endif } else { + pid = piped_child(args, f_in_p, f_out_p); #ifdef ICONV_CONST setup_iconv(); #endif - if (protect_args) { - int fd; -#ifdef ICONV_OPTION - int convert = ic_send != (iconv_t)-1; - xbuf outbuf, inbuf; - - if (convert) - alloc_xbuf(&outbuf, 1024); -#endif - - ret = piped_child(args, f_in_p, f_out_p); - - for (i = 0; args[i]; i++) {} /* find first NULL */ - args[i] = "rsync"; /* set a new arg0 */ - if (verbose > 1) - print_child_argv("protected args:", args + i + 1); - fd = *f_out_p; - do { -#ifdef ICONV_OPTION - if (convert) { - INIT_XBUF_STRLEN(inbuf, args[i]); - iconvbufs(ic_send, &inbuf, &outbuf, - ICB_EXPAND_OUT | ICB_INCLUDE_BAD | ICB_INCLUDE_INCOMPLETE); - outbuf.buf[outbuf.len] = '\0'; - write_buf(fd, outbuf.buf, outbuf.len + 1); - outbuf.len = 0; - } else -#endif - write_buf(fd, args[i], strlen(args[i]) + 1); - } while (args[++i]); - write_byte(fd, 0); -#ifdef ICONV_OPTION - if (convert) - free(outbuf.buf); -#endif - } else - ret = piped_child(args, f_in_p, f_out_p); + if (protect_args) + send_protected_args(*f_out_p, args); } - return ret; + return pid; oom: out_of_memory("do_cmd"); @@ -1447,7 +1410,7 @@ int main(int argc,char *argv[]) setlocale(LC_CTYPE, ""); #endif - if (!parse_arguments(&argc, (const char ***) &argv, 1)) { + if (!parse_arguments(&argc, (const char ***) &argv)) { /* FIXME: We ought to call the same error-handling * code here, rather than relying on getopt. */ option_error(); @@ -1512,7 +1475,7 @@ int main(int argc,char *argv[]) char buf[MAXPATHLEN]; protect_args = 2; read_args(STDIN_FILENO, NULL, buf, sizeof buf, 1, &argv, &argc, NULL); - if (!parse_arguments(&argc, (const char ***) &argv, 1)) { + if (!parse_arguments(&argc, (const char ***) &argv)) { option_error(); exit_cleanup(RERR_SYNTAX); } diff --git a/options.c b/options.c index 82597bf1..d1e1ff67 100644 --- a/options.c +++ b/options.c @@ -25,6 +25,7 @@ #include "zlib/zlib.h" extern int module_id; +extern int local_server; extern int sanitize_paths; extern int daemon_over_rsh; extern unsigned int module_dirlen; @@ -889,7 +890,7 @@ static void create_refuse_error(int which) * * @retval 0 on error, with err_buf containing an explanation **/ -int parse_arguments(int *argc_p, const char ***argv_p, int frommain) +int parse_arguments(int *argc_p, const char ***argv_p) { static poptContext pc; char *ref = lp_refuse_options(module_id); @@ -1092,8 +1093,7 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain) break; case 'q': - if (frommain) - quiet++; + quiet++; break; case 'x': @@ -1290,12 +1290,8 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain) } #endif - if (protect_args == 1) { - if (!frommain) - protect_args = 0; - else if (am_server) - return 1; - } + if (protect_args == 1 && am_server) + return 1; #ifndef SUPPORT_LINKS if (preserve_links && !am_sender) { @@ -1833,7 +1829,7 @@ void server_options(char **args, int *argc_p) } #endif - if (protect_args) /* initial args break here */ + if (protect_args && !local_server) /* unprotected args stop here */ args[ac++] = NULL; if (list_only > 1) diff --git a/rsync.c b/rsync.c index 302971fc..c384ed9b 100644 --- a/rsync.c +++ b/rsync.c @@ -205,6 +205,41 @@ int iconvbufs(iconv_t ic, xbuf *in, xbuf *out, int flags) } #endif +void send_protected_args(int fd, char *args[]) +{ +#ifdef ICONV_OPTION + int i, convert = ic_send != (iconv_t)-1; + xbuf outbuf, inbuf; + + if (convert) + alloc_xbuf(&outbuf, 1024); +#endif + + for (i = 0; args[i]; i++) {} /* find first NULL */ + args[i] = "rsync"; /* set a new arg0 */ + if (verbose > 1) + print_child_argv("protected args:", args + i + 1); + do { +#ifdef ICONV_OPTION + if (convert) { + INIT_XBUF_STRLEN(inbuf, args[i]); + iconvbufs(ic_send, &inbuf, &outbuf, + ICB_EXPAND_OUT | ICB_INCLUDE_BAD | ICB_INCLUDE_INCOMPLETE); + outbuf.buf[outbuf.len] = '\0'; + write_buf(fd, outbuf.buf, outbuf.len + 1); + outbuf.len = 0; + } else +#endif + write_buf(fd, args[i], strlen(args[i]) + 1); + } while (args[++i]); + write_byte(fd, 0); + +#ifdef ICONV_OPTION + if (convert) + free(outbuf.buf); +#endif +} + int read_ndx_and_attrs(int f_in, int *iflag_ptr, uchar *type_ptr, char *buf, int *len_ptr) { -- 2.34.1