openssh: update to 8.0p1

Signed-off-by: Peter Wagner <tripolar@gmx.at>
This commit is contained in:
Peter Wagner 2019-04-20 18:08:52 +02:00
parent f1772130fe
commit 626a4315a9
10 changed files with 3 additions and 1159 deletions

View file

@ -8,14 +8,14 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=openssh PKG_NAME:=openssh
PKG_VERSION:=7.9p1 PKG_VERSION:=8.0p1
PKG_RELEASE:=7 PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/ \ PKG_SOURCE_URL:=https://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/ \
https://ftp.spline.de/pub/OpenBSD/OpenSSH/portable/ \ https://ftp.spline.de/pub/OpenBSD/OpenSSH/portable/ \
https://anorien.csc.warwick.ac.uk/pub/OpenBSD/OpenSSH/portable/ https://anorien.csc.warwick.ac.uk/pub/OpenBSD/OpenSSH/portable/
PKG_HASH:=6b4b3ba2253d84ed3771c8050728d597c91cfce898713beb7b64a305b6f11aad PKG_HASH:=bd943879e69498e8031eb6b7f44d08cdc37d59a7ab689aa0b437320c3481fd68
PKG_LICENSE:=BSD ISC PKG_LICENSE:=BSD ISC
PKG_LICENSE_FILES:=LICENCE PKG_LICENSE_FILES:=LICENCE
@ -130,8 +130,6 @@ endef
define Package/openssh-sftp-server define Package/openssh-sftp-server
$(call Package/openssh/Default) $(call Package/openssh/Default)
TITLE+= SFTP server TITLE+= SFTP server
# Strip dependencies to avoid pulling in OpenSSL etc.
DEPENDS:=
endef endef
define Package/openssh-sftp-server/description define Package/openssh-sftp-server/description
@ -197,10 +195,6 @@ TARGET_LDFLAGS += -lpthread
endif endif
define Build/Compile define Build/Compile
$(MAKE) -C $(PKG_BUILD_DIR) \
DESTDIR="$(PKG_INSTALL_DIR)" \
LIBS="" \
sftp-server
$(MAKE) -C $(PKG_BUILD_DIR) \ $(MAKE) -C $(PKG_BUILD_DIR) \
DESTDIR="$(PKG_INSTALL_DIR)" \ DESTDIR="$(PKG_INSTALL_DIR)" \
STRIP_OPT="" \ STRIP_OPT="" \

View file

