From 2bbc3688bdfa8bd5f996501ab8fb61dc22f10b57 Mon Sep 17 00:00:00 2001 From: Mattias Ellert Date: Fri, 5 Feb 2021 15:12:25 +0100 Subject: [PATCH 1/7] Based on openssh-8.4p1-5.fc33 --- gsi-openssh.spec | 7 +++++-- openssh-8.0p1-pkcs11-uri.patch | 14 ++++++++------ 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/gsi-openssh.spec b/gsi-openssh.spec index 23d80e8..1ab04a5 100644 --- a/gsi-openssh.spec +++ b/gsi-openssh.spec @@ -28,7 +28,7 @@ %global libedit 1 %global openssh_ver 8.4p1 -%global openssh_rel 3 +%global openssh_rel 4 Summary: An implementation of the SSH protocol with GSI authentication Name: gsi-openssh @@ -501,7 +501,10 @@ getent passwd sshd >/dev/null || \ %attr(0644,root,root) %{_tmpfilesdir}/gsissh.conf %changelog -* Wed Dec 9 2020 Mattias Ellert - 8.4p1-3 +* Fri Feb 05 2021 Mattias Ellert - 8.4p1-4 +- Based on openssh-8.4p1-5.fc33 + +* Wed Dec 09 2020 Mattias Ellert - 8.4p1-3 - Based on openssh-8.4p1-4.fc33 * Mon Nov 30 2020 Mattias Ellert - 8.4p1-2 diff --git a/openssh-8.0p1-pkcs11-uri.patch b/openssh-8.0p1-pkcs11-uri.patch index d55df23..0713ffe 100644 --- a/openssh-8.0p1-pkcs11-uri.patch +++ b/openssh-8.0p1-pkcs11-uri.patch @@ -2159,12 +2159,13 @@ index a302c79c..879fe917 100644 if (rv != CKR_OK) { error("C_GetAttributeValue failed: %lu", rv); return (NULL); -@@ -717,18 +874,19 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, +@@ -717,19 +874,19 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, + * ensure that none of the others are zero length. * XXX assumes CKA_ID is always first. */ - if (key_attr[1].ulValueLen == 0 || +- if (key_attr[1].ulValueLen == 0 || - key_attr[2].ulValueLen == 0) { -+ key_attr[2].ulValueLen == 0 || ++ if (key_attr[2].ulValueLen == 0 || + key_attr[3].ulValueLen == 0) { error("invalid attribute length"); return (NULL); @@ -2259,12 +2260,13 @@ index a302c79c..879fe917 100644 if (rv != CKR_OK) { error("C_GetAttributeValue failed: %lu", rv); return (NULL); -@@ -838,18 +998,19 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, +@@ -838,19 +998,19 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, + * ensure that none of the others are zero length. * XXX assumes CKA_ID is always first. */ - if (key_attr[1].ulValueLen == 0 || +- if (key_attr[1].ulValueLen == 0 || - key_attr[2].ulValueLen == 0) { -+ key_attr[2].ulValueLen == 0 || ++ if (key_attr[2].ulValueLen == 0 || + key_attr[3].ulValueLen == 0) { error("invalid attribute length"); return (NULL); From 7b2f5e53c4d4a10dae85580d340168d60ae0eb21 Mon Sep 17 00:00:00 2001 From: Frank Scheiner Date: Fri, 12 Mar 2021 13:09:16 +0100 Subject: [PATCH 2/7] Add HPN patch --- gsi-openssh.spec | 12 +- openssh-8.4p1-hpn-15.1-modified.patch | 2738 +++++++++++++++++++++++++ 2 files changed, 2748 insertions(+), 2 deletions(-) create mode 100644 openssh-8.4p1-hpn-15.1-modified.patch diff --git a/gsi-openssh.spec b/gsi-openssh.spec index 1ab04a5..5da6a9f 100644 --- a/gsi-openssh.spec +++ b/gsi-openssh.spec @@ -28,7 +28,7 @@ %global libedit 1 %global openssh_ver 8.4p1 -%global openssh_rel 4 +%global openssh_rel 5 Summary: An implementation of the SSH protocol with GSI authentication Name: gsi-openssh @@ -163,6 +163,10 @@ Patch969: openssh-8.4p1-debian-compat.patch # Based on hpn_isshd-gsi.7.5p1b.patch from Globus upstream Patch98: openssh-8.4p1-gsissh.patch +# This is the HPN patch +# Based on https://sourceforge.net/projects/hpnssh/files/Patches/HPN-SSH%2015v1%208.4p1/ +Patch99: openssh-8.4p1-hpn-15.1-modified.patch + License: BSD Requires: /sbin/nologin @@ -310,6 +314,7 @@ gpgv2 --quiet --keyring %{SOURCE3} %{SOURCE1} %{SOURCE0} %patch100 -p1 -b .coverity %patch98 -p1 -b .gsi +%patch99 -p1 -b .hpn sed 's/sshd.pid/gsisshd.pid/' -i pathnames.h sed 's!$(piddir)/sshd.pid!$(piddir)/gsisshd.pid!' -i Makefile.in @@ -458,7 +463,7 @@ getent passwd sshd >/dev/null || \ %files %license LICENCE -%doc CREDITS ChangeLog OVERVIEW PROTOCOL* README README.platform README.privsep README.tun README.dns README.sshd-and-gsisshd TODO +%doc CREDITS ChangeLog OVERVIEW PROTOCOL* README HPN-README README.platform README.privsep README.tun README.dns README.sshd-and-gsisshd TODO %attr(0755,root,root) %dir %{_sysconfdir}/gsissh %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/gsissh/moduli %attr(0755,root,root) %{_bindir}/gsissh-keygen @@ -501,6 +506,9 @@ getent passwd sshd >/dev/null || \ %attr(0644,root,root) %{_tmpfilesdir}/gsissh.conf %changelog +* Thu Mar 11 2021 Frank Scheiner - 8.4p1-5 +- Add HPN patch + * Fri Feb 05 2021 Mattias Ellert - 8.4p1-4 - Based on openssh-8.4p1-5.fc33 diff --git a/openssh-8.4p1-hpn-15.1-modified.patch b/openssh-8.4p1-hpn-15.1-modified.patch new file mode 100644 index 0000000..62d5b65 --- /dev/null +++ b/openssh-8.4p1-hpn-15.1-modified.patch @@ -0,0 +1,2738 @@ +diff -Nur openssh-8.4p1.orig/auth2.c openssh-8.4p1/auth2.c +--- openssh-8.4p1.orig/auth2.c 2021-03-11 18:13:41.139603147 +0100 ++++ openssh-8.4p1/auth2.c 2021-03-11 18:18:03.302756116 +0100 +@@ -53,6 +53,8 @@ + #include "dispatch.h" + #include "pathnames.h" + #include "ssherr.h" ++#include "canohost.h" ++ + #ifdef GSSAPI + #include "ssh-gss.h" + #endif +@@ -77,6 +79,8 @@ + extern Authmethod method_gssapi; + #endif + ++static int log_flag = 0; ++ + Authmethod *authmethods[] = { + &method_none, + &method_pubkey, +@@ -301,6 +305,11 @@ + + debug("userauth-request for user %s service %s method %s", + user[0] ? user : "", service, method); ++ if (!log_flag) { ++ logit("SSH: Server;Ltype: Authname;Remote: %s-%d;Name: %s", ++ ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), user); ++ log_flag = 1; ++ } + debug("attempt %d failures %d", authctxt->attempt, authctxt->failures); + + #ifdef WITH_SELINUX +diff -Nur openssh-8.4p1.orig/canohost.h openssh-8.4p1/canohost.h +--- openssh-8.4p1.orig/canohost.h 2021-03-11 18:13:41.141603126 +0100 ++++ openssh-8.4p1/canohost.h 2021-03-11 18:16:31.126747922 +0100 +@@ -22,7 +22,7 @@ + int get_peer_port(int); + char *get_local_ipaddr(int); + char *get_local_name(int); +-int get_local_port(int); ++int get_local_port(int); + + #endif /* _CANOHOST_H */ + +diff -Nur openssh-8.4p1.orig/channels.c openssh-8.4p1/channels.c +--- openssh-8.4p1.orig/channels.c 2021-03-11 18:13:41.134603201 +0100 ++++ openssh-8.4p1/channels.c 2021-03-11 18:16:31.127747911 +0100 +@@ -220,6 +220,9 @@ + /* Setup helper */ + static void channel_handler_init(struct ssh_channels *sc); + ++static int hpn_disabled = 0; ++static int hpn_buffer_size = 2 * 1024 * 1024; ++ + /* -- channel core */ + + void +@@ -395,6 +398,7 @@ + c->local_window = window; + c->local_window_max = window; + c->local_maxpacket = maxpack; ++ c->dynamic_window = 0; + c->remote_name = xstrdup(remote_name); + c->ctl_chan = -1; + c->delayed = 1; /* prevent call to channel_post handler */ +@@ -1084,6 +1088,28 @@ + FD_SET(c->sock, writeset); + } + ++static int ++channel_tcpwinsz(struct ssh *ssh) ++{ ++ u_int32_t tcpwinsz = 0; ++ socklen_t optsz = sizeof(tcpwinsz); ++ int ret = -1; ++ ++ /* if we aren't on a socket return 128KB */ ++ if (!ssh_packet_connection_is_on_socket(ssh)) ++ return 128 * 1024; ++ ++ ret = getsockopt(ssh_packet_get_connection_in(ssh), ++ SOL_SOCKET, SO_RCVBUF, &tcpwinsz, &optsz); ++ /* return no more than SSHBUF_SIZE_MAX (currently 256MB) */ ++ if ((ret == 0) && tcpwinsz > SSHBUF_SIZE_MAX) ++ tcpwinsz = SSHBUF_SIZE_MAX; ++ ++ debug2("tcpwinsz: tcp connection %d, Receive window: %d", ++ ssh_packet_get_connection_in(ssh), tcpwinsz); ++ return tcpwinsz; ++} ++ + static void + channel_pre_open(struct ssh *ssh, Channel *c, + fd_set *readset, fd_set *writeset) +@@ -2179,25 +2205,34 @@ + + if (c->type == SSH_CHANNEL_OPEN && + !(c->flags & (CHAN_CLOSE_SENT|CHAN_CLOSE_RCVD)) && +- ((c->local_window_max - c->local_window > +- c->local_maxpacket*3) || ++ ((ssh_packet_is_interactive(ssh) && ++ c->local_window_max - c->local_window > c->local_maxpacket*3) || + c->local_window < c->local_window_max/2) && + c->local_consumed > 0) { ++ u_int addition = 0; ++ u_int32_t tcpwinsz = channel_tcpwinsz(ssh); ++ /* adjust max window size if we are in a dynamic environment */ ++ if (c->dynamic_window && (tcpwinsz > c->local_window_max)) { ++ /* grow the window somewhat aggressively to maintain pressure */ ++ addition = 1.5 * (tcpwinsz - c->local_window_max); ++ c->local_window_max += addition; ++ debug("Channel: Window growth to %d by %d bytes", c->local_window_max, addition); ++ } + if (!c->have_remote_id) + fatal(":%s: channel %d: no remote id", + __func__, c->self); + if ((r = sshpkt_start(ssh, + SSH2_MSG_CHANNEL_WINDOW_ADJUST)) != 0 || + (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || +- (r = sshpkt_put_u32(ssh, c->local_consumed)) != 0 || ++ (r = sshpkt_put_u32(ssh, c->local_consumed + addition)) != 0 || + (r = sshpkt_send(ssh)) != 0) { + fatal("%s: channel %i: %s", __func__, + c->self, ssh_err(r)); + } + debug2("channel %d: window %d sent adjust %d", + c->self, c->local_window, +- c->local_consumed); +- c->local_window += c->local_consumed; ++ c->local_consumed + addition); ++ c->local_window += c->local_consumed + addition; + c->local_consumed = 0; + } + return 1; +@@ -2548,7 +2583,7 @@ + size_t len, plen; + const u_char *pkt; + int r; +- ++ + if ((len = sshbuf_len(c->input)) == 0) { + if (c->istate == CHAN_INPUT_WAIT_DRAIN) { + /* +@@ -2594,7 +2629,6 @@ + c->self, ssh_err(r)); + } + c->remote_window -= plen; +- return; + } + + /* Enqueue packet for buffered data. */ +@@ -2666,7 +2700,7 @@ + c = sc->channels[i]; + if (c == NULL) + continue; +- ++ + /* + * We are only interested in channels that can have buffered + * incoming data. +@@ -2676,10 +2710,10 @@ + if ((c->flags & (CHAN_CLOSE_SENT|CHAN_CLOSE_RCVD))) { + /* XXX is this true? */ + debug3("channel %d: will not send data after close", +- c->self); ++ c->self); + continue; + } +- ++ + /* Get the amount of buffered data for this channel. */ + if (c->istate == CHAN_INPUT_OPEN || + c->istate == CHAN_INPUT_WAIT_DRAIN) +@@ -3382,6 +3416,14 @@ + return addr; + } + ++void ++channel_set_hpn(int external_hpn_disabled, int external_hpn_buffer_size) ++{ ++ hpn_disabled = external_hpn_disabled; ++ hpn_buffer_size = external_hpn_buffer_size; ++ debug("HPN Disabled: %d, HPN Buffer Size: %d", hpn_disabled, hpn_buffer_size); ++} ++ + static int + channel_setup_fwd_listener_tcpip(struct ssh *ssh, int type, + struct Forward *fwd, int *allocated_listen_port, +@@ -3522,9 +3564,11 @@ + } + + /* Allocate a channel number for the socket. */ ++ /* explicitly test for hpn disabled option. if true use smaller window size */ + c = channel_new(ssh, "port listener", type, sock, sock, -1, +- CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, +- 0, "port listener", 1); ++ hpn_disabled ? CHAN_TCP_WINDOW_DEFAULT : hpn_buffer_size, ++ CHAN_TCP_PACKET_DEFAULT, ++ 0, "port listener", 1); + c->path = xstrdup(host); + c->host_port = fwd->connect_port; + c->listening_addr = addr == NULL ? NULL : xstrdup(addr); +@@ -4694,8 +4738,9 @@ + sock = socks[n]; + nc = channel_new(ssh, "x11 listener", + SSH_CHANNEL_X11_LISTENER, sock, sock, -1, +- CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, +- 0, "X11 inet listener", 1); ++ hpn_disabled ? CHAN_X11_WINDOW_DEFAULT : hpn_buffer_size, ++ CHAN_X11_PACKET_DEFAULT, ++ 0, "X11 inet listener", 1); + nc->single_connection = single_connection; + (*chanids)[n] = nc->self; + } +diff -Nur openssh-8.4p1.orig/channels.h openssh-8.4p1/channels.h +--- openssh-8.4p1.orig/channels.h 2021-03-11 18:13:41.035604263 +0100 ++++ openssh-8.4p1/channels.h 2021-03-11 18:16:31.128747900 +0100 +@@ -158,8 +158,10 @@ + u_int local_window_max; + u_int local_consumed; + u_int local_maxpacket; ++ int dynamic_window; + int extended_usage; + int single_connection; ++ u_int tcpwinsz; + + char *ctype; /* type */ + +@@ -221,7 +223,7 @@ + #define CHAN_LOCAL 0x10 + + /* Read buffer size */ +-#define CHAN_RBUF (16*1024) ++#define CHAN_RBUF CHAN_SES_PACKET_DEFAULT + + /* Maximum channel input buffer size */ + #define CHAN_INPUT_MAX (16*1024*1024) +@@ -352,4 +354,6 @@ + void chan_write_failed(struct ssh *, Channel *); + void chan_obuf_empty(struct ssh *, Channel *); + ++/* hpn handler */ ++void channel_set_hpn(int, int); + #endif +diff -Nur openssh-8.4p1.orig/cipher.c openssh-8.4p1/cipher.c +--- openssh-8.4p1.orig/cipher.c 2021-03-11 18:13:41.113603426 +0100 ++++ openssh-8.4p1/cipher.c 2021-03-11 18:16:31.130747879 +0100 +@@ -48,6 +48,7 @@ + #include "sshbuf.h" + #include "ssherr.h" + #include "digest.h" ++#include "log.h" + + #include "openbsd-compat/openssl-compat.h" + +@@ -55,6 +56,9 @@ + #define EVP_CIPHER_CTX void + #endif + ++/* for multi-threaded aes-ctr cipher */ ++extern const EVP_CIPHER *evp_aes_ctr_mt(void); ++ + struct sshcipher_ctx { + int plaintext; + int encrypt; +@@ -64,7 +68,7 @@ + const struct sshcipher *cipher; + }; + +-static const struct sshcipher ciphers[] = { ++static struct sshcipher ciphers[] = { + #ifdef WITH_OPENSSL + #ifndef OPENSSL_NO_DES + { "3des-cbc", 8, 24, 0, 0, CFLAG_CBC, EVP_des_ede3_cbc }, +@@ -76,7 +80,8 @@ + 16, 32, 0, 0, CFLAG_CBC, EVP_aes_256_cbc }, + { "aes128-ctr", 16, 16, 0, 0, 0, EVP_aes_128_ctr }, + { "aes192-ctr", 16, 24, 0, 0, 0, EVP_aes_192_ctr }, +- { "aes256-ctr", 16, 32, 0, 0, 0, EVP_aes_256_ctr }, ++ { "aes256-ctr", 16, 32, 0, 0, 0, EVP_aes_256_ctr }, ++ + # ifdef OPENSSL_HAVE_EVPGCM + { "aes128-gcm@openssh.com", + 16, 16, 12, 16, 0, EVP_aes_128_gcm }, +@@ -135,6 +140,29 @@ + #endif + } + ++/* used to get the cipher name so when force rekeying to handle the ++ * single to multithreaded ctr cipher swap we only rekey when appropriate ++ */ ++const char * ++cipher_ctx_name(const struct sshcipher_ctx *cc) ++{ ++ return cc->cipher->name; ++} ++ ++/* in order to get around sandbox and forking issues with a threaded cipher ++ * we set the initial pre-auth aes-ctr cipher to the default OpenSSH cipher ++ * post auth we set them to the new evp as defined by cipher-ctr-mt ++ */ ++#ifdef WITH_OPENSSL ++void ++cipher_reset_multithreaded(void) ++{ ++ cipher_by_name("aes128-ctr")->evptype = evp_aes_ctr_mt; ++ cipher_by_name("aes192-ctr")->evptype = evp_aes_ctr_mt; ++ cipher_by_name("aes256-ctr")->evptype = evp_aes_ctr_mt; ++} ++#endif ++ + u_int + cipher_blocksize(const struct sshcipher *c) + { +@@ -184,10 +212,10 @@ + return cc->plaintext; + } + +-const struct sshcipher * ++struct sshcipher * + cipher_by_name(const char *name) + { +- const struct sshcipher *c; ++ struct sshcipher *c; + for (c = ciphers; c->name != NULL; c++) + if (strcmp(c->name, name) == 0) + return c; +@@ -209,7 +237,8 @@ + for ((p = strsep(&cp, CIPHER_SEP)); p && *p != '\0'; + (p = strsep(&cp, CIPHER_SEP))) { + c = cipher_by_name(p); +- if (c == NULL || (c->flags & CFLAG_INTERNAL) != 0) { ++ if (c == NULL || ((c->flags & CFLAG_INTERNAL) != 0 && ++ (c->flags & CFLAG_NONE) != 0)) { + free(cipher_list); + return 0; + } +diff -Nur openssh-8.4p1.orig/cipher-ctr-mt.c openssh-8.4p1/cipher-ctr-mt.c +--- openssh-8.4p1.orig/cipher-ctr-mt.c 1970-01-01 01:00:00.000000000 +0100 ++++ openssh-8.4p1/cipher-ctr-mt.c 2021-03-11 18:16:31.128747900 +0100 +@@ -0,0 +1,677 @@ ++/* ++ * OpenSSH Multi-threaded AES-CTR Cipher ++ * ++ * Author: Benjamin Bennett ++ * Author: Mike Tasota ++ * Author: Chris Rapier ++ * Copyright (c) 2008-2013 Pittsburgh Supercomputing Center. All rights reserved. ++ * ++ * Based on original OpenSSH AES-CTR cipher. Small portions remain unchanged, ++ * Copyright (c) 2003 Markus Friedl ++ * ++ * Permission to use, copy, modify, and distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#include "includes.h" ++ ++#if defined(WITH_OPENSSL) ++#include ++ ++#include ++#include ++ ++#include ++ ++#include "xmalloc.h" ++#include "log.h" ++#include ++ ++/* compatibility with old or broken OpenSSL versions */ ++#include "openbsd-compat/openssl-compat.h" ++ ++#ifndef USE_BUILTIN_RIJNDAEL ++#include ++#endif ++ ++#include ++ ++/*-------------------- TUNABLES --------------------*/ ++/* maximum number of threads and queues */ ++#define MAX_THREADS 32 ++#define MAX_NUMKQ (MAX_THREADS * 2) ++ ++/* Number of pregen threads to use */ ++int cipher_threads = 2; ++ ++/* Number of keystream queues */ ++int numkq = 4; ++ ++/* Length of a keystream queue */ ++#define KQLEN 4096 ++ ++/* Processor cacheline length */ ++#define CACHELINE_LEN 64 ++ ++/* Collect thread stats and print at cancellation when in debug mode */ ++#define CIPHER_THREAD_STATS ++ ++/* Can the system do unaligned loads natively? */ ++#if defined(__aarch64__) || \ ++ defined(__i386__) || \ ++ defined(__powerpc__) || \ ++ defined(__x86_64__) ++# define CIPHER_UNALIGNED_OK ++#endif ++#if defined(__SIZEOF_INT128__) ++# define CIPHER_INT128_OK ++#endif ++/*-------------------- END TUNABLES --------------------*/ ++ ++ ++const EVP_CIPHER *evp_aes_ctr_mt(void); ++ ++#ifdef CIPHER_THREAD_STATS ++/* ++ * Struct to collect thread stats ++ */ ++struct thread_stats { ++ u_int fills; ++ u_int skips; ++ u_int waits; ++ u_int drains; ++}; ++ ++/* ++ * Debug print the thread stats ++ * Use with pthread_cleanup_push for displaying at thread cancellation ++ */ ++static void ++thread_loop_stats(void *x) ++{ ++ struct thread_stats *s = x; ++ debug("AES-CTR MT tid %lu - %u fills, %u skips, %u waits", pthread_self(), ++ s->fills, s->skips, s->waits); ++} ++ ++# define STATS_STRUCT(s) struct thread_stats s ++# define STATS_INIT(s) { memset(&s, 0, sizeof(s)); } ++# define STATS_FILL(s) { s.fills++; } ++# define STATS_SKIP(s) { s.skips++; } ++# define STATS_WAIT(s) { s.waits++; } ++# define STATS_DRAIN(s) { s.drains++; } ++#else ++# define STATS_STRUCT(s) ++# define STATS_INIT(s) ++# define STATS_FILL(s) ++# define STATS_SKIP(s) ++# define STATS_WAIT(s) ++# define STATS_DRAIN(s) ++#endif ++ ++/* Keystream Queue state */ ++enum { ++ KQINIT, ++ KQEMPTY, ++ KQFILLING, ++ KQFULL, ++ KQDRAINING ++}; ++ ++/* Keystream Queue struct */ ++struct kq { ++ u_char keys[KQLEN][AES_BLOCK_SIZE]; ++ u_char ctr[AES_BLOCK_SIZE]; ++ u_char pad0[CACHELINE_LEN]; ++ int qstate; ++ pthread_mutex_t lock; ++ pthread_cond_t cond; ++ u_char pad1[CACHELINE_LEN]; ++}; ++ ++/* Context struct */ ++struct ssh_aes_ctr_ctx_mt ++{ ++ int struct_id; ++ struct kq q[MAX_NUMKQ]; ++ AES_KEY aes_ctx; ++ STATS_STRUCT(stats); ++ u_char aes_counter[AES_BLOCK_SIZE]; ++ pthread_t tid[MAX_THREADS]; ++ int id[MAX_THREADS]; ++ pthread_rwlock_t tid_lock; ++#ifdef __APPLE__ ++ pthread_rwlock_t stop_lock; ++ int exit_flag; ++#endif /* __APPLE__ */ ++ int state; ++ int qidx; ++ int ridx; ++}; ++ ++/* ++ * increment counter 'ctr', ++ * the counter is of size 'len' bytes and stored in network-byte-order. ++ * (LSB at ctr[len-1], MSB at ctr[0]) ++ */ ++static void ++ssh_ctr_inc(u_char *ctr, size_t len) ++{ ++ int i; ++ ++ for (i = len - 1; i >= 0; i--) ++ if (++ctr[i]) /* continue on overflow */ ++ return; ++} ++ ++/* ++ * Add num to counter 'ctr' ++ */ ++static void ++ssh_ctr_add(u_char *ctr, uint32_t num, u_int len) ++{ ++ int i; ++ uint16_t n; ++ ++ for (n = 0, i = len - 1; i >= 0 && (num || n); i--) { ++ n = ctr[i] + (num & 0xff) + n; ++ num >>= 8; ++ ctr[i] = n & 0xff; ++ n >>= 8; ++ } ++} ++ ++/* ++ * Threads may be cancelled in a pthread_cond_wait, we must free the mutex ++ */ ++static void ++thread_loop_cleanup(void *x) ++{ ++ pthread_mutex_unlock((pthread_mutex_t *)x); ++} ++ ++#ifdef __APPLE__ ++/* Check if we should exit, we are doing both cancel and exit condition ++ * since on OSX threads seem to occasionally fail to notice when they have ++ * been cancelled. We want to have a backup to make sure that we won't hang ++ * when the main process join()-s the cancelled thread. ++ */ ++static void ++thread_loop_check_exit(struct ssh_aes_ctr_ctx_mt *c) ++{ ++ int exit_flag; ++ ++ pthread_rwlock_rdlock(&c->stop_lock); ++ exit_flag = c->exit_flag; ++ pthread_rwlock_unlock(&c->stop_lock); ++ ++ if (exit_flag) ++ pthread_exit(NULL); ++} ++#else ++# define thread_loop_check_exit(s) ++#endif /* __APPLE__ */ ++ ++/* ++ * Helper function to terminate the helper threads ++ */ ++static void ++stop_and_join_pregen_threads(struct ssh_aes_ctr_ctx_mt *c) ++{ ++ int i; ++ ++#ifdef __APPLE__ ++ /* notify threads that they should exit */ ++ pthread_rwlock_wrlock(&c->stop_lock); ++ c->exit_flag = TRUE; ++ pthread_rwlock_unlock(&c->stop_lock); ++#endif /* __APPLE__ */ ++ ++ /* Cancel pregen threads */ ++ for (i = 0; i < cipher_threads; i++) { ++ debug ("Canceled %lu (%d,%d)", c->tid[i], c->struct_id, c->id[i]); ++ pthread_cancel(c->tid[i]); ++ } ++ /* shouldn't need this - see commit logs for hpn-7_7_P1 -cjr 11/7/19*/ ++ /* for (i = 0; i < numkq; i++) { */ ++ /* pthread_mutex_lock(&c->q[i].lock); */ ++ /* pthread_cond_broadcast(&c->q[i].cond); */ ++ /* pthread_mutex_unlock(&c->q[i].lock); */ ++ /* } */ ++ for (i = 0; i < cipher_threads; i++) { ++ if (pthread_kill(c->tid[i], 0) != 0) ++ debug3("AES-CTR MT pthread_join failure: Invalid thread id %lu in %s", c->tid[i], __FUNCTION__); ++ else { ++ debug ("Joining %lu (%d, %d)", c->tid[i], c->struct_id, c->id[i]); ++ pthread_join(c->tid[i], NULL); ++ } ++ } ++} ++ ++/* ++ * The life of a pregen thread: ++ * Find empty keystream queues and fill them using their counter. ++ * When done, update counter for the next fill. ++ */ ++static void * ++thread_loop(void *x) ++{ ++ AES_KEY key; ++ STATS_STRUCT(stats); ++ struct ssh_aes_ctr_ctx_mt *c = x; ++ struct kq *q; ++ int i; ++ int qidx; ++ pthread_t first_tid; ++ ++ /* Threads stats on cancellation */ ++ STATS_INIT(stats); ++#ifdef CIPHER_THREAD_STATS ++ pthread_cleanup_push(thread_loop_stats, &stats); ++#endif ++ ++ /* Thread local copy of AES key */ ++ memcpy(&key, &c->aes_ctx, sizeof(key)); ++ ++ pthread_rwlock_rdlock(&c->tid_lock); ++ first_tid = c->tid[0]; ++ pthread_rwlock_unlock(&c->tid_lock); ++ ++ /* ++ * Handle the special case of startup, one thread must fill ++ * the first KQ then mark it as draining. Lock held throughout. ++ */ ++ if (pthread_equal(pthread_self(), first_tid)) { ++ q = &c->q[0]; ++ pthread_mutex_lock(&q->lock); ++ if (q->qstate == KQINIT) { ++ for (i = 0; i < KQLEN; i++) { ++ AES_encrypt(q->ctr, q->keys[i], &key); ++ ssh_ctr_inc(q->ctr, AES_BLOCK_SIZE); ++ } ++ ssh_ctr_add(q->ctr, KQLEN * (numkq - 1), AES_BLOCK_SIZE); ++ q->qstate = KQDRAINING; ++ STATS_FILL(stats); ++ pthread_cond_broadcast(&q->cond); ++ } ++ pthread_mutex_unlock(&q->lock); ++ } else ++ STATS_SKIP(stats); ++ ++ /* ++ * Normal case is to find empty queues and fill them, skipping over ++ * queues already filled by other threads and stopping to wait for ++ * a draining queue to become empty. ++ * ++ * Multiple threads may be waiting on a draining queue and awoken ++ * when empty. The first thread to wake will mark it as filling, ++ * others will move on to fill, skip, or wait on the next queue. ++ */ ++ for (qidx = 1;; qidx = (qidx + 1) % numkq) { ++ /* Check if I was cancelled, also checked in cond_wait */ ++ pthread_testcancel(); ++ ++ /* Check if we should exit as well */ ++ thread_loop_check_exit(c); ++ ++ /* Lock queue and block if its draining */ ++ q = &c->q[qidx]; ++ pthread_mutex_lock(&q->lock); ++ pthread_cleanup_push(thread_loop_cleanup, &q->lock); ++ while (q->qstate == KQDRAINING || q->qstate == KQINIT) { ++ STATS_WAIT(stats); ++ thread_loop_check_exit(c); ++ pthread_cond_wait(&q->cond, &q->lock); ++ } ++ pthread_cleanup_pop(0); ++ ++ /* If filling or full, somebody else got it, skip */ ++ if (q->qstate != KQEMPTY) { ++ pthread_mutex_unlock(&q->lock); ++ STATS_SKIP(stats); ++ continue; ++ } ++ ++ /* ++ * Empty, let's fill it. ++ * Queue lock is relinquished while we do this so others ++ * can see that it's being filled. ++ */ ++ q->qstate = KQFILLING; ++ pthread_cond_broadcast(&q->cond); ++ pthread_mutex_unlock(&q->lock); ++ for (i = 0; i < KQLEN; i++) { ++ AES_encrypt(q->ctr, q->keys[i], &key); ++ ssh_ctr_inc(q->ctr, AES_BLOCK_SIZE); ++ } ++ ++ /* Re-lock, mark full and signal consumer */ ++ pthread_mutex_lock(&q->lock); ++ ssh_ctr_add(q->ctr, KQLEN * (numkq - 1), AES_BLOCK_SIZE); ++ q->qstate = KQFULL; ++ STATS_FILL(stats); ++ pthread_cond_broadcast(&q->cond); ++ pthread_mutex_unlock(&q->lock); ++ } ++ ++#ifdef CIPHER_THREAD_STATS ++ /* Stats */ ++ pthread_cleanup_pop(1); ++#endif ++ ++ return NULL; ++} ++ ++static int ++ssh_aes_ctr(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, ++ LIBCRYPTO_EVP_INL_TYPE len) ++{ ++ typedef union { ++#ifdef CIPHER_INT128_OK ++ __uint128_t *u128; ++#endif ++ uint64_t *u64; ++ uint32_t *u32; ++ uint8_t *u8; ++ const uint8_t *cu8; ++ uintptr_t u; ++ } ptrs_t; ++ ptrs_t destp, srcp, bufp; ++ uintptr_t align; ++ struct ssh_aes_ctr_ctx_mt *c; ++ struct kq *q, *oldq; ++ int ridx; ++ u_char *buf; ++ ++ if (len == 0) ++ return 1; ++ if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) ++ return 0; ++ ++ q = &c->q[c->qidx]; ++ ridx = c->ridx; ++ ++ /* src already padded to block multiple */ ++ srcp.cu8 = src; ++ destp.u8 = dest; ++ while (len > 0) { ++ buf = q->keys[ridx]; ++ bufp.u8 = buf; ++ ++ /* figure out the alignment on the fly */ ++#ifdef CIPHER_UNALIGNED_OK ++ align = 0; ++#else ++ align = destp.u | srcp.u | bufp.u; ++#endif ++ ++#ifdef CIPHER_INT128_OK ++ if ((align & 0xf) == 0) { ++ destp.u128[0] = srcp.u128[0] ^ bufp.u128[0]; ++ } else ++#endif ++ if ((align & 0x7) == 0) { ++ destp.u64[0] = srcp.u64[0] ^ bufp.u64[0]; ++ destp.u64[1] = srcp.u64[1] ^ bufp.u64[1]; ++ } else if ((align & 0x3) == 0) { ++ destp.u32[0] = srcp.u32[0] ^ bufp.u32[0]; ++ destp.u32[1] = srcp.u32[1] ^ bufp.u32[1]; ++ destp.u32[2] = srcp.u32[2] ^ bufp.u32[2]; ++ destp.u32[3] = srcp.u32[3] ^ bufp.u32[3]; ++ } else { ++ size_t i; ++ for (i = 0; i < AES_BLOCK_SIZE; ++i) ++ dest[i] = src[i] ^ buf[i]; ++ } ++ ++ destp.u += AES_BLOCK_SIZE; ++ srcp.u += AES_BLOCK_SIZE; ++ len -= AES_BLOCK_SIZE; ++ ssh_ctr_inc(c->aes_counter, AES_BLOCK_SIZE); ++ ++ /* Increment read index, switch queues on rollover */ ++ if ((ridx = (ridx + 1) % KQLEN) == 0) { ++ oldq = q; ++ ++ /* Mark next queue draining, may need to wait */ ++ c->qidx = (c->qidx + 1) % numkq; ++ q = &c->q[c->qidx]; ++ pthread_mutex_lock(&q->lock); ++ while (q->qstate != KQFULL) { ++ STATS_WAIT(c->stats); ++ pthread_cond_wait(&q->cond, &q->lock); ++ } ++ q->qstate = KQDRAINING; ++ pthread_cond_broadcast(&q->cond); ++ pthread_mutex_unlock(&q->lock); ++ ++ /* Mark consumed queue empty and signal producers */ ++ pthread_mutex_lock(&oldq->lock); ++ oldq->qstate = KQEMPTY; ++ STATS_DRAIN(c->stats); ++ pthread_cond_broadcast(&oldq->cond); ++ pthread_mutex_unlock(&oldq->lock); ++ } ++ } ++ c->ridx = ridx; ++ return 1; ++} ++ ++#define HAVE_NONE 0 ++#define HAVE_KEY 1 ++#define HAVE_IV 2 ++int X = 0; ++ ++static int ++ssh_aes_ctr_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv, ++ int enc) ++{ ++ struct ssh_aes_ctr_ctx_mt *c; ++ int i; ++ ++ /* get the number of cores in the system */ ++ /* if it's not linux it currently defaults to 2 */ ++ /* divide by 2 to get threads for each direction (MODE_IN||MODE_OUT) */ ++#ifdef __linux__ ++ cipher_threads = sysconf(_SC_NPROCESSORS_ONLN) / 2; ++#endif /*__linux__*/ ++#ifdef __APPLE__ ++ cipher_threads = sysconf(_SC_NPROCESSORS_ONLN) / 2; ++#endif /*__APPLE__*/ ++#ifdef __FREEBSD__ ++ int req[2]; ++ size_t len; ++ ++ req[0] = CTL_HW; ++ req[1] = HW_NCPU; ++ ++ len = sizeof(ncpu); ++ sysctl(req, 2, &cipher_threads, &len, NULL, 0); ++ cipher_threads = cipher_threads / 2; ++#endif /*__FREEBSD__*/ ++ ++ /* if they have less than 4 cores spin up 4 threads anyway */ ++ if (cipher_threads < 2) ++ cipher_threads = 2; ++ ++ /* assure that we aren't trying to create more threads */ ++ /* than we have in the struct. cipher_threads is half the */ ++ /* total of allowable threads hence the odd looking math here */ ++ if (cipher_threads * 2 > MAX_THREADS) ++ cipher_threads = MAX_THREADS / 2; ++ ++ /* set the number of keystream queues */ ++ numkq = cipher_threads * 2; ++ ++ if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) { ++ c = xmalloc(sizeof(*c)); ++ pthread_rwlock_init(&c->tid_lock, NULL); ++#ifdef __APPLE__ ++ pthread_rwlock_init(&c->stop_lock, NULL); ++ c->exit_flag = FALSE; ++#endif /* __APPLE__ */ ++ ++ c->state = HAVE_NONE; ++ for (i = 0; i < numkq; i++) { ++ pthread_mutex_init(&c->q[i].lock, NULL); ++ pthread_cond_init(&c->q[i].cond, NULL); ++ } ++ ++ STATS_INIT(c->stats); ++ EVP_CIPHER_CTX_set_app_data(ctx, c); ++ } ++ ++ if (c->state == (HAVE_KEY | HAVE_IV)) { ++ /* tell the pregen threads to exit */ ++ stop_and_join_pregen_threads(c); ++ ++#ifdef __APPLE__ ++ /* reset the exit flag */ ++ c->exit_flag = FALSE; ++#endif /* __APPLE__ */ ++ ++ /* Start over getting key & iv */ ++ c->state = HAVE_NONE; ++ } ++ ++ if (key != NULL) { ++ AES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, ++ &c->aes_ctx); ++ c->state |= HAVE_KEY; ++ } ++ ++ if (iv != NULL) { ++ memcpy(c->aes_counter, iv, AES_BLOCK_SIZE); ++ c->state |= HAVE_IV; ++ } ++ ++ if (c->state == (HAVE_KEY | HAVE_IV)) { ++ /* Clear queues */ ++ memcpy(c->q[0].ctr, c->aes_counter, AES_BLOCK_SIZE); ++ c->q[0].qstate = KQINIT; ++ for (i = 1; i < numkq; i++) { ++ memcpy(c->q[i].ctr, c->aes_counter, AES_BLOCK_SIZE); ++ ssh_ctr_add(c->q[i].ctr, i * KQLEN, AES_BLOCK_SIZE); ++ c->q[i].qstate = KQEMPTY; ++ } ++ c->qidx = 0; ++ c->ridx = 0; ++ ++ /* Start threads */ ++ for (i = 0; i < cipher_threads; i++) { ++ pthread_rwlock_wrlock(&c->tid_lock); ++ if (pthread_create(&c->tid[i], NULL, thread_loop, c) != 0) ++ debug ("AES-CTR MT Could not create thread in %s", __FUNCTION__); /*should die here */ ++ else { ++ if (!c->struct_id) ++ c->struct_id = X++; ++ c->id[i] = i; ++ debug ("AES-CTR MT spawned a thread with id %lu in %s (%d, %d)", c->tid[i], __FUNCTION__, c->struct_id, c->id[i]); ++ } ++ pthread_rwlock_unlock(&c->tid_lock); ++ } ++ pthread_mutex_lock(&c->q[0].lock); ++ while (c->q[0].qstate == KQINIT) ++ pthread_cond_wait(&c->q[0].cond, &c->q[0].lock); ++ pthread_mutex_unlock(&c->q[0].lock); ++ } ++ return 1; ++} ++ ++/* this function is no longer used but might prove handy in the future ++ * this comment also applies to ssh_aes_ctr_thread_reconstruction ++ */ ++void ++ssh_aes_ctr_thread_destroy(EVP_CIPHER_CTX *ctx) ++{ ++ struct ssh_aes_ctr_ctx_mt *c; ++ ++ c = EVP_CIPHER_CTX_get_app_data(ctx); ++ stop_and_join_pregen_threads(c); ++} ++ ++void ++ssh_aes_ctr_thread_reconstruction(EVP_CIPHER_CTX *ctx) ++{ ++ struct ssh_aes_ctr_ctx_mt *c; ++ int i; ++ c = EVP_CIPHER_CTX_get_app_data(ctx); ++ /* reconstruct threads */ ++ for (i = 0; i < cipher_threads; i++) { ++ pthread_rwlock_wrlock(&c->tid_lock); ++ if (pthread_create(&c->tid[i], NULL, thread_loop, c) !=0 ) ++ debug("AES-CTR MT could not create thread in %s", __FUNCTION__); ++ else { ++ c->struct_id = X++; ++ c->id[i] = i; ++ debug ("AES-CTR MT spawned a thread with id %lu in %s (%d, %d)", c->tid[i], __FUNCTION__, c->struct_id, c->id[i]); ++ debug("AES-CTR MT spawned a thread with id %lu in %s", c->tid[i], __FUNCTION__); ++ } ++ pthread_rwlock_unlock(&c->tid_lock); ++ } ++} ++ ++static int ++ssh_aes_ctr_cleanup(EVP_CIPHER_CTX *ctx) ++{ ++ struct ssh_aes_ctr_ctx_mt *c; ++ ++ if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) { ++#ifdef CIPHER_THREAD_STATS ++ debug("AES-CTR MT main thread: %u drains, %u waits", c->stats.drains, ++ c->stats.waits); ++#endif ++ stop_and_join_pregen_threads(c); ++ ++ memset(c, 0, sizeof(*c)); ++ free(c); ++ EVP_CIPHER_CTX_set_app_data(ctx, NULL); ++ } ++ return 1; ++} ++ ++/* */ ++const EVP_CIPHER * ++evp_aes_ctr_mt(void) ++{ ++# if OPENSSL_VERSION_NUMBER >= 0x10100000UL ++ static EVP_CIPHER *aes_ctr; ++ aes_ctr = EVP_CIPHER_meth_new(NID_undef, 16/*block*/, 16/*key*/); ++ EVP_CIPHER_meth_set_iv_length(aes_ctr, AES_BLOCK_SIZE); ++ EVP_CIPHER_meth_set_init(aes_ctr, ssh_aes_ctr_init); ++ EVP_CIPHER_meth_set_cleanup(aes_ctr, ssh_aes_ctr_cleanup); ++ EVP_CIPHER_meth_set_do_cipher(aes_ctr, ssh_aes_ctr); ++# ifndef SSH_OLD_EVP ++ EVP_CIPHER_meth_set_flags(aes_ctr, EVP_CIPH_CBC_MODE ++ | EVP_CIPH_VARIABLE_LENGTH ++ | EVP_CIPH_ALWAYS_CALL_INIT ++ | EVP_CIPH_CUSTOM_IV); ++# endif /*SSH_OLD_EVP*/ ++ return (aes_ctr); ++# else /*earlier versions of openssl*/ ++ static EVP_CIPHER aes_ctr; ++ memset(&aes_ctr, 0, sizeof(EVP_CIPHER)); ++ aes_ctr.nid = NID_undef; ++ aes_ctr.block_size = AES_BLOCK_SIZE; ++ aes_ctr.iv_len = AES_BLOCK_SIZE; ++ aes_ctr.key_len = 16; ++ aes_ctr.init = ssh_aes_ctr_init; ++ aes_ctr.cleanup = ssh_aes_ctr_cleanup; ++ aes_ctr.do_cipher = ssh_aes_ctr; ++# ifndef SSH_OLD_EVP ++ aes_ctr.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH | ++ EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV; ++# endif /*SSH_OLD_EVP*/ ++ return &aes_ctr; ++# endif /*OPENSSH_VERSION_NUMBER*/ ++} ++ ++#endif /* defined(WITH_OPENSSL) */ +diff -Nur openssh-8.4p1.orig/cipher.h openssh-8.4p1/cipher.h +--- openssh-8.4p1.orig/cipher.h 2021-03-11 18:13:41.113603426 +0100 ++++ openssh-8.4p1/cipher.h 2021-03-11 18:16:31.130747879 +0100 +@@ -68,7 +68,9 @@ + + struct sshcipher_ctx; + +-const struct sshcipher *cipher_by_name(const char *); ++void ssh_aes_ctr_thread_destroy(EVP_CIPHER_CTX *ctx); // defined in cipher-ctr-mt.c ++void ssh_aes_ctr_thread_reconstruction(EVP_CIPHER_CTX *ctx); ++struct sshcipher *cipher_by_name(const char *); + const char *cipher_warning_message(const struct sshcipher_ctx *); + int ciphers_valid(const char *); + char *cipher_alg_list(char, int); +@@ -86,7 +88,10 @@ + u_int cipher_authlen(const struct sshcipher *); + u_int cipher_ivlen(const struct sshcipher *); + u_int cipher_is_cbc(const struct sshcipher *); ++void cipher_reset_multithreaded(void); ++const char *cipher_ctx_name(const struct sshcipher_ctx *); + ++const char *cipher_ctx_name(const struct sshcipher_ctx *); + u_int cipher_ctx_is_plaintext(struct sshcipher_ctx *); + + int cipher_get_keyiv(struct sshcipher_ctx *, u_char *, size_t); +diff -Nur openssh-8.4p1.orig/clientloop.c openssh-8.4p1/clientloop.c +--- openssh-8.4p1.orig/clientloop.c 2021-03-11 18:13:40.875605976 +0100 ++++ openssh-8.4p1/clientloop.c 2021-03-11 18:16:31.131747868 +0100 +@@ -1610,9 +1610,11 @@ + sock = x11_connect_display(ssh); + if (sock < 0) + return NULL; +- c = channel_new(ssh, "x11", +- SSH_CHANNEL_X11_OPEN, sock, sock, -1, +- CHAN_TCP_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, 0, "x11", 1); ++ c = channel_new(ssh, "x11", ++ SSH_CHANNEL_X11_OPEN, sock, sock, -1, ++ /* again is this really necessary for X11? */ ++ options.hpn_disabled ? CHAN_TCP_WINDOW_DEFAULT : options.hpn_buffer_size, ++ CHAN_X11_PACKET_DEFAULT, 0, "x11", 1); + c->force_drain = 1; + return c; + } +@@ -1641,9 +1643,10 @@ + return NULL; + } + c = channel_new(ssh, "authentication agent connection", +- SSH_CHANNEL_OPEN, sock, sock, -1, +- CHAN_X11_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, +- "authentication agent connection", 1); ++ SSH_CHANNEL_OPEN, sock, sock, -1, ++ options.hpn_disabled ? CHAN_X11_WINDOW_DEFAULT : options.hpn_buffer_size, ++ CHAN_TCP_PACKET_DEFAULT, 0, ++ "authentication agent connection", 1); + c->force_drain = 1; + return c; + } +@@ -1668,10 +1671,13 @@ + } + debug("Tunnel forwarding using interface %s", ifname); + +- c = channel_new(ssh, "tun", SSH_CHANNEL_OPENING, fd, fd, -1, +- CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1); ++ c = channel_new(ssh, "tun", SSH_CHANNEL_OPENING, fd, fd, -1, ++ options.hpn_disabled ? CHAN_TCP_WINDOW_DEFAULT : options.hpn_buffer_size, ++ CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1); + c->datagram = 1; + ++ ++ + #if defined(SSH_TUN_FILTER) + if (options.tun_open == SSH_TUNMODE_POINTOPOINT) + channel_register_filter(ssh, c->self, sys_tun_infilter, +diff -Nur openssh-8.4p1.orig/compat.c openssh-8.4p1/compat.c +--- openssh-8.4p1.orig/compat.c 2021-03-11 18:13:41.099603576 +0100 ++++ openssh-8.4p1/compat.c 2021-03-11 18:16:31.132747857 +0100 +@@ -151,6 +151,15 @@ + debug("match: %s pat %s compat 0x%08x", + version, check[i].pat, check[i].bugs); + datafellows = check[i].bugs; /* XXX for now */ ++ /* Check to see if the remote side is OpenSSH and not HPN */ ++ if (strstr(version, "OpenSSH") != NULL) { ++ if (strstr(version, "hpn") == NULL) { ++ datafellows |= SSH_BUG_LARGEWINDOW; ++ debug("Remote is NOT HPN enabled"); ++ } else { ++ debug("Remote is HPN Enabled"); ++ } ++ } + return check[i].bugs; + } + } +diff -Nur openssh-8.4p1.orig/compat.h openssh-8.4p1/compat.h +--- openssh-8.4p1.orig/compat.h 2021-03-11 18:13:41.085603726 +0100 ++++ openssh-8.4p1/compat.h 2021-03-11 18:16:31.132747857 +0100 +@@ -57,6 +57,7 @@ + #define SSH_BUG_CURVE25519PAD 0x10000000 + #define SSH_BUG_HOSTKEYS 0x20000000 + #define SSH_BUG_DHGEX_LARGE 0x40000000 ++#define SSH_BUG_LARGEWINDOW 0x80000000 + + u_int compat_datafellows(const char *); + char *compat_cipher_proposal(char *); +diff -Nur openssh-8.4p1.orig/defines.h openssh-8.4p1/defines.h +--- openssh-8.4p1.orig/defines.h 2020-09-27 09:25:01.000000000 +0200 ++++ openssh-8.4p1/defines.h 2021-03-11 18:16:31.132747857 +0100 +@@ -848,7 +848,7 @@ + #endif + + #ifndef SSH_IOBUFSZ +-# define SSH_IOBUFSZ 8192 ++# define SSH_IOBUFSZ 32*1024 + #endif + + /* +diff -Nur openssh-8.4p1.orig/digest.h openssh-8.4p1/digest.h +--- openssh-8.4p1.orig/digest.h 2021-03-11 18:13:41.070603887 +0100 ++++ openssh-8.4p1/digest.h 2021-03-11 18:16:31.133747846 +0100 +@@ -27,7 +27,8 @@ + #define SSH_DIGEST_SHA256 2 + #define SSH_DIGEST_SHA384 3 + #define SSH_DIGEST_SHA512 4 +-#define SSH_DIGEST_MAX 5 ++#define SSH_DIGEST_NULL 5 ++#define SSH_DIGEST_MAX 6 + + struct sshbuf; + struct ssh_digest_ctx; +diff -Nur openssh-8.4p1.orig/digest-openssl.c openssh-8.4p1/digest-openssl.c +--- openssh-8.4p1.orig/digest-openssl.c 2021-03-11 18:13:41.070603887 +0100 ++++ openssh-8.4p1/digest-openssl.c 2021-03-11 18:16:31.133747846 +0100 +@@ -61,7 +61,8 @@ + { SSH_DIGEST_SHA256, "SHA256", 32, EVP_sha256 }, + { SSH_DIGEST_SHA384, "SHA384", 48, EVP_sha384 }, + { SSH_DIGEST_SHA512, "SHA512", 64, EVP_sha512 }, +- { -1, NULL, 0, NULL }, ++ { SSH_DIGEST_NULL, "NONEMAC", 0, EVP_md_null}, ++ { -1, NULL, 0, NULL }, + }; + + const EVP_MD * +diff -Nur openssh-8.4p1.orig/HPN-README openssh-8.4p1/HPN-README +--- openssh-8.4p1.orig/HPN-README 1970-01-01 01:00:00.000000000 +0100 ++++ openssh-8.4p1/HPN-README 2021-03-11 18:16:31.124747944 +0100 +@@ -0,0 +1,153 @@ ++Notes: ++ ++MULTI-THREADED CIPHER: ++The AES cipher in CTR mode has been multithreaded (MTR-AES-CTR). This will allow ssh installations ++on hosts with multiple cores to use more than one processing core during encryption. ++Tests have show significant throughput performance increases when using MTR-AES-CTR up ++to and including a full gigabit per second on quad core systems. It should be possible to ++achieve full line rate on dual core systems but OS and data management overhead makes this ++more difficult to achieve. The cipher stream from MTR-AES-CTR is entirely compatible with single ++thread AES-CTR (ST-AES-CTR) implementations and should be 100% backward compatible. Optimal ++performance requires the MTR-AES-CTR mode be enabled on both ends of the connection. ++The MTR-AES-CTR replaces ST-AES-CTR and is used in exactly the same way with the same ++nomenclature. ++Use examples: ++ ssh -caes128-ctr you@host.com ++ scp -oCipher=aes256-ctr file you@host.com:~/file ++ ++NONE CIPHER: ++To use the NONE option you must have the NoneEnabled switch set on the server and ++you *must* have *both* NoneEnabled and NoneSwitch set to yes on the client. The NONE ++feature works with ALL ssh subsystems (as far as we can tell) *AS LONG AS* a tty is not ++spawned. If a user uses the -T switch to prevent a tty being created the NONE cipher will ++be disabled. ++ ++The performance increase will only be as good as the network and TCP stack tuning ++on the reciever side of the connection allows. As a rule of thumb a user will need ++at least 10Mb/s connection with a 100ms RTT to see a doubling of performance. The ++HPN-SSH home page describes this in greater detail. ++ ++http://www.psc.edu/networking/projects/hpn-ssh ++ ++NONE MAC: ++Starting with HPN 15v1 users will have the option to disable HMAC (message ++authentication ciphers) when using the NONE cipher. You must enable the following: ++NoneEnabled, NoneSwitch, and NoneMacEnabled. If all three are not enabled the None MAC ++will be automatically disabled. In tests the use of the None MAC improved throuput by ++more than 30%. ++ ++ex: scp -oNoneSwitch=yes -oNoneEnabled=yes -oNoneMacEnabled=yes file host:~ ++ ++BUFFER SIZES: ++ ++If HPN is disabled the receive buffer size will be set to the ++OpenSSH default of 2MB (for OpenSSH versions before 4.7: 64KB). ++ ++If an HPN system connects to a nonHPN system the receive buffer will ++be set to the HPNBufferSize value. The default is 2MB but user adjustable. ++ ++If an HPN to HPN connection is established a number of different things might ++happen based on the user options and conditions. ++ ++Conditions: HPNBufferSize NOT Set, TCPRcvBufPoll enabled, TCPRcvBuf NOT Set ++HPN Buffer Size = up to 64MB ++This is the default state. The HPN buffer size will grow to a maximum of 64MB ++as the TCP receive buffer grows. The maximum HPN Buffer size of 64MB is ++geared towards 10GigE transcontinental connections. ++ ++Conditions: HPNBufferSize NOT Set, TCPRcvBufPoll disabled, TCPRcvBuf NOT Set ++HPN Buffer Size = TCP receive buffer value. ++Users on non-autotuning systems should disable TCPRcvBufPoll in the ++ssh_config and sshd_config ++ ++Conditions: HPNBufferSize SET, TCPRcvBufPoll disabled, TCPRcvBuf NOT Set ++HPN Buffer Size = minimum of TCP receive buffer and HPNBufferSize. ++This would be the system defined TCP receive buffer (RWIN). ++ ++Conditions: HPNBufferSize SET, TCPRcvBufPoll disabled, TCPRcvBuf SET ++HPN Buffer Size = minimum of TCPRcvBuf and HPNBufferSize. ++Generally there is no need to set both. ++ ++Conditions: HPNBufferSize SET, TCPRcvBufPoll enabled, TCPRcvBuf NOT Set ++HPN Buffer Size = grows to HPNBufferSize ++The buffer will grow up to the maximum size specified here. ++ ++Conditions: HPNBufferSize SET, TCPRcvBufPoll enabled, TCPRcvBuf SET ++HPN Buffer Size = minimum of TCPRcvBuf and HPNBufferSize. ++Generally there is no need to set both of these, especially on autotuning ++systems. However, if the users wishes to override the autotuning this would be ++one way to do it. ++ ++Conditions: HPNBufferSize NOT Set, TCPRcvBufPoll enabled, TCPRcvBuf SET ++HPN Buffer Size = TCPRcvBuf. ++This will override autotuning and set the TCP recieve buffer to the user defined ++value. ++ ++ ++HPN Specific Configuration options ++ ++TcpRcvBuf=[int]KB client ++ Set the TCP socket receive buffer to n Kilobytes. It can be set up to the ++maximum socket size allowed by the system. This is useful in situations where ++the tcp receive window is set low but the maximum buffer size is set ++higher (as is typical). This works on a per TCP connection basis. You can also ++use this to artifically limit the transfer rate of the connection. In these ++cases the throughput will be no more than n/RTT. The minimum buffer size is 1KB. ++Default is the current system wide tcp receive buffer size. ++ ++TcpRcvBufPoll=[yes/no] client/server ++ Enable of disable the polling of the tcp receive buffer through the life ++of the connection. You would want to make sure that this option is enabled ++for systems making use of autotuning kernels (linux 2.4.24+, 2.6, MS Vista) ++default is yes. ++ ++NoneEnabled=[yes/no] client/server ++ Enable or disable the use of the None cipher. Care must always be used ++when enabling this as it will allow users to send data in the clear. However, ++it is important to note that authentication information remains encrypted ++even if this option is enabled. Set to no by default. ++ ++NoneMacEnabled=[yes/no] client/server ++ Enable or disable the use of the None MAC. When this is enabled ssh ++will *not* provide data integrity of any data being transmitted between hosts. Use ++with caution as it, unlike just using NoneEnabled, doesn't provide data integrity and ++protection against man-in-the-middle attacks. As with NoneEnabled all authentication ++remains encrypted and integrity is ensured. Default is no. ++ ++NoneSwitch=[yes/no] client ++ Switch the encryption cipher being used to the None cipher after ++authentication takes place. NoneEnabled must be enabled on both the client ++and server side of the connection. When the connection switches to the NONE ++cipher a warning is sent to STDERR. The connection attempt will fail with an ++error if a client requests a NoneSwitch from the server that does not explicitly ++have NoneEnabled set to yes. Note: The NONE cipher cannot be used in ++interactive (shell) sessions and it will fail silently. Set to no by default. ++ ++HPNDisabled=[yes/no] client/server ++ In some situations, such as transfers on a local area network, the impact ++of the HPN code produces a net decrease in performance. In these cases it is ++helpful to disable the HPN functionality. By default HPNDisabled is set to no. ++ ++HPNBufferSize=[int]KB client/server ++ This is the default buffer size the HPN functionality uses when interacting ++with nonHPN SSH installations. Conceptually this is similar to the TcpRcvBuf ++option as applied to the internal SSH flow control. This value can range from ++1KB to 64MB (1-65536). Use of oversized or undersized buffers can cause performance ++problems depending on the length of the network path. The default size of this buffer ++is 2MB. ++ ++DisableMTAES=[yes/no] client/server ++ Switch the encryption cipher being used from the multithreaded MT-AES-CTR cipher ++back to the stock single-threaded AES-CTR cipher. Useful on modern processors with ++AES-NI instructions which make the stock single-threaded AES-CTR cipher faster than ++the multithreaded MT-AES-CTR cipher. Set to no by default. ++ ++ ++Credits: This patch was conceived, designed, and led by Chris Rapier (rapier@psc.edu) ++ The majority of the actual coding for versions up to HPN12v1 was performed ++ by Michael Stevens (mstevens@andrew.cmu.edu). The MT-AES-CTR cipher was ++ implemented by Ben Bennet (ben@psc.edu) and improved by Mike Tasota ++ (tasota@gmail.com) an NSF REU grant recipient for 2013. ++ Allan Jude provided the code for the NoneMac and buffer normalization. ++ This work was financed, in part, by Cisco System, Inc., the National ++ Library of Medicine, and the National Science Foundation. +diff -Nur openssh-8.4p1.orig/kex.c openssh-8.4p1/kex.c +--- openssh-8.4p1.orig/kex.c 2021-03-11 18:13:41.127603276 +0100 ++++ openssh-8.4p1/kex.c 2021-03-11 18:16:31.134747835 +0100 +@@ -64,6 +64,7 @@ + + #include "ssherr.h" + #include "sshbuf.h" ++#include "canohost.h" + #include "digest.h" + #include "audit.h" + +@@ -967,6 +968,11 @@ + int nenc, nmac, ncomp; + u_int mode, ctos, need, dh_need, authlen; + int r, first_kex_follows; ++ int auth_flag = 0; ++ int log_flag = 0; ++ ++ auth_flag = packet_authentication_state(ssh); ++ debug("AUTH STATE IS %d", auth_flag); + + debug2("local %s KEXINIT proposal", kex->server ? "server" : "client"); + if ((r = kex_buf2prop(kex->my, NULL, &my)) != 0) +@@ -1037,11 +1043,40 @@ + peer[ncomp] = NULL; + goto out; + } ++ debug("REQUESTED ENC.NAME is '%s'", newkeys->enc.name); ++ debug("REQUESTED MAC.NAME is '%s'", newkeys->mac.name); ++ if (strcmp(newkeys->enc.name, "none") == 0) { ++ if (auth_flag == 1) { ++ debug("None requested post authentication."); ++ ssh->none = 1; ++ } ++ else ++ fatal("Pre-authentication none cipher requests are not allowed."); ++ if (newkeys->mac.name != NULL && strcmp(newkeys->mac.name, "none") == 0) ++ debug("Requesting: NONEMAC. Authflag is %d", auth_flag); ++ } ++ + debug("kex: %s cipher: %s MAC: %s compression: %s", + ctos ? "client->server" : "server->client", + newkeys->enc.name, + authlen == 0 ? newkeys->mac.name : "", + newkeys->comp.name); ++ /* ++ * client starts with ctos = 0 && log flag = 0 and no log. ++ * 2nd client pass ctos = 1 and flag = 1 so no log. ++ * server starts with ctos = 1 && log_flag = 0 so log. ++ * 2nd sever pass ctos = 1 && log flag = 1 so no log. ++ * -cjr ++ */ ++ if (ctos && !log_flag) { ++ logit("SSH: Server;Ltype: Kex;Remote: %s-%d;Enc: %s;MAC: %s;Comp: %s", ++ ssh_remote_ipaddr(ssh), ++ ssh_remote_port(ssh), ++ newkeys->enc.name, ++ authlen == 0 ? newkeys->mac.name : "", ++ newkeys->comp.name); ++ } ++ log_flag = 1; + } + need = dh_need = 0; + for (mode = 0; mode < MODE_MAX; mode++) { +@@ -1386,7 +1421,7 @@ + if (version_addendum != NULL && *version_addendum == '\0') + version_addendum = NULL; + if ((r = sshbuf_putf(our_version, "SSH-%d.%d-%.100s%s%s\r\n", +- PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, SSH_VERSION, ++ PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, SSH_RELEASE, + version_addendum == NULL ? "" : " ", + version_addendum == NULL ? "" : version_addendum)) != 0) { + oerrno = errno; +@@ -1526,6 +1561,14 @@ + r = SSH_ERR_INVALID_FORMAT; + goto out; + } ++ ++ /* report the version information to syslog if this is the server */ ++ if (timeout_ms == -1) { /* only the server uses this value */ ++ logit("SSH: Server;Ltype: Version;Remote: %s-%d;Protocol: %d.%d;Client: %.100s", ++ ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), ++ remote_major, remote_minor, remote_version); ++ } ++ + debug("Remote protocol version %d.%d, remote software version %.100s", + remote_major, remote_minor, remote_version); + ssh->compat = compat_datafellows(remote_version); +diff -Nur openssh-8.4p1.orig/log.c openssh-8.4p1/log.c +--- openssh-8.4p1.orig/log.c 2021-03-11 18:13:41.012604510 +0100 ++++ openssh-8.4p1/log.c 2021-03-11 18:16:31.135747825 +0100 +@@ -46,6 +46,11 @@ + #include + #include + #include ++#include "packet.h" /* needed for host and port look ups */ ++#ifdef HAVE_SYS_TIME_H ++# include /* to get current time */ ++#endif ++ + #if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS) + # include + #endif +@@ -62,6 +67,8 @@ + + extern char *__progname; + ++extern struct ssh *active_state; ++ + #define LOG_SYSLOG_VIS (VIS_CSTYLE|VIS_NL|VIS_TAB|VIS_OCTAL) + #define LOG_STDERR_VIS (VIS_SAFE|VIS_OCTAL) + +diff -Nur openssh-8.4p1.orig/mac.c openssh-8.4p1/mac.c +--- openssh-8.4p1.orig/mac.c 2021-03-11 18:13:41.114603415 +0100 ++++ openssh-8.4p1/mac.c 2021-03-11 18:16:31.135747825 +0100 +@@ -63,6 +63,7 @@ + { "hmac-sha2-512", SSH_DIGEST, SSH_DIGEST_SHA512, 0, 0, 0, 0 }, + { "hmac-md5", SSH_DIGEST, SSH_DIGEST_MD5, 0, 0, 0, 0 }, + { "hmac-md5-96", SSH_DIGEST, SSH_DIGEST_MD5, 96, 0, 0, 0 }, ++ { "none", SSH_DIGEST, SSH_DIGEST_NULL, 0, 0, 0, 0 }, + { "umac-64@openssh.com", SSH_UMAC, 0, 0, 128, 64, 0 }, + { "umac-128@openssh.com", SSH_UMAC128, 0, 0, 128, 128, 0 }, + +diff -Nur openssh-8.4p1.orig/Makefile.in openssh-8.4p1/Makefile.in +--- openssh-8.4p1.orig/Makefile.in 2021-03-11 18:13:41.154602986 +0100 ++++ openssh-8.4p1/Makefile.in 2021-03-11 18:16:31.124747944 +0100 +@@ -49,7 +49,7 @@ + CFLAGS_NOPIE=@CFLAGS_NOPIE@ + CPPFLAGS=-I. -I$(srcdir) @CPPFLAGS@ $(PATHS) @DEFS@ + PICFLAG=@PICFLAG@ +-LIBS=@LIBS@ ++LIBS=@LIBS@ -lpthread + K5LIBS=@K5LIBS@ + GSSLIBS=@GSSLIBS@ + SSHDLIBS=@SSHDLIBS@ +@@ -96,7 +96,7 @@ + LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ + authfd.o authfile.o \ + canohost.o channels.o cipher.o cipher-aes.o cipher-aesctr.o \ +- cipher-ctr.o cleanup.o \ ++ cipher-ctr.o cleanup.o cipher-ctr-mt.o \ + compat.o fatal.o hostfile.o \ + log.o match.o moduli.o nchan.o packet.o \ + readpass.o ttymodes.o xmalloc.o addrmatch.o \ +diff -Nur openssh-8.4p1.orig/packet.c openssh-8.4p1/packet.c +--- openssh-8.4p1.orig/packet.c 2021-03-11 18:13:41.117603383 +0100 ++++ openssh-8.4p1/packet.c 2021-03-11 18:16:31.136747814 +0100 +@@ -246,7 +246,7 @@ + TAILQ_INIT(&ssh->public_keys); + state->connection_in = -1; + state->connection_out = -1; +- state->max_packet_size = 32768; ++ state->max_packet_size = CHAN_SES_PACKET_DEFAULT; + state->packet_timeout_ms = -1; + state->p_send.packets = state->p_read.packets = 0; + state->initialized = 1; +@@ -294,7 +294,7 @@ + ssh_packet_set_connection(struct ssh *ssh, int fd_in, int fd_out) + { + struct session_state *state; +- const struct sshcipher *none = cipher_by_name("none"); ++ struct sshcipher *none = cipher_by_name("none"); + int r; + + if (none == NULL) { +@@ -970,18 +970,45 @@ + * so enforce a 1GB limit for small blocksizes. + * See RFC4344 section 3.2. + */ +- if (enc->block_size >= 16) +- *max_blocks = (u_int64_t)1 << (enc->block_size*2); +- else +- *max_blocks = ((u_int64_t)1 << 30) / enc->block_size; ++ ++ /* we really don't need to rekey if we are using the none cipher ++ * but there isn't a good way to disable it entirely that I can find ++ * and using a blocksize larger that 16 doesn't work (dunno why) ++ * so this seems to be a good limit for now - CJR 10/16/2020*/ ++ if (ssh->none == 1) { ++ *max_blocks = (u_int64_t)1 << (16*2); ++ } else { ++ if (enc->block_size >= 16) ++ *max_blocks = (u_int64_t)1 << (enc->block_size*2); ++ else ++ *max_blocks = ((u_int64_t)1 << 30) / enc->block_size; ++ } + if (state->rekey_limit) + *max_blocks = MINIMUM(*max_blocks, + state->rekey_limit / enc->block_size); + debug("rekey %s after %llu blocks", dir, +- (unsigned long long)*max_blocks); ++ (unsigned long long)*max_blocks); + return 0; + } + ++/* this supports the forced rekeying required for the NONE cipher */ ++int rekey_requested = 0; ++void ++packet_request_rekeying(void) ++{ ++ rekey_requested = 1; ++} ++ ++/* used to determine if pre or post auth when rekeying for aes-ctr ++ * and none cipher switch */ ++int ++packet_authentication_state(const struct ssh *ssh) ++{ ++ struct session_state *state = ssh->state; ++ ++ return state->after_authentication; ++} ++ + #define MAX_PACKETS (1U<<31) + static int + ssh_packet_need_rekeying(struct ssh *ssh, u_int outbound_packet_len) +@@ -1008,6 +1035,13 @@ + if (state->p_send.packets == 0 && state->p_read.packets == 0) + return 0; + ++ /* used to force rekeying when called for by the none ++ * cipher switch and aes-mt-ctr methods -cjr */ ++ if (rekey_requested == 1) { ++ rekey_requested = 0; ++ return 1; ++ } ++ + /* Time-based rekeying */ + if (state->rekey_interval != 0 && + (int64_t)state->rekey_time + state->rekey_interval <= monotime()) +@@ -1346,7 +1380,7 @@ + struct session_state *state = ssh->state; + int len, r, ms_remain; + fd_set *setp; +- char buf[8192]; ++ char buf[SSH_IOBUFSZ]; + struct timeval timeout, start, *timeoutp = NULL; + + DBG(debug("packet_read()")); +@@ -1878,17 +1912,21 @@ + switch (r) { + case SSH_ERR_CONN_CLOSED: + ssh_packet_clear_keys(ssh); ++ sshpkt_final_log_entry(ssh); + logdie("Connection closed by %s", remote_id); + case SSH_ERR_CONN_TIMEOUT: + ssh_packet_clear_keys(ssh); ++ sshpkt_final_log_entry(ssh); + logdie("Connection %s %s timed out", + ssh->state->server_side ? "from" : "to", remote_id); + case SSH_ERR_DISCONNECTED: + ssh_packet_clear_keys(ssh); ++ sshpkt_final_log_entry(ssh); + logdie("Disconnected from %s", remote_id); + case SSH_ERR_SYSTEM_ERROR: + if (errno == ECONNRESET) { + ssh_packet_clear_keys(ssh); ++ sshpkt_final_log_entry(ssh); + logdie("Connection reset by %s", remote_id); + } + /* FALLTHROUGH */ +@@ -1932,6 +1970,24 @@ + logdie("%s: should have exited", __func__); + } + ++/* this prints out the final log entry */ ++void ++sshpkt_final_log_entry (struct ssh *ssh) { ++ double total_time; ++ ++ if (ssh->start_time < 1) ++ /* this will produce a NaN in the output. -cjr */ ++ total_time = 0; ++ else ++ total_time = monotime_double() - ssh->start_time; ++ ++ logit("SSH: Server;LType: Throughput;Remote: %s-%d;IN: %lu;OUT: %lu;Duration: %.1f;tPut_in: %.1f;tPut_out: %.1f", ++ ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), ++ ssh->stdin_bytes, ssh->fdout_bytes, total_time, ++ ssh->stdin_bytes / total_time, ++ ssh->fdout_bytes / total_time); ++} ++ + /* + * Logs the error plus constructs and sends a disconnect packet, closes the + * connection, and exits. This function never returns. The error message +@@ -2827,3 +2883,10 @@ + ssh->state->extra_pad = pad; + return 0; + } ++ ++/* need this for the moment for the aes-ctr cipher */ ++void * ++ssh_packet_get_send_context(struct ssh *ssh) ++{ ++ return ssh->state->send_context; ++} +diff -Nur openssh-8.4p1.orig/packet.h openssh-8.4p1/packet.h +--- openssh-8.4p1.orig/packet.h 2021-03-11 18:13:41.117603383 +0100 ++++ openssh-8.4p1/packet.h 2021-03-11 18:16:31.136747814 +0100 +@@ -86,6 +86,14 @@ + + /* APP data */ + void *app_data; ++ ++ /* logging data for ServerLogging patch*/ ++ double start_time; ++ u_long fdout_bytes; ++ u_long stdin_bytes; ++ ++ /* track that we are in a none cipher/mac state */ ++ int none; + }; + + typedef int (ssh_packet_hook_fn)(struct ssh *, struct sshbuf *, +@@ -155,6 +163,8 @@ + int ssh_packet_set_maxsize(struct ssh *, u_int); + u_int ssh_packet_get_maxsize(struct ssh *); + ++int packet_authentication_state(const struct ssh *); ++ + int ssh_packet_get_state(struct ssh *, struct sshbuf *); + int ssh_packet_set_state(struct ssh *, struct sshbuf *); + +@@ -169,6 +179,13 @@ + + void *ssh_packet_get_input(struct ssh *); + void *ssh_packet_get_output(struct ssh *); ++void *ssh_packet_get_receive_context(struct ssh *); ++void *ssh_packet_get_send_context(struct ssh *); ++ ++/* for forced packet rekeying post auth */ ++void packet_request_rekeying(void); ++/* final log entry support */ ++void sshpkt_final_log_entry (struct ssh *); + + /* new API */ + int sshpkt_start(struct ssh *ssh, u_char type); +diff -Nur openssh-8.4p1.orig/progressmeter.c openssh-8.4p1/progressmeter.c +--- openssh-8.4p1.orig/progressmeter.c 2020-09-27 09:25:01.000000000 +0200 ++++ openssh-8.4p1/progressmeter.c 2021-03-11 18:16:31.136747814 +0100 +@@ -68,6 +68,8 @@ + static off_t start_pos; /* initial position of transfer */ + static off_t end_pos; /* ending position of transfer */ + static off_t cur_pos; /* transfer position as of last refresh */ ++static off_t last_pos; ++static off_t max_delta_pos = 0; + static volatile off_t *counter; /* progress counter */ + static long stalled; /* how long we have been stalled */ + static int bytes_per_second; /* current speed in bytes per second */ +@@ -127,6 +129,7 @@ + int cur_speed; + int hours, minutes, seconds; + int file_len; ++ off_t delta_pos; + + if ((!force_update && !alarm_fired && !win_resized) || !can_output()) + return; +@@ -142,6 +145,10 @@ + now = monotime_double(); + bytes_left = end_pos - cur_pos; + ++ delta_pos = cur_pos - last_pos; ++ if (delta_pos > max_delta_pos) ++ max_delta_pos = delta_pos; ++ + if (bytes_left > 0) + elapsed = now - last_update; + else { +@@ -166,7 +173,7 @@ + + /* filename */ + buf[0] = '\0'; +- file_len = win_size - 36; ++ file_len = win_size - 45; + if (file_len > 0) { + buf[0] = '\r'; + snmprintf(buf+1, sizeof(buf)-1, &file_len, "%-*s", +@@ -191,6 +198,15 @@ + (off_t)bytes_per_second); + strlcat(buf, "/s ", win_size); + ++ /* instantaneous rate */ ++ if (bytes_left > 0) ++ format_rate(buf + strlen(buf), win_size - strlen(buf), ++ delta_pos); ++ else ++ format_rate(buf + strlen(buf), win_size - strlen(buf), ++ max_delta_pos); ++ strlcat(buf, "/s ", win_size); ++ + /* ETA */ + if (!transferred) + stalled += elapsed; +@@ -227,6 +243,7 @@ + + atomicio(vwrite, STDOUT_FILENO, buf, win_size - 1); + last_update = now; ++ last_pos = cur_pos; + } + + /*ARGSUSED*/ +diff -Nur openssh-8.4p1.orig/readconf.c openssh-8.4p1/readconf.c +--- openssh-8.4p1.orig/readconf.c 2021-03-11 18:13:41.146603072 +0100 ++++ openssh-8.4p1/readconf.c 2021-03-11 18:18:58.965186079 +0100 +@@ -67,6 +67,7 @@ + #include "uidswap.h" + #include "myproposal.h" + #include "digest.h" ++#include "sshbuf.h" + #include "ssh-gss.h" + + /* Format of the configuration file: +@@ -168,6 +169,9 @@ + oHashKnownHosts, + oTunnel, oTunnelDevice, + oLocalCommand, oPermitLocalCommand, oRemoteCommand, ++ oTcpRcvBufPoll, oTcpRcvBuf, oHPNDisabled, oHPNBufferSize, ++ oNoneEnabled, oNoneMacEnabled, oNoneSwitch, ++ oDisableMTAES, + oVisualHostKey, + oKexAlgorithms, oIPQoS, oRequestTTY, oIgnoreUnknown, oProxyUseFdpass, + oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots, +@@ -309,6 +313,10 @@ + { "kexalgorithms", oKexAlgorithms }, + { "ipqos", oIPQoS }, + { "requesttty", oRequestTTY }, ++ { "noneenabled", oNoneEnabled }, ++ { "nonemacenabled", oNoneMacEnabled }, ++ { "noneswitch", oNoneSwitch }, ++ { "disablemtaes", oDisableMTAES }, + { "proxyusefdpass", oProxyUseFdpass }, + { "canonicaldomains", oCanonicalDomains }, + { "canonicalizefallbacklocal", oCanonicalizeFallbackLocal }, +@@ -325,7 +333,10 @@ + { "ignoreunknown", oIgnoreUnknown }, + { "proxyjump", oProxyJump }, + { "securitykeyprovider", oSecurityKeyProvider }, +- ++ { "tcprcvbufpoll", oTcpRcvBufPoll }, ++ { "tcprcvbuf", oTcpRcvBuf }, ++ { "hpndisabled", oHPNDisabled }, ++ { "hpnbuffersize", oHPNBufferSize }, + { NULL, oBadOption } + }; + +@@ -1127,6 +1138,46 @@ + intptr = &options->check_host_ip; + goto parse_flag; + ++ case oHPNDisabled: ++ intptr = &options->hpn_disabled; ++ goto parse_flag; ++ ++ case oHPNBufferSize: ++ intptr = &options->hpn_buffer_size; ++ goto parse_int; ++ ++ case oTcpRcvBufPoll: ++ intptr = &options->tcp_rcv_buf_poll; ++ goto parse_flag; ++ ++ case oNoneEnabled: ++ intptr = &options->none_enabled; ++ goto parse_flag; ++ ++ case oNoneMacEnabled: ++ intptr = &options->nonemac_enabled; ++ goto parse_flag; ++ ++ case oDisableMTAES: ++ intptr = &options->disable_multithreaded; ++ goto parse_flag; ++ ++ /* ++ * We check to see if the command comes from the command ++ * line or not. If it does then enable it otherwise fail. ++ * NONE should never be a default configuration. ++ */ ++ case oNoneSwitch: ++ if (strcmp(filename, "command-line") == 0) { ++ intptr = &options->none_switch; ++ goto parse_flag; ++ } else { ++ error("NoneSwitch is found in %.200s.\nYou may only use this configuration option from the command line", filename); ++ error("Continuing..."); ++ debug("NoneSwitch directive found in %.200s.", filename); ++ return 0; ++ } ++ + case oVerifyHostKeyDNS: + intptr = &options->verify_host_key_dns; + multistate_ptr = multistate_yesnoask; +@@ -1327,6 +1378,10 @@ + *intptr = value; + break; + ++ case oTcpRcvBuf: ++ intptr = &options->tcp_rcv_buf; ++ goto parse_int; ++ + case oCiphers: + arg = strdelim(&s); + if (!arg || *arg == '\0') +@@ -2103,6 +2158,14 @@ + options->ip_qos_interactive = -1; + options->ip_qos_bulk = -1; + options->request_tty = -1; ++ options->none_switch = -1; ++ options->none_enabled = -1; ++ options->nonemac_enabled = -1; ++ options->disable_multithreaded = -1; ++ options->hpn_disabled = -1; ++ options->hpn_buffer_size = -1; ++ options->tcp_rcv_buf_poll = -1; ++ options->tcp_rcv_buf = -1; + options->proxy_use_fdpass = -1; + options->ignored_unknown = NULL; + options->num_canonical_domains = 0; +@@ -2269,6 +2332,43 @@ + options->server_alive_interval = 0; + if (options->server_alive_count_max == -1) + options->server_alive_count_max = 3; ++ if (options->hpn_disabled == -1) ++ options->hpn_disabled = 0; ++ if (options->hpn_buffer_size > -1) { ++ /* if a user tries to set the size to 0 set it to 1KB */ ++ if (options->hpn_buffer_size == 0) ++ options->hpn_buffer_size = 1; ++ /* limit the buffer to SSHBUF_SIZE_MAX (currently 256MB) */ ++ if (options->hpn_buffer_size > (SSHBUF_SIZE_MAX / 1024)) { ++ options->hpn_buffer_size = SSHBUF_SIZE_MAX; ++ debug("User requested buffer larger than 256MB. Request reverted to 256MB"); ++ } else ++ options->hpn_buffer_size *= 1024; ++ debug("hpn_buffer_size set to %d", options->hpn_buffer_size); ++ } ++ if (options->tcp_rcv_buf == 0) ++ options->tcp_rcv_buf = 1; ++ if (options->tcp_rcv_buf > -1) ++ options->tcp_rcv_buf *=1024; ++ if (options->tcp_rcv_buf_poll == -1) ++ options->tcp_rcv_buf_poll = 1; ++ if (options->none_switch == -1) ++ options->none_switch = 0; ++ if (options->none_enabled == -1) ++ options->none_enabled = 0; ++ if (options->none_enabled == 0 && options->none_switch > 0) { ++ fprintf(stderr, "NoneEnabled must be enabled to use the None Switch option. None cipher disabled.\n"); ++ options->none_enabled = 0; ++ } ++ if (options->nonemac_enabled == -1) ++ options->nonemac_enabled = 0; ++ if (options->nonemac_enabled > 0 && (options->none_enabled == 0 || ++ options->none_switch == 0)) { ++ fprintf(stderr, "None MAC can only be used with the None cipher. None MAC disabled.\n"); ++ options->nonemac_enabled = 0; ++ } ++ if (options->disable_multithreaded == -1) ++ options->disable_multithreaded = 0; + if (options->control_master == -1) + options->control_master = 0; + if (options->control_persist == -1) { +diff -Nur openssh-8.4p1.orig/readconf.h openssh-8.4p1/readconf.h +--- openssh-8.4p1.orig/readconf.h 2021-03-11 18:13:41.146603072 +0100 ++++ openssh-8.4p1/readconf.h 2021-03-11 18:16:31.138747792 +0100 +@@ -57,6 +57,10 @@ + int strict_host_key_checking; /* Strict host key checking. */ + int compression; /* Compress packets in both directions. */ + int tcp_keep_alive; /* Set SO_KEEPALIVE. */ ++ int tcp_rcv_buf; /* user switch to set tcp recv buffer */ ++ int tcp_rcv_buf_poll; /* Option to poll recv buf every window transfer */ ++ int hpn_disabled; /* Switch to disable HPN buffer management */ ++ int hpn_buffer_size; /* User definable size for HPN buffer window */ + int ip_qos_interactive; /* IP ToS/DSCP/class for interactive */ + int ip_qos_bulk; /* IP ToS/DSCP/class for bulk traffic */ + SyslogFacility log_facility; /* Facility for system logging. */ +@@ -123,7 +127,12 @@ + + int enable_ssh_keysign; + int64_t rekey_limit; ++ int none_switch; /* Use none cipher */ ++ int none_enabled; /* Allow none to be used */ ++ int nonemac_enabled; /* Allow none to be used */ ++ int disable_multithreaded; /*disable multithreaded aes-ctr*/ + int rekey_interval; ++ + int no_host_authentication_for_localhost; + int identities_only; + int server_alive_interval; +diff -Nur openssh-8.4p1.orig/regress/integrity.sh openssh-8.4p1/regress/integrity.sh +--- openssh-8.4p1.orig/regress/integrity.sh 2020-09-27 09:25:01.000000000 +0200 ++++ openssh-8.4p1/regress/integrity.sh 2021-03-11 18:16:31.139747781 +0100 +@@ -8,6 +8,7 @@ + tries=10 + startoffset=2900 + macs=`${SSH} -Q mac` ++ + # The following are not MACs, but ciphers with integrated integrity. They are + # handled specially below. + macs="$macs `${SSH} -Q cipher-auth`" +@@ -21,6 +22,12 @@ + cmd="$SUDO env SSH_SK_HELPER="$SSH_SK_HELPER" sh ${SRC}/sshd-log-wrapper.sh ${TEST_SSHD_LOGFILE} ${SSHD} -i -f $OBJ/sshd_proxy" + + for m in $macs; do ++ # the none mac is now valid but tests against it will succeed when we expect it to ++ # fail. so we need to explicity remove it from the list of macs returned. ++ if [ "$m" = "none" ]; then ++ continue ++ fi ++ + trace "test $tid: mac $m" + elen=0 + epad=0 +diff -Nur openssh-8.4p1.orig/sandbox-seccomp-filter.c openssh-8.4p1/sandbox-seccomp-filter.c +--- openssh-8.4p1.orig/sandbox-seccomp-filter.c 2021-03-11 18:13:41.128603265 +0100 ++++ openssh-8.4p1/sandbox-seccomp-filter.c 2021-03-11 18:16:31.139747781 +0100 +@@ -216,6 +216,9 @@ + #ifdef __NR_geteuid32 + SC_ALLOW(__NR_geteuid32), + #endif ++#ifdef __NR_getpeername /* not defined on archs that go via socketcall(2) */ ++ SC_ALLOW(__NR_getpeername), ++#endif + #ifdef __NR_getpgid + SC_ALLOW(__NR_getpgid), + #endif +@@ -309,6 +312,9 @@ + #ifdef __NR_sigprocmask + SC_ALLOW(__NR_sigprocmask), + #endif ++#ifdef __NR_socketcall ++ SC_ALLOW(__NR_socketcall), ++#endif + #ifdef __NR_time + SC_ALLOW(__NR_time), + #endif +diff -Nur openssh-8.4p1.orig/scp.c openssh-8.4p1/scp.c +--- openssh-8.4p1.orig/scp.c 2021-03-11 18:13:41.135603190 +0100 ++++ openssh-8.4p1/scp.c 2021-03-11 18:16:31.139747781 +0100 +@@ -1251,7 +1251,7 @@ + off_t size, statbytes; + unsigned long long ull; + int setimes, targisdir, wrerr; +- char ch, *cp, *np, *targ, *why, *vect[1], buf[2048], visbuf[2048]; ++ char ch, *cp, *np, *targ, *why, *vect[1], buf[16384], visbuf[16384]; + char **patterns = NULL; + size_t n, npatterns = 0; + struct timeval tv[2]; +diff -Nur openssh-8.4p1.orig/servconf.c openssh-8.4p1/servconf.c +--- openssh-8.4p1.orig/servconf.c 2021-03-11 18:13:41.146603072 +0100 ++++ openssh-8.4p1/servconf.c 2021-03-11 18:20:18.397376031 +0100 +@@ -70,6 +70,7 @@ + #include "auth.h" + #include "myproposal.h" + #include "digest.h" ++#include "sshbuf.h" + #include "ssh-gss.h" + + static void add_listen_addr(ServerOptions *, const char *, +@@ -196,6 +197,12 @@ + options->authorized_principals_file = NULL; + options->authorized_principals_command = NULL; + options->authorized_principals_command_user = NULL; ++ options->tcp_rcv_buf_poll = -1; ++ options->hpn_disabled = -1; ++ options->hpn_buffer_size = -1; ++ options->none_enabled = -1; ++ options->nonemac_enabled = -1; ++ options->disable_multithreaded = -1; + options->ip_qos_interactive = -1; + options->ip_qos_bulk = -1; + options->version_addendum = NULL; +@@ -312,6 +319,10 @@ + fill_default_server_options(ServerOptions *options) + { + u_int i; ++ /* needed for hpn socket tests */ ++ int sock; ++ int socksize; ++ int socksizelen = sizeof(int); + + /* Portable-specific options */ + if (options->use_pam == -1) +@@ -477,6 +488,51 @@ + } + if (options->permit_tun == -1) + options->permit_tun = SSH_TUNMODE_NO; ++ if (options->none_enabled == -1) ++ options->none_enabled = 0; ++ if (options->nonemac_enabled == -1) ++ options->nonemac_enabled = 0; ++ if (options->nonemac_enabled > 0 && options->none_enabled == 0) { ++ debug ("Attempted to enabled None MAC without setting None Enabled to true. None MAC disabled."); ++ options->nonemac_enabled = 0; ++ } ++ if (options->disable_multithreaded == -1) ++ options->disable_multithreaded = 0; ++ if (options->hpn_disabled == -1) ++ options->hpn_disabled = 0; ++ ++ if (options->hpn_buffer_size == -1) { ++ /* option not explicitly set. Now we have to figure out */ ++ /* what value to use */ ++ if (options->hpn_disabled == 1) { ++ options->hpn_buffer_size = CHAN_SES_WINDOW_DEFAULT; ++ } else { ++ /* get the current RCV size and set it to that */ ++ /*create a socket but don't connect it */ ++ /* we use that the get the rcv socket size */ ++ sock = socket(AF_INET, SOCK_STREAM, 0); ++ getsockopt(sock, SOL_SOCKET, SO_RCVBUF, ++ &socksize, &socksizelen); ++ close(sock); ++ options->hpn_buffer_size = socksize; ++ debug("HPN Buffer Size: %d", options->hpn_buffer_size); ++ } ++ } else { ++ /* we have to do this in case the user sets both values in a contradictory */ ++ /* manner. hpn_disabled overrrides hpn_buffer_size*/ ++ if (options->hpn_disabled <= 0) { ++ if (options->hpn_buffer_size == 0) ++ options->hpn_buffer_size = 1; ++ /* limit the maximum buffer to SSHBUF_SIZE_MAX (currently 256MB) */ ++ if (options->hpn_buffer_size > (SSHBUF_SIZE_MAX / 1024)) { ++ options->hpn_buffer_size = SSHBUF_SIZE_MAX; ++ } else { ++ options->hpn_buffer_size *= 1024; ++ } ++ } else ++ options->hpn_buffer_size = CHAN_TCP_WINDOW_DEFAULT; ++ } ++ + if (options->ip_qos_interactive == -1) + options->ip_qos_interactive = IPTOS_DSCP_AF21; + if (options->ip_qos_bulk == -1) +@@ -550,6 +606,9 @@ + sPasswordAuthentication, sKbdInteractiveAuthentication, + sListenAddress, sAddressFamily, + sPrintMotd, sPrintLastLog, sIgnoreRhosts, ++ sNoneEnabled, sNoneMacEnabled, ++ sDisableMTAES, ++ sTcpRcvBufPoll, sHPNDisabled, sHPNBufferSize, + sX11Forwarding, sX11DisplayOffset, sX11MaxDisplays, sX11UseLocalhost, + sPermitTTY, sStrictModes, sEmptyPasswd, sTCPKeepAlive, + sPermitUserEnvironment, sAllowTcpForwarding, sCompression, +@@ -744,6 +803,12 @@ + { "revokedkeys", sRevokedKeys, SSHCFG_ALL }, + { "trustedusercakeys", sTrustedUserCAKeys, SSHCFG_ALL }, + { "authorizedprincipalsfile", sAuthorizedPrincipalsFile, SSHCFG_ALL }, ++ { "hpndisabled", sHPNDisabled, SSHCFG_ALL }, ++ { "hpnbuffersize", sHPNBufferSize, SSHCFG_ALL }, ++ { "tcprcvbufpoll", sTcpRcvBufPoll, SSHCFG_ALL }, ++ { "noneenabled", sNoneEnabled, SSHCFG_ALL }, ++ { "disableMTAES", sDisableMTAES, SSHCFG_ALL }, ++ { "nonemacenabled", sNoneMacEnabled, SSHCFG_ALL }, + { "kexalgorithms", sKexAlgorithms, SSHCFG_GLOBAL }, + { "include", sInclude, SSHCFG_ALL }, + { "ipqos", sIPQoS, SSHCFG_ALL }, +@@ -802,6 +867,7 @@ + + for (i = 0; keywords[i].name; i++) + if (strcasecmp(cp, keywords[i].name) == 0) { ++ debug("Config token is %s", keywords[i].name); + *flags = keywords[i].flags; + return keywords[i].opcode; + } +@@ -1549,12 +1615,37 @@ + multistate_ptr = multistate_ignore_rhosts; + goto parse_multistate; + ++ ++ case sTcpRcvBufPoll: ++ intptr = &options->tcp_rcv_buf_poll; ++ goto parse_flag; ++ ++ case sHPNDisabled: ++ intptr = &options->hpn_disabled; ++ goto parse_flag; ++ ++ case sHPNBufferSize: ++ intptr = &options->hpn_buffer_size; ++ goto parse_int; ++ + case sIgnoreUserKnownHosts: + intptr = &options->ignore_user_known_hosts; + parse_flag: + multistate_ptr = multistate_flag; + goto parse_multistate; + ++ case sNoneEnabled: ++ intptr = &options->none_enabled; ++ goto parse_flag; ++ ++ case sNoneMacEnabled: ++ intptr = &options->nonemac_enabled; ++ goto parse_flag; ++ ++ case sDisableMTAES: ++ intptr = &options->disable_multithreaded; ++ goto parse_flag; ++ + case sHostbasedAuthentication: + intptr = &options->hostbased_authentication; + goto parse_flag; +diff -Nur openssh-8.4p1.orig/servconf.h openssh-8.4p1/servconf.h +--- openssh-8.4p1.orig/servconf.h 2021-03-11 18:13:41.147603061 +0100 ++++ openssh-8.4p1/servconf.h 2021-03-11 18:21:39.595526486 +0100 +@@ -209,6 +209,13 @@ + int use_pam; /* Enable auth via PAM */ + int permit_pam_user_change; /* Allow PAM to change user name */ + ++ int tcp_rcv_buf_poll; /* poll tcp rcv window in autotuning kernels*/ ++ int hpn_disabled; /* disable hpn functionality. false by default */ ++ int hpn_buffer_size; /* set the hpn buffer size - default 3MB */ ++ int none_enabled; /* Enable NONE cipher switch */ ++ int disable_multithreaded; /*disable multithreaded aes-ctr cipher */ ++ int nonemac_enabled; /* Enable NONE MAC switch */ ++ + int permit_tun; + + char **permitted_opens; /* May also be one of PERMITOPEN_* */ +diff -Nur openssh-8.4p1.orig/serverloop.c openssh-8.4p1/serverloop.c +--- openssh-8.4p1.orig/serverloop.c 2021-03-11 18:13:41.136603179 +0100 ++++ openssh-8.4p1/serverloop.c 2021-03-11 18:16:31.142747749 +0100 +@@ -322,7 +322,7 @@ + process_input(struct ssh *ssh, fd_set *readset, int connection_in) + { + int r, len; +- char buf[16384]; ++ char buf[SSH_IOBUFSZ]; + + /* Read and buffer any input data from the client. */ + if (FD_ISSET(connection_in, readset)) { +@@ -346,6 +346,7 @@ + != 0) + fatal("%s: ssh_packet_process_incoming: %s", + __func__, ssh_err(r)); ++ ssh->fdout_bytes += len; + } + } + return 0; +@@ -405,6 +406,7 @@ + u_int64_t rekey_timeout_ms = 0; + + debug("Entering interactive session for SSH2."); ++ ssh->start_time = monotime_double(); + + ssh_signal(SIGCHLD, sigchld_handler); + child_terminated = 0; +@@ -442,7 +444,9 @@ + &readset, &writeset, &max_fd, &nalloc, rekey_timeout_ms); + + if (received_sigterm) { ++ sshpkt_final_log_entry(ssh); + logit("Exiting on signal %d", (int)received_sigterm); ++ sshpkt_final_log_entry(ssh); + /* Clean up sessions, utmp, etc. */ + cleanup_exit(255); + } +@@ -455,13 +459,19 @@ + process_output(ssh, writeset, connection_out); + } + collect_children(ssh); +- ++ + free(readset); + free(writeset); + ++ /* write final log entry */ ++ sshpkt_final_log_entry(ssh); ++ + /* free all channels, no more reads and writes */ + channel_free_all(ssh); + ++ /* final entry must come after channels close -cjr */ ++ sshpkt_final_log_entry(ssh); ++ + /* free remaining sessions, e.g. remove wtmp entries */ + session_destroy_all(ssh, NULL); + } +@@ -612,7 +622,8 @@ + debug("Tunnel forwarding using interface %s", ifname); + + c = channel_new(ssh, "tun", SSH_CHANNEL_OPEN, sock, sock, -1, +- CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1); ++ options.hpn_disabled ? CHAN_TCP_WINDOW_DEFAULT : options.hpn_buffer_size, ++ CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1); + c->datagram = 1; + #if defined(SSH_TUN_FILTER) + if (mode == SSH_TUNMODE_POINTOPOINT) +@@ -663,6 +674,8 @@ + c = channel_new(ssh, "session", SSH_CHANNEL_LARVAL, + -1, -1, -1, /*window size*/0, CHAN_SES_PACKET_DEFAULT, + 0, "server-session", 1); ++ if ((options.tcp_rcv_buf_poll) && (!options.hpn_disabled)) ++ c->dynamic_window = 1; + if (session_open(the_authctxt, c->self) != 1) { + debug("session open failed, free channel %d", c->self); + channel_free(ssh, c); +diff -Nur openssh-8.4p1.orig/session.c openssh-8.4p1/session.c +--- openssh-8.4p1.orig/session.c 2021-03-11 18:13:41.124603308 +0100 ++++ openssh-8.4p1/session.c 2021-03-11 18:16:31.143747738 +0100 +@@ -97,6 +97,7 @@ + #include "sftp.h" + #include "atomicio.h" + ++ + #if defined(KRB5) && defined(USE_AFS) + #include + #endif +@@ -228,6 +229,7 @@ + goto authsock_err; + + /* Allocate a channel for the authentication agent socket. */ ++ /* this shouldn't matter if its hpn or not - cjr */ + nc = channel_new(ssh, "auth socket", + SSH_CHANNEL_AUTH_SOCKET, sock, sock, -1, + CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, +@@ -467,7 +469,7 @@ + return -1; + case 0: + is_child = 1; +- ++ + /* + * Create a new session and process group since the 4.4BSD + * setlogin() affects the entire process group. +@@ -612,7 +614,7 @@ + return -1; + case 0: + is_child = 1; +- ++ + close(fdout); + close(ptymaster); + +@@ -2371,10 +2373,11 @@ + */ + if (s->chanid == -1) + fatal("no channel for session %d", s->self); +- channel_set_fds(ssh, s->chanid, +- fdout, fdin, fderr, +- ignore_fderr ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ, +- 1, is_tty, CHAN_SES_WINDOW_DEFAULT); ++ channel_set_fds(ssh, s->chanid, ++ fdout, fdin, fderr, ++ ignore_fderr ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ, ++ 1, is_tty, ++ options.hpn_disabled ? CHAN_SES_WINDOW_DEFAULT : options.hpn_buffer_size); + } + + /* +diff -Nur openssh-8.4p1.orig/sftp.1 openssh-8.4p1/sftp.1 +--- openssh-8.4p1.orig/sftp.1 2020-09-27 09:25:01.000000000 +0200 ++++ openssh-8.4p1/sftp.1 2021-03-11 18:16:31.143747738 +0100 +@@ -295,7 +295,8 @@ + Specify how many requests may be outstanding at any one time. + Increasing this may slightly improve file transfer speed + but will increase memory usage. +-The default is 64 outstanding requests. ++The default is 256 outstanding requests providing for 8MB ++of outstanding data with a 32KB buffer. + .It Fl r + Recursively copy entire directories when uploading and downloading. + Note that +diff -Nur openssh-8.4p1.orig/sftp.c openssh-8.4p1/sftp.c +--- openssh-8.4p1.orig/sftp.c 2021-03-11 18:13:41.136603179 +0100 ++++ openssh-8.4p1/sftp.c 2021-03-11 18:16:31.143747738 +0100 +@@ -71,7 +71,7 @@ + #include "sftp-client.h" + + #define DEFAULT_COPY_BUFLEN 32768 /* Size of buffer for up/download */ +-#define DEFAULT_NUM_REQUESTS 64 /* # concurrent outstanding requests */ ++#define DEFAULT_NUM_REQUESTS 256 /* # concurrent outstanding requests */ + + /* File to read commands from */ + FILE* infile; +diff -Nur openssh-8.4p1.orig/ssh_api.c openssh-8.4p1/ssh_api.c +--- openssh-8.4p1.orig/ssh_api.c 2020-09-27 09:25:01.000000000 +0200 ++++ openssh-8.4p1/ssh_api.c 2021-03-11 18:16:31.144747727 +0100 +@@ -411,7 +411,7 @@ + char *cp; + int r; + +- if ((r = sshbuf_putf(banner, "SSH-2.0-%.100s\r\n", SSH_VERSION)) != 0) ++ if ((r = sshbuf_putf(banner, "SSH-2.0-%.100s\r\n", SSH_RELEASE)) != 0) + return r; + if ((r = sshbuf_putb(ssh_packet_get_output(ssh), banner)) != 0) + return r; +diff -Nur openssh-8.4p1.orig/sshbuf.h openssh-8.4p1/sshbuf.h +--- openssh-8.4p1.orig/sshbuf.h 2020-09-27 09:25:01.000000000 +0200 ++++ openssh-8.4p1/sshbuf.h 2021-03-11 18:16:31.145747716 +0100 +@@ -28,7 +28,7 @@ + # endif /* OPENSSL_HAS_ECC */ + #endif /* WITH_OPENSSL */ + +-#define SSHBUF_SIZE_MAX 0x8000000 /* Hard maximum size */ ++#define SSHBUF_SIZE_MAX 0xF000000 /* Hard maximum size 256MB */ + #define SSHBUF_REFS_MAX 0x100000 /* Max child buffers */ + #define SSHBUF_MAX_BIGNUM (16384 / 8) /* Max bignum *bytes* */ + #define SSHBUF_MAX_ECPOINT ((528 * 2 / 8) + 1) /* Max EC point *bytes* */ +diff -Nur openssh-8.4p1.orig/ssh.c openssh-8.4p1/ssh.c +--- openssh-8.4p1.orig/ssh.c 2021-03-11 18:13:41.147603061 +0100 ++++ openssh-8.4p1/ssh.c 2021-03-11 18:16:31.144747727 +0100 +@@ -1084,6 +1084,10 @@ + break; + case 'T': + options.request_tty = REQUEST_TTY_NO; ++ /* ensure that the user doesn't try to backdoor a */ ++ /* null cipher switch on an interactive session */ ++ /* so explicitly disable it no matter what */ ++ options.none_switch=0; + break; + case 'o': + line = xstrdup(optarg); +@@ -1793,6 +1797,8 @@ + setproctitle("%s [mux]", options.control_path); + } + ++extern const EVP_CIPHER *evp_aes_ctr_mt(void); ++ + /* Do fork() after authentication. Used by "ssh -f" */ + static void + fork_postauth(void) +@@ -2077,6 +2083,79 @@ + NULL, fileno(stdin), command, environ); + } + ++static void ++hpn_options_init(void) ++{ ++ /* ++ * We need to check to see if what they want to do about buffer ++ * sizes here. In a hpn to nonhpn connection we want to limit ++ * the window size to something reasonable in case the far side ++ * has the large window bug. In hpn to hpn connection we want to ++ * use the max window size but allow the user to override it ++ * lastly if they disabled hpn then use the ssh std window size. ++ * ++ * So why don't we just do a getsockopt() here and set the ++ * ssh window to that? In the case of a autotuning receive ++ * window the window would get stuck at the initial buffer ++ * size generally less than 96k. Therefore we need to set the ++ * maximum ssh window size to the maximum hpn buffer size ++ * unless the user has specifically set the tcprcvbufpoll ++ * to no. In which case we *can* just set the window to the ++ * minimum of the hpn buffer size and tcp receive buffer size. ++ */ ++ ++ if (tty_flag) ++ options.hpn_buffer_size = CHAN_SES_WINDOW_DEFAULT; ++ else ++ options.hpn_buffer_size = 2 * 1024 * 1024; ++ ++ if (datafellows & SSH_BUG_LARGEWINDOW) { ++ debug("HPN to Non-HPN connection"); ++ } else { ++ debug("HPN to HPN connection"); ++ int sock, socksize; ++ socklen_t socksizelen; ++ if (options.tcp_rcv_buf_poll <= 0) { ++ sock = socket(AF_INET, SOCK_STREAM, 0); ++ socksizelen = sizeof(socksize); ++ getsockopt(sock, SOL_SOCKET, SO_RCVBUF, ++ &socksize, &socksizelen); ++ close(sock); ++ debug("socksize %d", socksize); ++ options.hpn_buffer_size = socksize; ++ debug("HPNBufferSize set to TCP RWIN: %d", options.hpn_buffer_size); ++ } else { ++ if (options.tcp_rcv_buf > 0) { ++ /* ++ * Create a socket but don't connect it: ++ * we use that the get the rcv socket size ++ */ ++ sock = socket(AF_INET, SOCK_STREAM, 0); ++ /* ++ * If they are using the tcp_rcv_buf option, ++ * attempt to set the buffer size to that. ++ */ ++ if (options.tcp_rcv_buf) { ++ socksizelen = sizeof(options.tcp_rcv_buf); ++ setsockopt(sock, SOL_SOCKET, SO_RCVBUF, ++ &options.tcp_rcv_buf, socksizelen); ++ } ++ socksizelen = sizeof(socksize); ++ getsockopt(sock, SOL_SOCKET, SO_RCVBUF, ++ &socksize, &socksizelen); ++ close(sock); ++ debug("socksize %d", socksize); ++ options.hpn_buffer_size = socksize; ++ debug("HPNBufferSize set to user TCPRcvBuf: %d", options.hpn_buffer_size); ++ } ++ } ++ } ++ ++ debug("Final hpn_buffer_size = %d", options.hpn_buffer_size); ++ ++ channel_set_hpn(options.hpn_disabled, options.hpn_buffer_size); ++} ++ + /* open new channel for a session */ + static int + ssh_session2_open(struct ssh *ssh) +@@ -2103,9 +2182,11 @@ + if (!isatty(err)) + set_nonblock(err); + +- window = CHAN_SES_WINDOW_DEFAULT; ++ window = options.hpn_buffer_size; ++ + packetmax = CHAN_SES_PACKET_DEFAULT; + if (tty_flag) { ++ window = CHAN_SES_WINDOW_DEFAULT; + window >>= 1; + packetmax >>= 1; + } +@@ -2114,7 +2195,15 @@ + window, packetmax, CHAN_EXTENDED_WRITE, + "client-session", /*nonblock*/0); + ++ if ((options.tcp_rcv_buf_poll > 0) && (!options.hpn_disabled)) { ++ c->dynamic_window = 1; ++ debug("Enabled Dynamic Window Scaling"); ++ } + debug3("%s: channel_new: %d", __func__, c->self); ++ if (options.tcp_rcv_buf_poll > 0 && !options.hpn_disabled) { ++ c->dynamic_window = 1; ++ debug("Enabled Dynamic Window Scaling"); ++ } + + channel_send_open(ssh, c->self); + if (!no_shell_flag) +@@ -2130,6 +2219,13 @@ + int r, devnull, id = -1; + char *cp, *tun_fwd_ifname = NULL; + ++ /* ++ * We need to initialize this early because the forwarding logic below ++ * might open channels that use the hpn buffer sizes. We can't send a ++ * window of -1 (the default) to the server as it breaks things. ++ */ ++ hpn_options_init(); ++ + /* XXX should be pre-session */ + if (!options.control_persist) + ssh_init_stdio_forwarding(ssh); +diff -Nur openssh-8.4p1.orig/sshconnect2.c openssh-8.4p1/sshconnect2.c +--- openssh-8.4p1.orig/sshconnect2.c 2021-03-11 18:13:41.148603051 +0100 ++++ openssh-8.4p1/sshconnect2.c 2021-03-11 18:16:31.146747705 +0100 +@@ -85,6 +85,13 @@ + extern Options options; + + /* ++ * tty_flag is set in ssh.c. Use this in ssh_userauth2: ++ * if it is set, then prevent the switch to the null cipher. ++ */ ++ ++extern int tty_flag; ++ ++/* + * SSH2 key exchange + */ + +@@ -203,6 +210,8 @@ + return ret; + } + ++static char *myproposal[PROPOSAL_MAX]; ++static const char *myproposal_default[PROPOSAL_MAX] = { KEX_CLIENT }; + void + ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port) + { +@@ -215,6 +224,10 @@ + char *gss_host = NULL; + #endif + ++ memcpy(&myproposal, &myproposal_default, sizeof(myproposal)); ++ ++ memcpy(&myproposal, &myproposal_default, sizeof(myproposal)); ++ + xxx_host = host; + xxx_hostaddr = hostaddr; + +@@ -564,6 +577,53 @@ + + if (!authctxt.success) + fatal("Authentication failed."); ++ ++ /* ++ * If the user wants to use the none cipher and/or none mac, do it post authentication ++ * and only if the right conditions are met -- both of the NONE commands ++ * must be true and there must be no tty allocated. ++ */ ++ if (options.none_switch == 1 && options.none_enabled == 1) { ++ if (!tty_flag) { /* no null on tty sessions */ ++ debug("Requesting none rekeying..."); ++ memcpy(&myproposal, &myproposal_default, sizeof(myproposal)); ++ myproposal[PROPOSAL_ENC_ALGS_STOC] = "none"; ++ myproposal[PROPOSAL_ENC_ALGS_CTOS] = "none"; ++ fprintf(stderr, "WARNING: ENABLED NONE CIPHER!!!\n"); ++ /* NONEMAC can only be used in context of the NONE CIPHER */ ++ if (options.nonemac_enabled == 1) { ++ myproposal[PROPOSAL_MAC_ALGS_STOC] = "none"; ++ myproposal[PROPOSAL_MAC_ALGS_CTOS] = "none"; ++ fprintf(stderr, "WARNING: ENABLED NONE MAC\n"); ++ } ++ kex_prop2buf(ssh->kex->my, myproposal); ++ packet_request_rekeying(); ++ } else { ++ /* requested NONE cipher when in a tty */ ++ debug("Cannot switch to NONE cipher with tty allocated"); ++ fprintf(stderr, "NONE cipher switch disabled when a TTY is allocated\n"); ++ } ++ } ++ ++#ifdef WITH_OPENSSL ++ if (options.disable_multithreaded == 0) { ++ /* if we are using aes-ctr there can be issues in either a fork or sandbox ++ * so the initial aes-ctr is defined to point to the original single process ++ * evp. After authentication we'll be past the fork and the sandboxed privsep ++ * so we repoint the define to the multithreaded evp. To start the threads we ++ * then force a rekey ++ */ ++ const void *cc = ssh_packet_get_send_context(ssh); ++ ++ /* only do this for the ctr cipher. otherwise gcm mode breaks. Don't know why though */ ++ if (strstr(cipher_ctx_name(cc), "ctr")) { ++ debug("Single to Multithread CTR cipher swap - client request"); ++ cipher_reset_multithreaded(); ++ packet_request_rekeying(); ++ } ++ } ++#endif ++ + debug("Authentication succeeded (%s).", authctxt.method->name); + } + +diff -Nur openssh-8.4p1.orig/sshconnect.c openssh-8.4p1/sshconnect.c +--- openssh-8.4p1.orig/sshconnect.c 2020-09-27 09:25:01.000000000 +0200 ++++ openssh-8.4p1/sshconnect.c 2021-03-11 18:16:31.145747716 +0100 +@@ -362,6 +362,30 @@ + #endif + + /* ++ * Set TCP receive buffer if requested. ++ * Note: tuning needs to happen after the socket is ++ * created but before the connection happens ++ * so winscale is negotiated properly -cjr ++ */ ++static void ++ssh_set_socket_recvbuf(int sock) ++{ ++ void *buf = (void *)&options.tcp_rcv_buf; ++ int sz = sizeof(options.tcp_rcv_buf); ++ int socksize; ++ int socksizelen = sizeof(int); ++ ++ debug("setsockopt Attempting to set SO_RCVBUF to %d", options.tcp_rcv_buf); ++ if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, buf, sz) >= 0) { ++ getsockopt(sock, SOL_SOCKET, SO_RCVBUF, &socksize, &socksizelen); ++ debug("setsockopt SO_RCVBUF: %.100s %d", strerror(errno), socksize); ++ } ++ else ++ error("Couldn't set socket receive buffer to %d: %.100s", ++ options.tcp_rcv_buf, strerror(errno)); ++} ++ ++/* + * Creates a socket for use as the ssh connection. + */ + static int +@@ -383,6 +407,9 @@ + } + fcntl(sock, F_SETFD, FD_CLOEXEC); + ++ if (options.tcp_rcv_buf > 0) ++ ssh_set_socket_recvbuf(sock); ++ + /* Bind the socket to an alternative local IP address */ + if (options.bind_address == NULL && options.bind_interface == NULL) + return sock; +diff -Nur openssh-8.4p1.orig/sshd.c openssh-8.4p1/sshd.c +--- openssh-8.4p1.orig/sshd.c 2021-03-11 18:13:41.149603040 +0100 ++++ openssh-8.4p1/sshd.c 2021-03-11 18:16:31.147747694 +0100 +@@ -394,6 +394,8 @@ + sigdie("Timeout before authentication for %s port %d", + ssh_remote_ipaddr(the_active_state), + ssh_remote_port(the_active_state)); ++ ++ + } + + /* +@@ -1133,6 +1135,8 @@ + int ret, listen_sock; + struct addrinfo *ai; + char ntop[NI_MAXHOST], strport[NI_MAXSERV]; ++ int socksize; ++ int socksizelen = sizeof(int); + + for (ai = la->addrs; ai; ai = ai->ai_next) { + if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) +@@ -1178,6 +1182,11 @@ + + debug("Bind to port %s on %s.", strport, ntop); + ++ getsockopt(listen_sock, SOL_SOCKET, SO_RCVBUF, ++ &socksize, &socksizelen); ++ debug("Server TCP RWIN socket size: %d", socksize); ++ debug("HPN Buffer Size: %d", options.hpn_buffer_size); ++ + /* Bind the socket to the desired port. */ + if (bind(listen_sock, ai->ai_addr, ai->ai_addrlen) == -1) { + error("Bind to port %s on %s failed: %.200s.", +@@ -1847,6 +1856,19 @@ + /* Fill in default values for those options not explicitly set. */ + fill_default_server_options(&options); + ++ if (options.none_enabled == 1) { ++ char *old_ciphers = options.ciphers; ++ xasprintf(&options.ciphers, "%s,none", old_ciphers); ++ free(old_ciphers); ++ ++ /* only enable the none MAC in context of the none cipher -cjr */ ++ if (options.nonemac_enabled == 1) { ++ char *old_macs = options.macs; ++ xasprintf(&options.macs, "%s,none", old_macs); ++ free(old_macs); ++ } ++ } ++ + /* challenge-response is implemented via keyboard interactive */ + if (options.challenge_response_authentication) + options.kbd_interactive_authentication = 1; +@@ -2305,6 +2327,9 @@ + rdomain == NULL ? "" : "\""); + free(laddr); + ++ /* set the HPN options for the child */ ++ channel_set_hpn(options.hpn_disabled, options.hpn_buffer_size); ++ + /* + * We don't want to listen forever unless the other side + * successfully authenticates itself. So we set up an alarm which is +@@ -2417,6 +2442,25 @@ + /* Try to send all our hostkeys to the client */ + notify_hostkeys(ssh); + ++#ifdef WITH_OPENSSL ++ if (options.disable_multithreaded == 0) { ++ /* if we are using aes-ctr there can be issues in either a fork or sandbox ++ * so the initial aes-ctr is defined to point ot the original single process ++ * evp. After authentication we'll be past the fork and the sandboxed privsep ++ * so we repoint the define to the multithreaded evp. To start the threads we ++ * then force a rekey ++ */ ++ const void *cc = ssh_packet_get_send_context(the_active_state); ++ ++ /* only rekey if necessary. If we don't do this gcm mode cipher breaks */ ++ if (strstr(cipher_ctx_name(cc), "ctr")) { ++ debug("Single to Multithreaded CTR cipher swap - server request"); ++ cipher_reset_multithreaded(); ++ packet_request_rekeying(); ++ } ++ } ++#endif ++ + /* Start session. */ + do_authenticated(ssh, authctxt); + +@@ -2491,6 +2535,11 @@ + struct kex *kex; + int r; + ++ if (options.none_enabled == 1) ++ debug("WARNING: None cipher enabled"); ++ if (options.nonemac_enabled == 1) ++ debug("WARNING: None MAC enabled"); ++ + myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal( + options.kex_algorithms); + myproposal[PROPOSAL_ENC_ALGS_CTOS] = compat_cipher_proposal( +diff -Nur openssh-8.4p1.orig/sshd_config openssh-8.4p1/sshd_config +--- openssh-8.4p1.orig/sshd_config 2021-03-11 18:13:41.158602943 +0100 ++++ openssh-8.4p1/sshd_config 2021-03-11 18:16:31.147747694 +0100 +@@ -127,6 +127,22 @@ + # override default of no subsystems + Subsystem sftp /usr/libexec/sftp-server + ++# the following are HPN related configuration options ++# tcp receive buffer polling. disable in non autotuning kernels ++#TcpRcvBufPoll yes ++ ++# disable hpn performance boosts ++#HPNDisabled no ++ ++# buffer size for hpn to non-hpn connections ++#HPNBufferSize 2048 ++ ++# allow the use of the none cipher ++#NoneEnabled no ++ ++# allow the use of the none MAC ++#NoneMacEnabled no ++ + # Example of overriding settings on a per-user basis + #Match User anoncvs + # X11Forwarding no +diff -Nur openssh-8.4p1.orig/version.h openssh-8.4p1/version.h +--- openssh-8.4p1.orig/version.h 2021-03-11 18:13:41.150603029 +0100 ++++ openssh-8.4p1/version.h 2021-03-11 18:22:57.603714426 +0100 +@@ -16,5 +16,6 @@ + + #define SSH_PORTABLE "p1" + #define GSI_PORTABLE "c-GSI" ++#define SSH_HPN "-hpn15v1" + #define SSH_RELEASE SSH_VERSION SSH_PORTABLE GSI_PORTABLE \ +- GSI_VERSION KRB5_VERSION ++ GSI_VERSION SSH_HPN KRB5_VERSION From 85f5ecc116cae7ad3d00149293e3f5d4709d5b5d Mon Sep 17 00:00:00 2001 From: Mattias Ellert Date: Tue, 16 Mar 2021 06:59:04 +0100 Subject: [PATCH 3/7] Fix issue with read-only ssh buffer during gssapi key exchange Clean up HPN patch --- .gitignore | 2 +- gsi-openssh.spec | 10 +- openssh-8.0p1-sshbuf-readonly.patch | 152 +++++++ openssh-8.4p1-hpn-15.1-modified.patch | 568 ++++++++++---------------- 4 files changed, 371 insertions(+), 361 deletions(-) create mode 100644 openssh-8.0p1-sshbuf-readonly.patch diff --git a/.gitignore b/.gitignore index 149e338..7f20fba 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ /*.tar.bz2 /*.tar.gz /*.tar.gz.asc -/DJM-GPG-KEY.gpg +/*.gpg diff --git a/gsi-openssh.spec b/gsi-openssh.spec index 5da6a9f..f25783b 100644 --- a/gsi-openssh.spec +++ b/gsi-openssh.spec @@ -28,7 +28,7 @@ %global libedit 1 %global openssh_ver 8.4p1 -%global openssh_rel 5 +%global openssh_rel 6 Summary: An implementation of the SSH protocol with GSI authentication Name: gsi-openssh @@ -159,6 +159,9 @@ Patch968: openssh-8.4p1-sandbox-seccomp.patch # https://bugzilla.mindrot.org/show_bug.cgi?id=3213 Patch969: openssh-8.4p1-debian-compat.patch +# Fix issue with read-only ssh buffer during gssapi key exchange (#1938224) +# https://github.com/openssh-gsskex/openssh-gsskex/pull/19 +Patch97: openssh-8.0p1-sshbuf-readonly.patch # This is the patch that adds GSI support # Based on hpn_isshd-gsi.7.5p1b.patch from Globus upstream Patch98: openssh-8.4p1-gsissh.patch @@ -313,6 +316,7 @@ gpgv2 --quiet --keyring %{SOURCE3} %{SOURCE1} %{SOURCE0} %patch100 -p1 -b .coverity +%patch97 -p1 -b .sshbuf-ro %patch98 -p1 -b .gsi %patch99 -p1 -b .hpn @@ -506,6 +510,10 @@ getent passwd sshd >/dev/null || \ %attr(0644,root,root) %{_tmpfilesdir}/gsissh.conf %changelog +* Tue Mar 16 2021 Mattias Ellert - 8.4p1-6 +- Fix issue with read-only ssh buffer during gssapi key exchange +- Clean up HPN patch + * Thu Mar 11 2021 Frank Scheiner - 8.4p1-5 - Add HPN patch diff --git a/openssh-8.0p1-sshbuf-readonly.patch b/openssh-8.0p1-sshbuf-readonly.patch new file mode 100644 index 0000000..edc8bec --- /dev/null +++ b/openssh-8.0p1-sshbuf-readonly.patch @@ -0,0 +1,152 @@ +From 063e1a255b53abde1147522f9aceccfd2a7ceb9b Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Tue, 2 Mar 2021 19:45:25 +0100 +Subject: [PATCH] Unbreak gsi-openssh by not holding the sshbuf structures + originated from incoming packet buffer + +Keeping buffers from sshpkt_getb_froms() for breaks further packet +processing because the "derived" buffer keeps a "link" to te parent +buffer, which is then considered readonly. + +This addresses the visible issue in the kexgss_server(), which +demonstrated with GSI (requiring more round trips than GSSAPI +with kerberos). + +The additional two places in the client were never hit, because the host +keys are never sent as part of the gssapi key exchange but in case we +would have different server or we would start sending hostkeys as the +code is ready for that, we would hit it anyway. + +Fixes #18 +--- + kexgssc.c | 14 ++++++++++++-- + kexgsss.c | 48 ++++++++++++++++++++++++++++-------------------- + 2 files changed, 40 insertions(+), 22 deletions(-) + +diff --git a/kexgssc.c b/kexgssc.c +index 1c62740e..29b8b031 100644 +--- a/kexgssc.c ++++ b/kexgssc.c +@@ -162,11 +162,16 @@ kexgss_client(struct ssh *ssh) + do { + type = ssh_packet_read(ssh); + if (type == SSH2_MSG_KEXGSS_HOSTKEY) { ++ char *tmp = NULL; ++ size_t tmp_len = 0; ++ + debug("Received KEXGSS_HOSTKEY"); + if (server_host_key_blob) + fatal("Server host key received more than once"); +- if ((r = sshpkt_getb_froms(ssh, &server_host_key_blob)) != 0) ++ if ((r = sshpkt_get_string(ssh, &tmp, &tmp_len)) != 0) + fatal("Failed to read server host key: %s", ssh_err(r)); ++ if ((server_host_key_blob = sshbuf_from(tmp, tmp_len)) == NULL) ++ fatal("sshbuf_from failed"); + } + } while (type == SSH2_MSG_KEXGSS_HOSTKEY); + +@@ -453,11 +458,16 @@ kexgssgex_client(struct ssh *ssh) + do { + type = ssh_packet_read(ssh); + if (type == SSH2_MSG_KEXGSS_HOSTKEY) { ++ char *tmp = NULL; ++ size_t tmp_len = 0; ++ + debug("Received KEXGSS_HOSTKEY"); + if (server_host_key_blob) + fatal("Server host key received more than once"); +- if ((r = sshpkt_getb_froms(ssh, &server_host_key_blob)) != 0) ++ if ((r = sshpkt_get_string(ssh, &tmp, &tmp_len)) != 0) + fatal("sshpkt failed: %s", ssh_err(r)); ++ if ((server_host_key_blob = sshbuf_from(tmp, tmp_len)) == NULL) ++ fatal("sshbuf_from failed"); + } + } while (type == SSH2_MSG_KEXGSS_HOSTKEY); + +diff --git a/kexgsss.c b/kexgsss.c +index a2c02148..c8b7d652 100644 +--- a/kexgsss.c ++++ b/kexgsss.c +@@ -64,7 +64,7 @@ kexgss_server(struct ssh *ssh) + */ + + OM_uint32 ret_flags = 0; +- gss_buffer_desc gssbuf, recv_tok, msg_tok; ++ gss_buffer_desc gssbuf = {0, NULL}, recv_tok, msg_tok; + gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; + Gssctxt *ctxt = NULL; + struct sshbuf *shared_secret = NULL; +@@ -104,7 +104,7 @@ kexgss_server(struct ssh *ssh) + type = ssh_packet_read(ssh); + switch(type) { + case SSH2_MSG_KEXGSS_INIT: +- if (client_pubkey != NULL) ++ if (gssbuf.value != NULL) + fatal("Received KEXGSS_INIT after initialising"); + if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, + &recv_tok)) != 0 || +@@ -135,6 +135,31 @@ kexgss_server(struct ssh *ssh) + goto out; + + /* Send SSH_MSG_KEXGSS_HOSTKEY here, if we want */ ++ ++ /* Calculate the hash early so we can free the ++ * client_pubkey, which has reference to the parent ++ * buffer state->incoming_packet ++ */ ++ hashlen = sizeof(hash); ++ if ((r = kex_gen_hash( ++ kex->hash_alg, ++ kex->client_version, ++ kex->server_version, ++ kex->peer, ++ kex->my, ++ empty, ++ client_pubkey, ++ server_pubkey, ++ shared_secret, ++ hash, &hashlen)) != 0) ++ goto out; ++ ++ gssbuf.value = hash; ++ gssbuf.length = hashlen; ++ ++ sshbuf_free(client_pubkey); ++ client_pubkey = NULL; ++ + break; + case SSH2_MSG_KEXGSS_CONTINUE: + if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, +@@ -156,7 +181,7 @@ kexgss_server(struct ssh *ssh) + if (maj_status != GSS_S_COMPLETE && send_tok.length == 0) + fatal("Zero length token output when incomplete"); + +- if (client_pubkey == NULL) ++ if (gssbuf.value == NULL) + fatal("No client public key"); + + if (maj_status & GSS_S_CONTINUE_NEEDED) { +@@ -185,23 +210,6 @@ kexgss_server(struct ssh *ssh) + if (!(ret_flags & GSS_C_INTEG_FLAG)) + fatal("Integrity flag wasn't set"); + +- hashlen = sizeof(hash); +- if ((r = kex_gen_hash( +- kex->hash_alg, +- kex->client_version, +- kex->server_version, +- kex->peer, +- kex->my, +- empty, +- client_pubkey, +- server_pubkey, +- shared_secret, +- hash, &hashlen)) != 0) +- goto out; +- +- gssbuf.value = hash; +- gssbuf.length = hashlen; +- + if (GSS_ERROR(PRIVSEP(ssh_gssapi_sign(ctxt, &gssbuf, &msg_tok)))) + fatal("Couldn't get MIC"); + diff --git a/openssh-8.4p1-hpn-15.1-modified.patch b/openssh-8.4p1-hpn-15.1-modified.patch index 62d5b65..33a1475 100644 --- a/openssh-8.4p1-hpn-15.1-modified.patch +++ b/openssh-8.4p1-hpn-15.1-modified.patch @@ -1,6 +1,6 @@ diff -Nur openssh-8.4p1.orig/auth2.c openssh-8.4p1/auth2.c ---- openssh-8.4p1.orig/auth2.c 2021-03-11 18:13:41.139603147 +0100 -+++ openssh-8.4p1/auth2.c 2021-03-11 18:18:03.302756116 +0100 +--- openssh-8.4p1.orig/auth2.c 2021-03-16 19:47:18.027228699 +0100 ++++ openssh-8.4p1/auth2.c 2021-03-16 20:16:05.453909718 +0100 @@ -53,6 +53,8 @@ #include "dispatch.h" #include "pathnames.h" @@ -25,27 +25,15 @@ diff -Nur openssh-8.4p1.orig/auth2.c openssh-8.4p1/auth2.c user[0] ? user : "", service, method); + if (!log_flag) { + logit("SSH: Server;Ltype: Authname;Remote: %s-%d;Name: %s", -+ ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), user); ++ ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), user); + log_flag = 1; + } debug("attempt %d failures %d", authctxt->attempt, authctxt->failures); #ifdef WITH_SELINUX -diff -Nur openssh-8.4p1.orig/canohost.h openssh-8.4p1/canohost.h ---- openssh-8.4p1.orig/canohost.h 2021-03-11 18:13:41.141603126 +0100 -+++ openssh-8.4p1/canohost.h 2021-03-11 18:16:31.126747922 +0100 -@@ -22,7 +22,7 @@ - int get_peer_port(int); - char *get_local_ipaddr(int); - char *get_local_name(int); --int get_local_port(int); -+int get_local_port(int); - - #endif /* _CANOHOST_H */ - diff -Nur openssh-8.4p1.orig/channels.c openssh-8.4p1/channels.c ---- openssh-8.4p1.orig/channels.c 2021-03-11 18:13:41.134603201 +0100 -+++ openssh-8.4p1/channels.c 2021-03-11 18:16:31.127747911 +0100 +--- openssh-8.4p1.orig/channels.c 2021-03-16 19:47:18.019228682 +0100 ++++ openssh-8.4p1/channels.c 2021-03-16 20:27:24.311374041 +0100 @@ -220,6 +220,9 @@ /* Setup helper */ static void channel_handler_init(struct ssh_channels *sc); @@ -80,13 +68,13 @@ diff -Nur openssh-8.4p1.orig/channels.c openssh-8.4p1/channels.c + return 128 * 1024; + + ret = getsockopt(ssh_packet_get_connection_in(ssh), -+ SOL_SOCKET, SO_RCVBUF, &tcpwinsz, &optsz); ++ SOL_SOCKET, SO_RCVBUF, &tcpwinsz, &optsz); + /* return no more than SSHBUF_SIZE_MAX (currently 256MB) */ + if ((ret == 0) && tcpwinsz > SSHBUF_SIZE_MAX) + tcpwinsz = SSHBUF_SIZE_MAX; + + debug2("tcpwinsz: tcp connection %d, Receive window: %d", -+ ssh_packet_get_connection_in(ssh), tcpwinsz); ++ ssh_packet_get_connection_in(ssh), tcpwinsz); + return tcpwinsz; +} + @@ -133,46 +121,7 @@ diff -Nur openssh-8.4p1.orig/channels.c openssh-8.4p1/channels.c c->local_consumed = 0; } return 1; -@@ -2548,7 +2583,7 @@ - size_t len, plen; - const u_char *pkt; - int r; -- -+ - if ((len = sshbuf_len(c->input)) == 0) { - if (c->istate == CHAN_INPUT_WAIT_DRAIN) { - /* -@@ -2594,7 +2629,6 @@ - c->self, ssh_err(r)); - } - c->remote_window -= plen; -- return; - } - - /* Enqueue packet for buffered data. */ -@@ -2666,7 +2700,7 @@ - c = sc->channels[i]; - if (c == NULL) - continue; -- -+ - /* - * We are only interested in channels that can have buffered - * incoming data. -@@ -2676,10 +2710,10 @@ - if ((c->flags & (CHAN_CLOSE_SENT|CHAN_CLOSE_RCVD))) { - /* XXX is this true? */ - debug3("channel %d: will not send data after close", -- c->self); -+ c->self); - continue; - } -- -+ - /* Get the amount of buffered data for this channel. */ - if (c->istate == CHAN_INPUT_OPEN || - c->istate == CHAN_INPUT_WAIT_DRAIN) -@@ -3382,6 +3416,14 @@ +@@ -3382,6 +3417,14 @@ return addr; } @@ -187,35 +136,31 @@ diff -Nur openssh-8.4p1.orig/channels.c openssh-8.4p1/channels.c static int channel_setup_fwd_listener_tcpip(struct ssh *ssh, int type, struct Forward *fwd, int *allocated_listen_port, -@@ -3522,9 +3564,11 @@ +@@ -3522,8 +3565,10 @@ } /* Allocate a channel number for the socket. */ + /* explicitly test for hpn disabled option. if true use smaller window size */ c = channel_new(ssh, "port listener", type, sock, sock, -1, - CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, -- 0, "port listener", 1); -+ hpn_disabled ? CHAN_TCP_WINDOW_DEFAULT : hpn_buffer_size, -+ CHAN_TCP_PACKET_DEFAULT, -+ 0, "port listener", 1); ++ hpn_disabled ? CHAN_TCP_WINDOW_DEFAULT : hpn_buffer_size, ++ CHAN_TCP_PACKET_DEFAULT, + 0, "port listener", 1); c->path = xstrdup(host); c->host_port = fwd->connect_port; - c->listening_addr = addr == NULL ? NULL : xstrdup(addr); -@@ -4694,8 +4738,9 @@ +@@ -4694,7 +4739,8 @@ sock = socks[n]; nc = channel_new(ssh, "x11 listener", SSH_CHANNEL_X11_LISTENER, sock, sock, -1, - CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, -- 0, "X11 inet listener", 1); -+ hpn_disabled ? CHAN_X11_WINDOW_DEFAULT : hpn_buffer_size, -+ CHAN_X11_PACKET_DEFAULT, -+ 0, "X11 inet listener", 1); ++ hpn_disabled ? CHAN_X11_WINDOW_DEFAULT : hpn_buffer_size, ++ CHAN_X11_PACKET_DEFAULT, + 0, "X11 inet listener", 1); nc->single_connection = single_connection; (*chanids)[n] = nc->self; - } diff -Nur openssh-8.4p1.orig/channels.h openssh-8.4p1/channels.h ---- openssh-8.4p1.orig/channels.h 2021-03-11 18:13:41.035604263 +0100 -+++ openssh-8.4p1/channels.h 2021-03-11 18:16:31.128747900 +0100 +--- openssh-8.4p1.orig/channels.h 2021-03-16 19:47:17.935228504 +0100 ++++ openssh-8.4p1/channels.h 2021-03-17 12:36:22.333608855 +0100 @@ -158,8 +158,10 @@ u_int local_window_max; u_int local_consumed; @@ -232,20 +177,21 @@ diff -Nur openssh-8.4p1.orig/channels.h openssh-8.4p1/channels.h /* Read buffer size */ -#define CHAN_RBUF (16*1024) -+#define CHAN_RBUF CHAN_SES_PACKET_DEFAULT ++#define CHAN_RBUF CHAN_SES_PACKET_DEFAULT /* Maximum channel input buffer size */ #define CHAN_INPUT_MAX (16*1024*1024) -@@ -352,4 +354,6 @@ +@@ -352,4 +354,7 @@ void chan_write_failed(struct ssh *, Channel *); void chan_obuf_empty(struct ssh *, Channel *); +/* hpn handler */ -+void channel_set_hpn(int, int); ++void channel_set_hpn(int, int); ++ #endif diff -Nur openssh-8.4p1.orig/cipher.c openssh-8.4p1/cipher.c ---- openssh-8.4p1.orig/cipher.c 2021-03-11 18:13:41.113603426 +0100 -+++ openssh-8.4p1/cipher.c 2021-03-11 18:16:31.130747879 +0100 +--- openssh-8.4p1.orig/cipher.c 2021-03-16 19:47:18.001228644 +0100 ++++ openssh-8.4p1/cipher.c 2021-03-16 21:03:32.981989967 +0100 @@ -48,6 +48,7 @@ #include "sshbuf.h" #include "ssherr.h" @@ -273,17 +219,7 @@ diff -Nur openssh-8.4p1.orig/cipher.c openssh-8.4p1/cipher.c #ifdef WITH_OPENSSL #ifndef OPENSSL_NO_DES { "3des-cbc", 8, 24, 0, 0, CFLAG_CBC, EVP_des_ede3_cbc }, -@@ -76,7 +80,8 @@ - 16, 32, 0, 0, CFLAG_CBC, EVP_aes_256_cbc }, - { "aes128-ctr", 16, 16, 0, 0, 0, EVP_aes_128_ctr }, - { "aes192-ctr", 16, 24, 0, 0, 0, EVP_aes_192_ctr }, -- { "aes256-ctr", 16, 32, 0, 0, 0, EVP_aes_256_ctr }, -+ { "aes256-ctr", 16, 32, 0, 0, 0, EVP_aes_256_ctr }, -+ - # ifdef OPENSSL_HAVE_EVPGCM - { "aes128-gcm@openssh.com", - 16, 16, 12, 16, 0, EVP_aes_128_gcm }, -@@ -135,6 +140,29 @@ +@@ -135,6 +139,29 @@ #endif } @@ -313,7 +249,7 @@ diff -Nur openssh-8.4p1.orig/cipher.c openssh-8.4p1/cipher.c u_int cipher_blocksize(const struct sshcipher *c) { -@@ -184,10 +212,10 @@ +@@ -184,10 +211,10 @@ return cc->plaintext; } @@ -326,20 +262,20 @@ diff -Nur openssh-8.4p1.orig/cipher.c openssh-8.4p1/cipher.c for (c = ciphers; c->name != NULL; c++) if (strcmp(c->name, name) == 0) return c; -@@ -209,7 +237,8 @@ +@@ -209,7 +236,8 @@ for ((p = strsep(&cp, CIPHER_SEP)); p && *p != '\0'; (p = strsep(&cp, CIPHER_SEP))) { c = cipher_by_name(p); - if (c == NULL || (c->flags & CFLAG_INTERNAL) != 0) { -+ if (c == NULL || ((c->flags & CFLAG_INTERNAL) != 0 && -+ (c->flags & CFLAG_NONE) != 0)) { ++ if (c == NULL || ((c->flags & CFLAG_INTERNAL) != 0 && ++ (c->flags & CFLAG_NONE) != 0)) { free(cipher_list); return 0; } diff -Nur openssh-8.4p1.orig/cipher-ctr-mt.c openssh-8.4p1/cipher-ctr-mt.c --- openssh-8.4p1.orig/cipher-ctr-mt.c 1970-01-01 01:00:00.000000000 +0100 -+++ openssh-8.4p1/cipher-ctr-mt.c 2021-03-11 18:16:31.128747900 +0100 -@@ -0,0 +1,677 @@ ++++ openssh-8.4p1/cipher-ctr-mt.c 2021-03-17 14:10:46.044449474 +0100 +@@ -0,0 +1,678 @@ +/* + * OpenSSH Multi-threaded AES-CTR Cipher + * @@ -388,8 +324,8 @@ diff -Nur openssh-8.4p1.orig/cipher-ctr-mt.c openssh-8.4p1/cipher-ctr-mt.c + +/*-------------------- TUNABLES --------------------*/ +/* maximum number of threads and queues */ -+#define MAX_THREADS 32 -+#define MAX_NUMKQ (MAX_THREADS * 2) ++#define MAX_THREADS 32 ++#define MAX_NUMKQ (MAX_THREADS * 2) + +/* Number of pregen threads to use */ +int cipher_threads = 2; @@ -482,13 +418,13 @@ diff -Nur openssh-8.4p1.orig/cipher-ctr-mt.c openssh-8.4p1/cipher-ctr-mt.c +/* Context struct */ +struct ssh_aes_ctr_ctx_mt +{ -+ int struct_id; ++ int struct_id; + struct kq q[MAX_NUMKQ]; + AES_KEY aes_ctx; + STATS_STRUCT(stats); + u_char aes_counter[AES_BLOCK_SIZE]; + pthread_t tid[MAX_THREADS]; -+ int id[MAX_THREADS]; ++ int id[MAX_THREADS]; + pthread_rwlock_t tid_lock; +#ifdef __APPLE__ + pthread_rwlock_t stop_lock; @@ -807,9 +743,10 @@ diff -Nur openssh-8.4p1.orig/cipher-ctr-mt.c openssh-8.4p1/cipher-ctr-mt.c + return 1; +} + -+#define HAVE_NONE 0 -+#define HAVE_KEY 1 -+#define HAVE_IV 2 ++#define HAVE_NONE 0 ++#define HAVE_KEY 1 ++#define HAVE_IV 2 ++ +int X = 0; + +static int @@ -836,14 +773,14 @@ diff -Nur openssh-8.4p1.orig/cipher-ctr-mt.c openssh-8.4p1/cipher-ctr-mt.c + req[1] = HW_NCPU; + + len = sizeof(ncpu); -+ sysctl(req, 2, &cipher_threads, &len, NULL, 0); ++ sysctl(req, 2, &cipher_threads, &len, NULL, 0); + cipher_threads = cipher_threads / 2; +#endif /*__FREEBSD__*/ + + /* if they have less than 4 cores spin up 4 threads anyway */ -+ if (cipher_threads < 2) ++ if (cipher_threads < 2) + cipher_threads = 2; -+ ++ + /* assure that we aren't trying to create more threads */ + /* than we have in the struct. cipher_threads is half the */ + /* total of allowable threads hence the odd looking math here */ @@ -874,7 +811,7 @@ diff -Nur openssh-8.4p1.orig/cipher-ctr-mt.c openssh-8.4p1/cipher-ctr-mt.c + if (c->state == (HAVE_KEY | HAVE_IV)) { + /* tell the pregen threads to exit */ + stop_and_join_pregen_threads(c); -+ ++ +#ifdef __APPLE__ + /* reset the exit flag */ + c->exit_flag = FALSE; @@ -969,7 +906,7 @@ diff -Nur openssh-8.4p1.orig/cipher-ctr-mt.c openssh-8.4p1/cipher-ctr-mt.c + if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) { +#ifdef CIPHER_THREAD_STATS + debug("AES-CTR MT main thread: %u drains, %u waits", c->stats.drains, -+ c->stats.waits); ++ c->stats.waits); +#endif + stop_and_join_pregen_threads(c); + @@ -1009,17 +946,17 @@ diff -Nur openssh-8.4p1.orig/cipher-ctr-mt.c openssh-8.4p1/cipher-ctr-mt.c + aes_ctr.cleanup = ssh_aes_ctr_cleanup; + aes_ctr.do_cipher = ssh_aes_ctr; +# ifndef SSH_OLD_EVP -+ aes_ctr.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH | ++ aes_ctr.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH | + EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV; +# endif /*SSH_OLD_EVP*/ -+ return &aes_ctr; ++ return &aes_ctr; +# endif /*OPENSSH_VERSION_NUMBER*/ +} + +#endif /* defined(WITH_OPENSSL) */ diff -Nur openssh-8.4p1.orig/cipher.h openssh-8.4p1/cipher.h ---- openssh-8.4p1.orig/cipher.h 2021-03-11 18:13:41.113603426 +0100 -+++ openssh-8.4p1/cipher.h 2021-03-11 18:16:31.130747879 +0100 +--- openssh-8.4p1.orig/cipher.h 2021-03-16 19:47:18.001228644 +0100 ++++ openssh-8.4p1/cipher.h 2021-03-17 14:46:39.537297808 +0100 @@ -68,7 +68,9 @@ struct sshcipher_ctx; @@ -1031,68 +968,52 @@ diff -Nur openssh-8.4p1.orig/cipher.h openssh-8.4p1/cipher.h const char *cipher_warning_message(const struct sshcipher_ctx *); int ciphers_valid(const char *); char *cipher_alg_list(char, int); -@@ -86,7 +88,10 @@ +@@ -86,6 +88,8 @@ u_int cipher_authlen(const struct sshcipher *); u_int cipher_ivlen(const struct sshcipher *); u_int cipher_is_cbc(const struct sshcipher *); +void cipher_reset_multithreaded(void); +const char *cipher_ctx_name(const struct sshcipher_ctx *); -+const char *cipher_ctx_name(const struct sshcipher_ctx *); u_int cipher_ctx_is_plaintext(struct sshcipher_ctx *); - int cipher_get_keyiv(struct sshcipher_ctx *, u_char *, size_t); diff -Nur openssh-8.4p1.orig/clientloop.c openssh-8.4p1/clientloop.c ---- openssh-8.4p1.orig/clientloop.c 2021-03-11 18:13:40.875605976 +0100 -+++ openssh-8.4p1/clientloop.c 2021-03-11 18:16:31.131747868 +0100 -@@ -1610,9 +1610,11 @@ - sock = x11_connect_display(ssh); - if (sock < 0) +--- openssh-8.4p1.orig/clientloop.c 2021-03-16 19:47:17.870228366 +0100 ++++ openssh-8.4p1/clientloop.c 2021-03-16 21:06:55.127417877 +0100 +@@ -1612,7 +1612,9 @@ return NULL; -- c = channel_new(ssh, "x11", -- SSH_CHANNEL_X11_OPEN, sock, sock, -1, + c = channel_new(ssh, "x11", + SSH_CHANNEL_X11_OPEN, sock, sock, -1, - CHAN_TCP_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, 0, "x11", 1); -+ c = channel_new(ssh, "x11", -+ SSH_CHANNEL_X11_OPEN, sock, sock, -1, -+ /* again is this really necessary for X11? */ -+ options.hpn_disabled ? CHAN_TCP_WINDOW_DEFAULT : options.hpn_buffer_size, -+ CHAN_X11_PACKET_DEFAULT, 0, "x11", 1); ++ /* again is this really necessary for X11? */ ++ options.hpn_disabled ? CHAN_TCP_WINDOW_DEFAULT : options.hpn_buffer_size, ++ CHAN_X11_PACKET_DEFAULT, 0, "x11", 1); c->force_drain = 1; return c; } -@@ -1641,9 +1643,10 @@ - return NULL; +@@ -1642,7 +1644,8 @@ } c = channel_new(ssh, "authentication agent connection", -- SSH_CHANNEL_OPEN, sock, sock, -1, + SSH_CHANNEL_OPEN, sock, sock, -1, - CHAN_X11_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, -- "authentication agent connection", 1); -+ SSH_CHANNEL_OPEN, sock, sock, -1, -+ options.hpn_disabled ? CHAN_X11_WINDOW_DEFAULT : options.hpn_buffer_size, -+ CHAN_TCP_PACKET_DEFAULT, 0, -+ "authentication agent connection", 1); ++ options.hpn_disabled ? CHAN_X11_WINDOW_DEFAULT : options.hpn_buffer_size, ++ CHAN_TCP_PACKET_DEFAULT, 0, + "authentication agent connection", 1); c->force_drain = 1; return c; - } -@@ -1668,10 +1671,13 @@ - } +@@ -1669,7 +1672,8 @@ debug("Tunnel forwarding using interface %s", ifname); -- c = channel_new(ssh, "tun", SSH_CHANNEL_OPENING, fd, fd, -1, + c = channel_new(ssh, "tun", SSH_CHANNEL_OPENING, fd, fd, -1, - CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1); -+ c = channel_new(ssh, "tun", SSH_CHANNEL_OPENING, fd, fd, -1, + options.hpn_disabled ? CHAN_TCP_WINDOW_DEFAULT : options.hpn_buffer_size, + CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1); c->datagram = 1; -+ -+ #if defined(SSH_TUN_FILTER) - if (options.tun_open == SSH_TUNMODE_POINTOPOINT) - channel_register_filter(ssh, c->self, sys_tun_infilter, diff -Nur openssh-8.4p1.orig/compat.c openssh-8.4p1/compat.c ---- openssh-8.4p1.orig/compat.c 2021-03-11 18:13:41.099603576 +0100 -+++ openssh-8.4p1/compat.c 2021-03-11 18:16:31.132747857 +0100 +--- openssh-8.4p1.orig/compat.c 2021-03-16 19:47:17.996228634 +0100 ++++ openssh-8.4p1/compat.c 2021-03-16 19:48:09.902338892 +0100 @@ -151,6 +151,15 @@ debug("match: %s pat %s compat 0x%08x", version, check[i].pat, check[i].bugs); @@ -1110,8 +1031,8 @@ diff -Nur openssh-8.4p1.orig/compat.c openssh-8.4p1/compat.c } } diff -Nur openssh-8.4p1.orig/compat.h openssh-8.4p1/compat.h ---- openssh-8.4p1.orig/compat.h 2021-03-11 18:13:41.085603726 +0100 -+++ openssh-8.4p1/compat.h 2021-03-11 18:16:31.132747857 +0100 +--- openssh-8.4p1.orig/compat.h 2021-03-16 19:47:17.995228631 +0100 ++++ openssh-8.4p1/compat.h 2021-03-16 19:48:09.902338892 +0100 @@ -57,6 +57,7 @@ #define SSH_BUG_CURVE25519PAD 0x10000000 #define SSH_BUG_HOSTKEYS 0x20000000 @@ -1122,7 +1043,7 @@ diff -Nur openssh-8.4p1.orig/compat.h openssh-8.4p1/compat.h char *compat_cipher_proposal(char *); diff -Nur openssh-8.4p1.orig/defines.h openssh-8.4p1/defines.h --- openssh-8.4p1.orig/defines.h 2020-09-27 09:25:01.000000000 +0200 -+++ openssh-8.4p1/defines.h 2021-03-11 18:16:31.132747857 +0100 ++++ openssh-8.4p1/defines.h 2021-03-16 19:48:09.902338892 +0100 @@ -848,7 +848,7 @@ #endif @@ -1133,34 +1054,32 @@ diff -Nur openssh-8.4p1.orig/defines.h openssh-8.4p1/defines.h /* diff -Nur openssh-8.4p1.orig/digest.h openssh-8.4p1/digest.h ---- openssh-8.4p1.orig/digest.h 2021-03-11 18:13:41.070603887 +0100 -+++ openssh-8.4p1/digest.h 2021-03-11 18:16:31.133747846 +0100 +--- openssh-8.4p1.orig/digest.h 2021-03-16 19:47:17.975228589 +0100 ++++ openssh-8.4p1/digest.h 2021-03-16 20:44:12.111531917 +0100 @@ -27,7 +27,8 @@ #define SSH_DIGEST_SHA256 2 #define SSH_DIGEST_SHA384 3 #define SSH_DIGEST_SHA512 4 -#define SSH_DIGEST_MAX 5 -+#define SSH_DIGEST_NULL 5 ++#define SSH_DIGEST_NULL 5 +#define SSH_DIGEST_MAX 6 struct sshbuf; struct ssh_digest_ctx; diff -Nur openssh-8.4p1.orig/digest-openssl.c openssh-8.4p1/digest-openssl.c ---- openssh-8.4p1.orig/digest-openssl.c 2021-03-11 18:13:41.070603887 +0100 -+++ openssh-8.4p1/digest-openssl.c 2021-03-11 18:16:31.133747846 +0100 -@@ -61,7 +61,8 @@ +--- openssh-8.4p1.orig/digest-openssl.c 2021-03-16 19:47:17.975228589 +0100 ++++ openssh-8.4p1/digest-openssl.c 2021-03-16 20:46:16.192795507 +0100 +@@ -61,6 +61,7 @@ { SSH_DIGEST_SHA256, "SHA256", 32, EVP_sha256 }, { SSH_DIGEST_SHA384, "SHA384", 48, EVP_sha384 }, { SSH_DIGEST_SHA512, "SHA512", 64, EVP_sha512 }, -- { -1, NULL, 0, NULL }, -+ { SSH_DIGEST_NULL, "NONEMAC", 0, EVP_md_null}, -+ { -1, NULL, 0, NULL }, ++ { SSH_DIGEST_NULL, "NONEMAC", 0, EVP_md_null}, + { -1, NULL, 0, NULL }, }; - const EVP_MD * diff -Nur openssh-8.4p1.orig/HPN-README openssh-8.4p1/HPN-README --- openssh-8.4p1.orig/HPN-README 1970-01-01 01:00:00.000000000 +0100 -+++ openssh-8.4p1/HPN-README 2021-03-11 18:16:31.124747944 +0100 ++++ openssh-8.4p1/HPN-README 2021-03-17 09:11:32.385206429 +0100 @@ -0,0 +1,153 @@ +Notes: + @@ -1198,7 +1117,7 @@ diff -Nur openssh-8.4p1.orig/HPN-README openssh-8.4p1/HPN-README +authentication ciphers) when using the NONE cipher. You must enable the following: +NoneEnabled, NoneSwitch, and NoneMacEnabled. If all three are not enabled the None MAC +will be automatically disabled. In tests the use of the None MAC improved throuput by -+more than 30%. ++more than 30%. + +ex: scp -oNoneSwitch=yes -oNoneEnabled=yes -oNoneMacEnabled=yes file host:~ + @@ -1275,7 +1194,7 @@ diff -Nur openssh-8.4p1.orig/HPN-README openssh-8.4p1/HPN-README + Enable or disable the use of the None MAC. When this is enabled ssh +will *not* provide data integrity of any data being transmitted between hosts. Use +with caution as it, unlike just using NoneEnabled, doesn't provide data integrity and -+protection against man-in-the-middle attacks. As with NoneEnabled all authentication ++protection against man-in-the-middle attacks. As with NoneEnabled all authentication +remains encrypted and integrity is ensured. Default is no. + +NoneSwitch=[yes/no] client @@ -1312,12 +1231,12 @@ diff -Nur openssh-8.4p1.orig/HPN-README openssh-8.4p1/HPN-README + by Michael Stevens (mstevens@andrew.cmu.edu). The MT-AES-CTR cipher was + implemented by Ben Bennet (ben@psc.edu) and improved by Mike Tasota + (tasota@gmail.com) an NSF REU grant recipient for 2013. -+ Allan Jude provided the code for the NoneMac and buffer normalization. ++ Allan Jude provided the code for the NoneMac and buffer normalization. + This work was financed, in part, by Cisco System, Inc., the National + Library of Medicine, and the National Science Foundation. diff -Nur openssh-8.4p1.orig/kex.c openssh-8.4p1/kex.c ---- openssh-8.4p1.orig/kex.c 2021-03-11 18:13:41.127603276 +0100 -+++ openssh-8.4p1/kex.c 2021-03-11 18:16:31.134747835 +0100 +--- openssh-8.4p1.orig/kex.c 2021-03-16 19:47:18.012228668 +0100 ++++ openssh-8.4p1/kex.c 2021-03-16 20:53:01.084649104 +0100 @@ -64,6 +64,7 @@ #include "ssherr.h" @@ -1332,7 +1251,7 @@ diff -Nur openssh-8.4p1.orig/kex.c openssh-8.4p1/kex.c int r, first_kex_follows; + int auth_flag = 0; + int log_flag = 0; -+ ++ + auth_flag = packet_authentication_state(ssh); + debug("AUTH STATE IS %d", auth_flag); @@ -1351,7 +1270,7 @@ diff -Nur openssh-8.4p1.orig/kex.c openssh-8.4p1/kex.c + } + else + fatal("Pre-authentication none cipher requests are not allowed."); -+ if (newkeys->mac.name != NULL && strcmp(newkeys->mac.name, "none") == 0) ++ if (newkeys->mac.name != NULL && strcmp(newkeys->mac.name, "none") == 0) + debug("Requesting: NONEMAC. Authflag is %d", auth_flag); + } + @@ -1394,18 +1313,18 @@ diff -Nur openssh-8.4p1.orig/kex.c openssh-8.4p1/kex.c } + + /* report the version information to syslog if this is the server */ -+ if (timeout_ms == -1) { /* only the server uses this value */ ++ if (timeout_ms == -1) { /* only the server uses this value */ + logit("SSH: Server;Ltype: Version;Remote: %s-%d;Protocol: %d.%d;Client: %.100s", -+ ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), -+ remote_major, remote_minor, remote_version); ++ ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), ++ remote_major, remote_minor, remote_version); + } -+ ++ debug("Remote protocol version %d.%d, remote software version %.100s", remote_major, remote_minor, remote_version); ssh->compat = compat_datafellows(remote_version); diff -Nur openssh-8.4p1.orig/log.c openssh-8.4p1/log.c ---- openssh-8.4p1.orig/log.c 2021-03-11 18:13:41.012604510 +0100 -+++ openssh-8.4p1/log.c 2021-03-11 18:16:31.135747825 +0100 +--- openssh-8.4p1.orig/log.c 2021-03-16 19:47:17.912228455 +0100 ++++ openssh-8.4p1/log.c 2021-03-16 19:48:09.904338896 +0100 @@ -46,6 +46,11 @@ #include #include @@ -1428,19 +1347,19 @@ diff -Nur openssh-8.4p1.orig/log.c openssh-8.4p1/log.c #define LOG_STDERR_VIS (VIS_SAFE|VIS_OCTAL) diff -Nur openssh-8.4p1.orig/mac.c openssh-8.4p1/mac.c ---- openssh-8.4p1.orig/mac.c 2021-03-11 18:13:41.114603415 +0100 -+++ openssh-8.4p1/mac.c 2021-03-11 18:16:31.135747825 +0100 +--- openssh-8.4p1.orig/mac.c 2021-03-16 19:47:18.002228646 +0100 ++++ openssh-8.4p1/mac.c 2021-03-16 20:54:42.869864173 +0100 @@ -63,6 +63,7 @@ { "hmac-sha2-512", SSH_DIGEST, SSH_DIGEST_SHA512, 0, 0, 0, 0 }, { "hmac-md5", SSH_DIGEST, SSH_DIGEST_MD5, 0, 0, 0, 0 }, { "hmac-md5-96", SSH_DIGEST, SSH_DIGEST_MD5, 96, 0, 0, 0 }, -+ { "none", SSH_DIGEST, SSH_DIGEST_NULL, 0, 0, 0, 0 }, ++ { "none", SSH_DIGEST, SSH_DIGEST_NULL, 0, 0, 0, 0 }, { "umac-64@openssh.com", SSH_UMAC, 0, 0, 128, 64, 0 }, { "umac-128@openssh.com", SSH_UMAC128, 0, 0, 128, 128, 0 }, diff -Nur openssh-8.4p1.orig/Makefile.in openssh-8.4p1/Makefile.in ---- openssh-8.4p1.orig/Makefile.in 2021-03-11 18:13:41.154602986 +0100 -+++ openssh-8.4p1/Makefile.in 2021-03-11 18:16:31.124747944 +0100 +--- openssh-8.4p1.orig/Makefile.in 2021-03-16 19:47:18.031228708 +0100 ++++ openssh-8.4p1/Makefile.in 2021-03-16 19:48:09.905338898 +0100 @@ -49,7 +49,7 @@ CFLAGS_NOPIE=@CFLAGS_NOPIE@ CPPFLAGS=-I. -I$(srcdir) @CPPFLAGS@ $(PATHS) @DEFS@ @@ -1460,8 +1379,8 @@ diff -Nur openssh-8.4p1.orig/Makefile.in openssh-8.4p1/Makefile.in log.o match.o moduli.o nchan.o packet.o \ readpass.o ttymodes.o xmalloc.o addrmatch.o \ diff -Nur openssh-8.4p1.orig/packet.c openssh-8.4p1/packet.c ---- openssh-8.4p1.orig/packet.c 2021-03-11 18:13:41.117603383 +0100 -+++ openssh-8.4p1/packet.c 2021-03-11 18:16:31.136747814 +0100 +--- openssh-8.4p1.orig/packet.c 2021-03-16 19:47:18.005228653 +0100 ++++ openssh-8.4p1/packet.c 2021-03-16 21:27:52.291079838 +0100 @@ -246,7 +246,7 @@ TAILQ_INIT(&ssh->public_keys); state->connection_in = -1; @@ -1480,7 +1399,7 @@ diff -Nur openssh-8.4p1.orig/packet.c openssh-8.4p1/packet.c int r; if (none == NULL) { -@@ -970,18 +970,45 @@ +@@ -970,10 +970,19 @@ * so enforce a 1GB limit for small blocksizes. * See RFC4344 section 3.2. */ @@ -1504,9 +1423,7 @@ diff -Nur openssh-8.4p1.orig/packet.c openssh-8.4p1/packet.c if (state->rekey_limit) *max_blocks = MINIMUM(*max_blocks, state->rekey_limit / enc->block_size); - debug("rekey %s after %llu blocks", dir, -- (unsigned long long)*max_blocks); -+ (unsigned long long)*max_blocks); +@@ -982,6 +991,24 @@ return 0; } @@ -1535,12 +1452,12 @@ diff -Nur openssh-8.4p1.orig/packet.c openssh-8.4p1/packet.c if (state->p_send.packets == 0 && state->p_read.packets == 0) return 0; -+ /* used to force rekeying when called for by the none -+ * cipher switch and aes-mt-ctr methods -cjr */ -+ if (rekey_requested == 1) { -+ rekey_requested = 0; -+ return 1; -+ } ++ /* used to force rekeying when called for by the none ++ * cipher switch and aes-mt-ctr methods -cjr */ ++ if (rekey_requested == 1) { ++ rekey_requested = 0; ++ return 1; ++ } + /* Time-based rekeying */ if (state->rekey_interval != 0 && @@ -1581,21 +1498,21 @@ diff -Nur openssh-8.4p1.orig/packet.c openssh-8.4p1/packet.c } +/* this prints out the final log entry */ -+void ++void +sshpkt_final_log_entry (struct ssh *ssh) { + double total_time; -+ -+ if (ssh->start_time < 1) ++ ++ if (ssh->start_time < 1) + /* this will produce a NaN in the output. -cjr */ + total_time = 0; + else + total_time = monotime_double() - ssh->start_time; -+ ++ + logit("SSH: Server;LType: Throughput;Remote: %s-%d;IN: %lu;OUT: %lu;Duration: %.1f;tPut_in: %.1f;tPut_out: %.1f", -+ ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), -+ ssh->stdin_bytes, ssh->fdout_bytes, total_time, -+ ssh->stdin_bytes / total_time, -+ ssh->fdout_bytes / total_time); ++ ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), ++ ssh->stdin_bytes, ssh->fdout_bytes, total_time, ++ ssh->stdin_bytes / total_time, ++ ssh->fdout_bytes / total_time); +} + /* @@ -1610,11 +1527,11 @@ diff -Nur openssh-8.4p1.orig/packet.c openssh-8.4p1/packet.c +void * +ssh_packet_get_send_context(struct ssh *ssh) +{ -+ return ssh->state->send_context; ++ return ssh->state->send_context; +} diff -Nur openssh-8.4p1.orig/packet.h openssh-8.4p1/packet.h ---- openssh-8.4p1.orig/packet.h 2021-03-11 18:13:41.117603383 +0100 -+++ openssh-8.4p1/packet.h 2021-03-11 18:16:31.136747814 +0100 +--- openssh-8.4p1.orig/packet.h 2021-03-16 19:47:18.005228653 +0100 ++++ openssh-8.4p1/packet.h 2021-03-16 21:16:54.629688051 +0100 @@ -86,6 +86,14 @@ /* APP data */ @@ -1649,13 +1566,13 @@ diff -Nur openssh-8.4p1.orig/packet.h openssh-8.4p1/packet.h +/* for forced packet rekeying post auth */ +void packet_request_rekeying(void); +/* final log entry support */ -+void sshpkt_final_log_entry (struct ssh *); ++void sshpkt_final_log_entry (struct ssh *); /* new API */ int sshpkt_start(struct ssh *ssh, u_char type); diff -Nur openssh-8.4p1.orig/progressmeter.c openssh-8.4p1/progressmeter.c --- openssh-8.4p1.orig/progressmeter.c 2020-09-27 09:25:01.000000000 +0200 -+++ openssh-8.4p1/progressmeter.c 2021-03-11 18:16:31.136747814 +0100 ++++ openssh-8.4p1/progressmeter.c 2021-03-16 21:30:17.596387724 +0100 @@ -68,6 +68,8 @@ static off_t start_pos; /* initial position of transfer */ static off_t end_pos; /* ending position of transfer */ @@ -1700,10 +1617,10 @@ diff -Nur openssh-8.4p1.orig/progressmeter.c openssh-8.4p1/progressmeter.c + /* instantaneous rate */ + if (bytes_left > 0) + format_rate(buf + strlen(buf), win_size - strlen(buf), -+ delta_pos); ++ delta_pos); + else + format_rate(buf + strlen(buf), win_size - strlen(buf), -+ max_delta_pos); ++ max_delta_pos); + strlcat(buf, "/s ", win_size); + /* ETA */ @@ -1718,8 +1635,8 @@ diff -Nur openssh-8.4p1.orig/progressmeter.c openssh-8.4p1/progressmeter.c /*ARGSUSED*/ diff -Nur openssh-8.4p1.orig/readconf.c openssh-8.4p1/readconf.c ---- openssh-8.4p1.orig/readconf.c 2021-03-11 18:13:41.146603072 +0100 -+++ openssh-8.4p1/readconf.c 2021-03-11 18:18:58.965186079 +0100 +--- openssh-8.4p1.orig/readconf.c 2021-03-16 19:47:18.033228712 +0100 ++++ openssh-8.4p1/readconf.c 2021-03-17 12:39:38.158030116 +0100 @@ -67,6 +67,7 @@ #include "uidswap.h" #include "myproposal.h" @@ -1745,23 +1662,23 @@ diff -Nur openssh-8.4p1.orig/readconf.c openssh-8.4p1/readconf.c + { "noneenabled", oNoneEnabled }, + { "nonemacenabled", oNoneMacEnabled }, + { "noneswitch", oNoneSwitch }, -+ { "disablemtaes", oDisableMTAES }, ++ { "disablemtaes", oDisableMTAES }, { "proxyusefdpass", oProxyUseFdpass }, { "canonicaldomains", oCanonicalDomains }, { "canonicalizefallbacklocal", oCanonicalizeFallbackLocal }, -@@ -325,7 +333,10 @@ - { "ignoreunknown", oIgnoreUnknown }, +@@ -326,6 +334,11 @@ { "proxyjump", oProxyJump }, { "securitykeyprovider", oSecurityKeyProvider }, -- + + { "tcprcvbufpoll", oTcpRcvBufPoll }, + { "tcprcvbuf", oTcpRcvBuf }, + { "hpndisabled", oHPNDisabled }, + { "hpnbuffersize", oHPNBufferSize }, ++ { NULL, oBadOption } }; -@@ -1127,6 +1138,46 @@ +@@ -1127,6 +1140,46 @@ intptr = &options->check_host_ip; goto parse_flag; @@ -1784,11 +1701,11 @@ diff -Nur openssh-8.4p1.orig/readconf.c openssh-8.4p1/readconf.c + case oNoneMacEnabled: + intptr = &options->nonemac_enabled; + goto parse_flag; -+ -+ case oDisableMTAES: ++ ++ case oDisableMTAES: + intptr = &options->disable_multithreaded; + goto parse_flag; -+ ++ + /* + * We check to see if the command comes from the command + * line or not. If it does then enable it otherwise fail. @@ -1808,7 +1725,7 @@ diff -Nur openssh-8.4p1.orig/readconf.c openssh-8.4p1/readconf.c case oVerifyHostKeyDNS: intptr = &options->verify_host_key_dns; multistate_ptr = multistate_yesnoask; -@@ -1327,6 +1378,10 @@ +@@ -1327,6 +1380,10 @@ *intptr = value; break; @@ -1819,14 +1736,14 @@ diff -Nur openssh-8.4p1.orig/readconf.c openssh-8.4p1/readconf.c case oCiphers: arg = strdelim(&s); if (!arg || *arg == '\0') -@@ -2103,6 +2158,14 @@ +@@ -2103,6 +2160,14 @@ options->ip_qos_interactive = -1; options->ip_qos_bulk = -1; options->request_tty = -1; + options->none_switch = -1; + options->none_enabled = -1; + options->nonemac_enabled = -1; -+ options->disable_multithreaded = -1; ++ options->disable_multithreaded = -1; + options->hpn_disabled = -1; + options->hpn_buffer_size = -1; + options->tcp_rcv_buf_poll = -1; @@ -1834,7 +1751,7 @@ diff -Nur openssh-8.4p1.orig/readconf.c openssh-8.4p1/readconf.c options->proxy_use_fdpass = -1; options->ignored_unknown = NULL; options->num_canonical_domains = 0; -@@ -2269,6 +2332,43 @@ +@@ -2269,6 +2334,43 @@ options->server_alive_interval = 0; if (options->server_alive_count_max == -1) options->server_alive_count_max = 3; @@ -1873,14 +1790,14 @@ diff -Nur openssh-8.4p1.orig/readconf.c openssh-8.4p1/readconf.c + fprintf(stderr, "None MAC can only be used with the None cipher. None MAC disabled.\n"); + options->nonemac_enabled = 0; + } -+ if (options->disable_multithreaded == -1) ++ if (options->disable_multithreaded == -1) + options->disable_multithreaded = 0; if (options->control_master == -1) options->control_master = 0; if (options->control_persist == -1) { diff -Nur openssh-8.4p1.orig/readconf.h openssh-8.4p1/readconf.h ---- openssh-8.4p1.orig/readconf.h 2021-03-11 18:13:41.146603072 +0100 -+++ openssh-8.4p1/readconf.h 2021-03-11 18:16:31.138747792 +0100 +--- openssh-8.4p1.orig/readconf.h 2021-03-16 19:47:18.034228714 +0100 ++++ openssh-8.4p1/readconf.h 2021-03-17 15:06:07.668894706 +0100 @@ -57,6 +57,10 @@ int strict_host_key_checking; /* Strict host key checking. */ int compression; /* Compress packets in both directions. */ @@ -1907,16 +1824,8 @@ diff -Nur openssh-8.4p1.orig/readconf.h openssh-8.4p1/readconf.h int server_alive_interval; diff -Nur openssh-8.4p1.orig/regress/integrity.sh openssh-8.4p1/regress/integrity.sh --- openssh-8.4p1.orig/regress/integrity.sh 2020-09-27 09:25:01.000000000 +0200 -+++ openssh-8.4p1/regress/integrity.sh 2021-03-11 18:16:31.139747781 +0100 -@@ -8,6 +8,7 @@ - tries=10 - startoffset=2900 - macs=`${SSH} -Q mac` -+ - # The following are not MACs, but ciphers with integrated integrity. They are - # handled specially below. - macs="$macs `${SSH} -Q cipher-auth`" -@@ -21,6 +22,12 @@ ++++ openssh-8.4p1/regress/integrity.sh 2021-03-16 21:39:40.152581252 +0100 +@@ -21,6 +21,12 @@ cmd="$SUDO env SSH_SK_HELPER="$SSH_SK_HELPER" sh ${SRC}/sshd-log-wrapper.sh ${TEST_SSHD_LOGFILE} ${SSHD} -i -f $OBJ/sshd_proxy" for m in $macs; do @@ -1930,8 +1839,8 @@ diff -Nur openssh-8.4p1.orig/regress/integrity.sh openssh-8.4p1/regress/integrit elen=0 epad=0 diff -Nur openssh-8.4p1.orig/sandbox-seccomp-filter.c openssh-8.4p1/sandbox-seccomp-filter.c ---- openssh-8.4p1.orig/sandbox-seccomp-filter.c 2021-03-11 18:13:41.128603265 +0100 -+++ openssh-8.4p1/sandbox-seccomp-filter.c 2021-03-11 18:16:31.139747781 +0100 +--- openssh-8.4p1.orig/sandbox-seccomp-filter.c 2021-03-16 19:47:18.014228672 +0100 ++++ openssh-8.4p1/sandbox-seccomp-filter.c 2021-03-16 19:48:09.909338907 +0100 @@ -216,6 +216,9 @@ #ifdef __NR_geteuid32 SC_ALLOW(__NR_geteuid32), @@ -1953,8 +1862,8 @@ diff -Nur openssh-8.4p1.orig/sandbox-seccomp-filter.c openssh-8.4p1/sandbox-secc SC_ALLOW(__NR_time), #endif diff -Nur openssh-8.4p1.orig/scp.c openssh-8.4p1/scp.c ---- openssh-8.4p1.orig/scp.c 2021-03-11 18:13:41.135603190 +0100 -+++ openssh-8.4p1/scp.c 2021-03-11 18:16:31.139747781 +0100 +--- openssh-8.4p1.orig/scp.c 2021-03-16 19:47:18.021228687 +0100 ++++ openssh-8.4p1/scp.c 2021-03-16 19:48:09.909338907 +0100 @@ -1251,7 +1251,7 @@ off_t size, statbytes; unsigned long long ull; @@ -1965,8 +1874,8 @@ diff -Nur openssh-8.4p1.orig/scp.c openssh-8.4p1/scp.c size_t n, npatterns = 0; struct timeval tv[2]; diff -Nur openssh-8.4p1.orig/servconf.c openssh-8.4p1/servconf.c ---- openssh-8.4p1.orig/servconf.c 2021-03-11 18:13:41.146603072 +0100 -+++ openssh-8.4p1/servconf.c 2021-03-11 18:20:18.397376031 +0100 +--- openssh-8.4p1.orig/servconf.c 2021-03-16 19:47:18.034228714 +0100 ++++ openssh-8.4p1/servconf.c 2021-03-16 21:42:22.358925585 +0100 @@ -70,6 +70,7 @@ #include "auth.h" #include "myproposal.h" @@ -2082,11 +1991,10 @@ diff -Nur openssh-8.4p1.orig/servconf.c openssh-8.4p1/servconf.c *flags = keywords[i].flags; return keywords[i].opcode; } -@@ -1549,12 +1615,37 @@ +@@ -1549,12 +1615,36 @@ multistate_ptr = multistate_ignore_rhosts; goto parse_multistate; -+ + case sTcpRcvBufPoll: + intptr = &options->tcp_rcv_buf_poll; + goto parse_flag; @@ -2108,11 +2016,11 @@ diff -Nur openssh-8.4p1.orig/servconf.c openssh-8.4p1/servconf.c + case sNoneEnabled: + intptr = &options->none_enabled; + goto parse_flag; -+ ++ + case sNoneMacEnabled: + intptr = &options->nonemac_enabled; + goto parse_flag; -+ ++ + case sDisableMTAES: + intptr = &options->disable_multithreaded; + goto parse_flag; @@ -2121,8 +2029,8 @@ diff -Nur openssh-8.4p1.orig/servconf.c openssh-8.4p1/servconf.c intptr = &options->hostbased_authentication; goto parse_flag; diff -Nur openssh-8.4p1.orig/servconf.h openssh-8.4p1/servconf.h ---- openssh-8.4p1.orig/servconf.h 2021-03-11 18:13:41.147603061 +0100 -+++ openssh-8.4p1/servconf.h 2021-03-11 18:21:39.595526486 +0100 +--- openssh-8.4p1.orig/servconf.h 2021-03-16 19:47:18.035228717 +0100 ++++ openssh-8.4p1/servconf.h 2021-03-17 15:07:28.845076726 +0100 @@ -209,6 +209,13 @@ int use_pam; /* Enable auth via PAM */ int permit_pam_user_change; /* Allow PAM to change user name */ @@ -2138,8 +2046,8 @@ diff -Nur openssh-8.4p1.orig/servconf.h openssh-8.4p1/servconf.h char **permitted_opens; /* May also be one of PERMITOPEN_* */ diff -Nur openssh-8.4p1.orig/serverloop.c openssh-8.4p1/serverloop.c ---- openssh-8.4p1.orig/serverloop.c 2021-03-11 18:13:41.136603179 +0100 -+++ openssh-8.4p1/serverloop.c 2021-03-11 18:16:31.142747749 +0100 +--- openssh-8.4p1.orig/serverloop.c 2021-03-16 19:47:18.022228689 +0100 ++++ openssh-8.4p1/serverloop.c 2021-03-17 14:17:44.397405049 +0100 @@ -322,7 +322,7 @@ process_input(struct ssh *ssh, fd_set *readset, int connection_in) { @@ -2165,48 +2073,35 @@ diff -Nur openssh-8.4p1.orig/serverloop.c openssh-8.4p1/serverloop.c ssh_signal(SIGCHLD, sigchld_handler); child_terminated = 0; -@@ -442,7 +444,9 @@ - &readset, &writeset, &max_fd, &nalloc, rekey_timeout_ms); +@@ -443,6 +445,7 @@ if (received_sigterm) { -+ sshpkt_final_log_entry(ssh); logit("Exiting on signal %d", (int)received_sigterm); + sshpkt_final_log_entry(ssh); /* Clean up sessions, utmp, etc. */ cleanup_exit(255); } -@@ -455,13 +459,19 @@ - process_output(ssh, writeset, connection_out); - } - collect_children(ssh); -- -+ - free(readset); - free(writeset); - -+ /* write final log entry */ -+ sshpkt_final_log_entry(ssh); -+ +@@ -462,6 +465,9 @@ /* free all channels, no more reads and writes */ channel_free_all(ssh); + /* final entry must come after channels close -cjr */ -+ sshpkt_final_log_entry(ssh); -+ ++ sshpkt_final_log_entry(ssh); ++ /* free remaining sessions, e.g. remove wtmp entries */ session_destroy_all(ssh, NULL); } -@@ -612,7 +622,8 @@ +@@ -612,7 +618,8 @@ debug("Tunnel forwarding using interface %s", ifname); c = channel_new(ssh, "tun", SSH_CHANNEL_OPEN, sock, sock, -1, - CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1); -+ options.hpn_disabled ? CHAN_TCP_WINDOW_DEFAULT : options.hpn_buffer_size, -+ CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1); ++ options.hpn_disabled ? CHAN_TCP_WINDOW_DEFAULT : options.hpn_buffer_size, ++ CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1); c->datagram = 1; #if defined(SSH_TUN_FILTER) if (mode == SSH_TUNMODE_POINTOPOINT) -@@ -663,6 +674,8 @@ +@@ -663,6 +670,8 @@ c = channel_new(ssh, "session", SSH_CHANNEL_LARVAL, -1, -1, -1, /*window size*/0, CHAN_SES_PACKET_DEFAULT, 0, "server-session", 1); @@ -2216,17 +2111,9 @@ diff -Nur openssh-8.4p1.orig/serverloop.c openssh-8.4p1/serverloop.c debug("session open failed, free channel %d", c->self); channel_free(ssh, c); diff -Nur openssh-8.4p1.orig/session.c openssh-8.4p1/session.c ---- openssh-8.4p1.orig/session.c 2021-03-11 18:13:41.124603308 +0100 -+++ openssh-8.4p1/session.c 2021-03-11 18:16:31.143747738 +0100 -@@ -97,6 +97,7 @@ - #include "sftp.h" - #include "atomicio.h" - -+ - #if defined(KRB5) && defined(USE_AFS) - #include - #endif -@@ -228,6 +229,7 @@ +--- openssh-8.4p1.orig/session.c 2021-03-16 19:47:18.010228663 +0100 ++++ openssh-8.4p1/session.c 2021-03-16 21:52:59.138274844 +0100 +@@ -228,6 +228,7 @@ goto authsock_err; /* Allocate a channel for the authentication agent socket. */ @@ -2234,43 +2121,19 @@ diff -Nur openssh-8.4p1.orig/session.c openssh-8.4p1/session.c nc = channel_new(ssh, "auth socket", SSH_CHANNEL_AUTH_SOCKET, sock, sock, -1, CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, -@@ -467,7 +469,7 @@ - return -1; - case 0: - is_child = 1; -- -+ - /* - * Create a new session and process group since the 4.4BSD - * setlogin() affects the entire process group. -@@ -612,7 +614,7 @@ - return -1; - case 0: - is_child = 1; -- -+ - close(fdout); - close(ptymaster); - -@@ -2371,10 +2373,11 @@ - */ - if (s->chanid == -1) - fatal("no channel for session %d", s->self); -- channel_set_fds(ssh, s->chanid, -- fdout, fdin, fderr, -- ignore_fderr ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ, +@@ -2374,7 +2375,8 @@ + channel_set_fds(ssh, s->chanid, + fdout, fdin, fderr, + ignore_fderr ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ, - 1, is_tty, CHAN_SES_WINDOW_DEFAULT); -+ channel_set_fds(ssh, s->chanid, -+ fdout, fdin, fderr, -+ ignore_fderr ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ, -+ 1, is_tty, -+ options.hpn_disabled ? CHAN_SES_WINDOW_DEFAULT : options.hpn_buffer_size); ++ 1, is_tty, ++ options.hpn_disabled ? CHAN_SES_WINDOW_DEFAULT : options.hpn_buffer_size); } /* diff -Nur openssh-8.4p1.orig/sftp.1 openssh-8.4p1/sftp.1 --- openssh-8.4p1.orig/sftp.1 2020-09-27 09:25:01.000000000 +0200 -+++ openssh-8.4p1/sftp.1 2021-03-11 18:16:31.143747738 +0100 ++++ openssh-8.4p1/sftp.1 2021-03-16 19:48:09.913338915 +0100 @@ -295,7 +295,8 @@ Specify how many requests may be outstanding at any one time. Increasing this may slightly improve file transfer speed @@ -2282,8 +2145,8 @@ diff -Nur openssh-8.4p1.orig/sftp.1 openssh-8.4p1/sftp.1 Recursively copy entire directories when uploading and downloading. Note that diff -Nur openssh-8.4p1.orig/sftp.c openssh-8.4p1/sftp.c ---- openssh-8.4p1.orig/sftp.c 2021-03-11 18:13:41.136603179 +0100 -+++ openssh-8.4p1/sftp.c 2021-03-11 18:16:31.143747738 +0100 +--- openssh-8.4p1.orig/sftp.c 2021-03-16 19:47:18.022228689 +0100 ++++ openssh-8.4p1/sftp.c 2021-03-16 19:48:09.913338915 +0100 @@ -71,7 +71,7 @@ #include "sftp-client.h" @@ -2295,7 +2158,7 @@ diff -Nur openssh-8.4p1.orig/sftp.c openssh-8.4p1/sftp.c FILE* infile; diff -Nur openssh-8.4p1.orig/ssh_api.c openssh-8.4p1/ssh_api.c --- openssh-8.4p1.orig/ssh_api.c 2020-09-27 09:25:01.000000000 +0200 -+++ openssh-8.4p1/ssh_api.c 2021-03-11 18:16:31.144747727 +0100 ++++ openssh-8.4p1/ssh_api.c 2021-03-16 19:48:09.914338917 +0100 @@ -411,7 +411,7 @@ char *cp; int r; @@ -2307,7 +2170,7 @@ diff -Nur openssh-8.4p1.orig/ssh_api.c openssh-8.4p1/ssh_api.c return r; diff -Nur openssh-8.4p1.orig/sshbuf.h openssh-8.4p1/sshbuf.h --- openssh-8.4p1.orig/sshbuf.h 2020-09-27 09:25:01.000000000 +0200 -+++ openssh-8.4p1/sshbuf.h 2021-03-11 18:16:31.145747716 +0100 ++++ openssh-8.4p1/sshbuf.h 2021-03-16 19:48:09.914338917 +0100 @@ -28,7 +28,7 @@ # endif /* OPENSSL_HAS_ECC */ #endif /* WITH_OPENSSL */ @@ -2318,8 +2181,8 @@ diff -Nur openssh-8.4p1.orig/sshbuf.h openssh-8.4p1/sshbuf.h #define SSHBUF_MAX_BIGNUM (16384 / 8) /* Max bignum *bytes* */ #define SSHBUF_MAX_ECPOINT ((528 * 2 / 8) + 1) /* Max EC point *bytes* */ diff -Nur openssh-8.4p1.orig/ssh.c openssh-8.4p1/ssh.c ---- openssh-8.4p1.orig/ssh.c 2021-03-11 18:13:41.147603061 +0100 -+++ openssh-8.4p1/ssh.c 2021-03-11 18:16:31.144747727 +0100 +--- openssh-8.4p1.orig/ssh.c 2021-03-16 19:47:18.035228717 +0100 ++++ openssh-8.4p1/ssh.c 2021-03-17 10:06:41.578239214 +0100 @@ -1084,6 +1084,10 @@ break; case 'T': @@ -2433,23 +2296,19 @@ diff -Nur openssh-8.4p1.orig/ssh.c openssh-8.4p1/ssh.c window >>= 1; packetmax >>= 1; } -@@ -2114,7 +2195,15 @@ - window, packetmax, CHAN_EXTENDED_WRITE, - "client-session", /*nonblock*/0); +@@ -2116,6 +2197,11 @@ -+ if ((options.tcp_rcv_buf_poll > 0) && (!options.hpn_disabled)) { -+ c->dynamic_window = 1; -+ debug("Enabled Dynamic Window Scaling"); -+ } debug3("%s: channel_new: %d", __func__, c->self); + + if (options.tcp_rcv_buf_poll > 0 && !options.hpn_disabled) { + c->dynamic_window = 1; + debug("Enabled Dynamic Window Scaling"); + } - ++ channel_send_open(ssh, c->self); if (!no_shell_flag) -@@ -2130,6 +2219,13 @@ + channel_register_open_confirm(ssh, c->self, +@@ -2130,6 +2216,13 @@ int r, devnull, id = -1; char *cp, *tun_fwd_ifname = NULL; @@ -2464,8 +2323,8 @@ diff -Nur openssh-8.4p1.orig/ssh.c openssh-8.4p1/ssh.c if (!options.control_persist) ssh_init_stdio_forwarding(ssh); diff -Nur openssh-8.4p1.orig/sshconnect2.c openssh-8.4p1/sshconnect2.c ---- openssh-8.4p1.orig/sshconnect2.c 2021-03-11 18:13:41.148603051 +0100 -+++ openssh-8.4p1/sshconnect2.c 2021-03-11 18:16:31.146747705 +0100 +--- openssh-8.4p1.orig/sshconnect2.c 2021-03-16 19:47:18.037228721 +0100 ++++ openssh-8.4p1/sshconnect2.c 2021-03-16 22:30:49.219083791 +0100 @@ -85,6 +85,13 @@ extern Options options; @@ -2531,7 +2390,7 @@ diff -Nur openssh-8.4p1.orig/sshconnect2.c openssh-8.4p1/sshconnect2.c + fprintf(stderr, "NONE cipher switch disabled when a TTY is allocated\n"); + } + } -+ ++ +#ifdef WITH_OPENSSL + if (options.disable_multithreaded == 0) { + /* if we are using aes-ctr there can be issues in either a fork or sandbox @@ -2540,8 +2399,8 @@ diff -Nur openssh-8.4p1.orig/sshconnect2.c openssh-8.4p1/sshconnect2.c + * so we repoint the define to the multithreaded evp. To start the threads we + * then force a rekey + */ -+ const void *cc = ssh_packet_get_send_context(ssh); -+ ++ const void *cc = ssh_packet_get_send_context(ssh); ++ + /* only do this for the ctr cipher. otherwise gcm mode breaks. Don't know why though */ + if (strstr(cipher_ctx_name(cc), "ctr")) { + debug("Single to Multithread CTR cipher swap - client request"); @@ -2556,7 +2415,7 @@ diff -Nur openssh-8.4p1.orig/sshconnect2.c openssh-8.4p1/sshconnect2.c diff -Nur openssh-8.4p1.orig/sshconnect.c openssh-8.4p1/sshconnect.c --- openssh-8.4p1.orig/sshconnect.c 2020-09-27 09:25:01.000000000 +0200 -+++ openssh-8.4p1/sshconnect.c 2021-03-11 18:16:31.145747716 +0100 ++++ openssh-8.4p1/sshconnect.c 2021-03-16 21:57:53.023896961 +0100 @@ -362,6 +362,30 @@ #endif @@ -2576,8 +2435,8 @@ diff -Nur openssh-8.4p1.orig/sshconnect.c openssh-8.4p1/sshconnect.c + + debug("setsockopt Attempting to set SO_RCVBUF to %d", options.tcp_rcv_buf); + if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, buf, sz) >= 0) { -+ getsockopt(sock, SOL_SOCKET, SO_RCVBUF, &socksize, &socksizelen); -+ debug("setsockopt SO_RCVBUF: %.100s %d", strerror(errno), socksize); ++ getsockopt(sock, SOL_SOCKET, SO_RCVBUF, &socksize, &socksizelen); ++ debug("setsockopt SO_RCVBUF: %.100s %d", strerror(errno), socksize); + } + else + error("Couldn't set socket receive buffer to %d: %.100s", @@ -2599,18 +2458,9 @@ diff -Nur openssh-8.4p1.orig/sshconnect.c openssh-8.4p1/sshconnect.c if (options.bind_address == NULL && options.bind_interface == NULL) return sock; diff -Nur openssh-8.4p1.orig/sshd.c openssh-8.4p1/sshd.c ---- openssh-8.4p1.orig/sshd.c 2021-03-11 18:13:41.149603040 +0100 -+++ openssh-8.4p1/sshd.c 2021-03-11 18:16:31.147747694 +0100 -@@ -394,6 +394,8 @@ - sigdie("Timeout before authentication for %s port %d", - ssh_remote_ipaddr(the_active_state), - ssh_remote_port(the_active_state)); -+ -+ - } - - /* -@@ -1133,6 +1135,8 @@ +--- openssh-8.4p1.orig/sshd.c 2021-03-16 19:47:18.037228721 +0100 ++++ openssh-8.4p1/sshd.c 2021-03-16 22:33:24.824413110 +0100 +@@ -1133,6 +1133,8 @@ int ret, listen_sock; struct addrinfo *ai; char ntop[NI_MAXHOST], strport[NI_MAXSERV]; @@ -2619,19 +2469,19 @@ diff -Nur openssh-8.4p1.orig/sshd.c openssh-8.4p1/sshd.c for (ai = la->addrs; ai; ai = ai->ai_next) { if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) -@@ -1178,6 +1182,11 @@ +@@ -1178,6 +1180,11 @@ debug("Bind to port %s on %s.", strport, ntop); + getsockopt(listen_sock, SOL_SOCKET, SO_RCVBUF, -+ &socksize, &socksizelen); ++ &socksize, &socksizelen); + debug("Server TCP RWIN socket size: %d", socksize); + debug("HPN Buffer Size: %d", options.hpn_buffer_size); + /* Bind the socket to the desired port. */ if (bind(listen_sock, ai->ai_addr, ai->ai_addrlen) == -1) { error("Bind to port %s on %s failed: %.200s.", -@@ -1847,6 +1856,19 @@ +@@ -1847,6 +1854,19 @@ /* Fill in default values for those options not explicitly set. */ fill_default_server_options(&options); @@ -2642,16 +2492,16 @@ diff -Nur openssh-8.4p1.orig/sshd.c openssh-8.4p1/sshd.c + + /* only enable the none MAC in context of the none cipher -cjr */ + if (options.nonemac_enabled == 1) { -+ char *old_macs = options.macs; -+ xasprintf(&options.macs, "%s,none", old_macs); -+ free(old_macs); ++ char *old_macs = options.macs; ++ xasprintf(&options.macs, "%s,none", old_macs); ++ free(old_macs); + } + } + /* challenge-response is implemented via keyboard interactive */ if (options.challenge_response_authentication) options.kbd_interactive_authentication = 1; -@@ -2305,6 +2327,9 @@ +@@ -2305,6 +2325,9 @@ rdomain == NULL ? "" : "\""); free(laddr); @@ -2661,7 +2511,7 @@ diff -Nur openssh-8.4p1.orig/sshd.c openssh-8.4p1/sshd.c /* * We don't want to listen forever unless the other side * successfully authenticates itself. So we set up an alarm which is -@@ -2417,6 +2442,25 @@ +@@ -2417,6 +2440,25 @@ /* Try to send all our hostkeys to the client */ notify_hostkeys(ssh); @@ -2674,7 +2524,7 @@ diff -Nur openssh-8.4p1.orig/sshd.c openssh-8.4p1/sshd.c + * then force a rekey + */ + const void *cc = ssh_packet_get_send_context(the_active_state); -+ ++ + /* only rekey if necessary. If we don't do this gcm mode cipher breaks */ + if (strstr(cipher_ctx_name(cc), "ctr")) { + debug("Single to Multithreaded CTR cipher swap - server request"); @@ -2687,7 +2537,7 @@ diff -Nur openssh-8.4p1.orig/sshd.c openssh-8.4p1/sshd.c /* Start session. */ do_authenticated(ssh, authctxt); -@@ -2491,6 +2535,11 @@ +@@ -2491,6 +2533,11 @@ struct kex *kex; int r; @@ -2695,13 +2545,13 @@ diff -Nur openssh-8.4p1.orig/sshd.c openssh-8.4p1/sshd.c + debug("WARNING: None cipher enabled"); + if (options.nonemac_enabled == 1) + debug("WARNING: None MAC enabled"); -+ ++ myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal( options.kex_algorithms); myproposal[PROPOSAL_ENC_ALGS_CTOS] = compat_cipher_proposal( diff -Nur openssh-8.4p1.orig/sshd_config openssh-8.4p1/sshd_config ---- openssh-8.4p1.orig/sshd_config 2021-03-11 18:13:41.158602943 +0100 -+++ openssh-8.4p1/sshd_config 2021-03-11 18:16:31.147747694 +0100 +--- openssh-8.4p1.orig/sshd_config 2021-03-16 19:47:18.038228723 +0100 ++++ openssh-8.4p1/sshd_config 2021-03-16 19:48:09.918338926 +0100 @@ -127,6 +127,22 @@ # override default of no subsystems Subsystem sftp /usr/libexec/sftp-server @@ -2726,13 +2576,13 @@ diff -Nur openssh-8.4p1.orig/sshd_config openssh-8.4p1/sshd_config #Match User anoncvs # X11Forwarding no diff -Nur openssh-8.4p1.orig/version.h openssh-8.4p1/version.h ---- openssh-8.4p1.orig/version.h 2021-03-11 18:13:41.150603029 +0100 -+++ openssh-8.4p1/version.h 2021-03-11 18:22:57.603714426 +0100 +--- openssh-8.4p1.orig/version.h 2021-03-16 19:47:18.039228725 +0100 ++++ openssh-8.4p1/version.h 2021-03-16 20:55:06.060913438 +0100 @@ -16,5 +16,6 @@ #define SSH_PORTABLE "p1" #define GSI_PORTABLE "c-GSI" -+#define SSH_HPN "-hpn15v1" ++#define SSH_HPN "-hpn15v1" #define SSH_RELEASE SSH_VERSION SSH_PORTABLE GSI_PORTABLE \ - GSI_VERSION KRB5_VERSION + GSI_VERSION SSH_HPN KRB5_VERSION From 6c50475edde7a3b6cc9e418ad504b6ae54ff9f65 Mon Sep 17 00:00:00 2001 From: Mattias Ellert Date: Tue, 30 Mar 2021 10:02:52 +0200 Subject: [PATCH 4/7] Disable MTAES --- gsi-openssh.spec | 5 ++++- openssh-8.4p1-hpn-15.1-modified.patch | 10 ++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/gsi-openssh.spec b/gsi-openssh.spec index f25783b..12977b0 100644 --- a/gsi-openssh.spec +++ b/gsi-openssh.spec @@ -28,7 +28,7 @@ %global libedit 1 %global openssh_ver 8.4p1 -%global openssh_rel 6 +%global openssh_rel 7 Summary: An implementation of the SSH protocol with GSI authentication Name: gsi-openssh @@ -510,6 +510,9 @@ getent passwd sshd >/dev/null || \ %attr(0644,root,root) %{_tmpfilesdir}/gsissh.conf %changelog +* Tue Mar 30 2021 Mattias Ellert - 8.4p1-7 +- Disable MTAES + * Tue Mar 16 2021 Mattias Ellert - 8.4p1-6 - Fix issue with read-only ssh buffer during gssapi key exchange - Clean up HPN patch diff --git a/openssh-8.4p1-hpn-15.1-modified.patch b/openssh-8.4p1-hpn-15.1-modified.patch index 33a1475..c7eec26 100644 --- a/openssh-8.4p1-hpn-15.1-modified.patch +++ b/openssh-8.4p1-hpn-15.1-modified.patch @@ -2551,8 +2551,8 @@ diff -Nur openssh-8.4p1.orig/sshd.c openssh-8.4p1/sshd.c myproposal[PROPOSAL_ENC_ALGS_CTOS] = compat_cipher_proposal( diff -Nur openssh-8.4p1.orig/sshd_config openssh-8.4p1/sshd_config --- openssh-8.4p1.orig/sshd_config 2021-03-16 19:47:18.038228723 +0100 -+++ openssh-8.4p1/sshd_config 2021-03-16 19:48:09.918338926 +0100 -@@ -127,6 +127,22 @@ ++++ openssh-8.4p1/sshd_config 2021-03-30 09:54:45.869615770 +0200 +@@ -127,6 +127,28 @@ # override default of no subsystems Subsystem sftp /usr/libexec/sftp-server @@ -2571,6 +2571,12 @@ diff -Nur openssh-8.4p1.orig/sshd_config openssh-8.4p1/sshd_config + +# allow the use of the none MAC +#NoneMacEnabled no ++ ++# Disable MT-AES-CTR cipher on server ++# * needed for GSI-OpenSSH 7.4p1 because it's broken on the server side there ++# * useful for modern processors with AES-NI instructions making the stock ++# AES-CTR cipher faster than the MT-AES-CTR cipher ++DisableMTAES yes + # Example of overriding settings on a per-user basis #Match User anoncvs From 651d6b5d57972f5ce72b2d85f117717e2aeca305 Mon Sep 17 00:00:00 2001 From: Mattias Ellert Date: Tue, 25 May 2021 09:56:34 +0200 Subject: [PATCH 5/7] Based on openssh-8.4p1-5.fc33 --- gsi-openssh.spec | 5 ++++- openssh-7.8p1-role-mls.patch | 26 +++++++++++++------------- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/gsi-openssh.spec b/gsi-openssh.spec index 12977b0..b8089e6 100644 --- a/gsi-openssh.spec +++ b/gsi-openssh.spec @@ -28,7 +28,7 @@ %global libedit 1 %global openssh_ver 8.4p1 -%global openssh_rel 7 +%global openssh_rel 8 Summary: An implementation of the SSH protocol with GSI authentication Name: gsi-openssh @@ -510,6 +510,9 @@ getent passwd sshd >/dev/null || \ %attr(0644,root,root) %{_tmpfilesdir}/gsissh.conf %changelog +* Tue May 25 2021 Mattias Ellert - 8.4p1-8 +- Based on openssh-8.4p1-5.fc33 + * Tue Mar 30 2021 Mattias Ellert - 8.4p1-7 - Disable MTAES diff --git a/openssh-7.8p1-role-mls.patch b/openssh-7.8p1-role-mls.patch index add4727..ba5d23f 100644 --- a/openssh-7.8p1-role-mls.patch +++ b/openssh-7.8p1-role-mls.patch @@ -179,10 +179,10 @@ diff -up openssh/misc.c.role-mls openssh/misc.c } return NULL; } -diff -up openssh/monitor.c.role-mls openssh/monitor.c ---- openssh/monitor.c.role-mls 2018-08-20 07:57:29.000000000 +0200 -+++ openssh/monitor.c 2018-08-22 11:19:56.006844867 +0200 -@@ -115,6 +115,9 @@ int mm_answer_sign(int, struct sshbuf *) +diff -up openssh-8.6p1/monitor.c.role-mls openssh-8.6p1/monitor.c +--- openssh-8.6p1/monitor.c.role-mls 2021-04-16 05:55:25.000000000 +0200 ++++ openssh-8.6p1/monitor.c 2021-05-21 14:21:56.719414087 +0200 +@@ -117,6 +117,9 @@ int mm_answer_sign(struct ssh *, int, st int mm_answer_pwnamallow(struct ssh *, int, struct sshbuf *); int mm_answer_auth2_read_banner(struct ssh *, int, struct sshbuf *); int mm_answer_authserv(struct ssh *, int, struct sshbuf *); @@ -192,7 +192,7 @@ diff -up openssh/monitor.c.role-mls openssh/monitor.c int mm_answer_authpassword(struct ssh *, int, struct sshbuf *); int mm_answer_bsdauthquery(struct ssh *, int, struct sshbuf *); int mm_answer_bsdauthrespond(struct ssh *, int, struct sshbuf *); -@@ -189,6 +192,9 @@ struct mon_table mon_dispatch_proto20[] +@@ -195,6 +198,9 @@ struct mon_table mon_dispatch_proto20[] {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign}, {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow}, {MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv}, @@ -202,7 +202,7 @@ diff -up openssh/monitor.c.role-mls openssh/monitor.c {MONITOR_REQ_AUTH2_READ_BANNER, MON_ONCE, mm_answer_auth2_read_banner}, {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword}, #ifdef USE_PAM -@@ -796,6 +802,9 @@ mm_answer_pwnamallow(int sock, struct ss +@@ -803,6 +809,9 @@ mm_answer_pwnamallow(struct ssh *ssh, in /* Allow service/style information on the auth context */ monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1); @@ -212,7 +212,7 @@ diff -up openssh/monitor.c.role-mls openssh/monitor.c monitor_permit(mon_dispatch, MONITOR_REQ_AUTH2_READ_BANNER, 1); #ifdef USE_PAM -@@ -842,6 +851,26 @@ mm_answer_authserv(int sock, struct sshb +@@ -877,6 +886,26 @@ key_base_type_match(const char *method, return found; } @@ -239,7 +239,7 @@ diff -up openssh/monitor.c.role-mls openssh/monitor.c int mm_answer_authpassword(struct ssh *ssh, int sock, struct sshbuf *m) { -@@ -1218,7 +1247,7 @@ monitor_valid_userblob(u_char *data, u_i +@@ -1251,7 +1280,7 @@ monitor_valid_userblob(struct ssh *ssh, { struct sshbuf *b; const u_char *p; @@ -248,7 +248,7 @@ diff -up openssh/monitor.c.role-mls openssh/monitor.c size_t len; u_char type; int r, fail = 0; -@@ -1251,6 +1280,8 @@ monitor_valid_userblob(u_char *data, u_i +@@ -1282,6 +1311,8 @@ monitor_valid_userblob(struct ssh *ssh, fail++; if ((r = sshbuf_get_cstring(b, &cp, NULL)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); @@ -257,7 +257,7 @@ diff -up openssh/monitor.c.role-mls openssh/monitor.c xasprintf(&userstyle, "%s%s%s", authctxt->user, authctxt->style ? ":" : "", authctxt->style ? authctxt->style : ""); -@@ -1286,7 +1317,7 @@ monitor_valid_hostbasedblob(u_char *data +@@ -1317,7 +1348,7 @@ monitor_valid_hostbasedblob(const u_char { struct sshbuf *b; const u_char *p; @@ -266,11 +266,11 @@ diff -up openssh/monitor.c.role-mls openssh/monitor.c size_t len; int r, fail = 0; u_char type; -@@ -1308,6 +1339,8 @@ monitor_valid_hostbasedblob(u_char *data +@@ -1338,6 +1370,8 @@ monitor_valid_hostbasedblob(const u_char fail++; if ((r = sshbuf_get_cstring(b, &cp, NULL)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); -+ if ((s = strchr(p, '/')) != NULL) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); ++ if ((s = strchr(cp, '/')) != NULL) + *s = '\0'; xasprintf(&userstyle, "%s%s%s", authctxt->user, authctxt->style ? ":" : "", From 42f77e22d650bcf19bc9832ea8a427d6e6b7a8a3 Mon Sep 17 00:00:00 2001 From: Mattias Ellert Date: Mon, 21 Jun 2021 20:09:32 +0200 Subject: [PATCH 6/7] Based on openssh-8.4p1-7.fc33 --- gsi-openssh.spec | 10 ++++++++-- openssh-8.4p1-cve-2021-28041.patch | 11 +++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 openssh-8.4p1-cve-2021-28041.patch diff --git a/gsi-openssh.spec b/gsi-openssh.spec index b8089e6..30cc552 100644 --- a/gsi-openssh.spec +++ b/gsi-openssh.spec @@ -28,7 +28,7 @@ %global libedit 1 %global openssh_ver 8.4p1 -%global openssh_rel 8 +%global openssh_rel 9 Summary: An implementation of the SSH protocol with GSI authentication Name: gsi-openssh @@ -158,6 +158,8 @@ Patch967: openssh-8.4p1-ssh-copy-id.patch Patch968: openssh-8.4p1-sandbox-seccomp.patch # https://bugzilla.mindrot.org/show_bug.cgi?id=3213 Patch969: openssh-8.4p1-debian-compat.patch +# https://ftp.openbsd.org/pub/OpenBSD/patches/6.8/common/015_sshagent.patch.sig +Patch970: openssh-8.4p1-cve-2021-28041.patch # Fix issue with read-only ssh buffer during gssapi key exchange (#1938224) # https://github.com/openssh-gsskex/openssh-gsskex/pull/19 @@ -309,6 +311,7 @@ gpgv2 --quiet --keyring %{SOURCE3} %{SOURCE1} %{SOURCE0} %patch967 -p1 -b .ssh-copy-id %patch968 -p1 -b .seccomp %patch969 -p0 -b .debian +%patch970 -p1 -b .cve-2021-28041 %patch200 -p1 -b .audit %patch201 -p1 -b .audit-race @@ -510,8 +513,11 @@ getent passwd sshd >/dev/null || \ %attr(0644,root,root) %{_tmpfilesdir}/gsissh.conf %changelog +* Mon Jun 21 2021 Mattias Ellert - 8.4p1-9 +- Based on openssh-8.4p1-7.fc33 + * Tue May 25 2021 Mattias Ellert - 8.4p1-8 -- Based on openssh-8.4p1-5.fc33 +- Based on openssh-8.4p1-6.fc33 * Tue Mar 30 2021 Mattias Ellert - 8.4p1-7 - Disable MTAES diff --git a/openssh-8.4p1-cve-2021-28041.patch b/openssh-8.4p1-cve-2021-28041.patch new file mode 100644 index 0000000..6dc3000 --- /dev/null +++ b/openssh-8.4p1-cve-2021-28041.patch @@ -0,0 +1,11 @@ +diff -up openssh-8.4p1/ssh-agent.c.cve-2021-28041 openssh-8.4p1/ssh-agent.c +--- openssh-8.4p1/ssh-agent.c.cve-2021-28041 2021-06-17 13:15:58.691479334 +0200 ++++ openssh-8.4p1/ssh-agent.c 2021-06-17 13:17:16.573118348 +0200 +@@ -581,6 +581,7 @@ process_add_identity(SocketEntry *e) + goto err; + } + free(ext_name); ++ ext_name = NULL; + break; + default: + error("%s: Unknown constraint %d", __func__, ctype); From 76f997a6d6d06ad4d7d7ef2537b6337e51b54254 Mon Sep 17 00:00:00 2001 From: Mattias Ellert Date: Sun, 24 Oct 2021 06:24:47 +0200 Subject: [PATCH 7/7] Based on openssh-8.4p1-8.fc33 --- gsi-openssh.spec | 8 ++++++- openssh-8.7p1-upstream-cve-2021-41617.patch | 25 +++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 openssh-8.7p1-upstream-cve-2021-41617.patch diff --git a/gsi-openssh.spec b/gsi-openssh.spec index 30cc552..6c2d38d 100644 --- a/gsi-openssh.spec +++ b/gsi-openssh.spec @@ -28,7 +28,7 @@ %global libedit 1 %global openssh_ver 8.4p1 -%global openssh_rel 9 +%global openssh_rel 10 Summary: An implementation of the SSH protocol with GSI authentication Name: gsi-openssh @@ -160,6 +160,8 @@ Patch968: openssh-8.4p1-sandbox-seccomp.patch Patch969: openssh-8.4p1-debian-compat.patch # https://ftp.openbsd.org/pub/OpenBSD/patches/6.8/common/015_sshagent.patch.sig Patch970: openssh-8.4p1-cve-2021-28041.patch +# CVE-2021-41617 +Patch978: openssh-8.7p1-upstream-cve-2021-41617.patch # Fix issue with read-only ssh buffer during gssapi key exchange (#1938224) # https://github.com/openssh-gsskex/openssh-gsskex/pull/19 @@ -312,6 +314,7 @@ gpgv2 --quiet --keyring %{SOURCE3} %{SOURCE1} %{SOURCE0} %patch968 -p1 -b .seccomp %patch969 -p0 -b .debian %patch970 -p1 -b .cve-2021-28041 +%patch978 -p1 -b .cve-2021-41617 %patch200 -p1 -b .audit %patch201 -p1 -b .audit-race @@ -513,6 +516,9 @@ getent passwd sshd >/dev/null || \ %attr(0644,root,root) %{_tmpfilesdir}/gsissh.conf %changelog +* Sat Oct 23 2021 Mattias Ellert - 8.4p1-10 +- Based on openssh-8.4p1-8.fc33 + * Mon Jun 21 2021 Mattias Ellert - 8.4p1-9 - Based on openssh-8.4p1-7.fc33 diff --git a/openssh-8.7p1-upstream-cve-2021-41617.patch b/openssh-8.7p1-upstream-cve-2021-41617.patch new file mode 100644 index 0000000..ec9b839 --- /dev/null +++ b/openssh-8.7p1-upstream-cve-2021-41617.patch @@ -0,0 +1,25 @@ +diff --git a/auth.c b/auth.c +index b8d1040d..0134d694 100644 +--- a/auth.c ++++ b/auth.c +@@ -56,6 +56,7 @@ + # include + #endif + #include ++#include + #ifdef HAVE_LOGIN_H + #include + #endif +@@ -2695,6 +2696,12 @@ subprocess(const char *tag, const char *command, + } + closefrom(STDERR_FILENO + 1); + ++ if (geteuid() == 0 && ++ initgroups(pw->pw_name, pw->pw_gid) == -1) { ++ error("%s: initgroups(%s, %u): %s", tag, ++ pw->pw_name, (u_int)pw->pw_gid, strerror(errno)); ++ _exit(1); ++ } + /* Don't use permanently_set_uid() here to avoid fatal() */ + if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) == -1) { + error("%s: setresgid %u: %s", tag, (u_int)pw->pw_gid,