File CVE-2019-25017.patch of Package krb5-appl.26157

From 63f3e734c633a87c745a81a49fdb3fc8881f28ff Mon Sep 17 00:00:00 2001
From: Samuel Cabrero <scabrero@suse.de>
Date: Mon, 11 Jan 2021 12:25:29 +0100
Subject: [PATCH 2/2] CVE-2019-25017

An issue was discovered in rcp in MIT krb5-appl through 1.0.3. Due to the rcp
implementation being derived from 1983 rcp, the server chooses which
files/directories are sent to the client. However, the rcp client only
performs cursory validation of the object name returned (only directory
traversal attacks are prevented). A malicious rcp server (or
Man-in-The-Middle attacker) can overwrite arbitrary files in the rcp
client target directory. If recursive operation (-r) is performed, the server
can manipulate subdirectories as well (for example, to overwrite
the .ssh/authorized_keys file).

Check the filenames sent by the server match those requested by the
client. This checking provides some protection against a malicious server
sending unexpected filenames, but it comes at a risk of rejecting wanted
files due to differences between client and server wildcard expansion rules.

For this reason, this also adds a new -T flag to disable the check.

Related to CVE-2019-6111 (openssh) and CVE-2019-7283 (netkit-rsh).

Signed-off-by: Samuel Cabrero <scabrero@suse.de>
---
 bsd/krcp.c | 43 +++++++++++++++++++++++++++++++++++--------
 bsd/rcp.M  | 10 +++++++++-
 2 files changed, 44 insertions(+), 9 deletions(-)

diff --git a/bsd/krcp.c b/bsd/krcp.c
index d56b40c..54095f1 100644
--- a/bsd/krcp.c
+++ b/bsd/krcp.c
@@ -46,6 +46,7 @@ char copyright[] =
 #endif
 #include <sys/file.h>
 #include <fcntl.h>
+#include <fnmatch.h>
 #include <sys/stat.h>
 #include <sys/time.h>
 #include <sys/ioctl.h>
@@ -87,7 +88,7 @@ char	**save_argv(int, char **);
 char	*strsave();
 #endif
 int	rcmd_stream_write(), rcmd_stream_read();
-void 	usage(void), sink(int, char **),
+void 	usage(void), sink(int, char **, const char *),
     source(int, char **), rsource(char *, struct stat *), verifydir(char *);
 int	response(void), hosteq(char *, char *), okname(char *), 
     susystem(char *);
@@ -106,6 +107,7 @@ krb5_sigtype	lostconn(int);
 int	iamremote, targetshouldbedirectory;
 int	iamrecursive;
 int	pflag;
+int	Tflag;
 int	forcenet;
 struct	passwd *pwd;
 int	userid;
@@ -163,6 +165,7 @@ int main(argc, argv)
 	exit(1);
     }
     
+    Tflag = 0;
     for (argc--, argv++; argc > 0 && **argv == '-'; argc--, argv++) {
 	(*argv)++;
 	while (**argv) switch (*(*argv)++) {
@@ -175,6 +178,9 @@ int main(argc, argv)
 	    pflag++;
 	    break;
 	    
+	  case 'T': /* Related to CVE-2019-6111. Disable filename checks */
+	    Tflag++;
+	    break;
 	  case 'D':
 	    argc--, argv++;
 	    if (argc == 0)
@@ -236,7 +242,7 @@ int main(argc, argv)
 	    iamremote = 1;
 	    rcmd_stream_init_normal();
 
-	    sink(--argc, ++argv);
+	    sink(--argc, ++argv, NULL);
 	    exit(errs);
 	    
 	  default:
@@ -548,7 +554,7 @@ int main(argc, argv)
 			perror("rcp seteuid user"); errs++; exit(errs);
 		    }
 		}
