You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

187 lines
5.3 KiB

  1. From 125924e47db3713a85a70e0f8d6c23818d2ea054 Mon Sep 17 00:00:00 2001
  2. From: "djm@openbsd.org" <djm@openbsd.org>
  3. Date: Sat, 26 Jan 2019 22:41:28 +0000
  4. Subject: upstream: check in scp client that filenames sent during
  5. remote->local directory copies satisfy the wildcard specified by the user.
  6. This checking provides some protection against a malicious server
  7. sending unexpected filenames, but it comes at a risk of rejecting wanted
  8. files due to differences between client and server wildcard expansion rules.
  9. For this reason, this also adds a new -T flag to disable the check.
  10. reported by Harry Sintonen
  11. fix approach suggested by markus@;
  12. has been in snaps for ~1wk courtesy deraadt@
  13. OpenBSD-Commit-ID: 00f44b50d2be8e321973f3c6d014260f8f7a8eda
  14. CVE-2019-6111
  15. Origin: backport, https://anongit.mindrot.org/openssh.git/commit/?id=391ffc4b9d31fa1f4ad566499fef9176ff8a07dc
  16. Last-Update: 2019-02-08
  17. Patch-Name: check-filenames-in-scp-client.patch
  18. ---
  19. scp.1 | 12 +++++++++++-
  20. scp.c | 37 +++++++++++++++++++++++++++++--------
  21. 2 files changed, 40 insertions(+), 9 deletions(-)
  22. diff --git a/scp.1 b/scp.1
  23. index 0e5cc1b2d..397e77091 100644
  24. --- a/scp.1
  25. +++ b/scp.1
  26. @@ -18,7 +18,7 @@
  27. .Nd secure copy (remote file copy program)
  28. .Sh SYNOPSIS
  29. .Nm scp
  30. -.Op Fl 346BCpqrv
  31. +.Op Fl 346BCpqrTv
  32. .Op Fl c Ar cipher
  33. .Op Fl F Ar ssh_config
  34. .Op Fl i Ar identity_file
  35. @@ -208,6 +208,16 @@ to use for the encrypted connection.
  36. The program must understand
  37. .Xr ssh 1
  38. options.
  39. +.It Fl T
  40. +Disable strict filename checking.
  41. +By default when copying files from a remote host to a local directory
  42. +.Nm
  43. +checks that the received filenames match those requested on the command-line
  44. +to prevent the remote end from sending unexpected or unwanted files.
  45. +Because of differences in how various operating systems and shells interpret
  46. +filename wildcards, these checks may cause wanted files to be rejected.
  47. +This option disables these checks at the expense of fully trusting that
  48. +the server will not send unexpected filenames.
  49. .It Fl v
  50. Verbose mode.
  51. Causes
  52. diff --git a/scp.c b/scp.c
  53. index 1971c80cd..035037bcc 100644
  54. --- a/scp.c
  55. +++ b/scp.c
  56. @@ -94,6 +94,7 @@
  57. #include <dirent.h>
  58. #include <errno.h>
  59. #include <fcntl.h>
  60. +#include <fnmatch.h>
  61. #include <limits.h>
  62. #include <locale.h>
  63. #include <pwd.h>
  64. @@ -383,14 +384,14 @@ void verifydir(char *);
  65. struct passwd *pwd;
  66. uid_t userid;
  67. int errs, remin, remout;
  68. -int pflag, iamremote, iamrecursive, targetshouldbedirectory;
  69. +int Tflag, pflag, iamremote, iamrecursive, targetshouldbedirectory;
  70. #define CMDNEEDS 64
  71. char cmd[CMDNEEDS]; /* must hold "rcp -r -p -d\0" */
  72. int response(void);
  73. void rsource(char *, struct stat *);
  74. -void sink(int, char *[]);
  75. +void sink(int, char *[], const char *);
  76. void source(int, char *[]);
  77. void tolocal(int, char *[]);
  78. void toremote(int, char *[]);
  79. @@ -429,8 +430,9 @@ main(int argc, char **argv)
  80. addargs(&args, "-oRemoteCommand=none");
  81. addargs(&args, "-oRequestTTY=no");
  82. - fflag = tflag = 0;
  83. - while ((ch = getopt(argc, argv, "dfl:prtvBCc:i:P:q12346S:o:F:")) != -1)
  84. + fflag = Tflag = tflag = 0;
  85. + while ((ch = getopt(argc, argv,
  86. + "dfl:prtTvBCc:i:P:q12346S:o:F:")) != -1) {
  87. switch (ch) {
  88. /* User-visible flags. */
  89. case '1':
  90. @@ -509,9 +511,13 @@ main(int argc, char **argv)
  91. setmode(0, O_BINARY);
  92. #endif
  93. break;
  94. + case 'T':
  95. + Tflag = 1;
  96. + break;
  97. default:
  98. usage();
  99. }
  100. + }
  101. argc -= optind;
  102. argv += optind;
  103. @@ -542,7 +548,7 @@ main(int argc, char **argv)
  104. }
  105. if (tflag) {
  106. /* Receive data. */
  107. - sink(argc, argv);
  108. + sink(argc, argv, NULL);
  109. exit(errs != 0);
  110. }
  111. if (argc < 2)
  112. @@ -800,7 +806,7 @@ tolocal(int argc, char **argv)
  113. continue;
  114. }
  115. free(bp);
  116. - sink(1, argv + argc - 1);
  117. + sink(1, argv + argc - 1, src);
  118. (void) close(remin);
  119. remin = remout = -1;
  120. }
  121. @@ -976,7 +982,7 @@ rsource(char *name, struct stat *statp)
  122. (sizeof(type) != 4 && sizeof(type) != 8))
  123. void
  124. -sink(int argc, char **argv)
  125. +sink(int argc, char **argv, const char *src)
  126. {
  127. static BUF buffer;
  128. struct stat stb;
  129. @@ -992,6 +998,7 @@ sink(int argc, char **argv)
  130. unsigned long long ull;
  131. int setimes, targisdir, wrerrno = 0;
  132. char ch, *cp, *np, *targ, *why, *vect[1], buf[2048], visbuf[2048];
  133. + char *src_copy = NULL, *restrict_pattern = NULL;
  134. struct timeval tv[2];
  135. #define atime tv[0]
  136. @@ -1016,6 +1023,17 @@ sink(int argc, char **argv)
  137. (void) atomicio(vwrite, remout, "", 1);
  138. if (stat(targ, &stb) == 0 && S_ISDIR(stb.st_mode))
  139. targisdir = 1;
  140. + if (src != NULL && !iamrecursive && !Tflag) {
  141. + /*
  142. + * Prepare to try to restrict incoming filenames to match
  143. + * the requested destination file glob.
  144. + */
  145. + if ((src_copy = strdup(src)) == NULL)
  146. + fatal("strdup failed");
  147. + if ((restrict_pattern = strrchr(src_copy, '/')) != NULL) {
  148. + *restrict_pattern++ = '\0';
  149. + }
  150. + }
  151. for (first = 1;; first = 0) {
  152. cp = buf;
  153. if (atomicio(read, remin, cp, 1) != 1)
  154. @@ -1120,6 +1138,9 @@ sink(int argc, char **argv)
  155. run_err("error: unexpected filename: %s", cp);
  156. exit(1);
  157. }
  158. + if (restrict_pattern != NULL &&
  159. + fnmatch(restrict_pattern, cp, 0) != 0)
  160. + SCREWUP("filename does not match request");
  161. if (targisdir) {
  162. static char *namebuf;
  163. static size_t cursize;
  164. @@ -1157,7 +1178,7 @@ sink(int argc, char **argv)
  165. goto bad;
  166. }
  167. vect[0] = xstrdup(np);
  168. - sink(1, vect);
  169. + sink(1, vect, src);
  170. if (setimes) {
  171. setimes = 0;
  172. if (utimes(vect[0], tv) < 0)