From ea8fd89c06b78ef2ac0cc651ea9d74dabab25d11 Mon Sep 17 00:00:00 2001 From: Mattias Ellert Date: Fri, 31 Dec 2021 08:33:58 +0100 Subject: [PATCH 01/11] Based on openssh-8.7p1-4.el9 Drop patch openssh-8.0p1-sshbuf-readonly.patch (now included in openssh-8.0p1-gssapi-keyex.patch) --- gsi-openssh.spec | 17 +- openssh-6.6.1p1-log-in-chroot.patch | 28 +-- openssh-6.7p1-coverity.patch | 39 ++-- openssh-7.6p1-audit.patch | 90 ++++---- openssh-7.7p1-fips.patch | 50 ++--- openssh-7.7p1-gssapi-new-unique.patch | 38 ++-- openssh-7.7p1-redhat.patch | 16 +- openssh-8.0p1-gssapi-keyex.patch | 70 +++--- openssh-8.0p1-pkcs11-uri.patch | 224 ++++++++++---------- openssh-8.0p1-sshbuf-readonly.patch | 152 ------------- openssh-8.7p1-upstream-cve-2021-41617.patch | 6 - 11 files changed, 292 insertions(+), 438 deletions(-) delete mode 100644 openssh-8.0p1-sshbuf-readonly.patch diff --git a/gsi-openssh.spec b/gsi-openssh.spec index 7e7ccf0..183be66 100644 --- a/gsi-openssh.spec +++ b/gsi-openssh.spec @@ -28,7 +28,7 @@ %global libedit 1 %global openssh_ver 8.7p1 -%global openssh_rel 2 +%global openssh_rel 3 Summary: An implementation of the SSH protocol with GSI authentication Name: gsi-openssh @@ -145,7 +145,7 @@ Patch964: openssh-8.0p1-openssl-kdf.patch Patch965: openssh-8.2p1-visibility.patch # Do not break X11 without IPv6 Patch966: openssh-8.2p1-x11-without-ipv6.patch -# https://bugzilla.mindrot.org/show_bug.cgi?id=3213 +# ssh-keygen printing fingerprint issue with Windows keys (#1901518) Patch974: openssh-8.0p1-keygen-strip-doseol.patch # sshd provides PAM an incorrect error code (#1879503) Patch975: openssh-8.0p1-preserve-pam-errors.patch @@ -156,9 +156,6 @@ Patch977: openssh-8.7p1-scp-kill-switch.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 -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.7p1-gsissh.patch @@ -180,7 +177,6 @@ BuildRequires: systemd-rpm-macros BuildRequires: gcc make BuildRequires: p11-kit-devel BuildRequires: libfido2-devel -Recommends: p11-kit %if %{kerberos5} BuildRequires: krb5-devel @@ -313,7 +309,6 @@ gpgv2 --quiet --keyring %{SOURCE3} %{SOURCE1} %{SOURCE0} %patch100 -p1 -b .coverity -%patch97 -p1 -b .sshbuf-ro %patch98 -p1 -b .gsi %patch99 -p1 -b .hpn @@ -327,8 +322,7 @@ cp -p %{SOURCE99} . autoreconf %build -%set_build_flags -CFLAGS="$CFLAGS"; export CFLAGS +CFLAGS="$RPM_OPT_FLAGS"; export CFLAGS %if %{pie} %ifarch s390 s390x sparc sparcv9 sparc64 CFLAGS="$CFLAGS -fPIC" @@ -503,6 +497,11 @@ getent passwd sshd >/dev/null || \ %attr(0644,root,root) %{_unitdir}/gsisshd-keygen.target %changelog +* Fri Dec 31 2021 Mattias Ellert - 8.7p1-3 +- Based on openssh-8.7p1-4.el9 +- Drop patch openssh-8.0p1-sshbuf-readonly.patch (now included in + openssh-8.0p1-gssapi-keyex.patch) + * Sun Oct 24 2021 Mattias Ellert - 8.7p1-2 - Based on openssh-8.7p1-3.fc36 diff --git a/openssh-6.6.1p1-log-in-chroot.patch b/openssh-6.6.1p1-log-in-chroot.patch index 426c172..bf3293f 100644 --- a/openssh-6.6.1p1-log-in-chroot.patch +++ b/openssh-6.6.1p1-log-in-chroot.patch @@ -1,6 +1,6 @@ diff -up openssh-8.6p1/log.c.log-in-chroot openssh-8.6p1/log.c --- openssh-8.6p1/log.c.log-in-chroot 2021-04-16 05:55:25.000000000 +0200 -+++ openssh-8.6p1/log.c 2021-04-19 14:43:08.544843434 +0200 ++++ openssh-8.6p1/log.c 2021-05-06 11:32:25.179006811 +0200 @@ -194,6 +194,11 @@ void log_init(const char *av0, LogLevel level, SyslogFacility facility, int on_stderr) @@ -27,8 +27,8 @@ diff -up openssh-8.6p1/log.c.log-in-chroot openssh-8.6p1/log.c log_on_stderr = on_stderr; if (on_stderr) diff -up openssh-8.6p1/log.h.log-in-chroot openssh-8.6p1/log.h ---- openssh-8.6p1/log.h.log-in-chroot 2021-04-19 14:43:08.544843434 +0200 -+++ openssh-8.6p1/log.h 2021-04-19 14:56:46.931042176 +0200 +--- openssh-8.6p1/log.h.log-in-chroot 2021-05-06 11:32:25.179006811 +0200 ++++ openssh-8.6p1/log.h 2021-05-06 11:34:22.349925757 +0200 @@ -52,6 +52,7 @@ typedef enum { typedef void (log_handler_fn)(LogLevel, int, const char *, void *); @@ -38,8 +38,8 @@ diff -up openssh-8.6p1/log.h.log-in-chroot openssh-8.6p1/log.h int log_change_level(LogLevel); int log_is_on_stderr(void); diff -up openssh-8.6p1/monitor.c.log-in-chroot openssh-8.6p1/monitor.c ---- openssh-8.6p1/monitor.c.log-in-chroot 2021-04-19 14:43:08.526843298 +0200 -+++ openssh-8.6p1/monitor.c 2021-04-19 14:55:25.286424043 +0200 +--- openssh-8.6p1/monitor.c.log-in-chroot 2021-05-06 11:32:25.153006607 +0200 ++++ openssh-8.6p1/monitor.c 2021-05-06 11:33:37.671575348 +0200 @@ -297,6 +297,8 @@ monitor_child_preauth(struct ssh *ssh, s close(pmonitor->m_log_sendfd); pmonitor->m_log_sendfd = pmonitor->m_recvfd = -1; @@ -99,8 +99,8 @@ diff -up openssh-8.6p1/monitor.c.log-in-chroot openssh-8.6p1/monitor.c #ifdef GSSAPI diff -up openssh-8.6p1/monitor.h.log-in-chroot openssh-8.6p1/monitor.h ---- openssh-8.6p1/monitor.h.log-in-chroot 2021-04-19 14:43:08.527843305 +0200 -+++ openssh-8.6p1/monitor.h 2021-04-19 14:43:08.545843441 +0200 +--- openssh-8.6p1/monitor.h.log-in-chroot 2021-05-06 11:32:25.153006607 +0200 ++++ openssh-8.6p1/monitor.h 2021-05-06 11:32:25.180006819 +0200 @@ -80,10 +80,11 @@ struct monitor { int m_log_sendfd; struct kex **m_pkex; @@ -115,8 +115,8 @@ diff -up openssh-8.6p1/monitor.h.log-in-chroot openssh-8.6p1/monitor.h struct Authctxt; void monitor_child_preauth(struct ssh *, struct monitor *); diff -up openssh-8.6p1/session.c.log-in-chroot openssh-8.6p1/session.c ---- openssh-8.6p1/session.c.log-in-chroot 2021-04-19 14:43:08.534843358 +0200 -+++ openssh-8.6p1/session.c 2021-04-19 14:43:08.545843441 +0200 +--- openssh-8.6p1/session.c.log-in-chroot 2021-05-06 11:32:25.166006709 +0200 ++++ openssh-8.6p1/session.c 2021-05-06 11:32:25.181006827 +0200 @@ -160,6 +160,7 @@ login_cap_t *lc; static int is_child = 0; @@ -189,7 +189,7 @@ diff -up openssh-8.6p1/session.c.log-in-chroot openssh-8.6p1/session.c /* Get the last component of the shell name. */ diff -up openssh-8.6p1/sftp.h.log-in-chroot openssh-8.6p1/sftp.h --- openssh-8.6p1/sftp.h.log-in-chroot 2021-04-16 05:55:25.000000000 +0200 -+++ openssh-8.6p1/sftp.h 2021-04-19 14:43:08.545843441 +0200 ++++ openssh-8.6p1/sftp.h 2021-05-06 11:32:25.181006827 +0200 @@ -97,5 +97,5 @@ struct passwd; @@ -199,7 +199,7 @@ diff -up openssh-8.6p1/sftp.h.log-in-chroot openssh-8.6p1/sftp.h void sftp_server_cleanup_exit(int) __attribute__((noreturn)); diff -up openssh-8.6p1/sftp-server.c.log-in-chroot openssh-8.6p1/sftp-server.c --- openssh-8.6p1/sftp-server.c.log-in-chroot 2021-04-16 05:55:25.000000000 +0200 -+++ openssh-8.6p1/sftp-server.c 2021-04-19 14:43:08.545843441 +0200 ++++ openssh-8.6p1/sftp-server.c 2021-05-06 11:32:25.181006827 +0200 @@ -1644,7 +1644,7 @@ sftp_server_usage(void) } @@ -229,7 +229,7 @@ diff -up openssh-8.6p1/sftp-server.c.log-in-chroot openssh-8.6p1/sftp-server.c * On platforms where we can, avoid making /proc/self/{mem,maps} diff -up openssh-8.6p1/sftp-server-main.c.log-in-chroot openssh-8.6p1/sftp-server-main.c --- openssh-8.6p1/sftp-server-main.c.log-in-chroot 2021-04-16 05:55:25.000000000 +0200 -+++ openssh-8.6p1/sftp-server-main.c 2021-04-19 14:43:08.545843441 +0200 ++++ openssh-8.6p1/sftp-server-main.c 2021-05-06 11:32:25.181006827 +0200 @@ -50,5 +50,5 @@ main(int argc, char **argv) return 1; } @@ -238,8 +238,8 @@ diff -up openssh-8.6p1/sftp-server-main.c.log-in-chroot openssh-8.6p1/sftp-serve + return (sftp_server_main(argc, argv, user_pw, 0)); } diff -up openssh-8.6p1/sshd.c.log-in-chroot openssh-8.6p1/sshd.c ---- openssh-8.6p1/sshd.c.log-in-chroot 2021-04-19 14:43:08.543843426 +0200 -+++ openssh-8.6p1/sshd.c 2021-04-19 14:43:08.545843441 +0200 +--- openssh-8.6p1/sshd.c.log-in-chroot 2021-05-06 11:32:25.177006795 +0200 ++++ openssh-8.6p1/sshd.c 2021-05-06 11:32:25.182006834 +0200 @@ -559,7 +559,7 @@ privsep_postauth(struct ssh *ssh, Authct } diff --git a/openssh-6.7p1-coverity.patch b/openssh-6.7p1-coverity.patch index 930de69..6852384 100644 --- a/openssh-6.7p1-coverity.patch +++ b/openssh-6.7p1-coverity.patch @@ -142,21 +142,6 @@ diff -up openssh-8.5p1/gss-genr.c.coverity openssh-8.5p1/gss-genr.c for ((p = strsep(&cp, ",")); p && *p != '\0'; (p = strsep(&cp, ","))) { if (sshbuf_len(buf) != 0 && -diff -up openssh-8.5p1/kexgssc.c.coverity openssh-8.5p1/kexgssc.c ---- openssh-8.5p1/kexgssc.c.coverity 2021-03-24 12:03:33.711967665 +0100 -+++ openssh-8.5p1/kexgssc.c 2021-03-24 12:03:33.783968166 +0100 -@@ -98,8 +98,10 @@ kexgss_client(struct ssh *ssh) - default: - fatal_f("Unexpected KEX type %d", kex->kex_type); - } -- if (r != 0) -+ if (r != 0) { -+ ssh_gssapi_delete_ctx(&ctxt); - return r; -+ } - - token_ptr = GSS_C_NO_BUFFER; - diff -up openssh-8.5p1/krl.c.coverity openssh-8.5p1/krl.c --- openssh-8.5p1/krl.c.coverity 2021-03-02 11:31:47.000000000 +0100 +++ openssh-8.5p1/krl.c 2021-03-24 12:03:33.783968166 +0100 @@ -436,6 +421,30 @@ diff -up openssh-7.4p1/sftp.c.coverity openssh-7.4p1/sftp.c continue; } lname = ls_file(fname, g.gl_statv[i], 1, +diff --git a/sftp-client.c b/sftp-client.c +index 9de9afa20f..ea98d9f8d0 100644 +--- a/sftp-client.c ++++ b/sftp-client.c +@@ -2195,6 +2195,7 @@ handle_dest_replies(struct sftp_conn *to, const char *to_path, int synchronous, + (*nreqsp)--; + } + debug3_f("done: %u outstanding replies", *nreqsp); ++ sshbuf_free(msg); + } + + int +diff --git a/sftp-server.c b/sftp-server.c +index 18d1949112..6380c4dd23 100644 +--- a/sftp-server.c ++++ b/sftp-server.c +@@ -1553,6 +1553,7 @@ process_extended_expand(u_int32_t id) + npath = xstrdup(path + 2); + free(path); + xasprintf(&path, "%s/%s", cwd, npath); ++ free(npath); + } else { + /* ~user expansions */ + if (tilde_expand(path, pw->pw_uid, &npath) != 0) { diff -up openssh-8.5p1/sk-usbhid.c.coverity openssh-8.5p1/sk-usbhid.c --- openssh-8.5p1/sk-usbhid.c.coverity 2021-03-02 11:31:47.000000000 +0100 +++ openssh-8.5p1/sk-usbhid.c 2021-03-24 12:03:33.786968187 +0100 diff --git a/openssh-7.6p1-audit.patch b/openssh-7.6p1-audit.patch index 4473518..fa40053 100644 --- a/openssh-7.6p1-audit.patch +++ b/openssh-7.6p1-audit.patch @@ -1,6 +1,6 @@ diff -up openssh-8.6p1/audit-bsm.c.audit openssh-8.6p1/audit-bsm.c --- openssh-8.6p1/audit-bsm.c.audit 2021-04-16 05:55:25.000000000 +0200 -+++ openssh-8.6p1/audit-bsm.c 2021-04-19 16:47:35.753062106 +0200 ++++ openssh-8.6p1/audit-bsm.c 2021-05-06 12:05:27.376464524 +0200 @@ -373,13 +373,26 @@ audit_connection_from(const char *host, #endif } @@ -73,7 +73,7 @@ diff -up openssh-8.6p1/audit-bsm.c.audit openssh-8.6p1/audit-bsm.c #endif /* BSM */ diff -up openssh-8.6p1/audit.c.audit openssh-8.6p1/audit.c --- openssh-8.6p1/audit.c.audit 2021-04-16 05:55:25.000000000 +0200 -+++ openssh-8.6p1/audit.c 2021-04-19 16:47:35.753062106 +0200 ++++ openssh-8.6p1/audit.c 2021-05-06 12:05:27.376464524 +0200 @@ -34,6 +34,12 @@ #include "log.h" #include "hostfile.h" @@ -253,7 +253,7 @@ diff -up openssh-8.6p1/audit.c.audit openssh-8.6p1/audit.c #endif /* SSH_AUDIT_EVENTS */ diff -up openssh-8.6p1/audit.h.audit openssh-8.6p1/audit.h --- openssh-8.6p1/audit.h.audit 2021-04-16 05:55:25.000000000 +0200 -+++ openssh-8.6p1/audit.h 2021-04-19 16:47:35.753062106 +0200 ++++ openssh-8.6p1/audit.h 2021-05-06 12:05:27.376464524 +0200 @@ -26,6 +26,7 @@ # define _SSH_AUDIT_H @@ -298,7 +298,7 @@ diff -up openssh-8.6p1/audit.h.audit openssh-8.6p1/audit.h #endif /* _SSH_AUDIT_H */ diff -up openssh-8.6p1/audit-linux.c.audit openssh-8.6p1/audit-linux.c --- openssh-8.6p1/audit-linux.c.audit 2021-04-16 05:55:25.000000000 +0200 -+++ openssh-8.6p1/audit-linux.c 2021-04-19 16:47:35.753062106 +0200 ++++ openssh-8.6p1/audit-linux.c 2021-05-06 12:05:27.377464532 +0200 @@ -33,27 +33,40 @@ #include "log.h" @@ -670,8 +670,8 @@ diff -up openssh-8.6p1/audit-linux.c.audit openssh-8.6p1/audit-linux.c +} #endif /* USE_LINUX_AUDIT */ diff -up openssh-8.6p1/auditstub.c.audit openssh-8.6p1/auditstub.c ---- openssh-8.6p1/auditstub.c.audit 2021-04-19 16:47:35.754062114 +0200 -+++ openssh-8.6p1/auditstub.c 2021-04-19 16:47:35.754062114 +0200 +--- openssh-8.6p1/auditstub.c.audit 2021-05-06 12:05:27.377464532 +0200 ++++ openssh-8.6p1/auditstub.c 2021-05-06 12:05:27.377464532 +0200 @@ -0,0 +1,52 @@ +/* $Id: auditstub.c,v 1.1 jfch Exp $ */ + @@ -726,8 +726,8 @@ diff -up openssh-8.6p1/auditstub.c.audit openssh-8.6p1/auditstub.c +{ +} diff -up openssh-8.6p1/auth2.c.audit openssh-8.6p1/auth2.c ---- openssh-8.6p1/auth2.c.audit 2021-04-19 16:47:35.682061561 +0200 -+++ openssh-8.6p1/auth2.c 2021-04-19 16:47:35.754062114 +0200 +--- openssh-8.6p1/auth2.c.audit 2021-05-06 12:05:27.305463975 +0200 ++++ openssh-8.6p1/auth2.c 2021-05-06 12:05:27.377464532 +0200 @@ -298,9 +298,6 @@ input_userauth_request(int type, u_int32 } else { /* Invalid user, fake password information */ @@ -739,8 +739,8 @@ diff -up openssh-8.6p1/auth2.c.audit openssh-8.6p1/auth2.c #ifdef USE_PAM if (options.use_pam) diff -up openssh-8.6p1/auth2-hostbased.c.audit openssh-8.6p1/auth2-hostbased.c ---- openssh-8.6p1/auth2-hostbased.c.audit 2021-04-19 16:47:35.656061361 +0200 -+++ openssh-8.6p1/auth2-hostbased.c 2021-04-19 16:47:35.754062114 +0200 +--- openssh-8.6p1/auth2-hostbased.c.audit 2021-05-06 12:05:27.283463805 +0200 ++++ openssh-8.6p1/auth2-hostbased.c 2021-05-06 12:05:27.377464532 +0200 @@ -158,7 +158,7 @@ userauth_hostbased(struct ssh *ssh) authenticated = 0; if (PRIVSEP(hostbased_key_allowed(ssh, authctxt->pw, cuser, @@ -772,8 +772,8 @@ diff -up openssh-8.6p1/auth2-hostbased.c.audit openssh-8.6p1/auth2-hostbased.c int hostbased_key_allowed(struct ssh *ssh, struct passwd *pw, diff -up openssh-8.6p1/auth2-pubkey.c.audit openssh-8.6p1/auth2-pubkey.c ---- openssh-8.6p1/auth2-pubkey.c.audit 2021-04-19 16:47:35.726061899 +0200 -+++ openssh-8.6p1/auth2-pubkey.c 2021-04-19 16:47:35.754062114 +0200 +--- openssh-8.6p1/auth2-pubkey.c.audit 2021-05-06 12:05:27.344464277 +0200 ++++ openssh-8.6p1/auth2-pubkey.c 2021-05-06 12:05:27.378464540 +0200 @@ -213,7 +213,7 @@ userauth_pubkey(struct ssh *ssh) /* test for correct signature */ authenticated = 0; @@ -805,8 +805,8 @@ diff -up openssh-8.6p1/auth2-pubkey.c.audit openssh-8.6p1/auth2-pubkey.c match_principals_option(const char *principal_list, struct sshkey_cert *cert) { diff -up openssh-8.6p1/auth.c.audit openssh-8.6p1/auth.c ---- openssh-8.6p1/auth.c.audit 2021-04-19 16:47:35.681061553 +0200 -+++ openssh-8.6p1/auth.c 2021-04-19 16:47:35.754062114 +0200 +--- openssh-8.6p1/auth.c.audit 2021-05-06 12:05:27.304463967 +0200 ++++ openssh-8.6p1/auth.c 2021-05-06 12:05:27.378464540 +0200 @@ -597,9 +597,6 @@ getpwnamallow(struct ssh *ssh, const cha record_failed_login(ssh, user, auth_get_canonical_hostname(ssh, options.use_dns), "ssh"); @@ -818,8 +818,8 @@ diff -up openssh-8.6p1/auth.c.audit openssh-8.6p1/auth.c } if (!allowed_user(ssh, pw)) diff -up openssh-8.6p1/auth.h.audit openssh-8.6p1/auth.h ---- openssh-8.6p1/auth.h.audit 2021-04-19 16:47:35.697061676 +0200 -+++ openssh-8.6p1/auth.h 2021-04-19 16:47:35.754062114 +0200 +--- openssh-8.6p1/auth.h.audit 2021-05-06 12:05:27.318464076 +0200 ++++ openssh-8.6p1/auth.h 2021-05-06 12:05:27.378464540 +0200 @@ -193,6 +193,8 @@ struct passwd * getpwnamallow(struct ssh char *expand_authorized_keys(const char *, struct passwd *pw); @@ -840,7 +840,7 @@ diff -up openssh-8.6p1/auth.h.audit openssh-8.6p1/auth.h const struct sshauthopt *auth_options(struct ssh *); diff -up openssh-8.6p1/cipher.c.audit openssh-8.6p1/cipher.c --- openssh-8.6p1/cipher.c.audit 2021-04-16 05:55:25.000000000 +0200 -+++ openssh-8.6p1/cipher.c 2021-04-19 16:47:35.755062122 +0200 ++++ openssh-8.6p1/cipher.c 2021-05-06 12:05:27.378464540 +0200 @@ -64,25 +64,6 @@ struct sshcipher_ctx { const struct sshcipher *cipher; }; @@ -878,7 +878,7 @@ diff -up openssh-8.6p1/cipher.c.audit openssh-8.6p1/cipher.c chachapoly_free(cc->cp_ctx); diff -up openssh-8.6p1/cipher.h.audit openssh-8.6p1/cipher.h --- openssh-8.6p1/cipher.h.audit 2021-04-16 05:55:25.000000000 +0200 -+++ openssh-8.6p1/cipher.h 2021-04-19 16:47:35.755062122 +0200 ++++ openssh-8.6p1/cipher.h 2021-05-06 12:05:27.378464540 +0200 @@ -47,7 +47,25 @@ #define CIPHER_ENCRYPT 1 #define CIPHER_DECRYPT 0 @@ -907,8 +907,8 @@ diff -up openssh-8.6p1/cipher.h.audit openssh-8.6p1/cipher.h const struct sshcipher *cipher_by_name(const char *); diff -up openssh-8.6p1/kex.c.audit openssh-8.6p1/kex.c ---- openssh-8.6p1/kex.c.audit 2021-04-19 16:47:35.743062030 +0200 -+++ openssh-8.6p1/kex.c 2021-04-19 16:47:35.755062122 +0200 +--- openssh-8.6p1/kex.c.audit 2021-05-06 12:05:27.368464462 +0200 ++++ openssh-8.6p1/kex.c 2021-05-06 12:05:27.379464547 +0200 @@ -65,6 +65,7 @@ #include "ssherr.h" #include "sshbuf.h" @@ -1036,8 +1036,8 @@ diff -up openssh-8.6p1/kex.c.audit openssh-8.6p1/kex.c * Send a plaintext error message to the peer, suffixed by \r\n. * Only used during banner exchange, and there only for the server. diff -up openssh-8.6p1/kex.h.audit openssh-8.6p1/kex.h ---- openssh-8.6p1/kex.h.audit 2021-04-19 16:47:35.683061568 +0200 -+++ openssh-8.6p1/kex.h 2021-04-19 16:47:35.756062129 +0200 +--- openssh-8.6p1/kex.h.audit 2021-05-06 12:05:27.306463983 +0200 ++++ openssh-8.6p1/kex.h 2021-05-06 12:05:27.379464547 +0200 @@ -226,6 +226,8 @@ int kexgss_client(struct ssh *); int kexgss_server(struct ssh *); #endif @@ -1049,7 +1049,7 @@ diff -up openssh-8.6p1/kex.h.audit openssh-8.6p1/kex.h struct sshbuf **); diff -up openssh-8.6p1/mac.c.audit openssh-8.6p1/mac.c --- openssh-8.6p1/mac.c.audit 2021-04-16 05:55:25.000000000 +0200 -+++ openssh-8.6p1/mac.c 2021-04-19 16:47:35.756062129 +0200 ++++ openssh-8.6p1/mac.c 2021-05-06 12:05:27.379464547 +0200 @@ -239,6 +239,20 @@ mac_clear(struct sshmac *mac) mac->umac_ctx = NULL; } @@ -1073,7 +1073,7 @@ diff -up openssh-8.6p1/mac.c.audit openssh-8.6p1/mac.c int diff -up openssh-8.6p1/mac.h.audit openssh-8.6p1/mac.h --- openssh-8.6p1/mac.h.audit 2021-04-16 05:55:25.000000000 +0200 -+++ openssh-8.6p1/mac.h 2021-04-19 16:47:35.756062129 +0200 ++++ openssh-8.6p1/mac.h 2021-05-06 12:05:27.379464547 +0200 @@ -49,5 +49,6 @@ int mac_compute(struct sshmac *, u_int3 int mac_check(struct sshmac *, u_int32_t, const u_char *, size_t, const u_char *, size_t); @@ -1082,8 +1082,8 @@ diff -up openssh-8.6p1/mac.h.audit openssh-8.6p1/mac.h #endif /* SSHMAC_H */ diff -up openssh-8.6p1/Makefile.in.audit openssh-8.6p1/Makefile.in ---- openssh-8.6p1/Makefile.in.audit 2021-04-19 16:47:35.731061937 +0200 -+++ openssh-8.6p1/Makefile.in 2021-04-19 16:47:35.756062129 +0200 +--- openssh-8.6p1/Makefile.in.audit 2021-05-06 12:05:27.352464339 +0200 ++++ openssh-8.6p1/Makefile.in 2021-05-06 12:05:27.380464555 +0200 @@ -112,7 +112,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ kexsntrup761x25519.o sntrup761.o kexgen.o \ kexgssc.o \ @@ -1094,8 +1094,8 @@ diff -up openssh-8.6p1/Makefile.in.audit openssh-8.6p1/Makefile.in SKOBJS= ssh-sk-client.o diff -up openssh-8.6p1/monitor.c.audit openssh-8.6p1/monitor.c ---- openssh-8.6p1/monitor.c.audit 2021-04-19 16:47:35.707061753 +0200 -+++ openssh-8.6p1/monitor.c 2021-04-19 16:47:35.756062129 +0200 +--- openssh-8.6p1/monitor.c.audit 2021-05-06 12:05:27.326464138 +0200 ++++ openssh-8.6p1/monitor.c 2021-05-06 12:05:27.380464555 +0200 @@ -93,6 +93,7 @@ #include "compat.h" #include "ssh2.h" @@ -1427,8 +1427,8 @@ diff -up openssh-8.6p1/monitor.c.audit openssh-8.6p1/monitor.c +} +#endif /* SSH_AUDIT_EVENTS */ diff -up openssh-8.6p1/monitor.h.audit openssh-8.6p1/monitor.h ---- openssh-8.6p1/monitor.h.audit 2021-04-19 16:47:35.707061753 +0200 -+++ openssh-8.6p1/monitor.h 2021-04-19 16:47:35.757062137 +0200 +--- openssh-8.6p1/monitor.h.audit 2021-05-06 12:05:27.326464138 +0200 ++++ openssh-8.6p1/monitor.h 2021-05-06 12:05:27.380464555 +0200 @@ -65,7 +65,13 @@ enum monitor_reqtype { MONITOR_REQ_PAM_QUERY = 106, MONITOR_ANS_PAM_QUERY = 107, MONITOR_REQ_PAM_RESPOND = 108, MONITOR_ANS_PAM_RESPOND = 109, @@ -1445,8 +1445,8 @@ diff -up openssh-8.6p1/monitor.h.audit openssh-8.6p1/monitor.h MONITOR_REQ_GSSSIGN = 150, MONITOR_ANS_GSSSIGN = 151, MONITOR_REQ_GSSUPCREDS = 152, MONITOR_ANS_GSSUPCREDS = 153, diff -up openssh-8.6p1/monitor_wrap.c.audit openssh-8.6p1/monitor_wrap.c ---- openssh-8.6p1/monitor_wrap.c.audit 2021-04-19 16:47:35.685061584 +0200 -+++ openssh-8.6p1/monitor_wrap.c 2021-04-19 16:47:35.757062137 +0200 +--- openssh-8.6p1/monitor_wrap.c.audit 2021-05-06 12:05:27.307463991 +0200 ++++ openssh-8.6p1/monitor_wrap.c 2021-05-06 12:05:27.381464563 +0200 @@ -520,7 +520,7 @@ mm_key_allowed(enum mm_keytype type, con */ @@ -1620,8 +1620,8 @@ diff -up openssh-8.6p1/monitor_wrap.c.audit openssh-8.6p1/monitor_wrap.c +} +#endif /* SSH_AUDIT_EVENTS */ diff -up openssh-8.6p1/monitor_wrap.h.audit openssh-8.6p1/monitor_wrap.h ---- openssh-8.6p1/monitor_wrap.h.audit 2021-04-19 16:47:35.685061584 +0200 -+++ openssh-8.6p1/monitor_wrap.h 2021-04-19 16:47:35.757062137 +0200 +--- openssh-8.6p1/monitor_wrap.h.audit 2021-05-06 12:05:27.307463991 +0200 ++++ openssh-8.6p1/monitor_wrap.h 2021-05-06 12:05:27.381464563 +0200 @@ -61,7 +61,9 @@ int mm_user_key_allowed(struct ssh *, st struct sshauthopt **); int mm_hostbased_key_allowed(struct ssh *, struct passwd *, const char *, @@ -1649,7 +1649,7 @@ diff -up openssh-8.6p1/monitor_wrap.h.audit openssh-8.6p1/monitor_wrap.h struct Session; diff -up openssh-8.6p1/packet.c.audit openssh-8.6p1/packet.c --- openssh-8.6p1/packet.c.audit 2021-04-16 05:55:25.000000000 +0200 -+++ openssh-8.6p1/packet.c 2021-04-19 16:48:46.885608837 +0200 ++++ openssh-8.6p1/packet.c 2021-05-06 12:07:38.535478683 +0200 @@ -81,6 +81,7 @@ #endif @@ -1802,7 +1802,7 @@ diff -up openssh-8.6p1/packet.c.audit openssh-8.6p1/packet.c ssh_packet_set_postauth(struct ssh *ssh) diff -up openssh-8.6p1/packet.h.audit openssh-8.6p1/packet.h --- openssh-8.6p1/packet.h.audit 2021-04-16 05:55:25.000000000 +0200 -+++ openssh-8.6p1/packet.h 2021-04-19 16:47:35.758062145 +0200 ++++ openssh-8.6p1/packet.h 2021-05-06 12:05:27.382464571 +0200 @@ -218,4 +218,5 @@ const u_char *sshpkt_ptr(struct ssh *, s # undef EC_POINT #endif @@ -1810,8 +1810,8 @@ diff -up openssh-8.6p1/packet.h.audit openssh-8.6p1/packet.h +void packet_destroy_all(struct ssh *, int, int); #endif /* PACKET_H */ diff -up openssh-8.6p1/session.c.audit openssh-8.6p1/session.c ---- openssh-8.6p1/session.c.audit 2021-04-19 16:47:35.722061868 +0200 -+++ openssh-8.6p1/session.c 2021-04-19 16:47:35.758062145 +0200 +--- openssh-8.6p1/session.c.audit 2021-05-06 12:05:27.340464246 +0200 ++++ openssh-8.6p1/session.c 2021-05-06 12:05:27.383464578 +0200 @@ -136,7 +136,7 @@ extern char *__progname; extern int debug_flag; extern u_int utmp_len; @@ -1989,7 +1989,7 @@ diff -up openssh-8.6p1/session.c.audit openssh-8.6p1/session.c /* Return a name for the remote host that fits inside utmp_size */ diff -up openssh-8.6p1/session.h.audit openssh-8.6p1/session.h --- openssh-8.6p1/session.h.audit 2021-04-16 05:55:25.000000000 +0200 -+++ openssh-8.6p1/session.h 2021-04-19 16:47:35.758062145 +0200 ++++ openssh-8.6p1/session.h 2021-05-06 12:05:27.384464586 +0200 @@ -61,6 +61,12 @@ struct Session { char *name; char *val; @@ -2018,8 +2018,8 @@ diff -up openssh-8.6p1/session.h.audit openssh-8.6p1/session.h void session_close(struct ssh *, Session *); void do_setusercontext(struct passwd *); diff -up openssh-8.6p1/sshd.c.audit openssh-8.6p1/sshd.c ---- openssh-8.6p1/sshd.c.audit 2021-04-19 16:47:35.727061907 +0200 -+++ openssh-8.6p1/sshd.c 2021-04-19 16:47:35.759062152 +0200 +--- openssh-8.6p1/sshd.c.audit 2021-05-06 12:05:27.346464292 +0200 ++++ openssh-8.6p1/sshd.c 2021-05-06 12:05:27.385464594 +0200 @@ -122,6 +122,7 @@ #include "ssh-gss.h" #endif @@ -2260,8 +2260,8 @@ diff -up openssh-8.6p1/sshd.c.audit openssh-8.6p1/sshd.c #endif _exit(i); diff -up openssh-8.6p1/sshkey.c.audit openssh-8.6p1/sshkey.c ---- openssh-8.6p1/sshkey.c.audit 2021-04-19 16:47:35.741062014 +0200 -+++ openssh-8.6p1/sshkey.c 2021-04-19 16:47:35.759062152 +0200 +--- openssh-8.6p1/sshkey.c.audit 2021-05-06 12:05:27.364464431 +0200 ++++ openssh-8.6p1/sshkey.c 2021-05-06 12:05:27.386464602 +0200 @@ -371,6 +371,38 @@ sshkey_type_is_valid_ca(int type) } @@ -2302,8 +2302,8 @@ diff -up openssh-8.6p1/sshkey.c.audit openssh-8.6p1/sshkey.c { if (k == NULL) diff -up openssh-8.6p1/sshkey.h.audit openssh-8.6p1/sshkey.h ---- openssh-8.6p1/sshkey.h.audit 2021-04-19 16:47:35.741062014 +0200 -+++ openssh-8.6p1/sshkey.h 2021-04-19 16:47:35.759062152 +0200 +--- openssh-8.6p1/sshkey.h.audit 2021-05-06 12:05:27.365464439 +0200 ++++ openssh-8.6p1/sshkey.h 2021-05-06 12:05:27.386464602 +0200 @@ -189,6 +189,7 @@ int sshkey_shield_private(struct sshke int sshkey_unshield_private(struct sshkey *); diff --git a/openssh-7.7p1-fips.patch b/openssh-7.7p1-fips.patch index d2c5592..6e72d04 100644 --- a/openssh-7.7p1-fips.patch +++ b/openssh-7.7p1-fips.patch @@ -1,6 +1,6 @@ diff -up openssh-8.6p1/cipher-ctr.c.fips openssh-8.6p1/cipher-ctr.c ---- openssh-8.6p1/cipher-ctr.c.fips 2021-04-19 16:53:02.994577324 +0200 -+++ openssh-8.6p1/cipher-ctr.c 2021-04-19 16:53:03.064577862 +0200 +--- openssh-8.6p1/cipher-ctr.c.fips 2021-05-06 12:08:36.423926297 +0200 ++++ openssh-8.6p1/cipher-ctr.c 2021-05-06 12:08:36.497926869 +0200 @@ -179,7 +179,8 @@ evp_aes_128_ctr(void) aes_ctr.do_cipher = ssh_aes_ctr; #ifndef SSH_OLD_EVP @@ -13,7 +13,7 @@ diff -up openssh-8.6p1/cipher-ctr.c.fips openssh-8.6p1/cipher-ctr.c } diff -up openssh-8.6p1/dh.c.fips openssh-8.6p1/dh.c --- openssh-8.6p1/dh.c.fips 2021-04-16 05:55:25.000000000 +0200 -+++ openssh-8.6p1/dh.c 2021-04-19 16:58:47.750263410 +0200 ++++ openssh-8.6p1/dh.c 2021-05-06 12:12:10.107634472 +0200 @@ -164,6 +164,12 @@ choose_dh(int min, int wantbits, int max int best, bestcount, which, linenum; struct dhgroup dhg; @@ -67,8 +67,8 @@ diff -up openssh-8.6p1/dh.c.fips openssh-8.6p1/dh.c + #endif /* WITH_OPENSSL */ diff -up openssh-8.6p1/dh.h.fips openssh-8.6p1/dh.h ---- openssh-8.6p1/dh.h.fips 2021-04-19 16:53:03.064577862 +0200 -+++ openssh-8.6p1/dh.h 2021-04-19 16:59:31.951616078 +0200 +--- openssh-8.6p1/dh.h.fips 2021-05-06 12:08:36.498926877 +0200 ++++ openssh-8.6p1/dh.h 2021-05-06 12:11:28.393298005 +0200 @@ -45,6 +45,7 @@ DH *dh_new_group_fallback(int); int dh_gen_key(DH *, int); @@ -78,8 +78,8 @@ diff -up openssh-8.6p1/dh.h.fips openssh-8.6p1/dh.h u_int dh_estimate(int); void dh_set_moduli_file(const char *); diff -up openssh-8.6p1/kex.c.fips openssh-8.6p1/kex.c ---- openssh-8.6p1/kex.c.fips 2021-04-19 16:53:03.058577815 +0200 -+++ openssh-8.6p1/kex.c 2021-04-19 16:53:03.065577869 +0200 +--- openssh-8.6p1/kex.c.fips 2021-05-06 12:08:36.489926807 +0200 ++++ openssh-8.6p1/kex.c 2021-05-06 12:08:36.498926877 +0200 @@ -203,7 +203,10 @@ kex_names_valid(const char *names) for ((p = strsep(&cp, ",")); p && *p != '\0'; (p = strsep(&cp, ","))) { @@ -94,7 +94,7 @@ diff -up openssh-8.6p1/kex.c.fips openssh-8.6p1/kex.c } diff -up openssh-8.6p1/kexgexc.c.fips openssh-8.6p1/kexgexc.c --- openssh-8.6p1/kexgexc.c.fips 2021-04-16 05:55:25.000000000 +0200 -+++ openssh-8.6p1/kexgexc.c 2021-04-19 16:53:03.065577869 +0200 ++++ openssh-8.6p1/kexgexc.c 2021-05-06 12:08:36.498926877 +0200 @@ -28,6 +28,7 @@ #ifdef WITH_OPENSSL @@ -116,7 +116,7 @@ diff -up openssh-8.6p1/kexgexc.c.fips openssh-8.6p1/kexgexc.c /* generate and send 'e', client DH public key */ diff -up openssh-8.6p1/myproposal.h.fips openssh-8.6p1/myproposal.h --- openssh-8.6p1/myproposal.h.fips 2021-04-16 05:55:25.000000000 +0200 -+++ openssh-8.6p1/myproposal.h 2021-04-19 16:53:03.065577869 +0200 ++++ openssh-8.6p1/myproposal.h 2021-05-06 12:08:36.498926877 +0200 @@ -57,6 +57,20 @@ "rsa-sha2-256," \ "ssh-rsa" @@ -167,8 +167,8 @@ diff -up openssh-8.6p1/myproposal.h.fips openssh-8.6p1/myproposal.h #define SSH_ALLOWED_CA_SIGALGS \ "ssh-ed25519," \ diff -up openssh-8.6p1/readconf.c.fips openssh-8.6p1/readconf.c ---- openssh-8.6p1/readconf.c.fips 2021-04-19 16:53:02.999577362 +0200 -+++ openssh-8.6p1/readconf.c 2021-04-19 16:53:03.065577869 +0200 +--- openssh-8.6p1/readconf.c.fips 2021-05-06 12:08:36.428926336 +0200 ++++ openssh-8.6p1/readconf.c 2021-05-06 12:08:36.499926885 +0200 @@ -2538,11 +2538,16 @@ fill_default_options(Options * options) all_key = sshkey_alg_list(0, 0, 1, ','); all_sig = sshkey_alg_list(0, 1, 1, ','); @@ -192,8 +192,8 @@ diff -up openssh-8.6p1/readconf.c.fips openssh-8.6p1/readconf.c do { \ if ((r = kex_assemble_names(&options->what, \ diff -up openssh-8.6p1/sandbox-seccomp-filter.c.fips openssh-8.6p1/sandbox-seccomp-filter.c ---- openssh-8.6p1/sandbox-seccomp-filter.c.fips 2021-04-19 16:53:03.034577631 +0200 -+++ openssh-8.6p1/sandbox-seccomp-filter.c 2021-04-19 16:53:03.065577869 +0200 +--- openssh-8.6p1/sandbox-seccomp-filter.c.fips 2021-05-06 12:08:36.463926606 +0200 ++++ openssh-8.6p1/sandbox-seccomp-filter.c 2021-05-06 12:08:36.499926885 +0200 @@ -160,6 +160,9 @@ static const struct sock_filter preauth_ #ifdef __NR_open SC_DENY(__NR_open, EACCES), @@ -205,8 +205,8 @@ diff -up openssh-8.6p1/sandbox-seccomp-filter.c.fips openssh-8.6p1/sandbox-secco SC_DENY(__NR_openat, EACCES), #endif diff -up openssh-8.6p1/servconf.c.fips openssh-8.6p1/servconf.c ---- openssh-8.6p1/servconf.c.fips 2021-04-19 16:53:03.027577577 +0200 -+++ openssh-8.6p1/servconf.c 2021-04-19 16:53:03.066577877 +0200 +--- openssh-8.6p1/servconf.c.fips 2021-05-06 12:08:36.455926545 +0200 ++++ openssh-8.6p1/servconf.c 2021-05-06 12:08:36.500926893 +0200 @@ -226,11 +226,16 @@ assemble_algorithms(ServerOptions *o) all_key = sshkey_alg_list(0, 0, 1, ','); all_sig = sshkey_alg_list(0, 1, 1, ','); @@ -230,8 +230,8 @@ diff -up openssh-8.6p1/servconf.c.fips openssh-8.6p1/servconf.c do { \ if ((r = kex_assemble_names(&o->what, defaults, all)) != 0) \ diff -up openssh-8.6p1/ssh.c.fips openssh-8.6p1/ssh.c ---- openssh-8.6p1/ssh.c.fips 2021-04-19 16:53:03.038577662 +0200 -+++ openssh-8.6p1/ssh.c 2021-04-19 16:53:03.066577877 +0200 +--- openssh-8.6p1/ssh.c.fips 2021-05-06 12:08:36.467926637 +0200 ++++ openssh-8.6p1/ssh.c 2021-05-06 12:08:36.500926893 +0200 @@ -77,6 +77,7 @@ #include #include @@ -252,8 +252,8 @@ diff -up openssh-8.6p1/ssh.c.fips openssh-8.6p1/ssh.c if (options.sk_provider != NULL && *options.sk_provider == '$' && strlen(options.sk_provider) > 1) { diff -up openssh-8.6p1/sshconnect2.c.fips openssh-8.6p1/sshconnect2.c ---- openssh-8.6p1/sshconnect2.c.fips 2021-04-19 16:53:03.055577792 +0200 -+++ openssh-8.6p1/sshconnect2.c 2021-04-19 16:53:03.066577877 +0200 +--- openssh-8.6p1/sshconnect2.c.fips 2021-05-06 12:08:36.485926777 +0200 ++++ openssh-8.6p1/sshconnect2.c 2021-05-06 12:08:36.501926900 +0200 @@ -45,6 +45,8 @@ #include #endif @@ -333,8 +333,8 @@ diff -up openssh-8.6p1/sshconnect2.c.fips openssh-8.6p1/sshconnect2.c } #endif diff -up openssh-8.6p1/sshd.c.fips openssh-8.6p1/sshd.c ---- openssh-8.6p1/sshd.c.fips 2021-04-19 16:53:03.060577831 +0200 -+++ openssh-8.6p1/sshd.c 2021-04-19 16:57:45.827769340 +0200 +--- openssh-8.6p1/sshd.c.fips 2021-05-06 12:08:36.493926838 +0200 ++++ openssh-8.6p1/sshd.c 2021-05-06 12:13:56.501492639 +0200 @@ -66,6 +66,7 @@ #include #include @@ -390,8 +390,8 @@ diff -up openssh-8.6p1/sshd.c.fips openssh-8.6p1/sshd.c if (gss && orig) xasprintf(&newstr, "%s,%s", gss, orig); diff -up openssh-8.6p1/sshkey.c.fips openssh-8.6p1/sshkey.c ---- openssh-8.6p1/sshkey.c.fips 2021-04-19 16:53:03.061577838 +0200 -+++ openssh-8.6p1/sshkey.c 2021-04-19 16:53:03.067577885 +0200 +--- openssh-8.6p1/sshkey.c.fips 2021-05-06 12:08:36.493926838 +0200 ++++ openssh-8.6p1/sshkey.c 2021-05-06 12:08:36.502926908 +0200 @@ -34,6 +34,7 @@ #include #include @@ -418,8 +418,8 @@ diff -up openssh-8.6p1/sshkey.c.fips openssh-8.6p1/sshkey.c goto out; } diff -up openssh-8.6p1/ssh-keygen.c.fips openssh-8.6p1/ssh-keygen.c ---- openssh-8.6p1/ssh-keygen.c.fips 2021-04-19 16:53:03.038577662 +0200 -+++ openssh-8.6p1/ssh-keygen.c 2021-04-19 16:53:03.068577892 +0200 +--- openssh-8.6p1/ssh-keygen.c.fips 2021-05-06 12:08:36.467926637 +0200 ++++ openssh-8.6p1/ssh-keygen.c 2021-05-06 12:08:36.503926916 +0200 @@ -205,6 +205,12 @@ type_bits_valid(int type, const char *na #endif } diff --git a/openssh-7.7p1-gssapi-new-unique.patch b/openssh-7.7p1-gssapi-new-unique.patch index c130022..b2d2209 100644 --- a/openssh-7.7p1-gssapi-new-unique.patch +++ b/openssh-7.7p1-gssapi-new-unique.patch @@ -1,6 +1,6 @@ diff -up openssh-8.6p1/auth.h.ccache_name openssh-8.6p1/auth.h ---- openssh-8.6p1/auth.h.ccache_name 2021-04-19 14:05:10.820744325 +0200 -+++ openssh-8.6p1/auth.h 2021-04-19 14:05:10.853744569 +0200 +--- openssh-8.6p1/auth.h.ccache_name 2021-05-06 11:15:36.345143341 +0200 ++++ openssh-8.6p1/auth.h 2021-05-06 11:15:36.387143654 +0200 @@ -83,6 +83,7 @@ struct Authctxt { krb5_principal krb5_user; char *krb5_ticket_file; @@ -20,7 +20,7 @@ diff -up openssh-8.6p1/auth.h.ccache_name openssh-8.6p1/auth.h #endif /* AUTH_H */ diff -up openssh-8.6p1/auth-krb5.c.ccache_name openssh-8.6p1/auth-krb5.c --- openssh-8.6p1/auth-krb5.c.ccache_name 2021-04-16 05:55:25.000000000 +0200 -+++ openssh-8.6p1/auth-krb5.c 2021-04-19 14:40:55.142832954 +0200 ++++ openssh-8.6p1/auth-krb5.c 2021-05-06 11:28:40.195242317 +0200 @@ -51,6 +51,7 @@ #include #include @@ -338,8 +338,8 @@ diff -up openssh-8.6p1/auth-krb5.c.ccache_name openssh-8.6p1/auth-krb5.c #endif /* !HEIMDAL */ #endif /* KRB5 */ diff -up openssh-8.6p1/gss-serv.c.ccache_name openssh-8.6p1/gss-serv.c ---- openssh-8.6p1/gss-serv.c.ccache_name 2021-04-19 14:05:10.844744503 +0200 -+++ openssh-8.6p1/gss-serv.c 2021-04-19 14:05:10.854744577 +0200 +--- openssh-8.6p1/gss-serv.c.ccache_name 2021-05-06 11:15:36.374143558 +0200 ++++ openssh-8.6p1/gss-serv.c 2021-05-06 11:15:36.387143654 +0200 @@ -413,13 +413,15 @@ ssh_gssapi_cleanup_creds(void) } @@ -370,8 +370,8 @@ diff -up openssh-8.6p1/gss-serv.c.ccache_name openssh-8.6p1/gss-serv.c ok = PRIVSEP(ssh_gssapi_update_creds(&gssapi_client.store)); diff -up openssh-8.6p1/gss-serv-krb5.c.ccache_name openssh-8.6p1/gss-serv-krb5.c ---- openssh-8.6p1/gss-serv-krb5.c.ccache_name 2021-04-19 14:05:10.852744562 +0200 -+++ openssh-8.6p1/gss-serv-krb5.c 2021-04-19 14:05:10.854744577 +0200 +--- openssh-8.6p1/gss-serv-krb5.c.ccache_name 2021-05-06 11:15:36.384143632 +0200 ++++ openssh-8.6p1/gss-serv-krb5.c 2021-05-06 11:15:36.387143654 +0200 @@ -267,7 +267,7 @@ ssh_gssapi_krb5_cmdok(krb5_principal pri /* This writes out any forwarded credentials from the structure populated * during userauth. Called after we have setuid to the user */ @@ -484,8 +484,8 @@ diff -up openssh-8.6p1/gss-serv-krb5.c.ccache_name openssh-8.6p1/gss-serv-krb5.c int diff -up openssh-8.6p1/servconf.c.ccache_name openssh-8.6p1/servconf.c ---- openssh-8.6p1/servconf.c.ccache_name 2021-04-19 14:05:10.848744532 +0200 -+++ openssh-8.6p1/servconf.c 2021-04-19 14:05:10.854744577 +0200 +--- openssh-8.6p1/servconf.c.ccache_name 2021-05-06 11:15:36.377143580 +0200 ++++ openssh-8.6p1/servconf.c 2021-05-06 11:15:36.388143662 +0200 @@ -136,6 +136,7 @@ initialize_server_options(ServerOptions options->kerberos_or_local_passwd = -1; options->kerberos_ticket_cleanup = -1; @@ -547,8 +547,8 @@ diff -up openssh-8.6p1/servconf.c.ccache_name openssh-8.6p1/servconf.c #ifdef GSSAPI dump_cfg_fmtint(sGssAuthentication, o->gss_authentication); diff -up openssh-8.6p1/servconf.h.ccache_name openssh-8.6p1/servconf.h ---- openssh-8.6p1/servconf.h.ccache_name 2021-04-19 14:05:10.848744532 +0200 -+++ openssh-8.6p1/servconf.h 2021-04-19 14:05:10.855744584 +0200 +--- openssh-8.6p1/servconf.h.ccache_name 2021-05-06 11:15:36.377143580 +0200 ++++ openssh-8.6p1/servconf.h 2021-05-06 11:15:36.397143729 +0200 @@ -140,6 +140,8 @@ typedef struct { * file on logout. */ int kerberos_get_afs_token; /* If true, try to get AFS token if @@ -559,8 +559,8 @@ diff -up openssh-8.6p1/servconf.h.ccache_name openssh-8.6p1/servconf.h int gss_keyex; /* If true, permit GSSAPI key exchange */ int gss_cleanup_creds; /* If true, destroy cred cache on logout */ diff -up openssh-8.6p1/session.c.ccache_name openssh-8.6p1/session.c ---- openssh-8.6p1/session.c.ccache_name 2021-04-19 14:05:10.852744562 +0200 -+++ openssh-8.6p1/session.c 2021-04-19 14:05:10.855744584 +0200 +--- openssh-8.6p1/session.c.ccache_name 2021-05-06 11:15:36.384143632 +0200 ++++ openssh-8.6p1/session.c 2021-05-06 11:15:36.397143729 +0200 @@ -1038,7 +1038,8 @@ do_setup_env(struct ssh *ssh, Session *s /* Allow any GSSAPI methods that we've used to alter * the child's environment as they see fit @@ -581,8 +581,8 @@ diff -up openssh-8.6p1/session.c.ccache_name openssh-8.6p1/session.c s->authctxt->krb5_ccname); #endif diff -up openssh-8.6p1/sshd.c.ccache_name openssh-8.6p1/sshd.c ---- openssh-8.6p1/sshd.c.ccache_name 2021-04-19 14:05:10.849744540 +0200 -+++ openssh-8.6p1/sshd.c 2021-04-19 14:05:10.855744584 +0200 +--- openssh-8.6p1/sshd.c.ccache_name 2021-05-06 11:15:36.380143602 +0200 ++++ openssh-8.6p1/sshd.c 2021-05-06 11:15:36.398143736 +0200 @@ -2284,7 +2284,7 @@ main(int ac, char **av) #ifdef GSSAPI if (options.gss_authentication) { @@ -593,8 +593,8 @@ diff -up openssh-8.6p1/sshd.c.ccache_name openssh-8.6p1/sshd.c } #endif diff -up openssh-8.6p1/sshd_config.5.ccache_name openssh-8.6p1/sshd_config.5 ---- openssh-8.6p1/sshd_config.5.ccache_name 2021-04-19 14:05:10.849744540 +0200 -+++ openssh-8.6p1/sshd_config.5 2021-04-19 14:05:10.856744592 +0200 +--- openssh-8.6p1/sshd_config.5.ccache_name 2021-05-06 11:15:36.380143602 +0200 ++++ openssh-8.6p1/sshd_config.5 2021-05-06 11:15:36.398143736 +0200 @@ -939,6 +939,14 @@ Specifies whether to automatically destr file on logout. The default is @@ -611,8 +611,8 @@ diff -up openssh-8.6p1/sshd_config.5.ccache_name openssh-8.6p1/sshd_config.5 Specifies the available KEX (Key Exchange) algorithms. Multiple algorithms must be comma-separated. diff -up openssh-8.6p1/ssh-gss.h.ccache_name openssh-8.6p1/ssh-gss.h ---- openssh-8.6p1/ssh-gss.h.ccache_name 2021-04-19 14:05:10.852744562 +0200 -+++ openssh-8.6p1/ssh-gss.h 2021-04-19 14:05:10.855744584 +0200 +--- openssh-8.6p1/ssh-gss.h.ccache_name 2021-05-06 11:15:36.384143632 +0200 ++++ openssh-8.6p1/ssh-gss.h 2021-05-06 11:15:36.398143736 +0200 @@ -114,7 +114,7 @@ typedef struct ssh_gssapi_mech_struct { int (*dochild) (ssh_gssapi_client *); int (*userok) (ssh_gssapi_client *, char *); diff --git a/openssh-7.7p1-redhat.patch b/openssh-7.7p1-redhat.patch index fcda6c6..85ebc82 100644 --- a/openssh-7.7p1-redhat.patch +++ b/openssh-7.7p1-redhat.patch @@ -15,7 +15,7 @@ diff -up openssh/ssh_config.redhat openssh/ssh_config diff -up openssh/ssh_config_redhat.redhat openssh/ssh_config_redhat --- openssh/ssh_config_redhat.redhat 2020-02-13 18:13:39.180641839 +0100 +++ openssh/ssh_config_redhat 2020-02-13 18:13:39.180641839 +0100 -@@ -0,0 +1,21 @@ +@@ -0,0 +1,15 @@ +# The options here are in the "Match final block" to be applied as the last +# options and could be potentially overwritten by the user configuration +Match final all @@ -29,12 +29,6 @@ diff -up openssh/ssh_config_redhat.redhat openssh/ssh_config_redhat +# mode correctly we set this to yes. + ForwardX11Trusted yes + -+# Send locale-related environment variables -+ SendEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES -+ SendEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT -+ SendEnv LC_IDENTIFICATION LC_ALL LANGUAGE -+ SendEnv XMODIFIERS -+ +# Uncomment this if you want to use .local domain +# Host *.local diff -up openssh/sshd_config.0.redhat openssh/sshd_config.0 @@ -86,7 +80,7 @@ diff -up openssh/sshd_config.redhat openssh/sshd_config diff -up openssh/sshd_config_redhat.redhat openssh/sshd_config_redhat --- openssh/sshd_config_redhat.redhat 2020-02-13 18:14:02.268006439 +0100 +++ openssh/sshd_config_redhat 2020-02-13 18:19:20.765035947 +0100 -@@ -0,0 +1,28 @@ +@@ -0,0 +1,22 @@ +# This system is following system-wide crypto policy. The changes to +# crypto properties (Ciphers, MACs, ...) will not have any effect in +# this or following included files. To override some configuration option, @@ -109,9 +103,3 @@ diff -up openssh/sshd_config_redhat.redhat openssh/sshd_config_redhat +# as it is more configurable and versatile than the built-in version. +PrintMotd no + -+# Accept locale-related environment variables -+AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES -+AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT -+AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE -+AcceptEnv XMODIFIERS -+ diff --git a/openssh-8.0p1-gssapi-keyex.patch b/openssh-8.0p1-gssapi-keyex.patch index e26bebd..64d8925 100644 --- a/openssh-8.0p1-gssapi-keyex.patch +++ b/openssh-8.0p1-gssapi-keyex.patch @@ -1489,7 +1489,7 @@ new file mode 100644 index 00000000..f6e1405e --- /dev/null +++ b/kexgssc.c -@@ -0,0 +1,599 @@ +@@ -0,0 +1,611 @@ +/* + * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. + * @@ -1590,8 +1590,10 @@ index 00000000..f6e1405e + default: + fatal_f("Unexpected KEX type %d", kex->kex_type); + } -+ if (r != 0) ++ if (r != 0) { ++ ssh_gssapi_delete_ctx(&ctxt); + return r; ++ } + + token_ptr = GSS_C_NO_BUFFER; + @@ -1654,11 +1656,16 @@ index 00000000..f6e1405e + 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); + @@ -1945,11 +1952,16 @@ index 00000000..f6e1405e + 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); + @@ -2094,7 +2106,7 @@ new file mode 100644 index 00000000..60bc02de --- /dev/null +++ b/kexgsss.c -@@ -0,0 +1,474 @@ +@@ -0,0 +1,482 @@ +/* + * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. + * @@ -2161,7 +2173,7 @@ index 00000000..60bc02de + */ + + 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; @@ -2201,7 +2213,7 @@ index 00000000..60bc02de + 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 || @@ -2232,6 +2244,31 @@ index 00000000..60bc02de + 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, @@ -2253,7 +2290,7 @@ index 00000000..60bc02de + 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) { @@ -2282,23 +2319,6 @@ index 00000000..60bc02de + 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.0p1-pkcs11-uri.patch b/openssh-8.0p1-pkcs11-uri.patch index 8592607..d908981 100644 --- a/openssh-8.0p1-pkcs11-uri.patch +++ b/openssh-8.0p1-pkcs11-uri.patch @@ -1,7 +1,7 @@ -diff -up openssh-8.7p1/configure.ac.pkcs11-uri openssh-8.7p1/configure.ac ---- openssh-8.7p1/configure.ac.pkcs11-uri 2021-08-30 13:07:43.646699953 +0200 -+++ openssh-8.7p1/configure.ac 2021-08-30 13:07:43.662700088 +0200 -@@ -1985,12 +1985,14 @@ AC_LINK_IFELSE( +diff -up openssh-8.6p1/configure.ac.pkcs11-uri openssh-8.6p1/configure.ac +--- openssh-8.6p1/configure.ac.pkcs11-uri 2021-05-06 11:35:55.101653187 +0200 ++++ openssh-8.6p1/configure.ac 2021-05-06 11:35:55.111653265 +0200 +@@ -1974,12 +1974,14 @@ AC_LINK_IFELSE( [AC_DEFINE([HAVE_ISBLANK], [1], [Define if you have isblank(3C).]) ]) @@ -16,7 +16,7 @@ diff -up openssh-8.7p1/configure.ac.pkcs11-uri openssh-8.7p1/configure.ac fi ] ) -@@ -2019,6 +2021,40 @@ AC_SEARCH_LIBS([dlopen], [dl]) +@@ -2008,6 +2010,40 @@ AC_SEARCH_LIBS([dlopen], [dl]) AC_CHECK_FUNCS([dlopen]) AC_CHECK_DECL([RTLD_NOW], [], [], [#include ]) @@ -57,7 +57,7 @@ diff -up openssh-8.7p1/configure.ac.pkcs11-uri openssh-8.7p1/configure.ac # IRIX has a const char return value for gai_strerror() AC_CHECK_FUNCS([gai_strerror], [ AC_DEFINE([HAVE_GAI_STRERROR]) -@@ -5624,6 +5660,7 @@ echo " BSD Auth support +@@ -5564,6 +5600,7 @@ echo " BSD Auth support echo " Random number source: $RAND_MSG" echo " Privsep sandbox style: $SANDBOX_STYLE" echo " PKCS#11 support: $enable_pkcs11" @@ -65,9 +65,9 @@ diff -up openssh-8.7p1/configure.ac.pkcs11-uri openssh-8.7p1/configure.ac echo " U2F/FIDO support: $enable_sk" echo "" -diff -up openssh-8.7p1/Makefile.in.pkcs11-uri openssh-8.7p1/Makefile.in ---- openssh-8.7p1/Makefile.in.pkcs11-uri 2021-08-30 13:07:43.571699324 +0200 -+++ openssh-8.7p1/Makefile.in 2021-08-30 13:07:43.663700096 +0200 +diff -up openssh-8.6p1/Makefile.in.pkcs11-uri openssh-8.6p1/Makefile.in +--- openssh-8.6p1/Makefile.in.pkcs11-uri 2021-05-06 11:35:55.054652818 +0200 ++++ openssh-8.6p1/Makefile.in 2021-05-06 11:58:16.895135904 +0200 @@ -103,7 +103,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-ecdsa-sk.o \ ssh-ed25519-sk.o ssh-rsa.o dh.o \ @@ -77,7 +77,7 @@ diff -up openssh-8.7p1/Makefile.in.pkcs11-uri openssh-8.7p1/Makefile.in poly1305.o chacha.o cipher-chachapoly.o cipher-chachapoly-libcrypto.o \ ssh-ed25519.o digest-openssl.o digest-libc.o \ hmac.o sc25519.o ge25519.o fe25519.o ed25519.o verify.o hash.o \ -@@ -302,6 +302,8 @@ clean: regressclean +@@ -300,6 +300,8 @@ clean: regressclean rm -f regress/unittests/sshsig/test_sshsig$(EXEEXT) rm -f regress/unittests/utf8/*.o rm -f regress/unittests/utf8/test_utf8$(EXEEXT) @@ -86,7 +86,7 @@ diff -up openssh-8.7p1/Makefile.in.pkcs11-uri openssh-8.7p1/Makefile.in rm -f regress/misc/sk-dummy/*.o rm -f regress/misc/sk-dummy/*.lo rm -f regress/misc/sk-dummy/sk-dummy.so -@@ -339,6 +341,8 @@ distclean: regressclean +@@ -337,6 +339,8 @@ distclean: regressclean rm -f regress/unittests/sshsig/test_sshsig rm -f regress/unittests/utf8/*.o rm -f regress/unittests/utf8/test_utf8 @@ -95,7 +95,7 @@ diff -up openssh-8.7p1/Makefile.in.pkcs11-uri openssh-8.7p1/Makefile.in (cd openbsd-compat && $(MAKE) distclean) if test -d pkg ; then \ rm -fr pkg ; \ -@@ -513,6 +517,7 @@ regress-prep: +@@ -511,6 +515,7 @@ regress-prep: $(MKDIR_P) `pwd`/regress/unittests/sshkey $(MKDIR_P) `pwd`/regress/unittests/sshsig $(MKDIR_P) `pwd`/regress/unittests/utf8 @@ -103,7 +103,7 @@ diff -up openssh-8.7p1/Makefile.in.pkcs11-uri openssh-8.7p1/Makefile.in $(MKDIR_P) `pwd`/regress/misc/sk-dummy [ -f `pwd`/regress/Makefile ] || \ ln -s `cd $(srcdir) && pwd`/regress/Makefile `pwd`/regress/Makefile -@@ -677,6 +682,16 @@ regress/unittests/utf8/test_utf8$(EXEEXT +@@ -674,6 +679,16 @@ regress/unittests/utf8/test_utf8$(EXEEXT regress/unittests/test_helper/libtest_helper.a \ -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS) @@ -130,9 +130,9 @@ diff -up openssh-8.7p1/Makefile.in.pkcs11-uri openssh-8.7p1/Makefile.in tests: file-tests t-exec interop-tests unit echo all tests passed -diff -up openssh-8.7p1/regress/agent-pkcs11.sh.pkcs11-uri openssh-8.7p1/regress/agent-pkcs11.sh ---- openssh-8.7p1/regress/agent-pkcs11.sh.pkcs11-uri 2021-08-20 06:03:49.000000000 +0200 -+++ openssh-8.7p1/regress/agent-pkcs11.sh 2021-08-30 13:07:43.663700096 +0200 +diff -up openssh-8.6p1/regress/agent-pkcs11.sh.pkcs11-uri openssh-8.6p1/regress/agent-pkcs11.sh +--- openssh-8.6p1/regress/agent-pkcs11.sh.pkcs11-uri 2021-04-16 05:55:25.000000000 +0200 ++++ openssh-8.6p1/regress/agent-pkcs11.sh 2021-05-06 11:35:55.112653273 +0200 @@ -113,7 +113,7 @@ else done @@ -142,10 +142,10 @@ diff -up openssh-8.7p1/regress/agent-pkcs11.sh.pkcs11-uri openssh-8.7p1/regress/ r=$? if [ $r -ne 0 ]; then fail "ssh-add -e failed: exit code $r" -diff -up openssh-8.7p1/regress/Makefile.pkcs11-uri openssh-8.7p1/regress/Makefile ---- openssh-8.7p1/regress/Makefile.pkcs11-uri 2021-08-20 06:03:49.000000000 +0200 -+++ openssh-8.7p1/regress/Makefile 2021-08-30 13:07:43.663700096 +0200 -@@ -122,7 +122,8 @@ CLEANFILES= *.core actual agent-key.* au +diff -up openssh-8.6p1/regress/Makefile.pkcs11-uri openssh-8.6p1/regress/Makefile +--- openssh-8.6p1/regress/Makefile.pkcs11-uri 2021-04-16 05:55:25.000000000 +0200 ++++ openssh-8.6p1/regress/Makefile 2021-05-06 11:59:24.465658383 +0200 +@@ -119,7 +119,8 @@ CLEANFILES= *.core actual agent-key.* au known_hosts known_hosts-cert known_hosts.* krl-* ls.copy \ modpipe netcat no_identity_config \ pidfile putty.rsa2 ready regress.log remote_pid \ @@ -155,21 +155,17 @@ diff -up openssh-8.7p1/regress/Makefile.pkcs11-uri openssh-8.7p1/regress/Makefil rsa_ssh2_crnl.prv scp-ssh-wrapper.exe \ scp-ssh-wrapper.scp setuid-allowed sftp-server.log \ sftp-server.sh sftp.log ssh-log-wrapper.sh ssh.log \ -@@ -252,8 +253,9 @@ unit: +@@ -249,6 +250,7 @@ unit: V="" ; \ test "x${USE_VALGRIND}" = "x" || \ V=${.CURDIR}/valgrind-unit.sh ; \ -- $$V ${.OBJDIR}/unittests/sshbuf/test_sshbuf ; \ -- $$V ${.OBJDIR}/unittests/sshkey/test_sshkey \ -+ $$V ${.OBJDIR}/unittests/pkcs11/test_pkcs11 ; \ -+ $$V ${.OBJDIR}/unittests/sshbuf/test_sshbuf ; \ -+ $$V ${.OBJDIR}/unittests/sshkey/test_sshkey \ ++ $$V ${.OBJDIR}/unittests/pkcs11/test_pkcs11 ; \ + $$V ${.OBJDIR}/unittests/sshbuf/test_sshbuf ; \ + $$V ${.OBJDIR}/unittests/sshkey/test_sshkey \ -d ${.CURDIR}/unittests/sshkey/testdata ; \ - $$V ${.OBJDIR}/unittests/sshsig/test_sshsig \ - -d ${.CURDIR}/unittests/sshsig/testdata ; \ -diff -up openssh-8.7p1/regress/pkcs11.sh.pkcs11-uri openssh-8.7p1/regress/pkcs11.sh ---- openssh-8.7p1/regress/pkcs11.sh.pkcs11-uri 2021-08-30 13:07:43.663700096 +0200 -+++ openssh-8.7p1/regress/pkcs11.sh 2021-08-30 13:07:43.663700096 +0200 +diff -up openssh-8.6p1/regress/pkcs11.sh.pkcs11-uri openssh-8.6p1/regress/pkcs11.sh +--- openssh-8.6p1/regress/pkcs11.sh.pkcs11-uri 2021-05-06 11:35:55.112653273 +0200 ++++ openssh-8.6p1/regress/pkcs11.sh 2021-05-06 11:35:55.112653273 +0200 @@ -0,0 +1,349 @@ +# +# Copyright (c) 2017 Red Hat @@ -520,9 +516,9 @@ diff -up openssh-8.7p1/regress/pkcs11.sh.pkcs11-uri openssh-8.7p1/regress/pkcs11 + trace "kill agent" + ${SSHAGENT} -k > /dev/null +fi -diff -up openssh-8.7p1/regress/unittests/Makefile.pkcs11-uri openssh-8.7p1/regress/unittests/Makefile ---- openssh-8.7p1/regress/unittests/Makefile.pkcs11-uri 2021-08-20 06:03:49.000000000 +0200 -+++ openssh-8.7p1/regress/unittests/Makefile 2021-08-30 13:07:43.663700096 +0200 +diff -up openssh-8.6p1/regress/unittests/Makefile.pkcs11-uri openssh-8.6p1/regress/unittests/Makefile +--- openssh-8.6p1/regress/unittests/Makefile.pkcs11-uri 2021-04-16 05:55:25.000000000 +0200 ++++ openssh-8.6p1/regress/unittests/Makefile 2021-05-06 11:35:55.112653273 +0200 @@ -2,6 +2,6 @@ REGRESS_FAIL_EARLY?= yes @@ -531,9 +527,9 @@ diff -up openssh-8.7p1/regress/unittests/Makefile.pkcs11-uri openssh-8.7p1/regre +SUBDIR+=authopt misc sshsig pkcs11 .include -diff -up openssh-8.7p1/regress/unittests/pkcs11/tests.c.pkcs11-uri openssh-8.7p1/regress/unittests/pkcs11/tests.c ---- openssh-8.7p1/regress/unittests/pkcs11/tests.c.pkcs11-uri 2021-08-30 13:07:43.664700104 +0200 -+++ openssh-8.7p1/regress/unittests/pkcs11/tests.c 2021-08-30 13:07:43.664700104 +0200 +diff -up openssh-8.6p1/regress/unittests/pkcs11/tests.c.pkcs11-uri openssh-8.6p1/regress/unittests/pkcs11/tests.c +--- openssh-8.6p1/regress/unittests/pkcs11/tests.c.pkcs11-uri 2021-05-06 11:35:55.112653273 +0200 ++++ openssh-8.6p1/regress/unittests/pkcs11/tests.c 2021-05-06 11:35:55.112653273 +0200 @@ -0,0 +1,337 @@ +/* + * Copyright (c) 2017 Red Hat @@ -872,9 +868,9 @@ diff -up openssh-8.7p1/regress/unittests/pkcs11/tests.c.pkcs11-uri openssh-8.7p1 + test_parse_invalid(); + test_generate_valid(); +} -diff -up openssh-8.7p1/ssh-add.c.pkcs11-uri openssh-8.7p1/ssh-add.c ---- openssh-8.7p1/ssh-add.c.pkcs11-uri 2021-08-20 06:03:49.000000000 +0200 -+++ openssh-8.7p1/ssh-add.c 2021-08-30 13:07:43.664700104 +0200 +diff -up openssh-8.6p1/ssh-add.c.pkcs11-uri openssh-8.6p1/ssh-add.c +--- openssh-8.6p1/ssh-add.c.pkcs11-uri 2021-04-16 05:55:25.000000000 +0200 ++++ openssh-8.6p1/ssh-add.c 2021-05-06 11:35:55.112653273 +0200 @@ -68,6 +68,7 @@ #include "digest.h" #include "ssh-sk.h" @@ -954,9 +950,9 @@ diff -up openssh-8.7p1/ssh-add.c.pkcs11-uri openssh-8.7p1/ssh-add.c ret = 1; goto done; } -diff -up openssh-8.7p1/ssh-agent.c.pkcs11-uri openssh-8.7p1/ssh-agent.c ---- openssh-8.7p1/ssh-agent.c.pkcs11-uri 2021-08-20 06:03:49.000000000 +0200 -+++ openssh-8.7p1/ssh-agent.c 2021-08-30 13:07:43.664700104 +0200 +diff -up openssh-8.6p1/ssh-agent.c.pkcs11-uri openssh-8.6p1/ssh-agent.c +--- openssh-8.6p1/ssh-agent.c.pkcs11-uri 2021-04-16 05:55:25.000000000 +0200 ++++ openssh-8.6p1/ssh-agent.c 2021-05-06 11:35:55.113653281 +0200 @@ -847,10 +847,72 @@ no_identities(SocketEntry *e) } @@ -1127,10 +1123,10 @@ diff -up openssh-8.7p1/ssh-agent.c.pkcs11-uri openssh-8.7p1/ssh-agent.c send_status(e, success); } #endif /* ENABLE_PKCS11 */ -diff -up openssh-8.7p1/ssh_config.5.pkcs11-uri openssh-8.7p1/ssh_config.5 ---- openssh-8.7p1/ssh_config.5.pkcs11-uri 2021-08-30 13:07:43.578699383 +0200 -+++ openssh-8.7p1/ssh_config.5 2021-08-30 13:07:43.664700104 +0200 -@@ -1111,6 +1111,21 @@ may also be used in conjunction with +diff -up openssh-8.6p1/ssh_config.5.pkcs11-uri openssh-8.6p1/ssh_config.5 +--- openssh-8.6p1/ssh_config.5.pkcs11-uri 2021-05-06 11:35:55.061652873 +0200 ++++ openssh-8.6p1/ssh_config.5 2021-05-06 11:35:55.116653304 +0200 +@@ -1063,6 +1063,21 @@ may also be used in conjunction with .Cm CertificateFile in order to provide any certificate also needed for authentication with the identity. @@ -1152,10 +1148,10 @@ diff -up openssh-8.7p1/ssh_config.5.pkcs11-uri openssh-8.7p1/ssh_config.5 .It Cm IgnoreUnknown Specifies a pattern-list of unknown options to be ignored if they are encountered in configuration parsing. -diff -up openssh-8.7p1/ssh.c.pkcs11-uri openssh-8.7p1/ssh.c ---- openssh-8.7p1/ssh.c.pkcs11-uri 2021-08-30 13:07:43.578699383 +0200 -+++ openssh-8.7p1/ssh.c 2021-08-30 13:07:43.666700121 +0200 -@@ -826,6 +826,14 @@ main(int ac, char **av) +diff -up openssh-8.6p1/ssh.c.pkcs11-uri openssh-8.6p1/ssh.c +--- openssh-8.6p1/ssh.c.pkcs11-uri 2021-05-06 11:35:55.060652865 +0200 ++++ openssh-8.6p1/ssh.c 2021-05-06 12:00:07.129988275 +0200 +@@ -843,6 +843,14 @@ main(int ac, char **av) options.gss_deleg_creds = 1; break; case 'i': @@ -1170,7 +1166,7 @@ diff -up openssh-8.7p1/ssh.c.pkcs11-uri openssh-8.7p1/ssh.c p = tilde_expand_filename(optarg, getuid()); if (stat(p, &st) == -1) fprintf(stderr, "Warning: Identity file %s " -@@ -1681,6 +1689,7 @@ main(int ac, char **av) +@@ -1695,6 +1703,7 @@ main(int ac, char **av) #ifdef ENABLE_PKCS11 (void)pkcs11_del_provider(options.pkcs11_provider); #endif @@ -1178,7 +1174,7 @@ diff -up openssh-8.7p1/ssh.c.pkcs11-uri openssh-8.7p1/ssh.c skip_connect: exit_status = ssh_session2(ssh, cinfo); -@@ -2197,6 +2206,45 @@ ssh_session2(struct ssh *ssh, const stru +@@ -2211,6 +2220,45 @@ ssh_session2(struct ssh *ssh, const stru options.escape_char : SSH_ESCAPECHAR_NONE, id); } @@ -1224,7 +1220,7 @@ diff -up openssh-8.7p1/ssh.c.pkcs11-uri openssh-8.7p1/ssh.c /* Loads all IdentityFile and CertificateFile keys */ static void load_public_identity_files(const struct ssh_conn_info *cinfo) -@@ -2211,11 +2259,6 @@ load_public_identity_files(const struct +@@ -2225,11 +2273,6 @@ load_public_identity_files(const struct char *certificate_files[SSH_MAX_CERTIFICATE_FILES]; struct sshkey *certificates[SSH_MAX_CERTIFICATE_FILES]; int certificate_file_userprovided[SSH_MAX_CERTIFICATE_FILES]; @@ -1236,7 +1232,7 @@ diff -up openssh-8.7p1/ssh.c.pkcs11-uri openssh-8.7p1/ssh.c n_ids = n_certs = 0; memset(identity_files, 0, sizeof(identity_files)); -@@ -2228,33 +2271,46 @@ load_public_identity_files(const struct +@@ -2242,33 +2285,46 @@ load_public_identity_files(const struct sizeof(certificate_file_userprovided)); #ifdef ENABLE_PKCS11 @@ -1302,9 +1298,9 @@ diff -up openssh-8.7p1/ssh.c.pkcs11-uri openssh-8.7p1/ssh.c filename = default_client_percent_dollar_expand(cp, cinfo); free(cp); check_load(sshkey_load_public(filename, &public, NULL), -diff -up openssh-8.7p1/ssh-keygen.c.pkcs11-uri openssh-8.7p1/ssh-keygen.c ---- openssh-8.7p1/ssh-keygen.c.pkcs11-uri 2021-08-20 06:03:49.000000000 +0200 -+++ openssh-8.7p1/ssh-keygen.c 2021-08-30 13:07:43.666700121 +0200 +diff -up openssh-8.6p1/ssh-keygen.c.pkcs11-uri openssh-8.6p1/ssh-keygen.c +--- openssh-8.6p1/ssh-keygen.c.pkcs11-uri 2021-04-16 05:55:25.000000000 +0200 ++++ openssh-8.6p1/ssh-keygen.c 2021-05-06 11:35:55.114653289 +0200 @@ -860,8 +860,11 @@ do_download(struct passwd *pw) free(fp); } else { @@ -1319,9 +1315,9 @@ diff -up openssh-8.7p1/ssh-keygen.c.pkcs11-uri openssh-8.7p1/ssh-keygen.c } free(comments[i]); sshkey_free(keys[i]); -diff -up openssh-8.7p1/ssh-pkcs11-client.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11-client.c ---- openssh-8.7p1/ssh-pkcs11-client.c.pkcs11-uri 2021-08-20 06:03:49.000000000 +0200 -+++ openssh-8.7p1/ssh-pkcs11-client.c 2021-08-30 13:07:43.666700121 +0200 +diff -up openssh-8.6p1/ssh-pkcs11-client.c.pkcs11-uri openssh-8.6p1/ssh-pkcs11-client.c +--- openssh-8.6p1/ssh-pkcs11-client.c.pkcs11-uri 2021-04-16 05:55:25.000000000 +0200 ++++ openssh-8.6p1/ssh-pkcs11-client.c 2021-05-06 11:35:55.114653289 +0200 @@ -323,6 +323,8 @@ pkcs11_add_provider(char *name, char *pi u_int nkeys, i; struct sshbuf *msg; @@ -1339,9 +1335,9 @@ diff -up openssh-8.7p1/ssh-pkcs11-client.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11-c for (i = 0; i < nkeys; i++) { /* XXX clean up properly instead of fatal() */ if ((r = sshbuf_get_string(msg, &blob, &blen)) != 0 || -diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c ---- openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri 2021-08-20 06:03:49.000000000 +0200 -+++ openssh-8.7p1/ssh-pkcs11.c 2021-08-30 13:12:27.709084157 +0200 +diff -up openssh-8.6p1/ssh-pkcs11.c.pkcs11-uri openssh-8.6p1/ssh-pkcs11.c +--- openssh-8.6p1/ssh-pkcs11.c.pkcs11-uri 2021-04-16 05:55:25.000000000 +0200 ++++ openssh-8.6p1/ssh-pkcs11.c 2021-05-06 11:35:55.115653297 +0200 @@ -55,8 +55,8 @@ struct pkcs11_slotinfo { int logged_in; }; @@ -1542,7 +1538,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c } static RSA_METHOD *rsa_method; -@@ -195,6 +286,55 @@ static EC_KEY_METHOD *ec_key_method; +@@ -195,6 +283,55 @@ static EC_KEY_METHOD *ec_key_method; static int ec_key_idx = 0; #endif @@ -1598,7 +1594,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c /* release a wrapped object */ static void pkcs11_k11_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, -@@ -208,6 +348,7 @@ pkcs11_k11_free(void *parent, void *ptr, +@@ -208,6 +345,7 @@ pkcs11_k11_free(void *parent, void *ptr, if (k11->provider) pkcs11_provider_unref(k11->provider); free(k11->keyid); @@ -1606,7 +1602,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c free(k11); } -@@ -222,8 +363,8 @@ pkcs11_find(struct pkcs11_provider *p, C +@@ -222,8 +360,8 @@ pkcs11_find(struct pkcs11_provider *p, C CK_RV rv; int ret = -1; @@ -1617,7 +1613,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c if ((rv = f->C_FindObjectsInit(session, attr, nattr)) != CKR_OK) { error("C_FindObjectsInit failed (nattr %lu): %lu", nattr, rv); return (-1); -@@ -262,12 +403,12 @@ pkcs11_login_slot(struct pkcs11_provider +@@ -262,12 +400,12 @@ pkcs11_login_slot(struct pkcs11_provider else { snprintf(prompt, sizeof(prompt), "Enter PIN for '%s': ", si->token.label); @@ -1632,7 +1628,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c (pin != NULL) ? strlen(pin) : 0); if (pin != NULL) freezero(pin, strlen(pin)); -@@ -297,13 +438,14 @@ pkcs11_login_slot(struct pkcs11_provider +@@ -297,13 +435,14 @@ pkcs11_login_slot(struct pkcs11_provider static int pkcs11_login(struct pkcs11_key *k11, CK_USER_TYPE type) { @@ -1649,7 +1645,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c } -@@ -319,13 +461,14 @@ pkcs11_check_obj_bool_attrib(struct pkcs +@@ -319,13 +458,14 @@ pkcs11_check_obj_bool_attrib(struct pkcs *val = 0; @@ -1667,7 +1663,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c attr.type = type; attr.pValue = &flag; -@@ -356,13 +499,14 @@ pkcs11_get_key(struct pkcs11_key *k11, C +@@ -356,13 +496,14 @@ pkcs11_get_key(struct pkcs11_key *k11, C int always_auth = 0; int did_login = 0; @@ -1685,7 +1681,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c if ((si->token.flags & CKF_LOGIN_REQUIRED) && !si->logged_in) { if (pkcs11_login(k11, CKU_USER) < 0) { -@@ -439,8 +583,8 @@ pkcs11_rsa_private_encrypt(int flen, con +@@ -439,8 +580,8 @@ pkcs11_rsa_private_encrypt(int flen, con return (-1); } @@ -1696,7 +1692,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c tlen = RSA_size(rsa); /* XXX handle CKR_BUFFER_TOO_SMALL */ -@@ -484,7 +628,7 @@ pkcs11_rsa_start_wrapper(void) +@@ -484,7 +625,7 @@ pkcs11_rsa_start_wrapper(void) /* redirect private key operations for rsa key to pkcs11 token */ static int pkcs11_rsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx, @@ -1705,7 +1701,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c { struct pkcs11_key *k11; -@@ -502,6 +646,12 @@ pkcs11_rsa_wrap(struct pkcs11_provider * +@@ -502,6 +643,12 @@ pkcs11_rsa_wrap(struct pkcs11_provider * memcpy(k11->keyid, keyid_attrib->pValue, k11->keyid_len); } @@ -1718,7 +1714,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c RSA_set_method(rsa, rsa_method); RSA_set_ex_data(rsa, rsa_idx, k11); return (0); -@@ -532,8 +682,8 @@ ecdsa_do_sign(const unsigned char *dgst, +@@ -532,8 +679,8 @@ ecdsa_do_sign(const unsigned char *dgst, return (NULL); } @@ -1729,7 +1725,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c siglen = ECDSA_size(ec); sig = xmalloc(siglen); -@@ -598,7 +748,7 @@ pkcs11_ecdsa_start_wrapper(void) +@@ -598,7 +745,7 @@ pkcs11_ecdsa_start_wrapper(void) static int pkcs11_ecdsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx, @@ -1738,7 +1734,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c { struct pkcs11_key *k11; -@@ -614,6 +764,12 @@ pkcs11_ecdsa_wrap(struct pkcs11_provider +@@ -614,6 +761,12 @@ pkcs11_ecdsa_wrap(struct pkcs11_provider k11->keyid = xmalloc(k11->keyid_len); memcpy(k11->keyid, keyid_attrib->pValue, k11->keyid_len); @@ -1751,7 +1747,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c EC_KEY_set_method(ec, ec_key_method); EC_KEY_set_ex_data(ec, ec_key_idx, k11); -@@ -650,8 +806,8 @@ pkcs11_open_session(struct pkcs11_provid +@@ -650,8 +803,8 @@ pkcs11_open_session(struct pkcs11_provid CK_SESSION_HANDLE session; int login_required, ret; @@ -1762,7 +1758,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c login_required = si->token.flags & CKF_LOGIN_REQUIRED; -@@ -661,9 +817,9 @@ pkcs11_open_session(struct pkcs11_provid +@@ -661,9 +814,9 @@ pkcs11_open_session(struct pkcs11_provid error("pin required"); return (-SSH_PKCS11_ERR_PIN_REQUIRED); } @@ -1774,7 +1770,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c return (-1); } if (login_required && pin != NULL && strlen(pin) != 0) { -@@ -699,7 +855,8 @@ static struct sshkey * +@@ -699,7 +852,8 @@ static struct sshkey * pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, CK_OBJECT_HANDLE *obj) { @@ -1784,7 +1780,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c CK_SESSION_HANDLE session; CK_FUNCTION_LIST *f = NULL; CK_RV rv; -@@ -713,14 +870,15 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_ +@@ -713,14 +867,15 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_ memset(&key_attr, 0, sizeof(key_attr)); key_attr[0].type = CKA_ID; @@ -1805,7 +1801,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c if (rv != CKR_OK) { error("C_GetAttributeValue failed: %lu", rv); return (NULL); -@@ -731,19 +889,19 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_ +@@ -731,19 +886,19 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_ * ensure that none of the others are zero length. * XXX assumes CKA_ID is always first. */ @@ -1829,7 +1825,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c if (rv != CKR_OK) { error("C_GetAttributeValue failed: %lu", rv); goto fail; -@@ -755,8 +913,8 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_ +@@ -755,8 +910,8 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_ goto fail; } @@ -1840,7 +1836,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c if (group == NULL) { ossl_error("d2i_ECPKParameters failed"); goto fail; -@@ -767,13 +925,13 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_ +@@ -767,13 +922,13 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_ goto fail; } @@ -1857,7 +1853,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c if (octet == NULL) { ossl_error("d2i_ASN1_OCTET_STRING failed"); goto fail; -@@ -790,7 +948,7 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_ +@@ -790,7 +945,7 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_ goto fail; } @@ -1866,7 +1862,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c goto fail; key = sshkey_new(KEY_UNSPEC); -@@ -806,7 +964,7 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_ +@@ -806,7 +961,7 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_ ec = NULL; /* now owned by key */ fail: @@ -1875,7 +1871,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c free(key_attr[i].pValue); if (ec) EC_KEY_free(ec); -@@ -823,7 +981,8 @@ static struct sshkey * +@@ -823,7 +978,8 @@ static struct sshkey * pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, CK_OBJECT_HANDLE *obj) { @@ -1885,7 +1881,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c CK_SESSION_HANDLE session; CK_FUNCTION_LIST *f = NULL; CK_RV rv; -@@ -834,14 +993,15 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_pr +@@ -834,14 +990,15 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_pr memset(&key_attr, 0, sizeof(key_attr)); key_attr[0].type = CKA_ID; @@ -1906,7 +1902,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c if (rv != CKR_OK) { error("C_GetAttributeValue failed: %lu", rv); return (NULL); -@@ -852,19 +1012,19 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_pr +@@ -852,19 +1009,19 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_pr * ensure that none of the others are zero length. * XXX assumes CKA_ID is always first. */ @@ -1930,7 +1926,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c if (rv != CKR_OK) { error("C_GetAttributeValue failed: %lu", rv); goto fail; -@@ -876,8 +1036,8 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_pr +@@ -876,8 +1033,8 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_pr goto fail; } @@ -1941,7 +1937,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c if (rsa_n == NULL || rsa_e == NULL) { error("BN_bin2bn failed"); goto fail; -@@ -886,7 +1046,7 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_pr +@@ -886,7 +1043,7 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_pr fatal_f("set key"); rsa_n = rsa_e = NULL; /* transferred */ @@ -1950,7 +1946,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c goto fail; key = sshkey_new(KEY_UNSPEC); -@@ -901,7 +1061,7 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_pr +@@ -901,7 +1058,7 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_pr rsa = NULL; /* now owned by key */ fail: @@ -1959,7 +1955,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c free(key_attr[i].pValue); RSA_free(rsa); -@@ -912,7 +1072,8 @@ static int +@@ -912,7 +1069,8 @@ static int pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, CK_OBJECT_HANDLE *obj, struct sshkey **keyp, char **labelp) { @@ -1969,7 +1965,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c CK_SESSION_HANDLE session; CK_FUNCTION_LIST *f = NULL; CK_RV rv; -@@ -936,14 +1097,15 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p +@@ -936,14 +1094,15 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p memset(&cert_attr, 0, sizeof(cert_attr)); cert_attr[0].type = CKA_ID; @@ -1990,7 +1986,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c if (rv != CKR_OK) { error("C_GetAttributeValue failed: %lu", rv); return -1; -@@ -955,18 +1117,19 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p +@@ -955,18 +1114,19 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p * XXX assumes CKA_ID is always first. */ if (cert_attr[1].ulValueLen == 0 || @@ -2013,7 +2009,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c if (rv != CKR_OK) { error("C_GetAttributeValue failed: %lu", rv); goto out; -@@ -980,8 +1143,8 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p +@@ -980,8 +1140,8 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p subject = xstrdup("invalid subject"); X509_NAME_free(x509_name); @@ -2024,7 +2020,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c error("d2i_x509 failed"); goto out; } -@@ -1001,7 +1164,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p +@@ -1001,7 +1161,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p goto out; } @@ -2033,7 +2029,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c goto out; key = sshkey_new(KEY_UNSPEC); -@@ -1031,7 +1194,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p +@@ -1031,7 +1191,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p goto out; } @@ -2042,7 +2038,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c goto out; key = sshkey_new(KEY_UNSPEC); -@@ -1051,7 +1214,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p +@@ -1051,7 +1211,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p goto out; } out: @@ -2051,7 +2047,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c free(cert_attr[i].pValue); X509_free(x509); RSA_free(rsa); -@@ -1102,11 +1265,12 @@ note_key(struct pkcs11_provider *p, CK_U +@@ -1102,11 +1262,12 @@ note_key(struct pkcs11_provider *p, CK_U */ static int pkcs11_fetch_certs(struct pkcs11_provider *p, CK_ULONG slotidx, @@ -2066,7 +2062,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c CK_SESSION_HANDLE session; CK_FUNCTION_LIST *f = NULL; CK_RV rv; -@@ -1123,10 +1287,23 @@ pkcs11_fetch_certs(struct pkcs11_provide +@@ -1123,10 +1284,23 @@ pkcs11_fetch_certs(struct pkcs11_provide key_attr[0].pValue = &key_class; key_attr[0].ulValueLen = sizeof(key_class); @@ -2093,7 +2089,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c if (rv != CKR_OK) { error("C_FindObjectsInit failed: %lu", rv); goto fail; -@@ -1207,11 +1384,12 @@ fail: +@@ -1207,11 +1381,12 @@ fail: */ static int pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx, @@ -2108,7 +2104,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c CK_SESSION_HANDLE session; CK_FUNCTION_LIST *f = NULL; CK_RV rv; -@@ -1227,10 +1405,23 @@ pkcs11_fetch_keys(struct pkcs11_provider +@@ -1227,10 +1402,23 @@ pkcs11_fetch_keys(struct pkcs11_provider key_attr[0].pValue = &key_class; key_attr[0].ulValueLen = sizeof(key_class); @@ -2154,7 +2150,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c int ret = -1; struct pkcs11_provider *p = NULL; void *handle = NULL; -@@ -1517,164 +1702,298 @@ pkcs11_register_provider(char *provider_ +@@ -1517,164 +1699,298 @@ pkcs11_register_provider(char *provider_ CK_FUNCTION_LIST *f = NULL; CK_TOKEN_INFO *token; CK_ULONG i; @@ -2528,7 +2524,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c /* no keys found or some other error, de-register provider */ if (nkeys <= 0 && p != NULL) { -@@ -1683,7 +2002,37 @@ pkcs11_add_provider(char *provider_id, c +@@ -1683,7 +1999,37 @@ pkcs11_add_provider(char *provider_id, c pkcs11_provider_unref(p); } if (nkeys == 0) @@ -2567,9 +2563,9 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c return (nkeys); } -diff -up openssh-8.7p1/ssh-pkcs11.h.pkcs11-uri openssh-8.7p1/ssh-pkcs11.h ---- openssh-8.7p1/ssh-pkcs11.h.pkcs11-uri 2021-08-20 06:03:49.000000000 +0200 -+++ openssh-8.7p1/ssh-pkcs11.h 2021-08-30 13:07:43.666700121 +0200 +diff -up openssh-8.6p1/ssh-pkcs11.h.pkcs11-uri openssh-8.6p1/ssh-pkcs11.h +--- openssh-8.6p1/ssh-pkcs11.h.pkcs11-uri 2021-04-16 05:55:25.000000000 +0200 ++++ openssh-8.6p1/ssh-pkcs11.h 2021-05-06 11:35:55.115653297 +0200 @@ -22,10 +22,14 @@ #define SSH_PKCS11_ERR_PIN_REQUIRED 4 #define SSH_PKCS11_ERR_PIN_LOCKED 5 @@ -2585,9 +2581,9 @@ diff -up openssh-8.7p1/ssh-pkcs11.h.pkcs11-uri openssh-8.7p1/ssh-pkcs11.h #ifdef WITH_PKCS11_KEYGEN struct sshkey * pkcs11_gakp(char *, char *, unsigned int, char *, unsigned int, -diff -up openssh-8.7p1/ssh-pkcs11-uri.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11-uri.c ---- openssh-8.7p1/ssh-pkcs11-uri.c.pkcs11-uri 2021-08-30 13:07:43.667700130 +0200 -+++ openssh-8.7p1/ssh-pkcs11-uri.c 2021-08-30 13:07:43.667700130 +0200 +diff -up openssh-8.6p1/ssh-pkcs11-uri.c.pkcs11-uri openssh-8.6p1/ssh-pkcs11-uri.c +--- openssh-8.6p1/ssh-pkcs11-uri.c.pkcs11-uri 2021-05-06 11:35:55.114653289 +0200 ++++ openssh-8.6p1/ssh-pkcs11-uri.c 2021-05-06 11:35:55.114653289 +0200 @@ -0,0 +1,419 @@ +/* + * Copyright (c) 2017 Red Hat @@ -3008,9 +3004,9 @@ diff -up openssh-8.7p1/ssh-pkcs11-uri.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11-uri. +} + +#endif /* ENABLE_PKCS11 */ -diff -up openssh-8.7p1/ssh-pkcs11-uri.h.pkcs11-uri openssh-8.7p1/ssh-pkcs11-uri.h ---- openssh-8.7p1/ssh-pkcs11-uri.h.pkcs11-uri 2021-08-30 13:07:43.667700130 +0200 -+++ openssh-8.7p1/ssh-pkcs11-uri.h 2021-08-30 13:07:43.667700130 +0200 +diff -up openssh-8.6p1/ssh-pkcs11-uri.h.pkcs11-uri openssh-8.6p1/ssh-pkcs11-uri.h +--- openssh-8.6p1/ssh-pkcs11-uri.h.pkcs11-uri 2021-05-06 11:35:55.114653289 +0200 ++++ openssh-8.6p1/ssh-pkcs11-uri.h 2021-05-06 11:35:55.114653289 +0200 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2017 Red Hat diff --git a/openssh-8.0p1-sshbuf-readonly.patch b/openssh-8.0p1-sshbuf-readonly.patch deleted file mode 100644 index edc8bec..0000000 --- a/openssh-8.0p1-sshbuf-readonly.patch +++ /dev/null @@ -1,152 +0,0 @@ -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.7p1-upstream-cve-2021-41617.patch b/openssh-8.7p1-upstream-cve-2021-41617.patch index 0bca544..15d49f2 100644 --- a/openssh-8.7p1-upstream-cve-2021-41617.patch +++ b/openssh-8.7p1-upstream-cve-2021-41617.patch @@ -2,12 +2,6 @@ diff --git a/misc.c b/misc.c index b8d1040d..0134d694 100644 --- a/misc.c +++ b/misc.c -@@ -1,4 +1,4 @@ --/* $OpenBSD: misc.c,v 1.169 2021/08/09 23:47:44 djm Exp $ */ -+/* $OpenBSD: misc.c,v 1.170 2021/09/26 14:01:03 djm Exp $ */ - /* - * Copyright (c) 2000 Markus Friedl. All rights reserved. - * Copyright (c) 2005-2020 Damien Miller. All rights reserved. @@ -56,6 +56,7 @@ #ifdef HAVE_PATHS_H # include From 3cf1c29c91429cee117b7317a628228b66a40595 Mon Sep 17 00:00:00 2001 From: Mattias Ellert Date: Sat, 12 Feb 2022 19:44:55 +0100 Subject: [PATCH 02/11] Based on openssh-8.7p1-6.el9 --- gsi-openssh.spec | 12 ++- openssh-8.7p1-find-principals-fix.patch | 13 +++ openssh-8.7p1-minimize-sha1-use.patch | 102 ++++++++++++++++++++++++ 3 files changed, 126 insertions(+), 1 deletion(-) create mode 100644 openssh-8.7p1-find-principals-fix.patch create mode 100644 openssh-8.7p1-minimize-sha1-use.patch diff --git a/gsi-openssh.spec b/gsi-openssh.spec index 183be66..4513644 100644 --- a/gsi-openssh.spec +++ b/gsi-openssh.spec @@ -28,7 +28,7 @@ %global libedit 1 %global openssh_ver 8.7p1 -%global openssh_rel 3 +%global openssh_rel 4 Summary: An implementation of the SSH protocol with GSI authentication Name: gsi-openssh @@ -155,6 +155,10 @@ Patch976: openssh-8.7p1-sftp-default-protocol.patch Patch977: openssh-8.7p1-scp-kill-switch.patch # CVE-2021-41617 Patch978: openssh-8.7p1-upstream-cve-2021-41617.patch +# fix for `ssh-keygen -Y find-principals -f /dev/null -s /dev/null` (#2024902) +Patch979: openssh-8.7p1-find-principals-fix.patch + +Patch1000: openssh-8.7p1-minimize-sha1-use.patch # This is the patch that adds GSI support # Based on hpn_isshd-gsi.7.5p1b.patch from Globus upstream @@ -302,11 +306,14 @@ gpgv2 --quiet --keyring %{SOURCE3} %{SOURCE1} %{SOURCE0} %patch976 -p1 -b .sftp-by-default %patch977 -p1 -b .kill-scp %patch978 -p1 -b .cve-2021-41617 +%patch979 -p1 -b .find-principals %patch200 -p1 -b .audit %patch201 -p1 -b .audit-race %patch700 -p1 -b .fips +%patch1000 -p1 -b .minsha1 + %patch100 -p1 -b .coverity %patch98 -p1 -b .gsi @@ -497,6 +504,9 @@ getent passwd sshd >/dev/null || \ %attr(0644,root,root) %{_unitdir}/gsisshd-keygen.target %changelog +* Sat Feb 12 2022 Mattias Ellert - 8.7p1-4 +- Based on openssh-8.7p1-6.el9 + * Fri Dec 31 2021 Mattias Ellert - 8.7p1-3 - Based on openssh-8.7p1-4.el9 - Drop patch openssh-8.0p1-sshbuf-readonly.patch (now included in diff --git a/openssh-8.7p1-find-principals-fix.patch b/openssh-8.7p1-find-principals-fix.patch new file mode 100644 index 0000000..4c6594b --- /dev/null +++ b/openssh-8.7p1-find-principals-fix.patch @@ -0,0 +1,13 @@ +diff -up openssh-8.7p1/ssh-keygen.c.find-princ openssh-8.7p1/ssh-keygen.c +--- openssh-8.7p1/ssh-keygen.c.find-princ 2021-11-29 15:27:03.032070863 +0100 ++++ openssh-8.7p1/ssh-keygen.c 2021-11-29 15:27:34.736342968 +0100 +@@ -2700,7 +2700,8 @@ sig_process_opts(char * const *opts, siz + time_t now; + + *verify_timep = 0; +- *print_pubkey = 0; ++ if (print_pubkey) ++ *print_pubkey = 0; + for (i = 0; i < nopts; i++) { + if (strncasecmp(opts[i], "verify-time=", 12) == 0) { + if (parse_absolute_time(opts[i] + 12, diff --git a/openssh-8.7p1-minimize-sha1-use.patch b/openssh-8.7p1-minimize-sha1-use.patch new file mode 100644 index 0000000..519b8f4 --- /dev/null +++ b/openssh-8.7p1-minimize-sha1-use.patch @@ -0,0 +1,102 @@ +diff -up openssh-8.7p1/kex.c.minsha1 openssh-8.7p1/kex.c +--- openssh-8.7p1/kex.c.minsha1 2021-12-20 17:38:51.438294309 +0100 ++++ openssh-8.7p1/kex.c 2021-12-21 11:02:48.379991319 +0100 +@@ -994,6 +994,35 @@ kex_choose_conf(struct ssh *ssh) + free(ext); + } + ++ /* Check whether client supports rsa-sha2 algorithms */ ++ if (kex->server && (kex->flags & KEX_INITIAL)) { ++ char *ext; ++ ++ ext = match_list("rsa-sha2-256", peer[PROPOSAL_SERVER_HOST_KEY_ALGS], NULL); ++ if (ext) { ++ kex->flags |= KEX_RSA_SHA2_256_SUPPORTED; ++ free(ext); ++ } ++ ++ ext = match_list("rsa-sha2-512", peer[PROPOSAL_SERVER_HOST_KEY_ALGS], NULL); ++ if (ext) { ++ kex->flags |= KEX_RSA_SHA2_512_SUPPORTED; ++ free(ext); ++ } ++ ++ ext = match_list("rsa-sha2-256-cert-v01@openssh.com", peer[PROPOSAL_SERVER_HOST_KEY_ALGS], NULL); ++ if (ext) { ++ kex->flags |= KEX_RSA_SHA2_256_SUPPORTED; ++ free(ext); ++ } ++ ++ ext = match_list("rsa-sha2-512-cert-v01@openssh.com", peer[PROPOSAL_SERVER_HOST_KEY_ALGS], NULL); ++ if (ext) { ++ kex->flags |= KEX_RSA_SHA2_512_SUPPORTED; ++ free(ext); ++ } ++ } ++ + /* Algorithm Negotiation */ + if ((r = choose_kex(kex, cprop[PROPOSAL_KEX_ALGS], + sprop[PROPOSAL_KEX_ALGS])) != 0) { +diff -up openssh-8.7p1/kex.h.minsha1 openssh-8.7p1/kex.h +--- openssh-8.7p1/kex.h.minsha1 2021-12-20 17:38:51.430294240 +0100 ++++ openssh-8.7p1/kex.h 2021-12-21 10:56:29.066735608 +0100 +@@ -116,6 +116,8 @@ enum kex_exchange { + + #define KEX_INIT_SENT 0x0001 + #define KEX_INITIAL 0x0002 ++#define KEX_RSA_SHA2_256_SUPPORTED 0x0004 ++#define KEX_RSA_SHA2_512_SUPPORTED 0x0008 + + struct sshenc { + char *name; +diff -up openssh-8.7p1/serverloop.c.minsha1 openssh-8.7p1/serverloop.c +--- openssh-8.7p1/serverloop.c.minsha1 2021-08-20 06:03:49.000000000 +0200 ++++ openssh-8.7p1/serverloop.c 2021-12-21 11:01:00.594047538 +0100 +@@ -684,7 +685,7 @@ server_input_hostkeys_prove(struct ssh * + struct sshbuf *resp = NULL; + struct sshbuf *sigbuf = NULL; + struct sshkey *key = NULL, *key_pub = NULL, *key_prv = NULL; +- int r, ndx, kexsigtype, use_kexsigtype, success = 0; ++ int r, ndx, success = 0; + const u_char *blob; + u_char *sig = 0; + size_t blen, slen; +@@ -692,9 +693,11 @@ server_input_hostkeys_prove(struct ssh * + if ((resp = sshbuf_new()) == NULL || (sigbuf = sshbuf_new()) == NULL) + fatal_f("sshbuf_new"); + +- kexsigtype = sshkey_type_plain( +- sshkey_type_from_name(ssh->kex->hostkey_alg)); + while (ssh_packet_remaining(ssh) > 0) { ++ const char *pkexstr = NULL; ++ const char *rsa_sha2_256 = "rsa-sha2-256"; ++ const char *rsa_sha2_512 = "rsa-sha2-512"; ++ + sshkey_free(key); + key = NULL; + if ((r = sshpkt_get_string_direct(ssh, &blob, &blen)) != 0 || +@@ -726,8 +729,13 @@ server_input_hostkeys_prove(struct ssh * + * For RSA keys, prefer to use the signature type negotiated + * during KEX to the default (SHA1). + */ +- use_kexsigtype = kexsigtype == KEY_RSA && +- sshkey_type_plain(key->type) == KEY_RSA; ++ if (sshkey_type_plain(key->type) == KEY_RSA) { ++ if (ssh->kex->flags & KEX_RSA_SHA2_512_SUPPORTED) ++ pkexstr = rsa_sha2_512; ++ else if (ssh->kex->flags & KEX_RSA_SHA2_256_SUPPORTED) ++ pkexstr = rsa_sha2_256; ++ } ++ + if ((r = sshbuf_put_cstring(sigbuf, + "hostkeys-prove-00@openssh.com")) != 0 || + (r = sshbuf_put_stringb(sigbuf, +@@ -735,7 +743,7 @@ server_input_hostkeys_prove(struct ssh * + (r = sshkey_puts(key, sigbuf)) != 0 || + (r = ssh->kex->sign(ssh, key_prv, key_pub, &sig, &slen, + sshbuf_ptr(sigbuf), sshbuf_len(sigbuf), +- use_kexsigtype ? ssh->kex->hostkey_alg : NULL)) != 0 || ++ pkexstr)) != 0 || + (r = sshbuf_put_string(resp, sig, slen)) != 0) { + error_fr(r, "assemble signature"); + goto out; From 63e0c449d380ac85a87ea11417779c03c74941aa Mon Sep 17 00:00:00 2001 From: Mattias Ellert Date: Wed, 6 Apr 2022 16:11:26 +0200 Subject: [PATCH 03/11] Based on openssh-8.7p1-8.el9 --- gsi-openssh.spec | 18 ++- openssh-8.7p1-recursive-scp.patch | 174 +++++++++++++++++++++++++ openssh-8.7p1-sftpscp-dir-create.patch | 167 ++++++++++++++++++++++++ 3 files changed, 358 insertions(+), 1 deletion(-) create mode 100644 openssh-8.7p1-recursive-scp.patch create mode 100644 openssh-8.7p1-sftpscp-dir-create.patch diff --git a/gsi-openssh.spec b/gsi-openssh.spec index 4513644..f0fc765 100644 --- a/gsi-openssh.spec +++ b/gsi-openssh.spec @@ -28,7 +28,7 @@ %global libedit 1 %global openssh_ver 8.7p1 -%global openssh_rel 4 +%global openssh_rel 5 Summary: An implementation of the SSH protocol with GSI authentication Name: gsi-openssh @@ -157,6 +157,17 @@ Patch977: openssh-8.7p1-scp-kill-switch.patch Patch978: openssh-8.7p1-upstream-cve-2021-41617.patch # fix for `ssh-keygen -Y find-principals -f /dev/null -s /dev/null` (#2024902) Patch979: openssh-8.7p1-find-principals-fix.patch +# Create non-existent directories when scp works in sftp mode and some more minor fixes +# upstream commits: +# ba61123eef9c6356d438c90c1199a57a0d7bcb0a +# 63670d4e9030bcee490d5a9cce561373ac5b3b23 +# ac7c9ec894ed0825d04ef69c55babb49bab1d32e +Patch980: openssh-8.7p1-sftpscp-dir-create.patch +# Workaround for lack of sftp_realpath in older versions of RHEL +# https://bugzilla.redhat.com/show_bug.cgi?id=2038854 +# https://github.com/openssh/openssh-portable/pull/299 +# downstream only +Patch981: openssh-8.7p1-recursive-scp.patch Patch1000: openssh-8.7p1-minimize-sha1-use.patch @@ -307,6 +318,8 @@ gpgv2 --quiet --keyring %{SOURCE3} %{SOURCE1} %{SOURCE0} %patch977 -p1 -b .kill-scp %patch978 -p1 -b .cve-2021-41617 %patch979 -p1 -b .find-principals +%patch980 -p1 -b .sftpdirs +%patch981 -p1 -b .scp-sftpdirs %patch200 -p1 -b .audit %patch201 -p1 -b .audit-race @@ -504,6 +517,9 @@ getent passwd sshd >/dev/null || \ %attr(0644,root,root) %{_unitdir}/gsisshd-keygen.target %changelog +* Wed Apr 06 2022 Mattias Ellert - 8.7p1-5 +- Based on openssh-8.7p1-8.el9 + * Sat Feb 12 2022 Mattias Ellert - 8.7p1-4 - Based on openssh-8.7p1-6.el9 diff --git a/openssh-8.7p1-recursive-scp.patch b/openssh-8.7p1-recursive-scp.patch new file mode 100644 index 0000000..25765fb --- /dev/null +++ b/openssh-8.7p1-recursive-scp.patch @@ -0,0 +1,174 @@ +diff -up openssh-8.7p1/scp.c.scp-sftpdirs openssh-8.7p1/scp.c +--- openssh-8.7p1/scp.c.scp-sftpdirs 2022-02-07 12:31:07.407740407 +0100 ++++ openssh-8.7p1/scp.c 2022-02-07 12:31:07.409740424 +0100 +@@ -1324,7 +1324,7 @@ source_sftp(int argc, char *src, char *t + + if (src_is_dir && iamrecursive) { + if (upload_dir(conn, src, abs_dst, pflag, +- SFTP_PROGRESS_ONLY, 0, 0, 1) != 0) { ++ SFTP_PROGRESS_ONLY, 0, 0, 1, 1) != 0) { + error("failed to upload directory %s to %s", + src, abs_dst); + errs = 1; +diff -up openssh-8.7p1/sftp-client.c.scp-sftpdirs openssh-8.7p1/sftp-client.c +--- openssh-8.7p1/sftp-client.c.scp-sftpdirs 2021-08-20 06:03:49.000000000 +0200 ++++ openssh-8.7p1/sftp-client.c 2022-02-07 12:47:59.117516131 +0100 +@@ -971,7 +971,7 @@ do_fsetstat(struct sftp_conn *conn, cons + + /* Implements both the realpath and expand-path operations */ + static char * +-do_realpath_expand(struct sftp_conn *conn, const char *path, int expand) ++do_realpath_expand(struct sftp_conn *conn, const char *path, int expand, int create_dir) + { + struct sshbuf *msg; + u_int expected_id, count, id; +@@ -1012,9 +1012,38 @@ do_realpath_expand(struct sftp_conn *con + + if ((r = sshbuf_get_u32(msg, &status)) != 0) + fatal_fr(r, "parse status"); +- error("Couldn't canonicalize: %s", fx2txt(status)); +- sshbuf_free(msg); +- return NULL; ++ if ((status == SSH2_FX_NO_SUCH_FILE) && create_dir) { ++ memset(&a, '\0', sizeof(a)); ++ if ((r = do_mkdir(conn, path, &a, 0)) != 0) { ++ sshbuf_free(msg); ++ return NULL; ++ } ++ ++ send_string_request(conn, id, SSH2_FXP_REALPATH, ++ path, strlen(path)); ++ ++ get_msg(conn, msg); ++ if ((r = sshbuf_get_u8(msg, &type)) != 0 || ++ (r = sshbuf_get_u32(msg, &id)) != 0) ++ fatal_fr(r, "parse"); ++ ++ if (id != expected_id) ++ fatal("ID mismatch (%u != %u)", id, expected_id); ++ ++ if (type == SSH2_FXP_STATUS) { ++ u_int status; ++ ++ if ((r = sshbuf_get_u32(msg, &status)) != 0) ++ fatal_fr(r, "parse status"); ++ error("Couldn't canonicalize: %s", fx2txt(status)); ++ sshbuf_free(msg); ++ return NULL; ++ } ++ } else { ++ error("Couldn't canonicalize: %s", fx2txt(status)); ++ sshbuf_free(msg); ++ return NULL; ++ } + } else if (type != SSH2_FXP_NAME) + fatal("Expected SSH2_FXP_NAME(%u) packet, got %u", + SSH2_FXP_NAME, type); +@@ -1039,9 +1067,9 @@ do_realpath_expand(struct sftp_conn *con + } + + char * +-do_realpath(struct sftp_conn *conn, const char *path) ++do_realpath(struct sftp_conn *conn, const char *path, int create_dir) + { +- return do_realpath_expand(conn, path, 0); ++ return do_realpath_expand(conn, path, 0, create_dir); + } + + int +@@ -1055,9 +1083,9 @@ do_expand_path(struct sftp_conn *conn, c + { + if (!can_expand_path(conn)) { + debug3_f("no server support, fallback to realpath"); +- return do_realpath_expand(conn, path, 0); ++ return do_realpath_expand(conn, path, 0, 0); + } +- return do_realpath_expand(conn, path, 1); ++ return do_realpath_expand(conn, path, 1, 0); + } + + int +@@ -1807,7 +1835,7 @@ download_dir(struct sftp_conn *conn, con + char *src_canon; + int ret; + +- if ((src_canon = do_realpath(conn, src)) == NULL) { ++ if ((src_canon = do_realpath(conn, src, 0)) == NULL) { + error("Unable to canonicalize path \"%s\"", src); + return -1; + } +@@ -2115,12 +2143,12 @@ upload_dir_internal(struct sftp_conn *co + int + upload_dir(struct sftp_conn *conn, const char *src, const char *dst, + int preserve_flag, int print_flag, int resume, int fsync_flag, +- int follow_link_flag) ++ int follow_link_flag, int create_dir) + { + char *dst_canon; + int ret; + +- if ((dst_canon = do_realpath(conn, dst)) == NULL) { ++ if ((dst_canon = do_realpath(conn, dst, create_dir)) == NULL) { + error("Unable to canonicalize path \"%s\"", dst); + return -1; + } +@@ -2557,7 +2585,7 @@ crossload_dir(struct sftp_conn *from, st + char *from_path_canon; + int ret; + +- if ((from_path_canon = do_realpath(from, from_path)) == NULL) { ++ if ((from_path_canon = do_realpath(from, from_path, 0)) == NULL) { + error("Unable to canonicalize path \"%s\"", from_path); + return -1; + } +diff -up openssh-8.7p1/sftp-client.h.scp-sftpdirs openssh-8.7p1/sftp-client.h +--- openssh-8.7p1/sftp-client.h.scp-sftpdirs 2021-08-20 06:03:49.000000000 +0200 ++++ openssh-8.7p1/sftp-client.h 2022-02-07 12:31:07.410740433 +0100 +@@ -111,7 +111,7 @@ int do_fsetstat(struct sftp_conn *, cons + int do_lsetstat(struct sftp_conn *conn, const char *path, Attrib *a); + + /* Canonicalise 'path' - caller must free result */ +-char *do_realpath(struct sftp_conn *, const char *); ++char *do_realpath(struct sftp_conn *, const char *, int); + + /* Canonicalisation with tilde expansion (requires server extension) */ + char *do_expand_path(struct sftp_conn *, const char *); +@@ -159,7 +159,7 @@ int do_upload(struct sftp_conn *, const + * times if 'pflag' is set + */ + int upload_dir(struct sftp_conn *, const char *, const char *, int, int, int, +- int, int); ++ int, int, int); + + /* + * Download a 'from_path' from the 'from' connection and upload it to +diff -up openssh-8.7p1/sftp.c.scp-sftpdirs openssh-8.7p1/sftp.c +--- openssh-8.7p1/sftp.c.scp-sftpdirs 2021-08-20 06:03:49.000000000 +0200 ++++ openssh-8.7p1/sftp.c 2022-02-07 12:31:07.411740442 +0100 +@@ -760,7 +760,7 @@ process_put(struct sftp_conn *conn, cons + if (globpath_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) { + if (upload_dir(conn, g.gl_pathv[i], abs_dst, + pflag || global_pflag, 1, resume, +- fflag || global_fflag, 0) == -1) ++ fflag || global_fflag, 0, 0) == -1) + err = -1; + } else { + if (do_upload(conn, g.gl_pathv[i], abs_dst, +@@ -1577,7 +1577,7 @@ parse_dispatch_command(struct sftp_conn + if (path1 == NULL || *path1 == '\0') + path1 = xstrdup(startdir); + path1 = make_absolute(path1, *pwd); +- if ((tmp = do_realpath(conn, path1)) == NULL) { ++ if ((tmp = do_realpath(conn, path1, 0)) == NULL) { + err = 1; + break; + } +@@ -2160,7 +2160,7 @@ interactive_loop(struct sftp_conn *conn, + } + #endif /* USE_LIBEDIT */ + +- remote_path = do_realpath(conn, "."); ++ remote_path = do_realpath(conn, ".", 0); + if (remote_path == NULL) + fatal("Need cwd"); + startdir = xstrdup(remote_path); diff --git a/openssh-8.7p1-sftpscp-dir-create.patch b/openssh-8.7p1-sftpscp-dir-create.patch new file mode 100644 index 0000000..a549170 --- /dev/null +++ b/openssh-8.7p1-sftpscp-dir-create.patch @@ -0,0 +1,167 @@ +diff -up openssh-8.7p1/scp.c.sftpdirs openssh-8.7p1/scp.c +--- openssh-8.7p1/scp.c.sftpdirs 2022-02-02 14:11:12.553447509 +0100 ++++ openssh-8.7p1/scp.c 2022-02-02 14:12:56.081316414 +0100 +@@ -130,6 +130,7 @@ + #include "misc.h" + #include "progressmeter.h" + #include "utf8.h" ++#include "sftp.h" + + #include "sftp-common.h" + #include "sftp-client.h" +@@ -660,7 +661,7 @@ main(int argc, char **argv) + * Finally check the exit status of the ssh process, if one was forked + * and no error has occurred yet + */ +- if (do_cmd_pid != -1 && errs == 0) { ++ if (do_cmd_pid != -1 && (mode == MODE_SFTP || errs == 0)) { + if (remin != -1) + (void) close(remin); + if (remout != -1) +@@ -1264,13 +1265,18 @@ tolocal(int argc, char **argv, enum scp_ + static char * + prepare_remote_path(struct sftp_conn *conn, const char *path) + { ++ size_t nslash; ++ + /* Handle ~ prefixed paths */ +- if (*path != '~') +- return xstrdup(path); + if (*path == '\0' || strcmp(path, "~") == 0) + return xstrdup("."); +- if (strncmp(path, "~/", 2) == 0) +- return xstrdup(path + 2); ++ if (*path != '~') ++ return xstrdup(path); ++ if (strncmp(path, "~/", 2) == 0) { ++ if ((nslash = strspn(path + 2, "/")) == strlen(path + 2)) ++ return xstrdup("."); ++ return xstrdup(path + 2 + nslash); ++ } + if (can_expand_path(conn)) + return do_expand_path(conn, path); + /* No protocol extension */ +@@ -1282,10 +1288,16 @@ void + source_sftp(int argc, char *src, char *targ, struct sftp_conn *conn) + { + char *target = NULL, *filename = NULL, *abs_dst = NULL; +- int target_is_dir; +- ++ int src_is_dir, target_is_dir; ++ Attrib a; ++ struct stat st; ++ ++ memset(&a, '\0', sizeof(a)); ++ if (stat(src, &st) != 0) ++ fatal("stat local \"%s\": %s", src, strerror(errno)); ++ src_is_dir = S_ISDIR(st.st_mode); + if ((filename = basename(src)) == NULL) +- fatal("basename %s: %s", src, strerror(errno)); ++ fatal("basename \"%s\": %s", src, strerror(errno)); + + /* + * No need to glob here - the local shell already took care of +@@ -1295,8 +1307,12 @@ source_sftp(int argc, char *src, char *t + cleanup_exit(255); + target_is_dir = remote_is_dir(conn, target); + if (targetshouldbedirectory && !target_is_dir) { +- fatal("Target is not a directory, but more files selected " +- "for upload"); ++ debug("target directory \"%s\" does not exist", target); ++ a.flags = SSH2_FILEXFER_ATTR_PERMISSIONS; ++ a.perm = st.st_mode | 0700; /* ensure writable */ ++ if (do_mkdir(conn, target, &a, 1) != 0) ++ cleanup_exit(255); /* error already logged */ ++ target_is_dir = 1; + } + if (target_is_dir) + abs_dst = path_append(target, filename); +@@ -1306,14 +1322,17 @@ source_sftp(int argc, char *src, char *t + } + debug3_f("copying local %s to remote %s", src, abs_dst); + +- if (local_is_dir(src) && iamrecursive) { ++ if (src_is_dir && iamrecursive) { + if (upload_dir(conn, src, abs_dst, pflag, + SFTP_PROGRESS_ONLY, 0, 0, 1) != 0) { +- fatal("failed to upload directory %s to %s", ++ error("failed to upload directory %s to %s", + src, abs_dst); ++ errs = 1; + } +- } else if (do_upload(conn, src, abs_dst, pflag, 0, 0) != 0) +- fatal("failed to upload file %s to %s", src, abs_dst); ++ } else if (do_upload(conn, src, abs_dst, pflag, 0, 0) != 0) { ++ error("failed to upload file %s to %s", src, abs_dst); ++ errs = 1; ++ } + + free(abs_dst); + free(target); +@@ -1487,14 +1506,15 @@ sink_sftp(int argc, char *dst, const cha + char *abs_dst = NULL; + glob_t g; + char *filename, *tmp = NULL; +- int i, r, err = 0; ++ int i, r, err = 0, dst_is_dir; ++ struct stat st; + + memset(&g, 0, sizeof(g)); ++ + /* + * Here, we need remote glob as SFTP can not depend on remote shell + * expansions + */ +- + if ((abs_src = prepare_remote_path(conn, src)) == NULL) { + err = -1; + goto out; +@@ -1510,11 +1530,24 @@ sink_sftp(int argc, char *dst, const cha + goto out; + } + +- if (g.gl_matchc > 1 && !local_is_dir(dst)) { +- error("Multiple files match pattern, but destination " +- "\"%s\" is not a directory", dst); +- err = -1; +- goto out; ++ if ((r = stat(dst, &st)) != 0) ++ debug2_f("stat local \"%s\": %s", dst, strerror(errno)); ++ dst_is_dir = r == 0 && S_ISDIR(st.st_mode); ++ ++ if (g.gl_matchc > 1 && !dst_is_dir) { ++ if (r == 0) { ++ error("Multiple files match pattern, but destination " ++ "\"%s\" is not a directory", dst); ++ err = -1; ++ goto out; ++ } ++ debug2_f("creating destination \"%s\"", dst); ++ if (mkdir(dst, 0777) != 0) { ++ error("local mkdir \"%s\": %s", dst, strerror(errno)); ++ err = -1; ++ goto out; ++ } ++ dst_is_dir = 1; + } + + for (i = 0; g.gl_pathv[i] && !interrupted; i++) { +@@ -1525,7 +1558,7 @@ sink_sftp(int argc, char *dst, const cha + goto out; + } + +- if (local_is_dir(dst)) ++ if (dst_is_dir) + abs_dst = path_append(dst, filename); + else + abs_dst = xstrdup(dst); +@@ -1551,7 +1584,8 @@ out: + free(tmp); + globfree(&g); + if (err == -1) { +- fatal("Failed to download file '%s'", src); ++ error("Failed to download '%s'", src); ++ errs = 1; + } + } + From 9c5ea6a6a248cca5237f94b331261bacf0b97628 Mon Sep 17 00:00:00 2001 From: Mattias Ellert Date: Wed, 21 Sep 2022 16:12:35 +0200 Subject: [PATCH 04/11] Based on openssh-8.7p1-10.el9_0 --- gsi-openssh.spec | 10 +- openssh-6.7p1-coverity.patch | 2 +- openssh-8.7p1-hpn-15.2-modified.patch | 8 + openssh-8.7p1-scp-clears-file.patch | 304 ++++++++++++++++++++++++++ 4 files changed, 322 insertions(+), 2 deletions(-) create mode 100644 openssh-8.7p1-scp-clears-file.patch diff --git a/gsi-openssh.spec b/gsi-openssh.spec index f0fc765..803d345 100644 --- a/gsi-openssh.spec +++ b/gsi-openssh.spec @@ -28,7 +28,7 @@ %global libedit 1 %global openssh_ver 8.7p1 -%global openssh_rel 5 +%global openssh_rel 6 Summary: An implementation of the SSH protocol with GSI authentication Name: gsi-openssh @@ -170,6 +170,10 @@ Patch980: openssh-8.7p1-sftpscp-dir-create.patch Patch981: openssh-8.7p1-recursive-scp.patch Patch1000: openssh-8.7p1-minimize-sha1-use.patch +# Fix for scp clearing file when src and dest are the same (#2108409) +# upstream commits: +# 7b1cbcb7599d9f6a3bbad79d412604aa1203b5ee +Patch1001: openssh-8.7p1-scp-clears-file.patch # This is the patch that adds GSI support # Based on hpn_isshd-gsi.7.5p1b.patch from Globus upstream @@ -326,6 +330,7 @@ gpgv2 --quiet --keyring %{SOURCE3} %{SOURCE1} %{SOURCE0} %patch700 -p1 -b .fips %patch1000 -p1 -b .minsha1 +%patch1001 -p1 -b .scp-clears-file %patch100 -p1 -b .coverity @@ -517,6 +522,9 @@ getent passwd sshd >/dev/null || \ %attr(0644,root,root) %{_unitdir}/gsisshd-keygen.target %changelog +* Wed Sep 21 2022 Mattias Ellert - 8.7p1-6 +- Based on openssh-8.7p1-10.el9_0 + * Wed Apr 06 2022 Mattias Ellert - 8.7p1-5 - Based on openssh-8.7p1-8.el9 diff --git a/openssh-6.7p1-coverity.patch b/openssh-6.7p1-coverity.patch index 6852384..28632e0 100644 --- a/openssh-6.7p1-coverity.patch +++ b/openssh-6.7p1-coverity.patch @@ -405,7 +405,7 @@ diff -up openssh-7.4p1/sftp.c.coverity openssh-7.4p1/sftp.c _exit(1); @@ -762,6 +762,8 @@ process_put(struct sftp_conn *conn, cons - fflag || global_fflag) == -1) + fflag || global_fflag, 0) == -1) err = -1; } + free(abs_dst); diff --git a/openssh-8.7p1-hpn-15.2-modified.patch b/openssh-8.7p1-hpn-15.2-modified.patch index 75a4908..fcc0e40 100644 --- a/openssh-8.7p1-hpn-15.2-modified.patch +++ b/openssh-8.7p1-hpn-15.2-modified.patch @@ -1517,6 +1517,14 @@ diff -Nur openssh-8.7p1.orig/packet.c openssh-8.7p1/packet.c /* * Logs the error plus constructs and sends a disconnect packet, closes the * connection, and exits. This function never returns. The error message +@@ -1991,6 +2047,7 @@ + return SSH_ERR_CONN_CLOSED; + if ((r = sshbuf_consume(state->output, len)) != 0) + return r; ++ ssh->stdin_bytes += len; + } + return 0; + } @@ -2794,3 +2850,10 @@ ssh->state->extra_pad = pad; return 0; diff --git a/openssh-8.7p1-scp-clears-file.patch b/openssh-8.7p1-scp-clears-file.patch new file mode 100644 index 0000000..4c033da --- /dev/null +++ b/openssh-8.7p1-scp-clears-file.patch @@ -0,0 +1,304 @@ +diff --color -rup a/scp.c b/scp.c +--- a/scp.c 2022-07-26 14:51:40.560120817 +0200 ++++ b/scp.c 2022-07-26 14:52:37.118213004 +0200 +@@ -1324,12 +1324,12 @@ source_sftp(int argc, char *src, char *t + + if (src_is_dir && iamrecursive) { + if (upload_dir(conn, src, abs_dst, pflag, +- SFTP_PROGRESS_ONLY, 0, 0, 1, 1) != 0) { ++ SFTP_PROGRESS_ONLY, 0, 0, 1, 1, 1) != 0) { + error("failed to upload directory %s to %s", + src, abs_dst); + errs = 1; + } +- } else if (do_upload(conn, src, abs_dst, pflag, 0, 0) != 0) { ++ } else if (do_upload(conn, src, abs_dst, pflag, 0, 0, 1) != 0) { + error("failed to upload file %s to %s", src, abs_dst); + errs = 1; + } +@@ -1566,11 +1566,11 @@ sink_sftp(int argc, char *dst, const cha + debug("Fetching %s to %s\n", g.gl_pathv[i], abs_dst); + if (globpath_is_dir(g.gl_pathv[i]) && iamrecursive) { + if (download_dir(conn, g.gl_pathv[i], abs_dst, NULL, +- pflag, SFTP_PROGRESS_ONLY, 0, 0, 1) == -1) ++ pflag, SFTP_PROGRESS_ONLY, 0, 0, 1, 1) == -1) + err = -1; + } else { + if (do_download(conn, g.gl_pathv[i], abs_dst, NULL, +- pflag, 0, 0) == -1) ++ pflag, 0, 0, 1) == -1) + err = -1; + } + free(abs_dst); +diff --color -rup a/sftp.c b/sftp.c +--- a/sftp.c 2022-07-26 14:51:40.561120836 +0200 ++++ b/sftp.c 2022-07-26 14:52:37.119213023 +0200 +@@ -666,12 +666,12 @@ process_get(struct sftp_conn *conn, cons + if (globpath_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) { + if (download_dir(conn, g.gl_pathv[i], abs_dst, NULL, + pflag || global_pflag, 1, resume, +- fflag || global_fflag, 0) == -1) ++ fflag || global_fflag, 0, 0) == -1) + err = -1; + } else { + if (do_download(conn, g.gl_pathv[i], abs_dst, NULL, + pflag || global_pflag, resume, +- fflag || global_fflag) == -1) ++ fflag || global_fflag, 0) == -1) + err = -1; + } + free(abs_dst); +@@ -760,12 +760,12 @@ process_put(struct sftp_conn *conn, cons + if (globpath_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) { + if (upload_dir(conn, g.gl_pathv[i], abs_dst, + pflag || global_pflag, 1, resume, +- fflag || global_fflag, 0, 0) == -1) ++ fflag || global_fflag, 0, 0, 0) == -1) + err = -1; + } else { + if (do_upload(conn, g.gl_pathv[i], abs_dst, + pflag || global_pflag, resume, +- fflag || global_fflag) == -1) ++ fflag || global_fflag, 0) == -1) + err = -1; + } + } +diff --color -rup a/sftp-client.c b/sftp-client.c +--- a/sftp-client.c 2022-07-26 14:51:40.561120836 +0200 ++++ b/sftp-client.c 2022-07-26 15:09:54.825295533 +0200 +@@ -1454,7 +1454,7 @@ progress_meter_path(const char *path) + int + do_download(struct sftp_conn *conn, const char *remote_path, + const char *local_path, Attrib *a, int preserve_flag, int resume_flag, +- int fsync_flag) ++ int fsync_flag, int inplace_flag) + { + struct sshbuf *msg; + u_char *handle; +@@ -1498,8 +1498,8 @@ do_download(struct sftp_conn *conn, cons + &handle, &handle_len) != 0) + return -1; + +- local_fd = open(local_path, +- O_WRONLY | O_CREAT | (resume_flag ? 0 : O_TRUNC), mode | S_IWUSR); ++ local_fd = open(local_path, O_WRONLY | O_CREAT | ++ ((resume_flag || inplace_flag) ? 0 : O_TRUNC), mode | S_IWUSR); + if (local_fd == -1) { + error("Couldn't open local file \"%s\" for writing: %s", + local_path, strerror(errno)); +@@ -1661,8 +1661,11 @@ do_download(struct sftp_conn *conn, cons + /* Sanity check */ + if (TAILQ_FIRST(&requests) != NULL) + fatal("Transfer complete, but requests still in queue"); +- /* Truncate at highest contiguous point to avoid holes on interrupt */ +- if (read_error || write_error || interrupted) { ++ /* ++ * Truncate at highest contiguous point to avoid holes on interrupt, ++ * or unconditionally if writing in place. ++ */ ++ if (inplace_flag || read_error || write_error || interrupted) { + if (reordered && resume_flag) { + error("Unable to resume download of \"%s\": " + "server reordered requests", local_path); +@@ -1724,7 +1727,7 @@ do_download(struct sftp_conn *conn, cons + static int + download_dir_internal(struct sftp_conn *conn, const char *src, const char *dst, + int depth, Attrib *dirattrib, int preserve_flag, int print_flag, +- int resume_flag, int fsync_flag, int follow_link_flag) ++ int resume_flag, int fsync_flag, int follow_link_flag, int inplace_flag) + { + int i, ret = 0; + SFTP_DIRENT **dir_entries; +@@ -1781,7 +1784,7 @@ download_dir_internal(struct sftp_conn * + if (download_dir_internal(conn, new_src, new_dst, + depth + 1, &(dir_entries[i]->a), preserve_flag, + print_flag, resume_flag, +- fsync_flag, follow_link_flag) == -1) ++ fsync_flag, follow_link_flag, inplace_flag) == -1) + ret = -1; + } else if (S_ISREG(dir_entries[i]->a.perm) || + (follow_link_flag && S_ISLNK(dir_entries[i]->a.perm))) { +@@ -1793,7 +1796,8 @@ download_dir_internal(struct sftp_conn * + if (do_download(conn, new_src, new_dst, + S_ISLNK(dir_entries[i]->a.perm) ? NULL : + &(dir_entries[i]->a), +- preserve_flag, resume_flag, fsync_flag) == -1) { ++ preserve_flag, resume_flag, fsync_flag, ++ inplace_flag) == -1) { + error("Download of file %s to %s failed", + new_src, new_dst); + ret = -1; +@@ -1831,7 +1835,7 @@ download_dir_internal(struct sftp_conn * + int + download_dir(struct sftp_conn *conn, const char *src, const char *dst, + Attrib *dirattrib, int preserve_flag, int print_flag, int resume_flag, +- int fsync_flag, int follow_link_flag) ++ int fsync_flag, int follow_link_flag, int inplace_flag) + { + char *src_canon; + int ret; +@@ -1843,26 +1847,25 @@ download_dir(struct sftp_conn *conn, con + + ret = download_dir_internal(conn, src_canon, dst, 0, + dirattrib, preserve_flag, print_flag, resume_flag, fsync_flag, +- follow_link_flag); ++ follow_link_flag, inplace_flag); + free(src_canon); + return ret; + } + + int + do_upload(struct sftp_conn *conn, const char *local_path, +- const char *remote_path, int preserve_flag, int resume, int fsync_flag) ++ const char *remote_path, int preserve_flag, int resume, ++ int fsync_flag, int inplace_flag) + { + int r, local_fd; +- u_int status = SSH2_FX_OK; +- u_int id; +- u_char type; ++ u_int openmode, id, status = SSH2_FX_OK, reordered = 0; + off_t offset, progress_counter; +- u_char *handle, *data; ++ u_char type, *handle, *data; + struct sshbuf *msg; + struct stat sb; +- Attrib a, *c = NULL; +- u_int32_t startid; +- u_int32_t ackid; ++ Attrib a, t, *c = NULL; ++ u_int32_t startid, ackid; ++ u_int64_t highwater = 0; + struct request *ack = NULL; + struct requests acks; + size_t handle_len; +@@ -1913,10 +1916,15 @@ do_upload(struct sftp_conn *conn, const + } + } + ++ openmode = SSH2_FXF_WRITE|SSH2_FXF_CREAT; ++ if (resume) ++ openmode |= SSH2_FXF_APPEND; ++ else if (!inplace_flag) ++ openmode |= SSH2_FXF_TRUNC; ++ + /* Send open request */ +- if (send_open(conn, remote_path, "dest", SSH2_FXF_WRITE|SSH2_FXF_CREAT| +- (resume ? SSH2_FXF_APPEND : SSH2_FXF_TRUNC), +- &a, &handle, &handle_len) != 0) { ++ if (send_open(conn, remote_path, "dest", openmode, &a, ++ &handle, &handle_len) != 0) { + close(local_fd); + return -1; + } +@@ -1999,6 +2007,12 @@ do_upload(struct sftp_conn *conn, const + ack->id, ack->len, (unsigned long long)ack->offset); + ++ackid; + progress_counter += ack->len; ++ if (!reordered && ack->offset <= highwater) ++ highwater = ack->offset + ack->len; ++ else if (!reordered && ack->offset > highwater) { ++ debug3_f("server reordered ACKs"); ++ reordered = 1; ++ } + free(ack); + } + offset += len; +@@ -2017,6 +2031,14 @@ do_upload(struct sftp_conn *conn, const + status = SSH2_FX_FAILURE; + } + ++ if (inplace_flag || (resume && (status != SSH2_FX_OK || interrupted))) { ++ debug("truncating at %llu", (unsigned long long)highwater); ++ attrib_clear(&t); ++ t.flags = SSH2_FILEXFER_ATTR_SIZE; ++ t.size = highwater; ++ do_fsetstat(conn, handle, handle_len, &t); ++ } ++ + if (close(local_fd) == -1) { + error("Couldn't close local file \"%s\": %s", local_path, + strerror(errno)); +@@ -2041,7 +2063,7 @@ do_upload(struct sftp_conn *conn, const + static int + upload_dir_internal(struct sftp_conn *conn, const char *src, const char *dst, + int depth, int preserve_flag, int print_flag, int resume, int fsync_flag, +- int follow_link_flag) ++ int follow_link_flag, int inplace_flag) + { + int ret = 0; + DIR *dirp; +@@ -2119,12 +2141,13 @@ upload_dir_internal(struct sftp_conn *co + + if (upload_dir_internal(conn, new_src, new_dst, + depth + 1, preserve_flag, print_flag, resume, +- fsync_flag, follow_link_flag) == -1) ++ fsync_flag, follow_link_flag, inplace_flag) == -1) + ret = -1; + } else if (S_ISREG(sb.st_mode) || + (follow_link_flag && S_ISLNK(sb.st_mode))) { + if (do_upload(conn, new_src, new_dst, +- preserve_flag, resume, fsync_flag) == -1) { ++ preserve_flag, resume, fsync_flag, ++ inplace_flag) == -1) { + error("Uploading of file %s to %s failed!", + new_src, new_dst); + ret = -1; +@@ -2144,7 +2167,7 @@ upload_dir_internal(struct sftp_conn *co + int + upload_dir(struct sftp_conn *conn, const char *src, const char *dst, + int preserve_flag, int print_flag, int resume, int fsync_flag, +- int follow_link_flag, int create_dir) ++ int follow_link_flag, int create_dir, int inplace_flag) + { + char *dst_canon; + int ret; +@@ -2155,7 +2178,7 @@ upload_dir(struct sftp_conn *conn, const + } + + ret = upload_dir_internal(conn, src, dst_canon, 0, preserve_flag, +- print_flag, resume, fsync_flag, follow_link_flag); ++ print_flag, resume, fsync_flag, follow_link_flag, inplace_flag); + + free(dst_canon); + return ret; +diff --color -rup a/sftp-client.h b/sftp-client.h +--- a/sftp-client.h 2022-07-26 14:51:40.561120836 +0200 ++++ b/sftp-client.h 2022-07-26 14:52:37.120213042 +0200 +@@ -138,28 +138,29 @@ int do_fsync(struct sftp_conn *conn, u_c + * Download 'remote_path' to 'local_path'. Preserve permissions and times + * if 'pflag' is set + */ +-int do_download(struct sftp_conn *, const char *, const char *, +- Attrib *, int, int, int); ++int do_download(struct sftp_conn *, const char *, const char *, Attrib *, ++ int, int, int, int); + + /* + * Recursively download 'remote_directory' to 'local_directory'. Preserve + * times if 'pflag' is set + */ +-int download_dir(struct sftp_conn *, const char *, const char *, +- Attrib *, int, int, int, int, int); ++int download_dir(struct sftp_conn *, const char *, const char *, Attrib *, ++ int, int, int, int, int, int); + + /* + * Upload 'local_path' to 'remote_path'. Preserve permissions and times + * if 'pflag' is set + */ +-int do_upload(struct sftp_conn *, const char *, const char *, int, int, int); ++int do_upload(struct sftp_conn *, const char *, const char *, ++ int, int, int, int); + + /* + * Recursively upload 'local_directory' to 'remote_directory'. Preserve + * times if 'pflag' is set + */ +-int upload_dir(struct sftp_conn *, const char *, const char *, int, int, int, +- int, int, int); ++int upload_dir(struct sftp_conn *, const char *, const char *, ++ int, int, int, int, int, int, int); + + /* + * Download a 'from_path' from the 'from' connection and upload it to From a103a892352b3150a6a0b71a379bf1c4f39b5983 Mon Sep 17 00:00:00 2001 From: Mattias Ellert Date: Sat, 8 Oct 2022 11:26:58 +0200 Subject: [PATCH 05/11] Based on openssh-8.7p1-24.el9 --- gsi-openssh.spec | 54 ++- openssh-6.7p1-coverity.patch | 36 +- openssh-7.7p1-fips.patch | 229 +++++++++- openssh-7.8p1-UsePAM-warning.patch | 6 +- openssh-8.0p1-crypto-policies.patch | 74 +-- openssh-8.7p1-evpgenkey.patch | 110 +++++ openssh-8.7p1-gssapi-auth.patch | 20 + openssh-8.7p1-host-based-auth.patch | 151 +++++++ openssh-8.7p1-hpn-15.2-modified.patch | 10 +- openssh-8.7p1-ibmca.patch | 12 + openssh-8.7p1-mem-leak.patch | 156 +++++++ openssh-8.7p1-minimize-sha1-use.patch | 209 ++++++--- openssh-8.7p1-minrsabits.patch | 446 +++++++++++++++++++ openssh-8.7p1-negotiate-supported-algs.patch | 63 +++ openssh-8.7p1-ssh-manpage.patch | 53 +++ 15 files changed, 1474 insertions(+), 155 deletions(-) create mode 100644 openssh-8.7p1-evpgenkey.patch create mode 100644 openssh-8.7p1-gssapi-auth.patch create mode 100644 openssh-8.7p1-host-based-auth.patch create mode 100644 openssh-8.7p1-ibmca.patch create mode 100644 openssh-8.7p1-mem-leak.patch create mode 100644 openssh-8.7p1-minrsabits.patch create mode 100644 openssh-8.7p1-negotiate-supported-algs.patch create mode 100644 openssh-8.7p1-ssh-manpage.patch diff --git a/gsi-openssh.spec b/gsi-openssh.spec index 803d345..5ad48af 100644 --- a/gsi-openssh.spec +++ b/gsi-openssh.spec @@ -28,7 +28,7 @@ %global libedit 1 %global openssh_ver 8.7p1 -%global openssh_rel 6 +%global openssh_rel 7 Summary: An implementation of the SSH protocol with GSI authentication Name: gsi-openssh @@ -168,12 +168,49 @@ Patch980: openssh-8.7p1-sftpscp-dir-create.patch # https://github.com/openssh/openssh-portable/pull/299 # downstream only Patch981: openssh-8.7p1-recursive-scp.patch +# https://github.com/djmdjm/openssh-wip/pull/13 +Patch982: openssh-8.7p1-minrsabits.patch +# downstream only +Patch983: openssh-8.7p1-evpgenkey.patch +# downstream only, IBMCA tentative fix +# From https://bugzilla.redhat.com/show_bug.cgi?id=1976202#c14 +Patch984: openssh-8.7p1-ibmca.patch +# Minimize the use of SHA1 as a proof of possession for RSA key (#2031868) +# upstream commits: +# 291721bc7c840d113a49518f3fca70e86248b8e8 +# 0fa33683223c76289470a954404047bc762be84c +# Avoid dubious diagnostics on update known hosts (#2115246) +# 8832402bd500d1661ccc80a476fd563335ef6cdc Patch1000: openssh-8.7p1-minimize-sha1-use.patch -# Fix for scp clearing file when src and dest are the same (#2108409) +# Fix for scp clearing file when src and dest are the same (#2056884) # upstream commits: # 7b1cbcb7599d9f6a3bbad79d412604aa1203b5ee Patch1001: openssh-8.7p1-scp-clears-file.patch +# Add missing options from ssh_config into ssh manpage +# upstream bug: +# https://bugzilla.mindrot.org/show_bug.cgi?id=3455 +Patch1002: openssh-8.7p1-ssh-manpage.patch +# Always return allocated strings from the kex filtering so that we can free them +# upstream commits: +# 486c4dc3b83b4b67d663fb0fa62bc24138ec3946 +# 6c31ba10e97b6953c4f325f526f3e846dfea647a +# 322964f8f2e9c321e77ebae1e4d2cd0ccc5c5a0b +Patch1003: openssh-8.7p1-mem-leak.patch +# Reenable MONITOR_REQ_GSSCHECKMIC after gssapi-with-mic failures +# upstream MR: +# https://github.com/openssh-gsskex/openssh-gsskex/pull/21 +Patch1004: openssh-8.7p1-gssapi-auth.patch +# Fix host-based authentication with rsa keys +# upstream commits: +# 7aa7b096cf2bafe2777085abdeed5ce00581f641 +# d9dbb5d9a0326e252d3c7bc13beb9c2434f59409 +# fdb1d58d0d3888b042e5a500f6ce524486aaf782 +Patch1005: openssh-8.7p1-host-based-auth.patch +# Don't propose disallowed algorithms during hostkey negotiation +# upstream MR: +# https://github.com/openssh/openssh-portable/pull/323 +Patch1006: openssh-8.7p1-negotiate-supported-algs.patch # This is the patch that adds GSI support # Based on hpn_isshd-gsi.7.5p1b.patch from Globus upstream @@ -324,13 +361,21 @@ gpgv2 --quiet --keyring %{SOURCE3} %{SOURCE1} %{SOURCE0} %patch979 -p1 -b .find-principals %patch980 -p1 -b .sftpdirs %patch981 -p1 -b .scp-sftpdirs +%patch982 -p1 -b .minrsabits +%patch983 -p1 -b .evpgenrsa +%patch984 -p1 -b .ibmca %patch200 -p1 -b .audit %patch201 -p1 -b .audit-race %patch700 -p1 -b .fips -%patch1000 -p1 -b .minsha1 +%patch1000 -p1 -b .minimize-sha1-use %patch1001 -p1 -b .scp-clears-file +%patch1002 -p1 -b .ssh-manpage +%patch1003 -p1 -b .mem-leak +%patch1004 -p1 -b .gssapi-auth +%patch1005 -p1 -b .host-based-auth +%patch1006 -p1 -b .negotiate-supported-algs %patch100 -p1 -b .coverity @@ -522,6 +567,9 @@ getent passwd sshd >/dev/null || \ %attr(0644,root,root) %{_unitdir}/gsisshd-keygen.target %changelog +* Wed Oct 05 2022 Mattias Ellert - 8.7p1-7 +- Based on openssh-8.7p1-24.el9 + * Wed Sep 21 2022 Mattias Ellert - 8.7p1-6 - Based on openssh-8.7p1-10.el9_0 diff --git a/openssh-6.7p1-coverity.patch b/openssh-6.7p1-coverity.patch index 28632e0..e372f09 100644 --- a/openssh-6.7p1-coverity.patch +++ b/openssh-6.7p1-coverity.patch @@ -101,22 +101,6 @@ diff -up openssh-7.4p1/channels.c.coverity openssh-7.4p1/channels.c return idx; } -diff -up openssh-8.5p1/compat.c.coverity openssh-8.5p1/compat.c ---- openssh-8.5p1/compat.c.coverity 2021-03-24 12:03:33.768968062 +0100 -+++ openssh-8.5p1/compat.c 2021-03-24 12:03:33.783968166 +0100 -@@ -191,10 +191,12 @@ compat_kex_proposal(struct ssh *ssh, cha - return p; - debug2_f("original KEX proposal: %s", p); - if ((ssh->compat & SSH_BUG_CURVE25519PAD) != 0) -+ /* coverity[overwrite_var : FALSE] */ - if ((p = match_filter_denylist(p, - "curve25519-sha256@libssh.org")) == NULL) - fatal("match_filter_denylist failed"); - if ((ssh->compat & SSH_OLD_DHGEX) != 0) { -+ /* coverity[overwrite_var : FALSE] */ - if ((p = match_filter_denylist(p, - "diffie-hellman-group-exchange-sha256," - "diffie-hellman-group-exchange-sha1")) == NULL) diff -up openssh-8.5p1/dns.c.coverity openssh-8.5p1/dns.c --- openssh-8.5p1/dns.c.coverity 2021-03-02 11:31:47.000000000 +0100 +++ openssh-8.5p1/dns.c 2021-03-24 12:03:33.783968166 +0100 @@ -392,10 +376,9 @@ diff -up openssh-8.5p1/session.c.coverity openssh-8.5p1/session.c } /* SSH_CLIENT deprecated */ -diff -up openssh-7.4p1/sftp.c.coverity openssh-7.4p1/sftp.c ---- openssh-7.4p1/sftp.c.coverity 2016-12-19 05:59:41.000000000 +0100 -+++ openssh-7.4p1/sftp.c 2016-12-23 16:40:26.903788691 +0100 -@@ -224,7 +224,7 @@ killchild(int signo) +--- a/sftp.c 2022-06-30 10:43:13.914058913 +0200 ++++ b/sftp.c 2022-06-30 10:48:17.243997888 +0200 +@@ -222,7 +222,7 @@ killchild(int signo) pid = sshpid; if (pid > 1) { kill(pid, SIGTERM); @@ -404,7 +387,7 @@ diff -up openssh-7.4p1/sftp.c.coverity openssh-7.4p1/sftp.c } _exit(1); -@@ -762,6 +762,8 @@ process_put(struct sftp_conn *conn, cons +@@ -768,6 +768,8 @@ process_put(struct sftp_conn *conn, cons fflag || global_fflag, 0) == -1) err = -1; } @@ -413,7 +396,7 @@ diff -up openssh-7.4p1/sftp.c.coverity openssh-7.4p1/sftp.c } out: -@@ -985,6 +987,7 @@ do_globbed_ls(struct sftp_conn *conn, co +@@ -991,6 +993,7 @@ do_globbed_ls(struct sftp_conn *conn, co if (lflag & LS_LONG_VIEW) { if (g.gl_statv[i] == NULL) { error("no stat information for %s", fname); @@ -514,15 +497,6 @@ diff -up openssh-7.4p1/sshd.c.coverity openssh-7.4p1/sshd.c } /* -@@ -2474,7 +2479,7 @@ do_ssh2_kex(struct ssh *ssh) - if (options.rekey_limit || options.rekey_interval) - ssh_packet_set_rekey_limits(ssh, options.rekey_limit, - options.rekey_interval); -- -+ /* coverity[leaked_storage : FALSE]*/ - myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = compat_pkalg_proposal( - ssh, list_hostkey_types()); - @@ -2519,8 +2524,11 @@ do_ssh2_kex(struct ssh *ssh) if (newstr) diff --git a/openssh-7.7p1-fips.patch b/openssh-7.7p1-fips.patch index 6e72d04..1466b40 100644 --- a/openssh-7.7p1-fips.patch +++ b/openssh-7.7p1-fips.patch @@ -1,16 +1,3 @@ -diff -up openssh-8.6p1/cipher-ctr.c.fips openssh-8.6p1/cipher-ctr.c ---- openssh-8.6p1/cipher-ctr.c.fips 2021-05-06 12:08:36.423926297 +0200 -+++ openssh-8.6p1/cipher-ctr.c 2021-05-06 12:08:36.497926869 +0200 -@@ -179,7 +179,8 @@ evp_aes_128_ctr(void) - 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; -+ EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV | -+ EVP_CIPH_FLAG_FIPS; - #endif - return (&aes_ctr); - } diff -up openssh-8.6p1/dh.c.fips openssh-8.6p1/dh.c --- openssh-8.6p1/dh.c.fips 2021-04-16 05:55:25.000000000 +0200 +++ openssh-8.6p1/dh.c 2021-05-06 12:12:10.107634472 +0200 @@ -19,7 +6,7 @@ diff -up openssh-8.6p1/dh.c.fips openssh-8.6p1/dh.c struct dhgroup dhg; + if (FIPS_mode()) { -+ logit("Using arbitrary primes is not allowed in FIPS mode." ++ verbose("Using arbitrary primes is not allowed in FIPS mode." + " Falling back to known groups."); + return (dh_new_group_fallback(max)); + } @@ -117,7 +104,7 @@ diff -up openssh-8.6p1/kexgexc.c.fips openssh-8.6p1/kexgexc.c diff -up openssh-8.6p1/myproposal.h.fips openssh-8.6p1/myproposal.h --- openssh-8.6p1/myproposal.h.fips 2021-04-16 05:55:25.000000000 +0200 +++ openssh-8.6p1/myproposal.h 2021-05-06 12:08:36.498926877 +0200 -@@ -57,6 +57,20 @@ +@@ -57,6 +57,18 @@ "rsa-sha2-256," \ "ssh-rsa" @@ -127,13 +114,11 @@ diff -up openssh-8.6p1/myproposal.h.fips openssh-8.6p1/myproposal.h + "ecdsa-sha2-nistp521-cert-v01@openssh.com," \ + "rsa-sha2-512-cert-v01@openssh.com," \ + "rsa-sha2-256-cert-v01@openssh.com," \ -+ "ssh-rsa-cert-v01@openssh.com," \ + "ecdsa-sha2-nistp256," \ + "ecdsa-sha2-nistp384," \ + "ecdsa-sha2-nistp521," \ + "rsa-sha2-512," \ -+ "rsa-sha2-256," \ -+ "ssh-rsa" ++ "rsa-sha2-256" + #define KEX_SERVER_ENCRYPT \ "chacha20-poly1305@openssh.com," \ @@ -359,6 +344,20 @@ diff -up openssh-8.6p1/sshd.c.fips openssh-8.6p1/sshd.c /* Save argv. Duplicate so setproctitle emulation doesn't clobber it */ saved_argc = ac; rexec_argc = ac; +@@ -1931,6 +1931,13 @@ main(int ac, char **av) + &key, NULL)) != 0 && r != SSH_ERR_SYSTEM_ERROR) + do_log2_r(r, ll, "Unable to load host key \"%s\"", + options.host_key_files[i]); ++ if (FIPS_mode() && key != NULL && (sshkey_type_plain(key->type) == KEY_ED25519_SK ++ || sshkey_type_plain(key->type) == KEY_ED25519)) { ++ logit_f("sshd: Ed25519 keys are not allowed in FIPS mode, skipping %s", options.host_key_files[i]); ++ sshkey_free(key); ++ key = NULL; ++ continue; ++ } + if (sshkey_is_sk(key) && + key->sk_flags & SSH_SK_USER_PRESENCE_REQD) { + debug("host key %s requires user presence, ignoring", @@ -2110,6 +2113,10 @@ main(int ac, char **av) /* Reinitialize the log (because of the fork above). */ log_init(__progname, options.log_level, options.log_facility, log_stderr); @@ -408,15 +407,78 @@ diff -up openssh-8.6p1/sshkey.c.fips openssh-8.6p1/sshkey.c #include "ssh-sk.h" #ifdef WITH_XMSS -@@ -1705,6 +1707,8 @@ rsa_generate_private_key(u_int bits, RSA +@@ -285,6 +285,18 @@ sshkey_alg_list(int certs_only, int plai + for (kt = keytypes; kt->type != -1; kt++) { + if (kt->name == NULL || kt->type == KEY_NULL) + continue; ++ if (FIPS_mode()) { ++ switch (kt->type) { ++ case KEY_ED25519: ++ case KEY_ED25519_SK: ++ case KEY_ED25519_CERT: ++ case KEY_ED25519_SK_CERT: ++ continue; ++ break; ++ default: ++ break; ++ } ++ } + if (!include_sigonly && kt->sigonly) + continue; + if ((certs_only && !kt->cert) || (plain_only && kt->cert)) +@@ -1503,6 +1503,20 @@ sshkey_read(struct sshkey *ret, char **c + return SSH_ERR_EC_CURVE_MISMATCH; } - if (!BN_set_word(f4, RSA_F4) || - !RSA_generate_key_ex(private, bits, f4, NULL)) { -+ if (FIPS_mode()) -+ logit_f("the key length might be unsupported by FIPS mode approved key generation method"); + ++ switch (type) { ++ case KEY_ED25519: ++ case KEY_ED25519_SK: ++ case KEY_ED25519_CERT: ++ case KEY_ED25519_SK_CERT: ++ if (FIPS_mode()) { ++ sshkey_free(k); ++ logit_f("Ed25519 keys are not allowed in FIPS mode"); ++ return SSH_ERR_INVALID_ARGUMENT; ++ } ++ break; ++ default: ++ break; ++ } + /* Fill in ret from parsed key */ + ret->type = type; + if (sshkey_is_cert(ret)) { +@@ -1705,6 +1707,8 @@ rsa_generate_private_key(u_int bits, RSA + goto out; + + if (EVP_PKEY_keygen(ctx, &res) <= 0) { ++ if (FIPS_mode()) ++ logit_f("the key length might be unsupported by FIPS mode approved key generation method"); ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } +@@ -2916,6 +2916,11 @@ sshkey_sign(struct sshkey *key, + break; + case KEY_ED25519_SK: + case KEY_ED25519_SK_CERT: ++ if (FIPS_mode()) { ++ logit_f("Ed25519 keys are not allowed in FIPS mode"); ++ return SSH_ERR_INVALID_ARGUMENT; ++ } ++ /* Fallthrough */ + case KEY_ECDSA_SK_CERT: + case KEY_ECDSA_SK: + r = sshsk_sign(sk_provider, key, sigp, lenp, data, +@@ -2973,6 +2978,10 @@ sshkey_verify(const struct sshkey *key, + return ssh_ed25519_verify(key, sig, siglen, data, dlen, compat); + case KEY_ED25519_SK: + case KEY_ED25519_SK_CERT: ++ if (FIPS_mode()) { ++ logit_f("Ed25519 keys are not allowed in FIPS mode"); ++ return SSH_ERR_INVALID_ARGUMENT; ++ } + return ssh_ed25519_sk_verify(key, sig, siglen, data, dlen, + compat, detailsp); + #ifdef WITH_XMSS diff -up openssh-8.6p1/ssh-keygen.c.fips openssh-8.6p1/ssh-keygen.c --- openssh-8.6p1/ssh-keygen.c.fips 2021-05-06 12:08:36.467926637 +0200 +++ openssh-8.6p1/ssh-keygen.c 2021-05-06 12:08:36.503926916 +0200 @@ -427,7 +489,7 @@ diff -up openssh-8.6p1/ssh-keygen.c.fips openssh-8.6p1/ssh-keygen.c + if (FIPS_mode()) { + if (type == KEY_DSA) + fatal("DSA keys are not allowed in FIPS mode"); -+ if (type == KEY_ED25519) ++ if (type == KEY_ED25519 || type == KEY_ED25519_SK) + fatal("ED25519 keys are not allowed in FIPS mode"); + } switch (type) { @@ -452,3 +514,122 @@ diff -up openssh-8.6p1/ssh-keygen.c.fips openssh-8.6p1/ssh-keygen.c if ((fd = mkstemp(prv_tmp)) == -1) { error("Could not save your private key in %s: %s", prv_tmp, strerror(errno)); +diff -up openssh-8.7p1/kexgen.c.fips3 openssh-8.7p1/kexgen.c +--- openssh-8.7p1/kexgen.c.fips3 2022-07-11 16:11:21.973519913 +0200 ++++ openssh-8.7p1/kexgen.c 2022-07-11 16:25:31.172187365 +0200 +@@ -31,6 +31,7 @@ + #include + #include + #include ++#include + + #include "sshkey.h" + #include "kex.h" +@@ -115,10 +116,20 @@ kex_gen_client(struct ssh *ssh) + break; + #endif + case KEX_C25519_SHA256: +- r = kex_c25519_keypair(kex); ++ if (FIPS_mode()) { ++ logit_f("Key exchange type c25519 is not allowed in FIPS mode"); ++ r = SSH_ERR_INVALID_ARGUMENT; ++ } else { ++ r = kex_c25519_keypair(kex); ++ } + break; + case KEX_KEM_SNTRUP761X25519_SHA512: +- r = kex_kem_sntrup761x25519_keypair(kex); ++ if (FIPS_mode()) { ++ logit_f("Key exchange type sntrup761 is not allowed in FIPS mode"); ++ r = SSH_ERR_INVALID_ARGUMENT; ++ } else { ++ r = kex_kem_sntrup761x25519_keypair(kex); ++ } + break; + default: + r = SSH_ERR_INVALID_ARGUMENT; +@@ -186,11 +197,21 @@ input_kex_gen_reply(int type, u_int32_t + break; + #endif + case KEX_C25519_SHA256: +- r = kex_c25519_dec(kex, server_blob, &shared_secret); ++ if (FIPS_mode()) { ++ logit_f("Key exchange type c25519 is not allowed in FIPS mode"); ++ r = SSH_ERR_INVALID_ARGUMENT; ++ } else { ++ r = kex_c25519_dec(kex, server_blob, &shared_secret); ++ } + break; + case KEX_KEM_SNTRUP761X25519_SHA512: +- r = kex_kem_sntrup761x25519_dec(kex, server_blob, +- &shared_secret); ++ if (FIPS_mode()) { ++ logit_f("Key exchange type sntrup761 is not allowed in FIPS mode"); ++ r = SSH_ERR_INVALID_ARGUMENT; ++ } else { ++ r = kex_kem_sntrup761x25519_dec(kex, server_blob, ++ &shared_secret); ++ } + break; + default: + r = SSH_ERR_INVALID_ARGUMENT; +@@ -285,12 +306,22 @@ input_kex_gen_init(int type, u_int32_t s + break; + #endif + case KEX_C25519_SHA256: +- r = kex_c25519_enc(kex, client_pubkey, &server_pubkey, +- &shared_secret); ++ if (FIPS_mode()) { ++ logit_f("Key exchange type c25519 is not allowed in FIPS mode"); ++ r = SSH_ERR_INVALID_ARGUMENT; ++ } else { ++ r = kex_c25519_enc(kex, client_pubkey, &server_pubkey, ++ &shared_secret); ++ } + break; + case KEX_KEM_SNTRUP761X25519_SHA512: +- r = kex_kem_sntrup761x25519_enc(kex, client_pubkey, +- &server_pubkey, &shared_secret); ++ if (FIPS_mode()) { ++ logit_f("Key exchange type sntrup761 is not allowed in FIPS mode"); ++ r = SSH_ERR_INVALID_ARGUMENT; ++ } else { ++ r = kex_kem_sntrup761x25519_enc(kex, client_pubkey, ++ &server_pubkey, &shared_secret); ++ } + break; + default: + r = SSH_ERR_INVALID_ARGUMENT; +diff -up openssh-8.7p1/ssh-ed25519.c.fips3 openssh-8.7p1/ssh-ed25519.c +--- openssh-8.7p1/ssh-ed25519.c.fips3 2022-07-11 16:53:41.428343304 +0200 ++++ openssh-8.7p1/ssh-ed25519.c 2022-07-11 16:56:09.284663661 +0200 +@@ -24,6 +24,7 @@ + + #include + #include ++#include + + #include "log.h" + #include "sshbuf.h" +@@ -52,6 +53,10 @@ ssh_ed25519_sign(const struct sshkey *ke + key->ed25519_sk == NULL || + datalen >= INT_MAX - crypto_sign_ed25519_BYTES) + return SSH_ERR_INVALID_ARGUMENT; ++ if (FIPS_mode()) { ++ logit_f("Ed25519 keys are not allowed in FIPS mode"); ++ return SSH_ERR_INVALID_ARGUMENT; ++ } + smlen = slen = datalen + crypto_sign_ed25519_BYTES; + if ((sig = malloc(slen)) == NULL) + return SSH_ERR_ALLOC_FAIL; +@@ -108,6 +113,10 @@ ssh_ed25519_verify(const struct sshkey * + datalen >= INT_MAX - crypto_sign_ed25519_BYTES || + signature == NULL || signaturelen == 0) + return SSH_ERR_INVALID_ARGUMENT; ++ if (FIPS_mode()) { ++ logit_f("Ed25519 keys are not allowed in FIPS mode"); ++ return SSH_ERR_INVALID_ARGUMENT; ++ } + + if ((b = sshbuf_from(signature, signaturelen)) == NULL) + return SSH_ERR_ALLOC_FAIL; diff --git a/openssh-7.8p1-UsePAM-warning.patch b/openssh-7.8p1-UsePAM-warning.patch index 8560c9f..feedcba 100644 --- a/openssh-7.8p1-UsePAM-warning.patch +++ b/openssh-7.8p1-UsePAM-warning.patch @@ -5,9 +5,9 @@ diff -up openssh-8.6p1/sshd.c.log-usepam-no openssh-8.6p1/sshd.c parse_server_config(&options, rexeced_flag ? "rexec" : config_file_name, cfg, &includes, NULL); -+ /* 'UsePAM no' is not supported in Fedora */ ++ /* 'UsePAM no' is not supported in RHEL */ + if (! options.use_pam) -+ logit("WARNING: 'UsePAM no' is not supported in Fedora and may cause several problems."); ++ logit("WARNING: 'UsePAM no' is not supported in RHEL and may cause several problems."); + #ifdef WITH_OPENSSL if (options.moduli_file != NULL) @@ -19,7 +19,7 @@ diff -up openssh-8.6p1/sshd_config.log-usepam-no openssh-8.6p1/sshd_config # If you just want the PAM account and session checks to run without # PAM authentication, then enable this but set PasswordAuthentication # and KbdInteractiveAuthentication to 'no'. -+# WARNING: 'UsePAM no' is not supported in Fedora and may cause several ++# WARNING: 'UsePAM no' is not supported in RHEL and may cause several +# problems. #UsePAM no diff --git a/openssh-8.0p1-crypto-policies.patch b/openssh-8.0p1-crypto-policies.patch index 762825e..502e1de 100644 --- a/openssh-8.0p1-crypto-policies.patch +++ b/openssh-8.0p1-crypto-policies.patch @@ -1,13 +1,13 @@ -diff -up openssh-8.7p1/ssh_config.5.crypto-policies openssh-8.7p1/ssh_config.5 ---- openssh-8.7p1/ssh_config.5.crypto-policies 2021-08-30 13:29:00.174292872 +0200 -+++ openssh-8.7p1/ssh_config.5 2021-08-30 13:31:32.009548808 +0200 -@@ -373,17 +373,13 @@ or +diff --color -ru a/ssh_config.5 b/ssh_config.5 +--- a/ssh_config.5 2022-07-12 15:05:22.550013071 +0200 ++++ b/ssh_config.5 2022-07-12 15:17:20.016704545 +0200 +@@ -373,17 +373,13 @@ .Qq *.c.example.com domains. .It Cm CASignatureAlgorithms +The default is handled system-wide by +.Xr crypto-policies 7 . -+To see the defaults and how to modify this default, see manual page ++Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page +.Xr update-crypto-policies 8 . +.Pp Specifies which algorithms are allowed for signing of certificates @@ -24,13 +24,13 @@ diff -up openssh-8.7p1/ssh_config.5.crypto-policies openssh-8.7p1/ssh_config.5 If the specified list begins with a .Sq + character, then the specified algorithms will be appended to the default set -@@ -445,20 +441,25 @@ If the option is set to +@@ -445,20 +441,25 @@ (the default), the check will not be executed. .It Cm Ciphers +The default is handled system-wide by +.Xr crypto-policies 7 . -+To see the defaults and how to modify this default, see manual page ++Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page +.Xr update-crypto-policies 8 . +.Pp Specifies the ciphers allowed and their order of preference. @@ -54,7 +54,7 @@ diff -up openssh-8.7p1/ssh_config.5.crypto-policies openssh-8.7p1/ssh_config.5 .Pp The supported ciphers are: .Bd -literal -offset indent -@@ -474,13 +475,6 @@ aes256-gcm@openssh.com +@@ -474,13 +475,6 @@ chacha20-poly1305@openssh.com .Ed .Pp @@ -68,19 +68,19 @@ diff -up openssh-8.7p1/ssh_config.5.crypto-policies openssh-8.7p1/ssh_config.5 The list of available ciphers may also be obtained using .Qq ssh -Q cipher . .It Cm ClearAllForwardings -@@ -874,6 +868,11 @@ command line will be passed untouched to +@@ -874,6 +868,11 @@ The default is .Dq no . .It Cm GSSAPIKexAlgorithms +The default is handled system-wide by +.Xr crypto-policies 7 . -+To see the defaults and how to modify this default, see manual page ++Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page +.Xr update-crypto-policies 8 . +.Pp The list of key exchange algorithms that are offered for GSSAPI key exchange. Possible values are .Bd -literal -offset 3n -@@ -886,10 +885,8 @@ gss-nistp256-sha256-, +@@ -886,10 +885,8 @@ gss-curve25519-sha256- .Ed .Pp @@ -92,13 +92,13 @@ diff -up openssh-8.7p1/ssh_config.5.crypto-policies openssh-8.7p1/ssh_config.5 .It Cm HashKnownHosts Indicates that .Xr ssh 1 -@@ -1219,29 +1216,25 @@ it may be zero or more of: +@@ -1219,29 +1216,25 @@ and .Cm pam . .It Cm KexAlgorithms +The default is handled system-wide by +.Xr crypto-policies 7 . -+To see the defaults and how to modify this default, see manual page ++Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page +.Xr update-crypto-policies 8 . +.Pp Specifies the available KEX (Key Exchange) algorithms. @@ -131,13 +131,13 @@ diff -up openssh-8.7p1/ssh_config.5.crypto-policies openssh-8.7p1/ssh_config.5 .Pp The list of available key exchange algorithms may also be obtained using .Qq ssh -Q kex . -@@ -1351,37 +1344,33 @@ function, and all code in the +@@ -1351,37 +1344,33 @@ file. This option is intended for debugging and no overrides are enabled by default. .It Cm MACs +The default is handled system-wide by +.Xr crypto-policies 7 . -+To see the defaults and how to modify this default, see manual page ++Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page +.Xr update-crypto-policies 8 . +.Pp Specifies the MAC (message authentication code) algorithms @@ -178,13 +178,13 @@ diff -up openssh-8.7p1/ssh_config.5.crypto-policies openssh-8.7p1/ssh_config.5 The list of available MAC algorithms may also be obtained using .Qq ssh -Q mac . .It Cm NoHostAuthenticationForLocalhost -@@ -1553,37 +1542,25 @@ instead of continuing to execute and pas +@@ -1553,37 +1542,25 @@ The default is .Cm no . .It Cm PubkeyAcceptedAlgorithms +The default is handled system-wide by +.Xr crypto-policies 7 . -+To see the defaults and how to modify this default, see manual page ++Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page +.Xr update-crypto-policies 8 . +.Pp Specifies the signature algorithms that will be used for public key @@ -225,16 +225,16 @@ diff -up openssh-8.7p1/ssh_config.5.crypto-policies openssh-8.7p1/ssh_config.5 .Pp The list of available signature algorithms may also be obtained using .Qq ssh -Q PubkeyAcceptedAlgorithms . -diff -up openssh-8.7p1/sshd_config.5.crypto-policies openssh-8.7p1/sshd_config.5 ---- openssh-8.7p1/sshd_config.5.crypto-policies 2021-08-30 13:29:00.157292731 +0200 -+++ openssh-8.7p1/sshd_config.5 2021-08-30 13:32:16.263918533 +0200 -@@ -373,17 +373,13 @@ If the argument is +diff --color -ru a/sshd_config.5 b/sshd_config.5 +--- a/sshd_config.5 2022-07-12 15:05:22.535012771 +0200 ++++ b/sshd_config.5 2022-07-12 15:15:33.394809258 +0200 +@@ -373,17 +373,13 @@ then no banner is displayed. By default, no banner is displayed. .It Cm CASignatureAlgorithms +The default is handled system-wide by +.Xr crypto-policies 7 . -+To see the defaults and how to modify this default, see manual page ++Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page +.Xr update-crypto-policies 8 . +.Pp Specifies which algorithms are allowed for signing of certificates @@ -251,13 +251,13 @@ diff -up openssh-8.7p1/sshd_config.5.crypto-policies openssh-8.7p1/sshd_config.5 If the specified list begins with a .Sq + character, then the specified algorithms will be appended to the default set -@@ -450,20 +446,25 @@ The default is +@@ -450,20 +446,25 @@ indicating not to .Xr chroot 2 . .It Cm Ciphers +The default is handled system-wide by +.Xr crypto-policies 7 . -+To see the defaults and how to modify this default, see manual page ++Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page +.Xr update-crypto-policies 8 . +.Pp Specifies the ciphers allowed. @@ -281,7 +281,7 @@ diff -up openssh-8.7p1/sshd_config.5.crypto-policies openssh-8.7p1/sshd_config.5 .Pp The supported ciphers are: .Pp -@@ -490,13 +491,6 @@ aes256-gcm@openssh.com +@@ -490,13 +491,6 @@ chacha20-poly1305@openssh.com .El .Pp @@ -295,13 +295,13 @@ diff -up openssh-8.7p1/sshd_config.5.crypto-policies openssh-8.7p1/sshd_config.5 The list of available ciphers may also be obtained using .Qq ssh -Q cipher . .It Cm ClientAliveCountMax -@@ -685,21 +679,22 @@ For this to work +@@ -685,21 +679,22 @@ .Cm GSSAPIKeyExchange needs to be enabled in the server and also used by the client. .It Cm GSSAPIKexAlgorithms +The default is handled system-wide by +.Xr crypto-policies 7 . -+To see the defaults and how to modify this default, see manual page ++Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page +.Xr update-crypto-policies 8 . +.Pp The list of key exchange algorithms that are accepted by GSSAPI @@ -328,13 +328,13 @@ diff -up openssh-8.7p1/sshd_config.5.crypto-policies openssh-8.7p1/sshd_config.5 This option only applies to connections using GSSAPI. .It Cm HostbasedAcceptedAlgorithms Specifies the signature algorithms that will be accepted for hostbased -@@ -799,26 +794,13 @@ is specified, the location of the socket +@@ -799,26 +794,13 @@ .Ev SSH_AUTH_SOCK environment variable. .It Cm HostKeyAlgorithms +The default is handled system-wide by +.Xr crypto-policies 7 . -+To see the defaults and how to modify this default, see manual page ++Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page +.Xr update-crypto-policies 8 . +.Pp Specifies the host key signature algorithms @@ -360,13 +360,13 @@ diff -up openssh-8.7p1/sshd_config.5.crypto-policies openssh-8.7p1/sshd_config.5 The list of available signature algorithms may also be obtained using .Qq ssh -Q HostKeyAlgorithms . .It Cm IgnoreRhosts -@@ -965,20 +947,25 @@ Specifies whether to look at .k5login fi +@@ -965,20 +947,25 @@ The default is .Cm yes . .It Cm KexAlgorithms +The default is handled system-wide by +.Xr crypto-policies 7 . -+To see the defaults and how to modify this default, see manual page ++Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page +.Xr update-crypto-policies 8 . +.Pp Specifies the available KEX (Key Exchange) algorithms. @@ -390,7 +390,7 @@ diff -up openssh-8.7p1/sshd_config.5.crypto-policies openssh-8.7p1/sshd_config.5 The supported algorithms are: .Pp .Bl -item -compact -offset indent -@@ -1010,15 +997,6 @@ ecdh-sha2-nistp521 +@@ -1010,15 +997,6 @@ sntrup761x25519-sha512@openssh.com .El .Pp @@ -406,13 +406,13 @@ diff -up openssh-8.7p1/sshd_config.5.crypto-policies openssh-8.7p1/sshd_config.5 The list of available key exchange algorithms may also be obtained using .Qq ssh -Q KexAlgorithms . .It Cm ListenAddress -@@ -1104,21 +1082,26 @@ function, and all code in the +@@ -1104,21 +1082,26 @@ file. This option is intended for debugging and no overrides are enabled by default. .It Cm MACs +The default is handled system-wide by +.Xr crypto-policies 7 . -+To see the defaults and how to modify this default, see manual page ++Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page +.Xr update-crypto-policies 8 . +.Pp Specifies the available MAC (message authentication code) algorithms. @@ -437,7 +437,7 @@ diff -up openssh-8.7p1/sshd_config.5.crypto-policies openssh-8.7p1/sshd_config.5 .Pp The algorithms that contain .Qq -etm -@@ -1161,15 +1144,6 @@ umac-64-etm@openssh.com +@@ -1161,15 +1144,6 @@ umac-128-etm@openssh.com .El .Pp @@ -453,13 +453,13 @@ diff -up openssh-8.7p1/sshd_config.5.crypto-policies openssh-8.7p1/sshd_config.5 The list of available MAC algorithms may also be obtained using .Qq ssh -Q mac . .It Cm Match -@@ -1548,37 +1522,25 @@ or equivalent.) +@@ -1548,37 +1522,25 @@ The default is .Cm yes . .It Cm PubkeyAcceptedAlgorithms +The default is handled system-wide by +.Xr crypto-policies 7 . -+To see the defaults and how to modify this default, see manual page ++Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page +.Xr update-crypto-policies 8 . +.Pp Specifies the signature algorithms that will be accepted for public key diff --git a/openssh-8.7p1-evpgenkey.patch b/openssh-8.7p1-evpgenkey.patch new file mode 100644 index 0000000..1af9b49 --- /dev/null +++ b/openssh-8.7p1-evpgenkey.patch @@ -0,0 +1,110 @@ +diff -up openssh-8.7p1/sshkey.c.evpgenrsa openssh-8.7p1/sshkey.c +--- openssh-8.7p1/sshkey.c.evpgenrsa 2022-06-30 15:14:58.200518353 +0200 ++++ openssh-8.7p1/sshkey.c 2022-06-30 15:24:31.499641196 +0200 +@@ -1657,7 +1657,8 @@ sshkey_cert_type(const struct sshkey *k) + static int + rsa_generate_private_key(u_int bits, RSA **rsap) + { +- RSA *private = NULL; ++ EVP_PKEY_CTX *ctx = NULL; ++ EVP_PKEY *res = NULL; + BIGNUM *f4 = NULL; + int ret = SSH_ERR_INTERNAL_ERROR; + +@@ -1667,20 +1668,42 @@ rsa_generate_private_key(u_int bits, RSA + bits > SSHBUF_MAX_BIGNUM * 8) + return SSH_ERR_KEY_LENGTH; + *rsap = NULL; +- if ((private = RSA_new()) == NULL || (f4 = BN_new()) == NULL) { ++ ++ if ((ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL)) == NULL ++ || (f4 = BN_new()) == NULL || !BN_set_word(f4, RSA_F4)) { + ret = SSH_ERR_ALLOC_FAIL; + goto out; + } +- if (!BN_set_word(f4, RSA_F4) || +- !RSA_generate_key_ex(private, bits, f4, NULL)) { ++ ++ if (EVP_PKEY_keygen_init(ctx) <= 0) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ ++ if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, bits) <= 0) { ++ ret = SSH_ERR_KEY_LENGTH; ++ goto out; ++ } ++ ++ if (EVP_PKEY_CTX_set1_rsa_keygen_pubexp(ctx, f4) <= 0) ++ goto out; ++ ++ if (EVP_PKEY_keygen(ctx, &res) <= 0) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ ++ /* This function is deprecated in OpenSSL 3.0 but OpenSSH doesn't worry about it*/ ++ *rsap = EVP_PKEY_get1_RSA(res); ++ if (*rsap) { ++ ret = 0; ++ } else { + ret = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } +- *rsap = private; +- private = NULL; +- ret = 0; + out: +- RSA_free(private); ++ EVP_PKEY_CTX_free(ctx); ++ EVP_PKEY_free(res); + BN_free(f4); + return ret; + } +@@ -1820,7 +1820,8 @@ sshkey_ecdsa_key_to_nid(EC_KEY *k) + static int + ecdsa_generate_private_key(u_int bits, int *nid, EC_KEY **ecdsap) + { +- EC_KEY *private; ++ EVP_PKEY_CTX *ctx = NULL; ++ EVP_PKEY *res = NULL; + int ret = SSH_ERR_INTERNAL_ERROR; + + if (nid == NULL || ecdsap == NULL) +@@ -1828,20 +1829,29 @@ ecdsa_generate_private_key(u_int bits, i + if ((*nid = sshkey_ecdsa_bits_to_nid(bits)) == -1) + return SSH_ERR_KEY_LENGTH; + *ecdsap = NULL; +- if ((private = EC_KEY_new_by_curve_name(*nid)) == NULL) { ++ ++ if ((ctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL)) == NULL) { + ret = SSH_ERR_ALLOC_FAIL; + goto out; + } +- if (EC_KEY_generate_key(private) != 1) { ++ ++ if (EVP_PKEY_keygen_init(ctx) <= 0 || EVP_PKEY_CTX_set_group_name(ctx, OBJ_nid2sn(*nid)) <= 0 ++ || EVP_PKEY_keygen(ctx, &res) <= 0) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ /* This function is deprecated in OpenSSL 3.0 but OpenSSH doesn't worry about it*/ ++ *ecdsap = EVP_PKEY_get1_EC_KEY(res); ++ if (*ecdsap) { ++ EC_KEY_set_asn1_flag(*ecdsap, OPENSSL_EC_NAMED_CURVE); ++ ret = 0; ++ } else { + ret = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } +- EC_KEY_set_asn1_flag(private, OPENSSL_EC_NAMED_CURVE); +- *ecdsap = private; +- private = NULL; +- ret = 0; + out: +- EC_KEY_free(private); ++ EVP_PKEY_CTX_free(ctx); ++ EVP_PKEY_free(res); + return ret; + } + # endif /* OPENSSL_HAS_ECC */ diff --git a/openssh-8.7p1-gssapi-auth.patch b/openssh-8.7p1-gssapi-auth.patch new file mode 100644 index 0000000..6908cad --- /dev/null +++ b/openssh-8.7p1-gssapi-auth.patch @@ -0,0 +1,20 @@ +diff --color -rup a/monitor.c b/monitor.c +--- a/monitor.c 2022-07-11 15:11:28.146863144 +0200 ++++ b/monitor.c 2022-07-11 15:15:35.726655877 +0200 +@@ -376,8 +376,15 @@ monitor_child_preauth(struct ssh *ssh, s + if (ent->flags & (MON_AUTHDECIDE|MON_ALOG)) { + auth_log(ssh, authenticated, partial, + auth_method, auth_submethod); +- if (!partial && !authenticated) ++ if (!partial && !authenticated) { ++#ifdef GSSAPI ++ /* If gssapi-with-mic failed, MONITOR_REQ_GSSCHECKMIC is disabled. ++ * We have to reenable it to try again for gssapi-keyex */ ++ if (strcmp(auth_method, "gssapi-with-mic") == 0 && options.gss_keyex) ++ monitor_permit(mon_dispatch, MONITOR_REQ_GSSCHECKMIC, 1); ++#endif + authctxt->failures++; ++ } + if (authenticated || partial) { + auth2_update_session_info(authctxt, + auth_method, auth_submethod); diff --git a/openssh-8.7p1-host-based-auth.patch b/openssh-8.7p1-host-based-auth.patch new file mode 100644 index 0000000..23efe91 --- /dev/null +++ b/openssh-8.7p1-host-based-auth.patch @@ -0,0 +1,151 @@ +diff --color -rup a/sshconnect2.c b/sshconnect2.c +--- a/sshconnect2.c 2022-07-11 17:00:02.618575727 +0200 ++++ b/sshconnect2.c 2022-07-11 17:03:05.096085690 +0200 +@@ -2288,9 +2288,9 @@ userauth_hostbased(struct ssh *ssh) + if (authctxt->sensitive->keys[i] == NULL || + authctxt->sensitive->keys[i]->type == KEY_UNSPEC) + continue; +- if (match_pattern_list( ++ if (!sshkey_match_keyname_to_sigalgs( + sshkey_ssh_name(authctxt->sensitive->keys[i]), +- authctxt->active_ktype, 0) != 1) ++ authctxt->active_ktype)) + continue; + /* we take and free the key */ + private = authctxt->sensitive->keys[i]; +@@ -2316,7 +2316,8 @@ userauth_hostbased(struct ssh *ssh) + error_f("sshkey_fingerprint failed"); + goto out; + } +- debug_f("trying hostkey %s %s", sshkey_ssh_name(private), fp); ++ debug_f("trying hostkey %s %s using sigalg %s", ++ sshkey_ssh_name(private), fp, authctxt->active_ktype); + + /* figure out a name for the client host */ + lname = get_local_name(ssh_packet_get_connection_in(ssh)); +diff --color -rup a/sshkey.c b/sshkey.c +--- a/sshkey.c 2022-07-11 17:00:02.609575554 +0200 ++++ b/sshkey.c 2022-07-11 17:12:30.905976443 +0200 +@@ -252,6 +252,29 @@ sshkey_ecdsa_nid_from_name(const char *n + return -1; + } + ++int ++sshkey_match_keyname_to_sigalgs(const char *keyname, const char *sigalgs) ++{ ++ int ktype; ++ ++ if (sigalgs == NULL || *sigalgs == '\0' || ++ (ktype = sshkey_type_from_name(keyname)) == KEY_UNSPEC) ++ return 0; ++ else if (ktype == KEY_RSA) { ++ return match_pattern_list("ssh-rsa", sigalgs, 0) == 1 || ++ match_pattern_list("rsa-sha2-256", sigalgs, 0) == 1 || ++ match_pattern_list("rsa-sha2-512", sigalgs, 0) == 1; ++ } else if (ktype == KEY_RSA_CERT) { ++ return match_pattern_list("ssh-rsa-cert-v01@openssh.com", ++ sigalgs, 0) == 1 || ++ match_pattern_list("rsa-sha2-256-cert-v01@openssh.com", ++ sigalgs, 0) == 1 || ++ match_pattern_list("rsa-sha2-512-cert-v01@openssh.com", ++ sigalgs, 0) == 1; ++ } else ++ return match_pattern_list(keyname, sigalgs, 0) == 1; ++} ++ + char * + sshkey_alg_list(int certs_only, int plain_only, int include_sigonly, char sep) + { +diff --color -rup a/sshkey.h b/sshkey.h +--- a/sshkey.h 2022-07-11 17:00:02.603575438 +0200 ++++ b/sshkey.h 2022-07-11 17:13:01.052556879 +0200 +@@ -194,6 +194,10 @@ int sshkey_is_cert(const struct sshkey + int sshkey_is_sk(const struct sshkey *); + int sshkey_type_is_cert(int); + int sshkey_type_plain(int); ++ ++/* Returns non-zero if key name match sigalgs pattern list. (handles RSA) */ ++int sshkey_match_keyname_to_sigalgs(const char *, const char *); ++ + int sshkey_to_certified(struct sshkey *); + int sshkey_drop_cert(struct sshkey *); + int sshkey_cert_copy(const struct sshkey *, struct sshkey *); +diff --color -rup a/ssh-keysign.c b/ssh-keysign.c +--- a/ssh-keysign.c 2021-08-20 06:03:49.000000000 +0200 ++++ b/ssh-keysign.c 2022-07-11 17:00:23.306973667 +0200 +@@ -62,7 +62,7 @@ + extern char *__progname; + + static int +-valid_request(struct passwd *pw, char *host, struct sshkey **ret, ++valid_request(struct passwd *pw, char *host, struct sshkey **ret, char **pkalgp, + u_char *data, size_t datalen) + { + struct sshbuf *b; +@@ -75,6 +75,8 @@ valid_request(struct passwd *pw, char *h + + if (ret != NULL) + *ret = NULL; ++ if (pkalgp != NULL) ++ *pkalgp = NULL; + fail = 0; + + if ((b = sshbuf_from(data, datalen)) == NULL) +@@ -122,8 +124,6 @@ valid_request(struct passwd *pw, char *h + fail++; + } else if (key->type != pktype) + fail++; +- free(pkalg); +- free(pkblob); + + /* client host name, handle trailing dot */ + if ((r = sshbuf_get_cstring(b, &p, &len)) != 0) +@@ -154,8 +154,19 @@ valid_request(struct passwd *pw, char *h + + if (fail) + sshkey_free(key); +- else if (ret != NULL) +- *ret = key; ++ else { ++ if (ret != NULL) { ++ *ret = key; ++ key = NULL; ++ } ++ if (pkalgp != NULL) { ++ *pkalgp = pkalg; ++ pkalg = NULL; ++ } ++ } ++ sshkey_free(key); ++ free(pkalg); ++ free(pkblob); + + return (fail ? -1 : 0); + } +@@ -170,7 +181,7 @@ main(int argc, char **argv) + struct passwd *pw; + int r, key_fd[NUM_KEYTYPES], i, found, version = 2, fd; + u_char *signature, *data, rver; +- char *host, *fp; ++ char *host, *fp, *pkalg; + size_t slen, dlen; + + if (pledge("stdio rpath getpw dns id", NULL) != 0) +@@ -258,7 +269,7 @@ main(int argc, char **argv) + + if ((r = sshbuf_get_string(b, &data, &dlen)) != 0) + fatal_r(r, "%s: buffer error", __progname); +- if (valid_request(pw, host, &key, data, dlen) < 0) ++ if (valid_request(pw, host, &key, &pkalg, data, dlen) < 0) + fatal("%s: not a valid request", __progname); + free(host); + +@@ -279,7 +290,7 @@ main(int argc, char **argv) + } + + if ((r = sshkey_sign(keys[i], &signature, &slen, data, dlen, +- NULL, NULL, NULL, 0)) != 0) ++ pkalg, NULL, NULL, 0)) != 0) + fatal_r(r, "%s: sshkey_sign failed", __progname); + free(data); + diff --git a/openssh-8.7p1-hpn-15.2-modified.patch b/openssh-8.7p1-hpn-15.2-modified.patch index fcc0e40..2ddbe63 100644 --- a/openssh-8.7p1-hpn-15.2-modified.patch +++ b/openssh-8.7p1-hpn-15.2-modified.patch @@ -1674,8 +1674,8 @@ diff -Nur openssh-8.7p1.orig/readconf.c openssh-8.7p1/readconf.c { "stdinnull", oStdinNull }, { "forkafterauthentication", oForkAfterAuthentication }, @@ -336,6 +344,11 @@ - { "securitykeyprovider", oSecurityKeyProvider }, - { "knownhostscommand", oKnownHostsCommand }, + { "requiredrsasize", oRequiredRSASize }, + { "rsaminsize", oRequiredRSASize }, /* alias */ + { "tcprcvbufpoll", oTcpRcvBufPoll }, + { "tcprcvbuf", oTcpRcvBuf }, @@ -2545,7 +2545,7 @@ diff -Nur openssh-8.7p1.orig/sshd.c openssh-8.7p1/sshd.c do_authenticated(ssh, authctxt); @@ -2486,6 +2528,11 @@ - struct kex *kex; + char *prop_kex = NULL, *prop_enc = NULL, *prop_hostkey = NULL; int r; + if (options.none_enabled == 1) @@ -2553,9 +2553,9 @@ diff -Nur openssh-8.7p1.orig/sshd.c openssh-8.7p1/sshd.c + if (options.nonemac_enabled == 1) + debug("WARNING: None MAC enabled"); + - myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal(ssh, + myproposal[PROPOSAL_KEX_ALGS] = prop_kex = compat_kex_proposal(ssh, options.kex_algorithms); - myproposal[PROPOSAL_ENC_ALGS_CTOS] = compat_cipher_proposal(ssh, + myproposal[PROPOSAL_ENC_ALGS_CTOS] = diff -Nur openssh-8.7p1.orig/sshd_config openssh-8.7p1/sshd_config --- openssh-8.7p1.orig/sshd_config 2021-10-24 07:54:36.874834211 +0200 +++ openssh-8.7p1/sshd_config 2021-10-24 07:56:04.875030058 +0200 diff --git a/openssh-8.7p1-ibmca.patch b/openssh-8.7p1-ibmca.patch new file mode 100644 index 0000000..c9c12ee --- /dev/null +++ b/openssh-8.7p1-ibmca.patch @@ -0,0 +1,12 @@ +--- openssh-8.7p1/openbsd-compat/bsd-closefrom.c.orig 2022-04-12 15:47:03.815044607 +0200 ++++ openssh-8.7p1/openbsd-compat/bsd-closefrom.c 2022-04-12 15:48:12.464963511 +0200 +@@ -16,7 +16,7 @@ + + #include "includes.h" + +-#ifndef HAVE_CLOSEFROM ++#if (!defined HAVE_CLOSEFROM) || (defined __s390__) + + #include + #include + diff --git a/openssh-8.7p1-mem-leak.patch b/openssh-8.7p1-mem-leak.patch new file mode 100644 index 0000000..8c9ac80 --- /dev/null +++ b/openssh-8.7p1-mem-leak.patch @@ -0,0 +1,156 @@ +diff --color -rup a/compat.c b/compat.c +--- a/compat.c 2021-08-20 06:03:49.000000000 +0200 ++++ b/compat.c 2022-07-14 17:39:23.770268440 +0200 +@@ -157,11 +157,12 @@ compat_banner(struct ssh *ssh, const cha + debug_f("no match: %s", version); + } + ++/* Always returns pointer to allocated memory, caller must free. */ + char * + compat_cipher_proposal(struct ssh *ssh, char *cipher_prop) + { + if (!(ssh->compat & SSH_BUG_BIGENDIANAES)) +- return cipher_prop; ++ return xstrdup(cipher_prop); + debug2_f("original cipher proposal: %s", cipher_prop); + if ((cipher_prop = match_filter_denylist(cipher_prop, "aes*")) == NULL) + fatal("match_filter_denylist failed"); +@@ -171,11 +172,12 @@ compat_cipher_proposal(struct ssh *ssh, + return cipher_prop; + } + ++/* Always returns pointer to allocated memory, caller must free. */ + char * + compat_pkalg_proposal(struct ssh *ssh, char *pkalg_prop) + { + if (!(ssh->compat & SSH_BUG_RSASIGMD5)) +- return pkalg_prop; ++ return xstrdup(pkalg_prop); + debug2_f("original public key proposal: %s", pkalg_prop); + if ((pkalg_prop = match_filter_denylist(pkalg_prop, "ssh-rsa")) == NULL) + fatal("match_filter_denylist failed"); +@@ -185,21 +187,26 @@ compat_pkalg_proposal(struct ssh *ssh, c + return pkalg_prop; + } + ++/* Always returns pointer to allocated memory, caller must free. */ + char * + compat_kex_proposal(struct ssh *ssh, char *p) + { ++ char *cp = NULL; ++ + if ((ssh->compat & (SSH_BUG_CURVE25519PAD|SSH_OLD_DHGEX)) == 0) +- return p; ++ return xstrdup(p); + debug2_f("original KEX proposal: %s", p); + if ((ssh->compat & SSH_BUG_CURVE25519PAD) != 0) + if ((p = match_filter_denylist(p, + "curve25519-sha256@libssh.org")) == NULL) + fatal("match_filter_denylist failed"); + if ((ssh->compat & SSH_OLD_DHGEX) != 0) { ++ cp = p; + if ((p = match_filter_denylist(p, + "diffie-hellman-group-exchange-sha256," + "diffie-hellman-group-exchange-sha1")) == NULL) + fatal("match_filter_denylist failed"); ++ free(cp); + } + debug2_f("compat KEX proposal: %s", p); + if (*p == '\0') +diff --color -rup a/sshconnect2.c b/sshconnect2.c +--- a/sshconnect2.c 2022-07-14 17:38:43.241496549 +0200 ++++ b/sshconnect2.c 2022-07-14 17:39:23.772268479 +0200 +@@ -222,6 +222,7 @@ ssh_kex2(struct ssh *ssh, char *host, st + { + char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT }; + char *s, *all_key; ++ char *prop_kex = NULL, *prop_enc = NULL, *prop_hostkey = NULL; + int r, use_known_hosts_order = 0; + + #if defined(GSSAPI) && defined(WITH_OPENSSL) +@@ -252,10 +253,9 @@ ssh_kex2(struct ssh *ssh, char *host, st + + if ((s = kex_names_cat(options.kex_algorithms, "ext-info-c")) == NULL) + fatal_f("kex_names_cat"); +- myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal(ssh, s); ++ myproposal[PROPOSAL_KEX_ALGS] = prop_kex = compat_kex_proposal(ssh, s); + myproposal[PROPOSAL_ENC_ALGS_CTOS] = +- compat_cipher_proposal(ssh, options.ciphers); +- myproposal[PROPOSAL_ENC_ALGS_STOC] = ++ myproposal[PROPOSAL_ENC_ALGS_STOC] = prop_enc = + compat_cipher_proposal(ssh, options.ciphers); + myproposal[PROPOSAL_COMP_ALGS_CTOS] = + myproposal[PROPOSAL_COMP_ALGS_STOC] = +@@ -264,12 +264,12 @@ ssh_kex2(struct ssh *ssh, char *host, st + myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs; + if (use_known_hosts_order) { + /* Query known_hosts and prefer algorithms that appear there */ +- myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = ++ myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = prop_hostkey = + compat_pkalg_proposal(ssh, + order_hostkeyalgs(host, hostaddr, port, cinfo)); + } else { + /* Use specified HostkeyAlgorithms exactly */ +- myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = ++ myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = prop_hostkey = + compat_pkalg_proposal(ssh, options.hostkeyalgorithms); + } + +@@ -383,6 +383,10 @@ ssh_kex2(struct ssh *ssh, char *host, st + (r = ssh_packet_write_wait(ssh)) != 0) + fatal_fr(r, "send packet"); + #endif ++ /* Free only parts of proposal that were dynamically allocated here. */ ++ free(prop_kex); ++ free(prop_enc); ++ free(prop_hostkey); + } + + /* +diff --color -rup a/sshd.c b/sshd.c +--- a/sshd.c 2022-07-14 17:38:43.242496568 +0200 ++++ b/sshd.c 2022-07-14 17:42:07.616388978 +0200 +@@ -2493,14 +2493,15 @@ do_ssh2_kex(struct ssh *ssh) + { + char *myproposal[PROPOSAL_MAX] = { KEX_SERVER }; + struct kex *kex; ++ char *hostkey_types = NULL; ++ char *prop_kex = NULL, *prop_enc = NULL, *prop_hostkey = NULL; + int r; + +- myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal(ssh, ++ myproposal[PROPOSAL_KEX_ALGS] = prop_kex = compat_kex_proposal(ssh, + options.kex_algorithms); +- myproposal[PROPOSAL_ENC_ALGS_CTOS] = compat_cipher_proposal(ssh, +- options.ciphers); +- myproposal[PROPOSAL_ENC_ALGS_STOC] = compat_cipher_proposal(ssh, +- options.ciphers); ++ myproposal[PROPOSAL_ENC_ALGS_CTOS] = ++ myproposal[PROPOSAL_ENC_ALGS_STOC] = prop_enc = ++ compat_cipher_proposal(ssh, options.ciphers); + myproposal[PROPOSAL_MAC_ALGS_CTOS] = + myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs; + +@@ -2513,8 +2514,10 @@ do_ssh2_kex(struct ssh *ssh) + ssh_packet_set_rekey_limits(ssh, options.rekey_limit, + options.rekey_interval); + +- myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = compat_pkalg_proposal( +- ssh, list_hostkey_types()); ++ hostkey_types = list_hostkey_types(); ++ myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = prop_hostkey = ++ compat_pkalg_proposal(ssh, hostkey_types); ++ free(hostkey_types); + + #if defined(GSSAPI) && defined(WITH_OPENSSL) + { +@@ -2606,6 +2609,9 @@ do_ssh2_kex(struct ssh *ssh) + (r = ssh_packet_write_wait(ssh)) != 0) + fatal_fr(r, "send test"); + #endif ++ free(prop_kex); ++ free(prop_enc); ++ free(prop_hostkey); + debug("KEX done"); + } + diff --git a/openssh-8.7p1-minimize-sha1-use.patch b/openssh-8.7p1-minimize-sha1-use.patch index 519b8f4..fc517da 100644 --- a/openssh-8.7p1-minimize-sha1-use.patch +++ b/openssh-8.7p1-minimize-sha1-use.patch @@ -1,102 +1,207 @@ -diff -up openssh-8.7p1/kex.c.minsha1 openssh-8.7p1/kex.c ---- openssh-8.7p1/kex.c.minsha1 2021-12-20 17:38:51.438294309 +0100 -+++ openssh-8.7p1/kex.c 2021-12-21 11:02:48.379991319 +0100 -@@ -994,6 +994,35 @@ kex_choose_conf(struct ssh *ssh) +diff --color -ru a/clientloop.c b/clientloop.c +--- a/clientloop.c 2022-06-29 16:35:06.677597259 +0200 ++++ b/clientloop.c 2022-06-29 16:40:29.737926205 +0200 +@@ -116,6 +116,9 @@ + #include "ssh-gss.h" + #endif + ++/* Permitted RSA signature algorithms for UpdateHostkeys proofs */ ++#define HOSTKEY_PROOF_RSA_ALGS "rsa-sha2-512,rsa-sha2-256" ++ + /* import options */ + extern Options options; + +@@ -2110,8 +2113,10 @@ + struct hostkeys_update_ctx *ctx = (struct hostkeys_update_ctx *)_ctx; + size_t i, ndone; + struct sshbuf *signdata; +- int r, kexsigtype, use_kexsigtype; ++ int r, plaintype; + const u_char *sig; ++ const char *rsa_kexalg = NULL; ++ char *alg = NULL; + size_t siglen; + + if (ctx->nnew == 0) +@@ -2122,9 +2127,9 @@ + hostkeys_update_ctx_free(ctx); + return; + } +- kexsigtype = sshkey_type_plain( +- sshkey_type_from_name(ssh->kex->hostkey_alg)); +- ++ if (sshkey_type_plain(sshkey_type_from_name( ++ ssh->kex->hostkey_alg)) == KEY_RSA) ++ rsa_kexalg = ssh->kex->hostkey_alg; + if ((signdata = sshbuf_new()) == NULL) + fatal_f("sshbuf_new failed"); + /* +@@ -2135,6 +2140,7 @@ + for (ndone = i = 0; i < ctx->nkeys; i++) { + if (ctx->keys_match[i]) + continue; ++ plaintype = sshkey_type_plain(ctx->keys[i]->type); + /* Prepare data to be signed: session ID, unique string, key */ + sshbuf_reset(signdata); + if ( (r = sshbuf_put_cstring(signdata, +@@ -2148,19 +2154,33 @@ + error_fr(r, "parse sig"); + goto out; + } ++ if ((r = sshkey_get_sigtype(sig, siglen, &alg)) != 0) { ++ error_fr(r, "server gave unintelligible signature " ++ "for %s key %zu", sshkey_type(ctx->keys[i]), i); ++ goto out; ++ } + /* +- * For RSA keys, prefer to use the signature type negotiated +- * during KEX to the default (SHA1). ++ * Special case for RSA keys: if a RSA hostkey was negotiated, ++ * then use its signature type for verification of RSA hostkey ++ * proofs. Otherwise, accept only RSA-SHA256/512 signatures. + */ +- use_kexsigtype = kexsigtype == KEY_RSA && +- sshkey_type_plain(ctx->keys[i]->type) == KEY_RSA; +- debug3_f("verify %s key %zu using %s sigalg", +- sshkey_type(ctx->keys[i]), i, +- use_kexsigtype ? ssh->kex->hostkey_alg : "default"); ++ if (plaintype == KEY_RSA && rsa_kexalg == NULL && ++ match_pattern_list(alg, HOSTKEY_PROOF_RSA_ALGS, 0) != 1) { ++ debug_f("server used untrusted RSA signature algorithm " ++ "%s for key %zu, disregarding", alg, i); ++ free(alg); ++ /* zap the key from the list */ ++ sshkey_free(ctx->keys[i]); ++ ctx->keys[i] = NULL; ++ ndone++; ++ continue; ++ } ++ debug3_f("verify %s key %zu using sigalg %s", ++ sshkey_type(ctx->keys[i]), i, alg); ++ free(alg); + if ((r = sshkey_verify(ctx->keys[i], sig, siglen, + sshbuf_ptr(signdata), sshbuf_len(signdata), +- use_kexsigtype ? ssh->kex->hostkey_alg : NULL, 0, +- NULL)) != 0) { ++ plaintype == KEY_RSA ? rsa_kexalg : NULL, 0, NULL)) != 0) { + error_fr(r, "server gave bad signature for %s key %zu", + sshkey_type(ctx->keys[i]), i); + goto out; +diff --git a/hostfile.c b/hostfile.c +index a035b381..bd49e3ac 100644 +--- a/hostfile.c ++++ b/hostfile.c +@@ -642,7 +642,7 @@ hostfile_replace_entries(const char *filename, const char *host, const char *ip, + /* Re-add the requested keys */ + want = HKF_MATCH_HOST | (ip == NULL ? 0 : HKF_MATCH_IP); + for (i = 0; i < nkeys; i++) { +- if ((want & ctx.match_keys[i]) == want) ++ if (keys[i] == NULL || (want & ctx.match_keys[i]) == want) + continue; + if ((fp = sshkey_fingerprint(keys[i], hash_alg, + SSH_FP_DEFAULT)) == NULL) { +diff --color -ru a/kex.c b/kex.c +--- a/kex.c 2022-06-29 16:35:06.775599179 +0200 ++++ b/kex.c 2022-06-29 16:42:00.839710940 +0200 +@@ -959,6 +959,18 @@ + return (1); + } + ++/* returns non-zero if proposal contains any algorithm from algs */ ++static int ++has_any_alg(const char *proposal, const char *algs) ++{ ++ char *cp; ++ ++ if ((cp = match_list(proposal, algs, NULL)) == NULL) ++ return 0; ++ free(cp); ++ return 1; ++} ++ + static int + kex_choose_conf(struct ssh *ssh) + { +@@ -994,6 +1006,16 @@ free(ext); } + /* Check whether client supports rsa-sha2 algorithms */ + if (kex->server && (kex->flags & KEX_INITIAL)) { -+ char *ext; -+ -+ ext = match_list("rsa-sha2-256", peer[PROPOSAL_SERVER_HOST_KEY_ALGS], NULL); -+ if (ext) { ++ if (has_any_alg(peer[PROPOSAL_SERVER_HOST_KEY_ALGS], ++ "rsa-sha2-256,rsa-sha2-256-cert-v01@openssh.com")) + kex->flags |= KEX_RSA_SHA2_256_SUPPORTED; -+ free(ext); -+ } -+ -+ ext = match_list("rsa-sha2-512", peer[PROPOSAL_SERVER_HOST_KEY_ALGS], NULL); -+ if (ext) { ++ if (has_any_alg(peer[PROPOSAL_SERVER_HOST_KEY_ALGS], ++ "rsa-sha2-512,rsa-sha2-512-cert-v01@openssh.com")) + kex->flags |= KEX_RSA_SHA2_512_SUPPORTED; -+ free(ext); -+ } -+ -+ ext = match_list("rsa-sha2-256-cert-v01@openssh.com", peer[PROPOSAL_SERVER_HOST_KEY_ALGS], NULL); -+ if (ext) { -+ kex->flags |= KEX_RSA_SHA2_256_SUPPORTED; -+ free(ext); -+ } -+ -+ ext = match_list("rsa-sha2-512-cert-v01@openssh.com", peer[PROPOSAL_SERVER_HOST_KEY_ALGS], NULL); -+ if (ext) { -+ kex->flags |= KEX_RSA_SHA2_512_SUPPORTED; -+ free(ext); -+ } + } + /* Algorithm Negotiation */ if ((r = choose_kex(kex, cprop[PROPOSAL_KEX_ALGS], sprop[PROPOSAL_KEX_ALGS])) != 0) { -diff -up openssh-8.7p1/kex.h.minsha1 openssh-8.7p1/kex.h ---- openssh-8.7p1/kex.h.minsha1 2021-12-20 17:38:51.430294240 +0100 -+++ openssh-8.7p1/kex.h 2021-12-21 10:56:29.066735608 +0100 -@@ -116,6 +116,8 @@ enum kex_exchange { +diff --color -ru a/kex.h b/kex.h +--- a/kex.h 2022-06-29 16:35:06.766599003 +0200 ++++ b/kex.h 2022-06-29 16:42:24.199168567 +0200 +@@ -116,6 +116,8 @@ #define KEX_INIT_SENT 0x0001 #define KEX_INITIAL 0x0002 -+#define KEX_RSA_SHA2_256_SUPPORTED 0x0004 -+#define KEX_RSA_SHA2_512_SUPPORTED 0x0008 ++#define KEX_RSA_SHA2_256_SUPPORTED 0x0008 /* only set in server for now */ ++#define KEX_RSA_SHA2_512_SUPPORTED 0x0010 /* only set in server for now */ struct sshenc { char *name; -diff -up openssh-8.7p1/serverloop.c.minsha1 openssh-8.7p1/serverloop.c ---- openssh-8.7p1/serverloop.c.minsha1 2021-08-20 06:03:49.000000000 +0200 -+++ openssh-8.7p1/serverloop.c 2021-12-21 11:01:00.594047538 +0100 -@@ -684,7 +685,7 @@ server_input_hostkeys_prove(struct ssh * +diff --color -ru a/serverloop.c b/serverloop.c +--- a/serverloop.c 2021-08-20 06:03:49.000000000 +0200 ++++ b/serverloop.c 2022-06-29 16:45:05.902336428 +0200 +@@ -684,16 +684,18 @@ struct sshbuf *resp = NULL; struct sshbuf *sigbuf = NULL; struct sshkey *key = NULL, *key_pub = NULL, *key_prv = NULL; - int r, ndx, kexsigtype, use_kexsigtype, success = 0; + int r, ndx, success = 0; const u_char *blob; ++ const char *sigalg, *kex_rsa_sigalg = NULL; u_char *sig = 0; size_t blen, slen; -@@ -692,9 +693,11 @@ server_input_hostkeys_prove(struct ssh * + if ((resp = sshbuf_new()) == NULL || (sigbuf = sshbuf_new()) == NULL) fatal_f("sshbuf_new"); - kexsigtype = sshkey_type_plain( - sshkey_type_from_name(ssh->kex->hostkey_alg)); ++ if (sshkey_type_plain(sshkey_type_from_name( ++ ssh->kex->hostkey_alg)) == KEY_RSA) ++ kex_rsa_sigalg = ssh->kex->hostkey_alg; while (ssh_packet_remaining(ssh) > 0) { -+ const char *pkexstr = NULL; -+ const char *rsa_sha2_256 = "rsa-sha2-256"; -+ const char *rsa_sha2_512 = "rsa-sha2-512"; -+ sshkey_free(key); key = NULL; - if ((r = sshpkt_get_string_direct(ssh, &blob, &blen)) != 0 || -@@ -726,8 +729,13 @@ server_input_hostkeys_prove(struct ssh * +@@ -726,16 +728,24 @@ * For RSA keys, prefer to use the signature type negotiated * during KEX to the default (SHA1). */ - use_kexsigtype = kexsigtype == KEY_RSA && - sshkey_type_plain(key->type) == KEY_RSA; ++ sigalg = NULL; + if (sshkey_type_plain(key->type) == KEY_RSA) { -+ if (ssh->kex->flags & KEX_RSA_SHA2_512_SUPPORTED) -+ pkexstr = rsa_sha2_512; -+ else if (ssh->kex->flags & KEX_RSA_SHA2_256_SUPPORTED) -+ pkexstr = rsa_sha2_256; ++ if (kex_rsa_sigalg != NULL) ++ sigalg = kex_rsa_sigalg; ++ else if (ssh->kex->flags & KEX_RSA_SHA2_512_SUPPORTED) ++ sigalg = "rsa-sha2-512"; ++ else if (ssh->kex->flags & KEX_RSA_SHA2_256_SUPPORTED) ++ sigalg = "rsa-sha2-256"; + } -+ ++ debug3_f("sign %s key (index %d) using sigalg %s", ++ sshkey_type(key), ndx, sigalg == NULL ? "default" : sigalg); if ((r = sshbuf_put_cstring(sigbuf, "hostkeys-prove-00@openssh.com")) != 0 || (r = sshbuf_put_stringb(sigbuf, -@@ -735,7 +743,7 @@ server_input_hostkeys_prove(struct ssh * + ssh->kex->session_id)) != 0 || (r = sshkey_puts(key, sigbuf)) != 0 || (r = ssh->kex->sign(ssh, key_prv, key_pub, &sig, &slen, - sshbuf_ptr(sigbuf), sshbuf_len(sigbuf), +- sshbuf_ptr(sigbuf), sshbuf_len(sigbuf), - use_kexsigtype ? ssh->kex->hostkey_alg : NULL)) != 0 || -+ pkexstr)) != 0 || ++ sshbuf_ptr(sigbuf), sshbuf_len(sigbuf), sigalg)) != 0 || (r = sshbuf_put_string(resp, sig, slen)) != 0) { error_fr(r, "assemble signature"); goto out; diff --git a/openssh-8.7p1-minrsabits.patch b/openssh-8.7p1-minrsabits.patch new file mode 100644 index 0000000..b53c383 --- /dev/null +++ b/openssh-8.7p1-minrsabits.patch @@ -0,0 +1,446 @@ +diff --git a/auth2-hostbased.c b/auth2-hostbased.c +index 36b9d2f5..6b517db4 100644 +--- a/auth2-hostbased.c ++++ b/auth2-hostbased.c +@@ -119,6 +119,11 @@ userauth_hostbased(struct ssh *ssh, const char *method) + "(null)" : key->cert->signature_type); + goto done; + } ++ if ((r = sshkey_check_rsa_length(key, ++ options.required_rsa_size)) != 0) { ++ logit_r(r, "refusing %s key", sshkey_type(key)); ++ goto done; ++ } + + if (!authctxt->valid || authctxt->user == NULL) { + debug2_f("disabled because of invalid user"); +diff --git a/auth2-pubkey.c b/auth2-pubkey.c +index 962fd342..5d59febc 100644 +--- a/auth2-pubkey.c ++++ b/auth2-pubkey.c +@@ -175,6 +175,11 @@ userauth_pubkey(struct ssh *ssh, const char *method) + "(null)" : key->cert->signature_type); + goto done; + } ++ if ((r = sshkey_check_rsa_length(key, ++ options.required_rsa_size)) != 0) { ++ logit_r(r, "refusing %s key", sshkey_type(key)); ++ goto done; ++ } + key_s = format_key(key); + if (sshkey_is_cert(key)) + ca_s = format_key(key->cert->signature_key); +diff --git a/readconf.c b/readconf.c +index 7f26c680..42be690b 100644 +--- a/readconf.c ++++ b/readconf.c +@@ -174,7 +174,7 @@ typedef enum { + oStreamLocalBindMask, oStreamLocalBindUnlink, oRevokedHostKeys, + oFingerprintHash, oUpdateHostkeys, oHostbasedAcceptedAlgorithms, + oPubkeyAcceptedAlgorithms, oCASignatureAlgorithms, oProxyJump, +- oSecurityKeyProvider, oKnownHostsCommand, ++ oSecurityKeyProvider, oKnownHostsCommand, oRequiredRSASize, + oIgnore, oIgnoredUnknownOption, oDeprecated, oUnsupported + } OpCodes; + +@@ -320,6 +320,8 @@ static struct { + { "proxyjump", oProxyJump }, + { "securitykeyprovider", oSecurityKeyProvider }, + { "knownhostscommand", oKnownHostsCommand }, ++ { "requiredrsasize", oRequiredRSASize }, ++ { "rsaminsize", oRequiredRSASize }, /* alias */ + + { NULL, oBadOption } + }; +@@ -2176,6 +2177,10 @@ parse_pubkey_algos: + *charptr = xstrdup(arg); + break; + ++ case oRequiredRSASize: ++ intptr = &options->required_rsa_size; ++ goto parse_int; ++ + case oDeprecated: + debug("%s line %d: Deprecated option \"%s\"", + filename, linenum, keyword); +@@ -2423,6 +2428,7 @@ initialize_options(Options * options) + options->hostbased_accepted_algos = NULL; + options->pubkey_accepted_algos = NULL; + options->known_hosts_command = NULL; ++ options->required_rsa_size = -1; + } + + /* +@@ -2619,6 +2625,8 @@ fill_default_options(Options * options) + if (options->sk_provider == NULL) + options->sk_provider = xstrdup("$SSH_SK_PROVIDER"); + #endif ++ if (options->required_rsa_size == -1) ++ options->required_rsa_size = SSH_RSA_MINIMUM_MODULUS_SIZE; + + /* Expand KEX name lists */ + all_cipher = cipher_alg_list(',', 0); +@@ -3308,6 +3316,7 @@ dump_client_config(Options *o, const char *host) + dump_cfg_int(oNumberOfPasswordPrompts, o->number_of_password_prompts); + dump_cfg_int(oServerAliveCountMax, o->server_alive_count_max); + dump_cfg_int(oServerAliveInterval, o->server_alive_interval); ++ dump_cfg_int(oRequiredRSASize, o->required_rsa_size); + + /* String options */ + dump_cfg_string(oBindAddress, o->bind_address); +diff --git a/readconf.h b/readconf.h +index f647bd42..ffb5ec4f 100644 +--- a/readconf.h ++++ b/readconf.h +@@ -176,6 +176,8 @@ typedef struct { + + char *known_hosts_command; + ++ int required_rsa_size; /* minimum size of RSA keys */ ++ + char *ignored_unknown; /* Pattern list of unknown tokens to ignore */ + } Options; + +diff --git a/servconf.c b/servconf.c +index 29df0463..423772b1 100644 +--- a/servconf.c ++++ b/servconf.c +@@ -195,6 +195,7 @@ initialize_server_options(ServerOptions *options) + options->fingerprint_hash = -1; + options->disable_forwarding = -1; + options->expose_userauth_info = -1; ++ options->required_rsa_size = -1; + } + + /* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */ +@@ -441,6 +442,8 @@ fill_default_server_options(ServerOptions *options) + options->expose_userauth_info = 0; + if (options->sk_provider == NULL) + options->sk_provider = xstrdup("internal"); ++ if (options->required_rsa_size == -1) ++ options->required_rsa_size = SSH_RSA_MINIMUM_MODULUS_SIZE; + + assemble_algorithms(options); + +@@ -517,6 +520,7 @@ typedef enum { + sStreamLocalBindMask, sStreamLocalBindUnlink, + sAllowStreamLocalForwarding, sFingerprintHash, sDisableForwarding, + sExposeAuthInfo, sRDomain, sPubkeyAuthOptions, sSecurityKeyProvider, ++ sRequiredRSASize, + sDeprecated, sIgnore, sUnsupported + } ServerOpCodes; + +@@ -676,6 +680,8 @@ static struct { + { "rdomain", sRDomain, SSHCFG_ALL }, + { "casignaturealgorithms", sCASignatureAlgorithms, SSHCFG_ALL }, + { "securitykeyprovider", sSecurityKeyProvider, SSHCFG_GLOBAL }, ++ { "requiredrsasize", sRequiredRSASize, SSHCFG_ALL }, ++ { "rsaminsize", sRequiredRSASize, SSHCFG_ALL }, /* alias */ + { NULL, sBadOption, 0 } + }; + +@@ -2438,6 +2443,10 @@ process_server_config_line_depth(ServerOptions *options, char *line, + *charptr = xstrdup(arg); + break; + ++ case sRequiredRSASize: ++ intptr = &options->required_rsa_size; ++ goto parse_int; ++ + case sDeprecated: + case sIgnore: + case sUnsupported: +@@ -2610,6 +2619,7 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth) + M_CP_INTOPT(rekey_limit); + M_CP_INTOPT(rekey_interval); + M_CP_INTOPT(log_level); ++ M_CP_INTOPT(required_rsa_size); + + /* + * The bind_mask is a mode_t that may be unsigned, so we can't use +@@ -2874,6 +2884,7 @@ dump_config(ServerOptions *o) + dump_cfg_int(sMaxSessions, o->max_sessions); + dump_cfg_int(sClientAliveInterval, o->client_alive_interval); + dump_cfg_int(sClientAliveCountMax, o->client_alive_count_max); ++ dump_cfg_int(sRequiredRSASize, o->required_rsa_size); + dump_cfg_oct(sStreamLocalBindMask, o->fwd_opts.streamlocal_bind_mask); + + /* formatted integer arguments */ +diff --git a/servconf.h b/servconf.h +index 8a04463e..9346155c 100644 +--- a/servconf.h ++++ b/servconf.h +@@ -229,6 +229,7 @@ typedef struct { + int expose_userauth_info; + u_int64_t timing_secret; + char *sk_provider; ++ int required_rsa_size; /* minimum size of RSA keys */ + } ServerOptions; + + /* Information about the incoming connection as used by Match */ +diff --git a/ssh.c b/ssh.c +index 559bf2af..25be53d5 100644 +--- a/ssh.c ++++ b/ssh.c +@@ -516,14 +516,22 @@ resolve_canonicalize(char **hostp, int port) + } + + /* +- * Check the result of hostkey loading, ignoring some errors and +- * fatal()ing for others. ++ * Check the result of hostkey loading, ignoring some errors and either ++ * discarding the key or fatal()ing for others. + */ + static void +-check_load(int r, const char *path, const char *message) ++check_load(int r, struct sshkey **k, const char *path, const char *message) + { + switch (r) { + case 0: ++ /* Check RSA keys size and discard if undersized */ ++ if (k != NULL && *k != NULL && ++ (r = sshkey_check_rsa_length(*k, ++ options.required_rsa_size)) != 0) { ++ error_r(r, "load %s \"%s\"", message, path); ++ free(*k); ++ *k = NULL; ++ } + break; + case SSH_ERR_INTERNAL_ERROR: + case SSH_ERR_ALLOC_FAIL: +@@ -1578,7 +1586,7 @@ main(int ac, char **av) + if ((o) >= sensitive_data.nkeys) \ + fatal_f("pubkey out of array bounds"); \ + check_load(sshkey_load_public(p, &(sensitive_data.keys[o]), NULL), \ +- p, "pubkey"); \ ++ &(sensitive_data.keys[o]), p, "pubkey"); \ + } while (0) + #define L_CERT(p,o) do { \ + if ((o) >= sensitive_data.nkeys) \ +@@ -1586,7 +1594,8 @@ main(int ac, char **av) + #define L_CERT(p,o) do { \ + if ((o) >= sensitive_data.nkeys) \ + fatal_f("cert out of array bounds"); \ +- check_load(sshkey_load_cert(p, &(sensitive_data.keys[o])), p, "cert"); \ ++ check_load(sshkey_load_cert(p, &(sensitive_data.keys[o])), \ ++ &(sensitive_data.keys[o]), p, "cert"); \ + } while (0) + + if (options.hostbased_authentication == 1) { +@@ -2244,7 +2253,7 @@ load_public_identity_files(const struct ssh_conn_info *cinfo) + filename = default_client_percent_dollar_expand(cp, cinfo); + free(cp); + check_load(sshkey_load_public(filename, &public, NULL), +- filename, "pubkey"); ++ &public, filename, "pubkey"); + debug("identity file %s type %d", filename, + public ? public->type : -1); + free(options.identity_files[i]); +@@ -2284,7 +2293,7 @@ load_public_identity_files(const struct ssh_conn_info *cinfo) + continue; + xasprintf(&cp, "%s-cert", filename); + check_load(sshkey_load_public(cp, &public, NULL), +- filename, "pubkey"); ++ &public, filename, "pubkey"); + debug("identity file %s type %d", cp, + public ? public->type : -1); + if (public == NULL) { +@@ -2315,7 +2324,7 @@ load_public_identity_files(const struct ssh_conn_info *cinfo) + free(cp); + + check_load(sshkey_load_public(filename, &public, NULL), +- filename, "certificate"); ++ &public, filename, "certificate"); + debug("certificate file %s type %d", filename, + public ? public->type : -1); + free(options.certificate_files[i]); +diff --git a/sshconnect2.c b/sshconnect2.c +index f9bd19ea..58fe98db 100644 +--- a/sshconnect2.c ++++ b/sshconnect2.c +@@ -96,6 +96,11 @@ static const struct ssh_conn_info *xxx_conn_info; + static int + verify_host_key_callback(struct sshkey *hostkey, struct ssh *ssh) + { ++ int r; ++ ++ if ((r = sshkey_check_rsa_length(hostkey, ++ options.required_rsa_size)) != 0) ++ fatal_r(r, "Bad server host key"); + if (verify_host_key(xxx_host, xxx_hostaddr, hostkey, + xxx_conn_info) == -1) + fatal("Host key verification failed."); +@@ -1606,6 +1611,13 @@ load_identity_file(Identity *id) + private = NULL; + quit = 1; + } ++ if (!quit && (r = sshkey_check_rsa_length(private, ++ options.required_rsa_size)) != 0) { ++ debug_fr(r, "Skipping key %s", id->filename); ++ sshkey_free(private); ++ private = NULL; ++ quit = 1; ++ } + if (!quit && private != NULL && id->agent_fd == -1 && + !(id->key && id->isprivate)) + maybe_add_key_to_agent(id->filename, private, comment, +@@ -1752,6 +1764,12 @@ pubkey_prepare(struct ssh *ssh, Authctxt *authctxt) + close(agent_fd); + } else { + for (j = 0; j < idlist->nkeys; j++) { ++ if ((r = sshkey_check_rsa_length(idlist->keys[j], ++ options.required_rsa_size)) != 0) { ++ debug_fr(r, "ignoring %s agent key", ++ sshkey_ssh_name(idlist->keys[j])); ++ continue; ++ } + found = 0; + TAILQ_FOREACH(id, &files, next) { + /* +diff --git a/sshd.c b/sshd.c +index 17eee9d8..395ef493 100644 +--- a/sshd.c ++++ b/sshd.c +@@ -1870,6 +1870,13 @@ main(int ac, char **av) + fatal_r(r, "Could not demote key: \"%s\"", + options.host_key_files[i]); + } ++ if (pubkey != NULL && (r = sshkey_check_rsa_length(pubkey, ++ options.required_rsa_size)) != 0) { ++ error_fr(r, "Host key %s", options.host_key_files[i]); ++ sshkey_free(pubkey); ++ sshkey_free(key); ++ continue; ++ } + sensitive_data.host_keys[i] = key; + sensitive_data.host_pubkeys[i] = pubkey; + +diff --git a/sshkey.c b/sshkey.c +index ed2b5dff..77093235 100644 +--- a/sshkey.c ++++ b/sshkey.c +@@ -2365,18 +2365,24 @@ cert_parse(struct sshbuf *b, struct sshkey *key, struct sshbuf *certbuf) + return ret; + } + +-#ifdef WITH_OPENSSL +-static int +-check_rsa_length(const RSA *rsa) ++int ++sshkey_check_rsa_length(const struct sshkey *k, int min_size) + { ++#ifdef WITH_OPENSSL + const BIGNUM *rsa_n; ++ int nbits; + +- RSA_get0_key(rsa, &rsa_n, NULL, NULL); +- if (BN_num_bits(rsa_n) < SSH_RSA_MINIMUM_MODULUS_SIZE) ++ if (k == NULL || k->rsa == NULL || ++ (k->type != KEY_RSA && k->type != KEY_RSA_CERT)) ++ return 0; ++ RSA_get0_key(k->rsa, &rsa_n, NULL, NULL); ++ nbits = BN_num_bits(rsa_n); ++ if (nbits < SSH_RSA_MINIMUM_MODULUS_SIZE || ++ (min_size > 0 && nbits < min_size)) + return SSH_ERR_KEY_LENGTH; ++#endif /* WITH_OPENSSL */ + return 0; + } +-#endif + + static int + sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp, +@@ -2439,7 +2445,7 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp, + goto out; + } + rsa_n = rsa_e = NULL; /* transferred */ +- if ((ret = check_rsa_length(key->rsa)) != 0) ++ if ((ret = sshkey_check_rsa_length(key, 0)) != 0) + goto out; + #ifdef DEBUG_PK + RSA_print_fp(stderr, key->rsa, 8); +@@ -3642,7 +3648,7 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) + goto out; + } + rsa_p = rsa_q = NULL; /* transferred */ +- if ((r = check_rsa_length(k->rsa)) != 0) ++ if ((r = sshkey_check_rsa_length(k, 0)) != 0) + goto out; + if ((r = ssh_rsa_complete_crt_parameters(k, rsa_iqmp)) != 0) + goto out; +@@ -4644,7 +4650,7 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type, + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } +- if ((r = check_rsa_length(prv->rsa)) != 0) ++ if ((r = sshkey_check_rsa_length(prv, 0)) != 0) + goto out; + } else if (EVP_PKEY_base_id(pk) == EVP_PKEY_DSA && + (type == KEY_UNSPEC || type == KEY_DSA)) { +diff --git a/sshkey.h b/sshkey.h +index 094815e0..be254e6b 100644 +--- a/sshkey.h ++++ b/sshkey.h +@@ -273,6 +273,7 @@ int sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type, + int sshkey_parse_pubkey_from_private_fileblob_type(struct sshbuf *blob, + int type, struct sshkey **pubkeyp); + ++int sshkey_check_rsa_length(const struct sshkey *, int); + /* XXX should be internal, but used by ssh-keygen */ + int ssh_rsa_complete_crt_parameters(struct sshkey *, const BIGNUM *); + +diff --git a/ssh.1 b/ssh.1 +index b4956aec..e255b9b9 100644 +--- a/ssh.1 ++++ b/ssh.1 +@@ -571,6 +571,7 @@ For full details of the options listed below, and their possible values, see + .It RemoteCommand + .It RemoteForward + .It RequestTTY ++.It RequiredRSASize + .It SendEnv + .It ServerAliveInterval + .It ServerAliveCountMax +diff --git a/ssh_config.5 b/ssh_config.5 +index 24a46460..d1ede18e 100644 +--- a/ssh_config.5 ++++ b/ssh_config.5 +@@ -1634,6 +1634,17 @@ and + .Fl T + flags for + .Xr ssh 1 . ++.It Cm RequiredRSASize ++Specifies the minimum RSA key size (in bits) that ++.Xr ssh 1 ++will accept. ++User authentication keys smaller than this limit will be ignored. ++Servers that present host keys smaller than this limit will cause the ++connection to be terminated. ++The default is ++.Cm 1024 ++bits. ++Note that this limit may only be raised from the default. + .It Cm RevokedHostKeys + Specifies revoked host public keys. + Keys listed in this file will be refused for host authentication. +diff --git a/sshd_config.5 b/sshd_config.5 +index 867a747d..f5a06637 100644 +--- a/sshd_config.5 ++++ b/sshd_config.5 +@@ -1596,6 +1596,16 @@ is + .Cm default none , + which means that rekeying is performed after the cipher's default amount + of data has been sent or received and no time based rekeying is done. ++.It Cm RequiredRSASize ++Specifies the minimum RSA key size (in bits) that ++.Xr sshd 8 ++will accept. ++User and host-based authentication keys smaller than this limit will be ++refused. ++The default is ++.Cm 1024 ++bits. ++Note that this limit may only be raised from the default. + .It Cm RevokedKeys + Specifies revoked public keys file, or + .Cm none diff --git a/openssh-8.7p1-negotiate-supported-algs.patch b/openssh-8.7p1-negotiate-supported-algs.patch new file mode 100644 index 0000000..2fb9297 --- /dev/null +++ b/openssh-8.7p1-negotiate-supported-algs.patch @@ -0,0 +1,63 @@ +diff --color -rup a/regress/hostkey-agent.sh b/regress/hostkey-agent.sh +--- a/regress/hostkey-agent.sh 2021-08-20 06:03:49.000000000 +0200 ++++ b/regress/hostkey-agent.sh 2022-07-14 11:58:12.172786060 +0200 +@@ -13,8 +13,12 @@ r=$? + grep -vi 'hostkey' $OBJ/sshd_proxy > $OBJ/sshd_proxy.orig + echo "HostKeyAgent $SSH_AUTH_SOCK" >> $OBJ/sshd_proxy.orig + ++PUBKEY_ACCEPTED_ALGOS=`$SSH -G "example.com" | \ ++ grep -i "PubkeyAcceptedAlgorithms" | cut -d ' ' -f2- | tr "," "|"` ++SSH_ACCEPTED_KEYTYPES=`echo "$SSH_KEYTYPES" | egrep "$PUBKEY_ACCEPTED_ALGOS"` ++ + trace "load hostkeys" +-for k in $SSH_KEYTYPES ; do ++for k in $SSH_ACCEPTED_KEYTYPES ; do + ${SSHKEYGEN} -qt $k -f $OBJ/agent-key.$k -N '' || fatal "ssh-keygen $k" + ( + printf 'localhost-with-alias,127.0.0.1,::1 ' +@@ -31,7 +35,7 @@ cp $OBJ/known_hosts.orig $OBJ/known_host + unset SSH_AUTH_SOCK + + for ps in yes; do +- for k in $SSH_KEYTYPES ; do ++ for k in $SSH_ACCEPTED_KEYTYPES ; do + verbose "key type $k privsep=$ps" + cp $OBJ/sshd_proxy.orig $OBJ/sshd_proxy + echo "UsePrivilegeSeparation $ps" >> $OBJ/sshd_proxy +diff --color -rup a/sshconnect2.c b/sshconnect2.c +--- a/sshconnect2.c 2022-07-14 10:10:07.262975710 +0200 ++++ b/sshconnect2.c 2022-07-14 10:10:32.068452067 +0200 +@@ -222,6 +222,7 @@ ssh_kex2(struct ssh *ssh, char *host, st + { + char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT }; + char *s, *all_key; ++ char *hostkeyalgs = NULL, *pkalg = NULL; + char *prop_kex = NULL, *prop_enc = NULL, *prop_hostkey = NULL; + int r, use_known_hosts_order = 0; + +@@ -264,14 +265,19 @@ ssh_kex2(struct ssh *ssh, char *host, st + myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs; + if (use_known_hosts_order) { + /* Query known_hosts and prefer algorithms that appear there */ +- myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = prop_hostkey = +- compat_pkalg_proposal(ssh, +- order_hostkeyalgs(host, hostaddr, port, cinfo)); ++ if ((hostkeyalgs = order_hostkeyalgs(host, hostaddr, port, cinfo)) == NULL) ++ fatal_f("order_hostkeyalgs"); ++ pkalg = match_filter_allowlist(hostkeyalgs, options.pubkey_accepted_algos); ++ free(hostkeyalgs); + } else { +- /* Use specified HostkeyAlgorithms exactly */ +- myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = prop_hostkey = +- compat_pkalg_proposal(ssh, options.hostkeyalgorithms); ++ /* Use specified HostkeyAlgorithms */ ++ pkalg = match_filter_allowlist(options.hostkeyalgorithms, options.pubkey_accepted_algos); + } ++ if (pkalg == NULL) ++ fatal_f("match_filter_allowlist"); ++ myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = prop_hostkey = ++ compat_pkalg_proposal(ssh, pkalg); ++ free(pkalg); + + #if defined(GSSAPI) && defined(WITH_OPENSSL) + if (options.gss_keyex) { diff --git a/openssh-8.7p1-ssh-manpage.patch b/openssh-8.7p1-ssh-manpage.patch new file mode 100644 index 0000000..04e4c06 --- /dev/null +++ b/openssh-8.7p1-ssh-manpage.patch @@ -0,0 +1,53 @@ +diff --color -ru a/ssh.1 b/ssh.1 +--- a/ssh.1 2022-07-12 11:47:51.307295880 +0200 ++++ b/ssh.1 2022-07-12 11:50:28.793363263 +0200 +@@ -493,6 +493,7 @@ + .It AddressFamily + .It BatchMode + .It BindAddress ++.It BindInterface + .It CanonicalDomains + .It CanonicalizeFallbackLocal + .It CanonicalizeHostname +@@ -510,6 +511,7 @@ + .It ControlPath + .It ControlPersist + .It DynamicForward ++.It EnableSSHKeysign + .It EscapeChar + .It ExitOnForwardFailure + .It FingerprintHash +@@ -538,6 +540,8 @@ + .It IdentitiesOnly + .It IdentityAgent + .It IdentityFile ++.It IgnoreUnknown ++.It Include + .It IPQoS + .It KbdInteractiveAuthentication + .It KbdInteractiveDevices +@@ -546,6 +550,7 @@ + .It LocalCommand + .It LocalForward + .It LogLevel ++.It LogVerbose + .It MACs + .It Match + .It NoHostAuthenticationForLocalhost +@@ -566,6 +571,8 @@ + .It RemoteCommand + .It RemoteForward + .It RequestTTY ++.It RevokedHostKeys ++.It SecurityKeyProvider + .It RequiredRSASize + .It SendEnv + .It ServerAliveInterval +@@ -575,6 +582,7 @@ + .It StreamLocalBindMask + .It StreamLocalBindUnlink + .It StrictHostKeyChecking ++.It SyslogFacility + .It TCPKeepAlive + .It Tunnel + .It TunnelDevice From a0a72f43ad869350ea7283aed41c125120995dc7 Mon Sep 17 00:00:00 2001 From: Mattias Ellert Date: Wed, 10 May 2023 07:04:20 +0200 Subject: [PATCH 06/11] Based on openssh-8.7p1-29.el9_2 --- gsi-openssh.spec | 17 ++++- openssh-7.7p1-fips.patch | 54 ++++++++++++-- openssh-8.7p1-CVE-2023-25136.patch | 38 ++++++++++ openssh-8.7p1-hpn-15.2-modified.patch | 4 +- openssh-8.7p1-nohostsha1proof.patch | 100 ++++++++++++++++++++++++++ openssh-9.1p1-sshbanner.patch | 57 +++++++++++++++ 6 files changed, 260 insertions(+), 10 deletions(-) create mode 100644 openssh-8.7p1-CVE-2023-25136.patch create mode 100644 openssh-8.7p1-nohostsha1proof.patch create mode 100644 openssh-9.1p1-sshbanner.patch diff --git a/gsi-openssh.spec b/gsi-openssh.spec index 5ad48af..10c699c 100644 --- a/gsi-openssh.spec +++ b/gsi-openssh.spec @@ -28,7 +28,7 @@ %global libedit 1 %global openssh_ver 8.7p1 -%global openssh_rel 7 +%global openssh_rel 8 Summary: An implementation of the SSH protocol with GSI authentication Name: gsi-openssh @@ -175,6 +175,8 @@ Patch983: openssh-8.7p1-evpgenkey.patch # downstream only, IBMCA tentative fix # From https://bugzilla.redhat.com/show_bug.cgi?id=1976202#c14 Patch984: openssh-8.7p1-ibmca.patch +# Upstream ff89b1bed80721295555bd083b173247a9c0484e, 5062ad48814b06162511c4f5924a33d97b6b2566 +Patch986: openssh-9.1p1-sshbanner.patch # Minimize the use of SHA1 as a proof of possession for RSA key (#2031868) # upstream commits: @@ -211,6 +213,12 @@ Patch1005: openssh-8.7p1-host-based-auth.patch # upstream MR: # https://github.com/openssh/openssh-portable/pull/323 Patch1006: openssh-8.7p1-negotiate-supported-algs.patch +# +Patch1007: openssh-8.7p1-nohostsha1proof.patch +# CVE-2023-25136 +# upstream 12da7823336434a403f25c7cc0c2c6aed0737a35 +# to fix 1005 +Patch1008: openssh-8.7p1-CVE-2023-25136.patch # This is the patch that adds GSI support # Based on hpn_isshd-gsi.7.5p1b.patch from Globus upstream @@ -364,6 +372,7 @@ gpgv2 --quiet --keyring %{SOURCE3} %{SOURCE1} %{SOURCE0} %patch982 -p1 -b .minrsabits %patch983 -p1 -b .evpgenrsa %patch984 -p1 -b .ibmca +%patch986 -p1 -b .91cleanup %patch200 -p1 -b .audit %patch201 -p1 -b .audit-race @@ -379,6 +388,9 @@ gpgv2 --quiet --keyring %{SOURCE3} %{SOURCE1} %{SOURCE0} %patch100 -p1 -b .coverity +%patch1007 -p1 -b .sshrsacheck +%patch1008 -p1 -b .cve-2023-25136 + %patch98 -p1 -b .gsi %patch99 -p1 -b .hpn @@ -567,6 +579,9 @@ getent passwd sshd >/dev/null || \ %attr(0644,root,root) %{_unitdir}/gsisshd-keygen.target %changelog +* Wed May 10 2023 Mattias Ellert - 8.7p1-8 +- Based on openssh-8.7p1-29.el9_2 + * Wed Oct 05 2022 Mattias Ellert - 8.7p1-7 - Based on openssh-8.7p1-24.el9 diff --git a/openssh-7.7p1-fips.patch b/openssh-7.7p1-fips.patch index 1466b40..05b2907 100644 --- a/openssh-7.7p1-fips.patch +++ b/openssh-7.7p1-fips.patch @@ -1,6 +1,14 @@ diff -up openssh-8.6p1/dh.c.fips openssh-8.6p1/dh.c --- openssh-8.6p1/dh.c.fips 2021-04-16 05:55:25.000000000 +0200 +++ openssh-8.6p1/dh.c 2021-05-06 12:12:10.107634472 +0200 +@@ -36,6 +36,7 @@ + + #include + #include ++#include + + #include "dh.h" + #include "pathnames.h" @@ -164,6 +164,12 @@ choose_dh(int min, int wantbits, int max int best, bestcount, which, linenum; struct dhgroup dhg; @@ -67,6 +75,14 @@ diff -up openssh-8.6p1/dh.h.fips openssh-8.6p1/dh.h diff -up openssh-8.6p1/kex.c.fips openssh-8.6p1/kex.c --- openssh-8.6p1/kex.c.fips 2021-05-06 12:08:36.489926807 +0200 +++ openssh-8.6p1/kex.c 2021-05-06 12:08:36.498926877 +0200 +@@ -39,6 +39,7 @@ + + #ifdef WITH_OPENSSL + #include ++#include + #include + # ifdef HAVE_EVP_KDF_CTX_NEW_ID + # include @@ -203,7 +203,10 @@ kex_names_valid(const char *names) for ((p = strsep(&cp, ",")); p && *p != '\0'; (p = strsep(&cp, ","))) { @@ -86,7 +102,7 @@ diff -up openssh-8.6p1/kexgexc.c.fips openssh-8.6p1/kexgexc.c #ifdef WITH_OPENSSL -+#include ++#include #include #include @@ -154,6 +170,14 @@ diff -up openssh-8.6p1/myproposal.h.fips openssh-8.6p1/myproposal.h diff -up openssh-8.6p1/readconf.c.fips openssh-8.6p1/readconf.c --- openssh-8.6p1/readconf.c.fips 2021-05-06 12:08:36.428926336 +0200 +++ openssh-8.6p1/readconf.c 2021-05-06 12:08:36.499926885 +0200 +@@ -39,6 +39,7 @@ + #include + #include + #include ++#include + #ifdef USE_SYSTEM_GLOB + # include + #else @@ -2538,11 +2538,16 @@ fill_default_options(Options * options) all_key = sshkey_alg_list(0, 0, 1, ','); all_sig = sshkey_alg_list(0, 1, 1, ','); @@ -192,6 +216,14 @@ diff -up openssh-8.6p1/sandbox-seccomp-filter.c.fips openssh-8.6p1/sandbox-secco diff -up openssh-8.6p1/servconf.c.fips openssh-8.6p1/servconf.c --- openssh-8.6p1/servconf.c.fips 2021-05-06 12:08:36.455926545 +0200 +++ openssh-8.6p1/servconf.c 2021-05-06 12:08:36.500926893 +0200 +@@ -38,6 +38,7 @@ + #include + #include + #include ++#include + #ifdef HAVE_UTIL_H + #include + #endif @@ -226,11 +226,16 @@ assemble_algorithms(ServerOptions *o) all_key = sshkey_alg_list(0, 0, 1, ','); all_sig = sshkey_alg_list(0, 1, 1, ','); @@ -221,7 +253,7 @@ diff -up openssh-8.6p1/ssh.c.fips openssh-8.6p1/ssh.c #include #include #endif -+#include ++#include #include "openbsd-compat/openssl-compat.h" #include "openbsd-compat/sys-queue.h" @@ -243,7 +275,7 @@ diff -up openssh-8.6p1/sshconnect2.c.fips openssh-8.6p1/sshconnect2.c #include #endif -+#include ++#include + #include "openbsd-compat/sys-queue.h" @@ -332,7 +364,7 @@ diff -up openssh-8.6p1/sshd.c.fips openssh-8.6p1/sshd.c #include #include #include -+#include ++#include #include "openbsd-compat/openssl-compat.h" #endif @@ -395,7 +427,7 @@ diff -up openssh-8.6p1/sshkey.c.fips openssh-8.6p1/sshkey.c #include #include #include -+#include ++#include #endif #include "crypto_api.h" @@ -482,6 +514,14 @@ diff -up openssh-8.6p1/sshkey.c.fips openssh-8.6p1/sshkey.c diff -up openssh-8.6p1/ssh-keygen.c.fips openssh-8.6p1/ssh-keygen.c --- openssh-8.6p1/ssh-keygen.c.fips 2021-05-06 12:08:36.467926637 +0200 +++ openssh-8.6p1/ssh-keygen.c 2021-05-06 12:08:36.503926916 +0200 +@@ -20,6 +20,7 @@ + + #ifdef WITH_OPENSSL + #include ++#include + #include + #include "openbsd-compat/openssl-compat.h" + #endif @@ -205,6 +205,12 @@ type_bits_valid(int type, const char *na #endif } @@ -521,7 +561,7 @@ diff -up openssh-8.7p1/kexgen.c.fips3 openssh-8.7p1/kexgen.c #include #include #include -+#include ++#include #include "sshkey.h" #include "kex.h" @@ -607,7 +647,7 @@ diff -up openssh-8.7p1/ssh-ed25519.c.fips3 openssh-8.7p1/ssh-ed25519.c #include #include -+#include ++#include #include "log.h" #include "sshbuf.h" diff --git a/openssh-8.7p1-CVE-2023-25136.patch b/openssh-8.7p1-CVE-2023-25136.patch new file mode 100644 index 0000000..ca661ee --- /dev/null +++ b/openssh-8.7p1-CVE-2023-25136.patch @@ -0,0 +1,38 @@ +diff --git a/compat.c b/compat.c +index 46dfe3a9c2e..478a9403eea 100644 +--- a/compat.c ++++ b/compat.c +@@ -190,26 +190,26 @@ compat_pkalg_proposal(struct ssh *ssh, char *pkalg_prop) + char * + compat_kex_proposal(struct ssh *ssh, char *p) + { +- char *cp = NULL; ++ char *cp = NULL, *cp2 = NULL; + + if ((ssh->compat & (SSH_BUG_CURVE25519PAD|SSH_OLD_DHGEX)) == 0) + return xstrdup(p); + debug2_f("original KEX proposal: %s", p); + if ((ssh->compat & SSH_BUG_CURVE25519PAD) != 0) +- if ((p = match_filter_denylist(p, ++ if ((cp = match_filter_denylist(p, + "curve25519-sha256@libssh.org")) == NULL) + fatal("match_filter_denylist failed"); + if ((ssh->compat & SSH_OLD_DHGEX) != 0) { +- cp = p; +- if ((p = match_filter_denylist(p, ++ if ((cp2 = match_filter_denylist(cp ? cp : p, + "diffie-hellman-group-exchange-sha256," + "diffie-hellman-group-exchange-sha1")) == NULL) + fatal("match_filter_denylist failed"); + free(cp); ++ cp = cp2; + } +- debug2_f("compat KEX proposal: %s", p); +- if (*p == '\0') ++ if (cp == NULL || *cp == '\0') + fatal("No supported key exchange algorithms found"); +- return p; ++ debug2_f("compat KEX proposal: %s", cp); ++ return cp; + } + diff --git a/openssh-8.7p1-hpn-15.2-modified.patch b/openssh-8.7p1-hpn-15.2-modified.patch index 2ddbe63..23c3fb7 100644 --- a/openssh-8.7p1-hpn-15.2-modified.patch +++ b/openssh-8.7p1-hpn-15.2-modified.patch @@ -1012,9 +1012,9 @@ diff -Nur openssh-8.7p1.orig/compat.c openssh-8.7p1/compat.c --- openssh-8.7p1.orig/compat.c 2021-10-24 07:54:36.849834155 +0200 +++ openssh-8.7p1/compat.c 2021-10-24 07:56:04.850030003 +0200 @@ -151,6 +151,17 @@ - debug_f("match: %s pat %s compat 0x%08x", - version, check[i].pat, check[i].bugs); ssh->compat = check[i].bugs; + if (forbid_ssh_rsa) + ssh->compat |= SSH_RH_RSASIGSHA; + /* Check to see if the remote side is OpenSSH and not HPN */ + /* TODO: See if we can work this into the new method for bug checks */ + if (strstr(version, "OpenSSH") != NULL) { diff --git a/openssh-8.7p1-nohostsha1proof.patch b/openssh-8.7p1-nohostsha1proof.patch new file mode 100644 index 0000000..a5323e4 --- /dev/null +++ b/openssh-8.7p1-nohostsha1proof.patch @@ -0,0 +1,100 @@ +diff -up openssh-8.7p1/compat.c.sshrsacheck openssh-8.7p1/compat.c +--- openssh-8.7p1/compat.c.sshrsacheck 2023-01-12 13:29:06.338710923 +0100 ++++ openssh-8.7p1/compat.c 2023-01-12 13:29:06.357711165 +0100 +@@ -43,6 +43,7 @@ void + compat_banner(struct ssh *ssh, const char *version) + { + int i; ++ int forbid_ssh_rsa = 0; + static struct { + char *pat; + int bugs; +@@ -145,16 +146,21 @@ compat_banner(struct ssh *ssh, const cha + }; + + /* process table, return first match */ ++ forbid_ssh_rsa = (ssh->compat & SSH_RH_RSASIGSHA); + ssh->compat = 0; + for (i = 0; check[i].pat; i++) { + if (match_pattern_list(version, check[i].pat, 0) == 1) { + debug_f("match: %s pat %s compat 0x%08x", + version, check[i].pat, check[i].bugs); + ssh->compat = check[i].bugs; ++ if (forbid_ssh_rsa) ++ ssh->compat |= SSH_RH_RSASIGSHA; + return; + } + } + debug_f("no match: %s", version); ++ if (forbid_ssh_rsa) ++ ssh->compat |= SSH_RH_RSASIGSHA; + } + + /* Always returns pointer to allocated memory, caller must free. */ +diff -up openssh-8.7p1/compat.h.sshrsacheck openssh-8.7p1/compat.h +--- openssh-8.7p1/compat.h.sshrsacheck 2021-08-20 06:03:49.000000000 +0200 ++++ openssh-8.7p1/compat.h 2023-01-12 13:29:06.358711178 +0100 +@@ -30,7 +30,7 @@ + #define SSH_BUG_UTF8TTYMODE 0x00000001 + #define SSH_BUG_SIGTYPE 0x00000002 + #define SSH_BUG_SIGTYPE74 0x00000004 +-/* #define unused 0x00000008 */ ++#define SSH_RH_RSASIGSHA 0x00000008 + #define SSH_OLD_SESSIONID 0x00000010 + /* #define unused 0x00000020 */ + #define SSH_BUG_DEBUG 0x00000040 +diff -up openssh-8.7p1/serverloop.c.sshrsacheck openssh-8.7p1/serverloop.c +--- openssh-8.7p1/serverloop.c.sshrsacheck 2023-01-12 14:57:08.118400073 +0100 ++++ openssh-8.7p1/serverloop.c 2023-01-12 14:59:17.330470518 +0100 +@@ -737,6 +737,10 @@ server_input_hostkeys_prove(struct ssh * + else if (ssh->kex->flags & KEX_RSA_SHA2_256_SUPPORTED) + sigalg = "rsa-sha2-256"; + } ++ if (ssh->compat & SSH_RH_RSASIGSHA && sigalg == NULL) { ++ sigalg = "rsa-sha2-512"; ++ debug3_f("SHA1 signature is not supported, falling back to %s", sigalg); ++ } + debug3_f("sign %s key (index %d) using sigalg %s", + sshkey_type(key), ndx, sigalg == NULL ? "default" : sigalg); + if ((r = sshbuf_put_cstring(sigbuf, +diff -up openssh-8.7p1/sshd.c.sshrsacheck openssh-8.7p1/sshd.c +--- openssh-8.7p1/sshd.c.sshrsacheck 2023-01-12 13:29:06.355711140 +0100 ++++ openssh-8.7p1/sshd.c 2023-01-12 13:29:06.358711178 +0100 +@@ -1640,6 +1651,7 @@ main(int ac, char **av) + int keytype; + Authctxt *authctxt; + struct connection_info *connection_info = NULL; ++ int forbid_ssh_rsa = 0; + + #ifdef HAVE_SECUREWARE + (void)set_auth_parameters(ac, av); +@@ -1938,6 +1950,19 @@ main(int ac, char **av) + key = NULL; + continue; + } ++ if (key && (sshkey_type_plain(key->type) == KEY_RSA || sshkey_type_plain(key->type) == KEY_RSA_CERT)) { ++ size_t sign_size = 0; ++ u_char *tmp = NULL; ++ u_char data[] = "Test SHA1 vector"; ++ int res; ++ ++ res = ssh_rsa_sign(key, &tmp, &sign_size, data, sizeof(data), NULL); ++ free(tmp); ++ if (res == SSH_ERR_LIBCRYPTO_ERROR) { ++ logit_f("sshd: ssh-rsa algorithm is disabled"); ++ forbid_ssh_rsa = 1; ++ } ++ } + if (sshkey_is_sk(key) && + key->sk_flags & SSH_SK_USER_PRESENCE_REQD) { + debug("host key %s requires user presence, ignoring", +@@ -2275,6 +2306,9 @@ main(int ac, char **av) + + check_ip_options(ssh); + ++ if (forbid_ssh_rsa) ++ ssh->compat |= SSH_RH_RSASIGSHA; ++ + /* Prepare the channels layer */ + channel_init_channels(ssh); + channel_set_af(ssh, options.address_family); diff --git a/openssh-9.1p1-sshbanner.patch b/openssh-9.1p1-sshbanner.patch new file mode 100644 index 0000000..57112be --- /dev/null +++ b/openssh-9.1p1-sshbanner.patch @@ -0,0 +1,57 @@ +diff --git a/ssh-keyscan.c b/ssh-keyscan.c +index d29a03b4..d7283136 100644 +--- a/ssh-keyscan.c ++++ b/ssh-keyscan.c +@@ -490,6 +490,15 @@ congreet(int s) + return; + } + ++ /* ++ * Read the server banner as per RFC4253 section 4.2. The "SSH-" ++ * protocol identification string may be preceeded by an arbitarily ++ * large banner which we must read and ignore. Loop while reading ++ * newline-terminated lines until we have one starting with "SSH-". ++ * The ID string cannot be longer than 255 characters although the ++ * preceeding banner lines may (in which case they'll be discarded ++ * in multiple iterations of the outer loop). ++ */ + for (;;) { + memset(buf, '\0', sizeof(buf)); + bufsiz = sizeof(buf); +@@ -517,6 +526,11 @@ congreet(int s) + conrecycle(s); + return; + } ++ if (cp >= buf + sizeof(buf)) { ++ error("%s: greeting exceeds allowable length", c->c_name); ++ confree(s); ++ return; ++ } + if (*cp != '\n' && *cp != '\r') { + error("%s: bad greeting", c->c_name); + confree(s); +diff --git a/sshsig.c b/sshsig.c +index 1e3b6398..eb2a931e 100644 +--- a/sshsig.c ++++ b/sshsig.c +@@ -491,7 +491,7 @@ hash_file(int fd, const char *hashalg, struct sshbuf **bp) + { + char *hex, rbuf[8192], hash[SSH_DIGEST_MAX_LENGTH]; + ssize_t n, total = 0; +- struct ssh_digest_ctx *ctx; ++ struct ssh_digest_ctx *ctx = NULL; + int alg, oerrno, r = SSH_ERR_INTERNAL_ERROR; + struct sshbuf *b = NULL; + +@@ -549,9 +548,11 @@ hash_file(int fd, const char *hashalg, struct sshbuf **bp) + /* success */ + r = 0; + out: ++ oerrno = errno; + sshbuf_free(b); + ssh_digest_free(ctx); + explicit_bzero(hash, sizeof(hash)); ++ errno = oerrno; + return r; + } + From d62aba264c2d30d753753b9a8d2be5e77852162d Mon Sep 17 00:00:00 2001 From: Mattias Ellert Date: Fri, 11 Aug 2023 15:45:11 +0200 Subject: [PATCH 07/11] Based on openssh-8.7p1-30.el9_2 --- gsi-openssh.spec | 9 ++++++++- openssh-8.7p1-hpn-15.2-modified.patch | 4 +--- openssh-9.3p1-upstream-cve-2023-38408.patch | 17 +++++++++++++++++ 3 files changed, 26 insertions(+), 4 deletions(-) create mode 100644 openssh-9.3p1-upstream-cve-2023-38408.patch diff --git a/gsi-openssh.spec b/gsi-openssh.spec index 10c699c..6af2cf2 100644 --- a/gsi-openssh.spec +++ b/gsi-openssh.spec @@ -28,7 +28,7 @@ %global libedit 1 %global openssh_ver 8.7p1 -%global openssh_rel 8 +%global openssh_rel 9 Summary: An implementation of the SSH protocol with GSI authentication Name: gsi-openssh @@ -219,6 +219,9 @@ Patch1007: openssh-8.7p1-nohostsha1proof.patch # upstream 12da7823336434a403f25c7cc0c2c6aed0737a35 # to fix 1005 Patch1008: openssh-8.7p1-CVE-2023-25136.patch +# upsream commit +# b23fe83f06ee7e721033769cfa03ae840476d280 +Patch1015: openssh-9.3p1-upstream-cve-2023-38408.patch # This is the patch that adds GSI support # Based on hpn_isshd-gsi.7.5p1b.patch from Globus upstream @@ -390,6 +393,7 @@ gpgv2 --quiet --keyring %{SOURCE3} %{SOURCE1} %{SOURCE0} %patch1007 -p1 -b .sshrsacheck %patch1008 -p1 -b .cve-2023-25136 +%patch1015 -p1 -b .cve-2023-38408 %patch98 -p1 -b .gsi %patch99 -p1 -b .hpn @@ -579,6 +583,9 @@ getent passwd sshd >/dev/null || \ %attr(0644,root,root) %{_unitdir}/gsisshd-keygen.target %changelog +* Wed Aug 09 2023 Mattias Ellert - 8.7p1-9 +- Based on openssh-8.7p1-30.el9_2 + * Wed May 10 2023 Mattias Ellert - 8.7p1-8 - Based on openssh-8.7p1-29.el9_2 diff --git a/openssh-8.7p1-hpn-15.2-modified.patch b/openssh-8.7p1-hpn-15.2-modified.patch index 23c3fb7..e621d17 100644 --- a/openssh-8.7p1-hpn-15.2-modified.patch +++ b/openssh-8.7p1-hpn-15.2-modified.patch @@ -2355,12 +2355,10 @@ diff -Nur openssh-8.7p1.orig/sshconnect2.c openssh-8.7p1/sshconnect2.c void ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port, const struct ssh_conn_info *cinfo) -@@ -225,6 +234,10 @@ +@@ -225,6 +234,8 @@ char *gss_host = NULL; #endif -+ memcpy(&myproposal, &myproposal_default, sizeof(myproposal)); -+ + memcpy(&myproposal, &myproposal_default, sizeof(myproposal)); + xxx_host = host; diff --git a/openssh-9.3p1-upstream-cve-2023-38408.patch b/openssh-9.3p1-upstream-cve-2023-38408.patch new file mode 100644 index 0000000..5632ba1 --- /dev/null +++ b/openssh-9.3p1-upstream-cve-2023-38408.patch @@ -0,0 +1,17 @@ +diff --git a/ssh-pkcs11.c b/ssh-pkcs11.c +index 6be647ec..ebddf6c3 100644 +--- a/ssh-pkcs11.c ++++ b/ssh-pkcs11.c +@@ -1537,10 +1537,8 @@ pkcs11_register_provider(char *provider_id, char *pin, + error("dlopen %s failed: %s", provider_module, dlerror()); + goto fail; + } +- if ((getfunctionlist = dlsym(handle, "C_GetFunctionList")) == NULL) { +- error("dlsym(C_GetFunctionList) failed: %s", dlerror()); +- goto fail; +- } ++ if ((getfunctionlist = dlsym(handle, "C_GetFunctionList")) == NULL) ++ fatal("dlsym(C_GetFunctionList) failed: %s", dlerror()); + + p->module->handle = handle; + /* setup the pkcs11 callbacks */ From 02ec8a90c4da5b4b6e384fe211e3687ef2ced6a3 Mon Sep 17 00:00:00 2001 From: Mattias Ellert Date: Wed, 10 Jul 2024 15:44:12 +0200 Subject: [PATCH 08/11] Based on openssh-8.7p1-38.el9_4.1 --- gsi-openssh-server-systemd-sysusers.conf | 2 + gsi-openssh-systemd-sysusers.conf | 2 + gsi-openssh.spec | 62 +- openssh-6.7p1-coverity.patch | 27 - openssh-8.7p1-UTC-time-parse.patch | 323 ++++ openssh-8.7p1-evp-fips-compl-dh.patch | 292 +++ openssh-8.7p1-evp-fips-compl-ecdh.patch | 207 +++ openssh-8.7p1-evp-fips-compl-sign.patch | 468 +++++ openssh-8.7p1-evp-pkcs11.patch | 131 ++ ...fied.patch => openssh-8.7p1-hpn-15.4.patch | 1641 ++++++++++++++--- openssh-8.7p1-man-hostkeyalgos.patch | 31 + openssh-8.7p1-nohostsha1proof.patch | 332 +++- openssh-9.3p1-openssl-compat.patch | 52 + openssh-9.4p2-limit-delay.patch | 33 + openssh-9.6p1-CVE-2023-48795.patch | 447 +++++ openssh-9.6p1-CVE-2023-51385.patch | 57 + openssh-9.8p1-upstream-cve-2024-6387.patch | 18 + 17 files changed, 3789 insertions(+), 336 deletions(-) create mode 100644 gsi-openssh-server-systemd-sysusers.conf create mode 100644 gsi-openssh-systemd-sysusers.conf create mode 100644 openssh-8.7p1-UTC-time-parse.patch create mode 100644 openssh-8.7p1-evp-fips-compl-dh.patch create mode 100644 openssh-8.7p1-evp-fips-compl-ecdh.patch create mode 100644 openssh-8.7p1-evp-fips-compl-sign.patch create mode 100644 openssh-8.7p1-evp-pkcs11.patch rename openssh-8.7p1-hpn-15.2-modified.patch => openssh-8.7p1-hpn-15.4.patch (61%) create mode 100644 openssh-8.7p1-man-hostkeyalgos.patch create mode 100644 openssh-9.3p1-openssl-compat.patch create mode 100644 openssh-9.4p2-limit-delay.patch create mode 100644 openssh-9.6p1-CVE-2023-48795.patch create mode 100644 openssh-9.6p1-CVE-2023-51385.patch create mode 100644 openssh-9.8p1-upstream-cve-2024-6387.patch diff --git a/gsi-openssh-server-systemd-sysusers.conf b/gsi-openssh-server-systemd-sysusers.conf new file mode 100644 index 0000000..419c529 --- /dev/null +++ b/gsi-openssh-server-systemd-sysusers.conf @@ -0,0 +1,2 @@ +#Type Name ID GECOS Home directory Shell +u sshd 74 "Privilege-separated SSH" /usr/share/empty.sshd - diff --git a/gsi-openssh-systemd-sysusers.conf b/gsi-openssh-systemd-sysusers.conf new file mode 100644 index 0000000..1192c0b --- /dev/null +++ b/gsi-openssh-systemd-sysusers.conf @@ -0,0 +1,2 @@ +#Type Name ID +g ssh_keys 101 diff --git a/gsi-openssh.spec b/gsi-openssh.spec index 6af2cf2..fe6cc56 100644 --- a/gsi-openssh.spec +++ b/gsi-openssh.spec @@ -10,10 +10,6 @@ %global _hardened_build 1 -# OpenSSH privilege separation requires a user & group ID -%global sshd_uid 74 -%global sshd_gid 74 - # Build position-independent executables (requires toolchain support)? %global pie 1 @@ -28,7 +24,7 @@ %global libedit 1 %global openssh_ver 8.7p1 -%global openssh_rel 9 +%global openssh_rel 10 Summary: An implementation of the SSH protocol with GSI authentication Name: gsi-openssh @@ -48,6 +44,8 @@ Source11: gsisshd.service Source12: gsisshd-keygen@.service Source13: gsisshd-keygen Source15: gsisshd-keygen.target +Source17: %{name}-systemd-sysusers.conf +Source18: %{name}-server-systemd-sysusers.conf Source99: README.sshd-and-gsisshd #https://bugzilla.mindrot.org/show_bug.cgi?id=2581 @@ -219,17 +217,40 @@ Patch1007: openssh-8.7p1-nohostsha1proof.patch # upstream 12da7823336434a403f25c7cc0c2c6aed0737a35 # to fix 1005 Patch1008: openssh-8.7p1-CVE-2023-25136.patch + +# fips compliance for signing, dh, ecdh +Patch1009: openssh-8.7p1-evp-fips-compl-sign.patch +Patch1010: openssh-8.7p1-evp-fips-compl-dh.patch +Patch1011: openssh-8.7p1-evp-fips-compl-ecdh.patch +Patch1012: openssh-8.7p1-evp-pkcs11.patch + +# clarify rhbz#2068423 on the man page of ssh_config +Patch1013: openssh-8.7p1-man-hostkeyalgos.patch +# upstream commits +# ec1ddb72a146fd66d18df9cd423517453a5d8044 +# b98a42afb69d60891eb0488935990df6ee571c4 +# a00f59a645072e5f5a8d207af15916a7b23e2642 +Patch1014: openssh-8.7p1-UTC-time-parse.patch # upsream commit # b23fe83f06ee7e721033769cfa03ae840476d280 Patch1015: openssh-9.3p1-upstream-cve-2023-38408.patch +#upstream commit b7afd8a4ecaca8afd3179b55e9db79c0ff210237 +Patch1016: openssh-9.3p1-openssl-compat.patch +#upstream commit 01dbf3d46651b7d6ddf5e45d233839bbfffaeaec +Patch1017: openssh-9.4p2-limit-delay.patch +#upstream commit 1edb00c58f8a6875fad6a497aa2bacf37f9e6cd5 +Patch1018: openssh-9.6p1-CVE-2023-48795.patch +#upstream commit 7ef3787c84b6b524501211b11a26c742f829af1a +Patch1019: openssh-9.6p1-CVE-2023-51385.patch +Patch1020: openssh-9.8p1-upstream-cve-2024-6387.patch # This is the patch that adds GSI support # Based on hpn_isshd-gsi.7.5p1b.patch from Globus upstream Patch98: openssh-8.7p1-gsissh.patch # This is the HPN patch -# Based on https://sourceforge.net/projects/hpnssh/files/Patches/HPN-SSH%2015v2%208.5p1/ -Patch99: openssh-8.7p1-hpn-15.2-modified.patch +# Based on https://github.com/rapier1/hpn-ssh/ tag: hpn-8_7_P1 (hpn15v4) +Patch99: openssh-8.7p1-hpn-15.4.patch License: BSD Requires: /sbin/nologin @@ -393,7 +414,20 @@ gpgv2 --quiet --keyring %{SOURCE3} %{SOURCE1} %{SOURCE0} %patch1007 -p1 -b .sshrsacheck %patch1008 -p1 -b .cve-2023-25136 + +%patch1009 -p1 -b .evp_fips_sign +%patch1010 -p1 -b .evp_fips_dh +%patch1011 -p1 -b .evp_fips_ecdh +%patch1012 -p1 -b .evp_pkcs11 + +%patch1013 -p1 -b .man-hostkeyalgos +%patch1014 -p1 -b .utc_parse %patch1015 -p1 -b .cve-2023-38408 +%patch1016 -p1 -b .openssl3compat +%patch1017 -p1 -b .limitdelay +%patch1018 -p1 -b .cve-2023-48795 +%patch1019 -p1 -b .cve-2023-51385 +%patch1020 -p1 -b .cve-2024-6387 %patch98 -p1 -b .gsi %patch99 -p1 -b .hpn @@ -500,6 +534,8 @@ install -m644 %{SOURCE12} $RPM_BUILD_ROOT/%{_unitdir}/gsisshd-keygen@.service install -m644 %{SOURCE15} $RPM_BUILD_ROOT/%{_unitdir}/gsisshd-keygen.target install -m755 %{SOURCE13} $RPM_BUILD_ROOT/%{_libexecdir}/gsissh/sshd-keygen install -d -m711 ${RPM_BUILD_ROOT}/%{_datadir}/empty.sshd +install -p -D -m 0644 %{SOURCE17} %{buildroot}%{_sysusersdir}/%{name}.conf +install -p -D -m 0644 %{SOURCE18} %{buildroot}%{_sysusersdir}/%{name}-server.conf rm $RPM_BUILD_ROOT%{_bindir}/ssh-add rm $RPM_BUILD_ROOT%{_bindir}/ssh-agent @@ -522,13 +558,10 @@ done perl -pi -e "s|$RPM_BUILD_ROOT||g" $RPM_BUILD_ROOT%{_mandir}/man*/* %pre -getent group ssh_keys >/dev/null || groupadd -r ssh_keys || : +%sysusers_create_compat %{SOURCE17} %pre server -getent group sshd >/dev/null || groupadd -g %{sshd_uid} -r sshd || : -getent passwd sshd >/dev/null || \ - useradd -c "Privilege-separated SSH" -u %{sshd_uid} -g sshd \ - -s /sbin/nologin -r -d /usr/share/empty.sshd sshd 2> /dev/null || : +%sysusers_create_compat %{SOURCE18} %post server %systemd_post gsisshd.service gsisshd.socket @@ -549,6 +582,7 @@ getent passwd sshd >/dev/null || \ %attr(0755,root,root) %dir %{_libexecdir}/gsissh %attr(2755,root,ssh_keys) %{_libexecdir}/gsissh/ssh-keysign %attr(0644,root,root) %{_mandir}/man8/gsissh-keysign.8* +%attr(0644,root,root) %{_sysusersdir}/%{name}.conf %files clients %attr(0755,root,root) %{_bindir}/gsissh @@ -581,8 +615,12 @@ getent passwd sshd >/dev/null || \ %attr(0644,root,root) %{_unitdir}/gsisshd.socket %attr(0644,root,root) %{_unitdir}/gsisshd-keygen@.service %attr(0644,root,root) %{_unitdir}/gsisshd-keygen.target +%attr(0644,root,root) %{_sysusersdir}/%{name}-server.conf %changelog +* Tue Jul 09 2024 Mattias Ellert 1- 8.7p1-10 +- Based on openssh-8.7p1-38.el9_4.1 + * Wed Aug 09 2023 Mattias Ellert - 8.7p1-9 - Based on openssh-8.7p1-30.el9_2 diff --git a/openssh-6.7p1-coverity.patch b/openssh-6.7p1-coverity.patch index e372f09..f12f40e 100644 --- a/openssh-6.7p1-coverity.patch +++ b/openssh-6.7p1-coverity.patch @@ -74,33 +74,6 @@ diff -up openssh-7.4p1/channels.c.coverity openssh-7.4p1/channels.c close(c->sock); c->sock = c->rfd = c->wfd = sock; channel_find_maxfd(ssh->chanctxt); -@@ -3804,7 +3804,7 @@ int - channel_request_remote_forwarding(struct ssh *ssh, struct Forward *fwd) - { - int r, success = 0, idx = -1; -- char *host_to_connect, *listen_host, *listen_path; -+ char *host_to_connect = NULL, *listen_host = NULL, *listen_path = NULL; - int port_to_connect, listen_port; - - /* Send the forward request to the remote side. */ -@@ -3832,7 +3832,6 @@ channel_request_remote_forwarding(struct - success = 1; - if (success) { - /* Record that connection to this host/port is permitted. */ -- host_to_connect = listen_host = listen_path = NULL; - port_to_connect = listen_port = 0; - if (fwd->connect_path != NULL) { - host_to_connect = xstrdup(fwd->connect_path); -@@ -3853,6 +3852,9 @@ channel_request_remote_forwarding(struct - host_to_connect, port_to_connect, - listen_host, listen_path, listen_port, NULL); - } -+ free(host_to_connect); -+ free(listen_host); -+ free(listen_path); - return idx; - } - diff -up openssh-8.5p1/dns.c.coverity openssh-8.5p1/dns.c --- openssh-8.5p1/dns.c.coverity 2021-03-02 11:31:47.000000000 +0100 +++ openssh-8.5p1/dns.c 2021-03-24 12:03:33.783968166 +0100 diff --git a/openssh-8.7p1-UTC-time-parse.patch b/openssh-8.7p1-UTC-time-parse.patch new file mode 100644 index 0000000..1fd953d --- /dev/null +++ b/openssh-8.7p1-UTC-time-parse.patch @@ -0,0 +1,323 @@ +diff --git a/misc.c b/misc.c +index a8e87430..f2135803 100644 +--- a/misc.c ++++ b/misc.c +@@ -2399,15 +2399,26 @@ parse_absolute_time(const char *s, uint64_t *tp) + struct tm tm; + time_t tt; + char buf[32], *fmt; ++ const char *cp; ++ size_t l; ++ int is_utc = 0; + + *tp = 0; + ++ l = strlen(s); ++ if (l > 1 && strcasecmp(s + l - 1, "Z") == 0) { ++ is_utc = 1; ++ l--; ++ } else if (l > 3 && strcasecmp(s + l - 3, "UTC") == 0) { ++ is_utc = 1; ++ l -= 3; ++ } + /* + * POSIX strptime says "The application shall ensure that there + * is white-space or other non-alphanumeric characters between + * any two conversion specifications" so arrange things this way. + */ +- switch (strlen(s)) { ++ switch (l) { + case 8: /* YYYYMMDD */ + fmt = "%Y-%m-%d"; + snprintf(buf, sizeof(buf), "%.4s-%.2s-%.2s", s, s + 4, s + 6); +@@ -2427,10 +2438,15 @@ parse_absolute_time(const char *s, uint64_t *tp) + } + + memset(&tm, 0, sizeof(tm)); +- if (strptime(buf, fmt, &tm) == NULL) +- return SSH_ERR_INVALID_FORMAT; +- if ((tt = mktime(&tm)) < 0) ++ if ((cp = strptime(buf, fmt, &tm)) == NULL || *cp != '\0') + return SSH_ERR_INVALID_FORMAT; ++ if (is_utc) { ++ if ((tt = timegm(&tm)) < 0) ++ return SSH_ERR_INVALID_FORMAT; ++ } else { ++ if ((tt = mktime(&tm)) < 0) ++ return SSH_ERR_INVALID_FORMAT; ++ } + /* success */ + *tp = (uint64_t)tt; + return 0; +diff --git a/regress/unittests/misc/test_convtime.c b/regress/unittests/misc/test_convtime.c +index ef6fd77d..4794dbd9 100644 +--- a/regress/unittests/misc/test_convtime.c ++++ b/regress/unittests/misc/test_convtime.c +@@ -20,6 +20,7 @@ + + #include "log.h" + #include "misc.h" ++#include "ssherr.h" + + void test_convtime(void); + +@@ -27,6 +28,7 @@ void + test_convtime(void) + { + char buf[1024]; ++ uint64_t t; + + TEST_START("misc_convtime"); + ASSERT_INT_EQ(convtime("0"), 0); +@@ -56,4 +58,64 @@ test_convtime(void) + ASSERT_INT_EQ(convtime("3550w5d3h14m8s"), -1); + #endif + TEST_DONE(); ++ ++ /* XXX timezones/DST make verification of this tricky */ ++ /* XXX maybe setenv TZ and tzset() to make it unambiguous? */ ++ TEST_START("misc_parse_absolute_time"); ++ ASSERT_INT_EQ(parse_absolute_time("20000101", &t), 0); ++ ASSERT_INT_EQ(parse_absolute_time("200001011223", &t), 0); ++ ASSERT_INT_EQ(parse_absolute_time("20000101122345", &t), 0); ++ ++ /* forced UTC TZ */ ++ ASSERT_INT_EQ(parse_absolute_time("20000101Z", &t), 0); ++ ASSERT_U64_EQ(t, 946684800); ++ ASSERT_INT_EQ(parse_absolute_time("200001011223Z", &t), 0); ++ ASSERT_U64_EQ(t, 946729380); ++ ASSERT_INT_EQ(parse_absolute_time("20000101122345Z", &t), 0); ++ ASSERT_U64_EQ(t, 946729425); ++ ASSERT_INT_EQ(parse_absolute_time("20000101UTC", &t), 0); ++ ASSERT_U64_EQ(t, 946684800); ++ ASSERT_INT_EQ(parse_absolute_time("200001011223UTC", &t), 0); ++ ASSERT_U64_EQ(t, 946729380); ++ ASSERT_INT_EQ(parse_absolute_time("20000101122345UTC", &t), 0); ++ ASSERT_U64_EQ(t, 946729425); ++ ++ /* Bad month */ ++ ASSERT_INT_EQ(parse_absolute_time("20001301", &t), ++ SSH_ERR_INVALID_FORMAT); ++ ASSERT_INT_EQ(parse_absolute_time("20000001", &t), ++ SSH_ERR_INVALID_FORMAT); ++ /* Incomplete */ ++ ASSERT_INT_EQ(parse_absolute_time("2", &t), ++ SSH_ERR_INVALID_FORMAT); ++ ASSERT_INT_EQ(parse_absolute_time("2000", &t), ++ SSH_ERR_INVALID_FORMAT); ++ ASSERT_INT_EQ(parse_absolute_time("20000", &t), ++ SSH_ERR_INVALID_FORMAT); ++ ASSERT_INT_EQ(parse_absolute_time("200001", &t), ++ SSH_ERR_INVALID_FORMAT); ++ ASSERT_INT_EQ(parse_absolute_time("2000010", &t), ++ SSH_ERR_INVALID_FORMAT); ++ ASSERT_INT_EQ(parse_absolute_time("200001010", &t), ++ SSH_ERR_INVALID_FORMAT); ++ /* Bad day, hour, minute, second */ ++ ASSERT_INT_EQ(parse_absolute_time("20000199", &t), ++ SSH_ERR_INVALID_FORMAT); ++ ASSERT_INT_EQ(parse_absolute_time("200001019900", &t), ++ SSH_ERR_INVALID_FORMAT); ++ ASSERT_INT_EQ(parse_absolute_time("200001010099", &t), ++ SSH_ERR_INVALID_FORMAT); ++ ASSERT_INT_EQ(parse_absolute_time("20000101000099", &t), ++ SSH_ERR_INVALID_FORMAT); ++ /* Invalid TZ specifier */ ++ ASSERT_INT_EQ(parse_absolute_time("20000101ZZ", &t), ++ SSH_ERR_INVALID_FORMAT); ++ ASSERT_INT_EQ(parse_absolute_time("20000101PDT", &t), ++ SSH_ERR_INVALID_FORMAT); ++ ASSERT_INT_EQ(parse_absolute_time("20000101U", &t), ++ SSH_ERR_INVALID_FORMAT); ++ ASSERT_INT_EQ(parse_absolute_time("20000101UTCUTC", &t), ++ SSH_ERR_INVALID_FORMAT); ++ ++ TEST_DONE(); + } +diff --git a/ssh-keygen.1 b/ssh-keygen.1 +index 5f429813..6aeab1cb 100644 +--- a/ssh-keygen.1 ++++ b/ssh-keygen.1 +@@ -511,8 +511,11 @@ Print the full public key to standard output after signature verification. + .It Cm verify-time Ns = Ns Ar timestamp + Specifies a time to use when validating signatures instead of the current + time. +-The time may be specified as a date in YYYYMMDD format or a time +-in YYYYMMDDHHMM[SS] format. ++The time may be specified as a date or time in the YYYYMMDD[Z] or ++in YYYYMMDDHHMM[SS][Z] formats. ++Dates and times will be interpreted in the current system time zone unless ++suffixed with a Z character, which causes them to be interpreted in the ++UTC time zone. + .El + .Pp + The +@@ -603,31 +606,67 @@ A validity interval may consist of a single time, indicating that the + certificate is valid beginning now and expiring at that time, or may consist + of two times separated by a colon to indicate an explicit time interval. + .Pp +-The start time may be specified as the string ++The start time may be specified as: ++.Bl -bullet -compact ++.It ++The string + .Dq always +-to indicate the certificate has no specified start time, +-a date in YYYYMMDD format, a time in YYYYMMDDHHMM[SS] format, +-a relative time (to the current time) consisting of a minus sign followed by +-an interval in the format described in the ++to indicate the certificate has no specified start time. ++.It ++A date or time in the system time zone formatted as YYYYMMDD or ++YYYYMMDDHHMM[SS]. ++.It ++A date or time in the UTC time zone as YYYYMMDDZ or YYYYMMDDHHMM[SS]Z. ++.It ++A relative time before the current system time consisting of a minus sign ++followed by an interval in the format described in the + TIME FORMATS section of + .Xr sshd_config 5 . ++.It ++A raw seconds since epoch (Jan 1 1970 00:00:00 UTC) as a hexadecimal ++number beginning with ++.Dq 0x . ++.El + .Pp +-The end time may be specified as a YYYYMMDD date, a YYYYMMDDHHMM[SS] time, +-a relative time starting with a plus character or the string ++The end time may be specified similarly to the start time: ++.Bl -bullet -compact ++.It ++The string + .Dq forever +-to indicate that the certificate has no expiry date. ++to indicate the certificate has no specified end time. ++.It ++A date or time in the system time zone formatted as YYYYMMDD or ++YYYYMMDDHHMM[SS]. ++.It ++A date or time in the UTC time zone as YYYYMMDDZ or YYYYMMDDHHMM[SS]Z. ++.It ++A relative time after the current system time consisting of a plus sign ++followed by an interval in the format described in the ++TIME FORMATS section of ++.Xr sshd_config 5 . ++.It ++A raw seconds since epoch (Jan 1 1970 00:00:00 UTC) as a hexadecimal ++number beginning with ++.Dq 0x . ++.El + .Pp + For example: +-.Dq +52w1d +-(valid from now to 52 weeks and one day from now), +-.Dq -4w:+4w +-(valid from four weeks ago to four weeks from now), +-.Dq 20100101123000:20110101123000 +-(valid from 12:30 PM, January 1st, 2010 to 12:30 PM, January 1st, 2011), +-.Dq -1d:20110101 +-(valid from yesterday to midnight, January 1st, 2011), +-.Dq -1m:forever +-(valid from one minute ago and never expiring). ++.Bl -tag -width Ds ++.It +52w1d ++Valid from now to 52 weeks and one day from now. ++.It -4w:+4w ++Valid from four weeks ago to four weeks from now. ++.It 20100101123000:20110101123000 ++Valid from 12:30 PM, January 1st, 2010 to 12:30 PM, January 1st, 2011. ++.It 20100101123000Z:20110101123000Z ++Similar, but interpreted in the UTC time zone rather than the system time zone. ++.It -1d:20110101 ++Valid from yesterday to midnight, January 1st, 2011. ++.It 0x1:0x2000000000 ++Valid from roughly early 1970 to May 2033. ++.It -1m:forever ++Valid from one minute ago and never expiring. ++.El + .It Fl v + Verbose mode. + Causes +@@ -1206,7 +1245,10 @@ signature object and presented on the verification command-line must + match the specified list before the key will be considered acceptable. + .It Cm valid-after Ns = Ns "timestamp" + Indicates that the key is valid for use at or after the specified timestamp, +-which may be a date in YYYYMMDD format or a time in YYYYMMDDHHMM[SS] format. ++which may be a date or time in the YYYYMMDD[Z] or YYYYMMDDHHMM[SS][Z] formats. ++Dates and times will be interpreted in the current system time zone unless ++suffixed with a Z character, which causes them to be interpreted in the UTC ++time zone. + .It Cm valid-before Ns = Ns "timestamp" + Indicates that the key is valid for use at or before the specified timestamp. + .El +diff --git a/ssh-keygen.c b/ssh-keygen.c +index 20b321cc..9b2beda0 100644 +--- a/ssh-keygen.c ++++ b/ssh-keygen.c +@@ -1916,6 +1916,21 @@ parse_relative_time(const char *s, time_t now) + return now + (u_int64_t)(secs * mul); + } + ++static void ++parse_hex_u64(const char *s, uint64_t *up) ++{ ++ char *ep; ++ unsigned long long ull; ++ ++ errno = 0; ++ ull = strtoull(s, &ep, 16); ++ if (*s == '\0' || *ep != '\0') ++ fatal("Invalid certificate time: not a number"); ++ if (errno == ERANGE && ull == ULONG_MAX) ++ fatal_fr(SSH_ERR_SYSTEM_ERROR, "Invalid certificate time"); ++ *up = (uint64_t)ull; ++} ++ + static void + parse_cert_times(char *timespec) + { +@@ -1938,8 +1953,8 @@ parse_cert_times(char *timespec) + + /* + * from:to, where +- * from := [+-]timespec | YYYYMMDD | YYYYMMDDHHMMSS | "always" +- * to := [+-]timespec | YYYYMMDD | YYYYMMDDHHMMSS | "forever" ++ * from := [+-]timespec | YYYYMMDD | YYYYMMDDHHMMSS | 0x... | "always" ++ * to := [+-]timespec | YYYYMMDD | YYYYMMDDHHMMSS | 0x... | "forever" + */ + from = xstrdup(timespec); + to = strchr(from, ':'); +@@ -1951,6 +1966,8 @@ parse_cert_times(char *timespec) + cert_valid_from = parse_relative_time(from, now); + else if (strcmp(from, "always") == 0) + cert_valid_from = 0; ++ else if (strncmp(from, "0x", 2) == 0) ++ parse_hex_u64(from, &cert_valid_from); + else if (parse_absolute_time(from, &cert_valid_from) != 0) + fatal("Invalid from time \"%s\"", from); + +@@ -1958,6 +1975,8 @@ parse_cert_times(char *timespec) + cert_valid_to = parse_relative_time(to, now); + else if (strcmp(to, "forever") == 0) + cert_valid_to = ~(u_int64_t)0; ++ else if (strncmp(to, "0x", 2) == 0) ++ parse_hex_u64(to, &cert_valid_to); + else if (parse_absolute_time(to, &cert_valid_to) != 0) + fatal("Invalid to time \"%s\"", to); + +diff --git a/sshd.8 b/sshd.8 +index 2b50514e..8ccc5bc0 100644 +--- a/sshd.8 ++++ b/sshd.8 +@@ -533,8 +533,9 @@ controlled via the + option. + .It Cm expiry-time="timespec" + Specifies a time after which the key will not be accepted. +-The time may be specified as a YYYYMMDD date or a YYYYMMDDHHMM[SS] time +-in the system time-zone. ++The time may be specified as a YYYYMMDD[Z] date or a YYYYMMDDHHMM[SS][Z] time. ++Dates and times will be interpreted in the system time zone unless suffixed ++by a Z character, in which case they will be interpreted in the UTC time zone. + .It Cm from="pattern-list" + Specifies that in addition to public key authentication, either the canonical + name of the remote host or its IP address must be present in the diff --git a/openssh-8.7p1-evp-fips-compl-dh.patch b/openssh-8.7p1-evp-fips-compl-dh.patch new file mode 100644 index 0000000..ec04910 --- /dev/null +++ b/openssh-8.7p1-evp-fips-compl-dh.patch @@ -0,0 +1,292 @@ +diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac openssh-8.7p1/dh.c openssh-8.7p1-patched/dh.c +--- openssh-8.7p1/dh.c 2023-05-25 09:01:23.295627077 +0200 ++++ openssh-8.7p1-patched/dh.c 2023-05-25 09:00:56.519332820 +0200 +@@ -37,6 +37,9 @@ + #include + #include + #include ++#include ++#include ++#include + + #include "dh.h" + #include "pathnames.h" +@@ -290,10 +293,15 @@ + int + dh_gen_key(DH *dh, int need) + { +- int pbits; +- const BIGNUM *dh_p, *pub_key; ++ const BIGNUM *dh_p, *dh_g; ++ BIGNUM *pub_key = NULL, *priv_key = NULL; ++ EVP_PKEY *pkey = NULL; ++ EVP_PKEY_CTX *ctx = NULL; ++ OSSL_PARAM_BLD *param_bld = NULL; ++ OSSL_PARAM *params = NULL; ++ int pbits, r = 0; + +- DH_get0_pqg(dh, &dh_p, NULL, NULL); ++ DH_get0_pqg(dh, &dh_p, NULL, &dh_g); + + if (need < 0 || dh_p == NULL || + (pbits = BN_num_bits(dh_p)) <= 0 || +@@ -301,19 +309,85 @@ + return SSH_ERR_INVALID_ARGUMENT; + if (need < 256) + need = 256; ++ ++ if ((param_bld = OSSL_PARAM_BLD_new()) == NULL || ++ (ctx = EVP_PKEY_CTX_new_from_name(NULL, "DH", NULL)) == NULL) { ++ OSSL_PARAM_BLD_free(param_bld); ++ return SSH_ERR_ALLOC_FAIL; ++ } ++ ++ if (OSSL_PARAM_BLD_push_BN(param_bld, ++ OSSL_PKEY_PARAM_FFC_P, dh_p) != 1 || ++ OSSL_PARAM_BLD_push_BN(param_bld, ++ OSSL_PKEY_PARAM_FFC_G, dh_g) != 1) { ++ error_f("Could not set p,q,g parameters"); ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } + /* + * Pollard Rho, Big step/Little Step attacks are O(sqrt(n)), + * so double requested need here. + */ +- if (!DH_set_length(dh, MINIMUM(need * 2, pbits - 1))) +- return SSH_ERR_LIBCRYPTO_ERROR; +- +- if (DH_generate_key(dh) == 0) +- return SSH_ERR_LIBCRYPTO_ERROR; +- DH_get0_key(dh, &pub_key, NULL); +- if (!dh_pub_is_valid(dh, pub_key)) +- return SSH_ERR_INVALID_FORMAT; +- return 0; ++ if (OSSL_PARAM_BLD_push_int(param_bld, ++ OSSL_PKEY_PARAM_DH_PRIV_LEN, ++ MINIMUM(need * 2, pbits - 1)) != 1 || ++ (params = OSSL_PARAM_BLD_to_param(param_bld)) == NULL) { ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if (EVP_PKEY_fromdata_init(ctx) != 1) { ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if (EVP_PKEY_fromdata(ctx, &pkey, ++ EVP_PKEY_KEY_PARAMETERS, params) != 1) { ++ error_f("Failed key generation"); ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ ++ /* reuse context for key generation */ ++ EVP_PKEY_CTX_free(ctx); ++ ctx = NULL; ++ ++ if ((ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL)) == NULL || ++ EVP_PKEY_keygen_init(ctx) != 1) { ++ error_f("Could not create or init context"); ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if (EVP_PKEY_generate(ctx, &pkey) != 1) { ++ error_f("Could not generate keys"); ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if (EVP_PKEY_public_check(ctx) != 1) { ++ error_f("The public key is incorrect"); ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ ++ if (EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_PUB_KEY, ++ &pub_key) != 1 || ++ EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_PRIV_KEY, ++ &priv_key) != 1 || ++ DH_set0_key(dh, pub_key, priv_key) != 1) { ++ error_f("Could not set pub/priv keys to DH struct"); ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ ++ /* transferred */ ++ pub_key = NULL; ++ priv_key = NULL; ++out: ++ OSSL_PARAM_free(params); ++ OSSL_PARAM_BLD_free(param_bld); ++ EVP_PKEY_CTX_free(ctx); ++ EVP_PKEY_free(pkey); ++ BN_clear_free(pub_key); ++ BN_clear_free(priv_key); ++ return r; + } + + DH * +diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac openssh-8.7p1/kex.c openssh-8.7p1-patched/kex.c +--- openssh-8.7p1/kex.c 2023-05-25 09:01:23.299627122 +0200 ++++ openssh-8.7p1-patched/kex.c 2023-05-25 09:00:56.519332820 +0200 +@@ -1603,3 +1603,47 @@ + return r; + } + ++#ifdef WITH_OPENSSL ++/* ++ * Creates an EVP_PKEY from the given parameters and keys. ++ * The private key can be omitted. ++ */ ++int ++kex_create_evp_dh(EVP_PKEY **pkey, const BIGNUM *p, const BIGNUM *q, ++ const BIGNUM *g, const BIGNUM *pub, const BIGNUM *priv) ++{ ++ OSSL_PARAM_BLD *param_bld = NULL; ++ EVP_PKEY_CTX *ctx = NULL; ++ int r = 0; ++ ++ /* create EVP_PKEY-DH key */ ++ if ((ctx = EVP_PKEY_CTX_new_from_name(NULL, "DH", NULL)) == NULL || ++ (param_bld = OSSL_PARAM_BLD_new()) == NULL) { ++ error_f("EVP_PKEY_CTX or PARAM_BLD init failed"); ++ r = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } ++ if (OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_FFC_P, p) != 1 || ++ OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_FFC_Q, q) != 1 || ++ OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_FFC_G, g) != 1 || ++ OSSL_PARAM_BLD_push_BN(param_bld, ++ OSSL_PKEY_PARAM_PUB_KEY, pub) != 1) { ++ error_f("Failed pushing params to OSSL_PARAM_BLD"); ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if (priv != NULL && ++ OSSL_PARAM_BLD_push_BN(param_bld, ++ OSSL_PKEY_PARAM_PRIV_KEY, priv) != 1) { ++ error_f("Failed pushing private key to OSSL_PARAM_BLD"); ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if ((*pkey = sshkey_create_evp(param_bld, ctx)) == NULL) ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++out: ++ OSSL_PARAM_BLD_free(param_bld); ++ EVP_PKEY_CTX_free(ctx); ++ return r; ++} ++#endif /* WITH_OPENSSL */ +diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac openssh-8.7p1/kexdh.c openssh-8.7p1-patched/kexdh.c +--- openssh-8.7p1/kexdh.c 2023-05-25 09:01:23.237626425 +0200 ++++ openssh-8.7p1-patched/kexdh.c 2023-05-25 09:03:21.817957988 +0200 +@@ -35,6 +35,10 @@ + + #include "openbsd-compat/openssl-compat.h" + #include ++#include ++#include ++#include ++#include + + #include "sshkey.h" + #include "kex.h" +@@ -83,9 +87,12 @@ + kex_dh_compute_key(struct kex *kex, BIGNUM *dh_pub, struct sshbuf *out) + { + BIGNUM *shared_secret = NULL; ++ const BIGNUM *pub, *priv, *p, *q, *g; ++ EVP_PKEY *pkey = NULL, *dh_pkey = NULL; ++ EVP_PKEY_CTX *ctx = NULL; + u_char *kbuf = NULL; + size_t klen = 0; +- int kout, r; ++ int kout, r = 0; + + #ifdef DEBUG_KEXDH + fprintf(stderr, "dh_pub= "); +@@ -100,24 +107,59 @@ + r = SSH_ERR_MESSAGE_INCOMPLETE; + goto out; + } +- klen = DH_size(kex->dh); ++ ++ DH_get0_key(kex->dh, &pub, &priv); ++ DH_get0_pqg(kex->dh, &p, &q, &g); ++ /* import key */ ++ r = kex_create_evp_dh(&pkey, p, q, g, pub, priv); ++ if (r != 0) { ++ error_f("Could not create EVP_PKEY for dh"); ++ ERR_print_errors_fp(stderr); ++ goto out; ++ } ++ /* import peer key ++ * the parameters should be the same as with pkey ++ */ ++ r = kex_create_evp_dh(&dh_pkey, p, q, g, dh_pub, NULL); ++ if (r != 0) { ++ error_f("Could not import peer key for dh"); ++ ERR_print_errors_fp(stderr); ++ goto out; ++ } ++ ++ if ((ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL)) == NULL) { ++ error_f("Could not init EVP_PKEY_CTX for dh"); ++ r = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } ++ if (EVP_PKEY_derive_init(ctx) != 1 || ++ EVP_PKEY_derive_set_peer(ctx, dh_pkey) != 1 || ++ EVP_PKEY_derive(ctx, NULL, &klen) != 1) { ++ error_f("Could not get key size"); ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } + if ((kbuf = malloc(klen)) == NULL || + (shared_secret = BN_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } +- if ((kout = DH_compute_key(kbuf, dh_pub, kex->dh)) < 0 || +- BN_bin2bn(kbuf, kout, shared_secret) == NULL) { ++ if (EVP_PKEY_derive(ctx, kbuf, &klen) != 1 || ++ BN_bin2bn(kbuf, klen, shared_secret) == NULL) { ++ error_f("Could not derive key"); + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } + #ifdef DEBUG_KEXDH +- dump_digest("shared secret", kbuf, kout); ++ dump_digest("shared secret", kbuf, klen); + #endif + r = sshbuf_put_bignum2(out, shared_secret); + out: + freezero(kbuf, klen); + BN_clear_free(shared_secret); ++ EVP_PKEY_free(pkey); ++ EVP_PKEY_free(dh_pkey); ++ EVP_PKEY_CTX_free(ctx); + return r; + } + +diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac openssh-8.7p1/kex.h openssh-8.7p1-patched/kex.h +--- openssh-8.7p1/kex.h 2023-05-25 09:01:23.299627122 +0200 ++++ openssh-8.7p1-patched/kex.h 2023-05-25 09:00:56.519332820 +0200 +@@ -33,6 +33,9 @@ + # include + # include + # include ++# include ++# include ++# include + # ifdef OPENSSL_HAS_ECC + # include + # else /* OPENSSL_HAS_ECC */ +@@ -278,6 +281,8 @@ + const u_char pub[CURVE25519_SIZE], struct sshbuf *out, int) + __attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE))) + __attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE))); ++int kex_create_evp_dh(EVP_PKEY **, const BIGNUM *, const BIGNUM *, ++ const BIGNUM *, const BIGNUM *, const BIGNUM *); + + #if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH) + void dump_digest(const char *, const u_char *, int); diff --git a/openssh-8.7p1-evp-fips-compl-ecdh.patch b/openssh-8.7p1-evp-fips-compl-ecdh.patch new file mode 100644 index 0000000..0313c6f --- /dev/null +++ b/openssh-8.7p1-evp-fips-compl-ecdh.patch @@ -0,0 +1,207 @@ +diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac ../openssh-8.7p1/kexecdh.c ./kexecdh.c +--- ../openssh-8.7p1/kexecdh.c 2021-08-20 06:03:49.000000000 +0200 ++++ ./kexecdh.c 2023-04-13 14:30:14.882449593 +0200 +@@ -35,17 +35,57 @@ + #include + + #include ++#include ++#include ++#include ++#include + + #include "sshkey.h" + #include "kex.h" + #include "sshbuf.h" + #include "digest.h" + #include "ssherr.h" ++#include "log.h" + + static int + kex_ecdh_dec_key_group(struct kex *, const struct sshbuf *, EC_KEY *key, + const EC_GROUP *, struct sshbuf **); + ++static EC_KEY * ++generate_ec_keys(int ec_nid) ++{ ++ EC_KEY *client_key = NULL; ++ EVP_PKEY *pkey = NULL; ++ EVP_PKEY_CTX *ctx = NULL; ++ OSSL_PARAM_BLD *param_bld = NULL; ++ OSSL_PARAM *params = NULL; ++ const char *group_name; ++ ++ if ((ctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL)) == NULL || ++ (param_bld = OSSL_PARAM_BLD_new()) == NULL) ++ goto out; ++ if ((group_name = OSSL_EC_curve_nid2name(ec_nid)) == NULL || ++ OSSL_PARAM_BLD_push_utf8_string(param_bld, ++ OSSL_PKEY_PARAM_GROUP_NAME, group_name, 0) != 1 || ++ (params = OSSL_PARAM_BLD_to_param(param_bld)) == NULL) { ++ error_f("Could not create OSSL_PARAM"); ++ goto out; ++ } ++ if (EVP_PKEY_keygen_init(ctx) != 1 || ++ EVP_PKEY_CTX_set_params(ctx, params) != 1 || ++ EVP_PKEY_generate(ctx, &pkey) != 1 || ++ (client_key = EVP_PKEY_get1_EC_KEY(pkey)) == NULL) { ++ error_f("Could not generate ec keys"); ++ goto out; ++ } ++out: ++ EVP_PKEY_free(pkey); ++ EVP_PKEY_CTX_free(ctx); ++ OSSL_PARAM_BLD_free(param_bld); ++ OSSL_PARAM_free(params); ++ return client_key; ++} ++ + int + kex_ecdh_keypair(struct kex *kex) + { +@@ -55,11 +95,7 @@ + struct sshbuf *buf = NULL; + int r; + +- if ((client_key = EC_KEY_new_by_curve_name(kex->ec_nid)) == NULL) { +- r = SSH_ERR_ALLOC_FAIL; +- goto out; +- } +- if (EC_KEY_generate_key(client_key) != 1) { ++ if ((client_key = generate_ec_keys(kex->ec_nid)) == NULL) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } +@@ -101,11 +137,7 @@ + *server_blobp = NULL; + *shared_secretp = NULL; + +- if ((server_key = EC_KEY_new_by_curve_name(kex->ec_nid)) == NULL) { +- r = SSH_ERR_ALLOC_FAIL; +- goto out; +- } +- if (EC_KEY_generate_key(server_key) != 1) { ++ if ((server_key = generate_ec_keys(kex->ec_nid)) == NULL) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } +@@ -140,11 +172,21 @@ + { + struct sshbuf *buf = NULL; + BIGNUM *shared_secret = NULL; +- EC_POINT *dh_pub = NULL; +- u_char *kbuf = NULL; +- size_t klen = 0; ++ EVP_PKEY_CTX *ctx = NULL; ++ EVP_PKEY *pkey = NULL, *dh_pkey = NULL; ++ OSSL_PARAM_BLD *param_bld = NULL; ++ OSSL_PARAM *params = NULL; ++ u_char *kbuf = NULL, *pub = NULL; ++ size_t klen = 0, publen; ++ const char *group_name; + int r; + ++ /* import EC_KEY to EVP_PKEY */ ++ if ((r = ssh_create_evp_ec(key, kex->ec_nid, &pkey)) != 0) { ++ error_f("Could not create EVP_PKEY"); ++ goto out; ++ } ++ + *shared_secretp = NULL; + + if ((buf = sshbuf_new()) == NULL) { +@@ -153,45 +195,82 @@ + } + if ((r = sshbuf_put_stringb(buf, ec_blob)) != 0) + goto out; +- if ((dh_pub = EC_POINT_new(group)) == NULL) { ++ ++ /* the public key is in the buffer in octet string UNCOMPRESSED ++ * format. See sshbuf_put_ec */ ++ if ((r = sshbuf_get_string(buf, &pub, &publen)) != 0) ++ goto out; ++ sshbuf_reset(buf); ++ if ((ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL)) == NULL || ++ (param_bld = OSSL_PARAM_BLD_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } +- if ((r = sshbuf_get_ec(buf, dh_pub, group)) != 0) { ++ if ((group_name = OSSL_EC_curve_nid2name(kex->ec_nid)) == NULL) { ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if (OSSL_PARAM_BLD_push_octet_string(param_bld, ++ OSSL_PKEY_PARAM_PUB_KEY, pub, publen) != 1 || ++ OSSL_PARAM_BLD_push_utf8_string(param_bld, ++ OSSL_PKEY_PARAM_GROUP_NAME, group_name, 0) != 1 || ++ (params = OSSL_PARAM_BLD_to_param(param_bld)) == NULL) { ++ error_f("Failed to set params for dh_pkey"); ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if (EVP_PKEY_fromdata_init(ctx) != 1 || ++ EVP_PKEY_fromdata(ctx, &dh_pkey, ++ EVP_PKEY_PUBLIC_KEY, params) != 1 || ++ EVP_PKEY_public_check(ctx) != 1) { ++ error_f("Peer public key import failed"); ++ r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } +- sshbuf_reset(buf); + + #ifdef DEBUG_KEXECDH + fputs("public key:\n", stderr); +- sshkey_dump_ec_point(group, dh_pub); ++ EVP_PKEY_print_public_fp(stderr, dh_pkey, 0, NULL); + #endif +- if (sshkey_ec_validate_public(group, dh_pub) != 0) { +- r = SSH_ERR_MESSAGE_INCOMPLETE; ++ EVP_PKEY_CTX_free(ctx); ++ ctx = NULL; ++ if ((ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL)) == NULL || ++ EVP_PKEY_derive_init(ctx) != 1 || ++ EVP_PKEY_derive_set_peer(ctx, dh_pkey) != 1 || ++ EVP_PKEY_derive(ctx, NULL, &klen) != 1) { ++ error_f("Failed to get derive information"); ++ r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } +- klen = (EC_GROUP_get_degree(group) + 7) / 8; +- if ((kbuf = malloc(klen)) == NULL || +- (shared_secret = BN_new()) == NULL) { ++ if ((kbuf = malloc(klen)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } +- if (ECDH_compute_key(kbuf, klen, dh_pub, key, NULL) != (int)klen || +- BN_bin2bn(kbuf, klen, shared_secret) == NULL) { ++ if (EVP_PKEY_derive(ctx, kbuf, &klen) != 1) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } + #ifdef DEBUG_KEXECDH + dump_digest("shared secret", kbuf, klen); + #endif ++ if ((shared_secret = BN_new()) == NULL || ++ (BN_bin2bn(kbuf, klen, shared_secret) == NULL)) { ++ r = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } + if ((r = sshbuf_put_bignum2(buf, shared_secret)) != 0) + goto out; + *shared_secretp = buf; + buf = NULL; + out: +- EC_POINT_clear_free(dh_pub); ++ EVP_PKEY_CTX_free(ctx); ++ EVP_PKEY_free(pkey); ++ EVP_PKEY_free(dh_pkey); ++ OSSL_PARAM_BLD_free(param_bld); ++ OSSL_PARAM_free(params); + BN_clear_free(shared_secret); + freezero(kbuf, klen); ++ freezero(pub, publen); + sshbuf_free(buf); + return r; + } diff --git a/openssh-8.7p1-evp-fips-compl-sign.patch b/openssh-8.7p1-evp-fips-compl-sign.patch new file mode 100644 index 0000000..fc71678 --- /dev/null +++ b/openssh-8.7p1-evp-fips-compl-sign.patch @@ -0,0 +1,468 @@ +diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac ../../openssh-8.7p1/ssh-dss.c ./ssh-dss.c +--- ../../openssh-8.7p1/ssh-dss.c 2023-03-08 15:35:14.669943335 +0100 ++++ ./ssh-dss.c 2023-03-08 15:34:33.508578129 +0100 +@@ -32,6 +32,8 @@ + #include + #include + #include ++#include ++#include + + #include + #include +@@ -72,9 +74,8 @@ + sshkey_type_plain(key->type) != KEY_DSA) + return SSH_ERR_INVALID_ARGUMENT; + +- if ((pkey = EVP_PKEY_new()) == NULL || +- EVP_PKEY_set1_DSA(pkey, key->dsa) != 1) +- return SSH_ERR_ALLOC_FAIL; ++ if ((ret = ssh_create_evp_dss(key, &pkey)) != 0) ++ return ret; + ret = sshkey_calculate_signature(pkey, SSH_DIGEST_SHA1, &sigb, &len, + data, datalen); + EVP_PKEY_free(pkey); +@@ -201,11 +202,8 @@ + goto out; + } + +- if ((pkey = EVP_PKEY_new()) == NULL || +- EVP_PKEY_set1_DSA(pkey, key->dsa) != 1) { +- ret = SSH_ERR_ALLOC_FAIL; ++ if ((ret = ssh_create_evp_dss(key, &pkey)) != 0) + goto out; +- } + ret = sshkey_verify_signature(pkey, SSH_DIGEST_SHA1, data, datalen, + sigb, slen); + EVP_PKEY_free(pkey); +@@ -221,4 +219,63 @@ + freezero(sigblob, len); + return ret; + } ++ ++int ++ssh_create_evp_dss(const struct sshkey *k, EVP_PKEY **pkey) ++{ ++ OSSL_PARAM_BLD *param_bld = NULL; ++ EVP_PKEY_CTX *ctx = NULL; ++ const BIGNUM *p = NULL, *q = NULL, *g = NULL, *pub = NULL, *priv = NULL; ++ int ret = 0; ++ ++ if (k == NULL) ++ return SSH_ERR_INVALID_ARGUMENT; ++ if ((ctx = EVP_PKEY_CTX_new_from_name(NULL, "DSA", NULL)) == NULL || ++ (param_bld = OSSL_PARAM_BLD_new()) == NULL) { ++ ret = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } ++ ++ DSA_get0_pqg(k->dsa, &p, &q, &g); ++ DSA_get0_key(k->dsa, &pub, &priv); ++ ++ if (p != NULL && ++ OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_FFC_P, p) != 1) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if (q != NULL && ++ OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_FFC_Q, q) != 1) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if (g != NULL && ++ OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_FFC_G, g) != 1) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if (pub != NULL && ++ OSSL_PARAM_BLD_push_BN(param_bld, ++ OSSL_PKEY_PARAM_PUB_KEY, ++ pub) != 1) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if (priv != NULL && ++ OSSL_PARAM_BLD_push_BN(param_bld, ++ OSSL_PKEY_PARAM_PRIV_KEY, ++ priv) != 1) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if ((*pkey = sshkey_create_evp(param_bld, ctx)) == NULL) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ ++out: ++ OSSL_PARAM_BLD_free(param_bld); ++ EVP_PKEY_CTX_free(ctx); ++ return ret; ++} + #endif /* WITH_OPENSSL */ +diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac ../../openssh-8.7p1/ssh-ecdsa.c ./ssh-ecdsa.c +--- ../../openssh-8.7p1/ssh-ecdsa.c 2023-03-08 15:35:14.669943335 +0100 ++++ ./ssh-ecdsa.c 2023-03-08 15:40:52.628201267 +0100 +@@ -34,6 +34,8 @@ + #include + #include + #include ++#include ++#include + + #include + +@@ -72,9 +74,8 @@ + if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1) + return SSH_ERR_INTERNAL_ERROR; + +- if ((pkey = EVP_PKEY_new()) == NULL || +- EVP_PKEY_set1_EC_KEY(pkey, key->ecdsa) != 1) +- return SSH_ERR_ALLOC_FAIL; ++ if ((ret = ssh_create_evp_ec(key->ecdsa, key->ecdsa_nid, &pkey)) != 0) ++ return ret; + ret = sshkey_calculate_signature(pkey, hash_alg, &sigb, &len, data, + datalen); + EVP_PKEY_free(pkey); +@@ -193,11 +194,8 @@ + goto out; + } + +- if ((pkey = EVP_PKEY_new()) == NULL || +- EVP_PKEY_set1_EC_KEY(pkey, key->ecdsa) != 1) { +- ret = SSH_ERR_ALLOC_FAIL; ++ if (ssh_create_evp_ec(key->ecdsa, key->ecdsa_nid, &pkey) != 0) + goto out; +- } + ret = sshkey_verify_signature(pkey, hash_alg, data, datalen, sigb, len); + EVP_PKEY_free(pkey); + +@@ -212,4 +210,76 @@ + return ret; + } + ++int ++ssh_create_evp_ec(EC_KEY *k, int ecdsa_nid, EVP_PKEY **pkey) ++{ ++ OSSL_PARAM_BLD *param_bld = NULL; ++ EVP_PKEY_CTX *ctx = NULL; ++ BN_CTX *bn_ctx = NULL; ++ uint8_t *pub_ser = NULL; ++ const char *group_name; ++ const EC_POINT *pub = NULL; ++ const BIGNUM *priv = NULL; ++ int ret = 0; ++ ++ if (k == NULL) ++ return SSH_ERR_INVALID_ARGUMENT; ++ if ((ctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL)) == NULL || ++ (param_bld = OSSL_PARAM_BLD_new()) == NULL || ++ (bn_ctx = BN_CTX_new()) == NULL) { ++ ret = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } ++ ++ if ((group_name = OSSL_EC_curve_nid2name(ecdsa_nid)) == NULL || ++ OSSL_PARAM_BLD_push_utf8_string(param_bld, ++ OSSL_PKEY_PARAM_GROUP_NAME, ++ group_name, ++ strlen(group_name)) != 1) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if ((pub = EC_KEY_get0_public_key(k)) != NULL) { ++ const EC_GROUP *group; ++ size_t len; ++ ++ group = EC_KEY_get0_group(k); ++ len = EC_POINT_point2oct(group, pub, ++ POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL); ++ if ((pub_ser = malloc(len)) == NULL) { ++ ret = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } ++ EC_POINT_point2oct(group, ++ pub, ++ POINT_CONVERSION_UNCOMPRESSED, ++ pub_ser, ++ len, ++ bn_ctx); ++ if (OSSL_PARAM_BLD_push_octet_string(param_bld, ++ OSSL_PKEY_PARAM_PUB_KEY, ++ pub_ser, ++ len) != 1) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ } ++ if ((priv = EC_KEY_get0_private_key(k)) != NULL && ++ OSSL_PARAM_BLD_push_BN(param_bld, ++ OSSL_PKEY_PARAM_PRIV_KEY, priv) != 1) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if ((*pkey = sshkey_create_evp(param_bld, ctx)) == NULL) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ ++out: ++ OSSL_PARAM_BLD_free(param_bld); ++ EVP_PKEY_CTX_free(ctx); ++ BN_CTX_free(bn_ctx); ++ free(pub_ser); ++ return ret; ++} + #endif /* WITH_OPENSSL && OPENSSL_HAS_ECC */ +diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac ../../openssh-8.7p1/sshkey.c ./sshkey.c +--- ../../openssh-8.7p1/sshkey.c 2023-03-08 15:35:14.702943628 +0100 ++++ ./sshkey.c 2023-03-08 15:39:03.354082015 +0100 +@@ -35,6 +35,8 @@ + #include + #include + #include ++#include ++#include + #endif + + #include "crypto_api.h" +@@ -492,13 +494,14 @@ + { + EVP_MD_CTX *ctx = NULL; + u_char *sig = NULL; +- int ret, slen, len; ++ int ret, slen; ++ size_t len; + + if (sigp == NULL || lenp == NULL) { + return SSH_ERR_INVALID_ARGUMENT; + } + +- slen = EVP_PKEY_size(pkey); ++ slen = EVP_PKEY_get_size(pkey); + if (slen <= 0 || slen > SSHBUF_MAX_BIGNUM) + return SSH_ERR_INVALID_ARGUMENT; + +@@ -511,9 +514,10 @@ + ret = SSH_ERR_ALLOC_FAIL; + goto error; + } +- if (EVP_SignInit_ex(ctx, ssh_digest_to_md(hash_alg), NULL) <= 0 || +- EVP_SignUpdate(ctx, data, datalen) <= 0 || +- EVP_SignFinal(ctx, sig, &len, pkey) <= 0) { ++ if (EVP_DigestSignInit(ctx, NULL, ssh_digest_to_md(hash_alg), ++ NULL, pkey) != 1 || ++ EVP_DigestSignUpdate(ctx, data, datalen) != 1 || ++ EVP_DigestSignFinal(ctx, sig, &len) != 1) { + ret = SSH_ERR_LIBCRYPTO_ERROR; + goto error; + } +@@ -540,12 +544,13 @@ + if ((ctx = EVP_MD_CTX_new()) == NULL) { + return SSH_ERR_ALLOC_FAIL; + } +- if (EVP_VerifyInit_ex(ctx, ssh_digest_to_md(hash_alg), NULL) <= 0 || +- EVP_VerifyUpdate(ctx, data, datalen) <= 0) { ++ if (EVP_DigestVerifyInit(ctx, NULL, ssh_digest_to_md(hash_alg), ++ NULL, pkey) != 1 || ++ EVP_DigestVerifyUpdate(ctx, data, datalen) != 1) { + ret = SSH_ERR_LIBCRYPTO_ERROR; + goto done; + } +- ret = EVP_VerifyFinal(ctx, sigbuf, siglen, pkey); ++ ret = EVP_DigestVerifyFinal(ctx, sigbuf, siglen); + switch (ret) { + case 1: + ret = 0; +@@ -5038,3 +5043,27 @@ + return 0; + } + #endif /* WITH_XMSS */ ++ ++#ifdef WITH_OPENSSL ++EVP_PKEY * ++sshkey_create_evp(OSSL_PARAM_BLD *param_bld, EVP_PKEY_CTX *ctx) ++{ ++ EVP_PKEY *ret = NULL; ++ OSSL_PARAM *params = NULL; ++ if (param_bld == NULL || ctx == NULL) { ++ debug2_f("param_bld or ctx is NULL"); ++ return NULL; ++ } ++ if ((params = OSSL_PARAM_BLD_to_param(param_bld)) == NULL) { ++ debug2_f("Could not build param list"); ++ return NULL; ++ } ++ if (EVP_PKEY_fromdata_init(ctx) != 1 || ++ EVP_PKEY_fromdata(ctx, &ret, EVP_PKEY_KEYPAIR, params) != 1) { ++ debug2_f("EVP_PKEY_fromdata failed"); ++ OSSL_PARAM_free(params); ++ return NULL; ++ } ++ return ret; ++} ++#endif /* WITH_OPENSSL */ +diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac ../../openssh-8.7p1/sshkey.h ./sshkey.h +--- ../../openssh-8.7p1/sshkey.h 2023-03-08 15:35:14.702943628 +0100 ++++ ./sshkey.h 2023-03-08 15:34:33.509578138 +0100 +@@ -31,6 +31,9 @@ + #ifdef WITH_OPENSSL + #include + #include ++#include ++#include ++#include + # ifdef OPENSSL_HAS_ECC + # include + # include +@@ -293,6 +295,13 @@ + + void sshkey_sig_details_free(struct sshkey_sig_details *); + ++#ifdef WITH_OPENSSL ++EVP_PKEY *sshkey_create_evp(OSSL_PARAM_BLD *, EVP_PKEY_CTX *); ++int ssh_create_evp_dss(const struct sshkey *, EVP_PKEY **); ++int ssh_create_evp_rsa(const struct sshkey *, EVP_PKEY **); ++int ssh_create_evp_ec(EC_KEY *, int, EVP_PKEY **); ++#endif /* WITH_OPENSSL */ ++ + #ifdef SSHKEY_INTERNAL + int ssh_rsa_sign(const struct sshkey *key, + u_char **sigp, size_t *lenp, const u_char *data, size_t datalen, +diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac ../../openssh-8.7p1/ssh-rsa.c ./ssh-rsa.c +--- ../../openssh-8.7p1/ssh-rsa.c 2023-03-08 15:35:14.669943335 +0100 ++++ ./ssh-rsa.c 2023-03-08 15:34:33.509578138 +0100 +@@ -23,6 +23,8 @@ + + #include + #include ++#include ++#include + + #include + #include +@@ -172,9 +174,8 @@ + if (RSA_bits(key->rsa) < SSH_RSA_MINIMUM_MODULUS_SIZE) + return SSH_ERR_KEY_LENGTH; + +- if ((pkey = EVP_PKEY_new()) == NULL || +- EVP_PKEY_set1_RSA(pkey, key->rsa) != 1) +- return SSH_ERR_ALLOC_FAIL; ++ if ((ret = ssh_create_evp_rsa(key, &pkey)) != 0) ++ return ret; + ret = sshkey_calculate_signature(pkey, hash_alg, &sig, &len, data, + datalen); + EVP_PKEY_free(pkey); +@@ -285,11 +286,8 @@ + len = modlen; + } + +- if ((pkey = EVP_PKEY_new()) == NULL || +- EVP_PKEY_set1_RSA(pkey, key->rsa) != 1) { +- ret = SSH_ERR_ALLOC_FAIL; ++ if ((ret = ssh_create_evp_rsa(key, &pkey)) != 0) + goto out; +- } + ret = openssh_RSA_verify(hash_alg, data, datalen, sigblob, len, pkey); + EVP_PKEY_free(pkey); + +@@ -306,11 +304,9 @@ + u_char *sigbuf, size_t siglen, EVP_PKEY *pkey) + { + size_t rsasize = 0; +- const RSA *rsa; + int ret; + +- rsa = EVP_PKEY_get0_RSA(pkey); +- rsasize = RSA_size(rsa); ++ rsasize = EVP_PKEY_get_size(pkey); + if (rsasize <= 0 || rsasize > SSHBUF_MAX_BIGNUM || + siglen == 0 || siglen > rsasize) { + ret = SSH_ERR_INVALID_ARGUMENT; +@@ -323,4 +319,87 @@ + done: + return ret; + } ++ ++int ++ssh_create_evp_rsa(const struct sshkey *k, EVP_PKEY **pkey) ++{ ++ OSSL_PARAM_BLD *param_bld = NULL; ++ EVP_PKEY_CTX *ctx = NULL; ++ int ret = 0; ++ const BIGNUM *n = NULL, *e = NULL, *d = NULL, *p = NULL, *q = NULL; ++ const BIGNUM *dmp1 = NULL, *dmq1 = NULL, *iqmp = NULL; ++ ++ if (k == NULL) ++ return SSH_ERR_INVALID_ARGUMENT; ++ if ((ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL)) == NULL || ++ (param_bld = OSSL_PARAM_BLD_new()) == NULL) { ++ ret = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } ++ ++ RSA_get0_key(k->rsa, &n, &e, &d); ++ RSA_get0_factors(k->rsa, &p, &q); ++ RSA_get0_crt_params(k->rsa, &dmp1, &dmq1, &iqmp); ++ ++ if (n != NULL && ++ OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_RSA_N, n) != 1) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if (e != NULL && ++ OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_RSA_E, e) != 1) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if (d != NULL && ++ OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_RSA_D, d) != 1) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ ++ if ((*pkey = sshkey_create_evp(param_bld, ctx)) == NULL) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ ++ /* setting this to param_build makes the creation process fail */ ++ if (p != NULL && ++ EVP_PKEY_set_bn_param(*pkey, OSSL_PKEY_PARAM_RSA_FACTOR1, p) != 1) { ++ debug2_f("failed to add 'p' param"); ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if (q != NULL && ++ EVP_PKEY_set_bn_param(*pkey, OSSL_PKEY_PARAM_RSA_FACTOR2, q) != 1) { ++ debug2_f("failed to add 'q' param"); ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if (dmp1 != NULL && ++ EVP_PKEY_set_bn_param(*pkey, ++ OSSL_PKEY_PARAM_RSA_EXPONENT1, dmp1) != 1) { ++ debug2_f("failed to add 'dmp1' param"); ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if (dmq1 != NULL && ++ EVP_PKEY_set_bn_param(*pkey, ++ OSSL_PKEY_PARAM_RSA_EXPONENT2, dmq1) != 1) { ++ debug2_f("failed to add 'dmq1' param"); ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if (iqmp != NULL && ++ EVP_PKEY_set_bn_param(*pkey, ++ OSSL_PKEY_PARAM_RSA_COEFFICIENT1, iqmp) != 1) { ++ debug2_f("failed to add 'iqmp' param"); ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ ++out: ++ OSSL_PARAM_BLD_free(param_bld); ++ EVP_PKEY_CTX_free(ctx); ++ return ret; ++} + #endif /* WITH_OPENSSL */ diff --git a/openssh-8.7p1-evp-pkcs11.patch b/openssh-8.7p1-evp-pkcs11.patch new file mode 100644 index 0000000..44e0b8f --- /dev/null +++ b/openssh-8.7p1-evp-pkcs11.patch @@ -0,0 +1,131 @@ +diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac openssh-8.7p1/ssh-ecdsa.c openssh-8.7p1-patched/ssh-ecdsa.c +--- openssh-8.7p1/ssh-ecdsa.c 2023-05-24 09:39:45.002631174 +0200 ++++ openssh-8.7p1-patched/ssh-ecdsa.c 2023-05-24 09:09:34.400853951 +0200 +@@ -74,8 +74,18 @@ + if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1) + return SSH_ERR_INTERNAL_ERROR; + +- if ((ret = ssh_create_evp_ec(key->ecdsa, key->ecdsa_nid, &pkey)) != 0) +- return ret; ++#ifdef ENABLE_PKCS11 ++ if (is_ecdsa_pkcs11(key->ecdsa)) { ++ if ((pkey = EVP_PKEY_new()) == NULL || ++ EVP_PKEY_set1_EC_KEY(pkey, key->ecdsa) != 1) ++ return SSH_ERR_ALLOC_FAIL; ++ } else { ++#endif ++ if ((ret = ssh_create_evp_ec(key->ecdsa, key->ecdsa_nid, &pkey)) != 0) ++ return ret; ++#ifdef ENABLE_PKCS11 ++ } ++#endif + ret = sshkey_calculate_signature(pkey, hash_alg, &sigb, &len, data, + datalen); + EVP_PKEY_free(pkey); +diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac openssh-8.7p1/ssh-pkcs11.c openssh-8.7p1-patched/ssh-pkcs11.c +--- openssh-8.7p1/ssh-pkcs11.c 2023-05-24 09:39:44.950630607 +0200 ++++ openssh-8.7p1-patched/ssh-pkcs11.c 2023-05-24 09:33:59.153866357 +0200 +@@ -775,8 +775,24 @@ + + return (0); + } ++ ++int ++is_ecdsa_pkcs11(EC_KEY *ecdsa) ++{ ++ if (EC_KEY_get_ex_data(ecdsa, ec_key_idx) != NULL) ++ return 1; ++ return 0; ++} + #endif /* HAVE_EC_KEY_METHOD_NEW */ + ++int ++is_rsa_pkcs11(RSA *rsa) ++{ ++ if (RSA_get_ex_data(rsa, rsa_idx) != NULL) ++ return 1; ++ return 0; ++} ++ + /* remove trailing spaces */ + static void + rmspace(u_char *buf, size_t len) +diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac openssh-8.7p1/ssh-pkcs11-client.c openssh-8.7p1-patched/ssh-pkcs11-client.c +--- openssh-8.7p1/ssh-pkcs11-client.c 2023-05-24 09:39:44.950630607 +0200 ++++ openssh-8.7p1-patched/ssh-pkcs11-client.c 2023-05-24 09:31:16.139092673 +0200 +@@ -225,8 +225,36 @@ + static RSA_METHOD *helper_rsa; + #ifdef HAVE_EC_KEY_METHOD_NEW + static EC_KEY_METHOD *helper_ecdsa; ++ ++int ++is_ecdsa_pkcs11(EC_KEY *ecdsa) ++{ ++ const EC_KEY_METHOD *meth; ++ ECDSA_SIG *(*sign_sig)(const unsigned char *dgst, int dgstlen, ++ const BIGNUM *kinv, const BIGNUM *rp, EC_KEY *eckey) = NULL; ++ ++ meth = EC_KEY_get_method(ecdsa); ++ EC_KEY_METHOD_get_sign(meth, NULL, NULL, &sign_sig); ++ if (sign_sig == ecdsa_do_sign) ++ return 1; ++ return 0; ++} + #endif /* HAVE_EC_KEY_METHOD_NEW */ + ++int ++is_rsa_pkcs11(RSA *rsa) ++{ ++ const RSA_METHOD *meth; ++ int (*priv_enc)(int flen, const unsigned char *from, ++ unsigned char *to, RSA *rsa, int padding) = NULL; ++ ++ meth = RSA_get_method(rsa); ++ priv_enc = RSA_meth_get_priv_enc(meth); ++ if (priv_enc == rsa_encrypt) ++ return 1; ++ return 0; ++} ++ + /* redirect private key crypto operations to the ssh-pkcs11-helper */ + static void + wrap_key(struct sshkey *k) +diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac openssh-8.7p1/ssh-pkcs11.h openssh-8.7p1-patched/ssh-pkcs11.h +--- openssh-8.7p1/ssh-pkcs11.h 2023-05-24 09:39:44.950630607 +0200 ++++ openssh-8.7p1-patched/ssh-pkcs11.h 2023-05-24 09:36:49.055714975 +0200 +@@ -39,6 +39,11 @@ + u_int32_t *); + #endif + ++#ifdef HAVE_EC_KEY_METHOD_NEW ++int is_ecdsa_pkcs11(EC_KEY *ecdsa); ++#endif ++int is_rsa_pkcs11(RSA *rsa); ++ + #if !defined(WITH_OPENSSL) && defined(ENABLE_PKCS11) + #undef ENABLE_PKCS11 + #endif +diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac openssh-8.7p1/ssh-rsa.c openssh-8.7p1-patched/ssh-rsa.c +--- openssh-8.7p1/ssh-rsa.c 2023-05-24 09:39:45.003631184 +0200 ++++ openssh-8.7p1-patched/ssh-rsa.c 2023-05-24 09:31:37.019319860 +0200 +@@ -174,8 +174,18 @@ + if (RSA_bits(key->rsa) < SSH_RSA_MINIMUM_MODULUS_SIZE) + return SSH_ERR_KEY_LENGTH; + +- if ((ret = ssh_create_evp_rsa(key, &pkey)) != 0) +- return ret; ++#ifdef ENABLE_PKCS11 ++ if (is_rsa_pkcs11(key->rsa)) { ++ if ((pkey = EVP_PKEY_new()) == NULL || ++ EVP_PKEY_set1_RSA(pkey, key->rsa) != 1) ++ return SSH_ERR_ALLOC_FAIL; ++ } else { ++#endif ++ if ((ret = ssh_create_evp_rsa(key, &pkey)) != 0) ++ return ret; ++#ifdef ENABLE_PKCS11 ++ } ++#endif + ret = sshkey_calculate_signature(pkey, hash_alg, &sig, &len, data, + datalen); + EVP_PKEY_free(pkey); diff --git a/openssh-8.7p1-hpn-15.2-modified.patch b/openssh-8.7p1-hpn-15.4.patch similarity index 61% rename from openssh-8.7p1-hpn-15.2-modified.patch rename to openssh-8.7p1-hpn-15.4.patch index e621d17..13feb16 100644 --- a/openssh-8.7p1-hpn-15.2-modified.patch +++ b/openssh-8.7p1-hpn-15.4.patch @@ -1,6 +1,6 @@ diff -Nur openssh-8.7p1.orig/auth2.c openssh-8.7p1/auth2.c ---- openssh-8.7p1.orig/auth2.c 2021-10-24 07:54:36.863834186 +0200 -+++ openssh-8.7p1/auth2.c 2021-10-24 07:56:04.844029990 +0200 +--- openssh-8.7p1.orig/auth2.c 2024-07-09 13:38:43.811660916 +0200 ++++ openssh-8.7p1/auth2.c 2024-07-10 04:43:14.619862322 +0200 @@ -53,6 +53,8 @@ #include "dispatch.h" #include "pathnames.h" @@ -19,7 +19,7 @@ diff -Nur openssh-8.7p1.orig/auth2.c openssh-8.7p1/auth2.c Authmethod *authmethods[] = { &method_none, &method_pubkey, -@@ -299,6 +303,11 @@ +@@ -306,6 +310,11 @@ debug("userauth-request for user %s service %s method %s", user[0] ? user : "", service, method); @@ -32,8 +32,8 @@ diff -Nur openssh-8.7p1.orig/auth2.c openssh-8.7p1/auth2.c #ifdef WITH_SELINUX diff -Nur openssh-8.7p1.orig/channels.c openssh-8.7p1/channels.c ---- openssh-8.7p1.orig/channels.c 2021-10-24 07:54:36.849834155 +0200 -+++ openssh-8.7p1/channels.c 2021-10-24 07:56:04.845029992 +0200 +--- openssh-8.7p1.orig/channels.c 2024-07-09 13:38:43.757660757 +0200 ++++ openssh-8.7p1/channels.c 2024-07-10 04:45:40.307285392 +0200 @@ -220,6 +220,9 @@ /* Setup helper */ static void channel_handler_init(struct ssh_channels *sc); @@ -81,14 +81,14 @@ diff -Nur openssh-8.7p1.orig/channels.c openssh-8.7p1/channels.c static void channel_pre_open(struct ssh *ssh, Channel *c, fd_set *readset, fd_set *writeset) -@@ -2147,22 +2173,31 @@ +@@ -2147,22 +2173,32 @@ 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_max - c->local_window > + c->local_maxpacket*3) || c->local_window < c->local_window_max/2) && c->local_consumed > 0) { + u_int addition = 0; @@ -118,6 +118,14 @@ diff -Nur openssh-8.7p1.orig/channels.c openssh-8.7p1/channels.c c->local_consumed = 0; } return 1; +@@ -2552,7 +2588,6 @@ + (r = sshpkt_send(ssh)) != 0) + fatal_fr(r, "channel %i: send datagram", c->self); + c->remote_window -= plen; +- return; + } + + /* Enqueue packet for buffered data. */ @@ -3329,6 +3364,14 @@ return addr; } @@ -145,7 +153,7 @@ diff -Nur openssh-8.7p1.orig/channels.c openssh-8.7p1/channels.c 0, "port listener", 1); c->path = xstrdup(host); c->host_port = fwd->connect_port; -@@ -4655,7 +4700,8 @@ +@@ -4653,7 +4698,8 @@ sock = socks[n]; nc = channel_new(ssh, "x11 listener", SSH_CHANNEL_X11_LISTENER, sock, sock, -1, @@ -156,8 +164,8 @@ diff -Nur openssh-8.7p1.orig/channels.c openssh-8.7p1/channels.c nc->single_connection = single_connection; (*chanids)[n] = nc->self; diff -Nur openssh-8.7p1.orig/channels.h openssh-8.7p1/channels.h ---- openssh-8.7p1.orig/channels.h 2021-10-24 07:54:36.785834012 +0200 -+++ openssh-8.7p1/channels.h 2021-10-24 07:56:04.846029995 +0200 +--- openssh-8.7p1.orig/channels.h 2024-07-09 13:38:43.636660399 +0200 ++++ openssh-8.7p1/channels.h 2024-07-10 04:48:31.969783885 +0200 @@ -169,8 +169,10 @@ u_int local_window_max; u_int local_consumed; @@ -178,17 +186,16 @@ diff -Nur openssh-8.7p1.orig/channels.h openssh-8.7p1/channels.h /* Maximum channel input buffer size */ #define CHAN_INPUT_MAX (16*1024*1024) -@@ -363,4 +365,7 @@ +@@ -363,4 +365,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.7p1.orig/cipher.c openssh-8.7p1/cipher.c ---- openssh-8.7p1.orig/cipher.c 2021-10-24 07:54:36.828834108 +0200 -+++ openssh-8.7p1/cipher.c 2021-10-24 07:56:04.847029997 +0200 +--- openssh-8.7p1.orig/cipher.c 2024-07-09 13:38:43.714660630 +0200 ++++ openssh-8.7p1/cipher.c 2024-07-09 13:40:05.992903622 +0200 @@ -48,6 +48,7 @@ #include "sshbuf.h" #include "ssherr.h" @@ -271,15 +278,15 @@ diff -Nur openssh-8.7p1.orig/cipher.c openssh-8.7p1/cipher.c } diff -Nur openssh-8.7p1.orig/cipher-ctr-mt.c openssh-8.7p1/cipher-ctr-mt.c --- openssh-8.7p1.orig/cipher-ctr-mt.c 1970-01-01 01:00:00.000000000 +0100 -+++ openssh-8.7p1/cipher-ctr-mt.c 2021-10-24 07:56:04.848029999 +0200 -@@ -0,0 +1,678 @@ ++++ openssh-8.7p1/cipher-ctr-mt.c 2024-07-10 07:52:21.682918109 +0200 +@@ -0,0 +1,774 @@ +/* + * 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. ++ * Copyright (c) 2008-2021 Pittsburgh Supercomputing Center. All rights reserved. + * + * Based on original OpenSSH AES-CTR cipher. Small portions remain unchanged, + * Copyright (c) 2003 Markus Friedl @@ -325,13 +332,24 @@ diff -Nur openssh-8.7p1.orig/cipher-ctr-mt.c openssh-8.7p1/cipher-ctr-mt.c +#define MAX_NUMKQ (MAX_THREADS * 2) + +/* Number of pregen threads to use */ ++/* this is a default value. The actual number is ++ * determined during init as a function of the number ++ * of available cores */ +int cipher_threads = 2; + +/* Number of keystream queues */ ++/* ideally this should be large enough so that there is ++ * always a key queue for a thread to work on ++ * so maybe double of the number of threads. Again this ++ * is a default and the actual value is determined in init*/ +int numkq = 4; + +/* Length of a keystream queue */ -+#define KQLEN 4096 ++/* one queue holds 64KB of key data ++ * being that the queues are destroyed after a rekey ++ * and at leats one has to be fully filled prior to ++ * enciphering data we don't want this to be too large */ ++#define KQLEN 8192 + +/* Processor cacheline length */ +#define CACHELINE_LEN 64 @@ -351,6 +369,10 @@ diff -Nur openssh-8.7p1.orig/cipher-ctr-mt.c openssh-8.7p1/cipher-ctr-mt.c +#endif +/*-------------------- END TUNABLES --------------------*/ + ++#define HAVE_NONE 0 ++#define HAVE_KEY 1 ++#define HAVE_IV 2 ++int X = 0; + +const EVP_CIPHER *evp_aes_ctr_mt(void); + @@ -403,25 +425,27 @@ diff -Nur openssh-8.7p1.orig/cipher-ctr-mt.c openssh-8.7p1/cipher-ctr-mt.c + +/* Keystream Queue struct */ +struct kq { -+ u_char keys[KQLEN][AES_BLOCK_SIZE]; -+ u_char ctr[AES_BLOCK_SIZE]; -+ u_char pad0[CACHELINE_LEN]; ++ u_char keys[KQLEN][AES_BLOCK_SIZE]; /* 4096 x 16B */ ++ u_char ctr[AES_BLOCK_SIZE]; /* 16B */ ++ u_char pad0[CACHELINE_LEN]; /* 64B */ + int qstate; + pthread_mutex_t lock; + pthread_cond_t cond; -+ u_char pad1[CACHELINE_LEN]; ++ u_char pad1[CACHELINE_LEN]; /* 64B */ +}; + +/* Context struct */ +struct ssh_aes_ctr_ctx_mt +{ + int struct_id; -+ struct kq q[MAX_NUMKQ]; -+ AES_KEY aes_ctx; ++ struct kq q[MAX_NUMKQ]; /* 64 */ ++ AES_KEY aes_key; + STATS_STRUCT(stats); -+ u_char aes_counter[AES_BLOCK_SIZE]; -+ pthread_t tid[MAX_THREADS]; -+ int id[MAX_THREADS]; ++ const u_char *orig_key; ++ int keylen; ++ u_char aes_counter[AES_BLOCK_SIZE]; /* 16B */ ++ pthread_t tid[MAX_THREADS]; /* 32 */ ++ int id[MAX_THREADS]; /* 32 */ + pthread_rwlock_t tid_lock; +#ifdef __APPLE__ + pthread_rwlock_t stop_lock; @@ -515,12 +539,6 @@ diff -Nur openssh-8.7p1.orig/cipher-ctr-mt.c openssh-8.7p1/cipher-ctr-mt.c + 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__); @@ -536,16 +554,26 @@ diff -Nur openssh-8.7p1.orig/cipher-ctr-mt.c openssh-8.7p1/cipher-ctr-mt.c + * Find empty keystream queues and fill them using their counter. + * When done, update counter for the next fill. + */ ++/* previously this used the low level interface which is, sadly, ++ * slower than the EVP interface by a long shot. The original ctx (from the ++ * body of the code) isn't passed in here but we have the key and the counter ++ * which means we should be able to create the exact same ctx and use that to ++ * fill the keystream queues. I'm concerned about additional overhead but the ++ * additional speed from AESNI should make up for it. */ ++ +static void * +thread_loop(void *x) +{ -+ AES_KEY key; ++ EVP_CIPHER_CTX *aesni_ctx; + STATS_STRUCT(stats); + struct ssh_aes_ctr_ctx_mt *c = x; + struct kq *q; + int i; + int qidx; + pthread_t first_tid; ++ int outlen; ++ u_char mynull[AES_BLOCK_SIZE]; ++ memset(&mynull, 0, AES_BLOCK_SIZE); + + /* Threads stats on cancellation */ + STATS_INIT(stats); @@ -553,23 +581,46 @@ diff -Nur openssh-8.7p1.orig/cipher-ctr-mt.c openssh-8.7p1/cipher-ctr-mt.c + pthread_cleanup_push(thread_loop_stats, &stats); +#endif + -+ /* Thread local copy of AES key */ -+ memcpy(&key, &c->aes_ctx, sizeof(key)); -+ ++ /* get the thread id to see if this is the first one */ + pthread_rwlock_rdlock(&c->tid_lock); + first_tid = c->tid[0]; + pthread_rwlock_unlock(&c->tid_lock); + ++ /* create the context for this thread */ ++ aesni_ctx = EVP_CIPHER_CTX_new(); ++ + /* + * 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)) { ++ /* get the first element of the keyque struct */ + q = &c->q[0]; + pthread_mutex_lock(&q->lock); ++ /* if we are in the INIT state then fill the queue */ + if (q->qstate == KQINIT) { ++ /* initialize the cipher ctx with the key provided ++ * determinbe which cipher to use based on the key size */ ++ if (c->keylen == 256) ++ EVP_EncryptInit_ex(aesni_ctx, EVP_aes_256_ctr(), NULL, c->orig_key, NULL); ++ else if (c->keylen == 128) ++ EVP_EncryptInit_ex(aesni_ctx, EVP_aes_128_ctr(), NULL, c->orig_key, NULL); ++ else if (c->keylen == 192) ++ EVP_EncryptInit_ex(aesni_ctx, EVP_aes_192_ctr(), NULL, c->orig_key, NULL); ++ else { ++ logit("Invalid key length of %d in AES CTR MT. Exiting", c->keylen); ++ exit(1); ++ } ++ /* fill the queue */ + for (i = 0; i < KQLEN; i++) { -+ AES_encrypt(q->ctr, q->keys[i], &key); ++ /* set the counter to q-ctr*/ ++ EVP_EncryptInit_ex(aesni_ctx, NULL, NULL, NULL, q->ctr); ++ /* encypher a block sized null string (mynull) with the key. This ++ * returns the keystream because xoring the keystream ++ * against null returns the keystream. Store that in the appropriate queue */ ++ EVP_EncryptUpdate(aesni_ctx, q->keys[i], &outlen, mynull, AES_BLOCK_SIZE); ++ /* increment the counter */ + ssh_ctr_inc(q->ctr, AES_BLOCK_SIZE); + } + ssh_ctr_add(q->ctr, KQLEN * (numkq - 1), AES_BLOCK_SIZE); @@ -623,8 +674,21 @@ diff -Nur openssh-8.7p1.orig/cipher-ctr-mt.c openssh-8.7p1/cipher-ctr-mt.c + q->qstate = KQFILLING; + pthread_cond_broadcast(&q->cond); + pthread_mutex_unlock(&q->lock); ++ //fprintf(stderr, "Filling other queues\n"); ++ if (c->keylen == 256) ++ EVP_EncryptInit_ex(aesni_ctx, EVP_aes_256_ctr(), NULL, c->orig_key, NULL); ++ else if (c->keylen == 128) ++ EVP_EncryptInit_ex(aesni_ctx, EVP_aes_128_ctr(), NULL, c->orig_key, NULL); ++ else if (c->keylen == 192) ++ EVP_EncryptInit_ex(aesni_ctx, EVP_aes_192_ctr(), NULL, c->orig_key, NULL); ++ else { ++ logit("Invalid key length of %d in AES CTR MT. Exiting", c->keylen); ++ exit(1); ++ } ++ /* see coresponding block above for useful comments */ + for (i = 0; i < KQLEN; i++) { -+ AES_encrypt(q->ctr, q->keys[i], &key); ++ EVP_EncryptInit_ex(aesni_ctx, NULL, NULL, NULL, q->ctr); ++ EVP_EncryptUpdate(aesni_ctx, q->keys[i], &outlen, mynull, AES_BLOCK_SIZE); + ssh_ctr_inc(q->ctr, AES_BLOCK_SIZE); + } + @@ -645,6 +709,8 @@ diff -Nur openssh-8.7p1.orig/cipher-ctr-mt.c openssh-8.7p1/cipher-ctr-mt.c + return NULL; +} + ++/* this is where the data is actually enciphered and deciphered */ ++/* this may also benefit from upgrading to the EVP API */ +static int +ssh_aes_ctr(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, + LIBCRYPTO_EVP_INL_TYPE len) @@ -723,6 +789,7 @@ diff -Nur openssh-8.7p1.orig/cipher-ctr-mt.c openssh-8.7p1/cipher-ctr-mt.c + while (q->qstate != KQFULL) { + STATS_WAIT(c->stats); + pthread_cond_wait(&q->cond, &q->lock); ++ debug("Waiting to fill keystream queues in cipher"); + } + q->qstate = KQDRAINING; + pthread_cond_broadcast(&q->cond); @@ -740,12 +807,6 @@ diff -Nur openssh-8.7p1.orig/cipher-ctr-mt.c openssh-8.7p1/cipher-ctr-mt.c + 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) @@ -753,26 +814,43 @@ diff -Nur openssh-8.7p1.orig/cipher-ctr-mt.c openssh-8.7p1/cipher-ctr-mt.c + 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) */ ++ /* get the number of cores in the system ++ * peak performance seems to come with assigning half the number of ++ * physical cores in the system. This was determined by interating ++ * over the variables */ +#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__*/ ++ int divisor; /* Wouldn't it be nice if linux had sysctlbyname? Yes. */ ++ FILE *fp; ++ int status = 0; ++ /* determine is hyperthreading is enabled */ ++ fp = fopen("/sys/devices/system/cpu/smt/active", "r"); ++ /* can't find the file so assume that it does not exist */ ++ if (fp == NULL) ++ divisor = 2; ++ fscanf(fp, "%d", &status); ++ fclose(fp); ++ /* 1 for HT on 0 for HT off */ ++ if (status == 1) ++ divisor = 4; ++ else ++ divisor = 2; ++ cipher_threads = sysconf(_SC_NPROCESSORS_ONLN) / divisor; ++ #endif /*__linux__*/ ++ #ifdef __APPLE__ ++ int count; ++ size_t count_len = sizeof(count); ++ sysctlbyname("hw.physicalcpu", &count, &count_len, NULL, 0); ++ cipher_threads = count / 2; ++ #endif /*__APPLE__*/ ++ #ifdef __FREEBSD__ ++ int threads_per_core; ++ int cores; ++ size_t cores_len = sizeof(cores); ++ size_t tpc_len = sizeof(threads_per_core); ++ sysctlbyname("kern.smp.threads_per_core", &threads_per_core, &tpc_len, NULL, 0); ++ sysctlbyname("kern.smp.cores", &cores, &cores_len, NULL, 0); ++ cipher_threads = cores / threads_per_core; ++ #endif /*__FREEBSD__*/ + + /* if they have less than 4 cores spin up 4 threads anyway */ + if (cipher_threads < 2) @@ -784,9 +862,16 @@ diff -Nur openssh-8.7p1.orig/cipher-ctr-mt.c openssh-8.7p1/cipher-ctr-mt.c + if (cipher_threads * 2 > MAX_THREADS) + cipher_threads = MAX_THREADS / 2; + -+ /* set the number of keystream queues */ -+ numkq = cipher_threads * 2; ++ /* set the number of keystream queues. 4 for each thread ++ * this seems to reduce waiting in the cipher process for queues ++ * to fill up */ ++ numkq = cipher_threads * 4; ++ if (numkq > MAX_NUMKQ) ++ numkq = MAX_NUMKQ; + ++ debug("Starting %d threads and %d queues\n", cipher_threads, numkq); ++ ++ /* set up the initial state of c (our cipher stream struct) */ + if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) { + c = xmalloc(sizeof(*c)); + pthread_rwlock_init(&c->tid_lock, NULL); @@ -796,15 +881,23 @@ diff -Nur openssh-8.7p1.orig/cipher-ctr-mt.c openssh-8.7p1/cipher-ctr-mt.c +#endif /* __APPLE__ */ + + c->state = HAVE_NONE; ++ ++ /* initialize the mutexs and conditions for each lock in our struct */ + for (i = 0; i < numkq; i++) { + pthread_mutex_init(&c->q[i].lock, NULL); + pthread_cond_init(&c->q[i].cond, NULL); + } + ++ /* initialize the stats struct */ + STATS_INIT(c->stats); ++ ++ /* attach our struct to the context */ + EVP_CIPHER_CTX_set_app_data(ctx, c); + } + ++ /* we are initializing but the current structure already ++ has an IV and key so we want to kill the existing key data ++ and start over. This is important when we need to rekey the data stream */ + if (c->state == (HAVE_KEY | HAVE_IV)) { + /* tell the pregen threads to exit */ + stop_and_join_pregen_threads(c); @@ -818,21 +911,30 @@ diff -Nur openssh-8.7p1.orig/cipher-ctr-mt.c openssh-8.7p1/cipher-ctr-mt.c + c->state = HAVE_NONE; + } + ++ /* set the initial key for this key stream queue */ + if (key != NULL) { + AES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, -+ &c->aes_ctx); ++ &c->aes_key); ++ c->orig_key = key; ++ c->keylen = EVP_CIPHER_CTX_key_length(ctx) * 8; + c->state |= HAVE_KEY; + } + ++ /* set the IV */ + if (iv != NULL) { ++ /* init the counter this is just a 16byte uchar */ + memcpy(c->aes_counter, iv, AES_BLOCK_SIZE); + c->state |= HAVE_IV; + } + + if (c->state == (HAVE_KEY | HAVE_IV)) { + /* Clear queues */ ++ /* set the first key in the key queue to the current counter */ + memcpy(c->q[0].ctr, c->aes_counter, AES_BLOCK_SIZE); ++ /* indicate that it needs to be initialized */ + c->q[0].qstate = KQINIT; ++ /* for each of the remaining queues set the first counter to the ++ * counter and then add the size of the queue to the counter */ + 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); @@ -865,35 +967,36 @@ diff -Nur openssh-8.7p1.orig/cipher-ctr-mt.c openssh-8.7p1/cipher-ctr-mt.c +/* 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_destroy(EVP_CIPHER_CTX *ctx) */ ++/* { */ ++/* struct ssh_aes_ctr_ctx_mt *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); -+ } -+} ++/* 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) @@ -952,8 +1055,8 @@ diff -Nur openssh-8.7p1.orig/cipher-ctr-mt.c openssh-8.7p1/cipher-ctr-mt.c + +#endif /* defined(WITH_OPENSSL) */ diff -Nur openssh-8.7p1.orig/cipher.h openssh-8.7p1/cipher.h ---- openssh-8.7p1.orig/cipher.h 2021-10-24 07:54:36.829834110 +0200 -+++ openssh-8.7p1/cipher.h 2021-10-24 07:56:04.848029999 +0200 +--- openssh-8.7p1.orig/cipher.h 2024-07-09 13:38:43.714660630 +0200 ++++ openssh-8.7p1/cipher.h 2024-07-09 13:40:05.992903622 +0200 @@ -68,7 +68,9 @@ struct sshcipher_ctx; @@ -965,19 +1068,21 @@ diff -Nur openssh-8.7p1.orig/cipher.h openssh-8.7p1/cipher.h const char *cipher_warning_message(const struct sshcipher_ctx *); int ciphers_valid(const char *); char *cipher_alg_list(char, int); -@@ -86,6 +88,8 @@ +@@ -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.7p1.orig/clientloop.c openssh-8.7p1/clientloop.c ---- openssh-8.7p1.orig/clientloop.c 2021-10-24 07:54:36.738833908 +0200 -+++ openssh-8.7p1/clientloop.c 2021-10-24 07:56:04.849030001 +0200 -@@ -1582,7 +1582,9 @@ +--- openssh-8.7p1.orig/clientloop.c 2024-07-09 13:38:43.735660692 +0200 ++++ openssh-8.7p1/clientloop.c 2024-07-09 13:40:05.993903625 +0200 +@@ -1585,7 +1585,9 @@ return NULL; c = channel_new(ssh, "x11", SSH_CHANNEL_X11_OPEN, sock, sock, -1, @@ -988,7 +1093,7 @@ diff -Nur openssh-8.7p1.orig/clientloop.c openssh-8.7p1/clientloop.c c->force_drain = 1; return c; } -@@ -1611,7 +1613,8 @@ +@@ -1614,7 +1616,8 @@ } c = channel_new(ssh, "authentication agent connection", SSH_CHANNEL_OPEN, sock, sock, -1, @@ -998,7 +1103,7 @@ diff -Nur openssh-8.7p1.orig/clientloop.c openssh-8.7p1/clientloop.c "authentication agent connection", 1); c->force_drain = 1; return c; -@@ -1638,7 +1641,8 @@ +@@ -1641,7 +1644,8 @@ debug("Tunnel forwarding using interface %s", ifname); c = channel_new(ssh, "tun", SSH_CHANNEL_OPENING, fd, fd, -1, @@ -1009,9 +1114,9 @@ diff -Nur openssh-8.7p1.orig/clientloop.c openssh-8.7p1/clientloop.c #if defined(SSH_TUN_FILTER) diff -Nur openssh-8.7p1.orig/compat.c openssh-8.7p1/compat.c ---- openssh-8.7p1.orig/compat.c 2021-10-24 07:54:36.849834155 +0200 -+++ openssh-8.7p1/compat.c 2021-10-24 07:56:04.850030003 +0200 -@@ -151,6 +151,17 @@ +--- openssh-8.7p1.orig/compat.c 2024-07-09 13:38:43.777660816 +0200 ++++ openssh-8.7p1/compat.c 2024-07-10 07:52:46.684991340 +0200 +@@ -155,6 +155,17 @@ ssh->compat = check[i].bugs; if (forbid_ssh_rsa) ssh->compat |= SSH_RH_RSASIGSHA; @@ -1030,8 +1135,8 @@ diff -Nur openssh-8.7p1.orig/compat.c openssh-8.7p1/compat.c } } diff -Nur openssh-8.7p1.orig/compat.h openssh-8.7p1/compat.h ---- openssh-8.7p1.orig/compat.h 2021-08-20 06:03:49.000000000 +0200 -+++ openssh-8.7p1/compat.h 2021-10-24 07:56:04.850030003 +0200 +--- openssh-8.7p1.orig/compat.h 2024-07-09 13:38:43.770660795 +0200 ++++ openssh-8.7p1/compat.h 2024-07-09 13:40:05.994903628 +0200 @@ -57,6 +57,7 @@ #define SSH_BUG_CURVE25519PAD 0x10000000 #define SSH_BUG_HOSTKEYS 0x20000000 @@ -1042,7 +1147,7 @@ diff -Nur openssh-8.7p1.orig/compat.h openssh-8.7p1/compat.h diff -Nur openssh-8.7p1.orig/defines.h openssh-8.7p1/defines.h --- openssh-8.7p1.orig/defines.h 2021-08-20 06:03:49.000000000 +0200 -+++ openssh-8.7p1/defines.h 2021-10-24 07:56:04.851030005 +0200 ++++ openssh-8.7p1/defines.h 2024-07-09 13:40:05.994903628 +0200 @@ -854,7 +854,7 @@ #endif @@ -1053,8 +1158,8 @@ diff -Nur openssh-8.7p1.orig/defines.h openssh-8.7p1/defines.h /* diff -Nur openssh-8.7p1.orig/digest.h openssh-8.7p1/digest.h ---- openssh-8.7p1.orig/digest.h 2021-10-24 07:54:36.811834070 +0200 -+++ openssh-8.7p1/digest.h 2021-10-24 07:56:04.852030007 +0200 +--- openssh-8.7p1.orig/digest.h 2024-07-09 13:38:43.665660485 +0200 ++++ openssh-8.7p1/digest.h 2024-07-09 13:40:05.994903628 +0200 @@ -27,7 +27,8 @@ #define SSH_DIGEST_SHA256 2 #define SSH_DIGEST_SHA384 3 @@ -1066,8 +1171,8 @@ diff -Nur openssh-8.7p1.orig/digest.h openssh-8.7p1/digest.h struct sshbuf; struct ssh_digest_ctx; diff -Nur openssh-8.7p1.orig/digest-openssl.c openssh-8.7p1/digest-openssl.c ---- openssh-8.7p1.orig/digest-openssl.c 2021-10-24 07:54:36.810834068 +0200 -+++ openssh-8.7p1/digest-openssl.c 2021-10-24 07:56:04.852030007 +0200 +--- openssh-8.7p1.orig/digest-openssl.c 2024-07-09 13:38:43.665660485 +0200 ++++ openssh-8.7p1/digest-openssl.c 2024-07-09 13:40:05.995903631 +0200 @@ -61,6 +61,7 @@ { SSH_DIGEST_SHA256, "SHA256", 32, EVP_sha256 }, { SSH_DIGEST_SHA384, "SHA384", 48, EVP_sha384 }, @@ -1076,12 +1181,51 @@ diff -Nur openssh-8.7p1.orig/digest-openssl.c openssh-8.7p1/digest-openssl.c { -1, NULL, 0, NULL }, }; +diff -Nur openssh-8.7p1.orig/FUNDING.yml openssh-8.7p1/FUNDING.yml +--- openssh-8.7p1.orig/FUNDING.yml 1970-01-01 01:00:00.000000000 +0100 ++++ openssh-8.7p1/FUNDING.yml 2024-07-09 13:40:05.995903631 +0200 +@@ -0,0 +1,12 @@ ++# These are supported funding model platforms ++ ++github:rapier1 # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] ++#patreon: # Replace with a single Patreon username ++#open_collective: # Replace with a single Open Collective username ++#ko_fi: # Replace with a single Ko-fi username ++#tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel ++#community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry ++#liberapay: # Replace with a single Liberapay username ++#issuehunt: # Replace with a single IssueHunt username ++#otechie: # Replace with a single Otechie username ++#custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] diff -Nur openssh-8.7p1.orig/HPN-README openssh-8.7p1/HPN-README --- openssh-8.7p1.orig/HPN-README 1970-01-01 01:00:00.000000000 +0100 -+++ openssh-8.7p1/HPN-README 2021-10-24 07:56:04.852030007 +0200 -@@ -0,0 +1,153 @@ ++++ openssh-8.7p1/HPN-README 2024-07-10 05:02:36.866236732 +0200 +@@ -0,0 +1,176 @@ +Notes: + ++SCP with Resume functionality ++This feature allows SCP to resume failed transfers. In the event of a failed transfer ++issues the same scp command with the '-R' option. For example - if you issued: ++'scp myhugefile me@host:~' ++and it dies halfway through the transfer issuing ++'scp -Z myhugefile me@host:~' ++will resume the transfer at the point where it left off. ++ ++This is implemented by having the source host send a hash (blake2b512) of the file to the ++target host. Teh target host then computes it's own hash of the target file. If the hashes match ++then the file is skipped as this indicates a successful transfer. However, if the hashes do not ++match then the target sends the source its hash along with the size of the file. The source then ++computes the hash of the file *up to* the size of the target file. If those hashes match then ++the source only send the necessary bytes to complete the transfer. If the hashes do not match then ++the entire file is resent. If the target file is larger then the source file then the entire ++source file is sent and any existing target file is overwritten. ++ ++SCP however, will use the first scp in the user's path. This might not support the resume ++function and the attempt will fail. In those cases the user can explicitly define the path to the ++resume enabled scp with the '-z' option. For example: ++ ++'scp -Z -z /opt/hpnssh/usr/bin/scp myhugefile me@host:~' ++ +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. @@ -1116,7 +1260,7 @@ diff -Nur openssh-8.7p1.orig/HPN-README openssh-8.7p1/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:~ + @@ -1193,7 +1337,7 @@ diff -Nur openssh-8.7p1.orig/HPN-README openssh-8.7p1/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 @@ -1234,9 +1378,9 @@ diff -Nur openssh-8.7p1.orig/HPN-README openssh-8.7p1/HPN-README + This work was financed, in part, by Cisco System, Inc., the National + Library of Medicine, and the National Science Foundation. diff -Nur openssh-8.7p1.orig/kex.c openssh-8.7p1/kex.c ---- openssh-8.7p1.orig/kex.c 2021-10-24 07:54:36.841834137 +0200 -+++ openssh-8.7p1/kex.c 2021-10-24 07:56:04.853030010 +0200 -@@ -64,6 +64,7 @@ +--- openssh-8.7p1.orig/kex.c 2024-07-09 13:38:43.803660892 +0200 ++++ openssh-8.7p1/kex.c 2024-07-10 05:08:59.870347334 +0200 +@@ -65,6 +65,7 @@ #include "ssherr.h" #include "sshbuf.h" @@ -1244,7 +1388,7 @@ diff -Nur openssh-8.7p1.orig/kex.c openssh-8.7p1/kex.c #include "digest.h" #include "audit.h" -@@ -969,6 +970,11 @@ +@@ -996,6 +997,11 @@ int nenc, nmac, ncomp; u_int mode, ctos, need, dh_need, authlen; int r, first_kex_follows; @@ -1256,7 +1400,7 @@ diff -Nur openssh-8.7p1.orig/kex.c openssh-8.7p1/kex.c debug2("local %s KEXINIT proposal", kex->server ? "server" : "client"); if ((r = kex_buf2prop(kex->my, NULL, &my)) != 0) -@@ -1039,11 +1045,40 @@ +@@ -1086,11 +1092,40 @@ peer[ncomp] = NULL; goto out; } @@ -1297,7 +1441,7 @@ diff -Nur openssh-8.7p1.orig/kex.c openssh-8.7p1/kex.c } need = dh_need = 0; for (mode = 0; mode < MODE_MAX; mode++) { -@@ -1391,7 +1426,7 @@ +@@ -1438,7 +1473,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", @@ -1306,7 +1450,7 @@ diff -Nur openssh-8.7p1.orig/kex.c openssh-8.7p1/kex.c version_addendum == NULL ? "" : " ", version_addendum == NULL ? "" : version_addendum)) != 0) { oerrno = errno; -@@ -1527,6 +1562,14 @@ +@@ -1574,6 +1609,14 @@ r = SSH_ERR_INVALID_FORMAT; goto out; } @@ -1321,33 +1465,9 @@ diff -Nur openssh-8.7p1.orig/kex.c openssh-8.7p1/kex.c debug("Remote protocol version %d.%d, remote software version %.100s", remote_major, remote_minor, remote_version); compat_banner(ssh, remote_version); -diff -Nur openssh-8.7p1.orig/log.c openssh-8.7p1/log.c ---- openssh-8.7p1.orig/log.c 2021-10-24 07:54:36.769833977 +0200 -+++ openssh-8.7p1/log.c 2021-10-24 07:56:04.853030010 +0200 -@@ -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 -@@ -65,6 +70,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.7p1.orig/mac.c openssh-8.7p1/mac.c ---- openssh-8.7p1.orig/mac.c 2021-10-24 07:54:36.830834112 +0200 -+++ openssh-8.7p1/mac.c 2021-10-24 07:56:04.854030012 +0200 +--- openssh-8.7p1.orig/mac.c 2024-07-09 13:38:43.715660633 +0200 ++++ openssh-8.7p1/mac.c 2024-07-09 13:40:05.996903633 +0200 @@ -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 }, @@ -1357,8 +1477,8 @@ diff -Nur openssh-8.7p1.orig/mac.c openssh-8.7p1/mac.c { "umac-128@openssh.com", SSH_UMAC128, 0, 0, 128, 128, 0 }, diff -Nur openssh-8.7p1.orig/Makefile.in openssh-8.7p1/Makefile.in ---- openssh-8.7p1.orig/Makefile.in 2021-10-24 07:54:36.867834195 +0200 -+++ openssh-8.7p1/Makefile.in 2021-10-24 07:56:04.854030012 +0200 +--- openssh-8.7p1.orig/Makefile.in 2024-07-09 13:38:43.816660931 +0200 ++++ openssh-8.7p1/Makefile.in 2024-07-09 13:40:05.996903633 +0200 @@ -48,7 +48,7 @@ CFLAGS_NOPIE=@CFLAGS_NOPIE@ CPPFLAGS=-I. -I$(srcdir) @CPPFLAGS@ $(PATHS) @DEFS@ @@ -1378,8 +1498,8 @@ diff -Nur openssh-8.7p1.orig/Makefile.in openssh-8.7p1/Makefile.in log.o match.o moduli.o nchan.o packet.o \ readpass.o ttymodes.o xmalloc.o addr.o addrmatch.o \ diff -Nur openssh-8.7p1.orig/packet.c openssh-8.7p1/packet.c ---- openssh-8.7p1.orig/packet.c 2021-10-24 07:54:36.832834117 +0200 -+++ openssh-8.7p1/packet.c 2021-10-24 07:56:04.855030014 +0200 +--- openssh-8.7p1.orig/packet.c 2024-07-09 13:38:43.804660896 +0200 ++++ openssh-8.7p1/packet.c 2024-07-10 15:16:34.291496188 +0200 @@ -246,7 +246,7 @@ TAILQ_INIT(&ssh->public_keys); state->connection_in = -1; @@ -1461,7 +1581,7 @@ diff -Nur openssh-8.7p1.orig/packet.c openssh-8.7p1/packet.c /* Time-based rekeying */ if (state->rekey_interval != 0 && (int64_t)state->rekey_time + state->rekey_interval <= monotime()) -@@ -1342,7 +1376,7 @@ +@@ -1352,7 +1386,7 @@ struct session_state *state = ssh->state; int len, r, ms_remain; fd_set *setp; @@ -1470,7 +1590,7 @@ diff -Nur openssh-8.7p1.orig/packet.c openssh-8.7p1/packet.c struct timeval timeout, start, *timeoutp = NULL; DBG(debug("packet_read()")); -@@ -1870,17 +1904,21 @@ +@@ -1905,17 +1939,21 @@ switch (r) { case SSH_ERR_CONN_CLOSED: ssh_packet_clear_keys(ssh); @@ -1492,7 +1612,7 @@ diff -Nur openssh-8.7p1.orig/packet.c openssh-8.7p1/packet.c logdie("Connection reset by %s", remote_id); } /* FALLTHROUGH */ -@@ -1922,6 +1960,24 @@ +@@ -1957,6 +1995,24 @@ logdie_f("should have exited"); } @@ -1517,15 +1637,7 @@ diff -Nur openssh-8.7p1.orig/packet.c openssh-8.7p1/packet.c /* * Logs the error plus constructs and sends a disconnect packet, closes the * connection, and exits. This function never returns. The error message -@@ -1991,6 +2047,7 @@ - return SSH_ERR_CONN_CLOSED; - if ((r = sshbuf_consume(state->output, len)) != 0) - return r; -+ ssh->stdin_bytes += len; - } - return 0; - } -@@ -2794,3 +2850,10 @@ +@@ -2832,3 +2888,10 @@ ssh->state->extra_pad = pad; return 0; } @@ -1537,8 +1649,8 @@ diff -Nur openssh-8.7p1.orig/packet.c openssh-8.7p1/packet.c + return ssh->state->send_context; +} diff -Nur openssh-8.7p1.orig/packet.h openssh-8.7p1/packet.h ---- openssh-8.7p1.orig/packet.h 2021-10-24 07:54:36.833834119 +0200 -+++ openssh-8.7p1/packet.h 2021-10-24 07:56:04.856030016 +0200 +--- openssh-8.7p1.orig/packet.h 2024-07-09 13:38:43.718660641 +0200 ++++ openssh-8.7p1/packet.h 2024-07-10 05:21:57.520603526 +0200 @@ -86,6 +86,14 @@ /* APP data */ @@ -1579,7 +1691,7 @@ diff -Nur openssh-8.7p1.orig/packet.h openssh-8.7p1/packet.h int sshpkt_start(struct ssh *ssh, u_char type); diff -Nur openssh-8.7p1.orig/progressmeter.c openssh-8.7p1/progressmeter.c --- openssh-8.7p1.orig/progressmeter.c 2021-08-20 06:03:49.000000000 +0200 -+++ openssh-8.7p1/progressmeter.c 2021-10-24 07:56:04.857030018 +0200 ++++ openssh-8.7p1/progressmeter.c 2024-07-10 05:23:55.044944812 +0200 @@ -68,6 +68,8 @@ static off_t start_pos; /* initial position of transfer */ static off_t end_pos; /* ending position of transfer */ @@ -1642,17 +1754,17 @@ diff -Nur openssh-8.7p1.orig/progressmeter.c openssh-8.7p1/progressmeter.c /*ARGSUSED*/ diff -Nur openssh-8.7p1.orig/readconf.c openssh-8.7p1/readconf.c ---- openssh-8.7p1.orig/readconf.c 2021-10-24 07:54:36.870834202 +0200 -+++ openssh-8.7p1/readconf.c 2021-10-24 08:13:34.654331392 +0200 -@@ -67,6 +67,7 @@ - #include "uidswap.h" +--- openssh-8.7p1.orig/readconf.c 2024-07-09 13:38:43.819660940 +0200 ++++ openssh-8.7p1/readconf.c 2024-07-10 08:18:03.425445483 +0200 +@@ -69,6 +69,7 @@ #include "myproposal.h" #include "digest.h" -+#include "sshbuf.h" #include "ssh-gss.h" ++#include "sshbuf.h" /* Format of the configuration file: -@@ -169,6 +170,9 @@ + +@@ -170,6 +171,9 @@ oHashKnownHosts, oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand, oRemoteCommand, @@ -1662,7 +1774,7 @@ diff -Nur openssh-8.7p1.orig/readconf.c openssh-8.7p1/readconf.c oVisualHostKey, oKexAlgorithms, oIPQoS, oRequestTTY, oSessionType, oStdinNull, oForkAfterAuthentication, oIgnoreUnknown, oProxyUseFdpass, -@@ -313,6 +317,10 @@ +@@ -314,6 +318,10 @@ { "kexalgorithms", oKexAlgorithms }, { "ipqos", oIPQoS }, { "requesttty", oRequestTTY }, @@ -1673,19 +1785,18 @@ diff -Nur openssh-8.7p1.orig/readconf.c openssh-8.7p1/readconf.c { "sessiontype", oSessionType }, { "stdinnull", oStdinNull }, { "forkafterauthentication", oForkAfterAuthentication }, -@@ -336,6 +344,11 @@ +@@ -338,6 +346,10 @@ + { "knownhostscommand", oKnownHostsCommand }, { "requiredrsasize", oRequiredRSASize }, { "rsaminsize", oRequiredRSASize }, /* alias */ - + { "tcprcvbufpoll", oTcpRcvBufPoll }, + { "tcprcvbuf", oTcpRcvBuf }, + { "hpndisabled", oHPNDisabled }, + { "hpnbuffersize", oHPNBufferSize }, -+ + { NULL, oBadOption } }; - -@@ -1172,6 +1185,46 @@ +@@ -1175,6 +1187,46 @@ intptr = &options->check_host_ip; goto parse_flag; @@ -1732,7 +1843,7 @@ diff -Nur openssh-8.7p1.orig/readconf.c openssh-8.7p1/readconf.c case oVerifyHostKeyDNS: intptr = &options->verify_host_key_dns; multistate_ptr = multistate_yesnoask; -@@ -1426,6 +1479,10 @@ +@@ -1429,6 +1481,10 @@ *intptr = value; break; @@ -1743,7 +1854,7 @@ diff -Nur openssh-8.7p1.orig/readconf.c openssh-8.7p1/readconf.c case oCiphers: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') { -@@ -2440,6 +2497,14 @@ +@@ -2447,6 +2503,14 @@ options->ip_qos_interactive = -1; options->ip_qos_bulk = -1; options->request_tty = -1; @@ -1758,7 +1869,7 @@ diff -Nur openssh-8.7p1.orig/readconf.c openssh-8.7p1/readconf.c options->session_type = -1; options->stdin_null = -1; options->fork_after_authentication = -1; -@@ -2615,6 +2680,43 @@ +@@ -2623,6 +2687,43 @@ options->server_alive_interval = 0; if (options->server_alive_count_max == -1) options->server_alive_count_max = 3; @@ -1803,8 +1914,8 @@ diff -Nur openssh-8.7p1.orig/readconf.c openssh-8.7p1/readconf.c options->control_master = 0; if (options->control_persist == -1) { diff -Nur openssh-8.7p1.orig/readconf.h openssh-8.7p1/readconf.h ---- openssh-8.7p1.orig/readconf.h 2021-10-24 07:54:36.870834202 +0200 -+++ openssh-8.7p1/readconf.h 2021-10-24 07:56:04.860030025 +0200 +--- openssh-8.7p1.orig/readconf.h 2024-07-09 13:38:43.819660940 +0200 ++++ openssh-8.7p1/readconf.h 2024-07-10 06:26:33.500868479 +0200 @@ -55,6 +55,10 @@ int strict_host_key_checking; /* Strict host key checking. */ int compression; /* Compress packets in both directions. */ @@ -1816,38 +1927,22 @@ diff -Nur openssh-8.7p1.orig/readconf.h openssh-8.7p1/readconf.h 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. */ -@@ -126,7 +130,12 @@ - +@@ -127,6 +131,12 @@ int enable_ssh_keysign; int64_t rekey_limit; + int rekey_interval; ++ + 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.7p1.orig/regress/integrity.sh openssh-8.7p1/regress/integrity.sh ---- openssh-8.7p1.orig/regress/integrity.sh 2021-08-20 06:03:49.000000000 +0200 -+++ openssh-8.7p1/regress/integrity.sh 2021-10-24 07:56:04.860030025 +0200 -@@ -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 -+ # 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.7p1.orig/sandbox-seccomp-filter.c openssh-8.7p1/sandbox-seccomp-filter.c ---- openssh-8.7p1.orig/sandbox-seccomp-filter.c 2021-10-24 07:54:36.842834139 +0200 -+++ openssh-8.7p1/sandbox-seccomp-filter.c 2021-10-24 07:56:04.861030027 +0200 +--- openssh-8.7p1.orig/sandbox-seccomp-filter.c 2024-07-09 13:38:43.728660671 +0200 ++++ openssh-8.7p1/sandbox-seccomp-filter.c 2024-07-09 13:40:05.998903640 +0200 @@ -225,6 +225,9 @@ #ifdef __NR_geteuid32 SC_ALLOW(__NR_geteuid32), @@ -1868,30 +1963,989 @@ diff -Nur openssh-8.7p1.orig/sandbox-seccomp-filter.c openssh-8.7p1/sandbox-secc #ifdef __NR_time SC_ALLOW(__NR_time), #endif +diff -Nur openssh-8.7p1.orig/scp.1 openssh-8.7p1/scp.1 +--- openssh-8.7p1.orig/scp.1 2024-07-09 13:38:43.683660538 +0200 ++++ openssh-8.7p1/scp.1 2024-07-09 13:40:05.999903642 +0200 +@@ -18,7 +18,7 @@ + .Nd OpenSSH secure file copy + .Sh SYNOPSIS + .Nm scp +-.Op Fl 346ABCOpqRrTv ++.Op Fl 346ABCOpqRrTvZ + .Op Fl c Ar cipher + .Op Fl D Ar sftp_server_path + .Op Fl F Ar ssh_config +@@ -28,6 +28,7 @@ + .Op Fl o Ar ssh_option + .Op Fl P Ar port + .Op Fl S Ar program ++.Op Fl z Ar file path of remote scp + .Ar source ... target + .Sh DESCRIPTION + .Nm +@@ -251,6 +252,8 @@ + Note that + .Nm + follows symbolic links encountered in the tree traversal. ++.It Fl Z ++Resume failed or interrupted transfer. Identical files will be skipped. Remote must have resume option. + .It Fl S Ar program + Name of + .Ar program +@@ -258,6 +261,10 @@ + The program must understand + .Xr ssh 1 + options. ++.It Fl z Ar program ++Path to scp on remote system. Useful if remote has multiple scp installs. ++For example, using the resume option but the default remote scp does not have the resume option. ++Use -z to point the version that does - e.g. -z /opt/hpnssh/bin/scp + .It Fl T + Disable strict filename checking. + By default when copying files from a remote host to a local directory +@@ -316,3 +323,4 @@ + .Sh AUTHORS + .An Timo Rinne Aq Mt tri@iki.fi + .An Tatu Ylonen Aq Mt ylo@cs.hut.fi ++.An Chris Rapier Aq Mt rapier@psc.edu diff -Nur openssh-8.7p1.orig/scp.c openssh-8.7p1/scp.c ---- openssh-8.7p1.orig/scp.c 2021-10-24 07:54:36.854834166 +0200 -+++ openssh-8.7p1/scp.c 2021-10-24 07:56:04.861030027 +0200 -@@ -1566,7 +1566,7 @@ - off_t size, statbytes; +--- openssh-8.7p1.orig/scp.c 2024-07-09 13:38:43.762660771 +0200 ++++ openssh-8.7p1/scp.c 2024-07-10 06:40:12.849264367 +0200 +@@ -17,6 +17,7 @@ + /* + * Copyright (c) 1999 Theo de Raadt. All rights reserved. + * Copyright (c) 1999 Aaron Campbell. All rights reserved. ++ * Copyright (c) 2021 Chris Rapier. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions +@@ -131,6 +132,7 @@ + #include "progressmeter.h" + #include "utf8.h" + #include "sftp.h" ++#include + + #include "sftp-common.h" + #include "sftp-client.h" +@@ -172,6 +174,10 @@ + /* This is the program to execute for the secured connection. ("ssh" or -S) */ + char *ssh_program = _PATH_SSH_PROGRAM; + ++/* this is path to the remote scp program allowing the user to specify ++ * a non-default scp */ ++char *remote_path; ++ + /* This is used to store the pid of ssh_program */ + pid_t do_cmd_pid = -1; + pid_t do_cmd_pid2 = -1; +@@ -182,6 +188,12 @@ + int remote_glob(struct sftp_conn *, const char *, int, + int (*)(const char *, int), glob_t *); /* proto for sftp-glob.c */ + ++/* Flag to indicate that this is a file resume */ ++int resume_flag = 0; /* 0 is off, 1 is on */ ++ ++/* we want the host name for debugging purposes */ ++char hostname[HOST_NAME_MAX + 1]; ++ + static void + killchild(int signo) + { +@@ -227,6 +239,9 @@ + int status; + pid_t pid; + ++#ifdef DEBUG ++ fprintf(stderr, "In do_local_cmd\n"); ++#endif + if (a->num == 0) + fatal("do_local_cmd: no arguments"); + +@@ -435,6 +450,8 @@ + void tolocal(int, char *[], enum scp_mode_e, char *sftp_direct); + void toremote(int, char *[], enum scp_mode_e, char *sftp_direct); + void usage(void); ++void calculate_hash(char *, char *, off_t); /*get the hash of file to length*/ ++void rand_str(char *, size_t); /*gen randome char string */ + + void source_sftp(int, char *, char *, struct sftp_conn *); + void sink_sftp(int, char *, const char *, struct sftp_conn *); +@@ -452,6 +469,10 @@ + enum scp_mode_e mode = MODE_SFTP; + char *sftp_direct = NULL; + ++ /* we use this to prepend the debugging statements ++ * so we know which side is saying what */ ++ gethostname(hostname, HOST_NAME_MAX + 1); ++ + /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ + sanitise_stdfd(); + +@@ -459,6 +480,9 @@ + + msetlocale(); + ++ /* for use with rand function when resume option is used*/ ++ srand(time(NULL)); ++ + /* Copy argv, because we modify it */ + argv0 = argv[0]; + newargv = xcalloc(MAXIMUM(argc + 1, 1), sizeof(*newargv)); +@@ -482,7 +506,7 @@ + + fflag = Tflag = tflag = 0; + while ((ch = getopt(argc, argv, +- "12346ABCTdfOpqRrstvD:F:J:M:P:S:c:i:l:o:")) != -1) { ++ "12346ABCTdfOpqRrstvZz:D:F:J:M:P:S:c:i:l:o:")) != -1) { + switch (ch) { + /* User-visible flags. */ + case '1': +@@ -549,6 +573,9 @@ + case 'S': + ssh_program = xstrdup(optarg); + break; ++ case 'z': ++ remote_path = xstrdup(optarg); ++ break; + case 'v': + addargs(&args, "-v"); + addargs(&remote_remote_args, "-v"); +@@ -563,6 +590,9 @@ + addargs(&remote_remote_args, "-q"); + showprogress = 0; + break; ++ case 'Z': ++ resume_flag = 1; ++ break; + + /* Server options. */ + case 'd': +@@ -643,11 +673,20 @@ + remin = remout = -1; + do_cmd_pid = -1; + /* Command to be executed on remote system using "ssh". */ +- (void) snprintf(cmd, sizeof cmd, "scp%s%s%s%s", +- verbose_mode ? " -v" : "", +- iamrecursive ? " -r" : "", pflag ? " -p" : "", +- targetshouldbedirectory ? " -d" : ""); +- ++ /* the command uses the first scp in the users ++ * path. This isn't necessarily going to be the 'right' scp to use. ++ * So the current solution is to give the user the option of ++ * entering the path to correct scp. If they don't then it defaults ++ * to whatever scp is first in their path -cjr */ ++ (void) snprintf(cmd, sizeof cmd, "%s%s%s%s%s%s", ++ remote_path ? remote_path : "scp", ++ verbose_mode ? " -v" : "", ++ iamrecursive ? " -r" : "", pflag ? " -p" : "", ++ targetshouldbedirectory ? " -d" : "", ++ resume_flag ? " -R" : ""); ++#ifdef DEBUG ++ fprintf(stderr, "%s: Sending cmd %s\n", hostname, cmd); ++#endif + (void) ssh_signal(SIGPIPE, lostconn); + + if (colon(argv[argc - 1])) /* Dest is remote host. */ +@@ -1261,6 +1300,71 @@ + free(src); + } + ++/* calculate the hash of a file up to length bytes ++ * this is used to determine if remote and local file ++ * fragments match. There may be a more efficient process for the hashing ++ * TODO: I'd like to XXHash for the hashing but that requires that both ++ * ends have xxhash installed and then dealing with fallbacks */ ++void calculate_hash(char *filename, char *output, off_t length) ++{ ++#define HASH_LEN 128 /*40 sha1, 64 blake2s256 128 blake2b512*/ ++#define BUF_AND_HASH HASH_LEN + 64 /* length of the hash and other data to get size of buffer */ ++#define HASH_BUFLEN 8192 /* 8192 seems to be a good balance between freads ++ * and the digest func*/ ++ int n, md_len; ++ EVP_MD_CTX *c; ++ const EVP_MD *md; ++ char buf[HASH_BUFLEN]; ++ ssize_t bytes; ++ unsigned char out[EVP_MAX_MD_SIZE]; ++ char tmp[3]; ++ FILE *file_ptr; ++ *output = '\0'; ++ ++ /* open file for calculating hash */ ++ file_ptr = fopen(filename, "r"); ++ if (file_ptr==NULL) ++ { ++ if (verbose_mode) { ++ fprintf(stderr, "%s: error opening file %s\n", hostname, filename); ++ /* file the expected output with spaces */ ++ snprintf(output, HASH_LEN, "%s", " "); ++ } ++ return; ++ } ++ ++ md = EVP_get_digestbyname("blake2b512"); ++ c = EVP_MD_CTX_new(); ++ EVP_DigestInit_ex(c, md, NULL); ++ ++ while (length > 0) { ++ if (length > HASH_BUFLEN) ++ /* fread returns the number of elements read. ++ * in this case 1. Multiply by the length to get the bytes */ ++ bytes=fread(buf, HASH_BUFLEN, 1, file_ptr) * HASH_BUFLEN; ++ else ++ bytes=fread(buf, length, 1, file_ptr) * length; ++ EVP_DigestUpdate(c, buf, bytes); ++ length -= HASH_BUFLEN; ++ } ++ EVP_DigestFinal(c, out, &md_len); ++ EVP_MD_CTX_free(c); ++ /* convert the hash into a string */ ++ for(n=0; n < md_len; n++) { ++ snprintf(tmp, 3, "%02x", out[n]); ++ strncat(output, tmp, 3); ++ } ++#ifdef DEBUG ++ fprintf(stderr, "%s: HASH IS '%s' of length %ld\n", hostname, output, strlen(output)); ++#endif ++ fclose(file_ptr); ++} ++ ++#define TYPE_OVERFLOW(type, val) \ ++ ((sizeof(type) == 4 && (val) > INT32_MAX) || \ ++ (sizeof(type) == 8 && (val) > INT64_MAX) || \ ++ (sizeof(type) != 4 && sizeof(type) != 8)) ++ + /* Prepare remote path, handling ~ by assuming cwd is the homedir */ + static char * + prepare_remote_path(struct sftp_conn *conn, const char *path) +@@ -1344,14 +1448,23 @@ + struct stat stb; + static BUF buffer; + BUF *bp; +- off_t i, statbytes; ++ off_t i, statbytes, xfer_size; + size_t amt, nr; + int fd = -1, haderr, indx; +- char *last, *name, buf[PATH_MAX + 128], encname[PATH_MAX]; ++ char *cp, *last, *name, buf[PATH_MAX + BUF_AND_HASH], encname[PATH_MAX]; + int len; ++ char hashsum[HASH_LEN], test_hashsum[HASH_LEN]; ++ char inbuf[PATH_MAX + BUF_AND_HASH]; ++ size_t insize; ++ unsigned long long ull; ++ char *match; /* used to communicate fragment match */ ++ match = "\0"; /*default is to fail the match. NULL and F both indicate fail*/ + + for (indx = 0; indx < argc; ++indx) { + name = argv[indx]; ++#ifdef DEBUG ++ fprintf(stderr, "%s index is %d, name is %s\n", hostname, indx, name); ++#endif + statbytes = 0; + len = strlen(name); + while (len > 1 && name[len-1] == '/') +@@ -1373,6 +1486,14 @@ + unset_nonblock(fd); + switch (stb.st_mode & S_IFMT) { + case S_IFREG: ++ /* only calculate hash if we are in resume mode and a file*/ ++ if (resume_flag) { ++ calculate_hash(name, hashsum, stb.st_size); ++#ifdef DEBUG ++ fprintf(stderr, "%s: Name is '%s' and hash '%s'\n", hostname, name, hashsum); ++ fprintf (stderr,"%s: size of %s is %ld\n", hostname, name, stb.st_size); ++#endif ++ } + break; + case S_IFDIR: + if (iamrecursive) { +@@ -1394,14 +1515,132 @@ + goto next; + } + #define FILEMODEMASK (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO) +- snprintf(buf, sizeof buf, "C%04o %lld %s\n", +- (u_int) (stb.st_mode & FILEMODEMASK), +- (long long)stb.st_size, last); +- if (verbose_mode) +- fmprintf(stderr, "Sending file modes: %s", buf); ++ /* Add a hash of the file along with the filemode if in resume */ ++ if (resume_flag) ++ snprintf(buf, sizeof buf, "C%04o %lld %s %s\n", ++ (u_int) (stb.st_mode & FILEMODEMASK), ++ (long long)stb.st_size, hashsum, last); ++ else ++ snprintf(buf, sizeof buf, "C%04o %lld %s\n", ++ (u_int) (stb.st_mode & FILEMODEMASK), ++ (long long)stb.st_size, last); ++ ++#ifdef DEBUG ++ fprintf(stderr, "%s: Sending file modes: %s", hostname, buf); ++#endif + (void) atomicio(vwrite, remout, buf, strlen(buf)); +- if (response() < 0) ++ ++#ifdef DEBUG ++ fprintf(stderr, "%s: inbuf length %ld buf length %ld\n", hostname, strlen(inbuf), strlen(buf)); ++#endif ++ if (resume_flag) { /* get the hash response from the remote */ ++ (void) atomicio(read, remin, inbuf, BUF_AND_HASH - 1); ++#ifdef DEBUG ++ fprintf(stderr, "%s: we got '%s' in inbuf length %ld buf was %ld\n", ++ hostname, inbuf, strlen(inbuf), strlen(buf)); ++#endif ++ } ++ if (response() < 0) { ++#ifdef DEBUG ++ fprintf(stderr, "%s: response is less than 0\n", hostname); ++#endif + goto next; ++ } ++ xfer_size = stb.st_size; ++ ++ /* we only do the following in resume mode because we have a ++ * new buf from the remote to parse */ ++ if (resume_flag) { ++ cp = inbuf; ++ if (*cp == 'R') { /* resume file transfer*/ ++ char *in_hashsum; /* where to hold the incoming hash */ ++ in_hashsum = calloc(HASH_LEN+1, sizeof(char)); ++ for (++cp; cp < inbuf + 5; cp++) { ++ /* skip over the mode */ ++ } ++ if (*cp++ != ' ') { ++ fprintf(stderr, "%s: mode not delineated!\n", hostname); ++ } ++ ++ if (!isdigit((unsigned char)*cp)) ++ fprintf(stderr, "%s: size not present\n", hostname); ++ ull = strtoull(cp, &cp, 10); ++ if (!cp || *cp++ != ' ') ++ fprintf(stderr, "%s: size not delimited\n", hostname); ++ if (TYPE_OVERFLOW(off_t, ull)) ++ fprintf(stderr, "%s: size out of range\n", hostname); ++ insize = (off_t)ull; ++ ++#ifdef DEBUG ++ fprintf (stderr, "%s: received size of %ld\n", hostname, insize); ++#endif ++ ++ /* copy the cp pointer byte by byte */ ++ for (int i = 0; i < HASH_LEN; i++) { ++ strncat(in_hashsum, cp++, 1); ++ } ++#ifdef DEBUG ++ fprintf (stderr, "%s: in_hashsum '%s'\n", hostname, in_hashsum); ++#endif ++ ++ /*get the hash of the source file to the byte length we just got*/ ++ calculate_hash(name, test_hashsum, insize); ++#ifdef DEBUG ++ fprintf(stderr, "%s: calculated hashsum of local %s to %ld is %s\n", ++ hostname, last, insize, test_hashsum); ++#endif ++ /* compare the incoming hash to the hash of the local file*/ ++ if (strcmp(in_hashsum, test_hashsum) == 0) { ++ /* the fragments match so we should seek to the appropriate place in the ++ * local file and set the remote file to append */ ++#ifdef DEBUG ++ fprintf(stderr, "%s: File fragments match\n", hostname); ++ fprintf(stderr, "%s: seeking to %ld\n", hostname, insize); ++#endif ++ xfer_size = stb.st_size - insize; ++#ifdef DEBUG ++ fprintf(stderr, "%s: xfer_size: %ld, stb.st_size: %ld insize: %ld\n", ++ hostname, xfer_size, stb.st_size, insize); ++#endif ++ if (lseek(fd, insize, SEEK_CUR) != (off_t)insize) { ++#ifdef DEBUG ++ fprintf(stderr, "%s: lseek did not return %ld\n", hostname, insize) ; ++#endif ++ goto next; ++ } ++ match = "M"; ++ } else { ++ /* the fragments don't match so we should start over from the begining */ ++#ifdef DEBUG ++ fprintf(stderr, "%s: File fragments do not match '%s'(in) '%s'(local)\n", ++ hostname, in_hashsum, test_hashsum); ++#endif ++ match = "F"; ++ xfer_size = stb.st_size; ++ } ++ free(in_hashsum); ++ } ++ if (*cp == 'S') { /* skip file */ ++#ifdef DEBUG ++ fprintf(stderr, "%s: Should be skipping this file\n", hostname); ++#endif ++ goto next; ++ } ++ if (*cp == 'C') { /*transfer entire file*/ ++#ifdef DEBUG ++ fprintf(stderr, "%s: Resending entire file\n", hostname); ++#endif ++ xfer_size = stb.st_size; ++ } ++ /* need to send the match status ++ * We always send the match status or we get out of sync ++ */ ++#ifdef DEBUG ++ fprintf(stderr, "%s: sending match %s\n", hostname, match); ++#endif ++ (void) atomicio(vwrite, remout, match, 1); ++ } ++ + if ((bp = allocbuf(&buffer, fd, COPY_BUFLEN)) == NULL) { + next: if (fd != -1) { + (void) close(fd); +@@ -1409,13 +1648,17 @@ + } + continue; + } ++ ++#ifdef DEBUG ++ fprintf(stderr, "%s: going to xfer %ld\n", hostname, xfer_size); ++#endif + if (showprogress) +- start_progress_meter(curfile, stb.st_size, &statbytes); ++ start_progress_meter(curfile, xfer_size, &statbytes); + set_nonblock(remout); +- for (haderr = i = 0; i < stb.st_size; i += bp->cnt) { ++ for (haderr = i = 0; i < xfer_size; i += bp->cnt) { + amt = bp->cnt; +- if (i + (off_t)amt > stb.st_size) +- amt = stb.st_size - i; ++ if (i + (off_t)amt > xfer_size) ++ amt = xfer_size - i; + if (!haderr) { + if ((nr = atomicio(read, fd, + bp->buf, amt)) != amt) { +@@ -1599,24 +1842,36 @@ + sink(int argc, char **argv, const char *src) + { + static BUF buffer; +- struct stat stb; ++ struct stat stb, cpstat, npstat; + BUF *bp; + off_t i; + size_t j, count; + int amt, exists, first, ofd; + mode_t mode, omode, mask; +- off_t size, statbytes; ++ off_t size, statbytes, xfer_size; 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 ch, *cp, *np, *np_tmp, *targ, *why, *vect[1], buf[16384], visbuf[16384]; char **patterns = NULL; size_t n, npatterns = 0; struct timeval tv[2]; -diff -Nur openssh-8.7p1.orig/servconf.c openssh-8.7p1/servconf.c ---- openssh-8.7p1.orig/servconf.c 2021-10-24 07:54:36.871834204 +0200 -+++ openssh-8.7p1/servconf.c 2021-10-24 07:56:04.863030032 +0200 -@@ -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 *, -@@ -200,6 +201,12 @@ ++ char remote_hashsum[HASH_LEN+1]; ++ char local_hashsum[HASH_LEN+1]; ++ char tmpbuf[BUF_AND_HASH]; ++ char outbuf[BUF_AND_HASH]; ++ char match; ++ int bad_match_flag = 0; ++ np = '\0'; ++ np_tmp = NULL; ++ + #define atime tv[0] + #define mtime tv[1] + #define SCREWUP(str) { why = str; goto screwup; } + ++#ifdef DEBUG ++ fprintf (stderr, "%s: LOCAL In sink with %s\n", hostname, src); ++#endif + if (TYPE_OVERFLOW(time_t, 0) || TYPE_OVERFLOW(off_t, 0)) + SCREWUP("Unexpected off_t/time_t size"); + +@@ -1632,9 +1887,16 @@ + if (targetshouldbedirectory) + verifydir(targ); + ++#ifdef DEBUG ++ fprintf (stderr, "%s: Sending null to remout.\n",hostname); ++#endif + (void) atomicio(vwrite, remout, "", 1); + if (stat(targ, &stb) == 0 && S_ISDIR(stb.st_mode)) + targisdir = 1; ++ ++#ifdef DEBUG ++ fprintf(stderr, "%s: Target is %s with a size of %ld\n", hostname, targ, stb.st_size); ++#endif + if (src != NULL && !iamrecursive && !Tflag) { + /* + * Prepare to try to restrict incoming filenames to match +@@ -1643,7 +1905,12 @@ + if (brace_expand(src, &patterns, &npatterns) != 0) + fatal_f("could not expand pattern"); + } ++ + for (first = 1;; first = 0) { ++ bad_match_flag = 0; /* used in resume mode. */ ++#ifdef DEBUG ++ fprintf(stderr, "%s: At start of loop buf is %s\n", hostname, buf); ++#endif + cp = buf; + if (atomicio(read, remin, cp, 1) != 1) + goto done; +@@ -1671,6 +1938,9 @@ + continue; + } + if (buf[0] == 'E') { ++#ifdef DEBUG ++ fprintf (stderr, "%s: Sending null to remout.\n", hostname); ++#endif + (void) atomicio(vwrite, remout, "", 1); + goto done; + } +@@ -1678,6 +1948,9 @@ + *--cp = 0; + + cp = buf; ++#ifdef DEBUG ++ fprintf(stderr, "%s: buf is %s\n", hostname, buf); ++#endif + if (*cp == 'T') { + setimes++; + cp++; +@@ -1705,9 +1978,19 @@ + if (!cp || *cp++ != '\0' || atime.tv_usec < 0 || + atime.tv_usec > 999999) + SCREWUP("atime.usec not delimited"); ++ ++#ifdef DEBUG ++ fprintf (stderr, "%s: Sending null to remout.\n", hostname); ++#endif + (void) atomicio(vwrite, remout, "", 1); + continue; + } ++ if (*cp == 'R') { /*resume file transfer (dont' think I need this here)*/ ++#ifdef DEBUG ++ fprintf(stderr, "%s: Received a RESUME request with %s\n", hostname, cp); ++#endif ++ resume_flag = 1; ++ } + if (*cp != 'C' && *cp != 'D') { + /* + * Check for the case "rcp remote:foo\* local:bar". +@@ -1723,6 +2006,18 @@ + SCREWUP("expected control record"); + } + mode = 0; ++#ifdef DEBUG ++ fprintf(stderr, "%s: buf is %s\n", hostname, buf); ++ fprintf(stderr, "%s: cp is %s\n", hostname, cp); ++#endif ++ /* we need to track if this object is a directory ++ * before we move the pointer. If we are in resume mode ++ * we might end up trying to get an mdsum on a directory ++ * and that doesn't work */ ++ int dir_flag = 0; ++ if (*cp == 'D') ++ dir_flag = 1; ++ + for (++cp; cp < buf + 5; cp++) { + if (*cp < '0' || *cp > '7') + SCREWUP("bad mode"); +@@ -1733,6 +2028,10 @@ + if (*cp++ != ' ') + SCREWUP("mode not delimited"); + ++#ifdef DEBUG ++ fprintf(stderr, "%s: cp is %s\n", hostname, cp); ++#endif ++ + if (!isdigit((unsigned char)*cp)) + SCREWUP("size not present"); + ull = strtoull(cp, &cp, 10); +@@ -1742,11 +2041,31 @@ + SCREWUP("size out of range"); + size = (off_t)ull; + ++#ifdef DEBUG ++ fprintf(stderr, "%s: cp is %s\n", hostname, cp); ++#endif ++ if (resume_flag && !dir_flag) { ++ *remote_hashsum = '\0'; ++ for (int i = 0; i < HASH_LEN; i++) { ++ strncat (remote_hashsum, cp++, 1); ++ } ++#ifdef DEBUG ++ fprintf (stderr, "%s: '%s'\n", hostname, remote_hashsum); ++#endif ++ if (!cp || *cp++ != ' ') ++ SCREWUP("hash not delimited"); ++ } ++#ifdef DEBUG ++ fprintf(stderr, "%s: cp is %s\n", hostname, cp); ++#endif + if (*cp == '\0' || strchr(cp, '/') != NULL || + strcmp(cp, ".") == 0 || strcmp(cp, "..") == 0) { + run_err("error: unexpected filename: %s", cp); + exit(1); + } ++#ifdef DEBUG ++ fprintf(stderr, "%s cp is %s\n", hostname, cp); ++#endif + if (npatterns > 0) { + for (n = 0; n < npatterns; n++) { + if (fnmatch(patterns[n], cp, 0) == 0) +@@ -1807,11 +2126,195 @@ + } + omode = mode; + mode |= S_IWUSR; ++ stat(cp, &cpstat); ++ xfer_size = size; ++ if (resume_flag) { ++#ifdef DEBUG ++ fprintf(stderr, "%s: np is %s\n", hostname, np); ++#endif ++ /* does the file exist and if it does it writable? */ ++ if (stat(np, &npstat) == -1) { ++#ifdef DEBUG ++ fprintf(stderr, "%s Local file does not exist size is %ld!\n", ++ hostname, npstat.st_size); ++#endif ++ npstat.st_size = 0; ++ } else { ++ /* check to see if the file is writeable ++ * if it isn't then we need to skip it but ++ * before we skip it we need to send the remote ++ * what they are expecting so BUF_AND_HASH bytes and then ++ * a null. ++ * NOTE!!! The format in the snprintf needs the actual numeric ++ * because using a define isn't working */ ++ if (access (np, W_OK) != 0) { ++ fprintf(stderr, "scp: %s: Permission denied on %s\n", np, hostname); ++ snprintf(outbuf, BUF_AND_HASH, "S%-*s", BUF_AND_HASH-2, " "); ++ (void)atomicio(vwrite, remout, outbuf, strlen(outbuf)); ++ (void)atomicio(vwrite, remout, "", 1); ++ continue; ++ } ++ } ++ /* this file is already here do we need to move it? ++ * Check to make sure npstat.st_size > 0. If it is 0 then we ++ * may trying to be moving a zero byte file in which case this ++ * following block fails. See on 0 byte files the hashes will ++ * always match and the file won't be created even though it should ++ */ ++ if (xfer_size == npstat.st_size && (npstat.st_size > 0)) { ++ calculate_hash(np, local_hashsum, npstat.st_size); ++ if (strcmp(local_hashsum,remote_hashsum) == 0) { ++ /* we can skip this file if we want to. */ ++#ifdef DEBUG ++ fprintf(stderr, "%s: Files are the same\n", hostname); ++#endif ++ /* the remote is expecting something so we need to send them something*/ ++ snprintf(outbuf, BUF_AND_HASH, "S%-*s", BUF_AND_HASH-2, " "); ++ (void)atomicio(vwrite, remout, outbuf, strlen(outbuf)); ++#ifdef DEBUG ++ fprintf(stderr,"%s: sent '%s' to remote\n", hostname, outbuf); ++#endif ++ /* the remote is waiting on an ack so send a null */ ++ (void)atomicio(vwrite, remout, "", 1); ++ if (showprogress) ++ fprintf (stderr, "Skipping identical file: %s\n", np); ++ continue; ++ } else { ++ /* file sizes are the same but they don't match */ ++#ifdef DEBUG ++ fprintf(stderr, "%s: target(%ld) is different than source(%ld)!\n", ++ hostname, npstat.st_size, size); ++#endif ++ snprintf(tmpbuf, sizeof outbuf, "C%04o %lld %s", ++ (u_int) (npstat.st_mode & FILEMODEMASK), ++ (long long)npstat.st_size, local_hashsum); ++ snprintf(outbuf, BUF_AND_HASH, "%-*s", BUF_AND_HASH-1, tmpbuf); ++ (void) atomicio(vwrite, remout, outbuf, strlen(outbuf)); ++ bad_match_flag = 1; ++ } ++ } ++ /* if npstat.st_size is 0 then the local file doesn't exist and ++ * we have to move it. Since we are in resume mode treat it as a resume */ ++ if (npstat.st_size < xfer_size || (npstat.st_size == 0)) { ++ char rand_string[9]; ++#ifdef DEBUG ++ fprintf (stderr, "%s: %s is smaller than %s\n", hostname, np, cp); ++#endif ++ calculate_hash(np, local_hashsum, npstat.st_size); ++#define FILEMODEMASK (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO) ++ snprintf(tmpbuf, sizeof outbuf, "R%04o %lld %s", ++ (u_int) (npstat.st_mode & FILEMODEMASK), ++ (long long)npstat.st_size, local_hashsum); ++ snprintf(outbuf, BUF_AND_HASH, "%-*s", BUF_AND_HASH-1, tmpbuf); ++#ifdef DEBUG ++ fprintf (stderr, "%s: new buf is %s of length %ld\n", ++ hostname, outbuf, strlen(outbuf)); ++ fprintf(stderr, "%s: Sending new file (%s) modes: %s\n", ++ hostname, np, outbuf); ++#endif ++ /*now we have to send np's length and hash to the other end ++ * if the computed hashes match then we seek to np's length in ++ * file and append to np starting from there */ ++ (void) atomicio(vwrite, remout, outbuf, strlen(outbuf)); ++#ifdef DEBUG ++ fprintf(stderr, "%s: New size: %ld, size: %ld, st_size: %ld\n", ++ hostname, size - npstat.st_size, size, npstat.st_size); ++#endif ++ xfer_size = size - npstat.st_size; ++ resume_flag = 1; ++ np_tmp = xstrdup(np); ++ /* We should have a random component to avoid clobbering a ++ * local file */ ++ rand_str(rand_string, 8); ++ strcat(np, rand_string); ++#ifdef DEBUG ++ fprintf(stderr, "%s: Will concat %s to %s after xfer\n", ++ hostname, np, np_tmp); ++#endif ++ } else if (npstat.st_size > size) { ++ /* the target file is larger than the source. ++ * so we need to overwrite it. We don't need to send the hash though. */ ++#ifdef DEBUG ++ fprintf(stderr, "%s: target(%ld) is larger than source(%ld)!\n", ++ hostname, npstat.st_size, size); ++#endif ++ snprintf(tmpbuf, sizeof outbuf, "C%04o %lld", ++ (u_int) (npstat.st_mode & FILEMODEMASK), ++ (long long)npstat.st_size); ++ snprintf(outbuf, BUF_AND_HASH, "%-*s", BUF_AND_HASH-1, tmpbuf); ++ (void) atomicio(vwrite, remout, outbuf, strlen(outbuf)); ++ bad_match_flag = 1; ++ } ++ ++#ifdef DEBUG ++ fprintf (stderr, "%s: CP is %s(%ld) NP is %s(%ld)\n", ++ hostname, cp, size, np, npstat.st_size); ++#endif ++ /* we are in resume mode so we need this *here* and not later ++ * because we need to get the file match information from the remote ++ * outside of resume mode we don't get that so we get out of sync ++ * so we have a test for the resume_flag after this block */ ++#ifdef DEBUG ++ fprintf (stderr, "%s: Sending null to remout.\n", hostname); ++#endif ++ (void) atomicio(vwrite, remout, "", 1); ++ ++ /* the remote is always going to send a match status ++ * so we need to read it so we don't get out of sync */ ++ (void) atomicio(read, remin, &match, 1); ++ if (match != 'M') {/*fragments do not match*/ ++ /* expected response of F, M and NULL *but* ++ * anything other than M is a failure ++ * if it's a NULL then we reset xfer_size but ++ * we retain the file pointers */ ++ xfer_size = size; ++ bad_match_flag = 1; ++ if (match == 'F') { ++ /* got an F for failure and not NULL ++ * so we want to swap over the filename from ++ * the temp back to the original */ ++#ifdef DEBUG ++ fprintf(stderr, "%s: match status is F\n", hostname); ++#endif ++ if (np_tmp != NULL) ++ np = np_tmp; ++ else { ++ continue; ++ } ++ } else { ++#ifdef DEBUG ++ fprintf(stderr, "%s: match received is NULL\n", hostname); ++#endif ++ } ++ } else { ++#ifdef DEBUG ++ fprintf(stderr, "%s match status is M\n", hostname); ++#endif ++ bad_match_flag = 0; /* while this is set at the beginning of the ++ * loop I'm setting it here explicitly as well */ ++ } ++ } ++ ++#ifdef DEBUG ++ fprintf(stderr, "%s: Creating file. mode is %d for %s\n", ++ hostname, mode, np); ++#endif + if ((ofd = open(np, O_WRONLY|O_CREAT, mode)) == -1) { + bad: run_err("%s: %s", np, strerror(errno)); + continue; + } +- (void) atomicio(vwrite, remout, "", 1); ++ ++ /* in the case of not using the resume function we need this vwrite here ++ * in the case of using the resume flag it comes in the above if (resume_flag) block ++ * why? because scp is weird and depends on an intricate and silly dance of ++ * call and response at just the right time. That's why */ ++ if (!resume_flag) { ++#ifdef DEBUG ++ fprintf (stderr, "%s: Sending null to remout.\n", hostname); ++#endif ++ (void) atomicio(vwrite, remout, "", 1); ++ } ++ + if ((bp = allocbuf(&buffer, ofd, COPY_BUFLEN)) == NULL) { + (void) close(ofd); + continue; +@@ -1826,13 +2329,17 @@ + */ + statbytes = 0; + if (showprogress) +- start_progress_meter(curfile, size, &statbytes); ++ start_progress_meter(curfile, xfer_size, &statbytes); + set_nonblock(remin); +- for (count = i = 0; i < size; i += bp->cnt) { ++#ifdef DEBUG ++ fprintf(stderr, "%s: xfer_size is %ld\n", hostname, xfer_size); ++#endif ++ for (count = i = 0; i < xfer_size; i += bp->cnt) { + amt = bp->cnt; +- if (i + amt > size) +- amt = size - i; ++ if (i + amt > xfer_size) ++ amt = xfer_size - i; + count += amt; ++ /* read the data from the socket*/ + do { + j = atomicio6(read, remin, cp, amt, + scpio, &statbytes); +@@ -1867,8 +2374,78 @@ + wrerr = 1; + } + if (!wrerr && (!exists || S_ISREG(stb.st_mode)) && +- ftruncate(ofd, size) != 0) ++ ftruncate(ofd, xfer_size) != 0) + note_err("%s: truncate: %s", np, strerror(errno)); ++ ++ /* if np_tmp isn't set then we don't have a resume file to cat */ ++ /* likewise, bad match flag means no resume flag */ ++#ifdef DEBUG ++ fprintf (stderr, "%s: resume_flag: %d, np_tmp: %s, bad_match_flag: %d\n", ++ hostname, resume_flag, np_tmp, bad_match_flag); ++#endif ++ if (resume_flag && np_tmp && !bad_match_flag) { ++ FILE *orig, *resume; ++ char res_buf[512]; /* set at 512 just because, might want to increase*/ ++ ssize_t res_bytes = 0; ++ off_t sum = 0; ++ struct stat res_stat; ++ *res_buf = '\0'; ++ orig = NULL; /*supress warnings*/ ++ resume = NULL; /*supress warnings*/ ++#ifdef DEBUG ++ fprintf(stderr, "%s: Resume flag is set. Going to concat %s to %s now\n", ++ hostname, np, np_tmp); ++#endif ++ /* np/ofd is the resume file so open np_tmp for appending ++ * close ofd because we are going to be shifting it ++ * and I don't wnat the same file open in multiple descriptors */ ++ if (close(ofd) == -1) ++ note_err("%s: close: %s", np, strerror(errno)); ++ /* orig is the target file, resume is the temp file */ ++ orig = fopen(np_tmp, "a"); /*open for appending*/ ++ if (orig == NULL) { ++ fprintf(stderr, "%s: Could not open %s for appending.", hostname, np_tmp); ++ goto stopcat; ++ } ++ resume = fopen(np, "r"); /*open for reading only*/ ++ if (resume == NULL) { ++ fprintf(stderr, "%s: Could not open %s for reading.", hostname, np); ++ goto stopcat; ++ } ++ /* get the number of bytes in the temp file*/ ++ if (fstat(fileno(resume), &res_stat) == -1) { ++ fprintf(stderr, "%s: Could not stat %s", hostname, np); ++ goto stopcat; ++ } ++ /* while the number of bytes read from the temp file ++ * is less than the size of the file read in a chunk and ++ * write it to the target file */ ++ do { ++ res_bytes = fread(res_buf, 1, 512, resume); ++ fwrite(res_buf, 1, res_bytes, orig); ++ sum += res_bytes; ++ } while (sum < res_stat.st_size); ++ ++stopcat: if (orig) ++ fclose(orig); ++ if (resume) ++ fclose(resume); ++ /* delete the resume file */ ++ remove(np); ++#ifdef DEBUG ++ fprintf (stderr, "%s: np(%s) and np_tmp(%s)\n", hostname, np, np_tmp); ++#endif ++ np = np_tmp; ++#ifdef DEBUG ++ fprintf (stderr, "%s np(%s) and np_tmp(%s)\n", hostname, np, np_tmp); ++#endif ++ /* reset ofd to the original np */ ++ if ((ofd = open(np_tmp, O_WRONLY)) == -1) { ++ fprintf(stderr, "%s: couldn't open %s in append function\n", hostname, np_tmp); ++ atomicio(vwrite, remout, "", 1); ++ goto bad; ++ } ++ } + if (pflag) { + if (exists || omode != mode) + #ifdef HAVE_FCHMOD +@@ -1903,8 +2480,17 @@ + } + } + /* If no error was noted then signal success for this file */ +- if (note_err(NULL) == 0) ++ if (note_err(NULL) == 0) { ++#ifdef DEBUG ++ fprintf (stderr, "%s: Sending null to remout.\n", hostname); ++#endif + (void) atomicio(vwrite, remout, "", 1); ++ } ++ /* we are in resume mode and we have allocated memory for np_tmp */ ++ if (resume_flag && np_tmp != NULL) { ++ free(np_tmp); ++ np_tmp = NULL; ++ } + } + done: + for (n = 0; n < npatterns; n++) +@@ -2034,9 +2620,10 @@ + usage(void) + { + (void) fprintf(stderr, +- "usage: scp [-346ABCOpqRrTv] [-c cipher] [-D sftp_server_path] [-F ssh_config]\n" ++ "usage: scp [-346ABCOpqRrTvZ] [-c cipher] [-D sftp_server_path] [-F ssh_config]\n" + " [-i identity_file] [-J destination] [-l limit]\n" +- " [-o ssh_option] [-P port] [-S program] source ... target\n"); ++ " [-o ssh_option] [-P port] [-z filepath of remote scp]\n" ++ " [-S program] source ... target\n"); + exit(1); + } + +@@ -2176,6 +2763,18 @@ + exit(1); + } + ++void rand_str(char *dest, size_t length) { ++ char charset[] = "0123456789" ++ "abcdefghijklmnopqrstuvwxyz" ++ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; ++ ++ while (length-- > 0) { ++ size_t index = (double) rand() / RAND_MAX * (sizeof charset - 1); ++ *dest++ = charset[index]; ++ } ++ *dest = '\0'; ++} ++ + void + cleanup_exit(int i) + { +diff -Nur openssh-8.7p1.orig/servconf.c openssh-8.7p1/servconf.c +--- openssh-8.7p1.orig/servconf.c 2024-07-09 13:38:43.820660943 +0200 ++++ openssh-8.7p1/servconf.c 2024-07-10 05:45:47.022756751 +0200 +@@ -201,6 +201,12 @@ options->authorized_principals_file = NULL; options->authorized_principals_command = NULL; options->authorized_principals_command_user = NULL; @@ -1904,7 +2958,7 @@ diff -Nur openssh-8.7p1.orig/servconf.c openssh-8.7p1/servconf.c options->ip_qos_interactive = -1; options->ip_qos_bulk = -1; options->version_addendum = NULL; -@@ -290,6 +297,10 @@ +@@ -292,6 +298,10 @@ fill_default_server_options(ServerOptions *options) { u_int i; @@ -1915,7 +2969,7 @@ diff -Nur openssh-8.7p1.orig/servconf.c openssh-8.7p1/servconf.c /* Portable-specific options */ if (options->use_pam == -1) -@@ -461,6 +472,51 @@ +@@ -463,6 +473,51 @@ } if (options->permit_tun == -1) options->permit_tun = SSH_TUNMODE_NO; @@ -1967,7 +3021,7 @@ diff -Nur openssh-8.7p1.orig/servconf.c openssh-8.7p1/servconf.c if (options->ip_qos_interactive == -1) options->ip_qos_interactive = IPTOS_DSCP_AF21; if (options->ip_qos_bulk == -1) -@@ -533,6 +589,9 @@ +@@ -537,6 +592,9 @@ sPasswordAuthentication, sKbdInteractiveAuthentication, sListenAddress, sAddressFamily, sPrintMotd, sPrintLastLog, sIgnoreRhosts, @@ -1977,7 +3031,7 @@ diff -Nur openssh-8.7p1.orig/servconf.c openssh-8.7p1/servconf.c sX11Forwarding, sX11DisplayOffset, sX11MaxDisplays, sX11UseLocalhost, sPermitTTY, sStrictModes, sEmptyPasswd, sTCPKeepAlive, sPermitUserEnvironment, sAllowTcpForwarding, sCompression, -@@ -733,6 +792,12 @@ +@@ -738,6 +796,12 @@ { "revokedkeys", sRevokedKeys, SSHCFG_ALL }, { "trustedusercakeys", sTrustedUserCAKeys, SSHCFG_ALL }, { "authorizedprincipalsfile", sAuthorizedPrincipalsFile, SSHCFG_ALL }, @@ -1990,7 +3044,7 @@ diff -Nur openssh-8.7p1.orig/servconf.c openssh-8.7p1/servconf.c { "kexalgorithms", sKexAlgorithms, SSHCFG_GLOBAL }, { "include", sInclude, SSHCFG_ALL }, { "ipqos", sIPQoS, SSHCFG_ALL }, -@@ -791,6 +856,7 @@ +@@ -798,6 +862,7 @@ for (i = 0; keywords[i].name; i++) if (strcasecmp(cp, keywords[i].name) == 0) { @@ -1998,7 +3052,7 @@ diff -Nur openssh-8.7p1.orig/servconf.c openssh-8.7p1/servconf.c *flags = keywords[i].flags; return keywords[i].opcode; } -@@ -1568,12 +1634,36 @@ +@@ -1575,12 +1640,36 @@ multistate_ptr = multistate_ignore_rhosts; goto parse_multistate; @@ -2036,8 +3090,8 @@ diff -Nur openssh-8.7p1.orig/servconf.c openssh-8.7p1/servconf.c intptr = &options->hostbased_authentication; goto parse_flag; diff -Nur openssh-8.7p1.orig/servconf.h openssh-8.7p1/servconf.h ---- openssh-8.7p1.orig/servconf.h 2021-10-24 07:54:36.871834204 +0200 -+++ openssh-8.7p1/servconf.h 2021-10-24 07:56:04.864030034 +0200 +--- openssh-8.7p1.orig/servconf.h 2024-07-09 13:38:43.821660946 +0200 ++++ openssh-8.7p1/servconf.h 2024-07-09 13:40:06.000903645 +0200 @@ -214,6 +214,13 @@ int use_pam; /* Enable auth via PAM */ int permit_pam_user_change; /* Allow PAM to change user name */ @@ -2046,15 +3100,15 @@ diff -Nur openssh-8.7p1.orig/servconf.h openssh-8.7p1/servconf.h + 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 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.7p1.orig/serverloop.c openssh-8.7p1/serverloop.c ---- openssh-8.7p1.orig/serverloop.c 2021-10-24 07:54:36.855834168 +0200 -+++ openssh-8.7p1/serverloop.c 2021-10-24 07:56:04.865030036 +0200 +--- openssh-8.7p1.orig/serverloop.c 2024-07-09 13:38:43.772660801 +0200 ++++ openssh-8.7p1/serverloop.c 2024-07-10 05:48:02.027149199 +0200 @@ -266,7 +266,7 @@ process_input(struct ssh *ssh, fd_set *readset, int connection_in) { @@ -2080,15 +3134,23 @@ diff -Nur openssh-8.7p1.orig/serverloop.c openssh-8.7p1/serverloop.c if (sigemptyset(&bsigset) == -1 || sigaddset(&bsigset, SIGCHLD) == -1) error_f("bsigset setup: %s", strerror(errno)); -@@ -388,6 +390,7 @@ +@@ -387,7 +389,9 @@ + error_f("osigset sigprocmask: %s", strerror(errno)); 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); } -@@ -409,6 +412,9 @@ +@@ -406,9 +410,15 @@ + 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); @@ -2098,7 +3160,7 @@ diff -Nur openssh-8.7p1.orig/serverloop.c openssh-8.7p1/serverloop.c /* free remaining sessions, e.g. remove wtmp entries */ session_destroy_all(ssh, NULL); } -@@ -559,7 +565,8 @@ +@@ -559,7 +569,8 @@ debug("Tunnel forwarding using interface %s", ifname); c = channel_new(ssh, "tun", SSH_CHANNEL_OPEN, sock, sock, -1, @@ -2108,7 +3170,7 @@ diff -Nur openssh-8.7p1.orig/serverloop.c openssh-8.7p1/serverloop.c c->datagram = 1; #if defined(SSH_TUN_FILTER) if (mode == SSH_TUNMODE_POINTOPOINT) -@@ -610,6 +617,8 @@ +@@ -610,6 +621,8 @@ c = channel_new(ssh, "session", SSH_CHANNEL_LARVAL, -1, -1, -1, /*window size*/0, CHAN_SES_PACKET_DEFAULT, 0, "server-session", 1); @@ -2118,8 +3180,8 @@ diff -Nur openssh-8.7p1.orig/serverloop.c openssh-8.7p1/serverloop.c debug("session open failed, free channel %d", c->self); channel_free(ssh, c); diff -Nur openssh-8.7p1.orig/session.c openssh-8.7p1/session.c ---- openssh-8.7p1.orig/session.c 2021-10-24 07:54:36.855834168 +0200 -+++ openssh-8.7p1/session.c 2021-10-24 07:56:04.866030038 +0200 +--- openssh-8.7p1.orig/session.c 2024-07-09 13:38:43.763660775 +0200 ++++ openssh-8.7p1/session.c 2024-07-09 13:40:06.001903648 +0200 @@ -228,6 +228,7 @@ goto authsock_err; @@ -2140,7 +3202,7 @@ diff -Nur openssh-8.7p1.orig/session.c openssh-8.7p1/session.c /* diff -Nur openssh-8.7p1.orig/sftp.1 openssh-8.7p1/sftp.1 --- openssh-8.7p1.orig/sftp.1 2021-08-20 06:03:49.000000000 +0200 -+++ openssh-8.7p1/sftp.1 2021-10-24 07:56:04.867030041 +0200 ++++ openssh-8.7p1/sftp.1 2024-07-09 13:40:06.002903651 +0200 @@ -295,7 +295,8 @@ Specify how many requests may be outstanding at any one time. Increasing this may slightly improve file transfer speed @@ -2152,20 +3214,21 @@ diff -Nur openssh-8.7p1.orig/sftp.1 openssh-8.7p1/sftp.1 Recursively copy entire directories when uploading and downloading. Note that diff -Nur openssh-8.7p1.orig/sftp-client.c openssh-8.7p1/sftp-client.c ---- openssh-8.7p1.orig/sftp-client.c 2021-08-20 06:03:49.000000000 +0200 -+++ openssh-8.7p1/sftp-client.c 2021-10-24 07:56:04.868030043 +0200 -@@ -72,7 +72,7 @@ +--- openssh-8.7p1.orig/sftp-client.c 2024-07-09 13:38:43.764660777 +0200 ++++ openssh-8.7p1/sftp-client.c 2024-07-09 13:40:06.002903651 +0200 +@@ -72,7 +72,8 @@ #define DEFAULT_COPY_BUFLEN 32768 /* Default number of concurrent outstanding requests */ -#define DEFAULT_NUM_REQUESTS 64 -+#define DEFAULT_NUM_REQUESTS 256 ++#define DEFAULT_NUM_REQUESTS 512 ++/* 512 outstanding requests gives us 16MB of receive buffer space */ /* Minimum amount of data to read at a time */ #define MIN_READ_SIZE 512 diff -Nur openssh-8.7p1.orig/ssh_api.c openssh-8.7p1/ssh_api.c --- openssh-8.7p1.orig/ssh_api.c 2021-08-20 06:03:49.000000000 +0200 -+++ openssh-8.7p1/ssh_api.c 2021-10-24 07:56:04.869030045 +0200 ++++ openssh-8.7p1/ssh_api.c 2024-07-09 13:40:06.002903651 +0200 @@ -410,7 +410,7 @@ char *cp; int r; @@ -2177,7 +3240,7 @@ diff -Nur openssh-8.7p1.orig/ssh_api.c openssh-8.7p1/ssh_api.c return r; diff -Nur openssh-8.7p1.orig/sshbuf.h openssh-8.7p1/sshbuf.h --- openssh-8.7p1.orig/sshbuf.h 2021-08-20 06:03:49.000000000 +0200 -+++ openssh-8.7p1/sshbuf.h 2021-10-24 07:56:04.870030047 +0200 ++++ openssh-8.7p1/sshbuf.h 2024-07-09 13:40:06.003903654 +0200 @@ -28,7 +28,7 @@ # endif /* OPENSSL_HAS_ECC */ #endif /* WITH_OPENSSL */ @@ -2188,9 +3251,9 @@ diff -Nur openssh-8.7p1.orig/sshbuf.h openssh-8.7p1/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.7p1.orig/ssh.c openssh-8.7p1/ssh.c ---- openssh-8.7p1.orig/ssh.c 2021-10-24 07:54:36.872834206 +0200 -+++ openssh-8.7p1/ssh.c 2021-10-24 07:56:04.871030049 +0200 -@@ -1056,6 +1056,10 @@ +--- openssh-8.7p1.orig/ssh.c 2024-07-09 13:38:43.822660949 +0200 ++++ openssh-8.7p1/ssh.c 2024-07-09 13:40:06.003903654 +0200 +@@ -1099,6 +1099,10 @@ break; case 'T': options.request_tty = REQUEST_TTY_NO; @@ -2201,7 +3264,7 @@ diff -Nur openssh-8.7p1.orig/ssh.c openssh-8.7p1/ssh.c break; case 'o': line = xstrdup(optarg); -@@ -1784,6 +1788,8 @@ +@@ -1832,6 +1836,8 @@ setproctitle("%s [mux]", options.control_path); } @@ -2210,7 +3273,7 @@ diff -Nur openssh-8.7p1.orig/ssh.c openssh-8.7p1/ssh.c /* Do fork() after authentication. Used by "ssh -f" */ static void fork_postauth(void) -@@ -2101,6 +2107,79 @@ +@@ -2149,6 +2155,79 @@ NULL, fileno(stdin), command, environ); } @@ -2290,32 +3353,30 @@ diff -Nur openssh-8.7p1.orig/ssh.c openssh-8.7p1/ssh.c /* open new channel for a session */ static int ssh_session2_open(struct ssh *ssh) -@@ -2119,9 +2198,11 @@ +@@ -2167,9 +2246,10 @@ if (in == -1 || out == -1 || err == -1) fatal("dup() in/out/err failed"); - 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; } -@@ -2132,6 +2213,11 @@ - - debug3_f("channel_new: %d", c->self); +@@ -2178,6 +2258,10 @@ + window, packetmax, CHAN_EXTENDED_WRITE, + "client-session", CHANNEL_NONBLOCK_STDIO); + if (options.tcp_rcv_buf_poll > 0 && !options.hpn_disabled) { + c->dynamic_window = 1; + debug("Enabled Dynamic Window Scaling"); + } -+ + debug3_f("channel_new: %d", c->self); + channel_send_open(ssh, c->self); - if (options.session_type != SESSION_TYPE_NONE) - channel_register_open_confirm(ssh, c->self, -@@ -2146,6 +2232,13 @@ +@@ -2194,6 +2278,13 @@ int r, id = -1; char *cp, *tun_fwd_ifname = NULL; @@ -2330,8 +3391,8 @@ diff -Nur openssh-8.7p1.orig/ssh.c openssh-8.7p1/ssh.c if (!options.control_persist) ssh_init_stdio_forwarding(ssh); diff -Nur openssh-8.7p1.orig/sshconnect2.c openssh-8.7p1/sshconnect2.c ---- openssh-8.7p1.orig/sshconnect2.c 2021-10-24 07:54:36.873834208 +0200 -+++ openssh-8.7p1/sshconnect2.c 2021-10-24 08:06:47.586411958 +0200 +--- openssh-8.7p1.orig/sshconnect2.c 2024-07-09 13:38:43.823660952 +0200 ++++ openssh-8.7p1/sshconnect2.c 2024-07-10 05:53:06.277033821 +0200 @@ -86,6 +86,13 @@ extern Options options; @@ -2346,7 +3407,7 @@ diff -Nur openssh-8.7p1.orig/sshconnect2.c openssh-8.7p1/sshconnect2.c * SSH2 key exchange */ -@@ -212,6 +219,8 @@ +@@ -217,6 +224,8 @@ return ret; } @@ -2355,7 +3416,7 @@ diff -Nur openssh-8.7p1.orig/sshconnect2.c openssh-8.7p1/sshconnect2.c void ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port, const struct ssh_conn_info *cinfo) -@@ -225,6 +234,8 @@ +@@ -232,6 +241,8 @@ char *gss_host = NULL; #endif @@ -2364,7 +3425,7 @@ diff -Nur openssh-8.7p1.orig/sshconnect2.c openssh-8.7p1/sshconnect2.c xxx_host = host; xxx_hostaddr = hostaddr; xxx_conn_info = cinfo; -@@ -569,6 +582,53 @@ +@@ -584,6 +595,51 @@ if (!authctxt.success) fatal("Authentication failed."); @@ -2405,8 +3466,7 @@ diff -Nur openssh-8.7p1.orig/sshconnect2.c openssh-8.7p1/sshconnect2.c + * 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 */ ++ /* only do this for the ctr cipher. otherwise gcm mode breaks. */ + if (strstr(cipher_ctx_name(cc), "ctr")) { + debug("Single to Multithread CTR cipher swap - client request"); + cipher_reset_multithreaded(); @@ -2414,13 +3474,12 @@ diff -Nur openssh-8.7p1.orig/sshconnect2.c openssh-8.7p1/sshconnect2.c + } + } +#endif -+ if (ssh_packet_connection_is_on_socket(ssh)) { verbose("Authenticated to %s ([%s]:%d) using \"%s\".", host, ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), diff -Nur openssh-8.7p1.orig/sshconnect.c openssh-8.7p1/sshconnect.c ---- openssh-8.7p1.orig/sshconnect.c 2021-10-24 07:54:36.794834032 +0200 -+++ openssh-8.7p1/sshconnect.c 2021-10-24 07:56:04.873030054 +0200 +--- openssh-8.7p1.orig/sshconnect.c 2024-07-09 13:38:43.647660432 +0200 ++++ openssh-8.7p1/sshconnect.c 2024-07-10 05:54:01.339194000 +0200 @@ -345,6 +345,30 @@ #endif @@ -2463,8 +3522,8 @@ diff -Nur openssh-8.7p1.orig/sshconnect.c openssh-8.7p1/sshconnect.c if (options.ip_qos_interactive != INT_MAX) set_sock_tos(sock, options.ip_qos_interactive); diff -Nur openssh-8.7p1.orig/sshd.c openssh-8.7p1/sshd.c ---- openssh-8.7p1.orig/sshd.c 2021-10-24 07:54:36.874834211 +0200 -+++ openssh-8.7p1/sshd.c 2021-10-24 08:00:18.185586742 +0200 +--- openssh-8.7p1.orig/sshd.c 2024-07-09 13:38:43.824660955 +0200 ++++ openssh-8.7p1/sshd.c 2024-07-10 05:58:30.651977467 +0200 @@ -1110,6 +1110,8 @@ int ret, listen_sock; struct addrinfo *ai; @@ -2486,7 +3545,7 @@ diff -Nur openssh-8.7p1.orig/sshd.c openssh-8.7p1/sshd.c /* 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.", -@@ -1854,6 +1861,19 @@ +@@ -1855,6 +1862,19 @@ /* Fill in default values for those options not explicitly set. */ fill_default_server_options(&options); @@ -2506,7 +3565,7 @@ diff -Nur openssh-8.7p1.orig/sshd.c openssh-8.7p1/sshd.c /* Check that options are sensible */ if (options.authorized_keys_command_user == NULL && (options.authorized_keys_command != NULL && -@@ -2301,6 +2321,9 @@ +@@ -2346,6 +2366,9 @@ rdomain == NULL ? "" : "\""); free(laddr); @@ -2516,7 +3575,7 @@ diff -Nur openssh-8.7p1.orig/sshd.c openssh-8.7p1/sshd.c /* * We don't want to listen forever unless the other side * successfully authenticates itself. So we set up an alarm which is -@@ -2413,6 +2436,25 @@ +@@ -2458,6 +2481,25 @@ /* Try to send all our hostkeys to the client */ notify_hostkeys(ssh); @@ -2542,8 +3601,8 @@ diff -Nur openssh-8.7p1.orig/sshd.c openssh-8.7p1/sshd.c /* Start session. */ do_authenticated(ssh, authctxt); -@@ -2486,6 +2528,11 @@ - char *prop_kex = NULL, *prop_enc = NULL, *prop_hostkey = NULL; +@@ -2534,6 +2576,11 @@ + char *cp; int r; + if (options.none_enabled == 1) @@ -2551,13 +3610,13 @@ diff -Nur openssh-8.7p1.orig/sshd.c openssh-8.7p1/sshd.c + if (options.nonemac_enabled == 1) + debug("WARNING: None MAC enabled"); + - myproposal[PROPOSAL_KEX_ALGS] = prop_kex = compat_kex_proposal(ssh, - options.kex_algorithms); - myproposal[PROPOSAL_ENC_ALGS_CTOS] = + if ((cp = kex_names_cat(options.kex_algorithms, + "kex-strict-s-v00@openssh.com")) == NULL) + fatal_f("kex_names_cat"); diff -Nur openssh-8.7p1.orig/sshd_config openssh-8.7p1/sshd_config ---- openssh-8.7p1.orig/sshd_config 2021-10-24 07:54:36.874834211 +0200 -+++ openssh-8.7p1/sshd_config 2021-10-24 07:56:04.875030058 +0200 -@@ -127,6 +127,28 @@ +--- openssh-8.7p1.orig/sshd_config 2024-07-09 13:38:43.824660955 +0200 ++++ openssh-8.7p1/sshd_config 2024-07-09 13:40:06.005903660 +0200 +@@ -127,6 +127,22 @@ # override default of no subsystems Subsystem sftp /usr/libexec/sftp-server @@ -2576,24 +3635,18 @@ diff -Nur openssh-8.7p1.orig/sshd_config openssh-8.7p1/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 # X11Forwarding no diff -Nur openssh-8.7p1.orig/version.h openssh-8.7p1/version.h ---- openssh-8.7p1.orig/version.h 2021-10-24 07:54:36.876834215 +0200 -+++ openssh-8.7p1/version.h 2021-10-24 07:56:04.876030061 +0200 +--- openssh-8.7p1.orig/version.h 2024-07-09 13:38:43.825660957 +0200 ++++ openssh-8.7p1/version.h 2024-07-10 06:12:42.744455173 +0200 @@ -16,5 +16,6 @@ #define SSH_PORTABLE "p1" #define GSI_PORTABLE "c-GSI" -+#define SSH_HPN "-hpn15v2" ++#define SSH_HPN "-hpn15v4" #define SSH_RELEASE SSH_VERSION SSH_PORTABLE GSI_PORTABLE \ - GSI_VERSION KRB5_VERSION -+ GSI_VERSION SSH_HPN KRB5_VERSION ++ GSI_VERSION KRB5_VERSION SSH_HPN diff --git a/openssh-8.7p1-man-hostkeyalgos.patch b/openssh-8.7p1-man-hostkeyalgos.patch new file mode 100644 index 0000000..92c53b1 --- /dev/null +++ b/openssh-8.7p1-man-hostkeyalgos.patch @@ -0,0 +1,31 @@ +diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac openssh-8.7p1/ssh_config.5 openssh-8.7p1-patched/ssh_config.5 +--- openssh-8.7p1/ssh_config.5 2023-06-02 09:14:40.279373577 +0200 ++++ openssh-8.7p1-patched/ssh_config.5 2023-05-30 16:01:04.533848172 +0200 +@@ -989,6 +989,17 @@ + .Pp + The list of available signature algorithms may also be obtained using + .Qq ssh -Q HostKeyAlgorithms . ++.Pp ++The proposed ++.Cm HostKeyAlgorithms ++during KEX are limited to the set of algorithms that is defined in ++.Cm PubkeyAcceptedAlgorithms ++and therefore they are indirectly affected by system-wide ++.Xr crypto_policies 7 . ++.Xr crypto_policies 7 can not handle the list of host key algorithms directly as doing so ++would break the order given by the ++.Pa known_hosts ++file. + .It Cm HostKeyAlias + Specifies an alias that should be used instead of the + real host name when looking up or saving the host key +@@ -1564,6 +1575,9 @@ + .Pp + The list of available signature algorithms may also be obtained using + .Qq ssh -Q PubkeyAcceptedAlgorithms . ++.Pp ++This option affects also ++.Cm HostKeyAlgorithms + .It Cm PubkeyAuthentication + Specifies whether to try public key authentication. + The argument to this keyword must be diff --git a/openssh-8.7p1-nohostsha1proof.patch b/openssh-8.7p1-nohostsha1proof.patch index a5323e4..5c54e78 100644 --- a/openssh-8.7p1-nohostsha1proof.patch +++ b/openssh-8.7p1-nohostsha1proof.patch @@ -43,6 +43,255 @@ diff -up openssh-8.7p1/compat.h.sshrsacheck openssh-8.7p1/compat.h #define SSH_OLD_SESSIONID 0x00000010 /* #define unused 0x00000020 */ #define SSH_BUG_DEBUG 0x00000040 +diff -up openssh-8.7p1/monitor.c.sshrsacheck openssh-8.7p1/monitor.c +--- openssh-8.7p1/monitor.c.sshrsacheck 2023-01-20 13:07:54.279676981 +0100 ++++ openssh-8.7p1/monitor.c 2023-01-20 15:01:07.007821379 +0100 +@@ -660,11 +660,12 @@ mm_answer_sign(struct ssh *ssh, int sock + struct sshkey *key; + struct sshbuf *sigbuf = NULL; + u_char *p = NULL, *signature = NULL; +- char *alg = NULL; ++ char *alg = NULL, *effective_alg; + size_t datlen, siglen, alglen; + int r, is_proof = 0; + u_int keyid, compat; + const char proof_req[] = "hostkeys-prove-00@openssh.com"; ++ const char safe_rsa[] = "rsa-sha2-256"; + + debug3_f("entering"); + +@@ -719,18 +720,30 @@ mm_answer_sign(struct ssh *ssh, int sock + } + + if ((key = get_hostkey_by_index(keyid)) != NULL) { +- if ((r = sshkey_sign(key, &signature, &siglen, p, datlen, alg, ++ if (ssh->compat & SSH_RH_RSASIGSHA && strcmp(alg, "ssh-rsa") == 0 ++ && (sshkey_type_plain(key->type) == KEY_RSA)) { ++ effective_alg = safe_rsa; ++ } else { ++ effective_alg = alg; ++ } ++ if ((r = sshkey_sign(key, &signature, &siglen, p, datlen, effective_alg, + options.sk_provider, NULL, compat)) != 0) + fatal_fr(r, "sign"); + } else if ((key = get_hostkey_public_by_index(keyid, ssh)) != NULL && + auth_sock > 0) { ++ if (ssh->compat & SSH_RH_RSASIGSHA && strcmp(alg, "ssh-rsa") == 0 ++ && (sshkey_type_plain(key->type) == KEY_RSA)) { ++ effective_alg = safe_rsa; ++ } else { ++ effective_alg = alg; ++ } + if ((r = ssh_agent_sign(auth_sock, key, &signature, &siglen, +- p, datlen, alg, compat)) != 0) ++ p, datlen, effective_alg, compat)) != 0) + fatal_fr(r, "agent sign"); + } else + fatal_f("no hostkey from index %d", keyid); + +- debug3_f("%s %s signature len=%zu", alg, ++ debug3_f("%s (effective: %s) %s signature len=%zu", alg, effective_alg, + is_proof ? "hostkey proof" : "KEX", siglen); + + sshbuf_reset(m); +diff -up openssh-8.7p1/regress/cert-userkey.sh.sshrsacheck openssh-8.7p1/regress/cert-userkey.sh +--- openssh-8.7p1/regress/cert-userkey.sh.sshrsacheck 2023-01-25 14:26:52.885963113 +0100 ++++ openssh-8.7p1/regress/cert-userkey.sh 2023-01-25 14:27:25.757219800 +0100 +@@ -7,7 +7,8 @@ rm -f $OBJ/authorized_keys_$USER $OBJ/us + cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak + cp $OBJ/ssh_proxy $OBJ/ssh_proxy_bak + +-PLAIN_TYPES=`$SSH -Q key-plain | maybe_filter_sk | sed 's/^ssh-dss/ssh-dsa/;s/^ssh-//'` ++#ssh-dss keys are incompatible with DEFAULT crypto policy ++PLAIN_TYPES=`$SSH -Q key-plain | maybe_filter_sk | grep -v 'ssh-dss' | sed 's/^ssh-dss/ssh-dsa/;s/^ssh-//'` + EXTRA_TYPES="" + rsa="" + +diff -up openssh-8.7p1/regress/Makefile.sshrsacheck openssh-8.7p1/regress/Makefile +--- openssh-8.7p1/regress/Makefile.sshrsacheck 2023-01-20 13:07:54.169676051 +0100 ++++ openssh-8.7p1/regress/Makefile 2023-01-20 13:07:54.290677074 +0100 +@@ -2,7 +2,8 @@ + + tests: prep file-tests t-exec unit + +-REGRESS_TARGETS= t1 t2 t3 t4 t5 t6 t7 t8 t9 t10 t11 t12 ++#ssh-dss tests will not pass on DEFAULT crypto-policy because of SHA1, skipping ++REGRESS_TARGETS= t1 t2 t3 t4 t5 t7 t8 t9 t10 t11 t12 + + # File based tests + file-tests: $(REGRESS_TARGETS) +diff -up openssh-8.7p1/regress/test-exec.sh.sshrsacheck openssh-8.7p1/regress/test-exec.sh +--- openssh-8.7p1/regress/test-exec.sh.sshrsacheck 2023-01-25 14:24:54.778040819 +0100 ++++ openssh-8.7p1/regress/test-exec.sh 2023-01-25 14:26:39.500858590 +0100 +@@ -581,8 +581,9 @@ maybe_filter_sk() { + fi + } + +-SSH_KEYTYPES=`$SSH -Q key-plain | maybe_filter_sk` +-SSH_HOSTKEY_TYPES=`$SSH -Q key-plain | maybe_filter_sk` ++#ssh-dss keys are incompatible with DEFAULT crypto policy ++SSH_KEYTYPES=`$SSH -Q key-plain | maybe_filter_sk | grep -v 'ssh-dss'` ++SSH_HOSTKEY_TYPES=`$SSH -Q key-plain | maybe_filter_sk | grep -v 'ssh-dss'` + + for t in ${SSH_KEYTYPES}; do + # generate user key +diff -up openssh-8.7p1/regress/unittests/kex/test_kex.c.sshrsacheck openssh-8.7p1/regress/unittests/kex/test_kex.c +--- openssh-8.7p1/regress/unittests/kex/test_kex.c.sshrsacheck 2023-01-26 13:34:52.645743677 +0100 ++++ openssh-8.7p1/regress/unittests/kex/test_kex.c 2023-01-26 13:36:56.220745823 +0100 +@@ -97,7 +97,8 @@ do_kex_with_key(char *kex, int keytype, + memcpy(kex_params.proposal, myproposal, sizeof(myproposal)); + if (kex != NULL) + kex_params.proposal[PROPOSAL_KEX_ALGS] = kex; +- keyname = strdup(sshkey_ssh_name(private)); ++ keyname = (strcmp(sshkey_ssh_name(private), "ssh-rsa")) ? ++ strdup(sshkey_ssh_name(private)) : strdup("rsa-sha2-256"); + ASSERT_PTR_NE(keyname, NULL); + kex_params.proposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = keyname; + ASSERT_INT_EQ(ssh_init(&client, 0, &kex_params), 0); +@@ -180,7 +181,7 @@ do_kex(char *kex) + { + #ifdef WITH_OPENSSL + do_kex_with_key(kex, KEY_RSA, 2048); +- do_kex_with_key(kex, KEY_DSA, 1024); ++ /* do_kex_with_key(kex, KEY_DSA, 1024); */ + #ifdef OPENSSL_HAS_ECC + do_kex_with_key(kex, KEY_ECDSA, 256); + #endif /* OPENSSL_HAS_ECC */ +diff -up openssh-8.7p1/regress/unittests/sshkey/test_file.c.sshrsacheck openssh-8.7p1/regress/unittests/sshkey/test_file.c +--- openssh-8.7p1/regress/unittests/sshkey/test_file.c.sshrsacheck 2023-01-26 12:04:55.946343408 +0100 ++++ openssh-8.7p1/regress/unittests/sshkey/test_file.c 2023-01-26 12:06:35.235164432 +0100 +@@ -110,6 +110,7 @@ sshkey_file_tests(void) + sshkey_free(k2); + TEST_DONE(); + ++ /* Skip this test, SHA1 signatures are not supported + TEST_START("load RSA cert with SHA1 signature"); + ASSERT_INT_EQ(sshkey_load_cert(test_data_file("rsa_1_sha1"), &k2), 0); + ASSERT_PTR_NE(k2, NULL); +@@ -117,7 +118,7 @@ sshkey_file_tests(void) + ASSERT_INT_EQ(sshkey_equal_public(k1, k2), 1); + ASSERT_STRING_EQ(k2->cert->signature_type, "ssh-rsa"); + sshkey_free(k2); +- TEST_DONE(); ++ TEST_DONE(); */ + + TEST_START("load RSA cert with SHA512 signature"); + ASSERT_INT_EQ(sshkey_load_cert(test_data_file("rsa_1_sha512"), &k2), 0); +diff -up openssh-8.7p1/regress/unittests/sshkey/test_fuzz.c.sshrsacheck openssh-8.7p1/regress/unittests/sshkey/test_fuzz.c +--- openssh-8.7p1/regress/unittests/sshkey/test_fuzz.c.sshrsacheck 2023-01-26 12:10:37.533168013 +0100 ++++ openssh-8.7p1/regress/unittests/sshkey/test_fuzz.c 2023-01-26 12:15:35.637631860 +0100 +@@ -333,13 +333,14 @@ sshkey_fuzz_tests(void) + TEST_DONE(); + + #ifdef WITH_OPENSSL ++ /* Skip this test, SHA1 signatures are not supported + TEST_START("fuzz RSA sig"); + buf = load_file("rsa_1"); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); + sshbuf_free(buf); + sig_fuzz(k1, "ssh-rsa"); + sshkey_free(k1); +- TEST_DONE(); ++ TEST_DONE();*/ + + TEST_START("fuzz RSA SHA256 sig"); + buf = load_file("rsa_1"); +@@ -357,6 +358,7 @@ sshkey_fuzz_tests(void) + sshkey_free(k1); + TEST_DONE(); + ++ /* Skip this test, SHA1 signatures are not supported + TEST_START("fuzz DSA sig"); + buf = load_file("dsa_1"); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); +@@ -364,6 +366,7 @@ sshkey_fuzz_tests(void) + sig_fuzz(k1, NULL); + sshkey_free(k1); + TEST_DONE(); ++ */ + + #ifdef OPENSSL_HAS_ECC + TEST_START("fuzz ECDSA sig"); +diff -up openssh-8.7p1/regress/unittests/sshkey/test_sshkey.c.sshrsacheck openssh-8.7p1/regress/unittests/sshkey/test_sshkey.c +--- openssh-8.7p1/regress/unittests/sshkey/test_sshkey.c.sshrsacheck 2023-01-26 11:02:52.339413463 +0100 ++++ openssh-8.7p1/regress/unittests/sshkey/test_sshkey.c 2023-01-26 11:58:42.324253896 +0100 +@@ -60,6 +60,9 @@ build_cert(struct sshbuf *b, struct sshk + u_char *sigblob; + size_t siglen; + ++ /* ssh-rsa implies SHA1, forbidden in DEFAULT cp */ ++ int expected = (sig_alg == NULL || strcmp(sig_alg, "ssh-rsa") == 0) ? SSH_ERR_LIBCRYPTO_ERROR : 0; ++ + ca_buf = sshbuf_new(); + ASSERT_PTR_NE(ca_buf, NULL); + ASSERT_INT_EQ(sshkey_putb(ca_key, ca_buf), 0); +@@ -101,8 +104,9 @@ build_cert(struct sshbuf *b, struct sshk + ASSERT_INT_EQ(sshbuf_put_string(b, NULL, 0), 0); /* reserved */ + ASSERT_INT_EQ(sshbuf_put_stringb(b, ca_buf), 0); /* signature key */ + ASSERT_INT_EQ(sshkey_sign(sign_key, &sigblob, &siglen, +- sshbuf_ptr(b), sshbuf_len(b), sig_alg, NULL, NULL, 0), 0); +- ASSERT_INT_EQ(sshbuf_put_string(b, sigblob, siglen), 0); /* signature */ ++ sshbuf_ptr(b), sshbuf_len(b), sig_alg, NULL, NULL, 0), expected); ++ if (expected == 0) ++ ASSERT_INT_EQ(sshbuf_put_string(b, sigblob, siglen), 0); /* signature */ + + free(sigblob); + sshbuf_free(ca_buf); +@@ -119,16 +123,22 @@ signature_test(struct sshkey *k, struct + { + size_t len; + u_char *sig; ++ /* ssh-rsa implies SHA1, forbidden in DEFAULT cp */ ++ int expected = (sig_alg && strcmp(sig_alg, "ssh-rsa") == 0) ? SSH_ERR_LIBCRYPTO_ERROR : 0; ++ if (k && (sshkey_type_plain(k->type) == KEY_DSA || sshkey_type_plain(k->type) == KEY_DSA_CERT)) ++ expected = SSH_ERR_LIBCRYPTO_ERROR; + + ASSERT_INT_EQ(sshkey_sign(k, &sig, &len, d, l, sig_alg, +- NULL, NULL, 0), 0); +- ASSERT_SIZE_T_GT(len, 8); +- ASSERT_PTR_NE(sig, NULL); +- ASSERT_INT_EQ(sshkey_verify(k, sig, len, d, l, NULL, 0, NULL), 0); +- ASSERT_INT_NE(sshkey_verify(bad, sig, len, d, l, NULL, 0, NULL), 0); +- /* Fuzz test is more comprehensive, this is just a smoke test */ +- sig[len - 5] ^= 0x10; +- ASSERT_INT_NE(sshkey_verify(k, sig, len, d, l, NULL, 0, NULL), 0); ++ NULL, NULL, 0), expected); ++ if (expected == 0) { ++ ASSERT_SIZE_T_GT(len, 8); ++ ASSERT_PTR_NE(sig, NULL); ++ ASSERT_INT_EQ(sshkey_verify(k, sig, len, d, l, NULL, 0, NULL), 0); ++ ASSERT_INT_NE(sshkey_verify(bad, sig, len, d, l, NULL, 0, NULL), 0); ++ /* Fuzz test is more comprehensive, this is just a smoke test */ ++ sig[len - 5] ^= 0x10; ++ ASSERT_INT_NE(sshkey_verify(k, sig, len, d, l, NULL, 0, NULL), 0); ++ } + free(sig); + } + +@@ -514,7 +524,7 @@ sshkey_tests(void) + ASSERT_INT_EQ(sshkey_load_public(test_data_file("rsa_1.pub"), &k2, + NULL), 0); + k3 = get_private("rsa_1"); +- build_cert(b, k2, "ssh-rsa-cert-v01@openssh.com", k3, k1, NULL); ++ build_cert(b, k2, "ssh-rsa-cert-v01@openssh.com", k3, k1, "rsa-sha2-256"); + ASSERT_INT_EQ(sshkey_from_blob(sshbuf_ptr(b), sshbuf_len(b), &k4), + SSH_ERR_KEY_CERT_INVALID_SIGN_KEY); + ASSERT_PTR_EQ(k4, NULL); +diff -up openssh-8.7p1/regress/unittests/sshsig/tests.c.sshrsacheck openssh-8.7p1/regress/unittests/sshsig/tests.c +--- openssh-8.7p1/regress/unittests/sshsig/tests.c.sshrsacheck 2023-01-26 12:19:23.659513651 +0100 ++++ openssh-8.7p1/regress/unittests/sshsig/tests.c 2023-01-26 12:20:28.021044803 +0100 +@@ -102,9 +102,11 @@ tests(void) + check_sig("rsa.pub", "rsa.sig", msg, namespace); + TEST_DONE(); + ++ /* Skip this test, SHA1 signatures are not supported + TEST_START("check DSA signature"); + check_sig("dsa.pub", "dsa.sig", msg, namespace); + TEST_DONE(); ++ */ + + #ifdef OPENSSL_HAS_ECC + TEST_START("check ECDSA signature"); diff -up openssh-8.7p1/serverloop.c.sshrsacheck openssh-8.7p1/serverloop.c --- openssh-8.7p1/serverloop.c.sshrsacheck 2023-01-12 14:57:08.118400073 +0100 +++ openssh-8.7p1/serverloop.c 2023-01-12 14:59:17.330470518 +0100 @@ -57,6 +306,24 @@ diff -up openssh-8.7p1/serverloop.c.sshrsacheck openssh-8.7p1/serverloop.c debug3_f("sign %s key (index %d) using sigalg %s", sshkey_type(key), ndx, sigalg == NULL ? "default" : sigalg); if ((r = sshbuf_put_cstring(sigbuf, +diff -up openssh-8.7p1/sshconnect2.c.sshrsacheck openssh-8.7p1/sshconnect2.c +--- openssh-8.7p1/sshconnect2.c.sshrsacheck 2023-01-25 15:33:29.140353651 +0100 ++++ openssh-8.7p1/sshconnect2.c 2023-01-25 15:59:34.225364883 +0100 +@@ -1461,6 +1464,14 @@ identity_sign(struct identity *id, u_cha + retried = 1; + goto retry_pin; + } ++ if ((r == SSH_ERR_LIBCRYPTO_ERROR) && strcmp("ssh-rsa", alg)) { ++ char rsa_safe_alg[] = "rsa-sha2-512"; ++ debug3_f("trying to fallback to algorithm %s", rsa_safe_alg); ++ ++ if ((r = sshkey_sign(sign_key, sigp, lenp, data, datalen, ++ rsa_safe_alg, options.sk_provider, pin, compat)) != 0) ++ debug_fr(r, "sshkey_sign - RSA fallback"); ++ } + goto out; + } + diff -up openssh-8.7p1/sshd.c.sshrsacheck openssh-8.7p1/sshd.c --- openssh-8.7p1/sshd.c.sshrsacheck 2023-01-12 13:29:06.355711140 +0100 +++ openssh-8.7p1/sshd.c 2023-01-12 13:29:06.358711178 +0100 @@ -68,7 +335,7 @@ diff -up openssh-8.7p1/sshd.c.sshrsacheck openssh-8.7p1/sshd.c #ifdef HAVE_SECUREWARE (void)set_auth_parameters(ac, av); -@@ -1938,6 +1950,19 @@ main(int ac, char **av) +@@ -1938,6 +1950,33 @@ main(int ac, char **av) key = NULL; continue; } @@ -78,12 +345,26 @@ diff -up openssh-8.7p1/sshd.c.sshrsacheck openssh-8.7p1/sshd.c + u_char data[] = "Test SHA1 vector"; + int res; + -+ res = ssh_rsa_sign(key, &tmp, &sign_size, data, sizeof(data), NULL); ++ res = sshkey_sign(key, &tmp, &sign_size, data, sizeof(data), NULL, NULL, NULL, 0); + free(tmp); + if (res == SSH_ERR_LIBCRYPTO_ERROR) { -+ logit_f("sshd: ssh-rsa algorithm is disabled"); ++ verbose_f("sshd: SHA1 in signatures is disabled for RSA keys"); + forbid_ssh_rsa = 1; + } ++ } ++ if (key && (sshkey_type_plain(key->type) == KEY_DSA || sshkey_type_plain(key->type) == KEY_DSA_CERT)) { ++ size_t sign_size = 0; ++ u_char *tmp = NULL; ++ u_char data[] = "Test SHA1 vector"; ++ int res; ++ ++ res = sshkey_sign(key, &tmp, &sign_size, data, sizeof(data), NULL, NULL, NULL, 0); ++ free(tmp); ++ if (res == SSH_ERR_LIBCRYPTO_ERROR) { ++ logit_f("sshd: ssh-dss is disabled, skipping key file %s", options.host_key_files[i]); ++ key = NULL; ++ continue; ++ } + } if (sshkey_is_sk(key) && key->sk_flags & SSH_SK_USER_PRESENCE_REQD) { @@ -98,3 +379,48 @@ diff -up openssh-8.7p1/sshd.c.sshrsacheck openssh-8.7p1/sshd.c /* Prepare the channels layer */ channel_init_channels(ssh); channel_set_af(ssh, options.address_family); +diff -Nur openssh-8.7p1/ssh-keygen.c openssh-8.7p1_patched/ssh-keygen.c +--- openssh-8.7p1/ssh-keygen.c 2023-01-18 17:41:47.894515779 +0100 ++++ openssh-8.7p1_patched/ssh-keygen.c 2023-01-18 17:41:44.500488818 +0100 +@@ -491,6 +491,8 @@ + BIGNUM *dsa_pub_key = NULL, *dsa_priv_key = NULL; + BIGNUM *rsa_n = NULL, *rsa_e = NULL, *rsa_d = NULL; + BIGNUM *rsa_p = NULL, *rsa_q = NULL, *rsa_iqmp = NULL; ++ char rsa_safe_alg[] = "rsa-sha2-256"; ++ char *alg = NULL; + + if ((r = sshbuf_get_u32(b, &magic)) != 0) + fatal_fr(r, "parse magic"); +@@ -590,6 +592,7 @@ do_convert_private_ssh2(struct sshbuf *b + if ((r = ssh_rsa_complete_crt_parameters(key, rsa_iqmp)) != 0) + fatal_fr(r, "generate RSA parameters"); + BN_clear_free(rsa_iqmp); ++ alg = rsa_safe_alg; + break; + } + rlen = sshbuf_len(b); +@@ -598,9 +601,9 @@ do_convert_private_ssh2(struct sshbuf *b + + /* try the key */ + if (sshkey_sign(key, &sig, &slen, data, sizeof(data), +- NULL, NULL, NULL, 0) != 0 || ++ alg, NULL, NULL, 0) != 0 || + sshkey_verify(key, sig, slen, data, sizeof(data), +- NULL, 0, NULL) != 0) { ++ alg, 0, NULL) != 0) { + sshkey_free(key); + free(sig); + return NULL; +diff -up openssh-8.7p1/ssh-rsa.c.sshrsacheck openssh-8.7p1/ssh-rsa.c +--- openssh-8.7p1/ssh-rsa.c.sshrsacheck 2023-01-20 13:07:54.180676144 +0100 ++++ openssh-8.7p1/ssh-rsa.c 2023-01-20 13:07:54.290677074 +0100 +@@ -254,7 +254,8 @@ ssh_rsa_verify(const struct sshkey *key, + ret = SSH_ERR_INVALID_ARGUMENT; + goto out; + } +- if (hash_alg != want_alg) { ++ if (hash_alg != want_alg && want_alg != SSH_DIGEST_SHA1) { ++ debug_f("Unexpected digest algorithm: got %d, wanted %d", hash_alg, want_alg); + ret = SSH_ERR_SIGNATURE_INVALID; + goto out; + } diff --git a/openssh-9.3p1-openssl-compat.patch b/openssh-9.3p1-openssl-compat.patch new file mode 100644 index 0000000..0efbdec --- /dev/null +++ b/openssh-9.3p1-openssl-compat.patch @@ -0,0 +1,52 @@ +--- openssh-9.3p1/openbsd-compat/openssl-compat.c 2023-03-15 22:28:19.000000000 +0100 ++++ /home/dbelyavs/work/upstream/openssh-portable/openbsd-compat/openssl-compat.c 2023-05-25 14:19:42.870841944 +0200 +@@ -33,10 +33,10 @@ + + /* + * OpenSSL version numbers: MNNFFPPS: major minor fix patch status +- * We match major, minor, fix and status (not patch) for <1.0.0. +- * After that, we acceptable compatible fix versions (so we +- * allow 1.0.1 to work with 1.0.0). Going backwards is only allowed +- * within a patch series. ++ * Versions >=3 require only major versions to match. ++ * For versions <3, we accept compatible fix versions (so we allow 1.0.1 ++ * to work with 1.0.0). Going backwards is only allowed within a patch series. ++ * See https://www.openssl.org/policies/releasestrat.html + */ + + int +@@ -48,15 +48,17 @@ + if (headerver == libver) + return 1; + +- /* for versions < 1.0.0, major,minor,fix,status must match */ +- if (headerver < 0x1000000f) { +- mask = 0xfffff00fL; /* major,minor,fix,status */ ++ /* ++ * For versions >= 3.0, only the major and status must match. ++ */ ++ if (headerver >= 0x3000000f) { ++ mask = 0xf000000fL; /* major,status */ + return (headerver & mask) == (libver & mask); + } + + /* +- * For versions >= 1.0.0, major,minor,status must match and library +- * fix version must be equal to or newer than the header. ++ * For versions >= 1.0.0, but <3, major,minor,status must match and ++ * library fix version must be equal to or newer than the header. + */ + mask = 0xfff0000fL; /* major,minor,status */ + hfix = (headerver & 0x000ff000) >> 12; +diff -up openssh-8.7p1/configure.ac.check openssh-8.7p1/configure.ac +--- openssh-8.7p1/configure.ac.check 2023-11-27 14:54:32.959113758 +0100 ++++ openssh-8.7p1/configure.ac 2023-11-27 14:54:49.467500523 +0100 +@@ -2821,7 +2821,7 @@ if test "x$openssl" = "xyes" ; then + ;; + 101*) ;; # 1.1.x + 200*) ;; # LibreSSL +- 300*) ;; # OpenSSL development branch. ++ 30*) ;; # OpenSSL 3.x series + *) + AC_MSG_ERROR([Unknown/unsupported OpenSSL version ("$ssl_library_ver")]) + ;; diff --git a/openssh-9.4p2-limit-delay.patch b/openssh-9.4p2-limit-delay.patch new file mode 100644 index 0000000..8c1cbcb --- /dev/null +++ b/openssh-9.4p2-limit-delay.patch @@ -0,0 +1,33 @@ +diff -u -p -r1.166 auth2.c +--- a/auth2.c 8 Mar 2023 04:43:12 -0000 1.166 ++++ b/auth2.c 28 Aug 2023 08:32:44 -0000 +@@ -208,6 +208,7 @@ input_service_request(int type, u_int32_ + } + + #define MIN_FAIL_DELAY_SECONDS 0.005 ++#define MAX_FAIL_DELAY_SECONDS 5.0 + static double + user_specific_delay(const char *user) + { +@@ -233,6 +234,12 @@ ensure_minimum_time_since(double start, + struct timespec ts; + double elapsed = monotime_double() - start, req = seconds, remain; + ++ if (elapsed > MAX_FAIL_DELAY_SECONDS) { ++ debug3_f("elapsed %0.3lfms exceeded the max delay " ++ "requested %0.3lfms)", elapsed*1000, req*1000); ++ return; ++ } ++ + /* if we've already passed the requested time, scale up */ + while ((remain = seconds - elapsed) < 0.0) + seconds *= 2; +@@ -317,7 +324,7 @@ input_userauth_request(int type, u_int32 + debug2("input_userauth_request: try method %s", method); + authenticated = m->userauth(ssh); + } +- if (!authctxt->authenticated) ++ if (!authctxt->authenticated && strcmp(method, "none") != 0) + ensure_minimum_time_since(tstart, + user_specific_delay(authctxt->user)); + userauth_finish(ssh, authenticated, method, NULL); diff --git a/openssh-9.6p1-CVE-2023-48795.patch b/openssh-9.6p1-CVE-2023-48795.patch new file mode 100644 index 0000000..7f710db --- /dev/null +++ b/openssh-9.6p1-CVE-2023-48795.patch @@ -0,0 +1,447 @@ +diff --git a/PROTOCOL b/PROTOCOL +index d453c779..ded935eb 100644 +--- a/PROTOCOL ++++ b/PROTOCOL +@@ -137,6 +137,32 @@ than as a named global or channel request to allow pings with very + described at: + http://git.libssh.org/users/aris/libssh.git/plain/doc/curve25519-sha256@libssh.org.txt?h=curve25519 + ++1.9 transport: strict key exchange extension ++ ++OpenSSH supports a number of transport-layer hardening measures under ++a "strict KEX" feature. This feature is signalled similarly to the ++RFC8308 ext-info feature: by including a additional algorithm in the ++initiial SSH2_MSG_KEXINIT kex_algorithms field. The client may append ++"kex-strict-c-v00@openssh.com" to its kex_algorithms and the server ++may append "kex-strict-s-v00@openssh.com". These pseudo-algorithms ++are only valid in the initial SSH2_MSG_KEXINIT and MUST be ignored ++if they are present in subsequent SSH2_MSG_KEXINIT packets. ++ ++When an endpoint that supports this extension observes this algorithm ++name in a peer's KEXINIT packet, it MUST make the following changes to ++the the protocol: ++ ++a) During initial KEX, terminate the connection if any unexpected or ++ out-of-sequence packet is received. This includes terminating the ++ connection if the first packet received is not SSH2_MSG_KEXINIT. ++ Unexpected packets for the purpose of strict KEX include messages ++ that are otherwise valid at any time during the connection such as ++ SSH2_MSG_DEBUG and SSH2_MSG_IGNORE. ++b) After sending or receiving a SSH2_MSG_NEWKEYS message, reset the ++ packet sequence number to zero. This behaviour persists for the ++ duration of the connection (i.e. not just the first ++ SSH2_MSG_NEWKEYS). ++ + 2. Connection protocol changes + + 2.1. connection: Channel write close extension "eow@openssh.com" +diff --git a/kex.c b/kex.c +index aa5e792d..d478ff6e 100644 +--- a/kex.c ++++ b/kex.c +@@ -65,7 +65,7 @@ + #endif + + /* prototype */ +-static int kex_choose_conf(struct ssh *); ++static int kex_choose_conf(struct ssh *, uint32_t seq); + static int kex_input_newkeys(int, u_int32_t, struct ssh *); + + static const char *proposal_names[PROPOSAL_MAX] = { +@@ -177,6 +177,18 @@ kex_names_valid(const char *names) + return 1; + } + ++/* returns non-zero if proposal contains any algorithm from algs */ ++static int ++has_any_alg(const char *proposal, const char *algs) ++{ ++ char *cp; ++ ++ if ((cp = match_list(proposal, algs, NULL)) == NULL) ++ return 0; ++ free(cp); ++ return 1; ++} ++ + /* + * Concatenate algorithm names, avoiding duplicates in the process. + * Caller must free returned string. +@@ -184,7 +196,7 @@ kex_names_valid(const char *names) + char * + kex_names_cat(const char *a, const char *b) + { +- char *ret = NULL, *tmp = NULL, *cp, *p, *m; ++ char *ret = NULL, *tmp = NULL, *cp, *p; + size_t len; + + if (a == NULL || *a == '\0') +@@ -201,10 +213,8 @@ kex_names_cat(const char *a, const char *b) + } + strlcpy(ret, a, len); + for ((p = strsep(&cp, ",")); p && *p != '\0'; (p = strsep(&cp, ","))) { +- if ((m = match_list(ret, p, NULL)) != NULL) { +- free(m); ++ if (has_any_alg(ret, p)) + continue; /* Algorithm already present */ +- } + if (strlcat(ret, ",", len) >= len || + strlcat(ret, p, len) >= len) { + free(tmp); +@@ -466,7 +485,12 @@ kex_protocol_error(int type, u_int32_t seq, struct ssh *ssh) + { + int r; + +- error("kex protocol error: type %d seq %u", type, seq); ++ /* If in strict mode, any unexpected message is an error */ ++ if ((ssh->kex->flags & KEX_INITIAL) && ssh->kex->kex_strict) { ++ ssh_packet_disconnect(ssh, "strict KEX violation: " ++ "unexpected packet type %u (seqnr %u)", type, seq); ++ } ++ error_f("type %u seq %u", type, seq); + if ((r = sshpkt_start(ssh, SSH2_MSG_UNIMPLEMENTED)) != 0 || + (r = sshpkt_put_u32(ssh, seq)) != 0 || + (r = sshpkt_send(ssh)) != 0) +@@ -548,6 +572,11 @@ kex_input_ext_info(int type, u_int32_t seq, struct ssh *ssh) + ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, &kex_protocol_error); + if ((r = sshpkt_get_u32(ssh, &ninfo)) != 0) + return r; ++ if (ninfo >= 1024) { ++ error("SSH2_MSG_EXT_INFO with too many entries, expected " ++ "<=1024, received %u", ninfo); ++ return dispatch_protocol_error(type, seq, ssh); ++ } + for (i = 0; i < ninfo; i++) { + if ((r = sshpkt_get_cstring(ssh, &name, NULL)) != 0) + return r; +@@ -681,7 +705,7 @@ kex_input_kexinit(int type, u_int32_t seq, struct ssh *ssh) + error_f("no kex"); + return SSH_ERR_INTERNAL_ERROR; + } +- ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, NULL); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_protocol_error); + ptr = sshpkt_ptr(ssh, &dlen); + if ((r = sshbuf_put(kex->peer, ptr, dlen)) != 0) + return r; +@@ -717,7 +741,7 @@ kex_input_kexinit(int type, u_int32_t seq, struct ssh *ssh) + if (!(kex->flags & KEX_INIT_SENT)) + if ((r = kex_send_kexinit(ssh)) != 0) + return r; +- if ((r = kex_choose_conf(ssh)) != 0) ++ if ((r = kex_choose_conf(ssh, seq)) != 0) + return r; + + if (kex->kex_type < KEX_MAX && kex->kex[kex->kex_type] != NULL) +@@ -981,20 +1005,14 @@ proposals_match(char *my[PROPOSAL_MAX], char *peer[PROPOSAL_MAX]) + return (1); + } + +-/* returns non-zero if proposal contains any algorithm from algs */ + static int +-has_any_alg(const char *proposal, const char *algs) ++kexalgs_contains(char **peer, const char *ext) + { +- char *cp; +- +- if ((cp = match_list(proposal, algs, NULL)) == NULL) +- return 0; +- free(cp); +- return 1; ++ return has_any_alg(peer[PROPOSAL_KEX_ALGS], ext); + } + + static int +-kex_choose_conf(struct ssh *ssh) ++kex_choose_conf(struct ssh *ssh, uint32_t seq) + { + struct kex *kex = ssh->kex; + struct newkeys *newkeys; +@@ -1019,13 +1037,23 @@ kex_choose_conf(struct ssh *ssh) + sprop=peer; + } + +- /* Check whether client supports ext_info_c */ +- if (kex->server && (kex->flags & KEX_INITIAL)) { +- char *ext; +- +- ext = match_list("ext-info-c", peer[PROPOSAL_KEX_ALGS], NULL); +- kex->ext_info_c = (ext != NULL); +- free(ext); ++ /* Check whether peer supports ext_info/kex_strict */ ++ if ((kex->flags & KEX_INITIAL) != 0) { ++ if (kex->server) { ++ kex->ext_info_c = kexalgs_contains(peer, "ext-info-c"); ++ kex->kex_strict = kexalgs_contains(peer, ++ "kex-strict-c-v00@openssh.com"); ++ } else { ++ kex->kex_strict = kexalgs_contains(peer, ++ "kex-strict-s-v00@openssh.com"); ++ } ++ if (kex->kex_strict) { ++ debug3_f("will use strict KEX ordering"); ++ if (seq != 0) ++ ssh_packet_disconnect(ssh, ++ "strict KEX violation: " ++ "KEXINIT was not the first packet"); ++ } + } + + /* Check whether client supports rsa-sha2 algorithms */ +diff --git a/kex.h b/kex.h +index 5f7ef784..272ebb43 100644 +--- a/kex.h ++++ b/kex.h +@@ -149,6 +149,7 @@ struct kex { + u_int kex_type; + char *server_sig_algs; + int ext_info_c; ++ int kex_strict; + struct sshbuf *my; + struct sshbuf *peer; + struct sshbuf *client_version; +diff --git a/packet.c b/packet.c +index 52017def..beb214f9 100644 +--- a/packet.c ++++ b/packet.c +@@ -1207,8 +1207,13 @@ ssh_packet_send2_wrapped(struct ssh *ssh) + sshbuf_dump(state->output, stderr); + #endif + /* increment sequence number for outgoing packets */ +- if (++state->p_send.seqnr == 0) ++ if (++state->p_send.seqnr == 0) { ++ if ((ssh->kex->flags & KEX_INITIAL) != 0) { ++ ssh_packet_disconnect(ssh, "outgoing sequence number " ++ "wrapped during initial key exchange"); ++ } + logit("outgoing seqnr wraps around"); ++ } + if (++state->p_send.packets == 0) + if (!(ssh->compat & SSH_BUG_NOREKEY)) + return SSH_ERR_NEED_REKEY; +@@ -1216,6 +1221,11 @@ ssh_packet_send2_wrapped(struct ssh *ssh) + state->p_send.bytes += len; + sshbuf_reset(state->outgoing_packet); + ++ if (type == SSH2_MSG_NEWKEYS && ssh->kex->kex_strict) { ++ debug_f("resetting send seqnr %u", state->p_send.seqnr); ++ state->p_send.seqnr = 0; ++ } ++ + if (type == SSH2_MSG_NEWKEYS) + r = ssh_set_newkeys(ssh, MODE_OUT); + else if (type == SSH2_MSG_USERAUTH_SUCCESS && state->server_side) +@@ -1344,8 +1354,7 @@ ssh_packet_read_seqnr(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p) + /* Stay in the loop until we have received a complete packet. */ + for (;;) { + /* Try to read a packet from the buffer. */ +- r = ssh_packet_read_poll_seqnr(ssh, typep, seqnr_p); +- if (r != 0) ++ if ((r = ssh_packet_read_poll_seqnr(ssh, typep, seqnr_p)) != 0) + break; + /* If we got a packet, return it. */ + if (*typep != SSH_MSG_NONE) +@@ -1629,10 +1615,16 @@ ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p) + if ((r = sshbuf_consume(state->input, mac->mac_len)) != 0) + goto out; + } ++ + if (seqnr_p != NULL) + *seqnr_p = state->p_read.seqnr; +- if (++state->p_read.seqnr == 0) ++ if (++state->p_read.seqnr == 0) { ++ if ((ssh->kex->flags & KEX_INITIAL) != 0) { ++ ssh_packet_disconnect(ssh, "incoming sequence number " ++ "wrapped during initial key exchange"); ++ } + logit("incoming seqnr wraps around"); ++ } + if (++state->p_read.packets == 0) + if (!(ssh->compat & SSH_BUG_NOREKEY)) + return SSH_ERR_NEED_REKEY; +@@ -1698,6 +1690,10 @@ ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p) + #endif + /* reset for next packet */ + state->packlen = 0; ++ if (*typep == SSH2_MSG_NEWKEYS && ssh->kex->kex_strict) { ++ debug_f("resetting read seqnr %u", state->p_read.seqnr); ++ state->p_read.seqnr = 0; ++ } + + if ((r = ssh_packet_check_rekey(ssh)) != 0) + return r; +@@ -1720,10 +1716,39 @@ ssh_packet_read_poll_seqnr(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p) + r = ssh_packet_read_poll2(ssh, typep, seqnr_p); + if (r != 0) + return r; +- if (*typep) { +- state->keep_alive_timeouts = 0; +- DBG(debug("received packet type %d", *typep)); ++ if (*typep == 0) { ++ /* no message ready */ ++ return 0; + } ++ state->keep_alive_timeouts = 0; ++ DBG(debug("received packet type %d", *typep)); ++ ++ /* Always process disconnect messages */ ++ if (*typep == SSH2_MSG_DISCONNECT) { ++ if ((r = sshpkt_get_u32(ssh, &reason)) != 0 || ++ (r = sshpkt_get_string(ssh, &msg, NULL)) != 0) ++ return r; ++ /* Ignore normal client exit notifications */ ++ do_log2(ssh->state->server_side && ++ reason == SSH2_DISCONNECT_BY_APPLICATION ? ++ SYSLOG_LEVEL_INFO : SYSLOG_LEVEL_ERROR, ++ "Received disconnect from %s port %d:" ++ "%u: %.400s", ssh_remote_ipaddr(ssh), ++ ssh_remote_port(ssh), reason, msg); ++ free(msg); ++ return SSH_ERR_DISCONNECTED; ++ } ++ ++ /* ++ * Do not implicitly handle any messages here during initial ++ * KEX when in strict mode. They will be need to be allowed ++ * explicitly by the KEX dispatch table or they will generate ++ * protocol errors. ++ */ ++ if (ssh->kex != NULL && ++ (ssh->kex->flags & KEX_INITIAL) && ssh->kex->kex_strict) ++ return 0; ++ /* Implicitly handle transport-level messages */ + switch (*typep) { + case SSH2_MSG_IGNORE: + debug3("Received SSH2_MSG_IGNORE"); +@@ -1738,19 +1763,6 @@ ssh_packet_read_poll_seqnr(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p) + debug("Remote: %.900s", msg); + free(msg); + break; +- case SSH2_MSG_DISCONNECT: +- if ((r = sshpkt_get_u32(ssh, &reason)) != 0 || +- (r = sshpkt_get_string(ssh, &msg, NULL)) != 0) +- return r; +- /* Ignore normal client exit notifications */ +- do_log2(ssh->state->server_side && +- reason == SSH2_DISCONNECT_BY_APPLICATION ? +- SYSLOG_LEVEL_INFO : SYSLOG_LEVEL_ERROR, +- "Received disconnect from %s port %d:" +- "%u: %.400s", ssh_remote_ipaddr(ssh), +- ssh_remote_port(ssh), reason, msg); +- free(msg); +- return SSH_ERR_DISCONNECTED; + case SSH2_MSG_UNIMPLEMENTED: + if ((r = sshpkt_get_u32(ssh, &seqnr)) != 0) + return r; +@@ -2242,6 +2254,7 @@ kex_to_blob(struct sshbuf *m, struct kex *kex) + (r = sshbuf_put_u32(m, kex->hostkey_type)) != 0 || + (r = sshbuf_put_u32(m, kex->hostkey_nid)) != 0 || + (r = sshbuf_put_u32(m, kex->kex_type)) != 0 || ++ (r = sshbuf_put_u32(m, kex->kex_strict)) != 0 || + (r = sshbuf_put_stringb(m, kex->my)) != 0 || + (r = sshbuf_put_stringb(m, kex->peer)) != 0 || + (r = sshbuf_put_stringb(m, kex->client_version)) != 0 || +@@ -2404,6 +2417,7 @@ kex_from_blob(struct sshbuf *m, struct kex **kexp) + (r = sshbuf_get_u32(m, (u_int *)&kex->hostkey_type)) != 0 || + (r = sshbuf_get_u32(m, (u_int *)&kex->hostkey_nid)) != 0 || + (r = sshbuf_get_u32(m, &kex->kex_type)) != 0 || ++ (r = sshbuf_get_u32(m, &kex->kex_strict)) != 0 || + (r = sshbuf_get_stringb(m, kex->my)) != 0 || + (r = sshbuf_get_stringb(m, kex->peer)) != 0 || + (r = sshbuf_get_stringb(m, kex->client_version)) != 0 || +@@ -2732,6 +2746,7 @@ sshpkt_disconnect(struct ssh *ssh, const char *fmt,...) + vsnprintf(buf, sizeof(buf), fmt, args); + va_end(args); + ++ debug2_f("sending SSH2_MSG_DISCONNECT: %s", buf); + if ((r = sshpkt_start(ssh, SSH2_MSG_DISCONNECT)) != 0 || + (r = sshpkt_put_u32(ssh, SSH2_DISCONNECT_PROTOCOL_ERROR)) != 0 || + (r = sshpkt_put_cstring(ssh, buf)) != 0 || +diff --git a/sshconnect2.c b/sshconnect2.c +index df6caf81..0cccbcc4 100644 +--- a/sshconnect2.c ++++ b/sshconnect2.c +@@ -253,7 +253,8 @@ ssh_kex2(struct ssh *ssh, char *host, st + fatal_fr(r, "kex_assemble_namelist"); + free(all_key); + +- if ((s = kex_names_cat(options.kex_algorithms, "ext-info-c")) == NULL) ++ if ((s = kex_names_cat(options.kex_algorithms, ++ "ext-info-c,kex-strict-c-v00@openssh.com")) == NULL) + fatal_f("kex_names_cat"); + myproposal[PROPOSAL_KEX_ALGS] = prop_kex = compat_kex_proposal(ssh, s); + myproposal[PROPOSAL_ENC_ALGS_CTOS] = +@@ -358,7 +358,6 @@ struct cauthmethod { + }; + + static int input_userauth_service_accept(int, u_int32_t, struct ssh *); +-static int input_userauth_ext_info(int, u_int32_t, struct ssh *); + static int input_userauth_success(int, u_int32_t, struct ssh *); + static int input_userauth_failure(int, u_int32_t, struct ssh *); + static int input_userauth_banner(int, u_int32_t, struct ssh *); +@@ -472,7 +471,7 @@ ssh_userauth2(struct ssh *ssh, const char *local_user, + + ssh->authctxt = &authctxt; + ssh_dispatch_init(ssh, &input_userauth_error); +- ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, &input_userauth_ext_info); ++ ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, kex_input_ext_info); + ssh_dispatch_set(ssh, SSH2_MSG_SERVICE_ACCEPT, &input_userauth_service_accept); + ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &authctxt.success); /* loop until success */ + pubkey_cleanup(ssh); +@@ -531,12 +530,6 @@ input_userauth_service_accept(int type, u_int32_t seq, struct ssh *ssh) + } + + /* ARGSUSED */ +-static int +-input_userauth_ext_info(int type, u_int32_t seqnr, struct ssh *ssh) +-{ +- return kex_input_ext_info(type, seqnr, ssh); +-} +- + void + userauth(struct ssh *ssh, char *authlist) + { +@@ -615,6 +608,7 @@ input_userauth_success(int type, u_int32_t seq, struct ssh *ssh) + free(authctxt->methoddata); + authctxt->methoddata = NULL; + authctxt->success = 1; /* break out */ ++ ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, dispatch_protocol_error); + return 0; + } + +diff -up openssh-8.7p1/sshd.c.kexstrict openssh-8.7p1/sshd.c +--- openssh-8.7p1/sshd.c.kexstrict 2023-11-27 13:19:18.855433602 +0100 ++++ openssh-8.7p1/sshd.c 2023-11-27 13:28:10.441325314 +0100 +@@ -2531,10 +2531,14 @@ do_ssh2_kex(struct ssh *ssh) + struct kex *kex; + char *hostkey_types = NULL; + char *prop_kex = NULL, *prop_enc = NULL, *prop_hostkey = NULL; ++ char *cp; + int r; + +- myproposal[PROPOSAL_KEX_ALGS] = prop_kex = compat_kex_proposal(ssh, +- options.kex_algorithms); ++ if ((cp = kex_names_cat(options.kex_algorithms, ++ "kex-strict-s-v00@openssh.com")) == NULL) ++ fatal_f("kex_names_cat"); ++ ++ myproposal[PROPOSAL_KEX_ALGS] = prop_kex = compat_kex_proposal(ssh, cp); + myproposal[PROPOSAL_ENC_ALGS_CTOS] = + myproposal[PROPOSAL_ENC_ALGS_STOC] = prop_enc = + compat_cipher_proposal(ssh, options.ciphers); +@@ -2586,7 +2586,7 @@ do_ssh2_kex(struct ssh *ssh) + if (gss && orig) + xasprintf(&newstr, "%s,%s", gss, orig); + else if (gss) +- newstr = gss; ++ xasprintf(&newstr, "%s,%s", gss, "kex-strict-s-v00@openssh.com"); + else if (orig) + newstr = orig; + +@@ -2650,6 +2654,7 @@ do_ssh2_kex(struct ssh *ssh) + #endif + free(prop_kex); + free(prop_enc); ++ free(cp); + free(prop_hostkey); + debug("KEX done"); + } diff --git a/openssh-9.6p1-CVE-2023-51385.patch b/openssh-9.6p1-CVE-2023-51385.patch new file mode 100644 index 0000000..3b83b5c --- /dev/null +++ b/openssh-9.6p1-CVE-2023-51385.patch @@ -0,0 +1,57 @@ +diff --git a/ssh.c b/ssh.c +index 35c48e62..48d93ddf 100644 +--- a/ssh.c ++++ b/ssh.c +@@ -626,6 +626,41 @@ ssh_conn_info_free(struct ssh_conn_info *cinfo) + free(cinfo); + } + ++static int ++valid_hostname(const char *s) ++{ ++ size_t i; ++ ++ if (*s == '-') ++ return 0; ++ for (i = 0; s[i] != 0; i++) { ++ if (strchr("'`\"$\\;&<>|(){}", s[i]) != NULL || ++ isspace((u_char)s[i]) || iscntrl((u_char)s[i])) ++ return 0; ++ } ++ return 1; ++} ++ ++static int ++valid_ruser(const char *s) ++{ ++ size_t i; ++ ++ if (*s == '-') ++ return 0; ++ for (i = 0; s[i] != 0; i++) { ++ if (strchr("'`\";&<>|(){}", s[i]) != NULL) ++ return 0; ++ /* Disallow '-' after whitespace */ ++ if (isspace((u_char)s[i]) && s[i + 1] == '-') ++ return 0; ++ /* Disallow \ in last position */ ++ if (s[i] == '\\' && s[i + 1] == '\0') ++ return 0; ++ } ++ return 1; ++} ++ + /* + * Main program for the ssh client. + */ +@@ -1118,6 +1153,10 @@ main(int ac, char **av) + if (!host) + usage(); + ++ if (!valid_hostname(host)) ++ fatal("hostname contains invalid characters"); ++ if (options.user != NULL && !valid_ruser(options.user)) ++ fatal("remote username contains invalid characters"); + host_arg = xstrdup(host); + + /* Initialize the command to execute on remote host. */ diff --git a/openssh-9.8p1-upstream-cve-2024-6387.patch b/openssh-9.8p1-upstream-cve-2024-6387.patch new file mode 100644 index 0000000..754d279 --- /dev/null +++ b/openssh-9.8p1-upstream-cve-2024-6387.patch @@ -0,0 +1,18 @@ +diff -up openssh-8.7p1/log.c.xxx openssh-8.7p1/log.c +--- openssh-8.7p1/log.c.xxx 2024-06-28 11:02:43.949912398 +0200 ++++ openssh-8.7p1/log.c 2024-06-28 11:02:58.652297885 +0200 +@@ -455,12 +455,14 @@ void + sshsigdie(const char *file, const char *func, int line, int showfunc, + LogLevel level, const char *suffix, const char *fmt, ...) + { ++#if 0 + va_list args; + + va_start(args, fmt); + sshlogv(file, func, line, showfunc, SYSLOG_LEVEL_FATAL, + suffix, fmt, args); + va_end(args); ++#endif + _exit(1); + } + From 75dbccac9b73ea1e816ca6a915203923950c14f4 Mon Sep 17 00:00:00 2001 From: Mattias Ellert Date: Fri, 12 Jul 2024 20:31:20 +0200 Subject: [PATCH 09/11] Add scp symlink in gsisshd's path --- gsi-openssh.spec | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/gsi-openssh.spec b/gsi-openssh.spec index fe6cc56..9d0e675 100644 --- a/gsi-openssh.spec +++ b/gsi-openssh.spec @@ -24,7 +24,7 @@ %global libedit 1 %global openssh_ver 8.7p1 -%global openssh_rel 10 +%global openssh_rel 11 Summary: An implementation of the SSH protocol with GSI authentication Name: gsi-openssh @@ -475,8 +475,8 @@ fi --sysconfdir=%{_sysconfdir}/gsissh \ --libexecdir=%{_libexecdir}/gsissh \ --datadir=%{_datadir}/gsissh \ - --with-default-path=/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin \ - --with-superuser-path=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin \ + --with-default-path=%{_libexecdir}/gsissh/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin \ + --with-superuser-path=%{_libexecdir}/gsissh/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin \ --with-privsep-path=%{_datadir}/empty.sshd \ --disable-strip \ --without-zlib-version-check \ @@ -542,12 +542,10 @@ rm $RPM_BUILD_ROOT%{_bindir}/ssh-agent rm $RPM_BUILD_ROOT%{_bindir}/ssh-keyscan rm $RPM_BUILD_ROOT%{_libexecdir}/gsissh/ssh-keycat rm $RPM_BUILD_ROOT%{_libexecdir}/gsissh/ssh-pkcs11-helper -rm $RPM_BUILD_ROOT%{_libexecdir}/gsissh/ssh-sk-helper rm $RPM_BUILD_ROOT%{_mandir}/man1/ssh-add.1* rm $RPM_BUILD_ROOT%{_mandir}/man1/ssh-agent.1* rm $RPM_BUILD_ROOT%{_mandir}/man1/ssh-keyscan.1* rm $RPM_BUILD_ROOT%{_mandir}/man8/ssh-pkcs11-helper.8* -rm $RPM_BUILD_ROOT%{_mandir}/man8/ssh-sk-helper.8* for f in $RPM_BUILD_ROOT%{_bindir}/* \ $RPM_BUILD_ROOT%{_sbindir}/* \ @@ -555,6 +553,11 @@ for f in $RPM_BUILD_ROOT%{_bindir}/* \ mv $f `dirname $f`/gsi`basename $f` done +# Add scp symlink in gsisshd's path +mkdir $RPM_BUILD_ROOT%{_libexecdir}/gsissh/bin +ln -nrs $RPM_BUILD_ROOT%{_bindir}/gsiscp \ + $RPM_BUILD_ROOT%{_libexecdir}/gsissh/bin/scp + perl -pi -e "s|$RPM_BUILD_ROOT||g" $RPM_BUILD_ROOT%{_mandir}/man*/* %pre @@ -580,7 +583,7 @@ perl -pi -e "s|$RPM_BUILD_ROOT||g" $RPM_BUILD_ROOT%{_mandir}/man*/* %attr(0755,root,root) %{_bindir}/gsissh-keygen %attr(0644,root,root) %{_mandir}/man1/gsissh-keygen.1* %attr(0755,root,root) %dir %{_libexecdir}/gsissh -%attr(2755,root,ssh_keys) %{_libexecdir}/gsissh/ssh-keysign +%attr(2555,root,ssh_keys) %{_libexecdir}/gsissh/ssh-keysign %attr(0644,root,root) %{_mandir}/man8/gsissh-keysign.8* %attr(0644,root,root) %{_sysusersdir}/%{name}.conf @@ -594,7 +597,11 @@ perl -pi -e "s|$RPM_BUILD_ROOT||g" $RPM_BUILD_ROOT%{_mandir}/man*/* %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/gsissh/ssh_config.d/50-redhat.conf %attr(0644,root,root) %{_mandir}/man5/gsissh_config.5* %attr(0755,root,root) %{_bindir}/gsisftp +%attr(0755,root,root) %{_libexecdir}/gsissh/ssh-sk-helper %attr(0644,root,root) %{_mandir}/man1/gsisftp.1* +%attr(0644,root,root) %{_mandir}/man8/gsissh-sk-helper.8* +%attr(0755,root,root) %dir %{_libexecdir}/gsissh/bin +%{_libexecdir}/gsissh/bin/scp %files server %dir %attr(0711,root,root) %{_datadir}/empty.sshd @@ -618,7 +625,10 @@ perl -pi -e "s|$RPM_BUILD_ROOT||g" $RPM_BUILD_ROOT%{_mandir}/man*/* %attr(0644,root,root) %{_sysusersdir}/%{name}-server.conf %changelog -* Tue Jul 09 2024 Mattias Ellert 1- 8.7p1-10 +* Fri Jul 12 2024 Mattias Ellert - 8.7p1-11 +- Add scp symlink in gsisshd's path + +* Tue Jul 09 2024 Mattias Ellert - 8.7p1-10 - Based on openssh-8.7p1-38.el9_4.1 * Wed Aug 09 2023 Mattias Ellert - 8.7p1-9 From ffb65948a59b734d20d6d93356c107c3e0f508fb Mon Sep 17 00:00:00 2001 From: Mattias Ellert Date: Wed, 22 Jan 2025 09:40:20 +0100 Subject: [PATCH 10/11] Based on openssh-8.7p1-43.el9 --- gsi-openssh.spec | 18 +++- gsisshd-keygen | 12 ++- gsisshd.sysconfig | 3 + openssh-7.7p1-fips.patch | 2 +- openssh-8.0p1-openssl-kdf.patch | 101 ++++++++++++-------- openssh-8.7p1-audit-hostname.patch | 106 +++++++++++++++++++++ openssh-8.7p1-hpn-15.4.patch | 6 +- openssh-8.7p1-sigpipe.patch | 21 ++++ openssh-9.8p1-upstream-cve-2024-6387.patch | 12 +++ 9 files changed, 228 insertions(+), 53 deletions(-) create mode 100644 openssh-8.7p1-audit-hostname.patch create mode 100644 openssh-8.7p1-sigpipe.patch diff --git a/gsi-openssh.spec b/gsi-openssh.spec index 9d0e675..4cf9b4c 100644 --- a/gsi-openssh.spec +++ b/gsi-openssh.spec @@ -24,7 +24,7 @@ %global libedit 1 %global openssh_ver 8.7p1 -%global openssh_rel 11 +%global openssh_rel 12 Summary: An implementation of the SSH protocol with GSI authentication Name: gsi-openssh @@ -57,6 +57,8 @@ Patch100: openssh-6.7p1-coverity.patch Patch200: openssh-7.6p1-audit.patch # Audit race condition in forked child (#1310684) Patch201: openssh-7.1p2-audit-race-condition.patch +# Correctly audit hostname and IP address +Patch202: openssh-8.7p1-audit-hostname.patch #https://bugzilla.mindrot.org/show_bug.cgi?id=1641 (WONTFIX) Patch400: openssh-7.8p1-role-mls.patch @@ -242,7 +244,9 @@ Patch1017: openssh-9.4p2-limit-delay.patch Patch1018: openssh-9.6p1-CVE-2023-48795.patch #upstream commit 7ef3787c84b6b524501211b11a26c742f829af1a Patch1019: openssh-9.6p1-CVE-2023-51385.patch -Patch1020: openssh-9.8p1-upstream-cve-2024-6387.patch +#upstream commit 96faa0de6c673a2ce84736eba37fc9fb723d9e5c +Patch1020: openssh-8.7p1-sigpipe.patch +Patch1021: openssh-9.8p1-upstream-cve-2024-6387.patch # This is the patch that adds GSI support # Based on hpn_isshd-gsi.7.5p1b.patch from Globus upstream @@ -400,6 +404,7 @@ gpgv2 --quiet --keyring %{SOURCE3} %{SOURCE1} %{SOURCE0} %patch200 -p1 -b .audit %patch201 -p1 -b .audit-race +%patch202 -p1 -b .audit-hostname %patch700 -p1 -b .fips %patch1000 -p1 -b .minimize-sha1-use @@ -427,15 +432,15 @@ gpgv2 --quiet --keyring %{SOURCE3} %{SOURCE1} %{SOURCE0} %patch1017 -p1 -b .limitdelay %patch1018 -p1 -b .cve-2023-48795 %patch1019 -p1 -b .cve-2023-51385 -%patch1020 -p1 -b .cve-2024-6387 +%patch1020 -p1 -b .earlypipe +%patch1021 -p1 -b .cve-2024-6387 %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 -sed 's!/etc/sysconfig/sshd!/etc/sysconfig/gsisshd!' -i sshd_config -sed 's!/etc/pam.d/sshd!/etc/pam.d/gsisshd!' -i sshd_config +sed 's!/etc/pam.d/sshd!/etc/pam.d/gsisshd!' -i sshd_config_redhat cp -p %{SOURCE99} . @@ -625,6 +630,9 @@ perl -pi -e "s|$RPM_BUILD_ROOT||g" $RPM_BUILD_ROOT%{_mandir}/man*/* %attr(0644,root,root) %{_sysusersdir}/%{name}-server.conf %changelog +* Wed Jan 22 2025 Mattias Ellert - 8.7p1-12 +- Based on openssh-8.7p1-43.el9 + * Fri Jul 12 2024 Mattias Ellert - 8.7p1-11 - Add scp symlink in gsisshd's path diff --git a/gsisshd-keygen b/gsisshd-keygen index af0a740..c42ef00 100644 --- a/gsisshd-keygen +++ b/gsisshd-keygen @@ -9,8 +9,14 @@ case $KEYTYPE in if [[ -r "$FIPS" && $(cat $FIPS) == "1" ]]; then exit 0 fi ;; - "rsa") ;; # always ok - "ecdsa") ;; + "rsa") + if [[ ! -z $SSH_RSA_BITS ]]; then + SSH_KEYGEN_OPTIONS="-b $SSH_RSA_BITS" + fi ;; # always ok + "ecdsa") + if [[ ! -z $SSH_ECDSA_BITS ]]; then + SSH_KEYGEN_OPTIONS="-b $SSH_ECDSA_BITS" + fi ;; *) # wrong argument exit 12 ;; esac @@ -25,7 +31,7 @@ fi rm -f $KEY{,.pub} # create new keys -if ! $KEYGEN -q -t $KEYTYPE -f $KEY -C '' -N '' >&/dev/null; then +if ! $KEYGEN -q -t $KEYTYPE $SSH_KEYGEN_OPTIONS -f $KEY -C '' -N '' >&/dev/null; then exit 1 fi diff --git a/gsisshd.sysconfig b/gsisshd.sysconfig index 904d8c1..7e106f4 100644 --- a/gsisshd.sysconfig +++ b/gsisshd.sysconfig @@ -5,3 +5,6 @@ # example using systemctl enable gsisshd-keygen@dsa.service to allow creation # of DSA key or systemctl mask gsisshd-keygen@rsa.service to disable RSA key # creation. + +#SSH_RSA_BITS=3072 +#SSH_ECDSA_BITS=256 diff --git a/openssh-7.7p1-fips.patch b/openssh-7.7p1-fips.patch index 05b2907..704de05 100644 --- a/openssh-7.7p1-fips.patch +++ b/openssh-7.7p1-fips.patch @@ -81,7 +81,7 @@ diff -up openssh-8.6p1/kex.c.fips openssh-8.6p1/kex.c #include +#include #include - # ifdef HAVE_EVP_KDF_CTX_NEW_ID + # ifdef HAVE_EVP_KDF_CTX_NEW # include @@ -203,7 +203,10 @@ kex_names_valid(const char *names) for ((p = strsep(&cp, ",")); p && *p != '\0'; diff --git a/openssh-8.0p1-openssl-kdf.patch b/openssh-8.0p1-openssl-kdf.patch index 5d76a4f..e190472 100644 --- a/openssh-8.0p1-openssl-kdf.patch +++ b/openssh-8.0p1-openssl-kdf.patch @@ -12,7 +12,7 @@ index 2a455e4e..e01c3d43 100644 HMAC_CTX_init \ RSA_generate_key_ex \ RSA_get_default_method \ -+ EVP_KDF_CTX_new_id \ ++ EVP_KDF_CTX_new \ ]) # OpenSSL_add_all_algorithms may be a macro. @@ -20,33 +20,35 @@ diff --git a/kex.c b/kex.c index b6f041f4..1fbce2bb 100644 --- a/kex.c +++ b/kex.c -@@ -38,6 +38,9 @@ +@@ -38,6 +38,11 @@ #ifdef WITH_OPENSSL #include #include -+# ifdef HAVE_EVP_KDF_CTX_NEW_ID ++# ifdef HAVE_EVP_KDF_CTX_NEW +# include ++# include ++# include +# endif #endif #include "ssh.h" -@@ -942,6 +945,95 @@ kex_choose_conf(struct ssh *ssh) +@@ -942,6 +945,112 @@ kex_choose_conf(struct ssh *ssh) return r; } -+#ifdef HAVE_EVP_KDF_CTX_NEW_ID -+static const EVP_MD * ++#ifdef HAVE_EVP_KDF_CTX_NEW ++static const char * +digest_to_md(int digest_type) +{ + switch (digest_type) { + case SSH_DIGEST_SHA1: -+ return EVP_sha1(); ++ return SN_sha1; + case SSH_DIGEST_SHA256: -+ return EVP_sha256(); ++ return SN_sha256; + case SSH_DIGEST_SHA384: -+ return EVP_sha384(); ++ return SN_sha384; + case SSH_DIGEST_SHA512: -+ return EVP_sha512(); ++ return SN_sha512; + } + return NULL; +} @@ -56,52 +58,67 @@ index b6f041f4..1fbce2bb 100644 + const struct sshbuf *shared_secret, u_char **keyp) +{ + struct kex *kex = ssh->kex; -+ EVP_KDF_CTX *ctx = NULL; + u_char *key = NULL; + int r, key_len; + -+ if ((key_len = ssh_digest_bytes(kex->hash_alg)) == 0) -+ return SSH_ERR_INVALID_ARGUMENT; ++ EVP_KDF *kdf = EVP_KDF_fetch(NULL, "SSHKDF", NULL); ++ EVP_KDF_CTX *ctx = NULL; ++ OSSL_PARAM_BLD *param_bld = OSSL_PARAM_BLD_new(); ++ OSSL_PARAM *params = NULL; ++ const char *md = digest_to_md(kex->hash_alg); ++ char keytype = (char)id; ++ ++ if (!kdf) { ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ ctx = EVP_KDF_CTX_new(kdf); ++ EVP_KDF_free(kdf); ++ if (!ctx) { ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if (md == NULL) { ++ r = SSH_ERR_INVALID_ARGUMENT; ++ goto out; ++ } ++ ++ if (param_bld == NULL) { ++ EVP_KDF_CTX_free(ctx); ++ return -1; ++ } ++ if ((key_len = ssh_digest_bytes(kex->hash_alg)) == 0) { ++ r = SSH_ERR_INVALID_ARGUMENT; ++ goto out; ++ } ++ + key_len = ROUNDUP(need, key_len); + if ((key = calloc(1, key_len)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + -+ ctx = EVP_KDF_CTX_new_id(EVP_KDF_SSHKDF); -+ if (!ctx) { ++ r = OSSL_PARAM_BLD_push_utf8_string(param_bld, OSSL_KDF_PARAM_DIGEST, ++ md, strlen(md)) && /* SN */ ++ OSSL_PARAM_BLD_push_octet_string(param_bld, OSSL_KDF_PARAM_KEY, ++ sshbuf_ptr(shared_secret), sshbuf_len(shared_secret)) && ++ OSSL_PARAM_BLD_push_octet_string(param_bld, OSSL_KDF_PARAM_SSHKDF_XCGHASH, ++ hash, hashlen) && ++ OSSL_PARAM_BLD_push_octet_string(param_bld, OSSL_KDF_PARAM_SSHKDF_SESSION_ID, ++ sshbuf_ptr(kex->session_id), sshbuf_len(kex->session_id)) && ++ OSSL_PARAM_BLD_push_utf8_string(param_bld, OSSL_KDF_PARAM_SSHKDF_TYPE, ++ &keytype, 1); ++ if (r != 1) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } + -+ r = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_MD, digest_to_md(kex->hash_alg)); -+ if (r != 1) { ++ params = OSSL_PARAM_BLD_to_param(param_bld); ++ if (params == NULL) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } -+ r = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KEY, -+ sshbuf_ptr(shared_secret), sshbuf_len(shared_secret)); -+ if (r != 1) { -+ r = SSH_ERR_LIBCRYPTO_ERROR; -+ goto out; -+ } -+ r = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_SSHKDF_XCGHASH, hash, hashlen); -+ if (r != 1) { -+ r = SSH_ERR_LIBCRYPTO_ERROR; -+ goto out; -+ } -+ r = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_SSHKDF_TYPE, id); -+ if (r != 1) { -+ r = SSH_ERR_LIBCRYPTO_ERROR; -+ goto out; -+ } -+ r = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_SSHKDF_SESSION_ID, -+ sshbuf_ptr(kex->session_id), sshbuf_len(kex->session_id)); -+ if (r != 1) { -+ r = SSH_ERR_LIBCRYPTO_ERROR; -+ goto out; -+ } -+ r = EVP_KDF_derive(ctx, key, key_len); ++ r = EVP_KDF_derive(ctx, key, key_len, params); + if (r != 1) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; @@ -115,6 +132,8 @@ index b6f041f4..1fbce2bb 100644 + r = 0; + +out: ++ OSSL_PARAM_BLD_free(param_bld); ++ OSSL_PARAM_free(params); + free (key); + EVP_KDF_CTX_free(ctx); + if (r < 0) { @@ -130,7 +149,7 @@ index b6f041f4..1fbce2bb 100644 ssh_digest_free(hashctx); return r; } -+#endif /* HAVE_OPENSSL_EVP_KDF_CTX_NEW_ID */ ++#endif /* HAVE_OPENSSL_EVP_KDF_CTX_NEW */ #define NKEYS 6 int diff --git a/openssh-8.7p1-audit-hostname.patch b/openssh-8.7p1-audit-hostname.patch new file mode 100644 index 0000000..e450c00 --- /dev/null +++ b/openssh-8.7p1-audit-hostname.patch @@ -0,0 +1,106 @@ +diff --color -ruNp a/audit-linux.c b/audit-linux.c +--- a/audit-linux.c 2024-05-09 12:38:08.843017319 +0200 ++++ b/audit-linux.c 2024-05-09 12:47:05.162267634 +0200 +@@ -52,7 +52,7 @@ extern u_int utmp_len; + const char *audit_username(void); + + static void +-linux_audit_user_logxxx(int uid, const char *username, ++linux_audit_user_logxxx(int uid, const char *username, const char *hostname, + const char *ip, const char *ttyn, int success, int event) + { + int audit_fd, rc, saved_errno; +@@ -66,7 +66,7 @@ linux_audit_user_logxxx(int uid, const c + } + rc = audit_log_acct_message(audit_fd, event, + NULL, "login", username ? username : "(unknown)", +- username == NULL ? uid : -1, NULL, ip, ttyn, success); ++ username == NULL ? uid : -1, hostname, ip, ttyn, success); + saved_errno = errno; + close(audit_fd); + +@@ -181,9 +181,11 @@ audit_run_command(struct ssh *ssh, const + { + if (!user_login_count++) + linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, ++ options.use_dns ? remote_hostname(ssh) : NULL, + ssh_remote_ipaddr(ssh), + "ssh", 1, AUDIT_USER_LOGIN); + linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, ++ options.use_dns ? remote_hostname(ssh) : NULL, + ssh_remote_ipaddr(ssh), + "ssh", 1, AUDIT_USER_START); + return 0; +@@ -193,10 +195,12 @@ void + audit_end_command(struct ssh *ssh, int handle, const char *command) + { + linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, ++ options.use_dns ? remote_hostname(ssh) : NULL, + ssh_remote_ipaddr(ssh), + "ssh", 1, AUDIT_USER_END); + if (user_login_count && !--user_login_count) + linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, ++ options.use_dns ? remote_hostname(ssh) : NULL, + ssh_remote_ipaddr(ssh), + "ssh", 1, AUDIT_USER_LOGOUT); + } +@@ -211,19 +215,27 @@ void + audit_session_open(struct logininfo *li) + { + if (!user_login_count++) +- linux_audit_user_logxxx(li->uid, NULL, li->hostname, ++ linux_audit_user_logxxx(li->uid, NULL, ++ options.use_dns ? li->hostname : NULL, ++ options.use_dns ? NULL : li->hostname, + li->line, 1, AUDIT_USER_LOGIN); +- linux_audit_user_logxxx(li->uid, NULL, li->hostname, ++ linux_audit_user_logxxx(li->uid, NULL, ++ options.use_dns ? li->hostname : NULL, ++ options.use_dns ? NULL : li->hostname, + li->line, 1, AUDIT_USER_START); + } + + void + audit_session_close(struct logininfo *li) + { +- linux_audit_user_logxxx(li->uid, NULL, li->hostname, ++ linux_audit_user_logxxx(li->uid, NULL, ++ options.use_dns ? li->hostname : NULL, ++ options.use_dns ? NULL : li->hostname, + li->line, 1, AUDIT_USER_END); + if (user_login_count && !--user_login_count) +- linux_audit_user_logxxx(li->uid, NULL, li->hostname, ++ linux_audit_user_logxxx(li->uid, NULL, ++ options.use_dns ? li->hostname : NULL, ++ options.use_dns ? NULL : li->hostname, + li->line, 1, AUDIT_USER_LOGOUT); + } + +@@ -236,6 +248,7 @@ audit_event(struct ssh *ssh, ssh_audit_e + linux_audit_user_auth(-1, audit_username(), + ssh_remote_ipaddr(ssh), "ssh", 0, event); + linux_audit_user_logxxx(-1, audit_username(), ++ options.use_dns ? remote_hostname(ssh) : NULL, + ssh_remote_ipaddr(ssh), "ssh", 0, AUDIT_USER_LOGIN); + break; + case SSH_AUTH_FAIL_PASSWD: +@@ -254,9 +267,11 @@ audit_event(struct ssh *ssh, ssh_audit_e + if (user_login_count) { + while (user_login_count--) + linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, ++ options.use_dns ? remote_hostname(ssh) : NULL, + ssh_remote_ipaddr(ssh), + "ssh", 1, AUDIT_USER_END); + linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, ++ options.use_dns ? remote_hostname(ssh) : NULL, + ssh_remote_ipaddr(ssh), + "ssh", 1, AUDIT_USER_LOGOUT); + } +@@ -265,6 +280,7 @@ audit_event(struct ssh *ssh, ssh_audit_e + case SSH_CONNECTION_ABANDON: + case SSH_INVALID_USER: + linux_audit_user_logxxx(-1, audit_username(), ++ options.use_dns ? remote_hostname(ssh) : NULL, + ssh_remote_ipaddr(ssh), "ssh", 0, AUDIT_USER_LOGIN); + break; + default: diff --git a/openssh-8.7p1-hpn-15.4.patch b/openssh-8.7p1-hpn-15.4.patch index 13feb16..348aa41 100644 --- a/openssh-8.7p1-hpn-15.4.patch +++ b/openssh-8.7p1-hpn-15.4.patch @@ -3646,7 +3646,7 @@ diff -Nur openssh-8.7p1.orig/version.h openssh-8.7p1/version.h #define SSH_PORTABLE "p1" #define GSI_PORTABLE "c-GSI" +-#define SSH_RELEASE SSH_VERSION SSH_PORTABLE GSI_PORTABLE \ +#define SSH_HPN "-hpn15v4" - #define SSH_RELEASE SSH_VERSION SSH_PORTABLE GSI_PORTABLE \ -- GSI_VERSION KRB5_VERSION -+ GSI_VERSION KRB5_VERSION SSH_HPN ++#define SSH_RELEASE SSH_VERSION SSH_PORTABLE GSI_PORTABLE SSH_HPN \ + GSI_VERSION KRB5_VERSION diff --git a/openssh-8.7p1-sigpipe.patch b/openssh-8.7p1-sigpipe.patch new file mode 100644 index 0000000..be73b2c --- /dev/null +++ b/openssh-8.7p1-sigpipe.patch @@ -0,0 +1,21 @@ +diff --git a/ssh.c b/ssh.c +index 89ca1940..559bf2af 100644 +--- a/ssh.c ++++ b/ssh.c +@@ -1124,6 +1124,8 @@ main(int ac, char **av) + } + } + ++ ssh_signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE early */ ++ + /* + * Initialize "log" output. Since we are the client all output + * goes to stderr unless otherwise specified by -y or -E. +@@ -1652,7 +1654,6 @@ main(int ac, char **av) + options.num_system_hostfiles); + tilde_expand_paths(options.user_hostfiles, options.num_user_hostfiles); + +- ssh_signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE early */ + ssh_signal(SIGCHLD, main_sigchld_handler); + + /* Log into the remote system. Never returns if the login fails. */ diff --git a/openssh-9.8p1-upstream-cve-2024-6387.patch b/openssh-9.8p1-upstream-cve-2024-6387.patch index 754d279..fffd50a 100644 --- a/openssh-9.8p1-upstream-cve-2024-6387.patch +++ b/openssh-9.8p1-upstream-cve-2024-6387.patch @@ -16,3 +16,15 @@ diff -up openssh-8.7p1/log.c.xxx openssh-8.7p1/log.c _exit(1); } +diff -up openssh-8.7p1/sshd.c.xxx openssh-8.7p1/sshd.c +--- openssh-8.7p1/sshd.c.xxx 2024-07-01 10:33:04.332907749 +0200 ++++ openssh-8.7p1/sshd.c 2024-07-01 10:33:47.843998038 +0200 +@@ -384,7 +384,7 @@ grace_alarm_handler(int sig) + + /* Log error and exit. */ + if (use_privsep && pmonitor != NULL && pmonitor->m_pid <= 0) +- cleanup_exit(255); /* don't log in privsep child */ ++ _exit(255); /* don't log in privsep child */ + else { + sigdie("Timeout before authentication for %s port %d", + ssh_remote_ipaddr(the_active_state), From 66e44dcf77e8fc8a152e2a1add9a1251f05c809c Mon Sep 17 00:00:00 2001 From: Mattias Ellert Date: Thu, 12 Jun 2025 22:44:24 +0200 Subject: [PATCH 11/11] Based on openssh-8.7p1-45.el9 --- gsi-openssh.spec | 16 ++++- openssh-8.7p1-allow-duplicate-subsystem.patch | 32 +++++++++ openssh-8.7p1-openssl-log.patch | 65 +++++++++++++++++ openssh-8.7p1-redhat-help.patch | 40 +++++++++++ openssh-9.9p2-error_processing.patch | 69 +++++++++++++++++++ 5 files changed, 221 insertions(+), 1 deletion(-) create mode 100644 openssh-8.7p1-allow-duplicate-subsystem.patch create mode 100644 openssh-8.7p1-openssl-log.patch create mode 100644 openssh-8.7p1-redhat-help.patch create mode 100644 openssh-9.9p2-error_processing.patch diff --git a/gsi-openssh.spec b/gsi-openssh.spec index 4cf9b4c..8eba962 100644 --- a/gsi-openssh.spec +++ b/gsi-openssh.spec @@ -24,7 +24,7 @@ %global libedit 1 %global openssh_ver 8.7p1 -%global openssh_rel 12 +%global openssh_rel 13 Summary: An implementation of the SSH protocol with GSI authentication Name: gsi-openssh @@ -247,6 +247,13 @@ Patch1019: openssh-9.6p1-CVE-2023-51385.patch #upstream commit 96faa0de6c673a2ce84736eba37fc9fb723d9e5c Patch1020: openssh-8.7p1-sigpipe.patch Patch1021: openssh-9.8p1-upstream-cve-2024-6387.patch +Patch1022: openssh-8.7p1-redhat-help.patch +Patch1023: openssh-8.7p1-openssl-log.patch +#upstream commit 52dfe3c72d98503d8b7c6f64fc7e19d685636c0b +Patch1024: openssh-8.7p1-allow-duplicate-subsystem.patch +# upstream 6ce00f0c2ecbb9f75023dbe627ee6460bcec78c2 +# upstream 0832aac79517611dd4de93ad0a83577994d9c907 +Patch1025: openssh-9.9p2-error_processing.patch # This is the patch that adds GSI support # Based on hpn_isshd-gsi.7.5p1b.patch from Globus upstream @@ -434,6 +441,10 @@ gpgv2 --quiet --keyring %{SOURCE3} %{SOURCE1} %{SOURCE0} %patch1019 -p1 -b .cve-2023-51385 %patch1020 -p1 -b .earlypipe %patch1021 -p1 -b .cve-2024-6387 +%patch1022 -p1 -b .redhat-help +%patch1023 -p1 -b .openssl-log +%patch1024 -p1 -b .allow-dup-subsystem +%patch1025 -p1 -b .errcode_set %patch98 -p1 -b .gsi %patch99 -p1 -b .hpn @@ -630,6 +641,9 @@ perl -pi -e "s|$RPM_BUILD_ROOT||g" $RPM_BUILD_ROOT%{_mandir}/man*/* %attr(0644,root,root) %{_sysusersdir}/%{name}-server.conf %changelog +* Thu Jun 12 2025 Mattias Ellert - 8.7p1-13 +- Based on openssh-8.7p1-45.el9 + * Wed Jan 22 2025 Mattias Ellert - 8.7p1-12 - Based on openssh-8.7p1-43.el9 diff --git a/openssh-8.7p1-allow-duplicate-subsystem.patch b/openssh-8.7p1-allow-duplicate-subsystem.patch new file mode 100644 index 0000000..22fe73b --- /dev/null +++ b/openssh-8.7p1-allow-duplicate-subsystem.patch @@ -0,0 +1,32 @@ +diff --git a/servconf.c b/servconf.c +index e16f9e90fc71..a3779a9d86ee 100644 +--- a/servconf.c ++++ b/servconf.c +@@ -1942,13 +1942,22 @@ process_server_config_line_depth(ServerOptions *options, char *line, + fatal("%s line %d: %s missing argument.", + filename, linenum, keyword); + if (!*activep) { +- arg = argv_next(&ac, &av); ++ argv_consume(&ac); ++ break; ++ } ++ found = 0; ++ for (i = 0; i < options->num_subsystems; i++) { ++ if (strcmp(arg, options->subsystem_name[i]) == 0) { ++ found = 1; ++ break; ++ } ++ } ++ if (found) { ++ debug("%s line %d: Subsystem '%s' already defined.", ++ filename, linenum, arg); ++ argv_consume(&ac); + break; + } +- for (i = 0; i < options->num_subsystems; i++) +- if (strcmp(arg, options->subsystem_name[i]) == 0) +- fatal("%s line %d: Subsystem '%s' " +- "already defined.", filename, linenum, arg); + options->subsystem_name[options->num_subsystems] = xstrdup(arg); + arg = argv_next(&ac, &av); + if (!arg || *arg == '\0') diff --git a/openssh-8.7p1-openssl-log.patch b/openssh-8.7p1-openssl-log.patch new file mode 100644 index 0000000..9c9a3f5 --- /dev/null +++ b/openssh-8.7p1-openssl-log.patch @@ -0,0 +1,65 @@ +diff -up openssh-8.7p1/log.c.xxx openssh-8.7p1/log.c +--- openssh-8.7p1/log.c.xxx 2024-10-18 13:00:56.419560563 +0200 ++++ openssh-8.7p1/log.c 2024-10-18 13:22:35.954819016 +0200 +@@ -438,6 +438,26 @@ sshlog(const char *file, const char *fun + va_end(args); + } + ++#ifdef WITH_OPENSSL ++static int ++openssl_error_print_cb(const char *str, size_t len, void *u) ++{ ++ sshlogdirect(SYSLOG_LEVEL_DEBUG1, 0, "openssl error %s", str); ++ return 0; ++} ++#endif ++ ++void ++sshlog_openssl(int r) ++{ ++#ifdef WITH_OPENSSL ++ if (r != SSH_ERR_LIBCRYPTO_ERROR) return; ++ ++ ERR_print_errors_cb(openssl_error_print_cb, NULL); ++#endif ++ return; ++} ++ + void + sshlogdie(const char *file, const char *func, int line, int showfunc, + LogLevel level, const char *suffix, const char *fmt, ...) +diff -up openssh-8.7p1/log.h.xxx openssh-8.7p1/log.h +--- openssh-8.7p1/log.h.xxx 2024-10-18 12:56:18.944971946 +0200 ++++ openssh-8.7p1/log.h 2024-10-18 13:03:38.324351416 +0200 +@@ -71,6 +71,7 @@ void cleanup_exit(int) __attribute__((n + void sshlog(const char *, const char *, int, int, + LogLevel, const char *, const char *, ...) + __attribute__((format(printf, 7, 8))); ++void sshlog_openssl(int); + void sshlogv(const char *, const char *, int, int, + LogLevel, const char *, const char *, va_list); + void sshsigdie(const char *, const char *, int, int, +diff -up openssh-8.7p1/auth2-pubkey.c.yyy openssh-8.7p1/auth2-pubkey.c +--- openssh-8.7p1/auth2-pubkey.c.yyy 2024-10-18 13:27:00.709055845 +0200 ++++ openssh-8.7p1/auth2-pubkey.c 2024-10-18 13:27:31.638784460 +0200 +@@ -131,6 +131,7 @@ userauth_pubkey(struct ssh *ssh) + goto done; + } + if ((r = sshkey_from_blob(pkblob, blen, &key)) != 0) { ++ sshlog_openssl(r); + error_fr(r, "parse key"); + goto done; + } +diff -up openssh-8.7p1/dispatch.c.yyy openssh-8.7p1/dispatch.c +--- openssh-8.7p1/dispatch.c.yyy 2024-10-18 13:27:56.349366570 +0200 ++++ openssh-8.7p1/dispatch.c 2024-10-18 13:28:17.921874757 +0200 +@@ -130,6 +130,8 @@ ssh_dispatch_run_fatal(struct ssh *ssh, + { + int r; + +- if ((r = ssh_dispatch_run(ssh, mode, done)) != 0) ++ if ((r = ssh_dispatch_run(ssh, mode, done)) != 0) { ++ sshlog_openssl(r); + sshpkt_fatal(ssh, r, "%s", __func__); ++ } + } diff --git a/openssh-8.7p1-redhat-help.patch b/openssh-8.7p1-redhat-help.patch new file mode 100644 index 0000000..e71c824 --- /dev/null +++ b/openssh-8.7p1-redhat-help.patch @@ -0,0 +1,40 @@ +diff -up openssh-8.7p1/ssh.c.xxx openssh-8.7p1/ssh.c +--- openssh-8.7p1/ssh.c.xxx 2024-09-11 14:24:06.711088878 +0200 ++++ openssh-8.7p1/ssh.c 2024-09-11 14:35:12.883765718 +0200 +@@ -175,6 +175,16 @@ extern int muxserver_sock; + extern u_int muxclient_command; + + /* Prints a help message to the user. This function never returns. */ ++static void ++redhat_usage(void) ++{ ++ if(isatty(fileno(stderr))) { ++ fprintf(stderr, ++"\nYou can find some explanations for typical errors at this link:\n" ++" https://red.ht/support_rhel_ssh\n" ++ ); ++ } ++} + + static void + usage(void) +@@ -188,6 +196,7 @@ usage(void) + " [-Q query_option] [-R address] [-S ctl_path] [-W host:port]\n" + " [-w local_tun[:remote_tun]] destination [command]\n" + ); ++ redhat_usage(); + exit(255); + } + +@@ -1609,8 +1618,10 @@ main(int ac, char **av) + /* Open a connection to the remote host. */ + if (ssh_connect(ssh, host, host_arg, addrs, &hostaddr, options.port, + options.connection_attempts, +- &timeout_ms, options.tcp_keep_alive) != 0) ++ &timeout_ms, options.tcp_keep_alive) != 0) { ++ redhat_usage(); + exit(255); ++ } + + if (addrs != NULL) + freeaddrinfo(addrs); diff --git a/openssh-9.9p2-error_processing.patch b/openssh-9.9p2-error_processing.patch new file mode 100644 index 0000000..d42a370 --- /dev/null +++ b/openssh-9.9p2-error_processing.patch @@ -0,0 +1,69 @@ +diff --git a/krl.c b/krl.c +index e2efdf06..0d0f6953 100644 +--- a/krl.c ++++ b/krl.c +@@ -674,6 +674,7 @@ revoked_certs_generate(struct revoked_certs *rc, struct sshbuf *buf) + break; + case KRL_SECTION_CERT_SERIAL_BITMAP: + if (rs->lo - bitmap_start > INT_MAX) { ++ r = SSH_ERR_INVALID_FORMAT; + error_f("insane bitmap gap"); + goto out; + } +@@ -1059,6 +1060,7 @@ ssh_krl_from_blob(struct sshbuf *buf, struct ssh_krl **krlp) + goto out; + + if ((krl = ssh_krl_init()) == NULL) { ++ r = SSH_ERR_ALLOC_FAIL; + error_f("alloc failed"); + goto out; + } +diff --git a/sshconnect2.c b/sshconnect2.c +index a69c4da1..1ee6000a 100644 +--- a/sshconnect2.c ++++ b/sshconnect2.c +@@ -99,7 +99,7 @@ verify_host_key_callback(struct sshkey *hostkey, struct ssh *ssh) + options.required_rsa_size)) != 0) + fatal_r(r, "Bad server host key"); + if (verify_host_key(xxx_host, xxx_hostaddr, hostkey, +- xxx_conn_info) == -1) ++ xxx_conn_info) != 0) + fatal("Host key verification failed."); + return 0; + } +@@ -699,6 +699,7 @@ input_userauth_pk_ok(int type, u_int32_t seq, struct ssh *ssh) + + if ((pktype = sshkey_type_from_name(pkalg)) == KEY_UNSPEC) { + debug_f("server sent unknown pkalg %s", pkalg); ++ r = SSH_ERR_INVALID_FORMAT; + goto done; + } + if ((r = sshkey_from_blob(pkblob, blen, &key)) != 0) { +@@ -709,6 +710,7 @@ input_userauth_pk_ok(int type, u_int32_t seq, struct ssh *ssh) + error("input_userauth_pk_ok: type mismatch " + "for decoded key (received %d, expected %d)", + key->type, pktype); ++ r = SSH_ERR_INVALID_FORMAT; + goto done; + } + +@@ -728,6 +730,7 @@ input_userauth_pk_ok(int type, u_int32_t seq, struct ssh *ssh) + SSH_FP_DEFAULT); + error_f("server replied with unknown key: %s %s", + sshkey_type(key), fp == NULL ? "" : fp); ++ r = SSH_ERR_INVALID_FORMAT; + goto done; + } + ident = format_identity(id); +diff --git a/sshsig.c b/sshsig.c +index 6e03c0b0..3da005d6 100644 +--- a/sshsig.c ++++ b/sshsig.c +@@ -879,6 +879,7 @@ cert_filter_principals(const char *path, u_long linenum, + } + if ((principals = sshbuf_dup_string(nprincipals)) == NULL) { + error_f("buffer error"); ++ r = SSH_ERR_ALLOC_FAIL; + goto out; + } + /* success */