-		sink(1, argv+argc-1);
+		sink(1, argv+argc-1, src);
 		if (euid == 0) {
 		    if(krb5_seteuid(0)) {
 			perror("rcp seteuid 0"); errs++; exit(errs);
@@ -564,7 +570,7 @@ int main(argc, argv)
 		if (setreuid(0, userid)) {
 		    perror("rcp setreuid 0,user"); errs++; exit(errs);
 		}
-		sink(1, argv+argc-1);
+		sink(1, argv+argc-1, src);
 		if (setreuid(userid, 0)) {
 		    perror("rcp setreuid user,0"); errs++; exit(errs);
 		}
@@ -575,7 +581,7 @@ int main(argc, argv)
 		if(seteuid(userid)) {
 		  perror("rcp seteuid user"); errs++; exit(errs);
 		}
-		sink(1, argv+argc-1);
+		sink(1, argv+argc-1, src);
 		if(seteuid(0)) {
 		  perror("rcp seteuid 0"); errs++; exit(errs);
 		}
@@ -909,9 +915,10 @@ struct timeval *tvp;
 #endif
 
 
-void sink(argc, argv)
+void sink(argc, argv, src)
      int argc;
      char **argv;
+     const char *src;
 {
     mode_t mode;
     mode_t mask = umask(0);
@@ -927,6 +934,7 @@ void sink(argc, argv)
     char *myargv[1];
     char cmdbuf[RCP_BUFSIZ], nambuf[RCP_BUFSIZ];
     int setimes = 0;
+    char *src_copy = NULL, *restrict_pattern = NULL;
     struct timeval tv[2];
 #define atime	tv[0]
 #define mtime	tv[1]
@@ -944,6 +952,21 @@ void sink(argc, argv)
     ga();
     if (stat(targ, &stb) == 0 && (stb.st_mode & S_IFMT) == S_IFDIR)
       targisdir = 1;
+    if (src != NULL && !iamrecursive && !Tflag) {
+        /*
+         * Prepare to try to restrict incoming filenames to match
+         * the requested destination file glob.
+         */
+         if ((src_copy = strdup(src)) == NULL) {
+             error("rcp: strdup failed\n");
+             exit(1);
+         }
+         if ((restrict_pattern = strrchr(src_copy, '/')) != NULL) {
+             *restrict_pattern++ = '\0';
+         } else {
+             restrict_pattern = src_copy;
+         }
+    }
     for (first = 1; ; first = 0) {
 	cp = cmdbuf;
 	if (rcmd_stream_read(rem, cp, 1, 0) <= 0)
@@ -1022,6 +1045,10 @@ void sink(argc, argv)
 		error("Unexpected filename: %s\n", cp);
 		exit(1);
 	}
+	if (restrict_pattern != NULL &&
+	    fnmatch(restrict_pattern, cp, 0) != 0) {
+		SCREWUP("filename does not match request");
+	}
 	if (targisdir) {
           if(strlen(targ) + strlen(cp) + 2 >= sizeof(nambuf))
 	    SCREWUP("target name too long");
@@ -1045,7 +1072,7 @@ void sink(argc, argv)
 	    } else if (mkdir(nambuf, mode) < 0)
 	      goto bad;
 	    myargv[0] = nambuf;
-	    sink(1, myargv);
+	    sink(1, myargv, src);
 	    if (setimes) {
 		setimes = 0;
 		if (utimes(nambuf, tv) < 0)
@@ -1186,7 +1213,7 @@ void usage()
 {
 #ifdef KERBEROS
     fprintf(stderr,
-	    "Usage: \trcp [-PN | -PO] [-p] [-x] [-k realm] f1 f2; or:\n\trcp [-PN | -PO] [-r] [-p] [-x] [-k realm] f1 ... fn d2\n");
+	    "Usage: \trcp [-PN | -PO] [-p] [-T] [-x] [-k realm] f1 f2; or:\n\trcp [-PN | -PO] [-r] [-p] [-T] [-x] [-k realm] f1 ... fn d2\n");
 #else
     fputs("usage: rcp [-p] f1 f2; or: rcp [-rp] f1 ... fn d2\n", stderr);
 #endif
diff --git a/bsd/rcp.M b/bsd/rcp.M
index dcd206c..2e9b14f 100644
--- a/bsd/rcp.M
+++ b/bsd/rcp.M
@@ -22,7 +22,7 @@
 rcp \- remote file copy
 .SH SYNOPSIS
 .B rcp
-[\fB\-p\fP] [\fB\-x\fP] [\fB\-k\fP \fIrealm\fP ] [\fB-c\fP \fIccachefile\fP] [\fB-C\fP \fIconfigfile\fP] [\fB\-D\fP \fIport\fP]
+[\fB\-p\fP] [\fB\-x\fP] [\fB\-T\fP] [\fB\-k\fP \fIrealm\fP ] [\fB-c\fP \fIccachefile\fP] [\fB-C\fP \fIconfigfile\fP] [\fB\-D\fP \fIport\fP]
 [\fB\-N\fP]
 [\fB\-PN | \-PO\fP]
 .I file1 file2
@@ -128,6 +128,14 @@ remotely-running rcp process (started via the Kerberos remote shell
 daemon) which direction files are being sent.  These options should
 not be used by the user.  In particular, \fB-f\fP does \fBnot\fP mean
 that the user's Kerberos ticket should be forwarded!
+.TP
+.B \-T
+Checks that the received filenames match those requested on the command-line
+to prevent the remote end from sending unexpected or unwanted files.
+Because of differences in how various operating systems and shells interpret
+filename wildcards, these checks may cause wanted files to be rejected.
+This option disables these checks at the expense of fully trusting that
+the server will not send unexpected filenames.
 .PP
 .B Rcp
 handles third party copies, where neither source nor target files are on
-- 
2.30.0

openSUSE Build Service is sponsored by