[SCM] The rsync repository. - branch master updated
Rsync CVS commit messages
rsync-cvs at lists.samba.org
Tue Aug 9 18:47:22 UTC 2022
The branch, master has been updated
via cff8f044 Add `--trust-sender` option.
via db8034f1 Escape leading tilde char when "~" or with -R.
via c86763dc Fix handling of daemon module names in file-list verification; convert some while loops to for loops.
from 5ce575b1 Preparing for release of 3.2.5pre2
https://git.samba.org/?p=rsync.git;a=shortlog;h=master
- Log -----------------------------------------------------------------
commit cff8f044776c5143a5b270969d4bb0f1fea8b017
Author: Wayne Davison <wayne at opencoder.net>
Date: Tue Aug 9 11:45:56 2022 -0700
Add `--trust-sender` option.
commit db8034f12ecda624ce9f2adf3aa47ef40a12626c
Author: Wayne Davison <wayne at opencoder.net>
Date: Tue Aug 9 11:42:14 2022 -0700
Escape leading tilde char when "~" or with -R.
commit c86763dc382fc6ed6c4c4c461243f51acfc3f226
Author: Wayne Davison <wayne at opencoder.net>
Date: Tue Aug 9 11:37:37 2022 -0700
Fix handling of daemon module names in file-list verification; convert some while loops to for loops.
-----------------------------------------------------------------------
Summary of changes:
NEWS.md | 8 +++++++
exclude.c | 34 ++++++++++++---------------
io.c | 4 ++--
main.c | 6 ++---
options.c | 16 +++++++++++++
rsync.1.md | 78 ++++++++++++++++++++++++++++++++++++++++++++------------------
6 files changed, 99 insertions(+), 47 deletions(-)
Changeset truncated at 500 lines:
diff --git a/NEWS.md b/NEWS.md
index 0c212da9..5394b1a9 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -17,6 +17,9 @@
### BUG FIXES:
+- Fixed the handling of filenames specified with backslash-quoted wildcards
+ when the default remote-arg-escaping is enabled.
+
- Fixed the configure check for signed char that was causing a host that
defaults to unsigned characters to generate bogus rolling checksums. This
made rsync send mostly literal data for a copy instead of finding matching
@@ -26,6 +29,11 @@
- Lots of manpage improvements, including an attempt to better describe how
include/exclude filters work.
+### ENHANCEMENTS:
+
+- The [`--trust-sender`](rsync.1#opt) option was added as a way to bypass the
+ extra file-list safety checking (should that be required).
+
### PACKAGING RELATED:
- The build date that goes into the manpages is now based on the developer's
diff --git a/exclude.c b/exclude.c
index ba5ca5a3..da25661b 100644
--- a/exclude.c
+++ b/exclude.c
@@ -33,18 +33,15 @@ extern int recurse;
extern int local_server;
extern int prune_empty_dirs;
extern int ignore_perishable;
-extern int old_style_args;
extern int relative_paths;
extern int delete_mode;
extern int delete_excluded;
extern int cvs_exclude;
extern int sanitize_paths;
extern int protocol_version;
-extern int read_batch;
-extern int list_only;
+extern int trust_sender_args;
extern int module_id;
-extern char *filesfrom_host;
extern char curr_dir[MAXPATHLEN];
extern unsigned int curr_dir_len;
extern unsigned int module_dirlen;
@@ -55,6 +52,7 @@ filter_rule_list daemon_filter_list = { .debug_type = " [daemon]" };
filter_rule_list implied_filter_list = { .debug_type = " [implied]" };
int saw_xattr_filter = 0;
+int trust_sender_args = 0;
int trust_sender_filter = 0;
/* Need room enough for ":MODS " prefix plus some room to grow. */
@@ -316,13 +314,11 @@ static void maybe_add_literal_brackets_rule(filter_rule const *based_on, int arg
if (arg_len < 0)
arg_len = strlen(arg);
- cp = arg;
- while (*cp) {
+ for (cp = arg; *cp; cp++) {
if (*cp == '\\' && cp[1]) {
cp++;
} else if (*cp == '[')
cnt++;
- cp++;
}
if (!cnt)
return;
@@ -331,8 +327,7 @@ static void maybe_add_literal_brackets_rule(filter_rule const *based_on, int arg
rule->rflags = based_on->rflags;
rule->u.slash_cnt = based_on->u.slash_cnt;
p = rule->pattern = new_array(char, arg_len + cnt + 1);
- cp = arg;
- while (*cp) {
+ for (cp = arg; *cp; ) {
if (*cp == '\\' && cp[1]) {
*p++ = *cp++;
} else if (*cp == '[')
@@ -373,14 +368,14 @@ void free_implied_include_partial_string()
/* Each arg the client sends to the remote sender turns into an implied include
* that the receiver uses to validate the file list from the sender. */
-void add_implied_include(const char *arg)
+void add_implied_include(const char *arg, int skip_daemon_module)
{
filter_rule *rule;
int arg_len, saw_wild = 0, saw_live_open_brkt = 0, backslash_cnt = 0;
int slash_cnt = 1; /* We know we're adding a leading slash. */
const char *cp;
char *p;
- if (am_server || old_style_args || list_only || read_batch || filesfrom_host != NULL)
+ if (trust_sender_args)
return;
if (partial_string_len) {
arg_len = strlen(arg);
@@ -390,6 +385,12 @@ void add_implied_include(const char *arg)
partial_string_len = 0;
arg = partial_string_buf;
}
+ if (skip_daemon_module) {
+ if ((cp = strchr(arg, '/')) != NULL)
+ arg = cp + 1;
+ else
+ arg = "";
+ }
if (relative_paths) {
if ((cp = strstr(arg, "/./")) != NULL)
arg = cp + 3;
@@ -402,11 +403,8 @@ void add_implied_include(const char *arg)
if (arg_len) {
if (strpbrk(arg, "*[?")) {
/* We need to add room to escape backslashes if wildcard chars are present. */
- cp = arg;
- while ((cp = strchr(cp, '\\')) != NULL) {
+ for (cp = arg; (cp = strchr(cp, '\\')) != NULL; cp++)
arg_len++;
- cp++;
- }
saw_wild = 1;
}
arg_len++; /* Leave room for the prefixed slash */
@@ -420,8 +418,7 @@ void add_implied_include(const char *arg)
rule->rflags = FILTRULE_INCLUDE + (saw_wild ? FILTRULE_WILD : 0);
p = rule->pattern = new_array(char, arg_len + 1);
*p++ = '/';
- cp = arg;
- while (*cp) {
+ for (cp = arg; *cp; ) {
switch (*cp) {
case '\\':
if (cp[1] == ']')
@@ -498,8 +495,7 @@ void add_implied_include(const char *arg)
if (!saw_wild && backslash_cnt) {
/* We are appending a wildcard, so now the backslashes need to be escaped. */
p = rule->pattern = new_array(char, arg_len + backslash_cnt + 3 + 1);
- cp = arg;
- while (*cp) {
+ for (cp = arg; *cp; ) {
if (*cp == '\\')
*p++ = '\\';
*p++ = *cp++;
diff --git a/io.c b/io.c
index 7111878a..3f605d74 100644
--- a/io.c
+++ b/io.c
@@ -420,7 +420,7 @@ static void forward_filesfrom_data(void)
while (s != eob) {
if (*s++ == '\0') {
ff_xb.len = s - sob - 1;
- add_implied_include(sob);
+ add_implied_include(sob, 0);
if (iconvbufs(ic_send, &ff_xb, &iobuf.out, flags) < 0)
exit_cleanup(RERR_PROTOCOL); /* impossible? */
write_buf(iobuf.out_fd, s-1, 1); /* Send the '\0'. */
@@ -457,7 +457,7 @@ static void forward_filesfrom_data(void)
/* Eliminate any multi-'\0' runs. */
while (f != eob) {
if (!(*t++ = *f++)) {
- add_implied_include(cur);
+ add_implied_include(cur, 0);
cur = t;
while (f != eob && *f == '\0')
f++;
diff --git a/main.c b/main.c
index fa263d27..9ebfbea7 100644
--- a/main.c
+++ b/main.c
@@ -89,7 +89,6 @@ extern int backup_dir_len;
extern int basis_dir_cnt;
extern int default_af_hint;
extern int stdout_format_has_i;
-extern int trust_sender_filter;
extern struct stats stats;
extern char *stdout_format;
extern char *logfile_format;
@@ -636,7 +635,6 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char **remote_argv, in
#ifdef ICONV_CONST
setup_iconv();
#endif
- trust_sender_filter = 1;
} else if (local_server) {
/* If the user didn't request --[no-]whole-file, force
* it on, but only if we're not batch processing. */
@@ -1504,7 +1502,7 @@ static int start_client(int argc, char *argv[])
int dummy_port = rsync_port;
int i;
if (filesfrom_fd < 0)
- add_implied_include(remote_argv[0]);
+ add_implied_include(remote_argv[0], daemon_connection);
/* For remote source, any extra source args must have either
* the same hostname or an empty hostname. */
for (i = 1; i < remote_argc; i++) {
@@ -1528,7 +1526,7 @@ static int start_client(int argc, char *argv[])
if (!rsync_port && !*arg) /* Turn an empty arg into a dot dir. */
arg = ".";
remote_argv[i] = arg;
- add_implied_include(arg);
+ add_implied_include(arg, daemon_connection);
}
}
diff --git a/options.c b/options.c
index a60ff515..4feeb7e0 100644
--- a/options.c
+++ b/options.c
@@ -27,6 +27,8 @@
extern int module_id;
extern int local_server;
extern int sanitize_paths;
+extern int trust_sender_args;
+extern int trust_sender_filter;
extern unsigned int module_dirlen;
extern filter_rule_list filter_list;
extern filter_rule_list daemon_filter_list;
@@ -64,6 +66,7 @@ int preserve_atimes = 0;
int preserve_crtimes = 0;
int omit_dir_times = 0;
int omit_link_times = 0;
+int trust_sender = 0;
int update_only = 0;
int open_noatime = 0;
int cvs_exclude = 0;
@@ -788,6 +791,7 @@ static struct poptOption long_options[] = {
{"protect-args", 's', POPT_ARG_VAL, &protect_args, 1, 0, 0},
{"no-protect-args", 0, POPT_ARG_VAL, &protect_args, 0, 0, 0},
{"no-s", 0, POPT_ARG_VAL, &protect_args, 0, 0, 0},
+ {"trust-sender", 0, POPT_ARG_VAL, &trust_sender, 1, 0, 0},
{"numeric-ids", 0, POPT_ARG_VAL, &numeric_ids, 1, 0, 0 },
{"no-numeric-ids", 0, POPT_ARG_VAL, &numeric_ids, 0, 0, 0 },
{"usermap", 0, POPT_ARG_STRING, 0, OPT_USERMAP, 0, 0 },
@@ -2465,6 +2469,11 @@ int parse_arguments(int *argc_p, const char ***argv_p)
}
}
+ if (trust_sender || am_server || read_batch)
+ trust_sender_args = trust_sender_filter = 1;
+ else if (old_style_args || filesfrom_host != NULL)
+ trust_sender_args = 1;
+
am_starting_up = 0;
return 1;
@@ -2492,12 +2501,17 @@ char *safe_arg(const char *opt, const char *arg)
BOOL is_filename_arg = !opt;
char *escapes = is_filename_arg ? SHELL_CHARS : WILD_CHARS SHELL_CHARS;
BOOL escape_leading_dash = is_filename_arg && *arg == '-';
+ BOOL escape_leading_tilde = 0;
int len1 = opt && *opt ? strlen(opt) + 1 : 0;
int len2 = strlen(arg);
int extras = escape_leading_dash ? 2 : 0;
char *ret;
if (!protect_args && old_style_args < 2 && (!old_style_args || (!is_filename_arg && opt != SPLIT_ARG_WHEN_OLD))) {
const char *f;
+ if (!trust_sender_args && *arg == '~' && (relative_paths || !strchr(arg, '/'))) {
+ extras++;
+ escape_leading_tilde = 1;
+ }
for (f = arg; *f; f++) {
if (strchr(escapes, *f))
extras++;
@@ -2520,6 +2534,8 @@ char *safe_arg(const char *opt, const char *arg)
else {
const char *f = arg;
char *t = ret + len1;
+ if (escape_leading_tilde)
+ *t++ = '\\';
while (*f) {
if (*f == '\\') {
if (!is_filename_arg || !strchr(WILD_CHARS, f[1]))
diff --git a/rsync.1.md b/rsync.1.md
index 0c27df4c..72675594 100644
--- a/rsync.1.md
+++ b/rsync.1.md
@@ -193,6 +193,8 @@ Dedicate a "host1-files" dir to the remote content:
> rsync -aiv host1:dir1 ~/host1-files
+See the [`--trust-sender`](#opt) option for additional details.
+
## ADVANCED USAGE
The syntax for requesting multiple files from a remote host is done by
@@ -463,6 +465,7 @@ has its own detailed description later in this manpage.
--from0, -0 all *-from/filter files are delimited by 0s
--old-args disable the modern arg-protection idiom
--protect-args, -s no space-splitting; wildcard chars only
+--trust-sender trust the remote sender's file list
--copy-as=USER[:GROUP] specify user & optional group for the copy
--address=ADDRESS bind address for outgoing socket to daemon
--port=PORT specify double-colon alternate port number
@@ -536,7 +539,8 @@ option has a short variant).
The parameter may need to be quoted in some manner for it to survive the
shell's command-line parsing. Also keep in mind that a leading tilde (`~`) in
a pathname is substituted by your shell, so make sure that you separate the
-option name from the pathname using a space if you want the shell to expand it.
+option name from the pathname using a space if you want the local shell to
+expand it.
[comment]: # (Some markup below uses a literal non-breakable space when a backtick string)
[comment]: # (needs to contain a space since markdown strips spaces from the start/end)
@@ -1908,8 +1912,8 @@ option name from the pathname using a space if you want the shell to expand it.
A rule can still apply to both sides even with this option specified if the
rule is given both the sender & receiver modifer letters (e.g., `-f'-sr
foo'`). Receiver-side protect/risk rules can also be explicitly specified
- to limit the deletions. This is saves you from having to edit a bunch of
- `-f'- foo'` rules into `-f'-s foo'` or `-f'H foo'` rules (not to mention
+ to limit the deletions. This saves you from having to edit a bunch of
+ `-f'- foo'` rules into `-f'-s foo'` (aka `-f'H foo'`) rules (not to mention
the corresponding includes).
See the [FILTER RULES](#) section for more information. See
@@ -2408,6 +2412,38 @@ option name from the pathname using a space if you want the shell to expand it.
Note that this option is incompatible with the use of the restricted rsync
script (`rrsync`) since it hides options from the script's inspection.
+0. `--trust-sender`
+
+ Disable the extra validation of the file list from a remote sender (this
+ safety feature was added in 3.2.5). This should only be done if you trust
+ the sender to not try to do something malicious, which should be the case
+ if they're running a stock rsync.
+
+ Normally when pulling files from a remote rsync, the client runs 2 extra
+ validation checks:
+
+ - Verify that additional arg items didn't get added at the top of the
+ transfer.
+ - Verify that none of the items in the file list should have been excluded.
+
+ Note that various options can turn off one or both of these checks if the
+ option interferes with the validation. For instance:
+
+ - Using a per-directory filter file reads filter rules that only the server
+ knows about, so the filter checking is disabled.
+ - Using the [`--old-args`](#opt) option allows the sender to manipulate the
+ requested args, so the arg checking is disabled.
+ - Reading the files-from list from the server side means that the client
+ doesn't know the arg list, so the arg checking is disabled.
+ - Using [`--read-batch`](#opt) disables both checks since the batch file's
+ contents will have been verified when it was created.
+
+ This option may help an under-powered client server if the extra pattern
+ matching is slowing things down on a huge transfer. It can also be used
+ to work around a bug in the verification logic, possibly after using the
+ [`--list-only`](#opt) option combined with [`--trust-sender`](#opt) to look
+ over the full file list.
+
0. `--copy-as=USER[:GROUP]`
This option instructs rsync to use the USER and (if specified after a
@@ -3444,8 +3480,8 @@ option name from the pathname using a space if you want the shell to expand it.
include the destination.
CAUTION: keep in mind that a source arg with a wild-card is expanded by the
- shell into multiple args, so it is never safe to try to list such an arg
- without using this option. For example:
+ shell into multiple args, so it is never safe to try to specify a single
+ wild-card arg to try to infer this option. A safe example is:
> rsync -av --list-only foo* dest/
@@ -3790,7 +3826,7 @@ different ways.
We will first cover the basics of how include & exclude rules affect what files
are transferred, ignoring any deletion side-effects. Filter rules mainly
affect the contents of directories that rsync is "recursing" into, but they can
-also affect a top-level item in the transfer that were specified as a argument.
+also affect a top-level item in the transfer that was specified as a argument.
The default for any unmatched file/dir is for it to be included in the
transfer, which puts the file/dir into the sender's file list. The use of an
@@ -3919,7 +3955,7 @@ You have your choice of using either short or long RULE names, as described
below. If you use a short-named rule, the ',' separating the RULE from the
MODIFIERS is optional. The PATTERN or FILENAME that follows (when present)
must come after either a single space or an underscore (\_). Any additional
-spaces and/or undeerscore are considered to be a part of the pattern name.
+spaces and/or underscores are considered to be a part of the pattern name.
Here are the available rule prefixes:
0. `exclude, '-'` specifies an exclude pattern that (by default) is both a
@@ -3929,10 +3965,8 @@ Here are the available rule prefixes:
0. `merge, '.'` specifies a merge-file on the client side to read for more
rules.
0. `dir-merge, ':'` specifies a per-directory merge-file. Using this kind of
- filter rule requires that you trust the sending side's filter checking, and
- thus it disables the receiver's verification of the file-list names against
- the filter rules (since only the sender can know for sure if it obeyed all
- the filter rules when some are per-dir merged from the sender's files).
+ filter rule requires that you trust the sending side's filter checking, so
+ it has the side-effect mentioned under the [`--trust-sender`](#opt) option.
0. `hide, 'H'` specifies a pattern for hiding files from the transfer.
Equivalent to a sender-only exclude, so `-f'H foo'` could also be specified
as `-f'-s foo'`.
@@ -3969,15 +4003,15 @@ The matching rules for the pattern argument take several forms:
- If a pattern contains a `/` (not counting a trailing slash) or a "`**`"
(which can match a slash), then the pattern is matched against the full
pathname, including any leading directories within the transfer. If the
- pattern doesn't contain a `/` or a "`**`", then it is matched only against
- the final component of the filename or pathname. For example, `foo` means
- that the final path component must be "foo" while `foo/bar` would match the
- last 2 elements of the path (as long as both elements are within the
- transfer).
+ pattern doesn't contain a (non-trailing) `/` or a "`**`", then it is matched
+ only against the final component of the filename or pathname. For example,
+ `foo` means that the final path component must be "foo" while `foo/bar` would
+ match the last 2 elements of the path (as long as both elements are within
+ the transfer).
- A pattern that ends with a `/` only matches a directory, not a regular file,
symlink, or device.
- A pattern that starts with a `/` is anchored to the start of the transfer
- path instead of the end. For example, `/foo` or `/foo/bar` match only
+ path instead of the end. For example, `/foo/**` or `/foo/bar/**` match only
leading elements in the path. If the rule is read from a per-directory
filter file, the transfer path being matched will begin at the level of the
filter file instead of the top of the transfer. See the section on
@@ -4010,11 +4044,11 @@ Here are some examples of exclude/include matching:
- Option `-f'- /foo'` would exclude a file (or directory) named foo in the
transfer-root directory
- Option `-f'- foo/'` would exclude any directory named foo
-- Option `-f'- /foo/*/bar'` would exclude any file/dir named bar which is at
- two levels below a directory named foo, which must be at the root of the
- transfer
-- Option `-f'- /foo/**/bar'` would exclude any file/dir named bar two or more
- levels below a directory named foo, which must be at the root of the transfer
+- Option `-f'- foo/*/bar'` would exclude any file/dir named bar which is at two
+ levels below a directory named foo (if foo is in the transfer)
+- Option `-f'- /foo/**/bar'` would exclude any file/dir named bar that was two
+ or more levels below the top-level directory named foo (exclude /foo/bar in a
+ separate rule, if desired)
- Options `-f'+ */' -f'+ *.c' -f'- *'` would include all directories and .c
source files but nothing else
- Options `-f'+ foo/' -f'+ foo/bar.c' -f'- *'` would include only the foo
--
The rsync repository.
More information about the rsync-cvs
mailing list