The branch, master has been updated via e16b2275 Add `--early-input=FILE` option. from 7587e20c Output a helpful msg about configure only if the command fails.
https://git.samba.org/?p=rsync.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit e16b22751a7996ddba299ea0750b533ce492d12f Author: Wayne Davison <wa...@opencoder.net> Date: Sun Jun 21 14:32:00 2020 -0700 Add `--early-input=FILE` option. ----------------------------------------------------------------------- Summary of changes: NEWS.md | 3 ++ clientserver.c | 126 +++++++++++++++++++++++++++++++++++++++++---------------- options.c | 2 + rsync.1.md | 10 +++++ 4 files changed, 106 insertions(+), 35 deletions(-) Changeset truncated at 500 lines: diff --git a/NEWS.md b/NEWS.md index 8b3e2ed0..4ff2a446 100644 --- a/NEWS.md +++ b/NEWS.md @@ -23,6 +23,9 @@ Protocol: 31 (unchanged) ### ENHANCEMENTS: + - Added `--early-input=FILE` option that allows the client to send some + data to the "early exec" daemon script on its stdin. + - Added "atimes" to the capabilities list that `--version` outputs. - Mention either "default protect-args" or "optional protect-args" in the diff --git a/clientserver.c b/clientserver.c index 819e9f24..4d7ba1f0 100644 --- a/clientserver.c +++ b/clientserver.c @@ -54,6 +54,7 @@ extern char *config_file; extern char *logfile_format; extern char *files_from; extern char *tmpdir; +extern char *early_input_file; extern struct chmod_mode_struct *chmod_modes; extern filter_rule_list daemon_filter_list; #ifdef ICONV_OPTION @@ -67,8 +68,13 @@ char *auth_user; int read_only = 0; int module_id = -1; int pid_file_fd = -1; +int early_input_len = 0; +char *early_input = NULL; struct chmod_mode_struct *daemon_chmod_modes; +#define EARLY_INPUT_CMD "#early_input=" +#define EARLY_INPUT_CMDLEN (sizeof EARLY_INPUT_CMD - 1) + /* module_dirlen is the length of the module_dir string when in daemon * mode and module_dir is not "/"; otherwise 0. (Note that a chroot- * enabled module can have a non-"/" module_dir these days.) */ @@ -144,14 +150,12 @@ static int exchange_protocols(int f_in, int f_out, char *buf, size_t bufsiz, int #else int our_sub = 0; #endif - char *motd; io_printf(f_out, "@RSYNCD: %d.%d\n", protocol_version, our_sub); - if (!am_client) { - motd = lp_motd_file(); + char *motd = lp_motd_file(); if (motd && *motd) { - FILE *f = fopen(motd,"r"); + FILE *f = fopen(motd, "r"); while (f && !feof(f)) { int len = fread(buf, 1, bufsiz - 1, f); if (len > 0) @@ -245,6 +249,36 @@ int start_inband_exchange(int f_in, int f_out, const char *user, int argc, char if (exchange_protocols(f_in, f_out, line, sizeof line, 1) < 0) return -1; + if (early_input_file) { + STRUCT_STAT st; + FILE *f = fopen(early_input_file, "rb"); + if (!f || do_fstat(fileno(f), &st) < 0) { + rsyserr(FERROR, errno, "failed to open %s", early_input_file); + return -1; + } + early_input_len = st.st_size; + if (early_input_len >= (int)sizeof line) { + rprintf(FERROR, "%s is >= %d bytes.\n", early_input_file, (int)sizeof line); + return -1; + } + if (early_input_len > 0) { + io_printf(f_out, EARLY_INPUT_CMD "%d\n", early_input_len); + while (early_input_len > 0) { + int len; + if (feof(f)) { + rprintf(FERROR, "Early EOF in %s\n", early_input_file); + return -1; + } + len = fread(line, 1, early_input_len / 2 + 1, f); + if (len > 0) { + write_buf(f_out, line, len); + early_input_len -= len; + } + } + } + fclose(f); + } + /* set daemon_over_rsh to false since we need to build the * true set of args passed through the rsh/ssh connection; * this is a no-op for direct-socket-connection mode */ @@ -397,7 +431,7 @@ static pid_t start_pre_exec(const char *cmd, int *arg_fd_ptr, int *error_fd_ptr) int arg_fds[2], error_fds[2], arg_fd; pid_t pid; - if ((error_fd_ptr && pipe(error_fds) < 0) || (arg_fd_ptr && pipe(arg_fds) < 0) || (pid = fork()) < 0) + if ((error_fd_ptr && pipe(error_fds) < 0) || pipe(arg_fds) < 0 || (pid = fork()) < 0) return (pid_t)-1; if (pid == 0) { @@ -409,37 +443,35 @@ static pid_t start_pre_exec(const char *cmd, int *arg_fd_ptr, int *error_fd_ptr) set_blocking(error_fds[1]); } - if (arg_fd_ptr) { - close(arg_fds[1]); - arg_fd = arg_fds[0]; - set_blocking(arg_fd); + close(arg_fds[1]); + arg_fd = arg_fds[0]; + set_blocking(arg_fd); + + len = read_arg_from_pipe(arg_fd, buf, BIGPATHBUFLEN); + if (len <= 0) + _exit(1); + set_env_str("RSYNC_REQUEST", buf); + for (j = 0; ; j++) { + char *p; len = read_arg_from_pipe(arg_fd, buf, BIGPATHBUFLEN); - if (len <= 0) + if (len <= 0) { + if (!len) + break; _exit(1); - set_env_str("RSYNC_REQUEST", buf); - - for (j = 0; ; j++) { - char *p; - len = read_arg_from_pipe(arg_fd, buf, BIGPATHBUFLEN); - if (len <= 0) { - if (!len) - break; - _exit(1); - } - if (asprintf(&p, "RSYNC_ARG%d=%s", j, buf) >= 0) - putenv(p); } - close(arg_fd); + if (asprintf(&p, "RSYNC_ARG%d=%s", j, buf) >= 0) + putenv(p); } + dup2(arg_fd, STDIN_FILENO); + close(arg_fd); + if (error_fd_ptr) { dup2(error_fds[1], STDOUT_FILENO); close(error_fds[1]); } - close(STDIN_FILENO); - status = shell_exec(cmd); if (!WIFEXITED(status)) @@ -453,16 +485,14 @@ static pid_t start_pre_exec(const char *cmd, int *arg_fd_ptr, int *error_fd_ptr) set_blocking(error_fds[0]); } - if (arg_fd_ptr) { - close(arg_fds[0]); - arg_fd = *arg_fd_ptr = arg_fds[1]; - set_blocking(arg_fd); - } + close(arg_fds[0]); + arg_fd = *arg_fd_ptr = arg_fds[1]; + set_blocking(arg_fd); return pid; } -static void write_pre_exec_args(int write_fd, char *request, char **early_argv, char **argv) +static void write_pre_exec_args(int write_fd, char *request, char **early_argv, char **argv, int am_early) { int j = 0; @@ -475,10 +505,15 @@ static void write_pre_exec_args(int write_fd, char *request, char **early_argv, write_buf(write_fd, *early_argv, strlen(*early_argv)+1); j = 1; /* Skip arg0 name in argv. */ } - for ( ; argv[j]; j++) - write_buf(write_fd, argv[j], strlen(argv[j])+1); + if (argv) { + for ( ; argv[j]; j++) + write_buf(write_fd, argv[j], strlen(argv[j])+1); + } write_byte(write_fd, 0); + if (am_early && early_input_len) + write_buf(write_fd, early_input, early_input_len); + close(write_fd); } @@ -812,12 +847,14 @@ static int rsync_module(int f_in, int f_out, int i, const char *addr, const char /* For early exec, fork a child process to run the indicated * command and wait for it to exit. */ if (*lp_early_exec(i)) { - pid_t pid = start_pre_exec(lp_early_exec(i), NULL, NULL); + int arg_fd; + pid_t pid = start_pre_exec(lp_early_exec(i), &arg_fd, NULL); if (pid == (pid_t)-1) { rsyserr(FLOG, errno, "early exec preparation failed"); io_printf(f_out, "@ERROR: early exec preparation failed\n"); return -1; } + write_pre_exec_args(arg_fd, NULL, NULL, NULL, 1); if (finish_pre_exec("early exec", pid, -1) != NULL) { rsyserr(FLOG, errno, "early exec failed"); io_printf(f_out, "@ERROR: early exec failed\n"); @@ -839,6 +876,11 @@ static int rsync_module(int f_in, int f_out, int i, const char *addr, const char } #endif + if (early_input) { + free(early_input); + early_input = NULL; + } + if (use_chroot) { /* * XXX: The 'use chroot' flag is a fairly reliable @@ -953,7 +995,7 @@ static int rsync_module(int f_in, int f_out, int i, const char *addr, const char msgs2stderr = 0; /* A non-rsh-run daemon doesn't have stderr for msgs. */ if (pre_exec_pid) { - write_pre_exec_args(pre_exec_arg_fd, request, orig_early_argv, orig_argv); + write_pre_exec_args(pre_exec_arg_fd, request, orig_early_argv, orig_argv, 0); err_msg = finish_pre_exec("pre-xfer exec", pre_exec_pid, pre_exec_error_fd); } @@ -1185,6 +1227,20 @@ int start_daemon(int f_in, int f_out) if (!read_line_old(f_in, line, sizeof line, 0)) return -1; + if (strncmp(line, EARLY_INPUT_CMD, EARLY_INPUT_CMDLEN) == 0) { + early_input_len = strtol(line + EARLY_INPUT_CMDLEN, NULL, 10); + if (early_input_len <= 0 || early_input_len >= BIGPATHBUFLEN) { + io_printf(f_out, "@ERROR: invalid early_input length\n"); + return -1; + } + if (!(early_input = new_array(char, early_input_len))) + out_of_memory("exchange_protocols"); + read_buf(f_in, early_input, early_input_len); + + if (!read_line_old(f_in, line, sizeof line, 0)) + return -1; + } + if (!*line || strcmp(line, "#list") == 0) { rprintf(FLOG, "module-list request from %s (%s)\n", host, addr); diff --git a/options.c b/options.c index 6c99dd4b..c68b43b9 100644 --- a/options.c +++ b/options.c @@ -170,6 +170,7 @@ char *logfile_name = NULL; char *logfile_format = NULL; char *stdout_format = NULL; char *password_file = NULL; +char *early_input_file = NULL; char *rsync_path = RSYNC_PATH; char *backup_dir = NULL; char backup_dir_buf[MAXPATHLEN]; @@ -996,6 +997,7 @@ static struct poptOption long_options[] = { {"port", 0, POPT_ARG_INT, &rsync_port, 0, 0, 0 }, {"sockopts", 0, POPT_ARG_STRING, &sockopts, 0, 0, 0 }, {"password-file", 0, POPT_ARG_STRING, &password_file, 0, 0, 0 }, + {"early-input", 0, POPT_ARG_STRING, &early_input_file, 0, 0, 0 }, {"blocking-io", 0, POPT_ARG_VAL, &blocking_io, 1, 0, 0 }, {"no-blocking-io", 0, POPT_ARG_VAL, &blocking_io, 0, 0, 0 }, {"outbuf", 0, POPT_ARG_STRING, &outbuf_mode, 0, 0, 0 }, diff --git a/rsync.1.md b/rsync.1.md index 137c25a5..4a3099b9 100644 --- a/rsync.1.md +++ b/rsync.1.md @@ -452,6 +452,7 @@ detailed description below for a complete description. --log-file=FILE log what we're doing to the specified FILE --log-file-format=FMT log updates using the specified FMT --password-file=FILE read daemon-access password from FILE +--early-input=FILE use FILE for daemon's early exec input --list-only list the files instead of copying them --bwlimit=RATE limit socket I/O bandwidth --write-batch=FILE write a batched update to FILE @@ -2977,6 +2978,15 @@ your home directory (remove the '=' for that). authentication (i.e. if you have also specified a password in the daemon's config file). +0. `--early-input=FILE` + + This option allows rsync to send up to 5K of data to the "early exec" + script on its stdin. One possible use of this data is to give the script a + secret that can be used to mount an encrypted filesystem (which you should + unmount in the the "post-xfer exec" script). + + The daemon must be at least version 3.2.1. + 0. `--list-only` This option will cause the source files to be listed instead of -- The rsync repository. _______________________________________________ rsync-cvs mailing list rsync-cvs@lists.samba.org https://lists.samba.org/mailman/listinfo/rsync-cvs