Improve how the env restricts negotiated strings

- The env on the server side now affects the negotiated strings
  that are sent to the client.
- A too-old remote rsync gets a default negotiated string value
  so that an env restriction now handles old clients the same way
  as new ones.
This commit is contained in:
Wayne Davison
2020-06-23 17:19:58 -07:00
parent d1fdf9ff8d
commit 323c42d51e
3 changed files with 31 additions and 23 deletions

View File

@@ -85,7 +85,7 @@ static const char *checksum_name(int num)
{
struct name_num_item *nni = get_nni_by_num(&valid_checksums, num);
return nni ? nni->name : num < CSUM_MD4 ? "MD4" : "UNKNOWN";
return nni ? nni->name : num < CSUM_MD4 ? "md4" : "UNKNOWN";
}
void parse_checksum_choice(int final_call)

View File

@@ -390,20 +390,12 @@ static void send_negotiate_str(int f_out, struct name_num_obj *nno, const char *
{
char tmpbuf[MAX_NSTR_STRLEN];
const char *list_str = getenv(env_name);
int len, fail_if_empty = list_str && strstr(list_str, "FAIL");
int len;
if (!do_negotiated_strings) {
if (!am_server && fail_if_empty) {
rprintf(FERROR, "Remote rsync is too old for %s negotiation\n", nno->type);
exit_cleanup(RERR_UNSUPPORTED);
}
return;
}
if (list_str && *list_str && (!am_server || local_server)) {
if (list_str && *list_str) {
init_nno_saw(nno, 0);
len = parse_nni_str(nno, list_str, tmpbuf, MAX_NSTR_STRLEN);
if (fail_if_empty && !len)
if (!len)
len = strlcpy(tmpbuf, "FAIL", MAX_NSTR_STRLEN);
list_str = tmpbuf;
} else
@@ -423,7 +415,7 @@ static void send_negotiate_str(int f_out, struct name_num_obj *nno, const char *
/* A local server doesn't bother to send/recv the strings, it just constructs
* and parses the same string on both sides. */
recv_negotiate_str(-1, nno, tmpbuf, len);
} else {
} else if (do_negotiated_strings) {
/* Each side sends their list of valid names to the other side and then both sides
* pick the first name in the client's list that is also in the server's list. */
write_vstring(f_out, tmpbuf, len);
@@ -442,13 +434,28 @@ static void negotiate_the_strings(int f_in, int f_out)
if (valid_checksums.saw) {
char tmpbuf[MAX_NSTR_STRLEN];
recv_negotiate_str(f_in, &valid_checksums, tmpbuf, -1);
int len;
if (do_negotiated_strings)
len = -1;
else
len = strlcpy(tmpbuf, protocol_version >= 30 ? "md5" : "md4", MAX_NSTR_STRLEN);
recv_negotiate_str(f_in, &valid_checksums, tmpbuf, len);
}
if (valid_compressions.saw) {
char tmpbuf[MAX_NSTR_STRLEN];
recv_negotiate_str(f_in, &valid_compressions, tmpbuf, -1);
int len;
if (do_negotiated_strings)
len = -1;
else
len = strlcpy(tmpbuf, "zlib", MAX_NSTR_STRLEN);
recv_negotiate_str(f_in, &valid_compressions, tmpbuf, len);
}
/* If the other side is too old to negotiate, the above steps just made sure that
* the env didn't disallow the old algorithm. Mark things as non-negotiated. */
if (!do_negotiated_strings)
valid_checksums.negotiated_name = valid_compressions.negotiated_name = NULL;
}
void setup_protocol(int f_out,int f_in)

View File

@@ -1490,7 +1490,8 @@ your home directory (remove the '=' for that).
a negotiation between the client and the server as follows:
If both the client and the server are at least version 3.2.0, they will
exchange a list of checksum names and choose the first one in the list that
exchange a list of checksum names and choose the first one in the client's
list that
they have in common. This typically means that they will choose xxh64 if
they both support it and fall back to MD5. If one side of the transfer is
not new enough to support this checksum negotiation, then a value is chosen
@@ -1503,8 +1504,8 @@ your home directory (remove the '=' for that).
client exits with an error. This method does not allow you to specify the
transfer checksum separately from the pre-transfer checksum, and it ignores
"auto" and all unknown checksum names. If the remote rsync is not new
enough to handle a checksum negotiation list, the list is silently ignored
unless it contains the string "FAIL".
enough to handle a checksum negotiation list, its list is assumed to
consist of a single "md5" or "md4" item based on the protocol version.
The use of the `--checksum-choice` option overrides this environment list.
@@ -2267,13 +2268,11 @@ your home directory (remove the '=' for that).
When both sides of the transfer are at least 3.2.0, rsync chooses the first
algorithm in the client's list of choices that is also in the server's list
of choices. You default order can be customized by setting the environment
of choices. Your default order can be customized by setting the environment
variable RSYNC_COMPRESS_LIST to a space-separated list of acceptable
compression names. If no common compress choice is found, the client exits
with an error. The one exception to this is that the list is ignored when
talking with an old rsync that doesn't support the checksum negotiation.
Include the string "FAIL" in your list if you want rsync to fail in such a
case.
with an error. If the remote rsync is too old to support checksum negotiation,
its list is assumed to be "zlib".
There are some older rsync versions that were configured to reject a `-z`
option and require the use of `-zz` because their compression library was
@@ -2297,6 +2296,8 @@ your home directory (remove the '=' for that).
- `zlib`
- `none`
Run `rsync -V` to see the compress list compiled into your version.
Note that if you see an error about an option named `--old-compress` or
`--new-compress`, this is rsync trying to send the `--compress-choice=zlib`
or `--compress-choice=zlibx` option in a backward-compatible manner that