diff --git a/.github/workflows/c-cpp.yml b/.github/workflows/c-cpp.yml index 1aef209c5..7048a55ee 100644 --- a/.github/workflows/c-cpp.yml +++ b/.github/workflows/c-cpp.yml @@ -59,17 +59,18 @@ jobs: - { target: ubuntu-latest, config: libressl-3.5.3 } - { target: ubuntu-latest, config: libressl-3.6.1 } - { target: ubuntu-latest, config: libressl-3.7.2 } - - { target: ubuntu-latest, config: libressl-3.8.2 } + - { target: ubuntu-latest, config: libressl-3.8.3 } + - { target: ubuntu-latest, config: libressl-3.9.0 } - { target: ubuntu-latest, config: openssl-master } - { target: ubuntu-latest, config: openssl-noec } - { target: ubuntu-latest, config: openssl-1.1.1 } - { target: ubuntu-latest, config: openssl-1.1.1t } - { target: ubuntu-latest, config: openssl-1.1.1w } - { target: ubuntu-latest, config: openssl-3.0.0 } - - { target: ubuntu-latest, config: openssl-3.0.12 } + - { target: ubuntu-latest, config: openssl-3.0.13 } - { target: ubuntu-latest, config: openssl-3.1.0 } - - { target: ubuntu-latest, config: openssl-3.1.4 } - - { target: ubuntu-latest, config: openssl-3.2.0 } + - { target: ubuntu-latest, config: openssl-3.1.5 } + - { target: ubuntu-latest, config: openssl-3.2.1 } - { target: ubuntu-latest, config: openssl-1.1.1_stable } - { target: ubuntu-latest, config: openssl-3.0 } # stable branch - { target: ubuntu-latest, config: openssl-3.2 } # stable branch diff --git a/README b/README index 327562671..89981ef6f 100644 --- a/README +++ b/README @@ -1,4 +1,4 @@ -See https://www.openssh.com/releasenotes.html#9.6p1 for the release +See https://www.openssh.com/releasenotes.html#9.7p1 for the release notes. Please read https://www.openssh.com/report.html for bug reporting diff --git a/channels.c b/channels.c index 6a2f077cb..c96e15df9 100644 --- a/channels.c +++ b/channels.c @@ -1,4 +1,4 @@ -/* $OpenBSD: channels.c,v 1.436 2024/01/09 22:19:00 djm Exp $ */ +/* $OpenBSD: channels.c,v 1.437 2024/03/06 02:59:59 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -3254,9 +3254,8 @@ channel_proxy_downstream(struct ssh *ssh, Channel *downstream) goto out; } /* Record that connection to this host/port is permitted. */ - permission_set_add(ssh, FORWARD_USER, FORWARD_LOCAL, "", -1, - listen_host, NULL, (int)listen_port, downstream); - listen_host = NULL; + permission_set_add(ssh, FORWARD_USER, FORWARD_LOCAL, "", + -1, listen_host, NULL, (int)listen_port, downstream); break; case SSH2_MSG_CHANNEL_CLOSE: if (have < 4) diff --git a/configure.ac b/configure.ac index fda092830..82e8bb7c1 100644 --- a/configure.ac +++ b/configure.ac @@ -149,6 +149,7 @@ fi use_stack_protector=1 use_toolchain_hardening=1 +use_retpoline=1 AC_ARG_WITH([stackprotect], [ --without-stackprotect Don't use compiler's stack protection], [ if test "x$withval" = "xno"; then @@ -159,6 +160,11 @@ AC_ARG_WITH([hardening], if test "x$withval" = "xno"; then use_toolchain_hardening=0 fi ]) +AC_ARG_WITH([retpoline], + [ --without-retpoline Enable retpoline spectre mitigation], [ + if test "x$withval" = "xno"; then + use_retpoline=0 + fi ]) # We use -Werror for the tests only so that we catch warnings like "this is # on by default" for things like -fPIE. @@ -216,8 +222,6 @@ if test "$GCC" = "yes" || test "$GCC" = "egcs"; then OSSH_CHECK_CFLAG_COMPILE([-Wbitwise-instead-of-logical]) OSSH_CHECK_CFLAG_COMPILE([-fno-strict-aliasing]) if test "x$use_toolchain_hardening" = "x1"; then - OSSH_CHECK_CFLAG_COMPILE([-mretpoline]) # clang - OSSH_CHECK_LDFLAG_LINK([-Wl,-z,retpolineplt]) OSSH_CHECK_CFLAG_COMPILE([-D_FORTIFY_SOURCE=2]) OSSH_CHECK_LDFLAG_LINK([-Wl,-z,relro]) OSSH_CHECK_LDFLAG_LINK([-Wl,-z,now]) @@ -240,6 +244,10 @@ if test "$GCC" = "yes" || test "$GCC" = "egcs"; then esac OSSH_CHECK_CFLAG_COMPILE([-ftrivial-auto-var-init=zero]) fi + if test "x$use_retpoline" = "x1"; then + OSSH_CHECK_CFLAG_COMPILE([-mretpoline]) # clang + OSSH_CHECK_LDFLAG_LINK([-Wl,-z,retpolineplt]) + fi AC_MSG_CHECKING([if $CC accepts -fno-builtin-memset]) saved_CFLAGS="$CFLAGS" @@ -2735,7 +2743,15 @@ AC_ARG_WITH([ssl-dir], else CPPFLAGS="-I${withval} ${CPPFLAGS}" fi - openssl_bin_PATH="${PATH}${PATH_SEPARATOR}${withval}/bin${PATH_SEPARATOR}${withval}/apps" + dnl Ensure specified openssl binary works, eg it can + dnl find its runtime libraries, before trying to use. + if test -x "${withval}/bin/openssl" && \ + "${withval}/bin/openssl" version >/dev/null 2>&1; then + openssl_bin_PATH="${withval}/bin${PATH_SEPARATOR}${PATH}" + elif test -x "${withval}/apps/openssl" && \ + "${withval}/apps/openssl" version >/dev/null 2>&1; then + openssl_bin_PATH="${withval}/apps${PATH_SEPARATOR}${PATH}" + fi fi ] ) diff --git a/contrib/redhat/openssh.spec b/contrib/redhat/openssh.spec index 0524a72b4..b2309716f 100644 --- a/contrib/redhat/openssh.spec +++ b/contrib/redhat/openssh.spec @@ -1,4 +1,4 @@ -%global ver 9.6p1 +%global ver 9.7p1 %global rel 1%{?dist} # OpenSSH privilege separation requires a user & group ID diff --git a/contrib/suse/openssh.spec b/contrib/suse/openssh.spec index b5082f0d5..7dbe4db6e 100644 --- a/contrib/suse/openssh.spec +++ b/contrib/suse/openssh.spec @@ -13,7 +13,7 @@ Summary: OpenSSH, a free Secure Shell (SSH) protocol implementation Name: openssh -Version: 9.6p1 +Version: 9.7p1 URL: https://www.openssh.com/ Release: 1 Source0: openssh-%{version}.tar.gz diff --git a/regress/Makefile b/regress/Makefile index ca9c66e19..c9a495f6f 100644 --- a/regress/Makefile +++ b/regress/Makefile @@ -156,31 +156,40 @@ TEST_SSH_SSHKEYGEN?=ssh-keygen CPPFLAGS=-I.. t1: - ${TEST_SSH_SSHKEYGEN} -if ${.CURDIR}/rsa_ssh2.prv | diff - ${.CURDIR}/rsa_openssh.prv - tr '\n' '\r' <${.CURDIR}/rsa_ssh2.prv > ${.OBJDIR}/rsa_ssh2_cr.prv - ${TEST_SSH_SSHKEYGEN} -if ${.OBJDIR}/rsa_ssh2_cr.prv | diff - ${.CURDIR}/rsa_openssh.prv - awk '{print $$0 "\r"}' ${.CURDIR}/rsa_ssh2.prv > ${.OBJDIR}/rsa_ssh2_crnl.prv - ${TEST_SSH_SSHKEYGEN} -if ${.OBJDIR}/rsa_ssh2_crnl.prv | diff - ${.CURDIR}/rsa_openssh.prv + set -xe ; if ${TEST_SSH_SSH} -Q key | grep -q "^ssh-rsa" ; then \ + ${TEST_SSH_SSHKEYGEN} -if ${.CURDIR}/rsa_ssh2.prv | diff - ${.CURDIR}/rsa_openssh.prv ; \ + tr '\n' '\r' <${.CURDIR}/rsa_ssh2.prv > ${.OBJDIR}/rsa_ssh2_cr.prv ; \ + ${TEST_SSH_SSHKEYGEN} -if ${.OBJDIR}/rsa_ssh2_cr.prv | diff - ${.CURDIR}/rsa_openssh.prv ; \ + awk '{print $$0 "\r"}' ${.CURDIR}/rsa_ssh2.prv > ${.OBJDIR}/rsa_ssh2_crnl.prv ; \ + ${TEST_SSH_SSHKEYGEN} -if ${.OBJDIR}/rsa_ssh2_crnl.prv | diff - ${.CURDIR}/rsa_openssh.prv ; \ + fi t2: - cat ${.CURDIR}/rsa_openssh.prv > $(OBJ)/t2.out - chmod 600 $(OBJ)/t2.out - ${TEST_SSH_SSHKEYGEN} -yf $(OBJ)/t2.out | diff - ${.CURDIR}/rsa_openssh.pub + set -xe ; if ${TEST_SSH_SSH} -Q key | grep -q "^ssh-rsa" ; then \ + cat ${.CURDIR}/rsa_openssh.prv > $(OBJ)/t2.out ; \ + chmod 600 $(OBJ)/t2.out ; \ + ${TEST_SSH_SSHKEYGEN} -yf $(OBJ)/t2.out | diff - ${.CURDIR}/rsa_openssh.pub ; \ + fi t3: - ${TEST_SSH_SSHKEYGEN} -ef ${.CURDIR}/rsa_openssh.pub >$(OBJ)/t3.out - ${TEST_SSH_SSHKEYGEN} -if $(OBJ)/t3.out | diff - ${.CURDIR}/rsa_openssh.pub + set -xe ; if ${TEST_SSH_SSH} -Q key | grep -q "^ssh-rsa" ; then \ + ${TEST_SSH_SSHKEYGEN} -ef ${.CURDIR}/rsa_openssh.pub >$(OBJ)/t3.out ; \ + ${TEST_SSH_SSHKEYGEN} -if $(OBJ)/t3.out | diff - ${.CURDIR}/rsa_openssh.pub ; \ + fi t4: - ${TEST_SSH_SSHKEYGEN} -E md5 -lf ${.CURDIR}/rsa_openssh.pub |\ - awk '{print $$2}' | diff - ${.CURDIR}/t4.ok + set -xe ; if ${TEST_SSH_SSH} -Q key | grep -q "^ssh-rsa" ; then \ + ${TEST_SSH_SSHKEYGEN} -E md5 -lf ${.CURDIR}/rsa_openssh.pub |\ + awk '{print $$2}' | diff - ${.CURDIR}/t4.ok ; \ + fi t5: - ${TEST_SSH_SSHKEYGEN} -Bf ${.CURDIR}/rsa_openssh.pub |\ - awk '{print $$2}' | diff - ${.CURDIR}/t5.ok - + set -xe ; if ${TEST_SSH_SSH} -Q key | grep -q "^ssh-rsa" ; then \ + ${TEST_SSH_SSHKEYGEN} -Bf ${.CURDIR}/rsa_openssh.pub |\ + awk '{print $$2}' | diff - ${.CURDIR}/t5.ok ; \ + fi t6: - set -xe ; if ${TEST_SSH_SSH} -Q key | grep -q ^ssh-dss ; then \ + set -xe ; if ${TEST_SSH_SSH} -Q key | grep -q "^ssh-dss" ; then \ ${TEST_SSH_SSHKEYGEN} -if ${.CURDIR}/dsa_ssh2.prv > $(OBJ)/t6.out1 ; \ ${TEST_SSH_SSHKEYGEN} -if ${.CURDIR}/dsa_ssh2.pub > $(OBJ)/t6.out2 ; \ chmod 600 $(OBJ)/t6.out1 ; \ @@ -188,19 +197,23 @@ t6: fi $(OBJ)/t7.out: - ${TEST_SSH_SSHKEYGEN} -q -t rsa -N '' -f $@ + set -xe ; if ${TEST_SSH_SSH} -Q key | grep -q "^ssh-dss" ; then \ + ${TEST_SSH_SSHKEYGEN} -q -t rsa -N '' -f $@ ; \ + fi t7: $(OBJ)/t7.out - ${TEST_SSH_SSHKEYGEN} -lf $(OBJ)/t7.out > /dev/null - ${TEST_SSH_SSHKEYGEN} -Bf $(OBJ)/t7.out > /dev/null + set -xe ; if ${TEST_SSH_SSH} -Q key | grep -q "^ssh-dss" ; then \ + ${TEST_SSH_SSHKEYGEN} -lf $(OBJ)/t7.out > /dev/null ; \ + ${TEST_SSH_SSHKEYGEN} -Bf $(OBJ)/t7.out > /dev/null ; \ + fi $(OBJ)/t8.out: - set -xe ; if ssh -Q key | grep -q ^ssh-dss ; then \ + set -xe ; if ssh -Q key | grep -q "^ssh-dss" ; then \ ${TEST_SSH_SSHKEYGEN} -q -t dsa -N '' -f $@ ; \ fi t8: $(OBJ)/t8.out - set -xe ; if ssh -Q key | grep -q ^ssh-dss ; then \ + set -xe ; if ssh -Q key | grep -q "^ssh-dss" ; then \ ${TEST_SSH_SSHKEYGEN} -lf $(OBJ)/t8.out > /dev/null ; \ ${TEST_SSH_SSHKEYGEN} -Bf $(OBJ)/t8.out > /dev/null ; \ fi @@ -224,8 +237,10 @@ t10: $(OBJ)/t10.out ${TEST_SSH_SSHKEYGEN} -Bf $(OBJ)/t10.out > /dev/null t11: - ${TEST_SSH_SSHKEYGEN} -E sha256 -lf ${.CURDIR}/rsa_openssh.pub |\ - awk '{print $$2}' | diff - ${.CURDIR}/t11.ok + set -xe ; if ${TEST_SSH_SSH} -Q key | grep -q "^ssh-dss" ; then \ + ${TEST_SSH_SSHKEYGEN} -E sha256 -lf ${.CURDIR}/rsa_openssh.pub |\ + awk '{print $$2}' | diff - ${.CURDIR}/t11.ok ; \ + fi $(OBJ)/t12.out: ${TEST_SSH_SSHKEYGEN} -q -t ed25519 -N '' -C 'test-comment-1234' -f $@ diff --git a/regress/dynamic-forward.sh b/regress/dynamic-forward.sh index 893393cb9..4413d7c8c 100644 --- a/regress/dynamic-forward.sh +++ b/regress/dynamic-forward.sh @@ -1,4 +1,4 @@ -# $OpenBSD: dynamic-forward.sh,v 1.15 2023/01/06 08:50:33 dtucker Exp $ +# $OpenBSD: dynamic-forward.sh,v 1.17 2024/03/08 11:34:10 dtucker Exp $ # Placed in the Public Domain. tid="dynamic forwarding" @@ -26,6 +26,7 @@ start_ssh() { arg="$2" n=0 error="1" + # Use a multiplexed ssh so we can control its lifecycle. trace "start dynamic -$direction forwarding, fork to background" (cat $OBJ/ssh_config.orig ; echo "$arg") > $OBJ/ssh_config ${REAL_SSH} -vvvnNfF $OBJ/ssh_config -E$TEST_SSH_LOGFILE \ @@ -62,9 +63,9 @@ check_socks() { for s in 4 5; do for h in 127.0.0.1 localhost; do trace "testing ssh socks version $s host $h (-$direction)" - ${REAL_SSH} -q -F $OBJ/ssh_config \ - -o "ProxyCommand ${proxycmd}${s} $h $PORT 2>/dev/null" \ - somehost cat ${DATA} > ${COPY} + ${REAL_SSH} -q -F $OBJ/ssh_config -o \ + "ProxyCommand ${TEST_SHELL} -c '${proxycmd}${s} $h $PORT 2>/dev/null'" \ + somehost cat ${DATA} > ${COPY} r=$? if [ "x$expect_success" = "xY" ] ; then if [ $r -ne 0 ] ; then diff --git a/regress/test-exec.sh b/regress/test-exec.sh index 55f341aae..b1a0a00e0 100644 --- a/regress/test-exec.sh +++ b/regress/test-exec.sh @@ -1,4 +1,4 @@ -# $OpenBSD: test-exec.sh,v 1.107 2024/02/19 09:25:52 dtucker Exp $ +# $OpenBSD: test-exec.sh,v 1.108 2024/03/08 11:34:10 dtucker Exp $ # Placed in the Public Domain. #SUDO=sudo @@ -110,6 +110,9 @@ DBCLIENT=/usr/local/bin/dbclient DROPBEARKEY=/usr/local/bin/dropbearkey DROPBEARCONVERT=/usr/local/bin/dropbearconvert +# So we can override this in Portable. +TEST_SHELL="${TEST_SHELL:-/bin/sh}" + # Tools used by multiple tests NC=$OBJ/netcat # Always use the one configure tells us to, even if that's empty. diff --git a/ssh-agent.c b/ssh-agent.c index 7347aaee5..d35741a86 100644 --- a/ssh-agent.c +++ b/ssh-agent.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-agent.c,v 1.304 2023/12/18 15:58:56 djm Exp $ */ +/* $OpenBSD: ssh-agent.c,v 1.306 2024/03/09 05:12:13 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -162,6 +162,8 @@ int max_fd = 0; pid_t parent_pid = -1; time_t parent_alive_interval = 0; +sig_atomic_t signalled = 0; + /* pid of process for which cleanup_socket is applicable */ pid_t cleanup_pid = 0; @@ -250,6 +252,7 @@ free_dest_constraints(struct dest_constraint *dcs, size_t ndcs) free(dcs); } +#ifdef ENABLE_PKCS11 static void dup_dest_constraint_hop(const struct dest_constraint_hop *dch, struct dest_constraint_hop *out) @@ -289,6 +292,7 @@ dup_dest_constraints(const struct dest_constraint *dcs, size_t ndcs) } return ret; } +#endif /* ENABLE_PKCS11 */ #ifdef DEBUG_CONSTRAINTS static void @@ -1522,6 +1526,7 @@ no_identities(SocketEntry *e) sshbuf_free(msg); } +#ifdef ENABLE_PKCS11 /* Add an identity to idlist; takes ownership of 'key' and 'comment' */ static void add_p11_identity(struct sshkey *key, char *comment, const char *provider, @@ -1548,7 +1553,6 @@ add_p11_identity(struct sshkey *key, char *comment, const char *provider, idtab->nentries++; } -#ifdef ENABLE_PKCS11 static void process_add_smartcard_key(SocketEntry *e) { @@ -2060,7 +2064,7 @@ after_poll(struct pollfd *pfd, size_t npfd, u_int maxfds) } static int -prepare_poll(struct pollfd **pfdp, size_t *npfdp, int *timeoutp, u_int maxfds) +prepare_poll(struct pollfd **pfdp, size_t *npfdp, struct timespec *timeoutp, u_int maxfds) { struct pollfd *pfd = *pfdp; size_t i, j, npfd = 0; @@ -2126,14 +2130,8 @@ prepare_poll(struct pollfd **pfdp, size_t *npfdp, int *timeoutp, u_int maxfds) if (parent_alive_interval != 0) deadline = (deadline == 0) ? parent_alive_interval : MINIMUM(deadline, parent_alive_interval); - if (deadline == 0) { - *timeoutp = -1; /* INFTIM */ - } else { - if (deadline > INT_MAX / 1000) - *timeoutp = INT_MAX / 1000; - else - *timeoutp = deadline * 1000; - } + if (deadline != 0) + ptimeout_deadline_sec(timeoutp, deadline); return (1); } @@ -2153,17 +2151,16 @@ void cleanup_exit(int i) { cleanup_socket(); +#ifdef ENABLE_PKCS11 + pkcs11_terminate(); +#endif _exit(i); } static void cleanup_handler(int sig) { - cleanup_socket(); -#ifdef ENABLE_PKCS11 - pkcs11_terminate(); -#endif - _exit(2); + signalled = sig; } static void @@ -2207,10 +2204,11 @@ main(int ac, char **av) char pidstrbuf[1 + 3 * sizeof pid]; size_t len; mode_t prev_mask; - int timeout = -1; /* INFTIM */ + struct timespec timeout; struct pollfd *pfd = NULL; size_t npfd = 0; u_int maxfds; + sigset_t nsigset, osigset; /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ sanitise_stdfd(); @@ -2446,13 +2444,25 @@ skip: ssh_signal(SIGHUP, cleanup_handler); ssh_signal(SIGTERM, cleanup_handler); + sigemptyset(&nsigset); + sigaddset(&nsigset, SIGINT); + sigaddset(&nsigset, SIGHUP); + sigaddset(&nsigset, SIGTERM); + if (pledge("stdio rpath cpath unix id proc exec", NULL) == -1) fatal("%s: pledge: %s", __progname, strerror(errno)); platform_pledge_agent(); while (1) { + sigprocmask(SIG_BLOCK, &nsigset, &osigset); + if (signalled != 0) { + logit("exiting on signal %d", (int)signalled); + cleanup_exit(2); + } + ptimeout_init(&timeout); prepare_poll(&pfd, &npfd, &timeout, maxfds); - result = poll(pfd, npfd, timeout); + result = ppoll(pfd, npfd, ptimeout_get_tsp(&timeout), &osigset); + sigprocmask(SIG_SETMASK, &osigset, NULL); saved_errno = errno; if (parent_alive_interval != 0) check_parent_exists(); diff --git a/sshsig.c b/sshsig.c index 492f4d65b..d7345cc7f 100644 --- a/sshsig.c +++ b/sshsig.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshsig.c,v 1.34 2023/12/08 09:18:39 markus Exp $ */ +/* $OpenBSD: sshsig.c,v 1.35 2024/03/08 22:16:32 djm Exp $ */ /* * Copyright (c) 2019 Google LLC * @@ -779,7 +779,7 @@ parse_principals_key_and_options(const char *path, u_long linenum, char *line, *keyp = NULL; cp = line; - cp = cp + strspn(cp, " \t"); /* skip leading whitespace */ + cp = cp + strspn(cp, " \t\n\r"); /* skip leading whitespace */ if (*cp == '#' || *cp == '\0') return SSH_ERR_KEY_NOT_FOUND; /* blank or all-comment line */ diff --git a/version.h b/version.h index 1cffa5c7a..6bafd0f7f 100644 --- a/version.h +++ b/version.h @@ -1,6 +1,6 @@ -/* $OpenBSD: version.h,v 1.100 2023/12/18 14:48:44 djm Exp $ */ +/* $OpenBSD: version.h,v 1.101 2024/03/11 04:59:47 djm Exp $ */ -#define SSH_VERSION "OpenSSH_for_Windows_9.6" +#define SSH_VERSION "OpenSSH_for_Windows_9.7" #define SSH_PORTABLE "p1" #define SSH_RELEASE SSH_VERSION SSH_PORTABLE