Merge ~sergiodj/ubuntu/+source/openssh:lp1966591-ssh-keygen-permission-bionic into ubuntu/+source/openssh:ubuntu/devel

Proposed by Sergio Durigan Junior
Status: Superseded
Proposed branch: ~sergiodj/ubuntu/+source/openssh:lp1966591-ssh-keygen-permission-bionic
Merge into: ubuntu/+source/openssh:ubuntu/devel
Diff against target: 1411 lines (+1309/-0) (has conflicts)
13 files modified
debian/changelog (+75/-0)
debian/control (+8/-0)
debian/patches/0001-upstream-preserve-group-world-read-permission-on-kno.patch (+46/-0)
debian/patches/CVE-2018-15473.patch (+138/-0)
debian/patches/CVE-2018-20685.patch (+29/-0)
debian/patches/CVE-2019-6109-1.patch (+253/-0)
debian/patches/CVE-2019-6109-2.patch (+106/-0)
debian/patches/CVE-2019-6111-2.patch (+348/-0)
debian/patches/CVE-2019-6111.patch (+182/-0)
debian/patches/lp-1863930-Fix-logic-bug-in-sshd_exchange_identification.patch (+31/-0)
debian/patches/lp-1863930-unbreak-clients-that-advertise-protocol.patch (+31/-0)
debian/patches/regress-2020.patch (+44/-0)
debian/patches/series (+18/-0)
Conflict in debian/changelog
Conflict in debian/control
Conflict in debian/patches/series
Reviewer Review Type Date Requested Status
Canonical Server packageset reviewers Pending
Canonical Server Pending
Review via email: mp+418099@code.launchpad.net

Description of the change

This MP fixes bug #1966591 on Bionic.

From the SRU template:

When using "ssh-keygen -R" to remove a host from "known_hosts" the command changes permissions on the file. This can cause problems particularly when used on the global "known_hosts" file (/etc/ssh/ssh_known_hosts), because then only root can read it. Programs running non-interactively as non-root users suddenly fail to SSH and it's not immediately obvious why.

