Fixes CVE-2017-15994 (https://nvd.nist.gov/vuln/detail/CVE-2017-15994):

rsync 3.1.3-development before 2017-10-24, as used in the xlucas svfs rsync fork and other products,
mishandles archaic checksums, which makes it easier for remote attackers to bypass intended access
restrictions.

From 7b8a4ecd6ff9cdf4e5d3850ebf822f1e989255b3 Mon Sep 17 00:00:00 2001
From: Wayne Davison <wayned@samba.org>
Date: Tue, 24 Oct 2017 15:40:37 -0700
Subject: [PATCH] Handle archaic checksums properly.

---
 checksum.c | 20 ++++++++++++++------
 1 file changed, 14 insertions(+), 6 deletions(-)

diff --git a/checksum.c b/checksum.c
index 8b38833..9382694 100644
--- a/checksum.c
+++ b/checksum.c
@@ -27,7 +27,7 @@ extern int proper_seed_order;
 extern char *checksum_choice;
 
 #define CSUM_NONE 0
-#define CSUM_ARCHAIC 1
+#define CSUM_MD4_ARCHAIC 1
 #define CSUM_MD4_BUSTED 2
 #define CSUM_MD4_OLD 3
 #define CSUM_MD4 4
@@ -60,7 +60,7 @@ int parse_csum_name(const char *name, int len)
 			return CSUM_MD4_OLD;
 		if (protocol_version >= 21)
 			return CSUM_MD4_BUSTED;
-		return CSUM_ARCHAIC;
+		return CSUM_MD4_ARCHAIC;
 	}
 	if (len == 3 && strncasecmp(name, "md4", 3) == 0)
 		return CSUM_MD4;
@@ -78,7 +78,7 @@ int csum_len_for_type(int cst)
 	switch (cst) {
 	  case CSUM_NONE:
 		return 1;
-	  case CSUM_ARCHAIC:
+	  case CSUM_MD4_ARCHAIC:
 		return 2;
 	  case CSUM_MD4:
 	  case CSUM_MD4_OLD:
@@ -143,7 +143,8 @@ void get_checksum2(char *buf, int32 len, char *sum)
 	  }
 	  case CSUM_MD4:
 	  case CSUM_MD4_OLD:
-	  case CSUM_MD4_BUSTED: {
+	  case CSUM_MD4_BUSTED:
+	  case CSUM_MD4_ARCHAIC: {
 		int32 i;
 		static char *buf1;
 		static int32 len1;
@@ -174,7 +175,7 @@ void get_checksum2(char *buf, int32 len, char *sum)
 		 * are multiples of 64.  This is fixed by calling mdfour_update()
 		 * even when there are no more bytes.
 		 */
-		if (len - i > 0 || xfersum_type != CSUM_MD4_BUSTED)
+		if (len - i > 0 || xfersum_type > CSUM_MD4_BUSTED)
 			mdfour_update(&m, (uchar *)(buf1+i), len-i);
 
 		mdfour_result(&m, (uchar *)sum);
@@ -217,6 +218,7 @@ void file_checksum(const char *fname, const STRUCT_STAT *st_p, char *sum)
 	  case CSUM_MD4:
 	  case CSUM_MD4_OLD:
 	  case CSUM_MD4_BUSTED:
+	  case CSUM_MD4_ARCHAIC:
 		mdfour_begin(&m);
 
 		for (i = 0; i + CSUM_CHUNK <= len; i += CSUM_CHUNK) {
@@ -229,7 +231,7 @@ void file_checksum(const char *fname, const STRUCT_STAT *st_p, char *sum)
 		 * are multiples of 64.  This is fixed by calling mdfour_update()
 		 * even when there are no more bytes. */
 		remainder = (int32)(len - i);
-		if (remainder > 0 || checksum_type != CSUM_MD4_BUSTED)
+		if (remainder > 0 || checksum_type > CSUM_MD4_BUSTED)
 			mdfour_update(&m, (uchar *)map_ptr(buf, i, remainder), remainder);
 
 		mdfour_result(&m, (uchar *)sum);
@@ -265,6 +267,7 @@ void sum_init(int csum_type, int seed)
 		break;
 	  case CSUM_MD4_OLD:
 	  case CSUM_MD4_BUSTED:
+	  case CSUM_MD4_ARCHAIC:
 		mdfour_begin(&md);
 		sumresidue = 0;
 		SIVAL(s, 0, seed);
@@ -321,6 +324,10 @@ void sum_update(const char *p, int32 len)
 	}
 }
 
+/* NOTE: all the callers of sum_end() pass in a pointer to a buffer that is
+ * MAX_DIGEST_LEN in size, so even if the csum-len is shorter that that (i.e.
+ * CSUM_MD4_ARCHAIC), we don't have to worry about limiting the data we write
+ * into the "sum" buffer. */
 int sum_end(char *sum)
 {
 	switch (cursum_type) {
@@ -333,6 +340,7 @@ int sum_end(char *sum)
 		mdfour_result(&md, (uchar *)sum);
 		break;
 	  case CSUM_MD4_BUSTED:
+	  case CSUM_MD4_ARCHAIC:
 		if (sumresidue)
 			mdfour_update(&md, (uchar *)md.buffer, sumresidue);
 		mdfour_result(&md, (uchar *)sum);
-- 
1.9.1

diff --git a/authenticate.c b/authenticate.c
index d60ee20..a106b0f 100644
--- a/authenticate.c
+++ b/authenticate.c
@@ -22,6 +22,7 @@
 #include "itypes.h"
 
 extern int read_only;
+extern int protocol_version;
 extern char *password_file;
 
 /***************************************************************************
@@ -237,6 +238,11 @@ char *auth_server(int f_in, int f_out, int module, const char *host,
 	if (!users || !*users)
 		return "";
 
+	if (protocol_version < 21) { /* Don't allow a weak checksum for the password. */
+		rprintf(FERROR, "ERROR: protocol version is too old!\n");
+		exit_cleanup(RERR_PROTOCOL);
+	}
+
 	gen_challenge(addr, challenge);
 
 	io_printf(f_out, "%s%s\n", leader, challenge);
-- 
1.9.1

From c252546ceeb0925eb8a4061315e3ff0a8c55b48b Mon Sep 17 00:00:00 2001
From: Wayne Davison <wayned@samba.org>
Date: Tue, 24 Oct 2017 20:42:41 -0700
Subject: [PATCH] Don't forget to tweak sum_update().

---
 checksum.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/checksum.c b/checksum.c
index 9382694..c119f97 100644
--- a/checksum.c
+++ b/checksum.c
@@ -295,6 +295,7 @@ void sum_update(const char *p, int32 len)
 	  case CSUM_MD4:
 	  case CSUM_MD4_OLD:
 	  case CSUM_MD4_BUSTED:
+	  case CSUM_MD4_ARCHAIC:
 		if (len + sumresidue < CSUM_CHUNK) {
 			memcpy(md.buffer + sumresidue, p, len);
 			sumresidue += len;
-- 
1.9.1

From 9a480deec4d20277d8e20bc55515ef0640ca1e55 Mon Sep 17 00:00:00 2001
From: Wayne Davison <wayned@samba.org>
Date: Tue, 24 Oct 2017 20:44:37 -0700
Subject: [PATCH] Only allow a modern checksum method for passwords.

---
 authenticate.c | 6 ++++++
 1 file changed, 6 insertions(+)

