]> git.ipfire.org Git - thirdparty/rsync.git/commitdiff
Improve how the env restricts negotiated strings
authorWayne Davison <wayne@opencoder.net>
Wed, 24 Jun 2020 00:19:58 +0000 (17:19 -0700)
committerWayne Davison <wayne@opencoder.net>
Wed, 24 Jun 2020 00:33:16 +0000 (17:33 -0700)
- 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.

checksum.c
compat.c
rsync.1.md

index 87e836583a347887b3194dcb5bc444ab01a72a6c..7c9151731bc346e8cb49ae9c6e554e85ff297273 100644 (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)
index 9ec39ea04e35b608fe8b0612f84e4187dd41c14e..7a97cfc36b2a958898cd5d334a2abd3e620fef81 100644 (file)
--- a/compat.c
+++ b/compat.c
@@ -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)
index 164cbd44d7064da18f3ed719317066600d23b2fd..ebd59dcad98850e51dc9653480898adb006a1c1a 100644 (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