This bug has been fixed upstream (https://github.com/openssh/openssh-portable/commit/f2d84f1b3fa68d77c99238d4c645d0266fae2a74) and only impacts openssh on Bionic and Focal. The patch is simple and well contained.

The idea is to do a single SRU upload with this MP plus Athos' changes to fix bug #1903516.

There is a PPA with the proposed change here:

https://launchpad.net/~sergiodj/+archive/ubuntu/openssh-bugfix/+packages

autopkgtest is still running, but I don't expect any problems. I'll post the results when they're done.

To post a comment you must log in.

Unmerged commits

80f1bdb... by Sergio Durigan Junior

changelog for 1:7.6p1-4ubuntu0.7

828e903... by Sergio Durigan Junior

  * d/p/0001-upstream-preserve-group-world-read-permission-on-kno.patch:
    Preserve group/world read permissions on known_hosts. (LP: #1966591)

5488a2a... by Christian Ehrhardt 

1:7.6p1-4ubuntu0.6 (patches unapplied)

Imported using git-ubuntu import.

f271687... by Marc Deslauriers

1:7.6p1-4ubuntu0.5 (patches unapplied)

Imported using git-ubuntu import.

18afe7e... by Dimitri John Ledkov

1:7.6p1-4ubuntu0.4 (patches unapplied)

Imported using git-ubuntu import.

4ac6e76... by Marc Deslauriers

1:7.6p1-4ubuntu0.3 (patches unapplied)

Imported using git-ubuntu import.

844c653... by Marc Deslauriers

1:7.6p1-4ubuntu0.2 (patches unapplied)

Imported using git-ubuntu import.

95749f1... by Leonidas S. Barbosa

1:7.6p1-4ubuntu0.1 (patches unapplied)

Imported using git-ubuntu import.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/debian/changelog b/debian/changelog
index 9d6fadc..22a71c9 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,4 @@
1<<<<<<< debian/changelog
1openssh (1:8.9p1-3) unstable; urgency=medium2openssh (1:8.9p1-3) unstable; urgency=medium
23
3 * Allow ppoll_time64 in seccomp filter (closes: #1006445).4 * Allow ppoll_time64 in seccomp filter (closes: #1006445).
@@ -1532,6 +1533,80 @@ openssh (1:7.6p1-5) unstable; urgency=medium
1532 #894558).1533 #894558).
15331534
1534 -- Colin Watson <cjwatson@debian.org> Sun, 01 Apr 2018 21:37:19 +01001535 -- Colin Watson <cjwatson@debian.org> Sun, 01 Apr 2018 21:37:19 +0100
1536=======
1537openssh (1:7.6p1-4ubuntu0.7) bionic; urgency=medium
1538
1539 * d/p/0001-upstream-preserve-group-world-read-permission-on-kno.patch:
1540 Preserve group/world read permissions on known_hosts. (LP: #1966591)
1541
1542 -- Sergio Durigan Junior <sergio.durigan@canonical.com> Wed, 30 Mar 2022 19:04:23 -0400
1543
1544openssh (1:7.6p1-4ubuntu0.6) bionic; urgency=medium
1545
1546 * fix clients advertising version 1.99 (LP: #1863930)
1547 - d/p/lp-1863930-Fix-logic-bug-in-sshd_exchange_identification.patch
1548 - d/p/lp-1863930-unbreak-clients-that-advertise-protocol.patch
1549
1550 -- Christian Ehrhardt <christian.ehrhardt@canonical.com> Tue, 03 Mar 2020 07:47:02 +0100
1551
1552openssh (1:7.6p1-4ubuntu0.5) bionic-security; urgency=medium
1553
1554 * SECURITY REGRESSION: User enumeration issue (LP: #1934501)
1555 - debian/patches/CVE-2018-15473.patch: updated to fix bad patch
1556 backport.
1557
1558 -- Marc Deslauriers <marc.deslauriers@ubuntu.com> Wed, 11 Aug 2021 14:02:09 -0400
1559
1560openssh (1:7.6p1-4ubuntu0.4) bionic; urgency=medium
1561
1562 * Apply upstream patch to stop using 2020 as a future date in regress
1563 tests. LP: #1859013
1564
1565 -- Dimitri John Ledkov <xnox@ubuntu.com> Fri, 10 Jan 2020 00:00:50 +0000
1566
1567openssh (1:7.6p1-4ubuntu0.3) bionic-security; urgency=medium
1568
1569 * SECURITY UPDATE: Incomplete fix for CVE-2019-6111
1570 - debian/patches/CVE-2019-6111-2.patch: add another fix to the filename
1571 check in scp.c.
1572 - CVE-2019-6111
1573 * Fixed inverted CVE numbers in patch filenames and in previous
1574 changelog.
1575
1576 -- Marc Deslauriers <marc.deslauriers@ubuntu.com> Mon, 04 Mar 2019 07:17:51 -0500
1577
1578openssh (1:7.6p1-4ubuntu0.2) bionic-security; urgency=medium
1579
1580 * SECURITY UPDATE: access restrictions bypass in scp
1581 - debian/patches/CVE-2018-20685.patch: disallow empty filenames
1582 or ones that refer to the current directory in scp.c.
1583 - CVE-2018-20685
1584 * SECURITY UPDATE: scp client spoofing via object name
1585 - debian/patches/CVE-2019-6111.patch: make sure the filenames match
1586 the wildcard specified by the user, and add new flag to relax the new
1587 restrictions in scp.c, scp.1.
1588 - CVE-2019-6111
1589 * SECURITY UPDATE: scp client missing received object name validation
1590 - debian/patches/CVE-2019-6109-1.patch: sanitize scp filenames via
1591 snmprintf in atomicio.c, progressmeter.c, progressmeter.h,
1592 scp.c, sftp-client.c.
1593 - debian/patches/CVE-2019-6109-2.patch: force progressmeter updates in
1594 progressmeter.c, progressmeter.h, scp.c, sftp-client.c.
1595 - CVE-2019-6109
1596
1597 -- Marc Deslauriers <marc.deslauriers@ubuntu.com> Thu, 31 Jan 2019 08:58:34 -0500
1598
1599openssh (1:7.6p1-4ubuntu0.1) bionic-security; urgency=medium
1600
1601 [ Ryan Finnie ]
1602 * SECURITY UPDATE: OpenSSH User Enumeration Vulnerability (LP: #1794629)
1603 - debian/patches/CVE-2018-15473.patch: delay bailout for invalid
1604 authenticating user until after the packet containing the request
1605 has been fully parsed.
1606 - CVE-2018-15473
1607
1608 -- Leonidas S. Barbosa <leo.barbosa@canonical.com> Mon, 05 Nov 2018 08:51:29 -0300
1609>>>>>>> debian/changelog
15351610
1536openssh (1:7.6p1-4) unstable; urgency=medium1611openssh (1:7.6p1-4) unstable; urgency=medium
15371612
diff --git a/debian/control b/debian/control
index f9dc5f7..98035fb 100644
--- a/debian/control
+++ b/debian/control
@@ -1,9 +1,17 @@
1Source: openssh1Source: openssh
2Section: net2Section: net
3Priority: standard3Priority: standard
4<<<<<<< debian/control
4Maintainer: Debian OpenSSH Maintainers <debian-ssh@lists.debian.org>5Maintainer: Debian OpenSSH Maintainers <debian-ssh@lists.debian.org>
5Build-Depends: debhelper (>= 13.1~),6Build-Depends: debhelper (>= 13.1~),
6 debhelper-compat (= 13),7 debhelper-compat (= 13),
8=======
9Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
10XSBC-Original-Maintainer: Debian OpenSSH Maintainers <debian-ssh@lists.debian.org>
11Build-Depends: autotools-dev,
12 debhelper (>= 9.20160709~),
13 dh-autoreconf,
14>>>>>>> debian/control
7 dh-exec,15 dh-exec,
8 dh-runit (>= 2.8.8),16 dh-runit (>= 2.8.8),
9 dpkg-dev (>= 1.16.1~),17 dpkg-dev (>= 1.16.1~),
diff --git a/debian/patches/0001-upstream-preserve-group-world-read-permission-on-kno.patch b/debian/patches/0001-upstream-preserve-group-world-read-permission-on-kno.patch
10new file mode 10064418new file mode 100644
index 0000000..433ebfb
--- /dev/null
+++ b/debian/patches/0001-upstream-preserve-group-world-read-permission-on-kno.patch
@@ -0,0 +1,46 @@
1From: "djm@openbsd.org" <djm@openbsd.org>
2Date: Wed, 13 May 2020 09:55:57 +0000
3Subject: upstream: preserve group/world read permission on known_hosts
4
5file across runs of "ssh-keygen -Rf /path". The old behaviour was to remove
6all rights for group/other. bz#3146 ok dtucker@
7
8OpenBSD-Commit-ID: dc369d0e0b5dd826430c63fd5f4b269953448a8a
9
10Origin: backport, https://github.com/openssh/openssh-portable/commit/f2d84f1b3fa68d77c99238d4c645d0266fae2a74
11Bug: https://bugzilla.mindrot.org/show_bug.cgi?id=3146
12Bug-Ubuntu: https://bugs.launchpad.net/openssh/+bug/1966591
13Applied-Upstream: 8.4
14---
15 ssh-keygen.c | 4 ++++
16 1 file changed, 4 insertions(+)
17
18diff --git a/ssh-keygen.c b/ssh-keygen.c
19index 835f7d0..bfc5233 100644
20--- a/ssh-keygen.c
21+++ b/ssh-keygen.c
22@@ -1235,6 +1235,7 @@ do_known_hosts(struct passwd *pw, const char *name)
23 int r, fd, oerrno, inplace = 0;
24 struct known_hosts_ctx ctx;
25 u_int foreach_options;
26+ struct stat sb;
27
28 if (!have_identity) {
29 cp = tilde_expand_filename(_PATH_SSH_USER_HOSTFILE, pw->pw_uid);
30@@ -1244,6 +1245,8 @@ do_known_hosts(struct passwd *pw, const char *name)
31 free(cp);
32 have_identity = 1;
33 }
34+ if (stat(identity_file, &sb) != 0)
35+ fatal("Cannot stat %s: %s", identity_file, strerror(errno));
36
37 memset(&ctx, 0, sizeof(ctx));
38 ctx.out = stdout;
39@@ -1267,6 +1270,7 @@ do_known_hosts(struct passwd *pw, const char *name)
40 unlink(tmp);
41 fatal("fdopen: %s", strerror(oerrno));
42 }
43+ fchmod(fd, sb.st_mode & 0644);
44 inplace = 1;
45 }
46
diff --git a/debian/patches/CVE-2018-15473.patch b/debian/patches/CVE-2018-15473.patch
0new file mode 10064447new file mode 100644
index 0000000..f439e37
--- /dev/null
+++ b/debian/patches/CVE-2018-15473.patch
@@ -0,0 +1,138 @@
1Updated: 2021-08-11
2Backport of:
3
4From 779974d35b4859c07bc3cb8a12c74b43b0a7d1e0 Mon Sep 17 00:00:00 2001
5From: djm <djm@openbsd.org>
6Date: Tue, 31 Jul 2018 03:10:27 +0000
7Subject: [PATCH] =?UTF-8?q?delay=20bailout=20for=20invalid=20authenticatin?=
8 =?UTF-8?q?g=20user=20until=20after=20the=20packet=20containing=20the=20re?=
9 =?UTF-8?q?quest=20has=20been=20fully=20parsed.=20Reported=20by=20Dariusz?=
10 =?UTF-8?q?=20Tytko=20and=20Micha=C5=82=20Sajdak;=20ok=20deraadt?=
11MIME-Version: 1.0
12Content-Type: text/plain; charset=UTF-8
13Content-Transfer-Encoding: 8bit
14
15delay bailout for invalid authenticating user until after the packet
16containing the request has been fully parsed.
17
18---
19 auth2-gss.c | 9 ++++++---
20 auth2-hostbased.c | 9 +++++----
21 auth2-pubkey.c | 21 ++++++++++++++-------
22 3 files changed, 25 insertions(+), 14 deletions(-)
23
24--- a/auth2-gss.c
25+++ b/auth2-gss.c
26@@ -104,9 +104,6 @@ userauth_gssapi(struct ssh *ssh)
27 u_int len;
28 u_char *doid = NULL;
29
30- if (!authctxt->valid || authctxt->user == NULL)
31- return (0);
32-
33 mechs = packet_get_int();
34 if (mechs == 0) {
35 debug("Mechanism negotiation is not supported");
36@@ -137,6 +134,12 @@ userauth_gssapi(struct ssh *ssh)
37 return (0);
38 }
39
40+ if (!authctxt->valid || authctxt->user == NULL) {
41+ debug2("%s: disabled because of invalid user", __func__);
42+ free(doid);
43+ return (0);
44+ }
45+
46 if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, &goid)))) {
47 if (ctxt != NULL)
48 ssh_gssapi_delete_ctx(&ctxt);
49--- a/auth2-hostbased.c
50+++ b/auth2-hostbased.c
51@@ -67,10 +67,6 @@ userauth_hostbased(struct ssh *ssh)
52 size_t alen, blen, slen;
53 int r, pktype, authenticated = 0;
54
55- if (!authctxt->valid) {
56- debug2("%s: disabled because of invalid user", __func__);
57- return 0;
58- }
59 /* XXX use sshkey_froms() */
60 if ((r = sshpkt_get_cstring(ssh, &pkalg, &alen)) != 0 ||
61 (r = sshpkt_get_string(ssh, &pkblob, &blen)) != 0 ||
62@@ -118,6 +114,11 @@ userauth_hostbased(struct ssh *ssh)
63 goto done;
64 }
65
66+ if (!authctxt->valid || authctxt->user == NULL) {
67+ debug2("%s: disabled because of invalid user", __func__);
68+ goto done;
69+ }
70+
71 service = ssh->compat & SSH_BUG_HBSERVICE ? "ssh-userauth" :
72 authctxt->service;
73 if ((b = sshbuf_new()) == NULL)
74--- a/auth2-pubkey.c
75+++ b/auth2-pubkey.c
76@@ -77,18 +77,14 @@ static int
77 userauth_pubkey(struct ssh *ssh)
78 {
79 Authctxt *authctxt = ssh->authctxt;
80- struct sshbuf *b;
81+ struct sshbuf *b = NULL;
82 struct sshkey *key = NULL;
83- char *pkalg, *userstyle = NULL, *fp = NULL;
84- u_char *pkblob, *sig, have_sig;
85+ char *pkalg = NULL, *userstyle = NULL, *fp = NULL;
86+ u_char *pkblob = NULL, *sig = NULL, have_sig;
87 size_t blen, slen;
88 int r, pktype;
89 int authenticated = 0;
90
91- if (!authctxt->valid) {
92- debug2("%s: disabled because of invalid user", __func__);
93- return 0;
94- }
95 if ((r = sshpkt_get_u8(ssh, &have_sig)) != 0)
96 fatal("%s: sshpkt_get_u8 failed: %s", __func__, ssh_err(r));
97 if (ssh->compat & SSH_BUG_PKAUTH) {
98@@ -166,6 +162,12 @@ userauth_pubkey(struct ssh *ssh)
99 fatal("%s: sshbuf_put_string session id: %s",
100 __func__, ssh_err(r));
101 }
102+ if (!authctxt->valid || authctxt->user == NULL) {
103+ debug2("%s: disabled because of invalid user",
104+ __func__);
105+ sshbuf_free(b);
106+ goto done;
107+ }
108 /* reconstruct packet */
109 xasprintf(&userstyle, "%s%s%s", authctxt->user,
110 authctxt->style ? ":" : "",
111@@ -202,7 +204,6 @@ userauth_pubkey(struct ssh *ssh)
112 authenticated = 1;
113 }
114 sshbuf_free(b);
115- free(sig);
116 auth2_record_key(authctxt, authenticated, key);
117 } else {
118 debug("%s: test whether pkalg/pkblob are acceptable for %s %s",
119@@ -210,6 +211,11 @@ userauth_pubkey(struct ssh *ssh)
120 if ((r = sshpkt_get_end(ssh)) != 0)
121 fatal("%s: %s", __func__, ssh_err(r));
122
123+ if (!authctxt->valid || authctxt->user == NULL) {
124+ debug2("%s: disabled because of invalid user",
125+ __func__);
126+ goto done;
127+ }
128 /* XXX fake reply and always send PK_OK ? */
129 /*
130 * XXX this allows testing whether a user is allowed
131@@ -238,6 +244,7 @@ done:
132 free(pkalg);
133 free(pkblob);
134 free(fp);
135+ free(sig);
136 return authenticated;
137 }
138
diff --git a/debian/patches/CVE-2018-20685.patch b/debian/patches/CVE-2018-20685.patch
0new file mode 100644139new file mode 100644
index 0000000..0c2b94a
--- /dev/null
+++ b/debian/patches/CVE-2018-20685.patch
@@ -0,0 +1,29 @@
1Backport of:
2
3From 6010c0303a422a9c5fa8860c061bf7105eb7f8b2 Mon Sep 17 00:00:00 2001
4From: "djm@openbsd.org" <djm@openbsd.org>
5Date: Fri, 16 Nov 2018 03:03:10 +0000
6Subject: [PATCH] upstream: disallow empty incoming filename or ones that refer
7 to the
8
9current directory; based on report/patch from Harry Sintonen
10
11OpenBSD-Commit-ID: f27651b30eaee2df49540ab68d030865c04f6de9
12---
13 scp.c | 5 +++--
14 1 file changed, 3 insertions(+), 2 deletions(-)
15
16Index: openssh-7.6p1/scp.c
17===================================================================
18--- openssh-7.6p1.orig/scp.c 2019-01-31 08:56:55.553635620 -0500
19+++ openssh-7.6p1/scp.c 2019-01-31 08:56:55.553635620 -0500
20@@ -1073,7 +1073,8 @@ sink(int argc, char **argv)
21 SCREWUP("size out of range");
22 size = (off_t)ull;
23
24- if ((strchr(cp, '/') != NULL) || (strcmp(cp, "..") == 0)) {
25+ if (*cp == '\0' || strchr(cp, '/') != NULL ||
26+ strcmp(cp, ".") == 0 || strcmp(cp, "..") == 0) {
27 run_err("error: unexpected filename: %s", cp);
28 exit(1);
29 }
diff --git a/debian/patches/CVE-2019-6109-1.patch b/debian/patches/CVE-2019-6109-1.patch
0new file mode 10064430new file mode 100644
index 0000000..7da9698
--- /dev/null
+++ b/debian/patches/CVE-2019-6109-1.patch
@@ -0,0 +1,253 @@
1Backport of:
2
3From 8976f1c4b2721c26e878151f52bdf346dfe2d54c Mon Sep 17 00:00:00 2001
4From: "dtucker@openbsd.org" <dtucker@openbsd.org>
5Date: Wed, 23 Jan 2019 08:01:46 +0000
6Subject: [PATCH] upstream: Sanitize scp filenames via snmprintf. To do this we
7 move
8
9the progressmeter formatting outside of signal handler context and have the
10atomicio callback called for EINTR too. bz#2434 with contributions from djm
11and jjelen at redhat.com, ok djm@
12
13OpenBSD-Commit-ID: 1af61c1f70e4f3bd8ab140b9f1fa699481db57d8
14---
15 atomicio.c | 20 ++++++++++++++-----
16 progressmeter.c | 53 ++++++++++++++++++++++---------------------------
17 progressmeter.h | 3 ++-
18 scp.c | 3 ++-
19 sftp-client.c | 18 +++++++++--------
20 5 files changed, 53 insertions(+), 44 deletions(-)
21
22Index: openssh-7.6p1/atomicio.c
23===================================================================
24--- openssh-7.6p1.orig/atomicio.c 2019-01-31 08:58:23.885841566 -0500
25+++ openssh-7.6p1/atomicio.c 2019-01-31 08:58:23.881841557 -0500
26@@ -65,9 +65,14 @@ atomicio6(ssize_t (*f) (int, void *, siz
27 res = (f) (fd, s + pos, n - pos);
28 switch (res) {
29 case -1:
30- if (errno == EINTR)
31+ if (errno == EINTR) {
32+ /* possible SIGALARM, update callback */
33+ if (cb != NULL && cb(cb_arg, 0) == -1) {
34+ errno = EINTR;
35+ return pos;
36+ }
37 continue;
38- if (errno == EAGAIN || errno == EWOULDBLOCK) {
39+ } else if (errno == EAGAIN || errno == EWOULDBLOCK) {
40 #ifndef BROKEN_READ_COMPARISON
41 (void)poll(&pfd, 1, -1);
42 #endif
43@@ -122,9 +127,14 @@ atomiciov6(ssize_t (*f) (int, const stru
44 res = (f) (fd, iov, iovcnt);
45 switch (res) {
46 case -1:
47- if (errno == EINTR)
48+ if (errno == EINTR) {
49+ /* possible SIGALARM, update callback */
50+ if (cb != NULL && cb(cb_arg, 0) == -1) {
51+ errno = EINTR;
52+ return pos;
53+ }
54 continue;
55- if (errno == EAGAIN || errno == EWOULDBLOCK) {
56+ } else if (errno == EAGAIN || errno == EWOULDBLOCK) {
57 #ifndef BROKEN_READV_COMPARISON
58 (void)poll(&pfd, 1, -1);
59 #endif
60Index: openssh-7.6p1/progressmeter.c
61===================================================================
62--- openssh-7.6p1.orig/progressmeter.c 2019-01-31 08:58:23.885841566 -0500
63+++ openssh-7.6p1/progressmeter.c 2019-01-31 08:58:23.881841557 -0500
64@@ -31,6 +31,7 @@
65
66 #include <errno.h>
67 #include <signal.h>
68+#include <stdarg.h>
69 #include <stdio.h>
70 #include <string.h>
71 #include <time.h>
72@@ -39,6 +40,7 @@
73 #include "progressmeter.h"
74 #include "atomicio.h"
75 #include "misc.h"
76+#include "utf8.h"
77
78 #define DEFAULT_WINSIZE 80
79 #define MAX_WINSIZE 512
80@@ -61,7 +63,7 @@ static void setscreensize(void);
81 void refresh_progress_meter(void);
82
83 /* signal handler for updating the progress meter */
84-static void update_progress_meter(int);
85+static void sig_alarm(int);
86
87 static double start; /* start progress */
88 static double last_update; /* last progress update */
89@@ -74,6 +76,7 @@ static long stalled; /* how long we hav
90 static int bytes_per_second; /* current speed in bytes per second */
91 static int win_size; /* terminal window size */
92 static volatile sig_atomic_t win_resized; /* for window resizing */
93+static volatile sig_atomic_t alarm_fired;
94
95 /* units for format_size */
96 static const char unit[] = " KMGT";
97@@ -126,9 +129,17 @@ refresh_progress_meter(void)
98 off_t bytes_left;
99 int cur_speed;
100 int hours, minutes, seconds;
101- int i, len;
102 int file_len;
103
104+ if ((!alarm_fired && !win_resized) || !can_output())
105+ return;
106+ alarm_fired = 0;
107+
108+ if (win_resized) {
109+ setscreensize();
110+ win_resized = 0;
111+ }
112+
113 transferred = *counter - (cur_pos ? cur_pos : start_pos);
114 cur_pos = *counter;
115 now = monotime_double();
116@@ -158,16 +169,11 @@ refresh_progress_meter(void)
117
118 /* filename */
119 buf[0] = '\0';
120- file_len = win_size - 35;
121+ file_len = win_size - 36;
122 if (file_len > 0) {
123- len = snprintf(buf, file_len + 1, "\r%s", file);
124- if (len < 0)
125- len = 0;
126- if (len >= file_len + 1)
127- len = file_len;
128- for (i = len; i < file_len; i++)
129- buf[i] = ' ';
130- buf[file_len] = '\0';
131+ buf[0] = '\r';
132+ snmprintf(buf+1, sizeof(buf)-1 , &file_len, "%*s",
133+ file_len * -1, file);
134 }
135
136 /* percent of transfer done */
137@@ -228,22 +234,11 @@ refresh_progress_meter(void)
138
139 /*ARGSUSED*/
140 static void
141-update_progress_meter(int ignore)
142+sig_alarm(int ignore)
143 {
144- int save_errno;
145-
146- save_errno = errno;
147-
148- if (win_resized) {
149- setscreensize();
150- win_resized = 0;
151- }
152- if (can_output())
153- refresh_progress_meter();
154-
155- signal(SIGALRM, update_progress_meter);
156+ signal(SIGALRM, sig_alarm);
157+ alarm_fired = 1;
158 alarm(UPDATE_INTERVAL);
159- errno = save_errno;
160 }
161
162 void
163@@ -259,10 +254,9 @@ start_progress_meter(const char *f, off_
164 bytes_per_second = 0;
165
166 setscreensize();
167- if (can_output())
168- refresh_progress_meter();
169+ refresh_progress_meter();
170
171- signal(SIGALRM, update_progress_meter);
172+ signal(SIGALRM, sig_alarm);
173 signal(SIGWINCH, sig_winch);
174 alarm(UPDATE_INTERVAL);
175 }
176@@ -286,6 +280,7 @@ stop_progress_meter(void)
177 static void
178 sig_winch(int sig)
179 {
180+ signal(SIGWINCH, sig_winch);
181 win_resized = 1;
182 }
183
184Index: openssh-7.6p1/progressmeter.h
185===================================================================
186--- openssh-7.6p1.orig/progressmeter.h 2019-01-31 08:58:23.885841566 -0500
187+++ openssh-7.6p1/progressmeter.h 2019-01-31 08:58:23.881841557 -0500
188@@ -24,4 +24,5 @@
189 */
190
191 void start_progress_meter(const char *, off_t, off_t *);
192+void refresh_progress_meter(void);
193 void stop_progress_meter(void);
194Index: openssh-7.6p1/scp.c
195===================================================================
196--- openssh-7.6p1.orig/scp.c 2019-01-31 08:58:23.885841566 -0500
197+++ openssh-7.6p1/scp.c 2019-01-31 08:58:23.881841557 -0500
198@@ -580,6 +580,7 @@ scpio(void *_cnt, size_t s)
199 off_t *cnt = (off_t *)_cnt;
200
201 *cnt += s;
202+ refresh_progress_meter();
203 if (limit_kbps > 0)
204 bandwidth_limit(&bwlimit, s);
205 return 0;
206Index: openssh-7.6p1/sftp-client.c
207===================================================================
208--- openssh-7.6p1.orig/sftp-client.c 2019-01-31 08:58:23.885841566 -0500
209+++ openssh-7.6p1/sftp-client.c 2019-01-31 08:58:23.881841557 -0500
210@@ -101,7 +101,9 @@ sftpio(void *_bwlimit, size_t amount)
211 {
212 struct bwlimit *bwlimit = (struct bwlimit *)_bwlimit;
213
214- bandwidth_limit(bwlimit, amount);
215+ refresh_progress_meter();
216+ if (bwlimit != NULL)
217+ bandwidth_limit(bwlimit, amount);
218 return 0;
219 }
220
221@@ -121,8 +123,8 @@ send_msg(struct sftp_conn *conn, struct
222 iov[1].iov_base = (u_char *)sshbuf_ptr(m);
223 iov[1].iov_len = sshbuf_len(m);
224
225- if (atomiciov6(writev, conn->fd_out, iov, 2,
226- conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_out) !=
227+ if (atomiciov6(writev, conn->fd_out, iov, 2, sftpio,
228+ conn->limit_kbps > 0 ? &conn->bwlimit_out : NULL) !=
229 sshbuf_len(m) + sizeof(mlen))
230 fatal("Couldn't send packet: %s", strerror(errno));
231
232@@ -138,8 +140,8 @@ get_msg(struct sftp_conn *conn, struct s
233
234 if ((r = sshbuf_reserve(m, 4, &p)) != 0)
235 fatal("%s: buffer error: %s", __func__, ssh_err(r));
236- if (atomicio6(read, conn->fd_in, p, 4,
237- conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_in) != 4) {
238+ if (atomicio6(read, conn->fd_in, p, 4, sftpio,
239+ conn->limit_kbps > 0 ? &conn->bwlimit_in : NULL) != 4) {
240 if (errno == EPIPE || errno == ECONNRESET)
241 fatal("Connection closed");
242 else
243@@ -153,8 +155,8 @@ get_msg(struct sftp_conn *conn, struct s
244
245 if ((r = sshbuf_reserve(m, msg_len, &p)) != 0)
246 fatal("%s: buffer error: %s", __func__, ssh_err(r));
247- if (atomicio6(read, conn->fd_in, p, msg_len,
248- conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_in)
249+ if (atomicio6(read, conn->fd_in, p, msg_len, sftpio,
250+ conn->limit_kbps > 0 ? &conn->bwlimit_in : NULL)
251 != msg_len) {
252 if (errno == EPIPE)
253 fatal("Connection closed");
diff --git a/debian/patches/CVE-2019-6109-2.patch b/debian/patches/CVE-2019-6109-2.patch
0new file mode 100644254new file mode 100644
index 0000000..0cdc6d3
--- /dev/null
+++ b/debian/patches/CVE-2019-6109-2.patch
@@ -0,0 +1,106 @@
1Backport of:
2
3From bdc6c63c80b55bcbaa66b5fde31c1cb1d09a41eb Mon Sep 17 00:00:00 2001
4From: "dtucker@openbsd.org" <dtucker@openbsd.org>
5Date: Thu, 24 Jan 2019 16:52:17 +0000
6Subject: [PATCH] upstream: Have progressmeter force an update at the beginning
7 and
8
9end of each transfer. Fixes the problem recently introduces where very quick
10transfers do not display the progressmeter at all. Spotted by naddy@
11
12OpenBSD-Commit-ID: 68dc46c259e8fdd4f5db3ec2a130f8e4590a7a9a
13---
14 progressmeter.c | 13 +++++--------
15 progressmeter.h | 4 ++--
16 scp.c | 4 ++--
17 sftp-client.c | 4 ++--
18 4 files changed, 11 insertions(+), 14 deletions(-)
19
20Index: openssh-7.6p1/progressmeter.c
21===================================================================
22--- openssh-7.6p1.orig/progressmeter.c 2019-01-31 08:58:29.833855684 -0500
23+++ openssh-7.6p1/progressmeter.c 2019-01-31 08:58:29.833855684 -0500
24@@ -59,9 +59,6 @@ static void format_rate(char *, int, off
25 static void sig_winch(int);
26 static void setscreensize(void);
27
28-/* updates the progressmeter to reflect the current state of the transfer */
29-void refresh_progress_meter(void);
30-
31 /* signal handler for updating the progress meter */
32 static void sig_alarm(int);
33
34@@ -120,7 +117,7 @@ format_size(char *buf, int size, off_t b
35 }
36
37 void
38-refresh_progress_meter(void)
39+refresh_progress_meter(int force_update)
40 {
41 char buf[MAX_WINSIZE + 1];
42 off_t transferred;
43@@ -131,7 +128,7 @@ refresh_progress_meter(void)
44 int hours, minutes, seconds;
45 int file_len;
46
47- if ((!alarm_fired && !win_resized) || !can_output())
48+ if ((!force_update && !alarm_fired && !win_resized) || !can_output())
49 return;
50 alarm_fired = 0;
51
52@@ -254,7 +251,7 @@ start_progress_meter(const char *f, off_
53 bytes_per_second = 0;
54
55 setscreensize();
56- refresh_progress_meter();
57+ refresh_progress_meter(1);
58
59 signal(SIGALRM, sig_alarm);
60 signal(SIGWINCH, sig_winch);
61@@ -271,7 +268,7 @@ stop_progress_meter(void)
62
63 /* Ensure we complete the progress */
64 if (cur_pos != end_pos)
65- refresh_progress_meter();
66+ refresh_progress_meter(1);
67
68 atomicio(vwrite, STDOUT_FILENO, "\n", 1);
69 }
70Index: openssh-7.6p1/progressmeter.h
71===================================================================
72--- openssh-7.6p1.orig/progressmeter.h 2019-01-31 08:58:29.833855684 -0500
73+++ openssh-7.6p1/progressmeter.h 2019-01-31 08:58:29.833855684 -0500
74@@ -24,5 +24,5 @@
75 */
76
77 void start_progress_meter(const char *, off_t, off_t *);
78-void refresh_progress_meter(void);
79+void refresh_progress_meter(int);
80 void stop_progress_meter(void);
81Index: openssh-7.6p1/scp.c
82===================================================================
83--- openssh-7.6p1.orig/scp.c 2019-01-31 08:58:29.833855684 -0500
84+++ openssh-7.6p1/scp.c 2019-01-31 08:58:29.833855684 -0500
85@@ -580,7 +580,7 @@ scpio(void *_cnt, size_t s)
86 off_t *cnt = (off_t *)_cnt;
87
88 *cnt += s;
89- refresh_progress_meter();
90+ refresh_progress_meter(0);
91 if (limit_kbps > 0)
92 bandwidth_limit(&bwlimit, s);
93 return 0;
94Index: openssh-7.6p1/sftp-client.c
95===================================================================
96--- openssh-7.6p1.orig/sftp-client.c 2019-01-31 08:58:29.833855684 -0500
97+++ openssh-7.6p1/sftp-client.c 2019-01-31 08:58:29.833855684 -0500
98@@ -101,7 +101,7 @@ sftpio(void *_bwlimit, size_t amount)
99 {
100 struct bwlimit *bwlimit = (struct bwlimit *)_bwlimit;
101
102- refresh_progress_meter();
103+ refresh_progress_meter(0);
104 if (bwlimit != NULL)
105 bandwidth_limit(bwlimit, amount);
106 return 0;
diff --git a/debian/patches/CVE-2019-6111-2.patch b/debian/patches/CVE-2019-6111-2.patch
0new file mode 100644107new file mode 100644
index 0000000..21aa8fc
--- /dev/null
+++ b/debian/patches/CVE-2019-6111-2.patch
@@ -0,0 +1,348 @@
1From 3d896c157c722bc47adca51a58dca859225b5874 Mon Sep 17 00:00:00 2001
2From: "djm@openbsd.org" <djm@openbsd.org>
3Date: Sun, 10 Feb 2019 11:15:52 +0000
4Subject: [PATCH] upstream: when checking that filenames sent by the server
5 side
6
7match what the client requested, be prepared to handle shell-style brace
8alternations, e.g. "{foo,bar}".
9
10"looks good to me" millert@ + in snaps for the last week courtesy
11deraadt@
12
13OpenBSD-Commit-ID: 3b1ce7639b0b25b2248e3a30f561a548f6815f3e
14---
15 scp.c | 282 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---
16 1 file changed, 270 insertions(+), 12 deletions(-)
17
18Index: openssh-7.6p1/scp.c
19===================================================================
20--- openssh-7.6p1.orig/scp.c 2019-03-04 07:17:32.294099797 -0500
21+++ openssh-7.6p1/scp.c 2019-03-04 07:17:32.294099797 -0500
22@@ -604,6 +604,253 @@ do_times(int fd, int verb, const struct
23 return (response());
24 }
25
26+/* Appends a string to an array; returns 0 on success, -1 on alloc failure */
27+static int
28+append(char *cp, char ***ap, size_t *np)
29+{
30+ char **tmp;
31+
32+ if ((tmp = reallocarray(*ap, *np + 1, sizeof(*tmp))) == NULL)
33+ return -1;
34+ tmp[(*np)] = cp;
35+ (*np)++;
36+ *ap = tmp;
37+ return 0;
38+}
39+
40+/*
41+ * Finds the start and end of the first brace pair in the pattern.
42+ * returns 0 on success or -1 for invalid patterns.
43+ */
44+static int
45+find_brace(const char *pattern, int *startp, int *endp)
46+{
47+ int i;
48+ int in_bracket, brace_level;
49+
50+ *startp = *endp = -1;
51+ in_bracket = brace_level = 0;
52+ for (i = 0; i < INT_MAX && *endp < 0 && pattern[i] != '\0'; i++) {
53+ switch (pattern[i]) {
54+ case '\\':
55+ /* skip next character */
56+ if (pattern[i + 1] != '\0')
57+ i++;
58+ break;
59+ case '[':
60+ in_bracket = 1;
61+ break;
62+ case ']':
63+ in_bracket = 0;
64+ break;
65+ case '{':
66+ if (in_bracket)
67+ break;
68+ if (pattern[i + 1] == '}') {
69+ /* Protect a single {}, for find(1), like csh */
70+ i++; /* skip */
71+ break;
72+ }
73+ if (*startp == -1)
74+ *startp = i;
75+ brace_level++;
76+ break;
77+ case '}':
78+ if (in_bracket)
79+ break;
80+ if (*startp < 0) {
81+ /* Unbalanced brace */
82+ return -1;
83+ }
84+ if (--brace_level <= 0)
85+ *endp = i;
86+ break;
87+ }
88+ }
89+ /* unbalanced brackets/braces */
90+ if (*endp < 0 && (*startp >= 0 || in_bracket))
91+ return -1;
92+ return 0;
93+}
94+
95+/*
96+ * Assembles and records a successfully-expanded pattern, returns -1 on
97+ * alloc failure.
98+ */
99+static int
100+emit_expansion(const char *pattern, int brace_start, int brace_end,
101+ int sel_start, int sel_end, char ***patternsp, size_t *npatternsp)
102+{
103+ char *cp;
104+ int o = 0, tail_len = strlen(pattern + brace_end + 1);
105+
106+ if ((cp = malloc(brace_start + (sel_end - sel_start) +
107+ tail_len + 1)) == NULL)
108+ return -1;
109+
110+ /* Pattern before initial brace */
111+ if (brace_start > 0) {
112+ memcpy(cp, pattern, brace_start);
113+ o = brace_start;
114+ }
115+ /* Current braced selection */
116+ if (sel_end - sel_start > 0) {
117+ memcpy(cp + o, pattern + sel_start,
118+ sel_end - sel_start);
119+ o += sel_end - sel_start;
120+ }
121+ /* Remainder of pattern after closing brace */
122+ if (tail_len > 0) {
123+ memcpy(cp + o, pattern + brace_end + 1, tail_len);
124+ o += tail_len;
125+ }
126+ cp[o] = '\0';
127+ if (append(cp, patternsp, npatternsp) != 0) {
128+ free(cp);
129+ return -1;
130+ }
131+ return 0;
132+}
133+
134+/*
135+ * Expand the first encountered brace in pattern, appending the expanded
136+ * patterns it yielded to the *patternsp array.
137+ *
138+ * Returns 0 on success or -1 on allocation failure.
139+ *
140+ * Signals whether expansion was performed via *expanded and whether
141+ * pattern was invalid via *invalid.
142+ */
143+static int
144+brace_expand_one(const char *pattern, char ***patternsp, size_t *npatternsp,
145+ int *expanded, int *invalid)
146+{
147+ int i;
148+ int in_bracket, brace_start, brace_end, brace_level;
149+ int sel_start, sel_end;
150+
151+ *invalid = *expanded = 0;
152+
153+ if (find_brace(pattern, &brace_start, &brace_end) != 0) {
154+ *invalid = 1;
155+ return 0;
156+ } else if (brace_start == -1)
157+ return 0;
158+
159+ in_bracket = brace_level = 0;
160+ for (i = sel_start = brace_start + 1; i < brace_end; i++) {
161+ switch (pattern[i]) {
162+ case '{':
163+ if (in_bracket)
164+ break;
165+ brace_level++;
166+ break;
167+ case '}':
168+ if (in_bracket)
169+ break;
170+ brace_level--;
171+ break;
172+ case '[':
173+ in_bracket = 1;
174+ break;
175+ case ']':
176+ in_bracket = 0;
177+ break;
178+ case '\\':
179+ if (i < brace_end - 1)
180+ i++; /* skip */
181+ break;
182+ }
183+ if (pattern[i] == ',' || i == brace_end - 1) {
184+ if (in_bracket || brace_level > 0)
185+ continue;
186+ /* End of a selection, emit an expanded pattern */
187+
188+ /* Adjust end index for last selection */
189+ sel_end = (i == brace_end - 1) ? brace_end : i;
190+ if (emit_expansion(pattern, brace_start, brace_end,
191+ sel_start, sel_end, patternsp, npatternsp) != 0)
192+ return -1;
193+ /* move on to the next selection */
194+ sel_start = i + 1;
195+ continue;
196+ }
197+ }
198+ if (in_bracket || brace_level > 0) {
199+ *invalid = 1;
200+ return 0;
201+ }
202+ /* success */
203+ *expanded = 1;
204+ return 0;
205+}
206+
207+/* Expand braces from pattern. Returns 0 on success, -1 on failure */
208+static int
209+brace_expand(const char *pattern, char ***patternsp, size_t *npatternsp)
210+{
211+ char *cp, *cp2, **active = NULL, **done = NULL;
212+ size_t i, nactive = 0, ndone = 0;
213+ int ret = -1, invalid = 0, expanded = 0;
214+
215+ *patternsp = NULL;
216+ *npatternsp = 0;
217+
218+ /* Start the worklist with the original pattern */
219+ if ((cp = strdup(pattern)) == NULL)
220+ return -1;
221+ if (append(cp, &active, &nactive) != 0) {
222+ free(cp);
223+ return -1;
224+ }
225+ while (nactive > 0) {
226+ cp = active[nactive - 1];
227+ nactive--;
228+ if (brace_expand_one(cp, &active, &nactive,
229+ &expanded, &invalid) == -1) {
230+ free(cp);
231+ goto fail;
232+ }
233+ if (invalid)
234+ fatal("%s: invalid brace pattern \"%s\"", __func__, cp);
235+ if (expanded) {
236+ /*
237+ * Current entry expanded to new entries on the
238+ * active list; discard the progenitor pattern.
239+ */
240+ free(cp);
241+ continue;
242+ }
243+ /*
244+ * Pattern did not expand; append the finename component to
245+ * the completed list
246+ */
247+ if ((cp2 = strrchr(cp, '/')) != NULL)
248+ *cp2++ = '\0';
249+ else
250+ cp2 = cp;
251+ if (append(xstrdup(cp2), &done, &ndone) != 0) {
252+ free(cp);
253+ goto fail;
254+ }
255+ free(cp);
256+ }
257+ /* success */
258+ *patternsp = done;
259+ *npatternsp = ndone;
260+ done = NULL;
261+ ndone = 0;
262+ ret = 0;
263+ fail:
264+ for (i = 0; i < nactive; i++)
265+ free(active[i]);
266+ free(active);
267+ for (i = 0; i < ndone; i++)
268+ free(done[i]);
269+ free(done);
270+ return ret;
271+}
272+
273 void
274 toremote(char *targ, int argc, char **argv)
275 {
276@@ -959,7 +1206,8 @@ sink(int argc, char **argv, const char *
277 unsigned long long ull;
278 int setimes, targisdir, wrerrno = 0;
279 char ch, *cp, *np, *targ, *why, *vect[1], buf[2048], visbuf[2048];
280- char *src_copy = NULL, *restrict_pattern = NULL;
281+ char **patterns = NULL;
282+ size_t n, npatterns = 0;
283 struct timeval tv[2];
284
285 #define atime tv[0]
286@@ -989,16 +1237,13 @@ sink(int argc, char **argv, const char *
287 * Prepare to try to restrict incoming filenames to match
288 * the requested destination file glob.
289 */
290- if ((src_copy = strdup(src)) == NULL)
291- fatal("strdup failed");
292- if ((restrict_pattern = strrchr(src_copy, '/')) != NULL) {
293- *restrict_pattern++ = '\0';
294- }
295+ if (brace_expand(src, &patterns, &npatterns) != 0)
296+ fatal("%s: could not expand pattern", __func__);
297 }
298 for (first = 1;; first = 0) {
299 cp = buf;
300 if (atomicio(read, remin, cp, 1) != 1)
301- return;
302+ goto done;
303 if (*cp++ == '\n')
304 SCREWUP("unexpected <newline>");
305 do {
306@@ -1024,7 +1269,7 @@ sink(int argc, char **argv, const char *
307 }
308 if (buf[0] == 'E') {
309 (void) atomicio(vwrite, remout, "", 1);
310- return;
311+ goto done;
312 }
313 if (ch == '\n')
314 *--cp = 0;
315@@ -1097,9 +1342,14 @@ sink(int argc, char **argv, const char *
316 run_err("error: unexpected filename: %s", cp);
317 exit(1);
318 }
319- if (restrict_pattern != NULL &&
320- fnmatch(restrict_pattern, cp, 0) != 0)
321- SCREWUP("filename does not match request");
322+ if (npatterns > 0) {
323+ for (n = 0; n < npatterns; n++) {
324+ if (fnmatch(patterns[n], cp, 0) == 0)
325+ break;
326+ }
327+ if (n >= npatterns)
328+ SCREWUP("filename does not match request");
329+ }
330 if (targisdir) {
331 static char *namebuf;
332 static size_t cursize;
333@@ -1258,7 +1508,15 @@ bad: run_err("%s: %s", np, strerror(er
334 break;
335 }
336 }
337+done:
338+ for (n = 0; n < npatterns; n++)
339+ free(patterns[n]);
340+ free(patterns);
341+ return;
342 screwup:
343+ for (n = 0; n < npatterns; n++)
344+ free(patterns[n]);
345+ free(patterns);
346 run_err("protocol error: %s", why);
347 exit(1);
348 }
diff --git a/debian/patches/CVE-2019-6111.patch b/debian/patches/CVE-2019-6111.patch
0new file mode 100644349new file mode 100644
index 0000000..72b8bde
--- /dev/null
+++ b/debian/patches/CVE-2019-6111.patch
@@ -0,0 +1,182 @@
1Backport of:
2
3From 391ffc4b9d31fa1f4ad566499fef9176ff8a07dc Mon Sep 17 00:00:00 2001
4From: "djm@openbsd.org" <djm@openbsd.org>
5Date: Sat, 26 Jan 2019 22:41:28 +0000
6Subject: [PATCH] upstream: check in scp client that filenames sent during
7
8remote->local directory copies satisfy the wildcard specified by the user.
9
10This checking provides some protection against a malicious server
11sending unexpected filenames, but it comes at a risk of rejecting wanted
12files due to differences between client and server wildcard expansion rules.
13
14For this reason, this also adds a new -T flag to disable the check.
15
16reported by Harry Sintonen
17fix approach suggested by markus@;
18has been in snaps for ~1wk courtesy deraadt@
19
20OpenBSD-Commit-ID: 00f44b50d2be8e321973f3c6d014260f8f7a8eda
21---
22 scp.1 | 16 +++++++++++++---
23 scp.c | 39 ++++++++++++++++++++++++++++++---------
24 2 files changed, 43 insertions(+), 12 deletions(-)
25
26Index: openssh-7.6p1/scp.1
27===================================================================
28--- openssh-7.6p1.orig/scp.1 2019-01-31 08:57:08.113664456 -0500
29+++ openssh-7.6p1/scp.1 2019-01-31 08:57:44.625749147 -0500
30@@ -19,7 +19,7 @@
31 .Sh SYNOPSIS
32 .Nm scp
33 .Bk -words
34-.Op Fl 346BCpqrv
35+.Op Fl 346BCpqrTv
36 .Op Fl c Ar cipher
37 .Op Fl F Ar ssh_config
38 .Op Fl i Ar identity_file
39@@ -202,6 +202,16 @@ to use for the encrypted connection.
40 The program must understand
41 .Xr ssh 1
42 options.
43+.It Fl T
44+Disable strict filename checking.
45+By default when copying files from a remote host to a local directory
46+.Nm
47+checks that the received filenames match those requested on the command-line
48+to prevent the remote end from sending unexpected or unwanted files.
49+Because of differences in how various operating systems and shells interpret
50+filename wildcards, these checks may cause wanted files to be rejected.
51+This option disables these checks at the expense of fully trusting that
52+the server will not send unexpected filenames.
53 .It Fl v
54 Verbose mode.
55 Causes
56Index: openssh-7.6p1/scp.c
57===================================================================
58--- openssh-7.6p1.orig/scp.c 2019-01-31 08:57:08.113664456 -0500
59+++ openssh-7.6p1/scp.c 2019-01-31 08:57:08.109664446 -0500
60@@ -94,6 +94,7 @@
61 #include <dirent.h>
62 #include <errno.h>
63 #include <fcntl.h>
64+#include <fnmatch.h>
65 #include <limits.h>
66 #include <locale.h>
67 #include <pwd.h>
68@@ -365,14 +366,14 @@ void verifydir(char *);
69 struct passwd *pwd;
70 uid_t userid;
71 int errs, remin, remout;
72-int pflag, iamremote, iamrecursive, targetshouldbedirectory;
73+int Tflag, pflag, iamremote, iamrecursive, targetshouldbedirectory;
74
75 #define CMDNEEDS 64
76 char cmd[CMDNEEDS]; /* must hold "rcp -r -p -d\0" */
77
78 int response(void);
79 void rsource(char *, struct stat *);
80-void sink(int, char *[]);
81+void sink(int, char *[], const char *);
82 void source(int, char *[]);
83 void tolocal(int, char *[]);
84 void toremote(char *, int, char *[]);
85@@ -409,8 +410,9 @@ main(int argc, char **argv)
86 addargs(&args, "-oPermitLocalCommand=no");
87 addargs(&args, "-oClearAllForwardings=yes");
88
89- fflag = tflag = 0;
90- while ((ch = getopt(argc, argv, "dfl:prtvBCc:i:P:q12346S:o:F:")) != -1)
91+ fflag = Tflag = tflag = 0;
92+ while ((ch = getopt(argc, argv,
93+ "dfl:prtTvBCc:i:P:q12346S:o:F:")) != -1) {
94 switch (ch) {
95 /* User-visible flags. */
96 case '1':
97@@ -490,9 +492,13 @@ main(int argc, char **argv)
98 setmode(0, O_BINARY);
99 #endif
100 break;
101+ case 'T':
102+ Tflag = 1;
103+ break;
104 default:
105 usage();
106 }
107+ }
108 argc -= optind;
109 argv += optind;
110
111@@ -523,7 +529,7 @@ main(int argc, char **argv)
112 }
113 if (tflag) {
114 /* Receive data. */
115- sink(argc, argv);
116+ sink(argc, argv, NULL);
117 exit(errs != 0);
118 }
119 if (argc < 2)
120@@ -763,7 +769,7 @@ tolocal(int argc, char **argv)
121 continue;
122 }
123 free(bp);
124- sink(1, argv + argc - 1);
125+ sink(1, argv + argc - 1, src);
126 (void) close(remin);
127 remin = remout = -1;
128 }
129@@ -936,7 +942,7 @@ rsource(char *name, struct stat *statp)
130 (sizeof(type) != 4 && sizeof(type) != 8))
131
132 void
133-sink(int argc, char **argv)
134+sink(int argc, char **argv, const char *src)
135 {
136 static BUF buffer;
137 struct stat stb;
138@@ -952,6 +958,7 @@ sink(int argc, char **argv)
139 unsigned long long ull;
140 int setimes, targisdir, wrerrno = 0;
141 char ch, *cp, *np, *targ, *why, *vect[1], buf[2048], visbuf[2048];
142+ char *src_copy = NULL, *restrict_pattern = NULL;
143 struct timeval tv[2];
144
145 #define atime tv[0]
146@@ -976,6 +983,17 @@ sink(int argc, char **argv)
147 (void) atomicio(vwrite, remout, "", 1);
148 if (stat(targ, &stb) == 0 && S_ISDIR(stb.st_mode))
149 targisdir = 1;
150+ if (src != NULL && !iamrecursive && !Tflag) {
151+ /*
152+ * Prepare to try to restrict incoming filenames to match
153+ * the requested destination file glob.
154+ */
155+ if ((src_copy = strdup(src)) == NULL)
156+ fatal("strdup failed");
157+ if ((restrict_pattern = strrchr(src_copy, '/')) != NULL) {
158+ *restrict_pattern++ = '\0';
159+ }
160+ }
161 for (first = 1;; first = 0) {
162 cp = buf;
163 if (atomicio(read, remin, cp, 1) != 1)
164@@ -1078,6 +1096,9 @@ sink(int argc, char **argv)
165 run_err("error: unexpected filename: %s", cp);
166 exit(1);
167 }
168+ if (restrict_pattern != NULL &&
169+ fnmatch(restrict_pattern, cp, 0) != 0)
170+ SCREWUP("filename does not match request");
171 if (targisdir) {
172 static char *namebuf;
173 static size_t cursize;
174@@ -1115,7 +1136,7 @@ sink(int argc, char **argv)
175 goto bad;
176 }
177 vect[0] = xstrdup(np);
178- sink(1, vect);
179+ sink(1, vect, src);
180 if (setimes) {
181 setimes = 0;
182 if (utimes(vect[0], tv) < 0)
diff --git a/debian/patches/lp-1863930-Fix-logic-bug-in-sshd_exchange_identification.patch b/debian/patches/lp-1863930-Fix-logic-bug-in-sshd_exchange_identification.patch
0new file mode 100644183new file mode 100644
index 0000000..5f9fc47
--- /dev/null
+++ b/debian/patches/lp-1863930-Fix-logic-bug-in-sshd_exchange_identification.patch
@@ -0,0 +1,31 @@
1From c9c1bba06ad1c7cad8548549a68c071bd807af60 Mon Sep 17 00:00:00 2001
2From: "stsp@openbsd.org" <stsp@openbsd.org>
3Date: Tue, 23 Jan 2018 20:00:58 +0000
4Subject: [PATCH] upstream commit
5
6Fix a logic bug in sshd_exchange_identification which
7prevented clients using major protocol version 2 from connecting to the
8server. ok millert@
9
10OpenBSD-Commit-ID: 8668dec04586e27f1c0eb039ef1feb93d80a5ee9
11
12Backport-Note: dropped the no-op file header change
13Origin: backport, https://anongit.mindrot.org/openssh.git/commit/?id=c9c1bba06
14Bug-Ubuntu: https://bugs.launchpad.net/bugs/1863930
15Last-Update: 2020-03-03
16
17---
18 sshd.c | 4 ++--
19 1 file changed, 2 insertions(+), 2 deletions(-)
20
21--- a/sshd.c
22+++ b/sshd.c
23@@ -465,7 +465,7 @@ sshd_exchange_identification(struct ssh
24 chop(server_version_string);
25 debug("Local version string %.200s", server_version_string);
26
27- if (remote_major != 2 ||
28+ if (remote_major != 2 &&
29 !(remote_major == 1 && remote_minor == 99)) {
30 s = "Protocol major versions differ.\n";
31 (void) atomicio(vwrite, sock_out, s, strlen(s));
diff --git a/debian/patches/lp-1863930-unbreak-clients-that-advertise-protocol.patch b/debian/patches/lp-1863930-unbreak-clients-that-advertise-protocol.patch
0new file mode 10064432new file mode 100644
index 0000000..dbb035d
--- /dev/null
+++ b/debian/patches/lp-1863930-unbreak-clients-that-advertise-protocol.patch
@@ -0,0 +1,31 @@
1From 9e9c4a7e57b96ab29fe6d7545ed09d2e5bddbdec Mon Sep 17 00:00:00 2001
2From: "djm@openbsd.org" <djm@openbsd.org>
3Date: Tue, 23 Jan 2018 05:12:12 +0000
4Subject: [PATCH] upstream commit
5
6unbreak support for clients that advertise a protocol
7version of "1.99" (indicating both v2 and v1 support). Busted by me during
8SSHv1 purge in r1.358; bz2810, ok dtucker
9
10OpenBSD-Commit-ID: e8f9c2bee11afc16c872bb79d6abe9c555bd0e4b
11
12Backport-Note: dropped the no-op file header change
13Origin: backport, https://anongit.mindrot.org/openssh.git/commit/?id=9e9c4a7e5
14Bug-Ubuntu: https://bugs.launchpad.net/bugs/1863930
15Last-Update: 2020-03-03
16
17---
18 sshd.c | 4 ++--
19 1 file changed, 2 insertions(+), 2 deletions(-)
20
21--- a/sshd.c
22+++ b/sshd.c
23@@ -466,7 +466,7 @@ sshd_exchange_identification(struct ssh
24 debug("Local version string %.200s", server_version_string);
25
26 if (remote_major != 2 ||
27- (remote_major == 1 && remote_minor != 99)) {
28+ !(remote_major == 1 && remote_minor == 99)) {
29 s = "Protocol major versions differ.\n";
30 (void) atomicio(vwrite, sock_out, s, strlen(s));
31 close(sock_in);
diff --git a/debian/patches/regress-2020.patch b/debian/patches/regress-2020.patch
0new file mode 10064432new file mode 100644
index 0000000..b46e0df
--- /dev/null
+++ b/debian/patches/regress-2020.patch
@@ -0,0 +1,44 @@
1From df3ad29af495185aa9b051028ae94b965a4b1659 Mon Sep 17 00:00:00 2001
2From: "djm@openbsd.org" <djm@openbsd.org>
3Date: Fri, 3 Jan 2020 03:02:26 +0000
4Subject: upstream: what bozo decided to use 2020 as a future date in a regress
5
6test?
7
8OpenBSD-Regress-ID: 3b953df5a7e14081ff6cf495d4e8d40e153cbc3a
9
10Origin: upstream, https://anongit.mindrot.org/openssh.git/commit/?id=ff31f15773ee173502eec4d7861ec56f26bba381
11Last-Update: 2020-01-09
12
13Patch-Name: regress-2020.patch
14---
15 regress/cert-hostkey.sh | 2 +-
16 regress/cert-userkey.sh | 2 +-
17 2 files changed, 2 insertions(+), 2 deletions(-)
18
19diff --git a/regress/cert-hostkey.sh b/regress/cert-hostkey.sh
20index 86ea62504..844adabcc 100644
21--- a/regress/cert-hostkey.sh
22+++ b/regress/cert-hostkey.sh
23@@ -252,7 +252,7 @@ test_one() {
24 test_one "user-certificate" failure "-n $HOSTS"
25 test_one "empty principals" success "-h"
26 test_one "wrong principals" failure "-h -n foo"
27-test_one "cert not yet valid" failure "-h -V20200101:20300101"
28+test_one "cert not yet valid" failure "-h -V20300101:20320101"
29 test_one "cert expired" failure "-h -V19800101:19900101"
30 test_one "cert valid interval" success "-h -V-1w:+2w"
31 test_one "cert has constraints" failure "-h -Oforce-command=false"
32diff --git a/regress/cert-userkey.sh b/regress/cert-userkey.sh
33index 38c14a698..5cd02fc3f 100644
34--- a/regress/cert-userkey.sh
35+++ b/regress/cert-userkey.sh
36@@ -338,7 +338,7 @@ test_one() {
37 test_one "correct principal" success "-n ${USER}"
38 test_one "host-certificate" failure "-n ${USER} -h"
39 test_one "wrong principals" failure "-n foo"
40-test_one "cert not yet valid" failure "-n ${USER} -V20200101:20300101"
41+test_one "cert not yet valid" failure "-n ${USER} -V20300101:20320101"
42 test_one "cert expired" failure "-n ${USER} -V19800101:19900101"
43 test_one "cert valid interval" success "-n ${USER} -V-1w:+2w"
44 test_one "wrong source-address" failure "-n ${USER} -Osource-address=10.0.0.0/8"
diff --git a/debian/patches/series b/debian/patches/series
index 580b919..d8dd5ae 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -21,8 +21,26 @@ gnome-ssh-askpass2-icon.patch
21systemd-readiness.patch21systemd-readiness.patch
22debian-config.patch22debian-config.patch
23restore-authorized_keys2.patch23restore-authorized_keys2.patch
24<<<<<<< debian/patches/series
24revert-ipqos-defaults.patch25revert-ipqos-defaults.patch
25maxhostnamelen.patch26maxhostnamelen.patch
26conch-ssh-rsa.patch27conch-ssh-rsa.patch
27improve-zero-call-used-regs-detection.patch28improve-zero-call-used-regs-detection.patch
28sandbox-ppoll_time64.patch29sandbox-ppoll_time64.patch
30=======
31seccomp-s390-flock-ipc.patch
32seccomp-getuid-geteuid.patch
33seccomp-s390-ioctl-ep11-crypto.patch
34permitopen-argument-handling.patch
35fix-regress-putty-transfer.patch
36CVE-2018-15473.patch
37CVE-2018-20685.patch
38CVE-2019-6111.patch
39CVE-2019-6109-1.patch
40CVE-2019-6109-2.patch
41CVE-2019-6111-2.patch
42regress-2020.patch
43lp-1863930-unbreak-clients-that-advertise-protocol.patch
44lp-1863930-Fix-logic-bug-in-sshd_exchange_identification.patch
450001-upstream-preserve-group-world-read-permission-on-kno.patch
46>>>>>>> debian/patches/series

Subscribers

People subscribed via source and target branches