@ -1,33 +0,0 @@
From 6010c0303a422a9c5fa8860c061bf7105eb7f8b2 Mon Sep 17 00:00:00 2001
From: "djm@openbsd.org" <djm@openbsd.org>
Date: Fri, 16 Nov 2018 03:03:10 +0000
Subject: [PATCH] upstream: disallow empty incoming filename or ones that refer
to the
current directory; based on report/patch from Harry Sintonen
OpenBSD-Commit-ID: f27651b30eaee2df49540ab68d030865c04f6de9
---
scp.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/scp.c b/scp.c
index 60682c687..4f3fdcd3d 100644
--- a/scp.c
+++ b/scp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: scp.c,v 1.197 2018/06/01 04:31:48 dtucker Exp $ */
+/* $OpenBSD: scp.c,v 1.198 2018/11/16 03:03:10 djm Exp $ */
/*
* scp - secure remote copy. This is basically patched BSD rcp which
* uses ssh to do the data transfer (instead of using rcmd).
@@ -1106,7 +1106,8 @@ sink(int argc, char **argv)
SCREWUP("size out of range");
size = (off_t)ull;
- if ((strchr(cp, '/') != NULL) || (strcmp(cp, "..") == 0)) {
+ if (*cp == '\0' || strchr(cp, '/') != NULL ||
+ strcmp(cp, ".") == 0 || strcmp(cp, "..") == 0) {
run_err("error: unexpected filename: %s", cp);
exit(1);
}

View file

@ -1,82 +0,0 @@
From 5e021158aa22cc64da4fca1618ee0bfd2d031049 Mon Sep 17 00:00:00 2001
From: "djm@openbsd.org" <djm@openbsd.org>
Date: Fri, 16 Nov 2018 02:43:56 +0000
Subject: upstream: fix bug in HostbasedAcceptedKeyTypes and
PubkeyAcceptedKeyTypes options. If only RSA-SHA2 siganture types were
specified, then authentication would always fail for RSA keys as the monitor
checks only the base key (not the signature algorithm) type against
*AcceptedKeyTypes. bz#2746; reported by Jakub Jelen; ok dtucker
OpenBSD-Commit-ID: 117bc3dc54578dbdb515a1d3732988cb5b00461b
Origin: upstream, https://anongit.mindrot.org/openssh.git/commit/?id=cd9467318b56e6e93ff9575c906ff8350af9b8a2
Last-Update: 2019-02-28
Patch-Name: fix-key-type-check.patch
---
monitor.c | 39 ++++++++++++++++++++++++++++++++++-----
1 file changed, 34 insertions(+), 5 deletions(-)
diff --git a/monitor.c b/monitor.c
index 08fddabd7..037d6d333 100644
--- a/monitor.c
+++ b/monitor.c
@@ -892,6 +892,35 @@ mm_answer_authrole(int sock, struct sshbuf *m)
return (0);
}
+/*
+ * Check that the key type appears in the supplied pattern list, ignoring
+ * mismatches in the signature algorithm. (Signature algorithm checks are
+ * performed in the unprivileged authentication code).
+ * Returns 1 on success, 0 otherwise.
+ */
+static int
+key_base_type_match(const char *method, const struct sshkey *key,
+ const char *list)
+{
+ char *s, *l, *ol = xstrdup(list);
+ int found = 0;
+
+ l = ol;
+ for ((s = strsep(&l, ",")); s && *s != '\0'; (s = strsep(&l, ","))) {
+ if (sshkey_type_from_name(s) == key->type) {
+ found = 1;
+ break;
+ }
+ }
+ if (!found) {
+ error("%s key type %s is not in permitted list %s", method,
+ sshkey_ssh_name(key), list);
+ }
+
+ free(ol);
+ return found;
+}
+
int
mm_answer_authpassword(int sock, struct sshbuf *m)
{
@@ -1197,8 +1226,8 @@ mm_answer_keyallowed(int sock, struct sshbuf *m)
break;
if (auth2_key_already_used(authctxt, key))
break;
- if (match_pattern_list(sshkey_ssh_name(key),
- options.pubkey_key_types, 0) != 1)
+ if (!key_base_type_match(auth_method, key,
+ options.pubkey_key_types))
break;
allowed = user_key_allowed(ssh, authctxt->pw, key,
pubkey_auth_attempt, &opts);
@@ -1209,8 +1238,8 @@ mm_answer_keyallowed(int sock, struct sshbuf *m)
break;
if (auth2_key_already_used(authctxt, key))
break;
- if (match_pattern_list(sshkey_ssh_name(key),
- options.hostbased_key_types, 0) != 1)
+ if (!key_base_type_match(auth_method, key,
+ options.hostbased_key_types))
break;
allowed = hostbased_key_allowed(authctxt->pw,
cuser, chost, key);

View file

@ -1,39 +0,0 @@
From d94226d4fcefbc398c5583e12b5d07ca33884ba4 Mon Sep 17 00:00:00 2001
From: "djm@openbsd.org" <djm@openbsd.org>
Date: Thu, 27 Dec 2018 23:02:11 +0000
Subject: upstream: Request RSA-SHA2 signatures for
rsa-sha2-{256|512}-cert-v01@openssh.com cert algorithms; ok markus@
OpenBSD-Commit-ID: afc6f7ca216ccd821656d1c911d2a3deed685033
Origin: upstream, https://anongit.mindrot.org/openssh.git/commit/?id=f429c1b2ef631f2855e51a790cf71761d752bbca
Bug: https://bugzilla.mindrot.org/show_bug.cgi?id=2944
Bug-Debian: https://bugs.debian.org/923419
Last-Update: 2019-02-28
Patch-Name: request-rsa-sha2-cert-signatures.patch
---
authfd.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/authfd.c b/authfd.c
index ecdd869ab..62cbf8c19 100644
--- a/authfd.c
+++ b/authfd.c
@@ -327,10 +327,12 @@ ssh_free_identitylist(struct ssh_identitylist *idl)
static u_int
agent_encode_alg(const struct sshkey *key, const char *alg)
{
- if (alg != NULL && key->type == KEY_RSA) {
- if (strcmp(alg, "rsa-sha2-256") == 0)
+ if (alg != NULL && sshkey_type_plain(key->type) == KEY_RSA) {
+ if (strcmp(alg, "rsa-sha2-256") == 0 ||
+ strcmp(alg, "rsa-sha2-256-cert-v01@openssh.com") == 0)
return SSH_AGENT_RSA_SHA2_256;
- else if (strcmp(alg, "rsa-sha2-512") == 0)
+ if (strcmp(alg, "rsa-sha2-512") == 0 ||
+ strcmp(alg, "rsa-sha2-512-cert-v01@openssh.com") == 0)
return SSH_AGENT_RSA_SHA2_512;
}
return 0;

View file

@ -1,258 +0,0 @@
From 11b88754cadcad0ba79b4ffcc127223248dccb54 Mon Sep 17 00:00:00 2001
From: "dtucker@openbsd.org" <dtucker@openbsd.org>
Date: Wed, 23 Jan 2019 08:01:46 +0000
Subject: upstream: Sanitize scp filenames via snmprintf. To do this we move
the progressmeter formatting outside of signal handler context and have the
atomicio callback called for EINTR too. bz#2434 with contributions from djm
and jjelen at redhat.com, ok djm@
OpenBSD-Commit-ID: 1af61c1f70e4f3bd8ab140b9f1fa699481db57d8
CVE-2019-6109
Origin: backport, https://anongit.mindrot.org/openssh.git/commit/?id=8976f1c4b2721c26e878151f52bdf346dfe2d54c
Bug-Debian: https://bugs.debian.org/793412
Last-Update: 2019-02-08
Patch-Name: sanitize-scp-filenames-via-snmprintf.patch
---
atomicio.c | 20 ++++++++++++++-----
progressmeter.c | 53 ++++++++++++++++++++++---------------------------
progressmeter.h | 3 ++-
scp.c | 1 +
sftp-client.c | 16 ++++++++-------
5 files changed, 51 insertions(+), 42 deletions(-)
diff --git a/atomicio.c b/atomicio.c
index f854a06f5..d91bd7621 100644
--- a/atomicio.c
+++ b/atomicio.c
@@ -65,9 +65,14 @@ atomicio6(ssize_t (*f) (int, void *, size_t), int fd, void *_s, size_t n,
res = (f) (fd, s + pos, n - pos);
switch (res) {
case -1:
- if (errno == EINTR)
+ if (errno == EINTR) {
+ /* possible SIGALARM, update callback */
+ if (cb != NULL && cb(cb_arg, 0) == -1) {
+ errno = EINTR;
+ return pos;
+ }
continue;
- if (errno == EAGAIN || errno == EWOULDBLOCK) {
+ } else if (errno == EAGAIN || errno == EWOULDBLOCK) {
#ifndef BROKEN_READ_COMPARISON
(void)poll(&pfd, 1, -1);
#endif
@@ -122,9 +127,14 @@ atomiciov6(ssize_t (*f) (int, const struct iovec *, int), int fd,
res = (f) (fd, iov, iovcnt);
switch (res) {
case -1:
- if (errno == EINTR)
+ if (errno == EINTR) {
+ /* possible SIGALARM, update callback */
+ if (cb != NULL && cb(cb_arg, 0) == -1) {
+ errno = EINTR;
+ return pos;
+ }
continue;
- if (errno == EAGAIN || errno == EWOULDBLOCK) {
+ } else if (errno == EAGAIN || errno == EWOULDBLOCK) {
#ifndef BROKEN_READV_COMPARISON
(void)poll(&pfd, 1, -1);
#endif
diff --git a/progressmeter.c b/progressmeter.c
index fe9bf52e4..add462dde 100644
--- a/progressmeter.c
+++ b/progressmeter.c
@@ -31,6 +31,7 @@
#include <errno.h>
#include <signal.h>
+#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
@@ -39,6 +40,7 @@
#include "progressmeter.h"
#include "atomicio.h"
#include "misc.h"
+#include "utf8.h"
#define DEFAULT_WINSIZE 80
#define MAX_WINSIZE 512
@@ -61,7 +63,7 @@ static void setscreensize(void);
void refresh_progress_meter(void);
/* signal handler for updating the progress meter */
-static void update_progress_meter(int);
+static void sig_alarm(int);
static double start; /* start progress */
static double last_update; /* last progress update */
@@ -74,6 +76,7 @@ static long stalled; /* how long we have been stalled */
static int bytes_per_second; /* current speed in bytes per second */
static int win_size; /* terminal window size */
static volatile sig_atomic_t win_resized; /* for window resizing */
+static volatile sig_atomic_t alarm_fired;
/* units for format_size */
static const char unit[] = " KMGT";
@@ -126,9 +129,17 @@ refresh_progress_meter(void)
off_t bytes_left;
int cur_speed;
int hours, minutes, seconds;
- int i, len;
int file_len;
+ if ((!alarm_fired && !win_resized) || !can_output())
+ return;
+ alarm_fired = 0;
+
+ if (win_resized) {
+ setscreensize();
+ win_resized = 0;
+ }
+
transferred = *counter - (cur_pos ? cur_pos : start_pos);
cur_pos = *counter;
now = monotime_double();
@@ -158,16 +169,11 @@ refresh_progress_meter(void)
/* filename */
buf[0] = '\0';
- file_len = win_size - 35;
+ file_len = win_size - 36;
if (file_len > 0) {
- len = snprintf(buf, file_len + 1, "\r%s", file);
- if (len < 0)
- len = 0;
- if (len >= file_len + 1)
- len = file_len;
- for (i = len; i < file_len; i++)
- buf[i] = ' ';
- buf[file_len] = '\0';
+ buf[0] = '\r';
+ snmprintf(buf+1, sizeof(buf)-1 , &file_len, "%*s",
+ file_len * -1, file);
}
/* percent of transfer done */
@@ -228,22 +234,11 @@ refresh_progress_meter(void)
/*ARGSUSED*/
static void
-update_progress_meter(int ignore)
+sig_alarm(int ignore)
{
- int save_errno;
-
- save_errno = errno;
-
- if (win_resized) {
- setscreensize();
- win_resized = 0;
- }
- if (can_output())
- refresh_progress_meter();
-
- signal(SIGALRM, update_progress_meter);
+ signal(SIGALRM, sig_alarm);
+ alarm_fired = 1;
alarm(UPDATE_INTERVAL);
- errno = save_errno;
}
void
@@ -259,10 +254,9 @@ start_progress_meter(const char *f, off_t filesize, off_t *ctr)
bytes_per_second = 0;
setscreensize();
- if (can_output())
- refresh_progress_meter();
+ refresh_progress_meter();
- signal(SIGALRM, update_progress_meter);
+ signal(SIGALRM, sig_alarm);
signal(SIGWINCH, sig_winch);
alarm(UPDATE_INTERVAL);
}
@@ -286,6 +280,7 @@ stop_progress_meter(void)
static void
sig_winch(int sig)
{
+ signal(SIGWINCH, sig_winch);
win_resized = 1;
}
diff --git a/progressmeter.h b/progressmeter.h
index bf179dca6..8f6678060 100644
--- a/progressmeter.h
+++ b/progressmeter.h
@@ -24,4 +24,5 @@
*/
void start_progress_meter(const char *, off_t, off_t *);
+void refresh_progress_meter(void);
void stop_progress_meter(void);
diff --git a/scp.c b/scp.c
index 7163d33dc..80308573c 100644
--- a/scp.c
+++ b/scp.c
@@ -593,6 +593,7 @@ scpio(void *_cnt, size_t s)
off_t *cnt = (off_t *)_cnt;
*cnt += s;
+ refresh_progress_meter();
if (limit_kbps > 0)
bandwidth_limit(&bwlimit, s);
return 0;
diff --git a/sftp-client.c b/sftp-client.c
index 4986d6d8d..2bc698f86 100644
--- a/sftp-client.c
+++ b/sftp-client.c
@@ -101,7 +101,9 @@ sftpio(void *_bwlimit, size_t amount)
{
struct bwlimit *bwlimit = (struct bwlimit *)_bwlimit;
- bandwidth_limit(bwlimit, amount);
+ refresh_progress_meter();
+ if (bwlimit != NULL)
+ bandwidth_limit(bwlimit, amount);
return 0;
}
@@ -121,8 +123,8 @@ send_msg(struct sftp_conn *conn, struct sshbuf *m)
iov[1].iov_base = (u_char *)sshbuf_ptr(m);
iov[1].iov_len = sshbuf_len(m);
- if (atomiciov6(writev, conn->fd_out, iov, 2,
- conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_out) !=
+ if (atomiciov6(writev, conn->fd_out, iov, 2, sftpio,
+ conn->limit_kbps > 0 ? &conn->bwlimit_out : NULL) !=
sshbuf_len(m) + sizeof(mlen))
fatal("Couldn't send packet: %s", strerror(errno));
@@ -138,8 +140,8 @@ get_msg_extended(struct sftp_conn *conn, struct sshbuf *m, int initial)
if ((r = sshbuf_reserve(m, 4, &p)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
- if (atomicio6(read, conn->fd_in, p, 4,
- conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_in) != 4) {
+ if (atomicio6(read, conn->fd_in, p, 4, sftpio,
+ conn->limit_kbps > 0 ? &conn->bwlimit_in : NULL) != 4) {
if (errno == EPIPE || errno == ECONNRESET)
fatal("Connection closed");
else
@@ -157,8 +159,8 @@ get_msg_extended(struct sftp_conn *conn, struct sshbuf *m, int initial)
if ((r = sshbuf_reserve(m, msg_len, &p)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
- if (atomicio6(read, conn->fd_in, p, msg_len,
- conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_in)
+ if (atomicio6(read, conn->fd_in, p, msg_len, sftpio,
+ conn->limit_kbps > 0 ? &conn->bwlimit_in : NULL)
!= msg_len) {
if (errno == EPIPE)
fatal("Connection closed");

View file

@ -1,108 +0,0 @@
From 2a8f710447442e9a03e71c022859112ec2d77d17 Mon Sep 17 00:00:00 2001
From: "dtucker@openbsd.org" <dtucker@openbsd.org>
Date: Thu, 24 Jan 2019 16:52:17 +0000
Subject: upstream: Have progressmeter force an update at the beginning and
end of each transfer. Fixes the problem recently introduces where very quick
transfers do not display the progressmeter at all. Spotted by naddy@
OpenBSD-Commit-ID: 68dc46c259e8fdd4f5db3ec2a130f8e4590a7a9a
Origin: upstream, https://anongit.mindrot.org/openssh.git/commit/?id=bdc6c63c80b55bcbaa66b5fde31c1cb1d09a41eb
Last-Update: 2019-02-08
Patch-Name: have-progressmeter-force-update-at-beginning-and-end-transfer.patch
---
progressmeter.c | 13 +++++--------
progressmeter.h | 4 ++--
scp.c | 2 +-
sftp-client.c | 2 +-
4 files changed, 9 insertions(+), 12 deletions(-)
diff --git a/progressmeter.c b/progressmeter.c
index add462dde..e385c1254 100644
--- a/progressmeter.c
+++ b/progressmeter.c
@@ -59,9 +59,6 @@ static void format_rate(char *, int, off_t);
static void sig_winch(int);
static void setscreensize(void);
-/* updates the progressmeter to reflect the current state of the transfer */
-void refresh_progress_meter(void);
-
/* signal handler for updating the progress meter */
static void sig_alarm(int);
@@ -120,7 +117,7 @@ format_size(char *buf, int size, off_t bytes)
}
void
-refresh_progress_meter(void)
+refresh_progress_meter(int force_update)
{
char buf[MAX_WINSIZE + 1];
off_t transferred;
@@ -131,7 +128,7 @@ refresh_progress_meter(void)
int hours, minutes, seconds;
int file_len;
- if ((!alarm_fired && !win_resized) || !can_output())
+ if ((!force_update && !alarm_fired && !win_resized) || !can_output())
return;
alarm_fired = 0;
@@ -254,7 +251,7 @@ start_progress_meter(const char *f, off_t filesize, off_t *ctr)
bytes_per_second = 0;
setscreensize();
- refresh_progress_meter();
+ refresh_progress_meter(1);
signal(SIGALRM, sig_alarm);
signal(SIGWINCH, sig_winch);
@@ -271,7 +268,7 @@ stop_progress_meter(void)
/* Ensure we complete the progress */
if (cur_pos != end_pos)
- refresh_progress_meter();
+ refresh_progress_meter(1);
atomicio(vwrite, STDOUT_FILENO, "\n", 1);
}
diff --git a/progressmeter.h b/progressmeter.h
index 8f6678060..1703ea75b 100644
--- a/progressmeter.h
+++ b/progressmeter.h
@@ -24,5 +24,5 @@
*/
void start_progress_meter(const char *, off_t, off_t *);
-void refresh_progress_meter(void);
+void refresh_progress_meter(int);
void stop_progress_meter(void);
diff --git a/scp.c b/scp.c
index 80308573c..1971c80cd 100644
--- a/scp.c
+++ b/scp.c
@@ -593,7 +593,7 @@ scpio(void *_cnt, size_t s)
off_t *cnt = (off_t *)_cnt;
*cnt += s;
- refresh_progress_meter();
+ refresh_progress_meter(0);
if (limit_kbps > 0)
bandwidth_limit(&bwlimit, s);
return 0;
diff --git a/sftp-client.c b/sftp-client.c
index 2bc698f86..cf2887a40 100644
--- a/sftp-client.c
+++ b/sftp-client.c
@@ -101,7 +101,7 @@ sftpio(void *_bwlimit, size_t amount)
{
struct bwlimit *bwlimit = (struct bwlimit *)_bwlimit;
- refresh_progress_meter();
+ refresh_progress_meter(0);
if (bwlimit != NULL)
bandwidth_limit(bwlimit, amount);
return 0;

View file

@ -1,187 +0,0 @@
From 125924e47db3713a85a70e0f8d6c23818d2ea054 Mon Sep 17 00:00:00 2001
From: "djm@openbsd.org" <djm@openbsd.org>
Date: Sat, 26 Jan 2019 22:41:28 +0000
Subject: upstream: check in scp client that filenames sent during
remote->local directory copies satisfy the wildcard specified by the user.
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.
reported by Harry Sintonen
fix approach suggested by markus@;
has been in snaps for ~1wk courtesy deraadt@
OpenBSD-Commit-ID: 00f44b50d2be8e321973f3c6d014260f8f7a8eda
CVE-2019-6111
Origin: backport, https://anongit.mindrot.org/openssh.git/commit/?id=391ffc4b9d31fa1f4ad566499fef9176ff8a07dc
Last-Update: 2019-02-08
Patch-Name: check-filenames-in-scp-client.patch
---
scp.1 | 12 +++++++++++-
scp.c | 37 +++++++++++++++++++++++++++++--------
2 files changed, 40 insertions(+), 9 deletions(-)
diff --git a/scp.1 b/scp.1
index 0e5cc1b2d..397e77091 100644
--- a/scp.1
+++ b/scp.1
@@ -18,7 +18,7 @@
.Nd secure copy (remote file copy program)
.Sh SYNOPSIS
.Nm scp
-.Op Fl 346BCpqrv
+.Op Fl 346BCpqrTv
.Op Fl c Ar cipher
.Op Fl F Ar ssh_config
.Op Fl i Ar identity_file
@@ -208,6 +208,16 @@ to use for the encrypted connection.
The program must understand
.Xr ssh 1
options.
+.It Fl T
+Disable strict filename checking.
+By default when copying files from a remote host to a local directory
+.Nm
+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.
.It Fl v
Verbose mode.
Causes
diff --git a/scp.c b/scp.c
index 1971c80cd..035037bcc 100644
--- a/scp.c
+++ b/scp.c
@@ -94,6 +94,7 @@
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
+#include <fnmatch.h>
#include <limits.h>
#include <locale.h>
#include <pwd.h>
@@ -383,14 +384,14 @@ void verifydir(char *);
struct passwd *pwd;
uid_t userid;
int errs, remin, remout;
-int pflag, iamremote, iamrecursive, targetshouldbedirectory;
+int Tflag, pflag, iamremote, iamrecursive, targetshouldbedirectory;
#define CMDNEEDS 64
char cmd[CMDNEEDS]; /* must hold "rcp -r -p -d\0" */
int response(void);
void rsource(char *, struct stat *);
-void sink(int, char *[]);
+void sink(int, char *[], const char *);
void source(int, char *[]);
void tolocal(int, char *[]);
void toremote(int, char *[]);
@@ -429,8 +430,9 @@ main(int argc, char **argv)
addargs(&args, "-oRemoteCommand=none");
addargs(&args, "-oRequestTTY=no");
- fflag = tflag = 0;
- while ((ch = getopt(argc, argv, "dfl:prtvBCc:i:P:q12346S:o:F:")) != -1)
+ fflag = Tflag = tflag = 0;
+ while ((ch = getopt(argc, argv,
+ "dfl:prtTvBCc:i:P:q12346S:o:F:")) != -1) {
switch (ch) {
/* User-visible flags. */
case '1':
@@ -509,9 +511,13 @@ main(int argc, char **argv)
setmode(0, O_BINARY);
#endif
break;
+ case 'T':
+ Tflag = 1;
+ break;
default:
usage();
}
+ }
argc -= optind;
argv += optind;
@@ -542,7 +548,7 @@ main(int argc, char **argv)
}
if (tflag) {
/* Receive data. */
- sink(argc, argv);
+ sink(argc, argv, NULL);
exit(errs != 0);
}
if (argc < 2)
@@ -800,7 +806,7 @@ tolocal(int argc, char **argv)
continue;
}
free(bp);
- sink(1, argv + argc - 1);
+ sink(1, argv + argc - 1, src);
(void) close(remin);
remin = remout = -1;
}
@@ -976,7 +982,7 @@ rsource(char *name, struct stat *statp)
(sizeof(type) != 4 && sizeof(type) != 8))
void
-sink(int argc, char **argv)
+sink(int argc, char **argv, const char *src)
{
static BUF buffer;
struct stat stb;
@@ -992,6 +998,7 @@ sink(int argc, char **argv)
unsigned long long ull;
int setimes, targisdir, wrerrno = 0;
char ch, *cp, *np, *targ, *why, *vect[1], buf[2048], visbuf[2048];
+ char *src_copy = NULL, *restrict_pattern = NULL;
struct timeval tv[2];
#define atime tv[0]
@@ -1016,6 +1023,17 @@ sink(int argc, char **argv)
(void) atomicio(vwrite, remout, "", 1);
if (stat(targ, &stb) == 0 && S_ISDIR(stb.st_mode))
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)
+ fatal("strdup failed");
+ if ((restrict_pattern = strrchr(src_copy, '/')) != NULL) {
+ *restrict_pattern++ = '\0';
+ }
+ }
for (first = 1;; first = 0) {
cp = buf;
if (atomicio(read, remin, cp, 1) != 1)
@@ -1120,6 +1138,9 @@ sink(int argc, char **argv)
run_err("error: unexpected filename: %s", cp);
exit(1);
}
+ if (restrict_pattern != NULL &&
+ fnmatch(restrict_pattern, cp, 0) != 0)
+ SCREWUP("filename does not match request");
if (targisdir) {
static char *namebuf;
static size_t cursize;
@@ -1157,7 +1178,7 @@ sink(int argc, char **argv)
goto bad;
}
vect[0] = xstrdup(np);
- sink(1, vect);
+ sink(1, vect, src);
if (setimes) {
setimes = 0;
if (utimes(vect[0], tv) < 0)

View file

@ -1,353 +0,0 @@
From 7a3fa37583d4abf128f7f4c6eb1e7ffc90115eab Mon Sep 17 00:00:00 2001
From: "djm@openbsd.org" <djm@openbsd.org>
Date: Sun, 10 Feb 2019 11:15:52 +0000
Subject: upstream: when checking that filenames sent by the server side
match what the client requested, be prepared to handle shell-style brace
alternations, e.g. "{foo,bar}".
"looks good to me" millert@ + in snaps for the last week courtesy
deraadt@
OpenBSD-Commit-ID: 3b1ce7639b0b25b2248e3a30f561a548f6815f3e
Origin: upstream, https://anongit.mindrot.org/openssh.git/commit/?id=3d896c157c722bc47adca51a58dca859225b5874
Bug-Debian: https://bugs.debian.org/923486
Last-Update: 2019-03-01
Patch-Name: scp-handle-braces.patch
---
scp.c | 280 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 269 insertions(+), 11 deletions(-)
diff --git a/scp.c b/scp.c
index 035037bcc..3888baab0 100644
--- a/scp.c
+++ b/scp.c
@@ -635,6 +635,253 @@ parse_scp_uri(const char *uri, char **userp, char **hostp, int *portp,
return r;
}
+/* Appends a string to an array; returns 0 on success, -1 on alloc failure */
+static int
+append(char *cp, char ***ap, size_t *np)
+{
+ char **tmp;
+
+ if ((tmp = reallocarray(*ap, *np + 1, sizeof(*tmp))) == NULL)
+ return -1;
+ tmp[(*np)] = cp;
+ (*np)++;
+ *ap = tmp;
+ return 0;
+}
+
+/*
+ * Finds the start and end of the first brace pair in the pattern.
+ * returns 0 on success or -1 for invalid patterns.
+ */
+static int
+find_brace(const char *pattern, int *startp, int *endp)
+{
+ int i;
+ int in_bracket, brace_level;
+
+ *startp = *endp = -1;
+ in_bracket = brace_level = 0;
+ for (i = 0; i < INT_MAX && *endp < 0 && pattern[i] != '\0'; i++) {
+ switch (pattern[i]) {
+ case '\\':
+ /* skip next character */
+ if (pattern[i + 1] != '\0')
+ i++;
+ break;
+ case '[':
+ in_bracket = 1;
+ break;
+ case ']':
+ in_bracket = 0;
+ break;
+ case '{':
+ if (in_bracket)
+ break;
+ if (pattern[i + 1] == '}') {
+ /* Protect a single {}, for find(1), like csh */
+ i++; /* skip */
+ break;
+ }
+ if (*startp == -1)
+ *startp = i;
+ brace_level++;
+ break;
+ case '}':
+ if (in_bracket)
+ break;
+ if (*startp < 0) {
+ /* Unbalanced brace */
+ return -1;
+ }
+ if (--brace_level <= 0)
+ *endp = i;
+ break;
+ }
+ }
+ /* unbalanced brackets/braces */
+ if (*endp < 0 && (*startp >= 0 || in_bracket))
+ return -1;
+ return 0;
+}
+
+/*
+ * Assembles and records a successfully-expanded pattern, returns -1 on
+ * alloc failure.
+ */
+static int
+emit_expansion(const char *pattern, int brace_start, int brace_end,
+ int sel_start, int sel_end, char ***patternsp, size_t *npatternsp)
+{
+ char *cp;
+ int o = 0, tail_len = strlen(pattern + brace_end + 1);
+
+ if ((cp = malloc(brace_start + (sel_end - sel_start) +
+ tail_len + 1)) == NULL)
+ return -1;
+
+ /* Pattern before initial brace */
+ if (brace_start > 0) {
+ memcpy(cp, pattern, brace_start);
+ o = brace_start;
+ }
+ /* Current braced selection */
+ if (sel_end - sel_start > 0) {
+ memcpy(cp + o, pattern + sel_start,
+ sel_end - sel_start);
+ o += sel_end - sel_start;
+ }
+ /* Remainder of pattern after closing brace */
+ if (tail_len > 0) {
+ memcpy(cp + o, pattern + brace_end + 1, tail_len);
+ o += tail_len;
+ }
+ cp[o] = '\0';
+ if (append(cp, patternsp, npatternsp) != 0) {
+ free(cp);
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * Expand the first encountered brace in pattern, appending the expanded
+ * patterns it yielded to the *patternsp array.
+ *
+ * Returns 0 on success or -1 on allocation failure.
+ *
+ * Signals whether expansion was performed via *expanded and whether
+ * pattern was invalid via *invalid.
+ */
+static int
+brace_expand_one(const char *pattern, char ***patternsp, size_t *npatternsp,
+ int *expanded, int *invalid)
+{
+ int i;
+ int in_bracket, brace_start, brace_end, brace_level;
+ int sel_start, sel_end;
+
+ *invalid = *expanded = 0;
+
+ if (find_brace(pattern, &brace_start, &brace_end) != 0) {
+ *invalid = 1;
+ return 0;
+ } else if (brace_start == -1)
+ return 0;
+
+ in_bracket = brace_level = 0;
+ for (i = sel_start = brace_start + 1; i < brace_end; i++) {
+ switch (pattern[i]) {
+ case '{':
+ if (in_bracket)
+ break;
+ brace_level++;
+ break;
+ case '}':
+ if (in_bracket)
+ break;
+ brace_level--;
+ break;
+ case '[':
+ in_bracket = 1;
+ break;
+ case ']':
+ in_bracket = 0;
+ break;
+ case '\\':
+ if (i < brace_end - 1)
+ i++; /* skip */
+ break;
+ }
+ if (pattern[i] == ',' || i == brace_end - 1) {
+ if (in_bracket || brace_level > 0)
+ continue;
+ /* End of a selection, emit an expanded pattern */
+
+ /* Adjust end index for last selection */
+ sel_end = (i == brace_end - 1) ? brace_end : i;
+ if (emit_expansion(pattern, brace_start, brace_end,
+ sel_start, sel_end, patternsp, npatternsp) != 0)
+ return -1;
+ /* move on to the next selection */
+ sel_start = i + 1;
+ continue;
+ }
+ }
+ if (in_bracket || brace_level > 0) {
+ *invalid = 1;
+ return 0;
+ }
+ /* success */
+ *expanded = 1;
+ return 0;
+}
+
+/* Expand braces from pattern. Returns 0 on success, -1 on failure */
+static int
+brace_expand(const char *pattern, char ***patternsp, size_t *npatternsp)
+{
+ char *cp, *cp2, **active = NULL, **done = NULL;
+ size_t i, nactive = 0, ndone = 0;
+ int ret = -1, invalid = 0, expanded = 0;
+
+ *patternsp = NULL;
+ *npatternsp = 0;
+
+ /* Start the worklist with the original pattern */
+ if ((cp = strdup(pattern)) == NULL)
+ return -1;
+ if (append(cp, &active, &nactive) != 0) {
+ free(cp);
+ return -1;
+ }
+ while (nactive > 0) {
+ cp = active[nactive - 1];
+ nactive--;
+ if (brace_expand_one(cp, &active, &nactive,
+ &expanded, &invalid) == -1) {
+ free(cp);
+ goto fail;
+ }
+ if (invalid)
+ fatal("%s: invalid brace pattern \"%s\"", __func__, cp);
+ if (expanded) {
+ /*
+ * Current entry expanded to new entries on the
+ * active list; discard the progenitor pattern.
+ */
+ free(cp);
+ continue;
+ }
+ /*
+ * Pattern did not expand; append the finename component to
+ * the completed list
+ */
+ if ((cp2 = strrchr(cp, '/')) != NULL)
+ *cp2++ = '\0';
+ else
+ cp2 = cp;
+ if (append(xstrdup(cp2), &done, &ndone) != 0) {
+ free(cp);
+ goto fail;
+ }
+ free(cp);
+ }
+ /* success */
+ *patternsp = done;
+ *npatternsp = ndone;
+ done = NULL;
+ ndone = 0;
+ ret = 0;
+ fail:
+ for (i = 0; i < nactive; i++)
+ free(active[i]);
+ free(active);
+ for (i = 0; i < ndone; i++)
+ free(done[i]);
+ free(done);
+ return ret;
+}
+
void
toremote(int argc, char **argv)
{
@@ -998,7 +1245,8 @@ sink(int argc, char **argv, const char *src)
unsigned long long ull;
int setimes, targisdir, wrerrno = 0;
char ch, *cp, *np, *targ, *why, *vect[1], buf[2048], visbuf[2048];
- char *src_copy = NULL, *restrict_pattern = NULL;
+ char **patterns = NULL;
+ size_t n, npatterns = 0;
struct timeval tv[2];
#define atime tv[0]
@@ -1028,16 +1276,13 @@ sink(int argc, char **argv, const char *src)
* Prepare to try to restrict incoming filenames to match
* the requested destination file glob.
*/
- if ((src_copy = strdup(src)) == NULL)
- fatal("strdup failed");
- if ((restrict_pattern = strrchr(src_copy, '/')) != NULL) {
- *restrict_pattern++ = '\0';
- }
+ if (brace_expand(src, &patterns, &npatterns) != 0)
+ fatal("%s: could not expand pattern", __func__);
}
for (first = 1;; first = 0) {
cp = buf;
if (atomicio(read, remin, cp, 1) != 1)
- return;
+ goto done;
if (*cp++ == '\n')
SCREWUP("unexpected <newline>");
do {
@@ -1063,7 +1308,7 @@ sink(int argc, char **argv, const char *src)
}
if (buf[0] == 'E') {
(void) atomicio(vwrite, remout, "", 1);
- return;
+ goto done;
}
if (ch == '\n')
*--cp = 0;
@@ -1138,9 +1383,14 @@ sink(int argc, char **argv, const char *src)
run_err("error: unexpected filename: %s", cp);
exit(1);
}
- if (restrict_pattern != NULL &&
- fnmatch(restrict_pattern, cp, 0) != 0)
- SCREWUP("filename does not match request");
+ if (npatterns > 0) {
+ for (n = 0; n < npatterns; n++) {
+ if (fnmatch(patterns[n], cp, 0) == 0)
+ break;
+ }
+ if (n >= npatterns)
+ SCREWUP("filename does not match request");
+ }
if (targisdir) {
static char *namebuf;
static size_t cursize;
@@ -1299,7 +1549,15 @@ bad: run_err("%s: %s", np, strerror(errno));
break;
}
}
+done:
+ for (n = 0; n < npatterns; n++)
+ free(patterns[n]);
+ free(patterns);
+ return;
screwup:
+ for (n = 0; n < npatterns; n++)
+ free(patterns[n]);
+ free(patterns);
run_err("protocol error: %s", why);
exit(1);
}

View file

@ -1,70 +0,0 @@
From 91b777c7064d9d91a1433a42b0bb31592388d1b4 Mon Sep 17 00:00:00 2001
From: Eneas U de Queiroz <cote2004-github@yahoo.com>
Date: Tue, 9 Oct 2018 16:17:42 -0300
Subject: [PATCH] fix compilation with openssl built without ECC
ECDSA code in openssh-compat.h and libressl-api-compat.c needs to be
guarded by OPENSSL_HAS_ECC
Signed-off-by: Eneas U de Queiroz <cote2004-github@yahoo.com>
diff --git a/openbsd-compat/libressl-api-compat.c b/openbsd-compat/libressl-api-compat.c
index de3e64a6..ae00ff59 100644
--- a/openbsd-compat/libressl-api-compat.c
+++ b/openbsd-compat/libressl-api-compat.c
@@ -152,7 +152,9 @@
#include <openssl/dsa.h>
#include <openssl/rsa.h>
#include <openssl/evp.h>
+#ifdef OPENSSL_HAS_ECC
#include <openssl/ecdsa.h>
+#endif
#include <openssl/dh.h>
#ifndef HAVE_DSA_GET0_PQG
@@ -417,6 +419,7 @@ DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s)
}
#endif /* HAVE_DSA_SIG_SET0 */
+#ifdef OPENSSL_HAS_ECC
#ifndef HAVE_ECDSA_SIG_GET0
void
ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps)
@@ -442,6 +445,7 @@ ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s)
return 1;
}
#endif /* HAVE_ECDSA_SIG_SET0 */
+#endif /* OPENSSL_HAS_ECC */
#ifndef HAVE_DH_GET0_PQG
void
diff --git a/openbsd-compat/openssl-compat.h b/openbsd-compat/openssl-compat.h
index 9e0264c0..6a525f28 100644
--- a/openbsd-compat/openssl-compat.h
+++ b/openbsd-compat/openssl-compat.h
@@ -24,7 +24,9 @@
#include <openssl/evp.h>
#include <openssl/rsa.h>
#include <openssl/dsa.h>
+#ifdef OPENSSL_HAS_ECC
#include <openssl/ecdsa.h>
+#endif
#include <openssl/dh.h>
int ssh_compatible_openssl(long, long);
@@ -161,6 +163,7 @@ void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps);
int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s);
#endif /* DSA_SIG_SET0 */
+#ifdef OPENSSL_HAS_ECC
#ifndef HAVE_ECDSA_SIG_GET0
void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps);
#endif /* HAVE_ECDSA_SIG_GET0 */
@@ -168,6 +171,7 @@ void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps);
#ifndef HAVE_ECDSA_SIG_SET0
int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s);
#endif /* HAVE_ECDSA_SIG_SET0 */
+#endif /* OPENSSL_HAS_ECC */
#ifndef HAVE_DH_GET0_PQG
void DH_get0_pqg(const DH *dh, const BIGNUM **p, const BIGNUM **q,

View file

@ -1,20 +0,0 @@
From edfc2e18ef069ba600c8f4632ce1e3dc94a0669a Mon Sep 17 00:00:00 2001
From: Eneas U de Queiroz <cote2004-github@yahoo.com>
Date: Fri, 19 Oct 2018 10:04:24 -0300
Subject: [PATCH 2/2] Fix OPENSSL_init_crypto call for openssl < 1.1
Signed-off-by: Eneas U de Queiroz <cote2004-github@yahoo.com>
diff --git a/openbsd-compat/openssl-compat.c b/openbsd-compat/openssl-compat.c
index 8b4a3627..590b66d1 100644
--- a/openbsd-compat/openssl-compat.c
+++ b/openbsd-compat/openssl-compat.c
@@ -76,7 +76,7 @@ ssh_OpenSSL_add_all_algorithms(void)
ENGINE_load_builtin_engines();
ENGINE_register_all_complete();
-#if OPENSSL_VERSION_NUMBER < 0x10001000L
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
OPENSSL_config(NULL);
#else
OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS |