Compare commits

...
Sign in to create a new pull request.

21 commits

Author SHA1 Message Date
Mattias Ellert
adf6749248 Based on openssh-8.0p1-25.el8_10 2024-10-03 04:48:11 +02:00
Mattias Ellert
658736fecc Add scp symlink in gsisshd's path 2024-07-12 20:31:20 +02:00
Mattias Ellert
d9b07779a6 Based on openssh-8.0p1-24.el8
Drop patch openssh-8.0p1-sshbuf-readonly.patch (now included in
  openssh-8.0p1-gssapi-keyex.patch)
2024-07-10 07:01:00 +02:00
Mattias Ellert
d9643d4abf Based on openssh-8.0p1-19.el8_8 2023-08-11 16:01:15 +02:00
Mattias Ellert
ba7503ed34 Based on openssh-8.0p1-17.el8_7 2023-03-11 15:41:32 +01:00
Mattias Ellert
0155cda587 Based on openssh-8.0p1-16.el8 2022-10-08 11:53:45 +02:00
Mattias Ellert
897e3b92a6 Based on openssh-8.0p1-13.el8 2022-08-09 11:27:47 +02:00
Mattias Ellert
c4d973523c Based on openssh-8.0p1-10.el8 2021-11-24 17:28:40 +01:00
Mattias Ellert
a67ad5bbcf Based on openssh-8.0p1-6.el8_4.2 2021-05-22 09:28:33 +02:00
Mattias Ellert
9575bd55d5 Fix issue with read-only ssh buffer during gssapi key exchange
Clean up HPN patch
2021-03-16 06:37:00 +01:00
Mattias Ellert
06a633eb7a Based on openssh-8.0p1-5.el8 2020-11-30 07:08:28 +01:00
Frank Scheiner
68d8f4ac90 Update HPN patch
* document switch to disable MTAES cipher
* ship GSI-OpenSSH packages with MTAES cipher disabled
* include version string fix
2020-10-23 18:32:57 +02:00
Frank Scheiner
53bc8ae15d Add HPN patch 2020-09-25 19:33:42 +02:00
Mattias Ellert
9c88d73924 Add missing buffer initialization in gsissh patch 2020-05-04 20:52:37 +02:00
Mattias Ellert
149f61dfaa Based on openssh-8.0p1-4.el8 2020-04-14 16:11:58 +02:00
Mattias Ellert
146f9b28f3 Based on openssh-8.0p1-3.el8 2020-01-08 14:36:49 +01:00
Mattias Ellert
4f44809b0b Based on openssh-7.8p1-4.el8 2019-08-19 18:43:14 +02:00
Mattias Ellert
8e86bdb410 Remove usage statistics collection support 2019-02-27 09:23:05 +01:00
Mattias Ellert
775e7f8a14 CVE-2019-7639 2019-02-08 22:16:26 +01:00
Mattias Ellert
c2bba13c4a Forgotten patch from previous commit 2019-01-16 06:22:53 +01:00
Mattias Ellert
b17edf9dcf Based on openssh-7.8p1-4.fc28 2019-01-15 17:16:20 +01:00
77 changed files with 16273 additions and 15763 deletions

2
.gitignore vendored
View file

@ -1,4 +1,4 @@
/*.tar.bz2
/*.tar.gz
/*.tar.gz.asc
/DJM-GPG-KEY.gpg
/*.gpg

View file

@ -30,8 +30,8 @@
# Do we want LDAP support
%global ldap 1
%global openssh_ver 7.8p1
%global openssh_rel 1
%global openssh_ver 8.0p1
%global openssh_rel 16
Summary: An implementation of the SSH protocol with GSI authentication
Name: gsi-openssh
@ -56,11 +56,6 @@ Source99: README.sshd-and-gsisshd
#https://bugzilla.mindrot.org/show_bug.cgi?id=2581
Patch100: openssh-6.7p1-coverity.patch
#https://bugzilla.mindrot.org/show_bug.cgi?id=1894
#https://bugzilla.redhat.com/show_bug.cgi?id=735889
#Patch102: openssh-5.8p1-getaddrinfo.patch
# OpenSSL 1.1.0 compatibility
Patch104: openssh-7.3p1-openssl-1.1.0.patch
#https://bugzilla.mindrot.org/show_bug.cgi?id=1402
# https://bugzilla.redhat.com/show_bug.cgi?id=1171248
@ -98,8 +93,6 @@ Patch702: openssh-5.1p1-askpass-progress.patch
Patch703: openssh-4.3p2-askpass-grab-info.patch
#https://bugzilla.mindrot.org/show_bug.cgi?id=1635 (WONTFIX)
Patch707: openssh-7.7p1-redhat.patch
#https://bugzilla.mindrot.org/show_bug.cgi?id=1640 (WONTFIX)
Patch709: openssh-6.2p1-vendor.patch
# warn users for unsupported UsePAM=no (#757545)
Patch711: openssh-7.8p1-UsePAM-warning.patch
# make aes-ctr ciphers use EVP engines such as AES-NI from OpenSSL
@ -109,26 +102,20 @@ Patch713: openssh-6.6p1-ctr-cavstest.patch
# add SSH KDF CAVS test driver
Patch714: openssh-6.7p1-kdf-cavs.patch
#http://www.sxw.org.uk/computing/patches/openssh.html
#changed cache storage type - #848228
Patch800: openssh-7.8p1-gsskex.patch
# GSSAPI Key Exchange (RFC 4462 + draft-ietf-curdle-gss-keyex-sha2-08)
# from https://github.com/openssh-gsskex/openssh-gsskex/tree/fedora/master
Patch800: openssh-8.0p1-gssapi-keyex.patch
#http://www.mail-archive.com/kerberos@mit.edu/msg17591.html
Patch801: openssh-6.6p1-force_krb.patch
# add new option GSSAPIEnablek5users and disable using ~/.k5users by default (#1169843)
# CVE-2014-9278
Patch802: openssh-6.6p1-GSSAPIEnablek5users.patch
# Documentation about GSSAPI
# from https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=765655
Patch803: openssh-7.1p1-gssapi-documentation.patch
# Improve ccache handling in openssh (#991186, #1199363, #1566494)
# https://bugzilla.mindrot.org/show_bug.cgi?id=2775
Patch804: openssh-7.7p1-gssapi-new-unique.patch
# Respect k5login_directory option in krk5.conf (#1328243)
Patch805: openssh-7.2p2-k5login_directory.patch
# Support SHA2 in GSS key exchanges from draft-ssorce-gss-keyex-sha2-02
Patch807: openssh-7.5p1-gssapi-kex-with-ec.patch
Patch900: openssh-6.1p1-gssapi-canohost.patch
#https://bugzilla.mindrot.org/show_bug.cgi?id=1780
Patch901: openssh-6.6p1-kuserok.patch
# Use tty allocation for a remote scp (#985650)
@ -139,16 +126,12 @@ Patch916: openssh-6.6.1p1-selinux-contexts.patch
Patch918: openssh-6.6.1p1-log-in-chroot.patch
# scp file into non-existing directory (#1142223)
Patch919: openssh-6.6.1p1-scp-non-existing-directory.patch
# Config parser shouldn't accept ip/port syntax (#1130733)
Patch920: openssh-7.8p1-ip-port-config-parser.patch
# apply upstream patch and make sshd -T more consistent (#1187521)
Patch922: openssh-6.8p1-sshdT-output.patch
# Add sftp option to force mode of created files (#1191055)
Patch926: openssh-6.7p1-sftp-force-permission.patch
# Restore compatible default (#89216)
Patch929: openssh-6.9p1-permit-root-login.patch
# Add GSSAPIKexAlgorithms option for server and client application
Patch932: openssh-7.0p1-gssKexAlgorithms.patch
# make s390 use /dev/ crypto devices -- ignore closefrom
Patch939: openssh-7.2p2-s390-closefrom.patch
# Move MAX_DISPLAYS to a configuration option (#1341302)
@ -160,15 +143,110 @@ Patch949: openssh-7.6p1-cleanup-selinux.patch
# Sandbox adjustments for s390 and audit
Patch950: openssh-7.5p1-sandbox.patch
# PKCS#11 URIs (upstream #2817, 2nd iteration)
Patch951: openssh-7.6p1-pkcs11-uri.patch
# PKCS#11 ECDSA keys (upstream #2474, 8th iteration)
Patch952: openssh-7.6p1-pkcs11-ecdsa.patch
Patch951: openssh-8.0p1-pkcs11-uri.patch
# Unbreak scp between two IPv6 hosts (#1620333)
Patch953: openssh-7.8p1-scp-ipv6.patch
# ssh-copy-id is unmaintained: Aggreagete patches
# - do not return 0 if the write fails (full disk)
# - shellcheck reports (upstream #2902)
Patch958: openssh-7.9p1-ssh-copy-id.patch
# Verify the SCP vulnerabilities are fixed in the package testsuite
# https://bugzilla.mindrot.org/show_bug.cgi?id=3007
Patch961: openssh-8.0p1-scp-tests.patch
# Mention crypto-policies in manual pages (#1668325)
Patch962: openssh-8.0p1-crypto-policies.patch
# Use OpenSSL high-level API to produce and verify signatures (#1707485)
Patch963: openssh-8.0p1-openssl-evp.patch
# Use OpenSSL KDF (#1631761)
Patch964: openssh-8.0p1-openssl-kdf.patch
# Use new OpenSSL for PEM export to avoid MD5 dependency (#1712436)
Patch965: openssh-8.0p1-openssl-pem.patch
# Seed from dev/random if requested (#1785655)
Patch966: openssh-8.0p1-entropy.patch
# Unbreak ssh-keyscan RSA keys without SHA1 (#1744108)
Patch967: openssh-8.0p1-keyscan-rsa-sha2.patch
# Detect proxyJump loops in configuration files (#1804099)
Patch968: openssh-8.0p1-proxyjump-loops.patch
# ssh-keygen should default to SHA2-based signature algorithm (#1790610)
Patch969: openssh-8.0p1-keygen-sha2.patch
# RDomain is not suported on non-OpenBSD (#1807686)
# https://bugzilla.mindrot.org/show_bug.cgi?id=3126
Patch970: openssh-8.0p1-rdomain.patch
# Do not fail X11 forwarding if IPv6 is disabled (#1662189)
# https://bugzilla.mindrot.org/show_bug.cgi?id=2143
Patch971: openssh-8.0p1-x11-without-ipv6.patch
# Client window fix (#1913041)
Patch972: openssh-8.0p1-channel-limits.patch
# SFTP sort upon the modification time (#1909988)
# https://bugzilla.mindrot.org/show_bug.cgi?id=3248
Patch973: openssh-8.0p1-sftp-timespeccmp.patch
# 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
# ssh incorrectly restores the blocking mode on standard output (#1942901)
Patch976: openssh-8.0p1-restore-nonblock.patch
# CVE 2020-14145
Patch977: openssh-8.0p1-cve-2020-14145.patch
# sshd -T requires -C when "Match" is used in sshd_config (#1836277)
Patch978: openssh-8.0p1-sshd_config.patch
# CVE-2021-41617
Patch980: openssh-8.7p1-upstream-cve-2021-41617.patch
# support sshd Include directive
# upstream commits:
# c2bd7f74b0e0f3a3ee9d19ac549e6ba89013abaf~1..677d0ece67634262b3b96c3cd6410b19f3a603b7
# 8bdc3bb7cf4c82c3344cfcb82495a43406e87e83
# 47adfdc07f4f8ea0064a1495500244de08d311ed~1..7af1e92cd289b7eaa9a683e9a6f2fddd98f37a01
# supplementary commit 612b1dd1ec91ffb1e01f58cca0c6eb1d47bf4423
Patch981: openssh-8.0p1-sshd_include.patch
# Port upstream ClientAliveCountMax behaviour
# upstream commit:
# 69334996ae203c51c70bf01d414c918a44618f8e
Patch982: openssh-8.0p1-client_alive_count_max.patch
# add a local implementation of BSD realpath() for sftp-server
# use ahead of OpenBSD's realpath changing to match POSIX
# upstream commits:
# 569b650f93b561c09c655f83f128e1dfffe74101
# 53a6ebf1445a857f5e487b18ee5e5830a9575149
# 5428b0d239f6b516c81d1dd15aa9fe9e60af75d4
Patch983: openssh-8.0p1-sftp-realpath.patch
# include caveat for crypto-policy in sshd manpage (#2044354)
Patch984: openssh-8.0p1-crypto-policy-doc.patch
# minimize the use of SHA1 as a proof of possession for RSA key (#2093897)
# upstream commits:
# 291721bc7c840d113a49518f3fca70e86248b8e8
# 0fa33683223c76289470a954404047bc762be84c
# f8df0413f0a057b6a3d3dd7bd8bc7c5d80911d3a
Patch985: openssh-8.7p1-minimize-sha1-use.patch
# Upstream ff89b1bed80721295555bd083b173247a9c0484e
Patch986: openssh-9.1p1-sshbanner.patch
# Upstream 25e3bccbaa63d27b9d5e09c123f1eb28594d2bd6
Patch987: openssh-8.0p1-ipv6-process.patch
# Upstream 4332b4fe49360679647a8705bc08f4e81323f6b4
Patch988: openssh-8.0p1-avoidkillall.patch
# Upstream 89b54900ac61986760452f132bbe3fb7249cfdac
Patch989: openssh-8.0p1-bigsshdconfig.patch
# upsream commit
# b23fe83f06ee7e721033769cfa03ae840476d280
Patch1015: openssh-9.3p1-upstream-cve-2023-38408.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
# SCP kill switch
Patch1020: openssh-8.7p1-scp-kill-switch.patch
#upstream commit 96faa0de6c673a2ce84736eba37fc9fb723d9e5c
Patch1021: openssh-8.0p1-upstream-ignore-SIGPIPE.patch
# This is the patch that adds GSI support
# Based on hpn_isshd-gsi.7.5p1b.patch from Globus upstream
Patch98: openssh-7.8p1-gsissh.patch
Patch98: openssh-8.0p1-gsissh.patch
# This is the HPN patch
# Based on https://github.com/rapier1/hpn-ssh/ tag: hpn-8_0_P1 (hpn14v19)
Patch99: openssh-8.0p1-hpn-14.19.patch
License: BSD
Group: Applications/Internet
@ -182,7 +260,6 @@ BuildRequires: autoconf, automake, perl-interpreter, perl-generators, zlib-devel
BuildRequires: audit-libs-devel >= 2.0.5
BuildRequires: util-linux, groff
BuildRequires: pam-devel
BuildRequires: fipscheck-devel >= 1.3.0
BuildRequires: openssl-devel >= 0.9.8j
BuildRequires: systemd-devel
BuildRequires: gcc
@ -197,7 +274,6 @@ BuildRequires: krb5-devel
BuildRequires: globus-gss-assist-devel >= 8
BuildRequires: globus-gssapi-gsi-devel >= 12.12
BuildRequires: globus-common-devel >= 14
BuildRequires: globus-usage-devel >= 3
%endif
%if %{libedit}
@ -221,7 +297,6 @@ Provides: gsissh-clients = %{version}-%{release}
Obsoletes: gsissh-clients < 5.8p2-2
Group: Applications/Internet
Requires: %{name} = %{version}-%{release}
Requires: fipscheck-lib%{_isa} >= 1.3.0
Requires: crypto-policies >= 20180306-1
%package server
@ -232,7 +307,6 @@ Group: System Environment/Daemons
Requires: %{name} = %{version}-%{release}
Requires(pre): /usr/sbin/useradd
Requires: pam >= 1.0.1-3
Requires: fipscheck-lib%{_isa} >= 1.3.0
Requires: crypto-policies >= 20180306-1
%{?systemd_requires}
@ -271,8 +345,6 @@ This version of OpenSSH has been modified to support GSI authentication.
gpgv2 --quiet --keyring %{SOURCE3} %{SOURCE1} %{SOURCE0}
%setup -q -n openssh-%{version}
# investigate %%patch102 -p1 -b .getaddrinfo
%patch400 -p1 -b .role-mls
%patch404 -p1 -b .privsep-selinux
@ -290,7 +362,6 @@ gpgv2 --quiet --keyring %{SOURCE3} %{SOURCE1} %{SOURCE0}
%patch702 -p1 -b .progress
%patch703 -p1 -b .grab-info
%patch707 -p1 -b .redhat
%patch709 -p1 -b .vendor
%patch711 -p1 -b .log-usepam-no
%patch712 -p1 -b .evp-ctr
%patch713 -p1 -b .ctr-cavs
@ -298,44 +369,74 @@ gpgv2 --quiet --keyring %{SOURCE3} %{SOURCE1} %{SOURCE0}
%patch800 -p1 -b .gsskex
%patch801 -p1 -b .force_krb
%patch803 -p1 -b .gss-docs
%patch804 -p1 -b .ccache_name
%patch805 -p1 -b .k5login
%patch900 -p1 -b .canohost
%patch901 -p1 -b .kuserok
%patch906 -p1 -b .fromto-remote
%patch916 -p1 -b .contexts
%patch918 -p1 -b .log-in-chroot
%patch919 -p1 -b .scp
%patch920 -p1 -b .config
%patch802 -p1 -b .GSSAPIEnablek5users
%patch922 -p1 -b .sshdt
%patch926 -p1 -b .sftp-force-mode
%patch929 -p1 -b .root-login
%patch932 -p1 -b .gsskexalg
%patch939 -p1 -b .s390-dev
%patch944 -p1 -b .x11max
%patch948 -p1 -b .systemd
%patch807 -p1 -b .gsskex-ec
%patch949 -p1 -b .refactor
%patch950 -p1 -b .sandbox
%patch951 -p1 -b .pkcs11-uri
%patch952 -p1 -b .pkcs11-ecdsa
%patch953 -p1 -b .scp-ipv6
%patch958 -p1 -b .ssh-copy-id
%patch961 -p1 -b .scp-tests
%patch962 -p1 -b .crypto-policies
%patch963 -p1 -b .openssl-evp
%patch964 -p1 -b .openssl-kdf
%patch965 -p1 -b .openssl-pem
%patch966 -p1 -b .entropy
%patch967 -p1 -b .keyscan
%patch968 -p1 -b .proxyjump-loops
%patch969 -p1 -b .keygen-sha2
%patch970 -p1 -b .rdomain
%patch971 -p1 -b .x11-ipv6
%patch972 -p1 -b .channel-limits
%patch973 -p1 -b .sftp-timespeccmp
%patch974 -p1 -b .keygen-strip-doseol
%patch975 -p1 -b .preserve-pam-errors
%patch976 -p1 -b .restore-nonblock
%patch977 -p1 -b .cve-2020-14145
%patch978 -p1 -b .sshd_config
%patch980 -p1 -b .cve-2021-41617
%patch981 -p1 -b .sshdinclude
%patch982 -p1 -b .client_alive_count_max
%patch983 -p1 -b .sftp-realpath
%patch984 -p1 -b .crypto-policy-doc
%patch985 -p1 -b .minimize-sha1-use
%patch986 -p1 -b .banner
%patch987 -p1 -b .sftp_ipv6
%patch988 -p1 -b .killall
%patch989 -p1 -b .bigsshdconfig
%patch200 -p1 -b .audit
%patch201 -p1 -b .audit-race
%patch700 -p1 -b .fips
%patch100 -p1 -b .coverity
%patch104 -p1 -b .openssl
%patch1015 -p1 -b .cve-2023-38408
%patch1017 -p1 -b .limitdelay
%patch1018 -p1 -b .cve-2023-48795
%patch1019 -p1 -b .cve-2023-51385
%patch1020 -p1 -b .scp-kill-switch
%patch1021 -p1 -b .ignore-SIGPIPE
%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/ssh!/etc/pam.d/gsisshd!' -i sshd_config
cp -p %{SOURCE99} .
@ -375,10 +476,9 @@ fi
--sysconfdir=%{_sysconfdir}/gsissh \
--libexecdir=%{_libexecdir}/gsissh \
--datadir=%{_datadir}/gsissh \
--with-default-path=/usr/local/bin:/usr/bin \
--with-superuser-path=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin \
--with-privsep-path=%{_var}/empty/gsisshd \
--enable-vendor-patchlevel="FC-%{openssh_ver}-%{openssh_rel}" \
--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=%{_var}/empty/sshd \
--disable-strip \
--without-zlib-version-check \
--with-ssl-engine \
@ -391,6 +491,7 @@ fi
--with-ldap \
%endif
--with-pam \
--with-pam-service=gsisshd \
%if %{WITH_SELINUX}
--with-selinux --with-audit=linux \
--with-sandbox=seccomp_filter \
@ -414,27 +515,18 @@ fi
make SSH_PROGRAM=%{_bindir}/gsissh \
ASKPASS_PROGRAM=%{_libexecdir}/openssh/ssh-askpass
# Add generation of HMAC checksums of the final stripped binaries
%global __spec_install_post \
%%{?__debug_package:%%{__debug_install_post}} \
%%{__arch_install_post} \
%%{__os_install_post} \
fipshmac -d $RPM_BUILD_ROOT%{_libdir}/fipscheck $RPM_BUILD_ROOT%{_bindir}/gsissh $RPM_BUILD_ROOT%{_sbindir}/gsisshd \
%{nil}
%install
rm -rf $RPM_BUILD_ROOT
mkdir -p -m755 $RPM_BUILD_ROOT%{_sysconfdir}/gsissh
mkdir -p -m755 $RPM_BUILD_ROOT%{_sysconfdir}/gsissh/ssh_config.d
mkdir -p -m755 $RPM_BUILD_ROOT%{_libexecdir}/gsissh
mkdir -p -m755 $RPM_BUILD_ROOT%{_var}/empty/gsisshd
mkdir -p -m755 $RPM_BUILD_ROOT%{_var}/empty/sshd
make install DESTDIR=$RPM_BUILD_ROOT
rm -f $RPM_BUILD_ROOT%{_sysconfdir}/gsissh/ldap.conf
install -d $RPM_BUILD_ROOT/etc/pam.d/
install -d $RPM_BUILD_ROOT/etc/sysconfig/
install -d $RPM_BUILD_ROOT%{_libexecdir}/gsissh
install -d $RPM_BUILD_ROOT%{_libdir}/fipscheck
install -m644 %{SOURCE2} $RPM_BUILD_ROOT/etc/pam.d/gsisshd
install -m644 %{SOURCE7} $RPM_BUILD_ROOT/etc/sysconfig/gsisshd
install -m644 ssh_config_redhat $RPM_BUILD_ROOT/etc/gsissh/ssh_config.d/05-redhat.conf
@ -470,6 +562,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
@ -491,19 +588,18 @@ getent passwd sshd >/dev/null || \
%systemd_postun_with_restart gsisshd.service
%files
%license LICENCE LICENSE.globus_usage
%doc CREDITS ChangeLog INSTALL OVERVIEW PROTOCOL* README README.platform README.privsep README.tun README.dns README.sshd-and-gsisshd TODO
%license LICENCE
%doc CREDITS ChangeLog INSTALL OVERVIEW PROTOCOL* README HPN-README README.platform README.privsep README.tun README.dns README.sshd-and-gsisshd TODO
%attr(0755,root,root) %dir %{_sysconfdir}/gsissh
%attr(0644,root,root) %config(noreplace) %{_sysconfdir}/gsissh/moduli
%attr(0755,root,root) %{_bindir}/gsissh-keygen
%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*
%files clients
%attr(0755,root,root) %{_bindir}/gsissh
%attr(0644,root,root) %{_libdir}/fipscheck/gsissh.hmac
%attr(0644,root,root) %{_mandir}/man1/gsissh.1*
%attr(0755,root,root) %{_bindir}/gsiscp
%attr(0644,root,root) %{_mandir}/man1/gsiscp.1*
@ -513,11 +609,12 @@ getent passwd sshd >/dev/null || \
%attr(0644,root,root) %{_mandir}/man5/gsissh_config.5*
%attr(0755,root,root) %{_bindir}/gsisftp
%attr(0644,root,root) %{_mandir}/man1/gsisftp.1*
%attr(0755,root,root) %dir %{_libexecdir}/gsissh/bin
%{_libexecdir}/gsissh/bin/scp
%files server
%dir %attr(0711,root,root) %{_var}/empty/gsisshd
%dir %attr(0711,root,root) %{_var}/empty/sshd
%attr(0755,root,root) %{_sbindir}/gsisshd
%attr(0644,root,root) %{_libdir}/fipscheck/gsisshd.hmac
%attr(0755,root,root) %{_libexecdir}/gsissh/sftp-server
%attr(0755,root,root) %{_libexecdir}/gsissh/sshd-keygen
%attr(0644,root,root) %{_mandir}/man5/gsisshd_config.5*
@ -535,6 +632,70 @@ getent passwd sshd >/dev/null || \
%attr(0644,root,root) %{_tmpfilesdir}/gsissh.conf
%changelog
* Wed Oct 02 2024 Mattias Ellert <mattias.ellert@physics.uu.se> - 8.0p1-16
- Based on openssh-8.0p1-25.el8_10
* Fri Jul 12 2024 Mattias Ellert <mattias.ellert@physics.uu.se> - 8.0p1-15
- Add scp symlink in gsisshd's path
* Tue Jul 09 2024 Mattias Ellert <mattias.ellert@physics.uu.se> - 8.0p1-14
- Based on openssh-8.0p1-24.el8
- Drop patch openssh-8.0p1-sshbuf-readonly.patch (now included in
openssh-8.0p1-gssapi-keyex.patch)
* Fri Aug 11 2023 Mattias Ellert <mattias.ellert@physics.uu.se> - 8.0p1-13
- Based on openssh-8.0p1-19.el8_8
* Sat Mar 11 2023 Mattias Ellert <mattias.ellert@physics.uu.se> - 8.0p1-12
- Based on openssh-8.0p1-17.el8_7
* Wed Oct 05 2022 Mattias Ellert <mattias.ellert@physics.uu.se> - 8.0p1-11
- Based on openssh-8.0p1-16.el8
* Tue Aug 09 2022 Mattias Ellert <mattias.ellert@physics.uu.se> - 8.0p1-10
- Based on openssh-8.0p1-13.el8
* Wed Nov 24 2021 Mattias Ellert <mattias.ellert@physics.uu.se> - 8.0p1-9
- Based on openssh-8.0p1-10.el8
* Sat May 22 2021 Mattias Ellert <mattias.ellert@physics.uu.se> - 8.0p1-8
- Based on openssh-8.0p1-6.el8_4.2
* Tue Mar 16 2021 Mattias Ellert <mattias.ellert@physics.uu.se> - 8.0p1-7
- Fix issue with read-only ssh buffer during gssapi key exchange
- Clean up HPN patch
* Mon Nov 30 2020 Mattias Ellert <mattias.ellert@physics.uu.se> - 8.0p1-6
- Based on openssh-8.0p1-5.el8
* Fri Oct 23 2020 Frank Scheiner <scheiner@hlrs.de> - 8.0p1-5
- Update HPN patch with additional documentation and configuration and a
version number fix
* Fri Sep 25 2020 Frank Scheiner <scheiner@hlrs.de> - 8.0p1-4
- Add HPN patch
* Mon May 04 2020 Mattias Ellert <mattias.ellert@physics.uu.se> - 8.0p1-3
- Add missing buffer initialization in gsissh patch
* Tue Apr 14 2020 Mattias Ellert <mattias.ellert@physics.uu.se> - 8.0p1-2
- Based on openssh-8.0p1-4.el8
* Wed Jan 08 2020 Mattias Ellert <mattias.ellert@physics.uu.se> - 8.0p1-1
- Based on openssh-8.0p1-3.el8
* Mon Aug 19 2019 Mattias Ellert <mattias.ellert@physics.uu.se> - 7.8p1-5
- Based on openssh-7.8p1-4.el8
* Wed Feb 27 2019 Mattias Ellert <mattias.ellert@physics.uu.se> - 7.8p1-4
- Remove usage statistics collection support
* Fri Feb 08 2019 Mattias Ellert <mattias.ellert@physics.uu.se> - 7.8p1-3
- CVE-2019-7639
* Tue Jan 15 2019 Mattias Ellert <mattias.ellert@physics.uu.se> - 7.8p1-2
- Based on openssh-7.8p1-4.fc28
* Tue Oct 23 2018 Mattias Ellert <mattias.ellert@physics.uu.se> - 7.8p1-1
- Based on openssh-7.8p1-3.fc28

View file

@ -6,6 +6,12 @@
# of DSA key or systemctl mask gsisshd-keygen@rsa.service to disable RSA key
# creation.
# Do not change this option unless you have hardware random
# generator and you REALLY know what you are doing
SSH_USE_STRONG_RNG=0
# SSH_USE_STRONG_RNG=1
# System-wide crypto policy:
# To opt-out, uncomment the following line
# CRYPTO_POLICY=

View file

@ -1,24 +0,0 @@
diff -up openssh-5.6p1/channels.c.getaddrinfo openssh-5.6p1/channels.c
--- openssh-5.6p1/channels.c.getaddrinfo 2012-02-14 16:12:54.427852524 +0100
+++ openssh-5.6p1/channels.c 2012-02-14 16:13:22.818928690 +0100
@@ -3275,6 +3275,9 @@ x11_create_display_inet(int x11_display_
memset(&hints, 0, sizeof(hints));
hints.ai_family = IPv4or6;
hints.ai_flags = x11_use_localhost ? 0: AI_PASSIVE;
+#ifdef AI_ADDRCONFIG
+ hints.ai_flags |= AI_ADDRCONFIG;
+#endif
hints.ai_socktype = SOCK_STREAM;
snprintf(strport, sizeof strport, "%d", port);
if ((gaierr = getaddrinfo(NULL, strport, &hints, &aitop)) != 0) {
diff -up openssh-5.6p1/sshconnect.c.getaddrinfo openssh-5.6p1/sshconnect.c
--- openssh-5.6p1/sshconnect.c.getaddrinfo 2012-02-14 16:09:25.057964291 +0100
+++ openssh-5.6p1/sshconnect.c 2012-02-14 16:09:25.106047007 +0100
@@ -343,6 +343,7 @@ ssh_connect(const char *host, struct soc
memset(&hints, 0, sizeof(hints));
hints.ai_family = family;
hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_V4MAPPED | AI_ADDRCONFIG;
snprintf(strport, sizeof strport, "%u", port);
if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0)
fatal("%s: Could not resolve hostname %.100s: %s", __progname,

View file

@ -1,21 +0,0 @@
diff -up openssh-6.1p1/sshconnect2.c.canohost openssh-6.1p1/sshconnect2.c
--- openssh-6.1p1/sshconnect2.c.canohost 2012-10-30 10:52:59.593301692 +0100
+++ openssh-6.1p1/sshconnect2.c 2012-10-30 11:01:12.870301632 +0100
@@ -699,12 +699,15 @@ userauth_gssapi(Authctxt *authctxt)
static u_int mech = 0;
OM_uint32 min;
int r, ok = 0;
- const char *gss_host;
+ const char *gss_host = NULL;
if (options.gss_server_identity)
gss_host = options.gss_server_identity;
- else if (options.gss_trust_dns)
+ else if (options.gss_trust_dns) {
gss_host = get_canonical_hostname(active_state, 1);
+ if (strcmp(gss_host, "UNKNOWN") == 0)
+ gss_host = authctxt->host;
+ }
else
gss_host = authctxt->host;

View file

@ -1,142 +0,0 @@
diff -up openssh-7.4p1/configure.ac.vendor openssh-7.4p1/configure.ac
--- openssh-7.4p1/configure.ac.vendor 2016-12-23 13:34:51.681253844 +0100
+++ openssh-7.4p1/configure.ac 2016-12-23 13:34:51.694253847 +0100
@@ -4930,6 +4930,12 @@ AC_ARG_WITH([lastlog],
fi
]
)
+AC_ARG_ENABLE(vendor-patchlevel,
+ [ --enable-vendor-patchlevel=TAG specify a vendor patch level],
+ [AC_DEFINE_UNQUOTED(SSH_VENDOR_PATCHLEVEL,[SSH_RELEASE "-" "$enableval"],[Define to your vendor patch level, if it has been modified from the upstream source release.])
+ SSH_VENDOR_PATCHLEVEL="$enableval"],
+ [AC_DEFINE(SSH_VENDOR_PATCHLEVEL,SSH_RELEASE,[Define to your vendor patch level, if it has been modified from the upstream source release.])
+ SSH_VENDOR_PATCHLEVEL=none])
dnl lastlog, [uw]tmpx? detection
dnl NOTE: set the paths in the platform section to avoid the
@@ -5194,6 +5200,7 @@ echo " Translate v4 in v6 hack
echo " BSD Auth support: $BSD_AUTH_MSG"
echo " Random number source: $RAND_MSG"
echo " Privsep sandbox style: $SANDBOX_STYLE"
+echo " Vendor patch level: $SSH_VENDOR_PATCHLEVEL"
echo ""
diff -up openssh-7.4p1/servconf.c.vendor openssh-7.4p1/servconf.c
--- openssh-7.4p1/servconf.c.vendor 2016-12-19 05:59:41.000000000 +0100
+++ openssh-7.4p1/servconf.c 2016-12-23 13:36:07.555268628 +0100
@@ -143,6 +143,7 @@ initialize_server_options(ServerOptions
options->max_authtries = -1;
options->max_sessions = -1;
options->banner = NULL;
+ options->show_patchlevel = -1;
options->use_dns = -1;
options->client_alive_interval = -1;
options->client_alive_count_max = -1;
@@ -325,6 +326,8 @@ fill_default_server_options(ServerOption
options->ip_qos_bulk = IPTOS_DSCP_CS1;
if (options->version_addendum == NULL)
options->version_addendum = xstrdup("");
+ if (options->show_patchlevel == -1)
+ options->show_patchlevel = 0;
if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1)
options->fwd_opts.streamlocal_bind_mask = 0177;
if (options->fwd_opts.streamlocal_bind_unlink == -1)
@@ -402,7 +405,7 @@ typedef enum {
sIgnoreUserKnownHosts, sCiphers, sMacs, sPidFile,
sGatewayPorts, sPubkeyAuthentication, sPubkeyAcceptedKeyTypes,
sXAuthLocation, sSubsystem, sMaxStartups, sMaxAuthTries, sMaxSessions,
- sBanner, sUseDNS, sHostbasedAuthentication,
+ sBanner, sShowPatchLevel, sUseDNS, sHostbasedAuthentication,
sHostbasedUsesNameFromPacketOnly, sHostbasedAcceptedKeyTypes,
sHostKeyAlgorithms,
sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile,
@@ -528,6 +531,7 @@ static struct {
{ "maxauthtries", sMaxAuthTries, SSHCFG_ALL },
{ "maxsessions", sMaxSessions, SSHCFG_ALL },
{ "banner", sBanner, SSHCFG_ALL },
+ { "showpatchlevel", sShowPatchLevel, SSHCFG_GLOBAL },
{ "usedns", sUseDNS, SSHCFG_GLOBAL },
{ "verifyreversemapping", sDeprecated, SSHCFG_GLOBAL },
{ "reversemappingcheck", sDeprecated, SSHCFG_GLOBAL },
@@ -1369,6 +1373,10 @@ process_server_config_line(ServerOptions
intptr = &options->disable_forwarding;
goto parse_flag;
+ case sShowPatchLevel:
+ intptr = &options->show_patchlevel;
+ goto parse_flag;
+
case sAllowUsers:
while ((arg = strdelim(&cp)) && *arg != '\0') {
if (match_user(NULL, NULL, NULL, arg) == -1)
@@ -2269,6 +2277,7 @@ dump_config(ServerOptions *o)
dump_cfg_fmtint(sEmptyPasswd, o->permit_empty_passwd);
dump_cfg_fmtint(sCompression, o->compression);
dump_cfg_fmtint(sGatewayPorts, o->fwd_opts.gateway_ports);
+ dump_cfg_fmtint(sShowPatchLevel, o->show_patchlevel);
dump_cfg_fmtint(sUseDNS, o->use_dns);
dump_cfg_fmtint(sAllowTcpForwarding, o->allow_tcp_forwarding);
dump_cfg_fmtint(sAllowAgentForwarding, o->allow_agent_forwarding);
diff -up openssh-7.4p1/servconf.h.vendor openssh-7.4p1/servconf.h
--- openssh-7.4p1/servconf.h.vendor 2016-12-19 05:59:41.000000000 +0100
+++ openssh-7.4p1/servconf.h 2016-12-23 13:34:51.694253847 +0100
@@ -149,6 +149,7 @@ typedef struct {
int max_authtries;
int max_sessions;
char *banner; /* SSH-2 banner message */
+ int show_patchlevel; /* Show vendor patch level to clients */
int use_dns;
int client_alive_interval; /*
* poke the client this often to
diff -up openssh-7.4p1/sshd_config.5.vendor openssh-7.4p1/sshd_config.5
--- openssh-7.4p1/sshd_config.5.vendor 2016-12-23 13:34:51.695253847 +0100
+++ openssh-7.4p1/sshd_config.5 2016-12-23 13:37:17.482282253 +0100
@@ -1334,6 +1334,13 @@ an OpenSSH Key Revocation List (KRL) as
.Cm AcceptEnv
or
.Cm PermitUserEnvironment .
+.It Cm ShowPatchLevel
+Specifies whether
+.Nm sshd
+will display the patch level of the binary in the identification string.
+The patch level is set at compile-time.
+The default is
+.Dq no .
.It Cm StreamLocalBindMask
Sets the octal file creation mode mask
.Pq umask
diff -up openssh-7.4p1/sshd_config.vendor openssh-7.4p1/sshd_config
--- openssh-7.4p1/sshd_config.vendor 2016-12-23 13:34:51.690253846 +0100
+++ openssh-7.4p1/sshd_config 2016-12-23 13:34:51.695253847 +0100
@@ -105,6 +105,7 @@ X11Forwarding yes
#Compression delayed
#ClientAliveInterval 0
#ClientAliveCountMax 3
+#ShowPatchLevel no
#UseDNS no
#PidFile /var/run/sshd.pid
#MaxStartups 10:30:100
diff -up openssh-7.4p1/sshd.c.vendor openssh-7.4p1/sshd.c
--- openssh-7.4p1/sshd.c.vendor 2016-12-23 13:34:51.682253844 +0100
+++ openssh-7.4p1/sshd.c 2016-12-23 13:38:32.434296856 +0100
@@ -367,7 +367,8 @@ sshd_exchange_identification(struct ssh
char remote_version[256]; /* Must be at least as big as buf. */
xasprintf(&server_version_string, "SSH-%d.%d-%.100s%s%s\r\n",
- PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, SSH_VERSION,
+ PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2,
+ (options.show_patchlevel == 1) ? SSH_VENDOR_PATCHLEVEL : SSH_VERSION,
*options.version_addendum == '\0' ? "" : " ",
options.version_addendum);
@@ -1650,7 +1651,8 @@ main(int ac, char **av)
exit(1);
}
- debug("sshd version %s, %s", SSH_VERSION,
+ debug("sshd version %s, %s",
+ (options.show_patchlevel == 1) ? SSH_VENDOR_PATCHLEVEL : SSH_VERSION,
#ifdef WITH_OPENSSL
SSLeay_version(SSLEAY_VERSION)
#else

View file

@ -46,7 +46,7 @@ diff -up openssh-7.4p1/monitor.c.log-in-chroot openssh-7.4p1/monitor.c
+ pmonitor->m_state = "preauth";
+
authctxt = _authctxt;
authctxt = (Authctxt *)ssh->authctxt;
memset(authctxt, 0, sizeof(*authctxt));
ssh->authctxt = authctxt;
@@ -405,6 +407,8 @@ monitor_child_postauth(struct monitor *p
@ -113,7 +113,7 @@ diff -up openssh-7.4p1/monitor.h.log-in-chroot openssh-7.4p1/monitor.h
+void monitor_reinit(struct monitor *, const char *);
struct Authctxt;
void monitor_child_preauth(struct Authctxt *, struct monitor *);
void monitor_child_preauth(struct ssh *, struct monitor *);
diff -up openssh-7.4p1/session.c.log-in-chroot openssh-7.4p1/session.c
--- openssh-7.4p1/session.c.log-in-chroot 2016-12-23 15:14:33.319168086 +0100
+++ openssh-7.4p1/session.c 2016-12-23 15:18:18.742211853 +0100

View file

@ -19,7 +19,7 @@ index 8f32464..18a2ca4 100644
if (!sshd_selinux_enabled())
return;
@@ -461,6 +462,58 @@ sshd_selinux_copy_context(void)
@@ -461,6 +462,72 @@ sshd_selinux_copy_context(void)
}
}
@ -30,46 +30,60 @@ index 8f32464..18a2ca4 100644
+ char line[1024], *preauth_context = NULL, *cp, *arg;
+ const char *contexts_path;
+ FILE *contexts_file;
+ struct stat sb;
+
+ contexts_path = selinux_openssh_contexts_path();
+ if (contexts_path != NULL) {
+ if ((contexts_file = fopen(contexts_path, "r")) != NULL) {
+ struct stat sb;
+
+ if (fstat(fileno(contexts_file), &sb) == 0 && ((sb.st_uid == 0) && ((sb.st_mode & 022) == 0))) {
+ while (fgets(line, sizeof(line), contexts_file)) {
+ /* Strip trailing whitespace */
+ for (len = strlen(line) - 1; len > 0; len--) {
+ if (strchr(" \t\r\n", line[len]) == NULL)
+ break;
+ line[len] = '\0';
+ }
+
+ if (line[0] == '\0')
+ continue;
+
+ cp = line;
+ arg = strdelim(&cp);
+ if (arg && *arg == '\0')
+ arg = strdelim(&cp);
+
+ if (arg && strcmp(arg, "privsep_preauth") == 0) {
+ arg = strdelim(&cp);
+ if (!arg || *arg == '\0') {
+ debug("%s: privsep_preauth is empty", __func__);
+ fclose(contexts_file);
+ return;
+ }
+ preauth_context = xstrdup(arg);
+ }
+ }
+ }
+ fclose(contexts_file);
+ }
+ if (contexts_path == NULL) {
+ debug3("%s: Failed to get the path to SELinux context", __func__);
+ return;
+ }
+
+ if (preauth_context == NULL)
+ preauth_context = xstrdup("sshd_net_t");
+ if ((contexts_file = fopen(contexts_path, "r")) == NULL) {
+ debug("%s: Failed to open SELinux context file", __func__);
+ return;
+ }
+
+ if (fstat(fileno(contexts_file), &sb) != 0 ||
+ sb.st_uid != 0 || (sb.st_mode & 022) != 0) {
+ logit("%s: SELinux context file needs to be owned by root"
+ " and not writable by anyone else", __func__);
+ fclose(contexts_file);
+ return;
+ }
+
+ while (fgets(line, sizeof(line), contexts_file)) {
+ /* Strip trailing whitespace */
+ for (len = strlen(line) - 1; len > 0; len--) {
+ if (strchr(" \t\r\n", line[len]) == NULL)
+ break;
+ line[len] = '\0';
+ }
+
+ if (line[0] == '\0')
+ continue;
+
+ cp = line;
+ arg = strdelim(&cp);
+ if (arg && *arg == '\0')
+ arg = strdelim(&cp);
+
+ if (arg && strcmp(arg, "privsep_preauth") == 0) {
+ arg = strdelim(&cp);
+ if (!arg || *arg == '\0') {
+ debug("%s: privsep_preauth is empty", __func__);
+ fclose(contexts_file);
+ return;
+ }
+ preauth_context = xstrdup(arg);
+ }
+ }
+ fclose(contexts_file);
+
+ if (preauth_context == NULL) {
+ debug("%s: Unable to find 'privsep_preauth' option in"
+ " SELinux context file", __func__);
+ return;
+ }
+
+ ssh_selinux_change_context(preauth_context);
+ free(preauth_context);
@ -82,14 +96,6 @@ diff --git a/openbsd-compat/port-linux.c b/openbsd-compat/port-linux.c
index 22ea8ef..1fc963d 100644
--- a/openbsd-compat/port-linux.c
+++ b/openbsd-compat/port-linux.c
@@ -26,6 +26,7 @@
#include <stdarg.h>
#include <string.h>
#include <stdio.h>
+#include <stdlib.h>
#include "log.h"
#include "xmalloc.h"
@@ -179,7 +179,7 @@ ssh_selinux_change_context(const char *newname)
strlcpy(newctx + len, newname, newlen - len);
if ((cx = index(cx + 1, ':')))

View file

@ -22,15 +22,15 @@ diff -up openssh-7.4p1/servconf.c.GSSAPIEnablek5users openssh-7.4p1/servconf.c
--- openssh-7.4p1/servconf.c.GSSAPIEnablek5users 2016-12-23 15:18:40.615216100 +0100
+++ openssh-7.4p1/servconf.c 2016-12-23 15:35:36.354401156 +0100
@@ -168,6 +168,7 @@ initialize_server_options(ServerOptions
options->gss_strict_acceptor = -1;
options->gss_store_rekey = -1;
options->gss_kex_algorithms = NULL;
options->use_kuserok = -1;
+ options->enable_k5users = -1;
options->password_authentication = -1;
options->kbd_interactive_authentication = -1;
options->challenge_response_authentication = -1;
@@ -345,6 +346,8 @@ fill_default_server_options(ServerOption
options->gss_store_rekey = 0;
#endif
if (options->use_kuserok == -1)
options->use_kuserok = 1;
+ if (options->enable_k5users == -1)
@ -44,20 +44,22 @@ diff -up openssh-7.4p1/servconf.c.GSSAPIEnablek5users openssh-7.4p1/servconf.c
sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile,
- sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor,
+ sGssAuthentication, sGssCleanupCreds, sGssEnablek5users, sGssStrictAcceptor,
sGssKeyEx, sGssStoreRekey, sAcceptEnv, sSetEnv, sPermitTunnel,
sGssKeyEx, sGssKexAlgorithms, sGssStoreRekey,
sAcceptEnv, sSetEnv, sPermitTunnel,
sMatch, sPermitOpen, sPermitListen, sForceCommand, sChrootDirectory,
sUsePrivilegeSeparation, sAllowAgentForwarding,
@@ -497,12 +500,14 @@ static struct {
{ "gssapistrictacceptorcheck", sGssStrictAcceptor, SSHCFG_GLOBAL },
@@ -497,14 +500,16 @@ static struct {
{ "gssapikeyexchange", sGssKeyEx, SSHCFG_GLOBAL },
{ "gssapistorecredentialsonrekey", sGssStoreRekey, SSHCFG_GLOBAL },
{ "gssapikexalgorithms", sGssKexAlgorithms, SSHCFG_GLOBAL },
+ { "gssapienablek5users", sGssEnablek5users, SSHCFG_ALL },
#else
{ "gssapiauthentication", sUnsupported, SSHCFG_ALL },
{ "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL },
{ "gssapicleanupcreds", sUnsupported, SSHCFG_GLOBAL },
{ "gssapistrictacceptorcheck", sUnsupported, SSHCFG_GLOBAL },
{ "gssapikeyexchange", sUnsupported, SSHCFG_GLOBAL },
{ "gssapistorecredentialsonrekey", sUnsupported, SSHCFG_GLOBAL },
{ "gssapikexalgorithms", sUnsupported, SSHCFG_GLOBAL },
+ { "gssapienablek5users", sUnsupported, SSHCFG_ALL },
#endif
{ "gssusesessionccache", sUnsupported, SSHCFG_GLOBAL },
@ -83,7 +85,7 @@ diff -up openssh-7.4p1/servconf.c.GSSAPIEnablek5users openssh-7.4p1/servconf.c
M_CP_INTOPT(log_level);
@@ -2320,6 +2330,7 @@ dump_config(ServerOptions *o)
# endif
dump_cfg_fmtint(sKerberosUniqueTicket, o->kerberos_unique_ticket);
dump_cfg_fmtint(sKerberosUniqueCCache, o->kerberos_unique_ccache);
dump_cfg_fmtint(sKerberosUseKuserok, o->use_kuserok);
+ dump_cfg_fmtint(sGssEnablek5users, o->enable_k5users);
#endif
@ -93,7 +95,7 @@ diff -up openssh-7.4p1/servconf.h.GSSAPIEnablek5users openssh-7.4p1/servconf.h
--- openssh-7.4p1/servconf.h.GSSAPIEnablek5users 2016-12-23 15:18:40.616216100 +0100
+++ openssh-7.4p1/servconf.h 2016-12-23 15:18:40.629216102 +0100
@@ -174,6 +174,7 @@ typedef struct {
int kerberos_unique_ticket; /* If true, the aquired ticket will
int kerberos_unique_ccache; /* If true, the acquired ticket will
* be stored in per-session ccache */
int use_kuserok;
+ int enable_k5users;

View file

@ -20,10 +20,10 @@ diff -up openssh-6.8p1/Makefile.in.ctr-cavs openssh-6.8p1/Makefile.in
ssh-xmss.o \
@@ -194,6 +195,9 @@ ssh-ldap-helper$(EXEEXT): $(LIBCOMPAT) l
ssh-keycat$(EXEEXT): $(LIBCOMPAT) $(SSHDOBJS) libssh.a ssh-keycat.o uidswap.o
$(LD) -o $@ ssh-keycat.o uidswap.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(KEYCATLIBS) $(LIBS)
$(LD) -o $@ ssh-keycat.o uidswap.o $(LDFLAGS) -lssh -lopenbsd-compat $(KEYCATLIBS) $(LIBS)
+ctr-cavstest$(EXEEXT): $(LIBCOMPAT) libssh.a ctr-cavstest.o
+ $(LD) -o $@ ctr-cavstest.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lfipscheck $(LIBS)
+ $(LD) -o $@ ctr-cavstest.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS)
+
ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keyscan.o
$(LD) -o $@ ssh-keyscan.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS)
@ -187,7 +187,7 @@ diff -up openssh-6.8p1/ctr-cavstest.c.ctr-cavs openssh-6.8p1/ctr-cavstest.c
+ usage();
+ }
+
+ SSLeay_add_all_algorithms();
+ OpenSSL_add_all_algorithms();
+
+ c = cipher_by_name(algo);
+ if (c == NULL) {

View file

@ -235,9 +235,9 @@ index 28659ec..9c94d8e 100644
+#endif
+#endif
+
s->forced = 0;
if (forced != NULL) {
if (IS_INTERNAL_SFTP(command)) {
s->is_subsystem = s->is_subsystem ?
s->forced = 1;
diff --git a/ssh-gss.h b/ssh-gss.h
index 0374c88..509109a 100644
--- a/ssh-gss.h

View file

@ -62,10 +62,10 @@ diff -up openssh/Makefile.in.keycat openssh/Makefile.in
ssh-xmss.o \
@@ -190,6 +191,9 @@ ssh-pkcs11-helper$(EXEEXT): $(LIBCOMPAT)
ssh-ldap-helper$(EXEEXT): $(LIBCOMPAT) libssh.a ldapconf.o ldapbody.o ldapmisc.o ldap-helper.o
$(LD) -o $@ ldapconf.o ldapbody.o ldapmisc.o ldap-helper.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat -lfipscheck $(LIBS) $(LDAPLIBS)
$(LD) -o $@ ldapconf.o ldapbody.o ldapmisc.o ldap-helper.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS) $(LDAPLIBS)
+ssh-keycat$(EXEEXT): $(LIBCOMPAT) $(SSHDOBJS) libssh.a ssh-keycat.o uidswap.o
+ $(LD) -o $@ ssh-keycat.o uidswap.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(KEYCATLIBS) $(LIBS)
+ $(LD) -o $@ ssh-keycat.o uidswap.o $(LDFLAGS) -lssh -lopenbsd-compat $(KEYCATLIBS) $(LIBS)
+
ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keyscan.o
$(LD) -o $@ ssh-keyscan.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS)

View file

@ -176,17 +176,17 @@ diff -up openssh-7.4p1/servconf.c.kuserok openssh-7.4p1/servconf.c
--- openssh-7.4p1/servconf.c.kuserok 2016-12-23 14:36:07.630465944 +0100
+++ openssh-7.4p1/servconf.c 2016-12-23 15:11:52.278133344 +0100
@@ -116,6 +116,7 @@ initialize_server_options(ServerOptions
options->gss_cleanup_creds = -1;
options->gss_strict_acceptor = -1;
options->gss_store_rekey = -1;
options->gss_kex_algorithms = NULL;
+ options->use_kuserok = -1;
options->password_authentication = -1;
options->kbd_interactive_authentication = -1;
options->challenge_response_authentication = -1;
@@ -278,6 +279,8 @@ fill_default_server_options(ServerOption
options->gss_strict_acceptor = 1;
if (options->gss_store_rekey == -1)
options->gss_store_rekey = 0;
if (options->gss_kex_algorithms == NULL)
options->gss_kex_algorithms = strdup(GSS_KEX_DEFAULT_KEX);
#endif
+ if (options->use_kuserok == -1)
+ options->use_kuserok = 1;
if (options->password_authentication == -1)
@ -196,22 +196,22 @@ diff -up openssh-7.4p1/servconf.c.kuserok openssh-7.4p1/servconf.c
sPermitRootLogin, sLogFacility, sLogLevel,
sRhostsRSAAuthentication, sRSAAuthentication,
sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup,
- sKerberosGetAFSToken, sKerberosUniqueTicket,
+ sKerberosGetAFSToken, sKerberosUniqueTicket, sKerberosUseKuserok,
- sKerberosGetAFSToken, sKerberosUniqueCCache,
+ sKerberosGetAFSToken, sKerberosUniqueCCache, sKerberosUseKuserok,
sChallengeResponseAuthentication,
sPasswordAuthentication, sKbdInteractiveAuthentication,
sListenAddress, sAddressFamily,
@@ -478,12 +481,14 @@ static struct {
{ "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL },
#endif
{ "kerberosuniqueticket", sKerberosUniqueTicket, SSHCFG_GLOBAL },
{ "kerberosuniqueccache", sKerberosUniqueCCache, SSHCFG_GLOBAL },
+ { "kerberosusekuserok", sKerberosUseKuserok, SSHCFG_ALL },
#else
{ "kerberosauthentication", sUnsupported, SSHCFG_ALL },
{ "kerberosorlocalpasswd", sUnsupported, SSHCFG_GLOBAL },
{ "kerberosticketcleanup", sUnsupported, SSHCFG_GLOBAL },
{ "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL },
{ "kerberosuniqueticket", sUnsupported, SSHCFG_GLOBAL },
{ "kerberosuniqueccache", sUnsupported, SSHCFG_GLOBAL },
+ { "kerberosusekuserok", sUnsupported, SSHCFG_ALL },
#endif
{ "kerberostgtpassing", sUnsupported, SSHCFG_GLOBAL },
@ -238,7 +238,7 @@ diff -up openssh-7.4p1/servconf.c.kuserok openssh-7.4p1/servconf.c
@@ -2309,6 +2319,7 @@ dump_config(ServerOptions *o)
dump_cfg_fmtint(sKerberosGetAFSToken, o->kerberos_get_afs_token);
# endif
dump_cfg_fmtint(sKerberosUniqueTicket, o->kerberos_unique_ticket);
dump_cfg_fmtint(sKerberosUniqueCCache, o->kerberos_unique_ccache);
+ dump_cfg_fmtint(sKerberosUseKuserok, o->use_kuserok);
#endif
#ifdef GSSAPI
@ -248,7 +248,7 @@ diff -up openssh-7.4p1/servconf.h.kuserok openssh-7.4p1/servconf.h
+++ openssh-7.4p1/servconf.h 2016-12-23 14:36:07.645465936 +0100
@@ -118,6 +118,7 @@ typedef struct {
* authenticated with Kerberos. */
int kerberos_unique_ticket; /* If true, the aquired ticket will
int kerberos_unique_ccache; /* If true, the acquired ticket will
* be stored in per-session ccache */
+ int use_kuserok;
int gss_authentication; /* If true, permit GSSAPI authentication */
@ -258,9 +258,9 @@ diff -up openssh-7.4p1/sshd_config.5.kuserok openssh-7.4p1/sshd_config.5
--- openssh-7.4p1/sshd_config.5.kuserok 2016-12-23 14:36:07.637465940 +0100
+++ openssh-7.4p1/sshd_config.5 2016-12-23 15:14:03.117162222 +0100
@@ -850,6 +850,10 @@ Specifies whether to automatically destr
tickets aquired in different sessions of the same user.
The default is
.Cm no .
.Cm no
can lead to overwriting previous tickets by subseqent connections to the same
user account.
+.It Cm KerberosUseKuserok
+Specifies whether to look at .k5login file for user's aliases.
+The default is

View file

@ -25,15 +25,15 @@ diff -up openssh-7.4p1/openbsd-compat/port-linux-sshd.c.privsep-selinux openssh-
+ return;
+
+ if (getexeccon((security_context_t *)&ctx) != 0) {
+ logit("%s: getcon failed with %s", __func__, strerror (errno));
+ logit("%s: getexeccon failed with %s", __func__, strerror(errno));
+ return;
+ }
+ if (ctx != NULL) {
+ /* unset exec context before we will lose this capabililty */
+ if (setexeccon(NULL) != 0)
+ fatal("%s: setexeccon failed with %s", __func__, strerror (errno));
+ fatal("%s: setexeccon failed with %s", __func__, strerror(errno));
+ if (setcon(ctx) != 0)
+ fatal("%s: setcon failed with %s", __func__, strerror (errno));
+ fatal("%s: setcon failed with %s", __func__, strerror(errno));
+ freecon(ctx);
+ }
+}

View file

@ -1,26 +1,30 @@
diff -up openssh-7.4p1/channels.c.coverity openssh-7.4p1/channels.c
--- openssh-7.4p1/channels.c.coverity 2016-12-23 16:40:26.881788686 +0100
+++ openssh-7.4p1/channels.c 2016-12-23 16:42:36.244818763 +0100
@@ -288,11 +288,11 @@ channel_register_fds(Channel *c, int rfd
/* enable nonblocking mode */
if (nonblock) {
- if (rfd != -1)
+ if (rfd >= 0)
diff -up openssh-8.0p1/channels.c.coverity openssh-8.0p1/channels.c
--- openssh-8.0p1/channels.c.coverity 2021-06-21 10:59:17.297473319 +0200
+++ openssh-8.0p1/channels.c 2021-06-21 11:11:32.467290400 +0200
@@ -341,15 +341,15 @@ channel_register_fds(struct ssh *ssh, Ch
* restore their blocking state on exit to avoid interfering
* with other programs that follow.
*/
- if (rfd != -1 && !isatty(rfd) && fcntl(rfd, F_GETFL) == 0) {
+ if (rfd >= 0 && !isatty(rfd) && fcntl(rfd, F_GETFL) == 0) {
c->restore_block |= CHANNEL_RESTORE_RFD;
set_nonblock(rfd);
- if (wfd != -1)
+ if (wfd >= 0)
}
- if (wfd != -1 && !isatty(wfd) && fcntl(wfd, F_GETFL) == 0) {
+ if (wfd >= 0 && !isatty(wfd) && fcntl(wfd, F_GETFL) == 0) {
c->restore_block |= CHANNEL_RESTORE_WFD;
set_nonblock(wfd);
- if (efd != -1)
+ if (efd >= 0)
}
- if (efd != -1 && !isatty(efd) && fcntl(efd, F_GETFL) == 0) {
+ if (efd >= 0 && !isatty(efd) && fcntl(efd, F_GETFL) == 0) {
c->restore_block |= CHANNEL_RESTORE_EFD;
set_nonblock(efd);
}
}
diff -up openssh-7.4p1/monitor.c.coverity openssh-7.4p1/monitor.c
--- openssh-7.4p1/monitor.c.coverity 2016-12-23 16:40:26.888788688 +0100
+++ openssh-7.4p1/monitor.c 2016-12-23 16:40:26.900788691 +0100
@@ -411,7 +411,7 @@ monitor_child_preauth(Authctxt *_authctx
mm_get_keystate(pmonitor);
}
diff -up openssh-8.0p1/monitor.c.coverity openssh-8.0p1/monitor.c
--- openssh-8.0p1/monitor.c.coverity 2021-06-21 10:59:17.282473202 +0200
+++ openssh-8.0p1/monitor.c 2021-06-21 10:59:17.297473319 +0200
@@ -401,7 +401,7 @@ monitor_child_preauth(struct ssh *ssh, s
mm_get_keystate(ssh, pmonitor);
/* Drain any buffered messages from the child */
- while (pmonitor->m_log_recvfd != -1 && monitor_read_log(pmonitor) == 0)
@ -124,26 +128,14 @@ diff -up openssh-7.4p1/serverloop.c.coverity openssh-7.4p1/serverloop.c
}
@@ -518,7 +518,7 @@ server_request_tun(void)
debug("%s: invalid tun", __func__);
goto done;
}
tun = packet_get_int();
- if (auth_opts->force_tun_device != -1) {
+ if (auth_opts->force_tun_device >= 0) {
if (tun != SSH_TUNID_ANY && auth_opts->force_tun_device != tun)
if (tun != SSH_TUNID_ANY &&
auth_opts->force_tun_device != (int)tun)
goto done;
tun = auth_opts->force_tun_device;
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)
{
if (sshpid > 1) {
kill(sshpid, SIGTERM);
- waitpid(sshpid, NULL, 0);
+ (void) waitpid(sshpid, NULL, 0);
}
_exit(1);
diff -up openssh-7.4p1/ssh-agent.c.coverity openssh-7.4p1/ssh-agent.c
--- openssh-7.4p1/ssh-agent.c.coverity 2016-12-19 05:59:41.000000000 +0100
+++ openssh-7.4p1/ssh-agent.c 2016-12-23 16:40:26.903788691 +0100
@ -163,7 +155,7 @@ diff -up openssh-7.4p1/sshd.c.coverity openssh-7.4p1/sshd.c
+++ openssh-7.4p1/sshd.c 2016-12-23 16:40:26.904788692 +0100
@@ -691,8 +691,10 @@ privsep_preauth(Authctxt *authctxt)
privsep_preauth_child();
privsep_preauth_child(ssh);
setproctitle("%s", "[net]");
- if (box != NULL)
+ if (box != NULL) {
@ -174,8 +166,8 @@ diff -up openssh-7.4p1/sshd.c.coverity openssh-7.4p1/sshd.c
return 0;
}
@@ -1386,6 +1388,9 @@ server_accept_loop(int *sock_in, int *so
if (num_listen_socks < 0)
break;
explicit_bzero(rnd, sizeof(rnd));
}
}
+
+ if (fdset != NULL)

View file

@ -20,7 +20,7 @@ diff -up openssh-6.8p1/Makefile.in.kdf-cavs openssh-6.8p1/Makefile.in
ssh-xmss.o \
@@ -198,6 +199,9 @@ ssh-keycat$(EXEEXT): $(LIBCOMPAT) $(SSHD
ctr-cavstest$(EXEEXT): $(LIBCOMPAT) libssh.a ctr-cavstest.o
$(LD) -o $@ ctr-cavstest.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lfipscheck $(LIBS)
$(LD) -o $@ ctr-cavstest.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS)
+ssh-cavs$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-cavs.o
+ $(LD) -o $@ ssh-cavs.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
@ -40,7 +40,7 @@ diff -up openssh-6.8p1/Makefile.in.kdf-cavs openssh-6.8p1/Makefile.in
diff -up openssh-6.8p1/ssh-cavs.c.kdf-cavs openssh-6.8p1/ssh-cavs.c
--- openssh-6.8p1/ssh-cavs.c.kdf-cavs 2015-03-18 11:23:46.348049354 +0100
+++ openssh-6.8p1/ssh-cavs.c 2015-03-18 11:23:46.348049354 +0100
@@ -0,0 +1,377 @@
@@ -0,0 +1,387 @@
+/*
+ * Copyright (C) 2015, Stephan Mueller <smueller@chronox.de>
+ *
@ -208,6 +208,7 @@ diff -up openssh-6.8p1/ssh-cavs.c.kdf-cavs openssh-6.8p1/ssh-cavs.c
+{
+ int ret = 0;
+ struct kex kex;
+ struct sshbuf *Kb = NULL;
+ BIGNUM *Kbn = NULL;
+ int mode = 0;
+ struct newkeys *ctoskeys;
@ -222,10 +223,17 @@ diff -up openssh-6.8p1/ssh-cavs.c.kdf-cavs openssh-6.8p1/ssh-cavs.c
+ Kbn = BN_new();
+ BN_bin2bn(test->K, test->Klen, Kbn);
+ if (!Kbn) {
+ printf("cannot convert K into BIGNUM\n");
+ printf("cannot convert K into bignum\n");
+ ret = 1;
+ goto out;
+ }
+ Kb = sshbuf_new();
+ if (!Kb) {
+ printf("cannot convert K into sshbuf\n");
+ ret = 1;
+ goto out;
+ }
+ sshbuf_put_bignum2(Kb, Kbn);
+
+ kex.session_id = test->session_id;
+ kex.session_id_len = test->session_id_len;
@ -285,7 +293,7 @@ diff -up openssh-6.8p1/ssh-cavs.c.kdf-cavs openssh-6.8p1/ssh-cavs.c
+ goto out;
+ }
+ ssh->kex = &kex;
+ kex_derive_keys_bn(ssh, test->H, test->Hlen, Kbn);
+ kex_derive_keys(ssh, test->H, test->Hlen, Kb);
+
+ ctoskeys = kex.newkeys[0];
+ stockeys = kex.newkeys[1];
@ -321,6 +329,8 @@ diff -up openssh-6.8p1/ssh-cavs.c.kdf-cavs openssh-6.8p1/ssh-cavs.c
+out:
+ if (Kbn)
+ BN_free(Kbn);
+ if (Kb)
+ sshbuf_free(Kb);
+ if (ssh)
+ ssh_packet_close(ssh);
+ return ret;

View file

@ -171,7 +171,7 @@ diff -up openssh-6.8p1/Makefile.in.ldap openssh-6.8p1/Makefile.in
$(LD) -o $@ ssh-pkcs11-helper.o ssh-pkcs11.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
+ssh-ldap-helper$(EXEEXT): $(LIBCOMPAT) libssh.a ldapconf.o ldapbody.o ldapmisc.o ldap-helper.o
+ $(LD) -o $@ ldapconf.o ldapbody.o ldapmisc.o ldap-helper.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat -lfipscheck $(LIBS) $(LDAPLIBS)
+ $(LD) -o $@ ldapconf.o ldapbody.o ldapmisc.o ldap-helper.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS) $(LDAPLIBS)
+
ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keyscan.o
$(LD) -o $@ ssh-keyscan.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS)
@ -331,7 +331,7 @@ diff -up openssh-6.8p1/configure.ac.ldap openssh-6.8p1/configure.ac
+ [ac_cv_ldap_set_rebind_proc=3],
+ [ac_cv_ldap_set_rebind_proc=2])
+ AC_MSG_RESULT($ac_cv_ldap_set_rebind_proc)
+ AC_DEFINE(LDAP_SET_REBIND_PROC_ARGS, $ac_cv_ldap_set_rebind_proc, [number arguments of ldap_set_rebind_proc])
+ AC_DEFINE_UNQUOTED(LDAP_SET_REBIND_PROC_ARGS, $ac_cv_ldap_set_rebind_proc, [number arguments of ldap_set_rebind_proc])
+ )
+ LIBS="$saved_LIBS"
+ fi
@ -646,7 +646,7 @@ diff -up openssh-6.8p1/ldap.conf.ldap openssh-6.8p1/ldap.conf
diff -up openssh-6.8p1/ldapbody.c.ldap openssh-6.8p1/ldapbody.c
--- openssh-6.8p1/ldapbody.c.ldap 2015-03-18 11:11:29.031801462 +0100
+++ openssh-6.8p1/ldapbody.c 2015-03-18 11:11:29.031801462 +0100
@@ -0,0 +1,494 @@
@@ -0,0 +1,499 @@
+/* $OpenBSD: ldapbody.c,v 1.1 2009/12/03 03:34:42 jfch Exp $ */
+/*
+ * Copyright (c) 2009 Jan F. Chadima. All rights reserved.
@ -708,7 +708,11 @@ diff -up openssh-6.8p1/ldapbody.c.ldap openssh-6.8p1/ldapbody.c
+
+#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
+static int
+#if LDAP_API_VERSION > 3000
+_rebind_proc (LDAP * ld, LDAP_CONST char *url, ber_tag_t request, ber_int_t msgid, void *params)
+#else
+_rebind_proc (LDAP * ld, LDAP_CONST char *url, int request, ber_int_t msgid)
+#endif
+{
+ struct timeval timeout;
+ int rc;

View file

@ -1,6 +1,6 @@
diff -up openssh-7.2p2/sftp-server.8.sftp-force-mode openssh-7.2p2/sftp-server.8
--- openssh-7.2p2/sftp-server.8.sftp-force-mode 2016-03-09 19:04:48.000000000 +0100
+++ openssh-7.2p2/sftp-server.8 2016-06-23 16:18:20.463854117 +0200
diff --color -ru a/sftp-server.8 b/sftp-server.8
--- a/sftp-server.8 2019-04-18 00:52:57.000000000 +0200
+++ b/sftp-server.8 2022-06-20 16:03:47.892540068 +0200
@@ -38,6 +38,7 @@
.Op Fl P Ar blacklisted_requests
.Op Fl p Ar whitelisted_requests
@ -9,21 +9,23 @@ diff -up openssh-7.2p2/sftp-server.8.sftp-force-mode openssh-7.2p2/sftp-server.8
.Ek
.Nm
.Fl Q Ar protocol_feature
@@ -138,6 +139,10 @@ Sets an explicit
@@ -138,6 +139,12 @@
.Xr umask 2
to be applied to newly-created files and directories, instead of the
user's default mask.
+.It Fl m Ar force_file_perms
+Sets explicit file permissions to be applied to newly-created files instead
+of the default or client requested mode. Numeric values include:
+777, 755, 750, 666, 644, 640, etc. Option -u is ineffective if -m is set.
+777, 755, 750, 666, 644, 640, etc. Using both -m and -u switches makes the
+umask (-u) effective only for newly created directories and explicit mode (-m)
+for newly created files.
.El
.Pp
On some systems,
diff -up openssh-7.2p2/sftp-server.c.sftp-force-mode openssh-7.2p2/sftp-server.c
--- openssh-7.2p2/sftp-server.c.sftp-force-mode 2016-06-23 16:18:20.446854128 +0200
+++ openssh-7.2p2/sftp-server.c 2016-06-23 16:20:37.950766082 +0200
@@ -69,6 +69,10 @@ struct sshbuf *oqueue;
diff --color -ru a/sftp-server.c b/sftp-server.c
--- a/sftp-server.c 2022-06-20 16:01:26.183793633 +0200
+++ b/sftp-server.c 2022-06-20 16:02:12.442690608 +0200
@@ -65,6 +65,10 @@
/* Version of client */
static u_int version;
@ -34,7 +36,7 @@ diff -up openssh-7.2p2/sftp-server.c.sftp-force-mode openssh-7.2p2/sftp-server.c
/* SSH2_FXP_INIT received */
static int init_done;
@@ -683,6 +687,7 @@ process_open(u_int32_t id)
@@ -683,6 +687,7 @@
Attrib a;
char *name;
int r, handle, fd, flags, mode, status = SSH2_FX_FAILURE;
@ -42,7 +44,7 @@ diff -up openssh-7.2p2/sftp-server.c.sftp-force-mode openssh-7.2p2/sftp-server.c
if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 ||
(r = sshbuf_get_u32(iqueue, &pflags)) != 0 || /* portable flags */
@@ -692,6 +697,10 @@ process_open(u_int32_t id)
@@ -692,6 +697,10 @@
debug3("request %u: open flags %d", id, pflags);
flags = flags_from_portable(pflags);
mode = (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? a.perm : 0666;
@ -53,7 +55,7 @@ diff -up openssh-7.2p2/sftp-server.c.sftp-force-mode openssh-7.2p2/sftp-server.c
logit("open \"%s\" flags %s mode 0%o",
name, string_from_portable(pflags), mode);
if (readonly &&
@@ -713,6 +722,8 @@ process_open(u_int32_t id)
@@ -713,6 +722,8 @@
}
}
}
@ -62,7 +64,7 @@ diff -up openssh-7.2p2/sftp-server.c.sftp-force-mode openssh-7.2p2/sftp-server.c
if (status != SSH2_FX_OK)
send_status(id, status);
free(name);
@@ -1494,7 +1505,7 @@ sftp_server_usage(void)
@@ -1555,7 +1566,7 @@
fprintf(stderr,
"usage: %s [-ehR] [-d start_directory] [-f log_facility] "
"[-l log_level]\n\t[-P blacklisted_requests] "
@ -71,7 +73,7 @@ diff -up openssh-7.2p2/sftp-server.c.sftp-force-mode openssh-7.2p2/sftp-server.c
" %s -Q protocol_feature\n",
__progname, __progname);
exit(1);
@@ -1520,7 +1531,7 @@ sftp_server_main(int argc, char **argv,
@@ -1581,7 +1592,7 @@
pw = pwcopy(user_pw);
while (!skipargs && (ch = getopt(argc, argv,
@ -80,7 +82,7 @@ diff -up openssh-7.2p2/sftp-server.c.sftp-force-mode openssh-7.2p2/sftp-server.c
switch (ch) {
case 'Q':
if (strcasecmp(optarg, "requests") != 0) {
@@ -1580,6 +1591,15 @@ sftp_server_main(int argc, char **argv,
@@ -1643,6 +1654,15 @@
fatal("Invalid umask \"%s\"", optarg);
(void)umask((mode_t)mask);
break;

View file

@ -10,18 +10,3 @@ diff -up openssh/servconf.c.sshdt openssh/servconf.c
dump_cfg_string(sForceCommand, o->adm_forced_command);
dump_cfg_string(sChrootDirectory, o->chroot_directory);
dump_cfg_string(sTrustedUserCAKeys, o->trusted_user_ca_keys);
diff -up openssh/ssh.1.sshdt openssh/ssh.1
--- openssh/ssh.1.sshdt 2015-06-24 11:42:19.565102807 +0200
+++ openssh/ssh.1 2015-06-24 11:42:29.042078701 +0200
@@ -441,7 +441,11 @@ For full details of the options listed b
.It GatewayPorts
.It GlobalKnownHostsFile
.It GSSAPIAuthentication
+.It GSSAPIKeyExchange
+.It GSSAPIClientIdentity
.It GSSAPIDelegateCredentials
+.It GSSAPIRenewalForcesRekey
+.It GSSAPITrustDNS
.It HashKnownHosts
.It Host
.It HostbasedAuthentication

View file

@ -1,422 +0,0 @@
diff -up openssh-7.0p1/gss-genr.c.gsskexalg openssh-7.0p1/gss-genr.c
--- openssh-7.0p1/gss-genr.c.gsskexalg 2015-08-19 12:28:38.024518959 +0200
+++ openssh-7.0p1/gss-genr.c 2015-08-19 12:28:38.078518839 +0200
@@ -78,7 +78,8 @@ ssh_gssapi_oid_table_ok() {
*/
char *
-ssh_gssapi_client_mechanisms(const char *host, const char *client) {
+ssh_gssapi_client_mechanisms(const char *host, const char *client,
+ const char *kex) {
gss_OID_set gss_supported;
OM_uint32 min_status;
@@ -86,12 +87,12 @@ ssh_gssapi_client_mechanisms(const char
return NULL;
return(ssh_gssapi_kex_mechs(gss_supported, ssh_gssapi_check_mechanism,
- host, client));
+ host, client, kex));
}
char *
ssh_gssapi_kex_mechs(gss_OID_set gss_supported, ssh_gssapi_check_fn *check,
- const char *host, const char *client) {
+ const char *host, const char *client, const char *kex) {
struct sshbuf *buf;
size_t i;
int oidpos, enclen, r;
@@ -100,6 +101,7 @@ ssh_gssapi_kex_mechs(gss_OID_set gss_sup
char deroid[2];
const EVP_MD *evp_md = EVP_md5();
EVP_MD_CTX md;
+ char *s, *cp, *p;
if (gss_enc2oid != NULL) {
for (i = 0; gss_enc2oid[i].encoded != NULL; i++)
@@ -113,6 +115,7 @@ ssh_gssapi_kex_mechs(gss_OID_set gss_sup
fatal("%s: sshbuf_new failed", __func__);
oidpos = 0;
+ s = cp = xstrdup(kex);
for (i = 0; i < gss_supported->count; i++) {
if (gss_supported->elements[i].length < 128 &&
(*check)(NULL, &(gss_supported->elements[i]), host, client)) {
@@ -131,28 +134,25 @@ ssh_gssapi_kex_mechs(gss_OID_set gss_sup
enclen = __b64_ntop(digest, EVP_MD_size(evp_md),
encoded, EVP_MD_size(evp_md) * 2);
- if (oidpos != 0)
- if ((r = sshbuf_put_u8(buf, ',')) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
-
- if ((r = sshbuf_put(buf, KEX_GSS_GEX_SHA1_ID,
- sizeof(KEX_GSS_GEX_SHA1_ID) - 1)) != 0 ||
- (r = sshbuf_put(buf, encoded, enclen)) != 0 ||
- (r = sshbuf_put_u8(buf, ',')) != 0 ||
- (r = sshbuf_put(buf, KEX_GSS_GRP1_SHA1_ID,
- sizeof(KEX_GSS_GRP1_SHA1_ID) - 1)) != 0 ||
- (r = sshbuf_put(buf, encoded, enclen)) != 0 ||
- (r = sshbuf_put_u8(buf, ',')) != 0 ||
- (r = sshbuf_put(buf, KEX_GSS_GRP14_SHA1_ID,
- sizeof(KEX_GSS_GRP14_SHA1_ID) - 1)) != 0 ||
- (r = sshbuf_put(buf, encoded, enclen)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ cp = strncpy(s, kex, strlen(kex));
+ for ((p = strsep(&cp, ",")); p && *p != '\0';
+ (p = strsep(&cp, ","))) {
+ if (sshbuf_len(buf) != 0)
+ if ((r = sshbuf_put_u8(buf, ',')) != 0)
+ fatal("%s: buffer error: %s",
+ __func__, ssh_err(r));
+ if ((r = sshbuf_put(buf, p, strlen(p))) != 0 ||
+ (r = sshbuf_put(buf, encoded, enclen)) != 0)
+ fatal("%s: buffer error: %s",
+ __func__, ssh_err(r));
+ }
gss_enc2oid[oidpos].oid = &(gss_supported->elements[i]);
gss_enc2oid[oidpos].encoded = encoded;
oidpos++;
}
}
+ free(s);
gss_enc2oid[oidpos].oid = NULL;
gss_enc2oid[oidpos].encoded = NULL;
diff -up openssh-7.0p1/gss-serv.c.gsskexalg openssh-7.0p1/gss-serv.c
--- openssh-7.0p1/gss-serv.c.gsskexalg 2015-08-19 12:28:38.024518959 +0200
+++ openssh-7.0p1/gss-serv.c 2015-08-19 12:28:38.078518839 +0200
@@ -149,7 +149,8 @@ ssh_gssapi_server_mechanisms() {
if (supported_oids == NULL)
ssh_gssapi_prepare_supported_oids();
return (ssh_gssapi_kex_mechs(supported_oids,
- &ssh_gssapi_server_check_mech, NULL, NULL));
+ &ssh_gssapi_server_check_mech, NULL, NULL,
+ options.gss_kex_algorithms));
}
/* Unprivileged */
diff -up openssh-7.0p1/kex.c.gsskexalg openssh-7.0p1/kex.c
--- openssh-7.0p1/kex.c.gsskexalg 2015-08-19 12:28:38.078518839 +0200
+++ openssh-7.0p1/kex.c 2015-08-19 12:30:13.249306371 +0200
@@ -50,6 +50,7 @@
#include "misc.h"
#include "dispatch.h"
#include "monitor.h"
+#include "xmalloc.h"
#include "ssherr.h"
#include "sshbuf.h"
@@ -232,6 +232,29 @@ kex_assemble_names(const char *def, char
return r;
}
+/* Validate GSS KEX method name list */
+int
+gss_kex_names_valid(const char *names)
+{
+ char *s, *cp, *p;
+
+ if (names == NULL || *names == '\0')
+ return 0;
+ s = cp = xstrdup(names);
+ for ((p = strsep(&cp, ",")); p && *p != '\0';
+ (p = strsep(&cp, ","))) {
+ if (strncmp(p, "gss-", 4) != 0
+ || kex_alg_by_name(p) == NULL) {
+ error("Unsupported KEX algorithm \"%.100s\"", p);
+ free(s);
+ return 0;
+ }
+ }
+ debug3("gss kex names ok: [%s]", names);
+ free(s);
+ return 1;
+}
+
/* put algorithm proposal into buffer */
int
kex_prop2buf(struct sshbuf *b, char *proposal[PROPOSAL_MAX])
diff -up openssh-7.0p1/kex.h.gsskexalg openssh-7.0p1/kex.h
--- openssh-7.0p1/kex.h.gsskexalg 2015-08-19 12:28:38.078518839 +0200
+++ openssh-7.0p1/kex.h 2015-08-19 12:30:52.404218958 +0200
@@ -173,6 +173,7 @@ int kex_names_valid(const char *);
char *kex_alg_list(char);
char *kex_names_cat(const char *, const char *);
int kex_assemble_names(char **, const char *, const char *);
+int gss_kex_names_valid(const char *);
int kex_new(struct ssh *, char *[PROPOSAL_MAX], struct kex **);
int kex_setup(struct ssh *, char *[PROPOSAL_MAX]);
diff -up openssh-7.0p1/readconf.c.gsskexalg openssh-7.0p1/readconf.c
--- openssh-7.0p1/readconf.c.gsskexalg 2015-08-19 12:28:38.026518955 +0200
+++ openssh-7.0p1/readconf.c 2015-08-19 12:31:28.333138747 +0200
@@ -61,6 +61,7 @@
#include "uidswap.h"
#include "myproposal.h"
#include "digest.h"
+#include "ssh-gss.h"
/* Format of the configuration file:
@@ -148,7 +149,7 @@ typedef enum {
oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
oAddressFamily, oGssAuthentication, oGssDelegateCreds,
oGssTrustDns, oGssKeyEx, oGssClientIdentity, oGssRenewalRekey,
- oGssServerIdentity,
+ oGssServerIdentity, oGssKexAlgorithms,
oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
oSendEnv, oSetEnv, oControlPath, oControlMaster, oControlPersist,
oHashKnownHosts,
@@ -200,6 +201,7 @@ static struct {
{ "gssapiclientidentity", oGssClientIdentity },
{ "gssapiserveridentity", oGssServerIdentity },
{ "gssapirenewalforcesrekey", oGssRenewalRekey },
+ { "gssapikexalgorithms", oGssKexAlgorithms },
# else
{ "gssapiauthentication", oUnsupported },
{ "gssapikeyexchange", oUnsupported },
@@ -207,6 +209,7 @@ static struct {
{ "gssapitrustdns", oUnsupported },
{ "gssapiclientidentity", oUnsupported },
{ "gssapirenewalforcesrekey", oUnsupported },
+ { "gssapikexalgorithms", oUnsupported },
#endif
#ifdef ENABLE_PKCS11
{ "smartcarddevice", oPKCS11Provider },
@@ -929,6 +932,18 @@ parse_time:
intptr = &options->gss_renewal_rekey;
goto parse_flag;
+ case oGssKexAlgorithms:
+ arg = strdelim(&s);
+ if (!arg || *arg == '\0')
+ fatal("%.200s line %d: Missing argument.",
+ filename, linenum);
+ if (!gss_kex_names_valid(arg))
+ fatal("%.200s line %d: Bad GSSAPI KexAlgorithms '%s'.",
+ filename, linenum, arg ? arg : "<NONE>");
+ if (*activep && options->gss_kex_algorithms == NULL)
+ options->gss_kex_algorithms = xstrdup(arg);
+ break;
+
case oBatchMode:
intptr = &options->batch_mode;
goto parse_flag;
@@ -1638,6 +1653,7 @@ initialize_options(Options * options)
options->gss_renewal_rekey = -1;
options->gss_client_identity = NULL;
options->gss_server_identity = NULL;
+ options->gss_kex_algorithms = NULL;
options->password_authentication = -1;
options->kbd_interactive_authentication = -1;
options->kbd_interactive_devices = NULL;
@@ -1773,6 +1789,10 @@ fill_default_options(Options * options)
options->gss_trust_dns = 0;
if (options->gss_renewal_rekey == -1)
options->gss_renewal_rekey = 0;
+#ifdef GSSAPI
+ if (options->gss_kex_algorithms == NULL)
+ options->gss_kex_algorithms = strdup(GSS_KEX_DEFAULT_KEX);
+#endif
if (options->password_authentication == -1)
options->password_authentication = 1;
if (options->kbd_interactive_authentication == -1)
diff -up openssh-7.0p1/readconf.h.gsskexalg openssh-7.0p1/readconf.h
--- openssh-7.0p1/readconf.h.gsskexalg 2015-08-19 12:28:38.026518955 +0200
+++ openssh-7.0p1/readconf.h 2015-08-19 12:28:38.079518836 +0200
@@ -51,6 +51,7 @@ typedef struct {
int gss_renewal_rekey; /* Credential renewal forces rekey */
char *gss_client_identity; /* Principal to initiate GSSAPI with */
char *gss_server_identity; /* GSSAPI target principal */
+ char *gss_kex_algorithms; /* GSSAPI kex methods to be offered by client. */
int password_authentication; /* Try password
* authentication. */
int kbd_interactive_authentication; /* Try keyboard-interactive auth. */
diff -up openssh-7.0p1/servconf.c.gsskexalg openssh-7.0p1/servconf.c
--- openssh-7.0p1/servconf.c.gsskexalg 2015-08-19 12:28:38.074518847 +0200
+++ openssh-7.0p1/servconf.c 2015-08-19 12:33:13.599902732 +0200
@@ -57,6 +57,7 @@
#include "auth.h"
#include "myproposal.h"
#include "digest.h"
+#include "ssh-gss.h"
static void add_listen_addr(ServerOptions *, const char *,
const char *, int);
@@ -121,6 +122,7 @@ initialize_server_options(ServerOptions
options->gss_cleanup_creds = -1;
options->gss_strict_acceptor = -1;
options->gss_store_rekey = -1;
+ options->gss_kex_algorithms = NULL;
options->use_kuserok = -1;
options->enable_k5users = -1;
options->password_authentication = -1;
@@ -288,6 +290,10 @@ fill_default_server_options(ServerOption
options->gss_strict_acceptor = 1;
if (options->gss_store_rekey == -1)
options->gss_store_rekey = 0;
+#ifdef GSSAPI
+ if (options->gss_kex_algorithms == NULL)
+ options->gss_kex_algorithms = strdup(GSS_KEX_DEFAULT_KEX);
+#endif
if (options->use_kuserok == -1)
options->use_kuserok = 1;
if (options->enable_k5users == -1)
@@ -427,7 +431,7 @@ typedef enum {
sHostKeyAlgorithms,
sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile,
sGssAuthentication, sGssCleanupCreds, sGssEnablek5users, sGssStrictAcceptor,
- sGssKeyEx, sGssStoreRekey, sAcceptEnv, sSetEnv, sPermitTunnel,
+ sGssKeyEx, sGssStoreRekey, sGssKexAlgorithms, sAcceptEnv, sSetEnv, sPermitTunnel,
sMatch, sPermitOpen, sPermitListen, sForceCommand, sChrootDirectory,
sUsePrivilegeSeparation, sAllowAgentForwarding,
sHostCertificate,
@@ -506,6 +510,7 @@ static struct {
{ "gssapikeyexchange", sGssKeyEx, SSHCFG_GLOBAL },
{ "gssapistorecredentialsonrekey", sGssStoreRekey, SSHCFG_GLOBAL },
{ "gssapienablek5users", sGssEnablek5users, SSHCFG_ALL },
+ { "gssapikexalgorithms", sGssKexAlgorithms, SSHCFG_GLOBAL },
#else
{ "gssapiauthentication", sUnsupported, SSHCFG_ALL },
{ "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL },
@@ -513,6 +518,7 @@ static struct {
{ "gssapikeyexchange", sUnsupported, SSHCFG_GLOBAL },
{ "gssapistorecredentialsonrekey", sUnsupported, SSHCFG_GLOBAL },
{ "gssapienablek5users", sUnsupported, SSHCFG_ALL },
+ { "gssapikexalgorithms", sUnsupported, SSHCFG_GLOBAL },
#endif
{ "gssusesessionccache", sUnsupported, SSHCFG_GLOBAL },
{ "gssapiusesessioncredcache", sUnsupported, SSHCFG_GLOBAL },
@@ -1273,6 +1279,18 @@ process_server_config_line(ServerOptions
intptr = &options->gss_store_rekey;
goto parse_flag;
+ case sGssKexAlgorithms:
+ arg = strdelim(&cp);
+ if (!arg || *arg == '\0')
+ fatal("%.200s line %d: Missing argument.",
+ filename, linenum);
+ if (!gss_kex_names_valid(arg))
+ fatal("%.200s line %d: Bad GSSAPI KexAlgorithms '%s'.",
+ filename, linenum, arg ? arg : "<NONE>");
+ if (*activep && options->gss_kex_algorithms == NULL)
+ options->gss_kex_algorithms = xstrdup(arg);
+ break;
+
case sPasswordAuthentication:
intptr = &options->password_authentication;
goto parse_flag;
@@ -2304,6 +2322,7 @@ dump_config(ServerOptions *o)
dump_cfg_fmtint(sGssKeyEx, o->gss_keyex);
dump_cfg_fmtint(sGssStrictAcceptor, o->gss_strict_acceptor);
dump_cfg_fmtint(sGssStoreRekey, o->gss_store_rekey);
+ dump_cfg_string(sGssKexAlgorithms, o->gss_kex_algorithms);
#endif
dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication);
dump_cfg_fmtint(sKbdInteractiveAuthentication,
diff -up openssh-7.0p1/servconf.h.gsskexalg openssh-7.0p1/servconf.h
--- openssh-7.0p1/servconf.h.gsskexalg 2015-08-19 12:28:38.080518834 +0200
+++ openssh-7.0p1/servconf.h 2015-08-19 12:34:46.328693944 +0200
@@ -122,6 +122,7 @@ typedef struct {
int gss_cleanup_creds; /* If true, destroy cred cache on logout */
int gss_strict_acceptor; /* If true, restrict the GSSAPI acceptor name */
int gss_store_rekey;
+ char *gss_kex_algorithms; /* GSSAPI kex methods to be offered by client. */
int password_authentication; /* If true, permit password
* authentication. */
int kbd_interactive_authentication; /* If true, permit */
diff -up openssh-7.0p1/ssh.1.gsskexalg openssh-7.0p1/ssh.1
--- openssh-7.0p1/ssh.1.gsskexalg 2015-08-19 12:28:38.081518832 +0200
+++ openssh-7.0p1/ssh.1 2015-08-19 12:35:31.741591692 +0200
@@ -496,6 +496,7 @@ For full details of the options listed b
.It GSSAPIDelegateCredentials
.It GSSAPIRenewalForcesRekey
.It GSSAPITrustDNS
+.It GSSAPIKexAlgorithms
.It HashKnownHosts
.It Host
.It HostbasedAuthentication
diff -up openssh-7.0p1/ssh_config.5.gsskexalg openssh-7.0p1/ssh_config.5
--- openssh-7.0p1/ssh_config.5.gsskexalg 2015-08-19 12:28:38.028518950 +0200
+++ openssh-7.0p1/ssh_config.5 2015-08-19 12:28:38.082518830 +0200
@@ -786,6 +786,18 @@ command line will be passed untouched to
command line will be passed untouched to the GSSAPI library.
The default is
.Dq no .
+.It Cm GSSAPIKexAlgorithms
+The list of key exchange algorithms that are offered for GSSAPI
+key exchange. Possible values are
+.Bd -literal -offset 3n
+gss-gex-sha1-,
+gss-group1-sha1-,
+gss-group14-sha1-
+.Ed
+.Pp
+The default is
+.Dq gss-gex-sha1-,gss-group14-sha1- .
+This option only applies to protocol version 2 connections using GSSAPI.
.It Cm HashKnownHosts
Indicates that
.Xr ssh 1
diff -up openssh-7.0p1/sshconnect2.c.gsskexalg openssh-7.0p1/sshconnect2.c
--- openssh-7.0p1/sshconnect2.c.gsskexalg 2015-08-19 12:28:38.045518912 +0200
+++ openssh-7.0p1/sshconnect2.c 2015-08-19 12:28:38.081518832 +0200
@@ -179,7 +179,8 @@ ssh_kex2(char *host, struct sockaddr *ho
else
gss_host = host;
- gss = ssh_gssapi_client_mechanisms(gss_host, options.gss_client_identity);
+ gss = ssh_gssapi_client_mechanisms(gss_host,
+ options.gss_client_identity, options.gss_kex_algorithms);
if (gss) {
debug("Offering GSSAPI proposal: %s", gss);
xasprintf(&options.kex_algorithms,
--- openssh-7.1p1/sshd_config.5.gsskexalg 2015-12-10 15:32:48.105418092 +0100
+++ openssh-7.1p1/sshd_config.5 2015-12-10 15:33:47.771279548 +0100
@@ -663,6 +663,18 @@ or updated credentials from a compatible
For this to work
.Cm GSSAPIKeyExchange
needs to be enabled in the server and also used by the client.
+.It Cm GSSAPIKexAlgorithms
+The list of key exchange algorithms that are accepted by GSSAPI
+key exchange. Possible values are
+.Bd -literal -offset 3n
+gss-gex-sha1-,
+gss-group1-sha1-,
+gss-group14-sha1-
+.Ed
+.Pp
+The default is
+.Dq gss-gex-sha1-,gss-group14-sha1- .
+This option only applies to protocol version 2 connections using GSSAPI.
.It Cm HostbasedAcceptedKeyTypes
Specifies the key types that will be accepted for hostbased authentication
as a list of comma-separated patterns.
diff -up openssh-7.0p1/ssh-gss.h.gsskexalg openssh-7.0p1/ssh-gss.h
--- openssh-7.0p1/ssh-gss.h.gsskexalg 2015-08-19 12:28:38.031518944 +0200
+++ openssh-7.0p1/ssh-gss.h 2015-08-19 12:28:38.081518832 +0200
@@ -76,6 +76,10 @@ extern char **k5users_allowed_cmds;
#define KEX_GSS_GRP14_SHA1_ID "gss-group14-sha1-"
#define KEX_GSS_GEX_SHA1_ID "gss-gex-sha1-"
+#define GSS_KEX_DEFAULT_KEX \
+ KEX_GSS_GEX_SHA1_ID "," \
+ KEX_GSS_GRP14_SHA1_ID
+
typedef struct {
char *envvar;
char *envval;
@@ -147,9 +151,9 @@ int ssh_gssapi_credentials_updated(Gssct
/* In the server */
typedef int ssh_gssapi_check_fn(Gssctxt **, gss_OID, const char *,
const char *);
-char *ssh_gssapi_client_mechanisms(const char *, const char *);
+char *ssh_gssapi_client_mechanisms(const char *, const char *, const char *);
char *ssh_gssapi_kex_mechs(gss_OID_set, ssh_gssapi_check_fn *, const char *,
- const char *);
+ const char *, const char *);
gss_OID ssh_gssapi_id_kex(Gssctxt *, char *, int);
int ssh_gssapi_server_check_mech(Gssctxt **,gss_OID, const char *,
const char *);

View file

@ -1,52 +0,0 @@
diff -up openssh-7.4p1/ssh_config.5.gss-docs openssh-7.4p1/ssh_config.5
--- openssh-7.4p1/ssh_config.5.gss-docs 2016-12-23 14:28:34.051714486 +0100
+++ openssh-7.4p1/ssh_config.5 2016-12-23 14:34:24.568522417 +0100
@@ -765,10 +765,19 @@ The default is
If set to
.Dq yes
then renewal of the client's GSSAPI credentials will force the rekeying of the
-ssh connection. With a compatible server, this can delegate the renewed
+ssh connection. With a compatible server, this will delegate the renewed
credentials to a session on the server.
+.Pp
+Checks are made to ensure that credentials are only propagated when the new
+credentials match the old ones on the originating client and where the
+receiving server still has the old set in its cache.
+.Pp
The default is
.Dq no .
+.Pp
+For this to work
+.Cm GSSAPIKeyExchange
+needs to be enabled in the server and also used by the client.
.It Cm GSSAPIServerIdentity
If set, specifies the GSSAPI server identity that ssh should expect when
connecting to the server. The default is unset, which means that the
@@ -776,9 +785,11 @@ expected GSSAPI server identity will be
hostname.
.It Cm GSSAPITrustDns
Set to
-.Dq yes to indicate that the DNS is trusted to securely canonicalize
+.Dq yes
+to indicate that the DNS is trusted to securely canonicalize
the name of the host being connected to. If
-.Dq no, the hostname entered on the
+.Dq no ,
+the hostname entered on the
command line will be passed untouched to the GSSAPI library.
The default is
.Dq no .
diff -up openssh-7.4p1/sshd_config.5.gss-docs openssh-7.4p1/sshd_config.5
--- openssh-7.4p1/sshd_config.5.gss-docs 2016-12-23 14:28:34.043714490 +0100
+++ openssh-7.4p1/sshd_config.5 2016-12-23 14:28:34.051714486 +0100
@@ -652,6 +652,10 @@ Controls whether the user's GSSAPI crede
successful connection rekeying. This option can be used to accepted renewed
or updated credentials from a compatible client. The default is
.Dq no .
+.Pp
+For this to work
+.Cm GSSAPIKeyExchange
+needs to be enabled in the server and also used by the client.
.It Cm HostbasedAcceptedKeyTypes
Specifies the key types that will be accepted for hostbased authentication
as a list of comma-separated patterns.

View file

@ -56,9 +56,9 @@ diff -up openssh-7.4p1/monitor_wrap.h.audit-race openssh-7.4p1/monitor_wrap.h
--- openssh-7.4p1/monitor_wrap.h.audit-race 2016-12-23 16:35:52.694685771 +0100
+++ openssh-7.4p1/monitor_wrap.h 2016-12-23 16:35:52.698685772 +0100
@@ -83,6 +83,8 @@ void mm_audit_unsupported_body(int);
void mm_audit_kex_body(int, char *, char *, char *, char *, pid_t, uid_t);
void mm_audit_session_key_free_body(int, pid_t, uid_t);
void mm_audit_destroy_sensitive_data(const char *, pid_t, uid_t);
void mm_audit_kex_body(struct ssh *, int, char *, char *, char *, char *, pid_t, uid_t);
void mm_audit_session_key_free_body(struct ssh *, int, pid_t, uid_t);
void mm_audit_destroy_sensitive_data(struct ssh *, const char *, pid_t, uid_t);
+int mm_forward_audit_messages(int);
+void mm_set_monitor_pipe(int);
#endif
@ -82,7 +82,7 @@ diff -up openssh-7.4p1/session.c.audit-race openssh-7.4p1/session.c
return 1;
}
+void child_destory_sensitive_data();
+void child_destory_sensitive_data(struct ssh *ssh);
+
#define USE_PIPES 1
/*
@ -91,7 +91,7 @@ diff -up openssh-7.4p1/session.c.audit-race openssh-7.4p1/session.c
close(err[0]);
#endif
+ child_destory_sensitive_data();
+ child_destory_sensitive_data(ssh);
+
/* Do processing for the child (exec command etc). */
do_child(ssh, s, command);
@ -101,7 +101,7 @@ diff -up openssh-7.4p1/session.c.audit-race openssh-7.4p1/session.c
close(ttyfd);
+ /* Do this early, so we will not block large MOTDs */
+ child_destory_sensitive_data();
+ child_destory_sensitive_data(ssh);
+
/* record login, etc. similar to login(1) */
#ifndef HAVE_OSF_SIA
@ -109,7 +109,7 @@ diff -up openssh-7.4p1/session.c.audit-race openssh-7.4p1/session.c
@@ -717,6 +728,8 @@ do_exec(Session *s, const char *command)
}
if (s->command != NULL && s->ptyfd == -1)
s->command_handle = PRIVSEP(audit_run_command(s->command));
s->command_handle = PRIVSEP(audit_run_command(ssh, s->command));
+ if (pipe(paudit) < 0)
+ fatal("pipe: %s", strerror(errno));
#endif
@ -141,7 +141,7 @@ diff -up openssh-7.4p1/session.c.audit-race openssh-7.4p1/session.c
}
+void
+child_destory_sensitive_data()
+child_destory_sensitive_data(struct ssh *ssh)
+{
+#ifdef SSH_AUDIT_EVENTS
+ int pparent = paudit[1];
@ -152,15 +152,15 @@ diff -up openssh-7.4p1/session.c.audit-race openssh-7.4p1/session.c
+#endif
+
+ /* remove hostkey from the child's memory */
+ destroy_sensitive_data(use_privsep);
+ destroy_sensitive_data(ssh, use_privsep);
+ /*
+ * We can audit this, because we hacked the pipe to direct the
+ * messages over postauth child. But this message requires answer
+ * which we can't do using one-way pipe.
+ */
+ packet_destroy_all(0, 1);
+ packet_destroy_all(ssh, 0, 1);
+ /* XXX this will clean the rest but should not audit anymore */
+ /* packet_clear_keys(); */
+ /* packet_clear_keys(ssh); */
+
+#ifdef SSH_AUDIT_EVENTS
+ /* Notify parent that we are done */
@ -172,15 +172,15 @@ diff -up openssh-7.4p1/session.c.audit-race openssh-7.4p1/session.c
* Performs common processing for the child, such as setting up the
* environment, closing extra file descriptors, setting the user and group
@@ -1554,13 +1608,6 @@ do_child(Session *s, const char *command
struct passwd *pw = s->pw;
int r = 0;
sshpkt_fmt_connection_id(ssh, remote_id, sizeof(remote_id));
- /* remove hostkey from the child's memory */
- destroy_sensitive_data(1);
- packet_clear_keys();
- destroy_sensitive_data(ssh, 1);
- ssh_packet_clear_keys(ssh);
- /* Don't audit this - both us and the parent would be talking to the
- monitor over a single socket, with no synchronization. */
- packet_destroy_all(0, 1);
- packet_destroy_all(ssh, 0, 1);
-
/* Force a password change */
if (s->authctxt->force_pwchange) {

View file

@ -2,10 +2,11 @@ diff --git a/auth-krb5.c b/auth-krb5.c
index 2b02a04..19b9364 100644
--- a/auth-krb5.c
+++ b/auth-krb5.c
@@ -375,6 +375,22 @@ cleanup:
return -1;
@@ -375,5 +375,21 @@ cleanup:
return (krb5_cc_resolve(ctx, ccname, ccache));
}
}
+
+/*
+ * Reads k5login_directory option from the krb5.conf
+ */
@ -21,10 +22,8 @@ index 2b02a04..19b9364 100644
+ return profile_get_string(p, "libdefaults", "k5login_directory", NULL, NULL,
+ k5login_directory);
+}
+
krb5_error_code
ssh_krb5_get_cctemplate(krb5_context ctx, char **ccname) {
profile_t p;
#endif /* !HEIMDAL */
#endif /* KRB5 */
diff --git a/auth.h b/auth.h
index f9d191c..c432d2f 100644
--- a/auth.h

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -20,8 +20,8 @@ index ca75cc7..6e7de31 100644
+#if defined(__NR_flock) && defined(__s390__)
+ SC_ALLOW(__NR_flock),
+#endif
#ifdef __NR_geteuid
SC_ALLOW(__NR_geteuid),
#ifdef __NR_futex
SC_ALLOW(__NR_futex),
#endif
@@ -178,6 +181,9 @@ static const struct sock_filter preauth_insns[] = {
#ifdef __NR_gettimeofday
@ -106,3 +106,41 @@ diff -up openssh-7.6p1/sandbox-seccomp-filter.c.sandbox openssh-7.6p1/sandbox-se
#ifdef __NR_getrandom
SC_ALLOW(__NR_getrandom),
#endif
From ef34ea4521b042dd8a9c4c7455f5d1a8f8ee5bb2 Mon Sep 17 00:00:00 2001
From: Harald Freudenberger <freude@linux.ibm.com>
Date: Fri, 24 May 2019 10:11:15 +0200
Subject: [PATCH] allow s390 specific ioctl for ecc hardware support
Adding another s390 specific ioctl to be able to support ECC hardware acceleration
to the sandbox seccomp filter rules.
Now the ibmca openssl engine provides elliptic curve cryptography support with the
help of libica and CCA crypto cards. This is done via jet another ioctl call to the zcrypt
device driver and so there is a need to enable this on the openssl sandbox.
Code is s390 specific and has been tested, verified and reviewed.
Please note that I am also the originator of the previous changes in that area.
I posted these changes to Eduardo and he forwarded the patches to the openssl
community.
Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
Reviewed-by: Joerg Schmidbauer <jschmidb@de.ibm.com>
---
sandbox-seccomp-filter.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/sandbox-seccomp-filter.c b/sandbox-seccomp-filter.c
index 5edbc6946..56eb9317f 100644
--- a/sandbox-seccomp-filter.c
+++ b/sandbox-seccomp-filter.c
@@ -252,6 +252,7 @@ static const struct sock_filter preauth_insns[] = {
SC_ALLOW_ARG(__NR_ioctl, 1, ICARSACRT),
/* Allow ioctls for EP11 crypto card on s390 */
SC_ALLOW_ARG(__NR_ioctl, 1, ZSENDEP11CPRB),
+ SC_ALLOW_ARG(__NR_ioctl, 1, ZSECSENDCPRB),
#endif
#if defined(__x86_64__) && defined(__ILP32__) && defined(__X32_SYSCALL_BIT)
/*

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
diff -up openssh/auth2-pubkey.c.refactor openssh/auth2-pubkey.c
--- openssh/auth2-pubkey.c.refactor 2017-09-27 13:10:19.556830609 +0200
+++ openssh/auth2-pubkey.c 2017-09-27 13:10:19.677831274 +0200
--- openssh/auth2-pubkey.c.refactor 2019-04-04 13:19:12.188821236 +0200
+++ openssh/auth2-pubkey.c 2019-04-04 13:19:12.276822078 +0200
@@ -72,6 +72,9 @@
extern ServerOptions options;
extern u_char *session_id2;
@ -11,7 +11,7 @@ diff -up openssh/auth2-pubkey.c.refactor openssh/auth2-pubkey.c
static char *
format_key(const struct sshkey *key)
@@ -432,7 +435,8 @@ match_principals_command(struct passwd *
@@ -511,7 +514,8 @@ match_principals_command(struct ssh *ssh
if ((pid = subprocess("AuthorizedPrincipalsCommand", runas_pw, command,
ac, av, &f,
@ -21,7 +21,7 @@ diff -up openssh/auth2-pubkey.c.refactor openssh/auth2-pubkey.c
goto out;
uid_swapped = 1;
@@ -762,7 +766,8 @@ user_key_command_allowed2(struct passwd
@@ -981,7 +985,8 @@ user_key_command_allowed2(struct ssh *ss
if ((pid = subprocess("AuthorizedKeysCommand", runas_pw, command,
ac, av, &f,
@ -32,9 +32,9 @@ diff -up openssh/auth2-pubkey.c.refactor openssh/auth2-pubkey.c
uid_swapped = 1;
diff -up openssh/auth.c.refactor openssh/auth.c
--- openssh/auth.c.refactor 2017-09-27 13:10:19.640831071 +0200
+++ openssh/auth.c 2017-09-27 13:10:19.678831279 +0200
@@ -1435,7 +1435,8 @@ argv_assemble(int argc, char **argv)
--- openssh/auth.c.refactor 2019-04-04 13:19:12.235821686 +0200
+++ openssh/auth.c 2019-04-04 13:19:12.276822078 +0200
@@ -756,7 +756,8 @@ auth_get_canonical_hostname(struct ssh *
*/
pid_t
subprocess(const char *tag, struct passwd *pw, const char *command,
@ -44,7 +44,7 @@ diff -up openssh/auth.c.refactor openssh/auth.c
{
FILE *f = NULL;
struct stat st;
@@ -1551,7 +1552,7 @@ subprocess(const char *tag, struct passw
@@ -872,7 +873,7 @@ subprocess(const char *tag, struct passw
}
#ifdef WITH_SELINUX
@ -54,9 +54,9 @@ diff -up openssh/auth.c.refactor openssh/auth.c
strerror(errno));
_exit(127);
diff -up openssh/auth.h.refactor openssh/auth.h
--- openssh/auth.h.refactor 2017-09-25 01:48:10.000000000 +0200
+++ openssh/auth.h 2017-09-27 13:10:19.678831279 +0200
@@ -144,7 +144,7 @@ int exited_cleanly(pid_t, const char *,
--- openssh/auth.h.refactor 2019-04-04 13:19:12.251821839 +0200
+++ openssh/auth.h 2019-04-04 13:19:12.276822078 +0200
@@ -235,7 +235,7 @@ struct passwd *fakepw(void);
#define SSH_SUBPROCESS_STDOUT_CAPTURE (1<<1) /* Redirect stdout */
#define SSH_SUBPROCESS_STDERR_DISCARD (1<<2) /* Discard stderr */
pid_t subprocess(const char *, struct passwd *,
@ -66,8 +66,8 @@ diff -up openssh/auth.h.refactor openssh/auth.h
int sys_auth_passwd(struct ssh *, const char *);
diff -up openssh/openbsd-compat/port-linux.h.refactor openssh/openbsd-compat/port-linux.h
--- openssh/openbsd-compat/port-linux.h.refactor 2017-09-27 13:10:19.634831038 +0200
+++ openssh/openbsd-compat/port-linux.h 2017-09-27 13:10:54.954025248 +0200
--- openssh/openbsd-compat/port-linux.h.refactor 2019-04-04 13:19:12.256821887 +0200
+++ openssh/openbsd-compat/port-linux.h 2019-04-04 13:19:12.276822078 +0200
@@ -26,8 +26,8 @@ void ssh_selinux_setfscreatecon(const ch
int sshd_selinux_enabled(void);
@ -80,9 +80,9 @@ diff -up openssh/openbsd-compat/port-linux.h.refactor openssh/openbsd-compat/por
#endif
diff -up openssh/openbsd-compat/port-linux-sshd.c.refactor openssh/openbsd-compat/port-linux-sshd.c
--- openssh/openbsd-compat/port-linux-sshd.c.refactor 2017-09-27 13:10:19.634831038 +0200
+++ openssh/openbsd-compat/port-linux-sshd.c 2017-09-27 13:12:06.811420371 +0200
@@ -48,11 +48,6 @@
--- openssh/openbsd-compat/port-linux-sshd.c.refactor 2019-04-04 13:19:12.256821887 +0200
+++ openssh/openbsd-compat/port-linux-sshd.c 2019-04-04 13:19:12.276822078 +0200
@@ -49,11 +49,6 @@
#include <unistd.h>
#endif
@ -94,7 +94,7 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.refactor openssh/openbsd-compa
/* Wrapper around is_selinux_enabled() to log its return value once only */
int
sshd_selinux_enabled(void)
@@ -222,7 +217,8 @@ get_user_context(const char *sename, con
@@ -223,7 +218,8 @@ get_user_context(const char *sename, con
}
static void
@ -104,7 +104,7 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.refactor openssh/openbsd-compa
{
*role = NULL;
*level = NULL;
@@ -240,8 +236,8 @@ ssh_selinux_get_role_level(char **role,
@@ -241,8 +237,8 @@ ssh_selinux_get_role_level(char **role,
/* Return the default security context for the given username */
static int
@ -115,7 +115,7 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.refactor openssh/openbsd-compa
{
char *sename, *lvl;
char *role;
@@ -249,7 +245,7 @@ sshd_selinux_getctxbyname(char *pwname,
@@ -250,7 +246,7 @@ sshd_selinux_getctxbyname(char *pwname,
int r = 0;
context_t con = NULL;
@ -124,7 +124,7 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.refactor openssh/openbsd-compa
#ifdef HAVE_GETSEUSERBYNAME
if ((r=getseuserbyname(pwname, &sename, &lvl)) != 0) {
@@ -271,7 +267,7 @@ sshd_selinux_getctxbyname(char *pwname,
@@ -272,7 +268,7 @@ sshd_selinux_getctxbyname(char *pwname,
if (r == 0) {
/* If launched from xinetd, we must use current level */
@ -133,7 +133,7 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.refactor openssh/openbsd-compa
security_context_t sshdsc=NULL;
if (getcon_raw(&sshdsc) < 0)
@@ -332,7 +328,8 @@ sshd_selinux_getctxbyname(char *pwname,
@@ -333,7 +329,8 @@ sshd_selinux_getctxbyname(char *pwname,
/* Setup environment variables for pam_selinux */
static int
@ -143,7 +143,7 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.refactor openssh/openbsd-compa
{
const char *reqlvl;
char *role;
@@ -341,11 +338,11 @@ sshd_selinux_setup_variables(int(*set_it
@@ -342,11 +339,11 @@ sshd_selinux_setup_variables(int(*set_it
debug3("%s: setting execution context", __func__);
@ -157,7 +157,7 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.refactor openssh/openbsd-compa
use_current = "1";
} else {
use_current = "";
@@ -361,9 +358,10 @@ sshd_selinux_setup_variables(int(*set_it
@@ -362,9 +359,10 @@ sshd_selinux_setup_variables(int(*set_it
}
static int
@ -170,7 +170,7 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.refactor openssh/openbsd-compa
}
static int
@@ -373,25 +371,28 @@ do_setenv(char *name, const char *value)
@@ -374,25 +372,28 @@ do_setenv(char *name, const char *value)
}
int
@ -204,7 +204,7 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.refactor openssh/openbsd-compa
switch (security_getenforce()) {
case -1:
fatal("%s: security_getenforce() failed", __func__);
@@ -409,7 +410,7 @@ sshd_selinux_setup_exec_context(char *pw
@@ -410,7 +411,7 @@ sshd_selinux_setup_exec_context(char *pw
debug3("%s: setting execution context", __func__);
@ -214,9 +214,9 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.refactor openssh/openbsd-compa
r = setexeccon(user_ctx);
if (r < 0) {
diff -up openssh/platform.c.refactor openssh/platform.c
--- openssh/platform.c.refactor 2017-09-27 13:10:19.574830708 +0200
+++ openssh/platform.c 2017-09-27 13:11:45.475303050 +0200
@@ -33,6 +33,9 @@
--- openssh/platform.c.refactor 2019-04-04 13:19:12.204821389 +0200
+++ openssh/platform.c 2019-04-04 13:19:12.277822088 +0200
@@ -32,6 +32,9 @@
extern int use_privsep;
extern ServerOptions options;
@ -226,7 +226,7 @@ diff -up openssh/platform.c.refactor openssh/platform.c
void
platform_pre_listen(void)
@@ -184,7 +187,9 @@ platform_setusercontext_post_groups(stru
@@ -183,7 +186,9 @@ platform_setusercontext_post_groups(stru
}
#endif /* HAVE_SETPCRED */
#ifdef WITH_SELINUX
@ -238,9 +238,27 @@ diff -up openssh/platform.c.refactor openssh/platform.c
}
diff -up openssh/sshd.c.refactor openssh/sshd.c
--- openssh/sshd.c.refactor 2017-09-27 13:10:19.674831257 +0200
+++ openssh/sshd.c 2017-09-27 13:12:01.635391909 +0200
@@ -2135,7 +2135,9 @@ main(int ac, char **av)
--- openssh/sshd.c.refactor 2019-04-04 13:19:12.275822068 +0200
+++ openssh/sshd.c 2019-04-04 13:19:51.270195262 +0200
@@ -158,7 +158,7 @@ int debug_flag = 0;
static int test_flag = 0;
/* Flag indicating that the daemon is being started from inetd. */
-static int inetd_flag = 0;
+int inetd_flag = 0;
/* Flag indicating that sshd should not detach and become a daemon. */
static int no_daemon_flag = 0;
@@ -171,7 +171,7 @@ static char **saved_argv;
static int saved_argc;
/* re-exec */
-static int rexeced_flag = 0;
+int rexeced_flag = 0;
static int rexec_flag = 1;
static int rexec_argc = 0;
static char **rexec_argv;
@@ -2192,7 +2192,9 @@ main(int ac, char **av)
}
#endif
#ifdef WITH_SELINUX

View file

@ -1,801 +0,0 @@
diff -up openssh-7.6p1/ssh-pkcs11-client.c.pkcs11-ecdsa openssh-7.6p1/ssh-pkcs11-client.c
--- openssh-7.6p1/ssh-pkcs11-client.c.pkcs11-ecdsa 2018-02-16 13:25:59.426469253 +0100
+++ openssh-7.6p1/ssh-pkcs11-client.c 2018-02-16 13:25:59.428469265 +0100
@@ -31,6 +31,15 @@
#include <errno.h>
#include <openssl/rsa.h>
+#ifdef OPENSSL_HAS_ECC
+#include <openssl/ecdsa.h>
+#if ((defined(LIBRESSL_VERSION_NUMBER) && \
+ (LIBRESSL_VERSION_NUMBER >= 0x20010002L))) || \
+ (defined(ECDSA_F_ECDSA_METHOD_NEW)) || \
+ (OPENSSL_VERSION_NUMBER >= 0x00010100L)
+#define ENABLE_PKCS11_ECDSA 1
+#endif
+#endif
#include "pathnames.h"
#include "xmalloc.h"
@@ -139,9 +147,9 @@ pkcs11_rsa_private_encrypt(int flen, con
return (ret);
}
-/* redirect the private key encrypt operation to the ssh-pkcs11-helper */
+/* redirect the RSA private key encrypt operation to the ssh-pkcs11-helper */
static int
-wrap_key(RSA *rsa)
+wrap_rsa_key(RSA *rsa)
{
static RSA_METHOD helper_rsa;
@@ -152,6 +160,88 @@ wrap_key(RSA *rsa)
return (0);
}
+#ifdef ENABLE_PKCS11_ECDSA
+static ECDSA_SIG *
+pkcs11_ecdsa_private_sign(const unsigned char *from, int flen,
+ const BIGNUM *inv, const BIGNUM *rp, EC_KEY * ecdsa)
+{
+ struct sshkey *key = NULL;
+ u_char *blob, *signature = NULL;
+ size_t blen, slen = 0;
+ struct sshbuf *msg = NULL;
+ ECDSA_SIG *ret = NULL;
+ BIGNUM *r = NULL, *s = NULL;
+ int rv;
+
+ if ((key = sshkey_new(KEY_ECDSA)) == NULL)
+ fatal("%s: sshkey_new failed", __func__);
+ key->ecdsa = ecdsa;
+ key->ecdsa_nid = sshkey_ecdsa_key_to_nid(ecdsa);
+ if (sshkey_to_blob(key, &blob, &blen) == 0)
+ goto out;
+ if ((msg = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
+ if ((rv = sshbuf_put_u8(msg, SSH2_AGENTC_SIGN_REQUEST)) != 0 ||
+ (rv = sshbuf_put_string(msg, blob, blen)) != 0 ||
+ (rv = sshbuf_put_string(msg, from, flen)) != 0 ||
+ (rv = sshbuf_put_u32(msg, 0)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(rv));
+ free(blob);
+ send_msg(msg);
+ sshbuf_reset(msg);
+
+ if (recv_msg(msg) == SSH2_AGENT_SIGN_RESPONSE) {
+ if ((rv = sshbuf_get_string(msg, &signature, &slen)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(rv));
+ if (slen <= (size_t)ECDSA_size(ecdsa)) {
+ int nlen = slen / 2;
+ ret = ECDSA_SIG_new();
+ r = BN_new();
+ s = BN_new();
+ BN_bin2bn(&signature[0], nlen, r);
+ BN_bin2bn(&signature[nlen], nlen, s);
+ ECDSA_SIG_set0(ret, r, s);
+ }
+ free(signature);
+ }
+out:
+ sshkey_free(key);
+ sshbuf_free(msg);
+ return (ret);
+}
+
+/* redirect the ECDSA private key encrypt operation to the ssh-pkcs11-helper */
+static int
+wrap_ecdsa_key(EC_KEY *ecdsa) {
+#if (OPENSSL_VERSION_NUMBER >= 0x00010100L)
+ static EC_KEY_METHOD *helper_ecdsa = NULL;
+ if (helper_ecdsa == NULL) {
+ const EC_KEY_METHOD *def = EC_KEY_get_default_method();
+ helper_ecdsa = EC_KEY_METHOD_new(def);
+ EC_KEY_METHOD_set_sign(helper_ecdsa, NULL, NULL, pkcs11_ecdsa_private_sign);
+ }
+ EC_KEY_set_method(ecdsa, helper_ecdsa);
+#else
+ static ECDSA_METHOD *helper_ecdsa = NULL;
+ if(helper_ecdsa == NULL) {
+ const ECDSA_METHOD *def = ECDSA_get_default_method();
+# ifdef ECDSA_F_ECDSA_METHOD_NEW
+ helper_ecdsa = ECDSA_METHOD_new((ECDSA_METHOD *)def);
+ ECDSA_METHOD_set_name(helper_ecdsa, "ssh-pkcs11-helper-ecdsa");
+ ECDSA_METHOD_set_sign(helper_ecdsa, pkcs11_ecdsa_private_sign);
+# else
+ helper_ecdsa = xcalloc(1, sizeof(*helper_ecdsa));
+ memcpy(helper_ecdsa, def, sizeof(*helper_ecdsa));
+ helper_ecdsa->name = "ssh-pkcs11-helper-ecdsa";
+ helper_ecdsa->ecdsa_do_sign = pkcs11_ecdsa_private_sign;
+# endif
+ }
+ ECDSA_set_method(ecdsa, helper_ecdsa);
+#endif
+ return (0);
+}
+#endif
+
static int
pkcs11_start_helper(void)
{
@@ -212,7 +281,15 @@ pkcs11_add_provider(char *name, char *pi
__func__, ssh_err(r));
if ((r = sshkey_from_blob(blob, blen, &k)) != 0)
fatal("%s: bad key: %s", __func__, ssh_err(r));
- wrap_key(k->rsa);
+ if(k->type == KEY_RSA) {
+ wrap_rsa_key(k->rsa);
+#ifdef ENABLE_PKCS11_ECDSA
+ } else if(k->type == KEY_ECDSA) {
+ wrap_ecdsa_key(k->ecdsa);
+#endif /* ENABLE_PKCS11_ECDSA */
+ } else {
+ /* Unsupported type */
+ }
(*keysp)[i] = k;
free(blob);
}
diff -up openssh-7.6p1/ssh-pkcs11.c.pkcs11-ecdsa openssh-7.6p1/ssh-pkcs11.c
--- openssh-7.6p1/ssh-pkcs11.c.pkcs11-ecdsa 2018-02-16 13:25:59.427469259 +0100
+++ openssh-7.6p1/ssh-pkcs11.c 2018-02-16 13:44:51.270554797 +0100
@@ -32,6 +32,16 @@
#include "openbsd-compat/sys-queue.h"
#include <openssl/x509.h>
+#include <openssl/rsa.h>
+#ifdef OPENSSL_HAS_ECC
+#include <openssl/ecdsa.h>
+#if ((defined(LIBRESSL_VERSION_NUMBER) && \
+ (LIBRESSL_VERSION_NUMBER >= 0x20010002L))) || \
+ (defined(ECDSA_F_ECDSA_METHOD_NEW)) || \
+ (OPENSSL_VERSION_NUMBER >= 0x00010100L)
+#define ENABLE_PKCS11_ECDSA 1
+#endif
+#endif
#define CRYPTOKI_COMPAT
#include "pkcs11.h"
@@ -67,6 +76,7 @@ TAILQ_HEAD(, pkcs11_provider) pkcs11_pro
struct pkcs11_key {
struct pkcs11_provider *provider;
CK_ULONG slotidx;
+ CK_ULONG key_type;
int (*orig_finish)(RSA *rsa);
RSA_METHOD rsa_method;
char *keyid;
@@ -75,6 +85,9 @@ struct pkcs11_key {
};
int pkcs11_interactive = 0;
+#ifdef ENABLE_PKCS11_ECDSA
+static int pkcs11_key_idx = -1;
+#endif /* ENABLE_PKCS11_ECDSA */
/*
* This can't be in the ssh-pkcs11-uri, becase we can not depend on
@@ -289,6 +302,40 @@ pkcs11_find(struct pkcs11_provider *p, C
return (ret);
}
+int pkcs11_login(struct pkcs11_key *k11, CK_FUNCTION_LIST *f, struct pkcs11_slotinfo *si) {
+ char *pin = NULL, prompt[1024];
+ CK_RV rv;
+ if ((si->token.flags & CKF_LOGIN_REQUIRED) && !si->logged_in) {
+ if (!pkcs11_interactive) {
+ error("need pin entry%s", (si->token.flags &
+ CKF_PROTECTED_AUTHENTICATION_PATH) ?
+ " on reader keypad" : "");
+ return (-1);
+ }
+ if (si->token.flags & CKF_PROTECTED_AUTHENTICATION_PATH)
+ verbose("Deferring PIN entry to reader keypad.");
+ else {
+ snprintf(prompt, sizeof(prompt),
+ "Enter PIN for '%s': ", si->token.label);
+ pin = read_passphrase(prompt, RP_ALLOW_EOF);
+ if (pin == NULL)
+ return (-1); /* bail out */
+ }
+ rv = f->C_Login(si->session, CKU_USER, (u_char *)pin,
+ (pin != NULL) ? strlen(pin) : 0);
+ if (pin != NULL) {
+ explicit_bzero(pin, strlen(pin));
+ free(pin);
+ }
+ if (rv != CKR_OK && rv != CKR_USER_ALREADY_LOGGED_IN) {
+ error("C_Login failed: %lu", rv);
+ return (-1);
+ }
+ si->logged_in = 1;
+ }
+ return 0;
+}
+
/* openssl callback doing the actual signing operation */
static int
pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa,
@@ -310,7 +357,6 @@ pkcs11_rsa_private_encrypt(int flen, con
{CKA_ID, NULL, 0},
{CKA_SIGN, NULL, sizeof(true_val) }
};
- char *pin = NULL, prompt[1024];
int rval = -1;
key_filter[0].pValue = &private_key_class;
@@ -326,33 +372,8 @@ pkcs11_rsa_private_encrypt(int flen, con
}
f = k11->provider->module->function_list;
si = &k11->provider->module->slotinfo[k11->slotidx];
- if ((si->token.flags & CKF_LOGIN_REQUIRED) && !si->logged_in) {
- if (!pkcs11_interactive) {
- error("need pin entry%s", (si->token.flags &
- CKF_PROTECTED_AUTHENTICATION_PATH) ?
- " on reader keypad" : "");
- return (-1);
- }
- if (si->token.flags & CKF_PROTECTED_AUTHENTICATION_PATH)
- verbose("Deferring PIN entry to reader keypad.");
- else {
- snprintf(prompt, sizeof(prompt),
- "Enter PIN for '%s': ", si->token.label);
- pin = read_passphrase(prompt, RP_ALLOW_EOF);
- if (pin == NULL)
- return (-1); /* bail out */
- }
- rv = f->C_Login(si->session, CKU_USER, (u_char *)pin,
- (pin != NULL) ? strlen(pin) : 0);
- if (pin != NULL) {
- explicit_bzero(pin, strlen(pin));
- free(pin);
- }
- if (rv != CKR_OK && rv != CKR_USER_ALREADY_LOGGED_IN) {
- error("C_Login failed: %lu", rv);
- return (-1);
- }
- si->logged_in = 1;
+ if(pkcs11_login(k11, f, si)) {
+ return (-1);
}
key_filter[1].pValue = k11->keyid;
key_filter[1].ulValueLen = k11->keyid_len;
@@ -390,6 +411,7 @@ pkcs11_rsa_wrap(struct pkcs11_provider *
const RSA_METHOD *def = RSA_get_default_method();
k11 = xcalloc(1, sizeof(*k11));
+ k11->key_type = CKK_RSA;
k11->provider = provider;
provider->refcount++; /* provider referenced by RSA key */
k11->slotidx = slotidx;
@@ -415,6 +437,184 @@ pkcs11_rsa_wrap(struct pkcs11_provider *
return (0);
}
+#ifdef ENABLE_PKCS11_ECDSA
+static ECDSA_SIG *pkcs11_ecdsa_sign(const unsigned char *dgst, int dgst_len,
+ const BIGNUM *inv, const BIGNUM *rp,
+ EC_KEY *ecdsa) {
+ struct pkcs11_key *k11;
+ struct pkcs11_slotinfo *si;
+ CK_FUNCTION_LIST *f;
+ CK_OBJECT_HANDLE obj;
+ CK_ULONG tlen = 0;
+ CK_RV rv;
+ CK_OBJECT_CLASS private_key_class = CKO_PRIVATE_KEY;
+ CK_BBOOL true_val = CK_TRUE;
+ CK_MECHANISM mech = {
+ CKM_ECDSA, NULL_PTR, 0
+ };
+ CK_ATTRIBUTE key_filter[] = {
+ {CKA_CLASS, NULL, sizeof(private_key_class) },
+ {CKA_ID, NULL, 0},
+ {CKA_SIGN, NULL, sizeof(true_val) }
+ };
+ ECDSA_SIG *rval = NULL;
+ key_filter[0].pValue = &private_key_class;
+ key_filter[2].pValue = &true_val;
+
+ #if (OPENSSL_VERSION_NUMBER >= 0x00010100L)
+ if ((k11 = (struct pkcs11_key *)EC_KEY_get_ex_data(ecdsa, pkcs11_key_idx)) == NULL) {
+ error("EC_KEY_get_ex_data failed for ecdsa %p", ecdsa);
+ #else
+ if ((k11 = (struct pkcs11_key *)ECDSA_get_ex_data(ecdsa, pkcs11_key_idx)) == NULL) {
+ error("ECDSA_get_ex_data failed for ecdsa %p", ecdsa);
+ #endif
+ return NULL;
+ }
+ if (!k11->provider || !k11->provider->valid) {
+ error("no pkcs11 (valid) provider for ecdsa %p", ecdsa);
+ return NULL;
+ }
+ f = k11->provider->module->function_list;
+ si = &k11->provider->module->slotinfo[k11->slotidx];
+ if(pkcs11_login(k11, f, si)) {
+ return NULL;
+ }
+ key_filter[1].pValue = k11->keyid;
+ key_filter[1].ulValueLen = k11->keyid_len;
+ /* try to find object w/CKA_SIGN first, retry w/o */
+ if (pkcs11_find(k11->provider, k11->slotidx, key_filter, 3, &obj) < 0 &&
+ pkcs11_find(k11->provider, k11->slotidx, key_filter, 2, &obj) < 0) {
+ error("cannot find private key");
+ } else if ((rv = f->C_SignInit(si->session, &mech, obj)) != CKR_OK) {
+ error("C_SignInit failed: %lu", rv);
+ } else {
+ CK_BYTE_PTR buf = NULL;
+ BIGNUM *r = NULL, *s = NULL;
+ int nlen;
+ /* Make a call to C_Sign to find out the size of the signature */
+ rv = f->C_Sign(si->session, (CK_BYTE *)dgst, dgst_len, NULL, &tlen);
+ if (rv != CKR_OK) {
+ error("C_Sign failed: %lu", rv);
+ return NULL;
+ }
+ if ((buf = xmalloc(tlen)) == NULL) {
+ error("failure to allocate signature buffer");
+ return NULL;
+ }
+ rv = f->C_Sign(si->session, (CK_BYTE *)dgst, dgst_len, buf, &tlen);
+ if (rv != CKR_OK) {
+ error("C_Sign failed: %lu", rv);
+ }
+
+ if ((rval = ECDSA_SIG_new()) == NULL ||
+ (r = BN_new()) == NULL ||
+ (s = BN_new()) == NULL) {
+ error("failure to allocate ECDSA signature");
+ } else {
+ /*
+ * ECDSA signature is 2 large integers of same size returned
+ * concatenated by PKCS#11, we separate them to create an
+ * ECDSA_SIG for OpenSSL.
+ */
+ nlen = tlen / 2;
+ BN_bin2bn(&buf[0], nlen, r);
+ BN_bin2bn(&buf[nlen], nlen, s);
+ ECDSA_SIG_set0(rval, r, s);
+ }
+ free(buf);
+ }
+ return (rval);
+}
+
+#if (OPENSSL_VERSION_NUMBER >= 0x00010100L)
+static EC_KEY_METHOD *get_pkcs11_ecdsa_method(void) {
+ static EC_KEY_METHOD *pkcs11_ecdsa_method = NULL;
+ if(pkcs11_key_idx == -1) {
+ pkcs11_key_idx = EC_KEY_get_ex_new_index(0, NULL, NULL, NULL, 0);
+ }
+ if (pkcs11_ecdsa_method == NULL) {
+ const EC_KEY_METHOD *def = EC_KEY_get_default_method();
+ pkcs11_ecdsa_method = EC_KEY_METHOD_new(def);
+ EC_KEY_METHOD_set_sign(pkcs11_ecdsa_method, NULL, NULL, pkcs11_ecdsa_sign);
+ }
+#else
+static ECDSA_METHOD *get_pkcs11_ecdsa_method(void) {
+ static ECDSA_METHOD *pkcs11_ecdsa_method = NULL;
+ if(pkcs11_key_idx == -1) {
+ pkcs11_key_idx = ECDSA_get_ex_new_index(0, NULL, NULL, NULL, 0);
+ }
+ if(pkcs11_ecdsa_method == NULL) {
+ const ECDSA_METHOD *def = ECDSA_get_default_method();
+ #ifdef ECDSA_F_ECDSA_METHOD_NEW
+ pkcs11_ecdsa_method = ECDSA_METHOD_new((ECDSA_METHOD *)def);
+ ECDSA_METHOD_set_name(pkcs11_ecdsa_method, "pkcs11");
+ ECDSA_METHOD_set_sign(pkcs11_ecdsa_method, pkcs11_ecdsa_sign);
+ #else
+ pkcs11_ecdsa_method = xcalloc(1, sizeof(*pkcs11_ecdsa_method));
+ memcpy(pkcs11_ecdsa_method, def, sizeof(*pkcs11_ecdsa_method));
+ pkcs11_ecdsa_method->name = "pkcs11";
+ pkcs11_ecdsa_method->ecdsa_do_sign = pkcs11_ecdsa_sign;
+ #endif
+ }
+#endif
+ return pkcs11_ecdsa_method;
+}
+
+static int
+pkcs11_ecdsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx,
+ CK_ATTRIBUTE *keyid_attrib, CK_ATTRIBUTE *label_attrib, EC_KEY *ecdsa)
+{
+ struct pkcs11_key *k11;
+ k11 = xcalloc(1, sizeof(*k11));
+ k11->key_type = CKK_EC;
+ k11->provider = provider;
+ provider->refcount++; /* provider referenced by ECDSA key */
+ k11->slotidx = slotidx;
+ /* identify key object on smartcard */
+ k11->keyid_len = keyid_attrib->ulValueLen;
+ if (k11->keyid_len > 0) {
+ k11->keyid = xmalloc(k11->keyid_len);
+ memcpy(k11->keyid, keyid_attrib->pValue, k11->keyid_len);
+ }
+ if (label_attrib->ulValueLen > 0 ) {
+ k11->label = xmalloc(label_attrib->ulValueLen+1);
+ memcpy(k11->label, label_attrib->pValue, label_attrib->ulValueLen);
+ k11->label[label_attrib->ulValueLen] = 0;
+ }
+ #if (OPENSSL_VERSION_NUMBER >= 0x00010100L)
+ EC_KEY_set_method(ecdsa, get_pkcs11_ecdsa_method());
+ EC_KEY_set_ex_data(ecdsa, pkcs11_key_idx, k11);
+ #else
+ ECDSA_set_method(ecdsa, get_pkcs11_ecdsa_method());
+ ECDSA_set_ex_data(ecdsa, pkcs11_key_idx, k11);
+ #endif
+ return (0);
+}
+#endif /* ENABLE_PKCS11_ECDSA */
+
+int pkcs11_del_key(struct sshkey *key) {
+#ifdef ENABLE_PKCS11_ECDSA
+ if(key->type == KEY_ECDSA) {
+ struct pkcs11_key *k11 = (struct pkcs11_key *)
+ #if (OPENSSL_VERSION_NUMBER >= 0x00010100L)
+ EC_KEY_get_ex_data(key->ecdsa, pkcs11_key_idx);
+ #else
+ ECDSA_get_ex_data(key->ecdsa, pkcs11_key_idx);
+ #endif
+ if (k11 == NULL) {
+ error("EC_KEY_get_ex_data failed for ecdsa %p", key->ecdsa);
+ } else {
+ if (k11->provider)
+ pkcs11_provider_unref(k11->provider);
+ free(k11->keyid);
+ free(k11);
+ }
+ }
+#endif /* ENABLE_PKCS11_ECDSA */
+ sshkey_free(key);
+ return (0);
+}
+
/* remove trailing spaces */
static void
rmspace(u_char *buf, size_t len)
@@ -482,11 +646,13 @@ static int
pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx,
struct sshkey ***keysp, int *nkeys, struct pkcs11_uri *uri)
{
- size_t filter_size = 1;
+ size_t filter_size = 2;
+ CK_KEY_TYPE pubkey_type = CKK_RSA;
CK_OBJECT_CLASS pubkey_class = CKO_PUBLIC_KEY;
CK_OBJECT_CLASS cert_class = CKO_CERTIFICATE;
CK_ATTRIBUTE pubkey_filter[] = {
{ CKA_CLASS, NULL, sizeof(pubkey_class) },
+ { CKA_KEY_TYPE, NULL, sizeof(pubkey_type) },
{ CKA_ID, NULL, 0 },
{ CKA_LABEL, NULL, 0 }
};
@@ -507,29 +673,60 @@ pkcs11_fetch_keys(struct pkcs11_provider
{ CKA_SUBJECT, NULL, 0 },
{ CKA_VALUE, NULL, 0 }
};
+#ifdef ENABLE_PKCS11_ECDSA
+ CK_KEY_TYPE ecdsa_type = CKK_EC;
+ CK_ATTRIBUTE ecdsa_filter[] = {
+ { CKA_CLASS, NULL, sizeof(pubkey_class) },
+ { CKA_KEY_TYPE, NULL, sizeof(ecdsa_type) },
+ { CKA_ID, NULL, 0 },
+ { CKA_LABEL, NULL, 0 }
+ };
+ CK_ATTRIBUTE ecdsa_attribs[] = {
+ { CKA_ID, NULL, 0 },
+ { CKA_LABEL, NULL, 0 },
+ { CKA_EC_PARAMS, NULL, 0 },
+ { CKA_EC_POINT, NULL, 0 }
+ };
+ ecdsa_filter[0].pValue = &pubkey_class;
+ ecdsa_filter[1].pValue = &ecdsa_type;
+#endif /* ENABLE_PKCS11_ECDSA */
pubkey_filter[0].pValue = &pubkey_class;
+ pubkey_filter[1].pValue = &pubkey_type;
cert_filter[0].pValue = &cert_class;
if (uri->id != NULL) {
pubkey_filter[filter_size].pValue = uri->id;
pubkey_filter[filter_size].ulValueLen = uri->id_len;
- cert_filter[filter_size].pValue = uri->id;
- cert_filter[filter_size].ulValueLen = uri->id_len;
+#ifdef ENABLE_PKCS11_ECDSA
+ ecdsa_filter[filter_size].pValue = uri->id;
+ ecdsa_filter[filter_size].ulValueLen = uri->id_len;
+#endif /* ENABLE_PKCS11_ECDSA */
+ cert_filter[filter_size-1].pValue = uri->id;
+ cert_filter[filter_size-1].ulValueLen = uri->id_len;
filter_size++;
}
if (uri->object != NULL) {
pubkey_filter[filter_size].pValue = uri->object;
pubkey_filter[filter_size].ulValueLen = strlen(uri->object);
pubkey_filter[filter_size].type = CKA_LABEL;
- cert_filter[filter_size].pValue = uri->object;
- cert_filter[filter_size].ulValueLen = strlen(uri->object);
- cert_filter[filter_size].type = CKA_LABEL;
+#ifdef ENABLE_PKCS11_ECDSA
+ ecdsa_filter[filter_size].pValue = uri->object;
+ ecdsa_filter[filter_size].ulValueLen = strlen(uri->object);
+ ecdsa_filter[filter_size].type = CKA_LABEL;
+#endif /* ENABLE_PKCS11_ECDSA */
+ cert_filter[filter_size-1].pValue = uri->object;
+ cert_filter[filter_size-1].ulValueLen = strlen(uri->object);
+ cert_filter[filter_size-1].type = CKA_LABEL;
filter_size++;
}
if (pkcs11_fetch_keys_filter(p, slotidx, pubkey_filter, filter_size,
pubkey_attribs, keysp, nkeys) < 0 ||
- pkcs11_fetch_keys_filter(p, slotidx, cert_filter, filter_size,
+#ifdef ENABLE_PKCS11_ECDSA
+ pkcs11_fetch_keys_filter(p, slotidx, ecdsa_filter, filter_size,
+ ecdsa_attribs, keysp, nkeys) < 0||
+#endif /* ENABLE_PKCS11_ECDSA */
+ pkcs11_fetch_keys_filter(p, slotidx, cert_filter, filter_size - 1,
cert_attribs, keysp, nkeys) < 0)
return (-1);
return (0);
@@ -553,6 +746,11 @@ pkcs11_fetch_keys_filter(struct pkcs11_p
{
struct sshkey *key;
RSA *rsa;
+#ifdef ENABLE_PKCS11_ECDSA
+ EC_KEY *ecdsa;
+#else
+ void *ecdsa;
+#endif /* ENABLE_PKCS11_ECDSA */
X509 *x509;
EVP_PKEY *evp = NULL;
int i;
@@ -608,6 +806,9 @@ pkcs11_fetch_keys_filter(struct pkcs11_p
* or ID, label, subject and value for certificates.
*/
rsa = NULL;
+#ifdef ENABLE_PKCS11_ECDSA
+ ecdsa = NULL;
+#endif /* ENABLE_PKCS11_ECDSA */
if ((rv = f->C_GetAttributeValue(session, obj, attribs, nattribs))
!= CKR_OK) {
error("C_GetAttributeValue failed: %lu", rv);
@@ -620,6 +821,45 @@ pkcs11_fetch_keys_filter(struct pkcs11_p
rsa->e = BN_bin2bn(attribs[3].pValue,
attribs[3].ulValueLen, NULL);
}
+#ifdef ENABLE_PKCS11_ECDSA
+ } else if (attribs[2].type == CKA_EC_PARAMS ) {
+ if ((ecdsa = EC_KEY_new()) == NULL) {
+ error("EC_KEY_new failed");
+ } else {
+ const unsigned char *ptr1 = attribs[2].pValue;
+ const unsigned char *ptr2 = attribs[3].pValue;
+ CK_ULONG len1 = attribs[2].ulValueLen;
+ CK_ULONG len2 = attribs[3].ulValueLen;
+ ASN1_OCTET_STRING *point = NULL;
+
+ /*
+ * CKA_EC_PARAMS contains the curve parameters of the key
+ * either referenced as an OID or directly with all values.
+ * CKA_EC_POINT contains the point (public key) on the curve.
+ * The point is should be returned inside a DER-encoded
+ * ASN.1 OCTET STRING value (but some implementation).
+ */
+ if ((point = d2i_ASN1_OCTET_STRING(NULL, &ptr2, len2))) {
+ /* Pointing to OCTET STRING content */
+ ptr2 = point->data;
+ len2 = point->length;
+ } else {
+ /* No OCTET STRING */
+ ptr2 = attribs[3].pValue;
+ }
+
+ if((d2i_ECParameters(&ecdsa, &ptr1, len1) == NULL) ||
+ (o2i_ECPublicKey(&ecdsa, &ptr2, len2) == NULL)) {
+ EC_KEY_free(ecdsa);
+ ecdsa = NULL;
+ error("EC public key parsing failed");
+ }
+
+ if(point) {
+ ASN1_OCTET_STRING_free(point);
+ }
+ }
+#endif /* ENABLE_PKCS11_ECDSA */
} else {
cp = attribs[3].pValue;
if ((x509 = X509_new()) == NULL) {
@@ -639,13 +879,28 @@ pkcs11_fetch_keys_filter(struct pkcs11_p
X509_free(x509);
EVP_PKEY_free(evp);
}
- if (rsa && rsa->n && rsa->e &&
- pkcs11_rsa_wrap(p, slotidx, &attribs[0], &attribs[1], rsa) == 0) {
- if ((key = sshkey_new(KEY_UNSPEC)) == NULL)
- fatal("sshkey_new failed");
- key->rsa = rsa;
- key->type = KEY_RSA;
- key->flags |= SSHKEY_FLAG_EXT;
+ key = NULL;
+ if (rsa || ecdsa) {
+ if (rsa && rsa->n && rsa->e &&
+ pkcs11_rsa_wrap(p, slotidx, &attribs[0], &attribs[1], rsa) == 0) {
+ if ((key = sshkey_new(KEY_UNSPEC)) == NULL)
+ fatal("sshkey_new failed");
+ key->rsa = rsa;
+ key->type = KEY_RSA;
+ key->flags |= SSHKEY_FLAG_EXT;
+#ifdef ENABLE_PKCS11_ECDSA
+ } else if(ecdsa && pkcs11_ecdsa_wrap(p, slotidx, &attribs[0], &attribs[1], ecdsa) == 0) {
+ if ((key = sshkey_new(KEY_UNSPEC)) == NULL)
+ fatal("sshkey_new failed");
+ key->ecdsa = ecdsa;
+ key->ecdsa_nid = sshkey_ecdsa_key_to_nid(ecdsa);
+ key->type = KEY_ECDSA;
+ key->flags |= SSHKEY_FLAG_EXT;
+#endif /* ENABLE_PKCS11_ECDSA */
+ }
+ }
+
+ if(key) {
if (pkcs11_key_included(keysp, nkeys, key)) {
sshkey_free(key);
} else {
@@ -658,6 +913,10 @@ pkcs11_fetch_keys_filter(struct pkcs11_p
}
} else if (rsa) {
RSA_free(rsa);
+#ifdef ENABLE_PKCS11_ECDSA
+ } else if (ecdsa) {
+ EC_KEY_free(ecdsa);
+#endif /* ENABLE_PKCS11_ECDSA */
}
for (i = 0; i < nattribs; i++)
free(attribs[i].pValue);
diff -up openssh-7.6p1/ssh-pkcs11-helper.c.pkcs11-ecdsa openssh-7.6p1/ssh-pkcs11-helper.c
--- openssh-7.6p1/ssh-pkcs11-helper.c.pkcs11-ecdsa 2017-10-02 21:34:26.000000000 +0200
+++ openssh-7.6p1/ssh-pkcs11-helper.c 2018-02-16 13:25:59.428469265 +0100
@@ -24,6 +24,17 @@
#include "openbsd-compat/sys-queue.h"
+#include <openssl/rsa.h>
+#ifdef OPENSSL_HAS_ECC
+#include <openssl/ecdsa.h>
+#if ((defined(LIBRESSL_VERSION_NUMBER) && \
+ (LIBRESSL_VERSION_NUMBER >= 0x20010002L))) || \
+ (defined(ECDSA_F_ECDSA_METHOD_NEW)) || \
+ (OPENSSL_VERSION_NUMBER >= 0x00010100L)
+#define ENABLE_PKCS11_ECDSA 1
+#endif
+#endif
+
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
@@ -80,7 +90,7 @@ del_keys_by_name(char *name)
if (!strcmp(ki->providername, name)) {
TAILQ_REMOVE(&pkcs11_keylist, ki, next);
free(ki->providername);
- sshkey_free(ki->key);
+ pkcs11_del_key(ki->key);
free(ki);
}
}
@@ -164,6 +174,20 @@ process_del(void)
sshbuf_free(msg);
}
+#ifdef ENABLE_PKCS11_ECDSA
+static u_int EC_KEY_order_size(EC_KEY *key)
+{
+ const EC_GROUP *group = EC_KEY_get0_group(key);
+ BIGNUM *order = BN_new();
+ u_int nbytes = 0;
+ if ((group != NULL) && (order != NULL) && EC_GROUP_get_order(group, order, NULL)) {
+ nbytes = BN_num_bytes(order);
+ }
+ BN_clear_free(order);
+ return nbytes;
+}
+#endif /* ENABLE_PKCS11_ECDSA */
+
static void
process_sign(void)
{
@@ -180,14 +204,38 @@ process_sign(void)
else {
if ((found = lookup_key(key)) != NULL) {
#ifdef WITH_OPENSSL
- int ret;
-
- slen = RSA_size(key->rsa);
- signature = xmalloc(slen);
- if ((ret = RSA_private_encrypt(dlen, data, signature,
- found->rsa, RSA_PKCS1_PADDING)) != -1) {
- slen = ret;
- ok = 0;
+ if(found->type == KEY_RSA) {
+ int ret;
+ slen = RSA_size(key->rsa);
+ signature = xmalloc(slen);
+ if ((ret = RSA_private_encrypt(dlen, data, signature,
+ found->rsa, RSA_PKCS1_PADDING)) != -1) {
+ slen = ret;
+ ok = 0;
+ }
+#ifdef ENABLE_PKCS11_ECDSA
+ } else if(found->type == KEY_ECDSA) {
+ ECDSA_SIG *sig;
+ const BIGNUM *r = NULL, *s = NULL;
+ if ((sig = ECDSA_do_sign(data, dlen, found->ecdsa)) != NULL) {
+ /* PKCS11 2.3.1 recommends both r and s to have the order size for
+ backward compatiblity */
+ ECDSA_SIG_get0(sig, &r, &s);
+ u_int o_len = EC_KEY_order_size(found->ecdsa);
+ u_int r_len = BN_num_bytes(r);
+ u_int s_len = BN_num_bytes(s);
+ if (o_len > 0 && r_len <= o_len && s_len <= o_len) {
+ signature = xcalloc(2, o_len);
+ BN_bn2bin(r, signature + o_len - r_len);
+ BN_bn2bin(s, signature + (2 * o_len) - s_len);
+ slen = 2 * o_len;
+ ok = 0;
+ }
+ ECDSA_SIG_free(sig);
+ }
+#endif /* ENABLE_PKCS11_ECDSA */
+ } else {
+ /* Unsupported type */
}
#endif /* WITH_OPENSSL */
}
diff -up openssh-7.6p1/ssh-pkcs11.h.pkcs11-ecdsa openssh-7.6p1/ssh-pkcs11.h
--- openssh-7.6p1/ssh-pkcs11.h.pkcs11-ecdsa 2018-02-16 13:25:59.429469272 +0100
+++ openssh-7.6p1/ssh-pkcs11.h 2018-02-16 13:45:29.623800048 +0100
@@ -20,6 +20,7 @@
int pkcs11_init(int);
void pkcs11_terminate(void);
int pkcs11_add_provider(char *, char *, struct sshkey ***);
+int pkcs11_del_key(struct sshkey *);
int pkcs11_add_provider_by_uri(struct pkcs11_uri *, char *, struct sshkey ***);
int pkcs11_del_provider(char *);
int pkcs11_uri_write(const struct sshkey *, FILE *);
diff -up openssh-7.6p1/ssh-pkcs11.c.old openssh-7.6p1/ssh-pkcs11.c
--- openssh-7.6p1/ssh-pkcs11.c.old 2018-02-16 16:43:08.861520255 +0100
+++ openssh-7.6p1/ssh-pkcs11.c 2018-02-16 16:56:35.312601451 +0100
@@ -917,13 +917,28 @@ pkcs11_fetch_keys_filter(struct pkcs11_p
} else if (d2i_X509(&x509, &cp, attribs[3].ulValueLen)
== NULL) {
error("d2i_X509 failed");
- } else if ((evp = X509_get_pubkey(x509)) == NULL ||
- evp->type != EVP_PKEY_RSA ||
- evp->pkey.rsa == NULL) {
- debug("X509_get_pubkey failed or no rsa");
- } else if ((rsa = RSAPublicKey_dup(evp->pkey.rsa))
- == NULL) {
- error("RSAPublicKey_dup");
+ } else if ((evp = X509_get_pubkey(x509)) == NULL) {
+ debug("X509_get_pubkey failed");
+ } else {
+ switch (evp->type) {
+ case EVP_PKEY_RSA:
+ if (evp->pkey.rsa == NULL)
+ debug("Missing RSA key");
+ else if ((rsa = RSAPublicKey_dup(
+ evp->pkey.rsa)) == NULL)
+ error("RSAPublicKey_dup failed");
+ break;
+ case EVP_PKEY_EC:
+ if (evp->pkey.ecdsa == NULL)
+ debug("Missing ECDSA key");
+ else if ((ecdsa = EC_KEY_dup(
+ evp->pkey.ecdsa)) == NULL)
+ error("EC_KEY_dup failed");
+ break;
+ default:
+ debug("not a RSA or ECDSA key");
+ break;
+ }
}
X509_free(x509);
EVP_PKEY_free(evp);

File diff suppressed because it is too large Load diff

View file

@ -1,70 +1,6 @@
diff -up openssh-7.7p1/cipher.c.fips openssh-7.7p1/cipher.c
--- openssh-7.7p1/cipher.c.fips 2018-08-08 10:08:40.814719906 +0200
+++ openssh-7.7p1/cipher.c 2018-08-08 10:08:40.821719965 +0200
@@ -39,6 +39,8 @@
#include <sys/types.h>
+#include <openssl/fips.h>
+
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
@@ -90,6 +92,33 @@ static const struct sshcipher ciphers[]
{ NULL, 0, 0, 0, 0, 0, NULL }
};
+static const struct sshcipher fips_ciphers[] = {
+#ifdef WITH_OPENSSL
+ { "3des-cbc", 8, 24, 0, 0, CFLAG_CBC, EVP_des_ede3_cbc },
+ { "aes128-cbc", 16, 16, 0, 0, CFLAG_CBC, EVP_aes_128_cbc },
+ { "aes192-cbc", 16, 24, 0, 0, CFLAG_CBC, EVP_aes_192_cbc },
+ { "aes256-cbc", 16, 32, 0, 0, CFLAG_CBC, EVP_aes_256_cbc },
+ { "rijndael-cbc@lysator.liu.se",
+ 16, 32, 0, 0, CFLAG_CBC, EVP_aes_256_cbc },
+ { "aes128-ctr", 16, 16, 0, 0, 0, EVP_aes_128_ctr },
+ { "aes192-ctr", 16, 24, 0, 0, 0, EVP_aes_192_ctr },
+ { "aes256-ctr", 16, 32, 0, 0, 0, EVP_aes_256_ctr },
+# ifdef OPENSSL_HAVE_EVPGCM
+ { "aes128-gcm@openssh.com",
+ 16, 16, 12, 16, 0, EVP_aes_128_gcm },
+ { "aes256-gcm@openssh.com",
+ 16, 32, 12, 16, 0, EVP_aes_256_gcm },
+# endif /* OPENSSL_HAVE_EVPGCM */
+#else
+ { "aes128-ctr", 16, 16, 0, 0, CFLAG_AESCTR, NULL },
+ { "aes192-ctr", 16, 24, 0, 0, CFLAG_AESCTR, NULL },
+ { "aes256-ctr", 16, 32, 0, 0, CFLAG_AESCTR, NULL },
+#endif
+ { "none", 8, 0, 0, 0, CFLAG_NONE, NULL },
+
+ { NULL, 0, 0, 0, 0, 0, NULL }
+};
+
/*--*/
/* Returns a comma-separated list of supported ciphers. */
@@ -100,7 +129,7 @@ cipher_alg_list(char sep, int auth_only)
size_t nlen, rlen = 0;
const struct sshcipher *c;
- for (c = ciphers; c->name != NULL; c++) {
+ for (c = FIPS_mode() ? fips_ciphers : ciphers; c->name != NULL; c++) {
if ((c->flags & CFLAG_INTERNAL) != 0)
continue;
if (auth_only && c->auth_len == 0)
@@ -172,7 +201,7 @@ const struct sshcipher *
cipher_by_name(const char *name)
{
const struct sshcipher *c;
- for (c = ciphers; c->name != NULL; c++)
+ for (c = FIPS_mode() ? fips_ciphers : ciphers; c->name != NULL; c++)
if (strcmp(c->name, name) == 0)
return c;
return NULL;
diff -up openssh-7.7p1/cipher-ctr.c.fips openssh-7.7p1/cipher-ctr.c
--- openssh-7.7p1/cipher-ctr.c.fips 2018-08-08 10:08:40.709719021 +0200
+++ openssh-7.7p1/cipher-ctr.c 2018-08-08 10:08:40.821719965 +0200
diff -up openssh-7.9p1/cipher-ctr.c.fips openssh-7.9p1/cipher-ctr.c
--- openssh-7.9p1/cipher-ctr.c.fips 2019-03-11 17:06:37.519877082 +0100
+++ openssh-7.9p1/cipher-ctr.c 2019-03-11 17:06:37.620878031 +0100
@@ -179,7 +179,8 @@ evp_aes_128_ctr(void)
aes_ctr.do_cipher = ssh_aes_ctr;
#ifndef SSH_OLD_EVP
@ -75,10 +11,10 @@ diff -up openssh-7.7p1/cipher-ctr.c.fips openssh-7.7p1/cipher-ctr.c
#endif
return (&aes_ctr);
}
diff -up openssh-7.7p1/clientloop.c.fips openssh-7.7p1/clientloop.c
--- openssh-7.7p1/clientloop.c.fips 2018-08-08 10:08:40.769719527 +0200
+++ openssh-7.7p1/clientloop.c 2018-08-08 10:08:40.822719973 +0200
@@ -1978,7 +1978,8 @@ key_accepted_by_hostkeyalgs(const struct
diff -up openssh-7.9p1/clientloop.c.fips openssh-7.9p1/clientloop.c
--- openssh-7.9p1/clientloop.c.fips 2019-03-11 17:06:37.523877120 +0100
+++ openssh-7.9p1/clientloop.c 2019-03-11 17:06:37.620878031 +0100
@@ -2014,7 +2014,8 @@ key_accepted_by_hostkeyalgs(const struct
{
const char *ktype = sshkey_ssh_name(key);
const char *hostkeyalgs = options.hostkeyalgorithms != NULL ?
@ -88,86 +24,75 @@ diff -up openssh-7.7p1/clientloop.c.fips openssh-7.7p1/clientloop.c
if (key == NULL || key->type == KEY_UNSPEC)
return 0;
diff -up openssh-7.7p1/dh.h.fips openssh-7.7p1/dh.h
--- openssh-7.7p1/dh.h.fips 2018-04-02 07:38:28.000000000 +0200
+++ openssh-7.7p1/dh.h 2018-08-08 10:08:40.822719973 +0200
@@ -51,6 +51,7 @@ u_int dh_estimate(int);
* Miniumum increased in light of DH precomputation attacks.
*/
#define DH_GRP_MIN 2048
+#define DH_GRP_MIN_FIPS 2048
#define DH_GRP_MAX 8192
diff -up openssh-7.9p1/dh.c.fips openssh-7.9p1/dh.c
--- openssh-7.9p1/dh.c.fips 2018-10-17 02:01:20.000000000 +0200
+++ openssh-7.9p1/dh.c 2019-03-11 17:08:11.769763057 +0100
@@ -152,6 +152,12 @@ choose_dh(int min, int wantbits, int max
int best, bestcount, which, linenum;
struct dhgroup dhg;
/*
diff -up openssh-7.7p1/entropy.c.fips openssh-7.7p1/entropy.c
--- openssh-7.7p1/entropy.c.fips 2018-08-08 10:08:40.698718928 +0200
+++ openssh-7.7p1/entropy.c 2018-08-08 10:08:40.822719973 +0200
@@ -217,6 +217,9 @@ seed_rng(void)
fatal("OpenSSL version mismatch. Built against %lx, you "
"have %lx", (u_long)OPENSSL_VERSION_NUMBER, SSLeay());
+ /* clean the PRNG status when exiting the program */
+ atexit(RAND_cleanup);
+ if (FIPS_mode()) {
+ verbose("Using arbitrary primes is not allowed in FIPS mode."
+ " Falling back to known groups.");
+ return (dh_new_group_fallback(max));
+ }
+
#ifndef OPENSSL_PRNG_ONLY
if (RAND_status() == 1) {
debug3("RNG is ready, skipping seeding");
diff -up openssh-7.7p1/kex.c.fips openssh-7.7p1/kex.c
--- openssh-7.7p1/kex.c.fips 2018-08-08 10:08:40.815719915 +0200
+++ openssh-7.7p1/kex.c 2018-08-08 10:11:24.109081924 +0200
@@ -35,6 +35,7 @@
#ifdef WITH_OPENSSL
#include <openssl/crypto.h>
#include <openssl/dh.h>
+#include <openssl/fips.h>
#endif
if ((f = fopen(_PATH_DH_MODULI, "r")) == NULL) {
logit("WARNING: could not open %s (%s), using fixed modulus",
_PATH_DH_MODULI, strerror(errno));
@@ -489,4 +495,38 @@ dh_estimate(int bits)
return 8192;
}
#include "ssh2.h"
@@ -122,6 +123,26 @@ static const struct kexalg kexalgs[] = {
{ NULL, -1, -1, -1},
};
+static const struct kexalg kexalgs_fips[] = {
+ { KEX_DH14_SHA256, KEX_DH_GRP14_SHA256, 0, SSH_DIGEST_SHA256 },
+ { KEX_DH16_SHA512, KEX_DH_GRP16_SHA512, 0, SSH_DIGEST_SHA512 },
+ { KEX_DH18_SHA512, KEX_DH_GRP18_SHA512, 0, SSH_DIGEST_SHA512 },
+#ifdef HAVE_EVP_SHA256
+ { KEX_DHGEX_SHA256, KEX_DH_GEX_SHA256, 0, SSH_DIGEST_SHA256 },
+#endif
+#ifdef OPENSSL_HAS_ECC
+ { KEX_ECDH_SHA2_NISTP256, KEX_ECDH_SHA2,
+ NID_X9_62_prime256v1, SSH_DIGEST_SHA256 },
+ { KEX_ECDH_SHA2_NISTP384, KEX_ECDH_SHA2, NID_secp384r1,
+ SSH_DIGEST_SHA384 },
+# ifdef OPENSSL_HAS_NISTP521
+ { KEX_ECDH_SHA2_NISTP521, KEX_ECDH_SHA2, NID_secp521r1,
+ SSH_DIGEST_SHA512 },
+# endif
+#endif
+ { NULL, -1, -1, -1},
+};
+/*
+ * Compares the received DH parameters with known-good groups,
+ * which might be either from group14, group16 or group18.
+ */
+int
+dh_is_known_group(const DH *dh)
+{
+ const BIGNUM *p, *g;
+ const BIGNUM *known_p, *known_g;
+ DH *known = NULL;
+ int bits = 0, rv = 0;
+
char *
kex_alg_list(char sep)
{
@@ -129,7 +150,7 @@ kex_alg_list(char sep)
size_t nlen, rlen = 0;
const struct kexalg *k;
+ DH_get0_pqg(dh, &p, NULL, &g);
+ bits = BN_num_bits(p);
+
+ if (bits <= 3072) {
+ known = dh_new_group14();
+ } else if (bits <= 6144) {
+ known = dh_new_group16();
+ } else {
+ known = dh_new_group18();
+ }
+
+ DH_get0_pqg(known, &known_p, NULL, &known_g);
+
+ if (BN_cmp(g, known_g) == 0 &&
+ BN_cmp(p, known_p) == 0) {
+ rv = 1;
+ }
+
+ DH_free(known);
+ return rv;
+}
+
#endif /* WITH_OPENSSL */
diff -up openssh-7.9p1/dh.h.fips openssh-7.9p1/dh.h
--- openssh-7.9p1/dh.h.fips 2018-10-17 02:01:20.000000000 +0200
+++ openssh-7.9p1/dh.h 2019-03-11 17:08:18.718828381 +0100
@@ -43,6 +43,7 @@ DH *dh_new_group_fallback(int);
- for (k = kexalgs; k->name != NULL; k++) {
+ for (k = (FIPS_mode() ? kexalgs_fips : kexalgs); k->name != NULL; k++) {
if (ret != NULL)
ret[rlen++] = sep;
nlen = strlen(k->name);
@@ -149,7 +170,7 @@ kex_alg_by_name(const char *name)
{
const struct kexalg *k;
int dh_gen_key(DH *, int);
int dh_pub_is_valid(const DH *, const BIGNUM *);
+int dh_is_known_group(const DH *);
- for (k = kexalgs; k->name != NULL; k++) {
+ for (k = (FIPS_mode() ? kexalgs_fips : kexalgs); k->name != NULL; k++) {
if (strcmp(k->name, name) == 0)
return k;
#ifdef GSSAPI
u_int dh_estimate(int);
diff -up openssh-7.9p1/kex.c.fips openssh-7.9p1/kex.c
--- openssh-7.9p1/kex.c.fips 2019-03-11 17:06:37.614877975 +0100
+++ openssh-7.9p1/kex.c 2019-03-11 17:06:37.621878041 +0100
@@ -175,7 +196,10 @@ kex_names_valid(const char *names)
for ((p = strsep(&cp, ",")); p && *p != '\0';
(p = strsep(&cp, ","))) {
@ -180,158 +105,39 @@ diff -up openssh-7.7p1/kex.c.fips openssh-7.7p1/kex.c
free(s);
return 0;
}
diff -up openssh-7.7p1/kexgexc.c.fips openssh-7.7p1/kexgexc.c
--- openssh-7.7p1/kexgexc.c.fips 2018-04-02 07:38:28.000000000 +0200
+++ openssh-7.7p1/kexgexc.c 2018-08-08 10:08:40.822719973 +0200
diff -up openssh-7.9p1/kexgexc.c.fips openssh-7.9p1/kexgexc.c
--- openssh-7.9p1/kexgexc.c.fips 2018-10-17 02:01:20.000000000 +0200
+++ openssh-7.9p1/kexgexc.c 2019-03-11 17:06:37.621878041 +0100
@@ -28,6 +28,7 @@
#ifdef WITH_OPENSSL
+#include <openssl/fips.h>
+#include <openssl/crypto.h>
#include <sys/types.h>
#include <openssl/dh.h>
@@ -63,7 +64,7 @@ kexgex_client(struct ssh *ssh)
@@ -118,6 +119,10 @@ input_kex_dh_gex_group(int type, u_int32
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
+ if (FIPS_mode() && dh_is_known_group(kex->dh) == 0) {
+ r = SSH_ERR_INVALID_ARGUMENT;
+ goto out;
+ }
p = g = NULL; /* belong to kex->dh now */
nbits = dh_estimate(kex->dh_need * 8);
- kex->min = DH_GRP_MIN;
+ kex->min = FIPS_mode() ? DH_GRP_MIN_FIPS : DH_GRP_MIN;
kex->max = DH_GRP_MAX;
kex->nbits = nbits;
if (datafellows & SSH_BUG_DHGEX_LARGE)
diff -up openssh-7.7p1/kexgexs.c.fips openssh-7.7p1/kexgexs.c
--- openssh-7.7p1/kexgexs.c.fips 2018-04-02 07:38:28.000000000 +0200
+++ openssh-7.7p1/kexgexs.c 2018-08-08 10:08:40.823719982 +0200
@@ -82,9 +82,9 @@ input_kex_dh_gex_request(int type, u_int
kex->nbits = nbits;
kex->min = min;
kex->max = max;
- min = MAXIMUM(DH_GRP_MIN, min);
+ min = MAXIMUM(FIPS_mode() ? DH_GRP_MIN_FIPS : DH_GRP_MIN, min);
max = MINIMUM(DH_GRP_MAX, max);
- nbits = MAXIMUM(DH_GRP_MIN, nbits);
+ nbits = MAXIMUM(FIPS_mode() ? DH_GRP_MIN_FIPS : DH_GRP_MIN, nbits);
nbits = MINIMUM(DH_GRP_MAX, nbits);
if (kex->max < kex->min || kex->nbits < kex->min ||
diff -up openssh-7.7p1/mac.c.fips openssh-7.7p1/mac.c
--- openssh-7.7p1/mac.c.fips 2018-08-08 10:08:40.815719915 +0200
+++ openssh-7.7p1/mac.c 2018-08-08 10:11:56.915352642 +0200
@@ -27,6 +27,8 @@
#include <sys/types.h>
+#include <openssl/fips.h>
+
#include <string.h>
#include <stdio.h>
@@ -54,7 +56,7 @@ struct macalg {
int etm; /* Encrypt-then-MAC */
};
-static const struct macalg macs[] = {
+static const struct macalg all_macs[] = {
/* Encrypt-and-MAC (encrypt-and-authenticate) variants */
{ "hmac-sha1", SSH_DIGEST, SSH_DIGEST_SHA1, 0, 0, 0, 0 },
{ "hmac-sha1-96", SSH_DIGEST, SSH_DIGEST_SHA1, 96, 0, 0, 0 },
@@ -82,6 +84,24 @@ static const struct macalg macs[] = {
{ NULL, 0, 0, 0, 0, 0, 0 }
};
+static const struct macalg fips_macs[] = {
+ /* Encrypt-and-MAC (encrypt-and-authenticate) variants */
+ { "hmac-sha1", SSH_DIGEST, SSH_DIGEST_SHA1, 0, 0, 0, 0 },
+#ifdef HAVE_EVP_SHA256
+ { "hmac-sha2-256", SSH_DIGEST, SSH_DIGEST_SHA256, 0, 0, 0, 0 },
+ { "hmac-sha2-512", SSH_DIGEST, SSH_DIGEST_SHA512, 0, 0, 0, 0 },
+#endif
+
+ /* Encrypt-then-MAC variants */
+ { "hmac-sha1-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_SHA1, 0, 0, 0, 1 },
+#ifdef HAVE_EVP_SHA256
+ { "hmac-sha2-256-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_SHA256, 0, 0, 0, 1 },
+ { "hmac-sha2-512-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_SHA512, 0, 0, 0, 1 },
+#endif
+
+ { NULL, 0, 0, 0, 0, 0, 0 }
+};
+
/* Returns a list of supported MACs separated by the specified char. */
char *
mac_alg_list(char sep)
@@ -90,7 +110,7 @@ mac_alg_list(char sep)
size_t nlen, rlen = 0;
const struct macalg *m;
- for (m = macs; m->name != NULL; m++) {
+ for (m = FIPS_mode() ? fips_macs : all_macs; m->name != NULL; m++) {
if (ret != NULL)
ret[rlen++] = sep;
nlen = strlen(m->name);
@@ -129,7 +149,7 @@ mac_setup(struct sshmac *mac, char *name
{
const struct macalg *m;
- for (m = macs; m->name != NULL; m++) {
+ for (m = FIPS_mode() ? fips_macs : all_macs; m->name != NULL; m++) {
if (strcmp(name, m->name) != 0)
continue;
if (mac != NULL)
diff -up openssh-7.7p1/Makefile.in.fips openssh-7.7p1/Makefile.in
--- openssh-7.7p1/Makefile.in.fips 2018-08-08 10:08:40.815719915 +0200
+++ openssh-7.7p1/Makefile.in 2018-08-08 10:08:40.823719982 +0200
@@ -179,25 +179,25 @@ libssh.a: $(LIBSSH_OBJS)
$(RANLIB) $@
ssh$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHOBJS)
- $(LD) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHLIBS) $(LIBS) $(GSSLIBS)
+ $(LD) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(SSHLIBS) $(LIBS) $(GSSLIBS)
sshd$(EXEEXT): libssh.a $(LIBCOMPAT) $(SSHDOBJS)
- $(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHDLIBS) $(LIBS) $(GSSLIBS) $(K5LIBS)
+ $(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(SSHDLIBS) $(LIBS) $(GSSLIBS) $(K5LIBS)
scp$(EXEEXT): $(LIBCOMPAT) libssh.a scp.o progressmeter.o
$(LD) -o $@ scp.o progressmeter.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
ssh-add$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-add.o
- $(LD) -o $@ ssh-add.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
+ $(LD) -o $@ ssh-add.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS)
ssh-agent$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-agent.o ssh-pkcs11-client.o
- $(LD) -o $@ ssh-agent.o ssh-pkcs11-client.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
+ $(LD) -o $@ ssh-agent.o ssh-pkcs11-client.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS)
ssh-keygen$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keygen.o
- $(LD) -o $@ ssh-keygen.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
+ $(LD) -o $@ ssh-keygen.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS)
ssh-keysign$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keysign.o readconf.o uidswap.o
- $(LD) -o $@ ssh-keysign.o readconf.o uidswap.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
+ $(LD) -o $@ ssh-keysign.o readconf.o uidswap.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS)
ssh-pkcs11-helper$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-pkcs11-helper.o ssh-pkcs11.o
$(LD) -o $@ ssh-pkcs11-helper.o ssh-pkcs11.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
@@ -215,7 +215,7 @@ ssh-cavs$(EXEEXT): $(LIBCOMPAT) libssh.a
$(LD) -o $@ ssh-cavs.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keyscan.o
- $(LD) -o $@ ssh-keyscan.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS)
+ $(LD) -o $@ ssh-keyscan.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lfipscheck $(LIBS)
sftp-server$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-common.o sftp-server.o sftp-server-main.o
$(LD) -o $@ sftp-server.o sftp-common.o sftp-server-main.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
diff -up openssh-7.7p1/myproposal.h.fips openssh-7.7p1/myproposal.h
--- openssh-7.7p1/myproposal.h.fips 2018-04-02 07:38:28.000000000 +0200
+++ openssh-7.7p1/myproposal.h 2018-08-08 10:08:40.823719982 +0200
@@ -114,6 +114,14 @@
/* generate and send 'e', client DH public key */
diff -up openssh-7.9p1/myproposal.h.fips openssh-7.9p1/myproposal.h
--- openssh-7.9p1/myproposal.h.fips 2018-10-17 02:01:20.000000000 +0200
+++ openssh-7.9p1/myproposal.h 2019-03-11 17:06:37.621878041 +0100
@@ -116,6 +116,16 @@
"rsa-sha2-256," \
"ssh-rsa"
+#define KEX_FIPS_PK_ALG \
+ HOSTKEY_ECDSA_CERT_METHODS \
+ "rsa-sha2-512-cert-v01@openssh.com," \
+ "rsa-sha2-256-cert-v01@openssh.com," \
+ "ssh-rsa-cert-v01@openssh.com," \
+ HOSTKEY_ECDSA_METHODS \
+ "rsa-sha2-512," \
@ -341,7 +147,7 @@ diff -up openssh-7.7p1/myproposal.h.fips openssh-7.7p1/myproposal.h
/* the actual algorithms */
#define KEX_SERVER_ENCRYPT \
@@ -137,6 +145,38 @@
@@ -139,6 +147,38 @@
#define KEX_CLIENT_MAC KEX_SERVER_MAC
@ -377,16 +183,16 @@ diff -up openssh-7.7p1/myproposal.h.fips openssh-7.7p1/myproposal.h
+ "hmac-sha1"
+#endif
+
#else /* WITH_OPENSSL */
#define KEX_SERVER_KEX \
diff -up openssh-7.7p1/readconf.c.fips openssh-7.7p1/readconf.c
--- openssh-7.7p1/readconf.c.fips 2018-08-08 10:08:40.769719527 +0200
+++ openssh-7.7p1/readconf.c 2018-08-08 10:08:40.824719990 +0200
@@ -2081,17 +2081,18 @@ fill_default_options(Options * options)
all_mac = mac_alg_list(',');
/* Not a KEX value, but here so all the algorithm defaults are together */
#define SSH_ALLOWED_CA_SIGALGS \
"ecdsa-sha2-nistp256," \
diff -up openssh-7.9p1/readconf.c.fips openssh-7.9p1/readconf.c
--- openssh-7.9p1/readconf.c.fips 2019-03-11 17:06:37.601877853 +0100
+++ openssh-7.9p1/readconf.c 2019-03-11 17:06:37.622878050 +0100
@@ -2178,18 +2178,19 @@ fill_default_options(Options * options)
all_kex = kex_alg_list(',');
all_key = sshkey_alg_list(0, 0, 1, ',');
all_sig = sshkey_alg_list(0, 1, 1, ',');
-#define ASSEMBLE(what, defaults, all) \
+#define ASSEMBLE(what, defaults, fips_defaults, all) \
do { \
@ -396,22 +202,24 @@ diff -up openssh-7.7p1/readconf.c.fips openssh-7.7p1/readconf.c
+ all)) != 0) \
fatal("%s: %s: %s", __func__, #what, ssh_err(r)); \
} while (0)
- ASSEMBLE(ciphers, KEX_SERVER_ENCRYPT, all_cipher);
- ASSEMBLE(macs, KEX_SERVER_MAC, all_mac);
- ASSEMBLE(kex_algorithms, KEX_SERVER_KEX, all_kex);
- ASSEMBLE(ciphers, KEX_CLIENT_ENCRYPT, all_cipher);
- ASSEMBLE(macs, KEX_CLIENT_MAC, all_mac);
- ASSEMBLE(kex_algorithms, KEX_CLIENT_KEX, all_kex);
- ASSEMBLE(hostbased_key_types, KEX_DEFAULT_PK_ALG, all_key);
- ASSEMBLE(pubkey_key_types, KEX_DEFAULT_PK_ALG, all_key);
+ ASSEMBLE(ciphers, KEX_SERVER_ENCRYPT, KEX_FIPS_ENCRYPT, all_cipher);
+ ASSEMBLE(macs, KEX_SERVER_MAC, KEX_FIPS_MAC, all_mac);
+ ASSEMBLE(kex_algorithms, KEX_SERVER_KEX, KEX_DEFAULT_KEX_FIPS, all_kex);
- ASSEMBLE(ca_sign_algorithms, SSH_ALLOWED_CA_SIGALGS, all_sig);
+ ASSEMBLE(ciphers, KEX_CLIENT_ENCRYPT, KEX_FIPS_ENCRYPT, all_cipher);
+ ASSEMBLE(macs, KEX_CLIENT_MAC, KEX_FIPS_MAC, all_mac);
+ ASSEMBLE(kex_algorithms, KEX_CLIENT_KEX, KEX_DEFAULT_KEX_FIPS, all_kex);
+ ASSEMBLE(hostbased_key_types, KEX_DEFAULT_PK_ALG, KEX_FIPS_PK_ALG, all_key);
+ ASSEMBLE(pubkey_key_types, KEX_DEFAULT_PK_ALG, KEX_FIPS_PK_ALG, all_key);
+ ASSEMBLE(ca_sign_algorithms, SSH_ALLOWED_CA_SIGALGS, KEX_FIPS_PK_ALG, all_sig);
#undef ASSEMBLE
free(all_cipher);
free(all_mac);
diff -up openssh-7.7p1/sandbox-seccomp-filter.c.fips openssh-7.7p1/sandbox-seccomp-filter.c
--- openssh-7.7p1/sandbox-seccomp-filter.c.fips 2018-08-08 10:08:40.794719737 +0200
+++ openssh-7.7p1/sandbox-seccomp-filter.c 2018-08-08 10:08:40.824719990 +0200
diff -up openssh-7.9p1/sandbox-seccomp-filter.c.fips openssh-7.9p1/sandbox-seccomp-filter.c
--- openssh-7.9p1/sandbox-seccomp-filter.c.fips 2019-03-11 17:06:37.586877712 +0100
+++ openssh-7.9p1/sandbox-seccomp-filter.c 2019-03-11 17:06:37.622878050 +0100
@@ -137,6 +137,9 @@ static const struct sock_filter preauth_
#ifdef __NR_open
SC_DENY(__NR_open, EACCES),
@ -422,13 +230,13 @@ diff -up openssh-7.7p1/sandbox-seccomp-filter.c.fips openssh-7.7p1/sandbox-secco
#ifdef __NR_openat
SC_DENY(__NR_openat, EACCES),
#endif
diff -up openssh-7.7p1/servconf.c.fips openssh-7.7p1/servconf.c
--- openssh-7.7p1/servconf.c.fips 2018-08-08 10:08:40.778719603 +0200
+++ openssh-7.7p1/servconf.c 2018-08-08 10:08:40.824719990 +0200
@@ -196,17 +196,18 @@ option_clear_or_none(const char *o)
all_mac = mac_alg_list(',');
diff -up openssh-7.9p1/servconf.c.fips openssh-7.9p1/servconf.c
--- openssh-7.9p1/servconf.c.fips 2019-03-11 17:06:37.568877543 +0100
+++ openssh-7.9p1/servconf.c 2019-03-11 17:06:37.622878050 +0100
@@ -209,18 +209,19 @@ assemble_algorithms(ServerOptions *o)
all_kex = kex_alg_list(',');
all_key = sshkey_alg_list(0, 0, 1, ',');
all_sig = sshkey_alg_list(0, 1, 1, ',');
-#define ASSEMBLE(what, defaults, all) \
+#define ASSEMBLE(what, defaults, fips_defaults, all) \
do { \
@ -443,129 +251,65 @@ diff -up openssh-7.7p1/servconf.c.fips openssh-7.7p1/servconf.c
- ASSEMBLE(hostkeyalgorithms, KEX_DEFAULT_PK_ALG, all_key);
- ASSEMBLE(hostbased_key_types, KEX_DEFAULT_PK_ALG, all_key);
- ASSEMBLE(pubkey_key_types, KEX_DEFAULT_PK_ALG, all_key);
- ASSEMBLE(ca_sign_algorithms, SSH_ALLOWED_CA_SIGALGS, all_sig);
+ ASSEMBLE(ciphers, KEX_SERVER_ENCRYPT, KEX_FIPS_ENCRYPT, all_cipher);
+ ASSEMBLE(macs, KEX_SERVER_MAC, KEX_FIPS_MAC, all_mac);
+ ASSEMBLE(kex_algorithms, KEX_SERVER_KEX, KEX_DEFAULT_KEX_FIPS, all_kex);
+ ASSEMBLE(hostkeyalgorithms, KEX_DEFAULT_PK_ALG, KEX_FIPS_PK_ALG, all_key);
+ ASSEMBLE(hostbased_key_types, KEX_DEFAULT_PK_ALG, KEX_FIPS_PK_ALG, all_key);
+ ASSEMBLE(pubkey_key_types, KEX_DEFAULT_PK_ALG, KEX_FIPS_PK_ALG, all_key);
+ ASSEMBLE(ca_sign_algorithms, SSH_ALLOWED_CA_SIGALGS, KEX_FIPS_PK_ALG, all_sig);
#undef ASSEMBLE
free(all_cipher);
free(all_mac);
diff -up openssh-7.7p1/ssh.c.fips openssh-7.7p1/ssh.c
--- openssh-7.7p1/ssh.c.fips 2018-08-08 10:08:40.811719881 +0200
+++ openssh-7.7p1/ssh.c 2018-08-08 10:08:40.825719999 +0200
@@ -76,6 +76,8 @@
diff -up openssh-7.9p1/ssh.c.fips openssh-7.9p1/ssh.c
--- openssh-7.9p1/ssh.c.fips 2019-03-11 17:06:37.602877862 +0100
+++ openssh-7.9p1/ssh.c 2019-03-11 17:06:37.623878060 +0100
@@ -76,6 +76,7 @@
#include <openssl/evp.h>
#include <openssl/err.h>
#endif
+#include <openssl/fips.h>
+#include <fipscheck.h>
+#include <openssl/crypto.h>
#include "openbsd-compat/openssl-compat.h"
#include "openbsd-compat/sys-queue.h"
@@ -579,6 +581,14 @@ main(int ac, char **av)
sanitise_stdfd();
__progname = ssh_get_progname(av[0]);
+ SSLeay_add_all_algorithms();
+ if (access("/etc/system-fips", F_OK) == 0)
+ if (! FIPSCHECK_verify(NULL, NULL)){
+ if (FIPS_mode())
+ fatal("FIPS integrity verification test failed.");
+ else
+ logit("FIPS integrity verification test failed.");
+ }
#ifndef HAVE_SETPROCTITLE
/* Prepare for later setproctitle emulation */
@@ -1045,7 +1055,6 @@ main(int ac, char **av)
host_arg = xstrdup(host);
#ifdef WITH_OPENSSL
- OpenSSL_add_all_algorithms();
ERR_load_crypto_strings();
#endif
@@ -1268,6 +1277,10 @@ main(int ac, char **av)
seed_rng();
+ if (FIPS_mode()) {
+ logit("FIPS mode initialized");
+ }
@@ -1283,6 +1294,10 @@ main(int ac, char **av)
dump_client_config(&options, host);
exit(0);
}
+
if (options.user == NULL)
options.user = xstrdup(pw->pw_name);
+ if (FIPS_mode()) {
+ debug("FIPS mode initialized");
+ }
diff -up openssh-7.7p1/sshconnect2.c.fips openssh-7.7p1/sshconnect2.c
--- openssh-7.7p1/sshconnect2.c.fips 2018-08-08 10:08:40.786719670 +0200
+++ openssh-7.7p1/sshconnect2.c 2018-08-08 10:08:40.825719999 +0200
if (muxclient_command != 0 && options.control_path == NULL)
fatal("No ControlPath specified for \"-O\" command");
diff -up openssh-7.9p1/sshconnect2.c.fips openssh-7.9p1/sshconnect2.c
--- openssh-7.9p1/sshconnect2.c.fips 2019-03-11 17:06:37.580877655 +0100
+++ openssh-7.9p1/sshconnect2.c 2019-03-11 17:06:37.623878060 +0100
@@ -44,6 +44,8 @@
#include <vis.h>
#endif
+#include <openssl/fips.h>
+#include <openssl/crypto.h>
+
#include "openbsd-compat/sys-queue.h"
#include "xmalloc.h"
@@ -235,7 +237,8 @@ order_hostkeyalgs(char *host, struct soc
for (i = 0; i < options.num_system_hostfiles; i++)
load_hostkeys(hostkeys, hostname, options.system_hostfiles[i]);
@@ -148,7 +150,8 @@ order_hostkeyalgs(char *host, struct soc
* Otherwise, prefer the host key algorithms that match known keys
* while keeping the ordering of HostkeyAlgorithms as much as possible.
*/
- oavail = avail = xstrdup(KEX_DEFAULT_PK_ALG);
+ oavail = avail = xstrdup((FIPS_mode()
+ ? KEX_FIPS_PK_ALG : KEX_DEFAULT_PK_ALG));
maxlen = strlen(avail) + 1;
first = xmalloc(maxlen);
last = xmalloc(maxlen);
@@ -290,21 +293,26 @@ ssh_kex2(char *host, struct sockaddr *ho
#ifdef GSSAPI
if (options.gss_keyex) {
- /* Add the GSSAPI mechanisms currently supported on this
- * client to the key exchange algorithm proposal */
- orig = options.kex_algorithms;
-
- if (options.gss_trust_dns)
- gss_host = (char *)get_canonical_hostname(active_state, 1);
- else
- gss_host = host;
-
- gss = ssh_gssapi_client_mechanisms(gss_host,
- options.gss_client_identity, options.gss_kex_algorithms);
- if (gss) {
- debug("Offering GSSAPI proposal: %s", gss);
- xasprintf(&options.kex_algorithms,
- "%s,%s", gss, orig);
+ if (FIPS_mode()) {
+ logit("Disabling GSSAPIKeyExchange. Not usable in FIPS mode");
+ options.gss_keyex = 0;
+ } else {
+ /* Add the GSSAPI mechanisms currently supported on this
+ * client to the key exchange algorithm proposal */
+ orig = options.kex_algorithms;
+
+ if (options.gss_trust_dns)
+ gss_host = (char *)get_canonical_hostname(active_state, 1);
+ else
+ gss_host = host;
+
+ gss = ssh_gssapi_client_mechanisms(gss_host,
+ options.gss_client_identity, options.gss_kex_algorithms);
+ if (gss) {
+ debug("Offering GSSAPI proposal: %s", gss);
+ xasprintf(&options.kex_algorithms,
+ "%s,%s", gss, orig);
+ }
}
}
#endif
@@ -322,14 +330,16 @@ ssh_kex2(char *host, struct sockaddr *ho
@@ -229,14 +232,16 @@ ssh_kex2(struct ssh *ssh, char *host, st
if (options.hostkeyalgorithms != NULL) {
all_key = sshkey_alg_list(0, 0, 1, ',');
if (kex_assemble_names(&options.hostkeyalgorithms,
if (kex_assemble_names(&options.hostkeyalgorithms,
- KEX_DEFAULT_PK_ALG, all_key) != 0)
+ (FIPS_mode() ? KEX_FIPS_PK_ALG : KEX_DEFAULT_PK_ALG),
+ all_key) != 0)
@ -581,9 +325,79 @@ diff -up openssh-7.7p1/sshconnect2.c.fips openssh-7.7p1/sshconnect2.c
/* Prefer algorithms that we already have keys for */
myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] =
compat_pkalg_proposal(
diff -up openssh-7.7p1/sshd.c.fips openssh-7.7p1/sshd.c
--- openssh-7.7p1/sshd.c.fips 2018-08-08 10:08:40.818719940 +0200
+++ openssh-7.7p1/sshd.c 2018-08-08 10:08:40.826720007 +0200
@@ -201,35 +201,40 @@ ssh_kex2(char *host, struct sockaddr *ho
#if defined(GSSAPI) && defined(WITH_OPENSSL)
if (options.gss_keyex) {
- /* Add the GSSAPI mechanisms currently supported on this
- * client to the key exchange algorithm proposal */
- orig = myproposal[PROPOSAL_KEX_ALGS];
-
- if (options.gss_server_identity) {
- gss_host = xstrdup(options.gss_server_identity);
- } else if (options.gss_trust_dns) {
- gss_host = remote_hostname(ssh);
- /* Fall back to specified host if we are using proxy command
- * and can not use DNS on that socket */
- if (strcmp(gss_host, "UNKNOWN") == 0) {
- gss_host = xstrdup(host);
- }
- } else {
- gss_host = xstrdup(host);
- }
-
- gss = ssh_gssapi_client_mechanisms(gss_host,
- options.gss_client_identity, options.gss_kex_algorithms);
- if (gss) {
- debug("Offering GSSAPI proposal: %s", gss);
- xasprintf(&myproposal[PROPOSAL_KEX_ALGS],
- "%s,%s", gss, orig);
-
- /* If we've got GSSAPI algorithms, then we also support the
- * 'null' hostkey, as a last resort */
- orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS];
- xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS],
- "%s,null", orig);
+ if (FIPS_mode()) {
+ logit("Disabling GSSAPIKeyExchange. Not usable in FIPS mode");
+ options.gss_keyex = 0;
+ } else {
+ /* Add the GSSAPI mechanisms currently supported on this
+ * client to the key exchange algorithm proposal */
+ orig = myproposal[PROPOSAL_KEX_ALGS];
+
+ if (options.gss_server_identity) {
+ gss_host = xstrdup(options.gss_server_identity);
+ } else if (options.gss_trust_dns) {
+ gss_host = remote_hostname(ssh);
+ /* Fall back to specified host if we are using proxy command
+ * and can not use DNS on that socket */
+ if (strcmp(gss_host, "UNKNOWN") == 0) {
+ gss_host = xstrdup(host);
+ }
+ } else {
+ gss_host = xstrdup(host);
+ }
+
+ gss = ssh_gssapi_client_mechanisms(gss_host,
+ options.gss_client_identity, options.gss_kex_algorithms);
+ if (gss) {
+ debug("Offering GSSAPI proposal: %s", gss);
+ xasprintf(&myproposal[PROPOSAL_KEX_ALGS],
+ "%s,%s", gss, orig);
+
+ /* If we've got GSSAPI algorithms, then we also support the
+ * 'null' hostkey, as a last resort */
+ orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS];
+ xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS],
+ "%s,null", orig);
+ }
}
}
#endif
diff -up openssh-7.9p1/sshd.c.fips openssh-7.9p1/sshd.c
--- openssh-7.9p1/sshd.c.fips 2019-03-11 17:06:37.617878003 +0100
+++ openssh-7.9p1/sshd.c 2019-03-11 17:06:37.624878069 +0100
@@ -66,6 +66,7 @@
#include <grp.h>
#include <pwd.h>
@ -592,55 +406,34 @@ diff -up openssh-7.7p1/sshd.c.fips openssh-7.7p1/sshd.c
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
@@ -77,6 +78,8 @@
@@ -77,6 +78,7 @@
#include <openssl/dh.h>
#include <openssl/bn.h>
#include <openssl/rand.h>
+#include <openssl/fips.h>
+#include <fipscheck.h>
+#include <openssl/crypto.h>
#include "openbsd-compat/openssl-compat.h"
#endif
@@ -1534,6 +1537,18 @@ main(int ac, char **av)
@@ -1581,6 +1584,7 @@ main(int ac, char **av)
#endif
__progname = ssh_get_progname(av[0]);
+ SSLeay_add_all_algorithms();
+ if (access("/etc/system-fips", F_OK) == 0)
+ if (! FIPSCHECK_verify(NULL, NULL)) {
+ openlog(__progname, LOG_PID, LOG_AUTHPRIV);
+ if (FIPS_mode()) {
+ syslog(LOG_CRIT, "FIPS integrity verification test failed.");
+ cleanup_exit(255);
+ }
+ else
+ syslog(LOG_INFO, "FIPS integrity verification test failed.");
+ closelog();
+ }
+ OpenSSL_add_all_algorithms();
/* Save argv. Duplicate so setproctitle emulation doesn't clobber it */
saved_argc = ac;
rexec_argc = ac;
@@ -1675,7 +1690,7 @@ main(int ac, char **av)
else
closefrom(REEXEC_DEVCRYPTO_RESERVED_FD);
-#ifdef WITH_OPENSSL
+#if 0 /* FIPS */
OpenSSL_add_all_algorithms();
#endif
@@ -1979,6 +1994,10 @@ main(int ac, char **av)
@@ -2036,6 +2051,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);
+ if (FIPS_mode()) {
+ logit("FIPS mode initialized");
+ debug("FIPS mode initialized");
+ }
+
/* Chdir to the root directory so that the current disk can be
unmounted if desired. */
if (chdir("/") == -1)
@@ -2359,10 +2378,14 @@ do_ssh2_kex(void)
@@ -2412,10 +2431,14 @@ do_ssh2_kex(void)
if (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]) == 0)
orig = NULL;
@ -659,14 +452,14 @@ diff -up openssh-7.7p1/sshd.c.fips openssh-7.7p1/sshd.c
if (gss && orig)
xasprintf(&newstr, "%s,%s", gss, orig);
diff -up openssh-7.7p1/sshkey.c.fips openssh-7.7p1/sshkey.c
--- openssh-7.7p1/sshkey.c.fips 2018-08-08 10:08:40.818719940 +0200
+++ openssh-7.7p1/sshkey.c 2018-08-08 10:08:40.826720007 +0200
diff -up openssh-7.9p1/sshkey.c.fips openssh-7.9p1/sshkey.c
--- openssh-7.9p1/sshkey.c.fips 2019-03-11 17:06:37.617878003 +0100
+++ openssh-7.9p1/sshkey.c 2019-03-11 17:06:37.624878069 +0100
@@ -34,6 +34,7 @@
#include <openssl/evp.h>
#include <openssl/err.h>
#include <openssl/pem.h>
+#include <openssl/fips.h>
+#include <openssl/crypto.h>
#endif
#include "crypto_api.h"
@ -678,19 +471,60 @@ diff -up openssh-7.7p1/sshkey.c.fips openssh-7.7p1/sshkey.c
#include "xmss_fast.h"
@@ -1526,6 +1528,8 @@ rsa_generate_private_key(u_int bits, RSA
@@ -392,7 +394,8 @@ sshkey_calculate_signature(EVP_PKEY *pkey
{
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;
@@ -411,9 +414,10 @@ sshkey_calculate_signature(EVP_PKEY *pkey
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;
}
@@ -440,12 +444,13 @@ sshkey_verify_signature(EVP_PKEY *pkey
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;
@@ -1514,6 +1516,8 @@ rsa_generate_private_key(u_int bits, RSA
}
if (!BN_set_word(f4, RSA_F4) ||
!RSA_generate_key_ex(private, bits, f4, NULL)) {
+ if (FIPS_mode())
+ logit("%s: the key length might be unsupported by FIPS mode approved key generation method", __func__);
+ if (FIPS_mode())
+ logit("%s: the key length might be unsupported by FIPS mode approved key generation method", __func__);
ret = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
diff -up openssh-7.7p1/ssh-keygen.c.fips openssh-7.7p1/ssh-keygen.c
--- openssh-7.7p1/ssh-keygen.c.fips 2018-08-08 10:08:40.801719797 +0200
+++ openssh-7.7p1/ssh-keygen.c 2018-08-08 10:08:40.827720016 +0200
@@ -229,6 +229,12 @@ type_bits_valid(int type, const char *na
diff -up openssh-7.9p1/ssh-keygen.c.fips openssh-7.9p1/ssh-keygen.c
--- openssh-7.9p1/ssh-keygen.c.fips 2019-03-11 17:06:37.590877750 +0100
+++ openssh-7.9p1/ssh-keygen.c 2019-03-11 17:06:37.625878079 +0100
@@ -230,6 +230,12 @@ type_bits_valid(int type, const char *na
OPENSSL_DSA_MAX_MODULUS_BITS : OPENSSL_RSA_MAX_MODULUS_BITS;
if (*bitsp > maxbits)
fatal("key bits exceeds maximum %d", maxbits);
@ -703,3 +537,33 @@ diff -up openssh-7.7p1/ssh-keygen.c.fips openssh-7.7p1/ssh-keygen.c
switch (type) {
case KEY_DSA:
if (*bitsp != 1024)
@@ -1029,9 +1035,17 @@ do_gen_all_hostkeys(struct passwd *pw)
first = 1;
printf("%s: generating new host keys: ", __progname);
}
+ type = sshkey_type_from_name(key_types[i].key_type);
+
+ /* Skip the keys that are not supported in FIPS mode */
+ if (FIPS_mode() && (type == KEY_DSA || type == KEY_ED25519)) {
+ logit("Skipping %s key in FIPS mode",
+ key_types[i].key_type_display);
+ goto next;
+ }
+
printf("%s ", key_types[i].key_type_display);
fflush(stdout);
- type = sshkey_type_from_name(key_types[i].key_type);
if ((fd = mkstemp(prv_tmp)) == -1) {
error("Could not save your public key in %s: %s",
prv_tmp, strerror(errno));
diff -up openssh-8.0p1/sshd_config.xxx openssh-8.0p1/sshd_config
--- openssh-8.0p1/sshd_config.xxx 2023-10-30 13:01:59.150952364 +0100
+++ openssh-8.0p1/sshd_config 2023-10-30 13:02:56.662231354 +0100
@@ -21,6 +21,7 @@
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
+#In FIPS mode Ed25519 keys are not supported, please comment out the next line
HostKey /etc/ssh/ssh_host_ed25519_key
# Ciphers and keying

View file

@ -84,7 +84,7 @@ index a5a81ed2..63f877f2 100644
+ /* There is at least one other ccache in collection
+ * we can switch to */
+ krb5_cc_switch(ctx, ccache);
+ } else {
+ } else if (authctxt->krb5_ccname != NULL) {
+ /* Clean up the collection too */
+ strncpy(krb5_ccname, authctxt->krb5_ccname, sizeof(krb5_ccname) - 10);
+ krb5_ccname_dir_start = strchr(krb5_ccname, ':') + 1;
@ -113,29 +113,12 @@ index a5a81ed2..63f877f2 100644
if (authctxt->krb5_user) {
krb5_free_principal(authctxt->krb5_ctx, authctxt->krb5_user);
authctxt->krb5_user = NULL;
@@ -237,36 +287,186 @@ krb5_cleanup_proc(Authctxt *authctxt)
@@ -237,36 +281,188 @@ krb5_cleanup_proc(Authctxt *authctxt)
}
}
-#ifndef HEIMDAL
-krb5_error_code
-ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache) {
- int tmpfd, ret, oerrno;
- char ccname[40];
- mode_t old_umask;
- ret = snprintf(ccname, sizeof(ccname),
- "FILE:/tmp/krb5cc_%d_XXXXXXXXXX", geteuid());
- if (ret < 0 || (size_t)ret >= sizeof(ccname))
- return ENOMEM;
-
- old_umask = umask(0177);
- tmpfd = mkstemp(ccname + strlen("FILE:"));
- oerrno = errno;
- umask(old_umask);
- if (tmpfd == -1) {
- logit("mkstemp(): %.100s", strerror(oerrno));
- return oerrno;
+
+#if !defined(HEIMDAL)
+int
+ssh_asprintf_append(char **dsc, const char *fmt, ...) {
@ -195,14 +178,13 @@ index a5a81ed2..63f877f2 100644
+ continue;
+ } else {
+ p_o = strchr(p_n, '}') + 1;
+ p_o = '\0';
+ *p_o = '\0';
+ debug("%s: unsupported token %s in %s", __func__, p_n, template);
+ /* unknown token, fallback to the default */
+ goto cleanup;
+ }
}
- if (fchmod(tmpfd,S_IRUSR | S_IWUSR) == -1) {
+ }
+
+ if (ssh_asprintf_append(&r, "%s", p_o) == -1)
+ goto cleanup;
+
@ -216,7 +198,10 @@ index a5a81ed2..63f877f2 100644
+ return -1;
+}
+
+krb5_error_code
krb5_error_code
-ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache) {
- int tmpfd, ret, oerrno;
- char ccname[40];
+ssh_krb5_get_cctemplate(krb5_context ctx, char **ccname) {
+ profile_t p;
+ int ret = 0;
@ -241,14 +226,27 @@ index a5a81ed2..63f877f2 100644
+ssh_krb5_cc_new_unique(krb5_context ctx, krb5_ccache *ccache, int *need_environment) {
+ int tmpfd, ret, oerrno, type_len;
+ char *ccname = NULL;
+ mode_t old_umask;
mode_t old_umask;
+ char *type = NULL, *colon = NULL;
+
- ret = snprintf(ccname, sizeof(ccname),
- "FILE:/tmp/krb5cc_%d_XXXXXXXXXX", geteuid());
- if (ret < 0 || (size_t)ret >= sizeof(ccname))
- return ENOMEM;
-
- old_umask = umask(0177);
- tmpfd = mkstemp(ccname + strlen("FILE:"));
- oerrno = errno;
- umask(old_umask);
- if (tmpfd == -1) {
- logit("mkstemp(): %.100s", strerror(oerrno));
- return oerrno;
- }
+ debug3("%s: called", __func__);
+ if (need_environment)
+ *need_environment = 0;
+ ret = ssh_krb5_get_cctemplate(ctx, &ccname);
+ if (ret || !ccname || options.kerberos_unique_ticket) {
+ if (ret || !ccname || options.kerberos_unique_ccache) {
+ /* Otherwise, go with the old method */
+ if (ccname)
+ free(ccname);
@ -258,7 +256,8 @@ index a5a81ed2..63f877f2 100644
+ "FILE:/tmp/krb5cc_%d_XXXXXXXXXX", geteuid());
+ if (ret < 0)
+ return ENOMEM;
+
- if (fchmod(tmpfd,S_IRUSR | S_IWUSR) == -1) {
+ old_umask = umask(0177);
+ tmpfd = mkstemp(ccname + strlen("FILE:"));
oerrno = errno;
@ -307,6 +306,7 @@ index a5a81ed2..63f877f2 100644
+ if (krb5_cc_support_switch(ctx, type)) {
+ debug3("%s: calling cc_new_unique(%s)", __func__, ccname);
+ ret = krb5_cc_new_unique(ctx, type, NULL, ccache);
+ free(type);
+ if (ret)
+ return ret;
+
@ -317,6 +317,7 @@ index a5a81ed2..63f877f2 100644
+ * it is already unique from above or the type does not support
+ * collections
+ */
+ free(type);
+ debug3("%s: calling cc_resolve(%s)", __func__, ccname);
+ return (krb5_cc_resolve(ctx, ccname, ccache));
+ }
@ -343,11 +344,10 @@ index 29491df9..fdab5040 100644
+krb5_error_code ssh_krb5_cc_new_unique(krb5_context, krb5_ccache *, int *);
#endif
#endif
diff --git a/gss-serv-krb5.c b/gss-serv-krb5.c
index 795992d9..0623a107 100644
--- a/gss-serv-krb5.c
+++ b/gss-serv-krb5.c
@@ -114,7 +114,7 @@ ssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *name)
diff -up openssh-7.9p1/gss-serv-krb5.c.ccache_name openssh-7.9p1/gss-serv-krb5.c
--- openssh-7.9p1/gss-serv-krb5.c.ccache_name 2019-03-01 15:17:42.708611802 +0100
+++ openssh-7.9p1/gss-serv-krb5.c 2019-03-01 15:17:42.713611844 +0100
@@ -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 */
@ -356,12 +356,9 @@ index 795992d9..0623a107 100644
ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client)
{
krb5_ccache ccache;
@@ -121,16 +121,17 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client)
krb5_error_code problem;
krb5_principal princ;
@@ -276,14 +276,15 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl
OM_uint32 maj_status, min_status;
- const char *new_ccname, *new_cctype;
+ int len;
const char *new_ccname, *new_cctype;
const char *errmsg;
+ int set_env = 0;
@ -377,7 +374,7 @@ index 795992d9..0623a107 100644
#ifdef HEIMDAL
# ifdef HAVE_KRB5_CC_NEW_UNIQUE
@@ -144,14 +145,14 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client)
@@ -297,14 +298,14 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl
krb5_get_err_text(krb_context, problem));
# endif
krb5_free_error_message(krb_context, errmsg);
@ -396,7 +393,7 @@ index 795992d9..0623a107 100644
}
#endif /* #ifdef HEIMDAL */
@@ -160,7 +161,7 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client)
@@ -313,7 +314,7 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl
errmsg = krb5_get_error_message(krb_context, problem);
logit("krb5_parse_name(): %.100s", errmsg);
krb5_free_error_message(krb_context, errmsg);
@ -405,7 +402,7 @@ index 795992d9..0623a107 100644
}
if ((problem = krb5_cc_initialize(krb_context, ccache, princ))) {
@@ -169,7 +170,7 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client)
@@ -322,7 +323,7 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl
krb5_free_error_message(krb_context, errmsg);
krb5_free_principal(krb_context, princ);
krb5_cc_destroy(krb_context, ccache);
@ -414,7 +411,7 @@ index 795992d9..0623a107 100644
}
krb5_free_principal(krb_context, princ);
@@ -178,37 +179,27 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client)
@@ -331,32 +332,21 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl
client->creds, ccache))) {
logit("gss_krb5_copy_ccache() failed");
krb5_cc_destroy(krb_context, ccache);
@ -422,30 +419,29 @@ index 795992d9..0623a107 100644
+ return 0;
}
- new_cctype = krb5_cc_get_type(krb_context, ccache);
- new_ccname = krb5_cc_get_name(krb_context, ccache);
new_cctype = krb5_cc_get_type(krb_context, ccache);
new_ccname = krb5_cc_get_name(krb_context, ccache);
-
- client->store.envvar = "KRB5CCNAME";
-#ifdef USE_CCAPI
- xasprintf(&client->store.envval, "API:%s", new_ccname);
- client->store.filename = NULL;
-#else
- if (new_ccname[0] == ':')
- new_ccname++;
- xasprintf(&client->store.envval, "%s:%s", new_cctype, new_ccname);
xasprintf(&client->store.envval, "%s:%s", new_cctype, new_ccname);
- if (strcmp(new_cctype, "DIR") == 0) {
- char *p;
- p = strrchr(client->store.envval, '/');
- if (p)
- *p = '\0';
- }
-#endif
+
+ if (set_env) {
+ const char *filename = krb5_cc_get_name(krb_context, ccache);
+ client->store.envvar = "KRB5CCNAME";
+ len = strlen(filename) + 6;
+ client->store.envval = xmalloc(len);
+ snprintf(client->store.envval, len, "FILE:%s", filename);
+ }
}
if ((strcmp(new_cctype, "FILE") == 0) || (strcmp(new_cctype, "DIR") == 0))
client->store.filename = xstrdup(new_ccname);
-#endif
#ifdef USE_PAM
- if (options.use_pam)
@ -453,7 +449,7 @@ index 795992d9..0623a107 100644
do_pam_putenv(client->store.envvar, client->store.envval);
#endif
krb5_cc_close(krb_context, ccache);
@@ -361,7 +355,7 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl
client->store.data = krb_context;
@ -484,15 +480,25 @@ index 6cae720e..16e55cbc 100644
}
/* This allows GSSAPI methods to do things to the childs environment based
diff --git a/servconf.c b/servconf.c
index cb578658..a6e01df2 100644
--- a/servconf.c
+++ b/servconf.c
@@ -122,6 +122,7 @@ initialize_server_options(ServerOptions *options)
@@ -498,9 +500,7 @@ ssh_gssapi_rekey_creds() {
char *envstr;
#endif
- if (gssapi_client.store.filename == NULL &&
- gssapi_client.store.envval == NULL &&
- gssapi_client.store.envvar == NULL)
+ if (gssapi_client.store.envval == NULL)
return;
ok = PRIVSEP(ssh_gssapi_update_creds(&gssapi_client.store));
diff -up openssh-7.9p1/servconf.c.ccache_name openssh-7.9p1/servconf.c
--- openssh-7.9p1/servconf.c.ccache_name 2019-03-01 15:17:42.704611768 +0100
+++ openssh-7.9p1/servconf.c 2019-03-01 15:17:42.713611844 +0100
@@ -123,6 +123,7 @@ initialize_server_options(ServerOptions
options->kerberos_or_local_passwd = -1;
options->kerberos_ticket_cleanup = -1;
options->kerberos_get_afs_token = -1;
+ options->kerberos_unique_ticket = -1;
+ options->kerberos_unique_ccache = -1;
options->gss_authentication=-1;
options->gss_keyex = -1;
options->gss_cleanup_creds = -1;
@ -500,8 +506,8 @@ index cb578658..a6e01df2 100644
options->kerberos_ticket_cleanup = 1;
if (options->kerberos_get_afs_token == -1)
options->kerberos_get_afs_token = 0;
+ if (options->kerberos_unique_ticket == -1)
+ options->kerberos_unique_ticket = 0;
+ if (options->kerberos_unique_ccache == -1)
+ options->kerberos_unique_ccache = 0;
if (options->gss_authentication == -1)
options->gss_authentication = 0;
if (options->gss_keyex == -1)
@ -510,7 +516,7 @@ index cb578658..a6e01df2 100644
sRhostsRSAAuthentication, sRSAAuthentication,
sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup,
- sKerberosGetAFSToken, sChallengeResponseAuthentication,
+ sKerberosGetAFSToken, sKerberosUniqueTicket,
+ sKerberosGetAFSToken, sKerberosUniqueCCache,
+ sChallengeResponseAuthentication,
sPasswordAuthentication, sKbdInteractiveAuthentication,
sListenAddress, sAddressFamily,
@ -519,13 +525,13 @@ index cb578658..a6e01df2 100644
#else
{ "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL },
#endif
+ { "kerberosuniqueticket", sKerberosUniqueTicket, SSHCFG_GLOBAL },
+ { "kerberosuniqueccache", sKerberosUniqueCCache, SSHCFG_GLOBAL },
#else
{ "kerberosauthentication", sUnsupported, SSHCFG_ALL },
{ "kerberosorlocalpasswd", sUnsupported, SSHCFG_GLOBAL },
{ "kerberosticketcleanup", sUnsupported, SSHCFG_GLOBAL },
{ "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL },
+ { "kerberosuniqueticket", sUnsupported, SSHCFG_GLOBAL },
+ { "kerberosuniqueccache", sUnsupported, SSHCFG_GLOBAL },
#endif
{ "kerberostgtpassing", sUnsupported, SSHCFG_GLOBAL },
{ "afstokenpassing", sUnsupported, SSHCFG_GLOBAL },
@ -533,8 +539,8 @@ index cb578658..a6e01df2 100644
intptr = &options->kerberos_get_afs_token;
goto parse_flag;
+ case sKerberosUniqueTicket:
+ intptr = &options->kerberos_unique_ticket;
+ case sKerberosUniqueCCache:
+ intptr = &options->kerberos_unique_ccache;
+ goto parse_flag;
+
case sGssAuthentication:
@ -544,7 +550,7 @@ index cb578658..a6e01df2 100644
# ifdef USE_AFS
dump_cfg_fmtint(sKerberosGetAFSToken, o->kerberos_get_afs_token);
# endif
+ dump_cfg_fmtint(sKerberosUniqueTicket, o->kerberos_unique_ticket);
+ dump_cfg_fmtint(sKerberosUniqueCCache, o->kerberos_unique_ccache);
#endif
#ifdef GSSAPI
dump_cfg_fmtint(sGssAuthentication, o->gss_authentication);
@ -556,7 +562,7 @@ index db8362c6..4fa42d64 100644
* file on logout. */
int kerberos_get_afs_token; /* If true, try to get AFS token if
* authenticated with Kerberos. */
+ int kerberos_unique_ticket; /* If true, the aquired ticket will
+ int kerberos_unique_ccache; /* If true, the acquired ticket will
+ * be stored in per-session ccache */
int gss_authentication; /* If true, permit GSSAPI authentication */
int gss_keyex; /* If true, permit GSSAPI key exchange */
@ -588,14 +594,6 @@ diff --git a/ssh-gss.h b/ssh-gss.h
index 6593e422..245178af 100644
--- a/ssh-gss.h
+++ b/ssh-gss.h
@@ -62,7 +62,6 @@
#define KEX_GSS_GEX_SHA1_ID "gss-gex-sha1-"
typedef struct {
- char *filename;
char *envvar;
char *envval;
struct passwd *owner;
@@ -83,7 +82,7 @@ typedef struct ssh_gssapi_mech_struct {
int (*dochild) (ssh_gssapi_client *);
int (*userok) (ssh_gssapi_client *, char *);
@ -631,16 +629,18 @@ diff --git a/sshd_config.5 b/sshd_config.5
index c0683d4a..2349f477 100644
--- a/sshd_config.5
+++ b/sshd_config.5
@@ -860,6 +860,12 @@ Specifies whether to automatically destroy the user's ticket cache
@@ -860,6 +860,14 @@ Specifies whether to automatically destroy the user's ticket cache
file on logout.
The default is
.Cm yes .
+.It Cm KerberosUniqueTicket
+Specifies whether to store the aquired tickets in the per-session credential
+cache or whether to use per-user credential cache, which might overwrite
+tickets aquired in different sessions of the same user.
+The default is
+.Cm no .
+.It Cm KerberosUniqueCCache
+Specifies whether to store the acquired tickets in the per-session credential
+cache under /tmp/ or whether to use per-user credential cache as configured in
+.Pa /etc/krb5.conf .
+The default value
+.Cm no
+can lead to overwriting previous tickets by subseqent connections to the same
+user account.
.It Cm KexAlgorithms
Specifies the available KEX (Key Exchange) algorithms.
Multiple algorithms must be comma-separated.

View file

@ -1,26 +1,25 @@
diff -up openssh-7.7p1/ssh_config.redhat openssh-7.7p1/ssh_config
--- openssh-7.7p1/ssh_config.redhat 2018-04-02 07:38:28.000000000 +0200
+++ openssh-7.7p1/ssh_config 2018-07-03 10:44:06.522245125 +0200
@@ -44,3 +44,7 @@
@@ -44,3 +44,8 @@
# VisualHostKey no
# ProxyCommand ssh -q -W %h:%p gateway.example.com
# RekeyLimit 1G 1h
+#
+# This system is following system-wide crypto policy.
+# To modify the system-wide ssh configuration, create a *.conf file under
+# /etc/ssh/ssh_config.d/ which will be automatically included below
+Include /etc/ssh/ssh_config.d/*.conf
diff -up openssh-7.7p1/ssh_config_redhat.redhat openssh-7.7p1/ssh_config_redhat
--- openssh-7.7p1/ssh_config_redhat.redhat 2018-07-03 10:44:06.522245125 +0200
+++ openssh-7.7p1/ssh_config_redhat 2018-07-03 10:44:06.522245125 +0200
@@ -0,0 +1,20 @@
+# Follow system-wide Crypto Policy, if defined:
+Include /etc/crypto-policies/back-ends/openssh.config
@@ -0,0 +1,21 @@
+# 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
+ # Follow system-wide Crypto Policy, if defined:
+ Include /etc/crypto-policies/back-ends/openssh.config
+
+# Uncomment this if you want to use .local domain
+# Host *.local
+# CheckHostIP no
+
+Host *
+ GSSAPIAuthentication yes
+
+# If this option is set to yes then remote X11 clients will have full access
@ -33,6 +32,10 @@ diff -up openssh-7.7p1/ssh_config_redhat.redhat openssh-7.7p1/ssh_config_redhat
+ 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
+# CheckHostIP no
diff -up openssh-7.7p1/sshd_config.0.redhat openssh-7.7p1/sshd_config.0
--- openssh-7.7p1/sshd_config.0.redhat 2018-04-02 07:39:27.000000000 +0200
+++ openssh-7.7p1/sshd_config.0 2018-07-03 10:44:06.523245133 +0200
@ -64,7 +67,7 @@ diff -up openssh-7.7p1/sshd_config.5.redhat openssh-7.7p1/sshd_config.5
diff -up openssh-7.7p1/sshd_config.redhat openssh-7.7p1/sshd_config
--- openssh-7.7p1/sshd_config.redhat 2018-04-02 07:38:28.000000000 +0200
+++ openssh-7.7p1/sshd_config 2018-07-03 10:45:16.950782466 +0200
@@ -10,20 +10,34 @@
@@ -10,20 +10,31 @@
# possible, but leave them commented. Uncommented options override the
# default value.
@ -87,14 +90,11 @@ diff -up openssh-7.7p1/sshd_config.redhat openssh-7.7p1/sshd_config
# Ciphers and keying
#RekeyLimit default none
+# System-wide Crypto policy:
+# This system is following system-wide crypto policy. The changes to
+# Ciphers, MACs, KexAlgoritms and GSSAPIKexAlgorithsm will not have any
+# effect here. They will be overridden by command-line options passed on
+# the server start up.
+# To opt out, uncomment a line with redefinition of CRYPTO_POLICY=
+# variable in /etc/sysconfig/sshd to overwrite the policy.
+# For more information, see manual page for update-crypto-policies(8).
+# crypto properties (Ciphers, MACs, ...) will not have any effect here.
+# They will be overridden by command-line options passed to the server
+# on command line.
+# Please, check manual pages for update-crypto-policies(8) and sshd_config(5).
+
# Logging
#SyslogFacility AUTH
@ -142,7 +142,7 @@ diff -up openssh-7.7p1/sshd_config.redhat openssh-7.7p1/sshd_config
#PermitTTY yes
-#PrintMotd yes
+
+# It is recommended to use pam_motd in /etc/pam.d/ssh instead of PrintMotd,
+# It is recommended to use pam_motd in /etc/pam.d/sshd instead of PrintMotd,
+# as it is more configurable and versatile than the built-in version.
+PrintMotd no
+

View file

@ -5,13 +5,13 @@ diff --git a/sshd.c b/sshd.c
parse_server_config(&options, rexeced_flag ? "rexec" : config_file_name,
cfg, 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.");
+
seed_rng();
/* Fill in default values for those options not explicitly set. */
fill_default_server_options(&options);
diff --git a/sshd_config b/sshd_config
--- a/sshd_config
+++ b/sshd_config
@ -19,7 +19,7 @@ diff --git a/sshd_config b/sshd_config
# If you just want the PAM account and session checks to run without
# PAM authentication, then enable this but set PasswordAuthentication
# and ChallengeResponseAuthentication 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 yes

File diff suppressed because it is too large Load diff

View file

@ -1,72 +0,0 @@
diff -up openssh/misc.c.config openssh/misc.c
--- openssh/misc.c.config 2018-08-22 13:58:54.922807799 +0200
+++ openssh/misc.c 2018-08-22 13:58:55.000808428 +0200
@@ -485,7 +485,7 @@ put_host_port(const char *host, u_short
* The delimiter char, if present, is stored in delim.
* If this is the last field, *cp is set to NULL.
*/
-static char *
+char *
hpdelim2(char **cp, char *delim)
{
char *s, *old;
diff -up openssh/misc.h.config openssh/misc.h
--- openssh/misc.h.config 2018-08-20 07:57:29.000000000 +0200
+++ openssh/misc.h 2018-08-22 13:58:55.001808436 +0200
@@ -54,6 +54,7 @@ int set_rdomain(int, const char *);
int a2port(const char *);
int a2tun(const char *, int *);
char *put_host_port(const char *, u_short);
+char *hpdelim2(char **, char *);
char *hpdelim(char **);
char *cleanhostname(char *);
char *colon(char *);
diff -up openssh/servconf.c.config openssh/servconf.c
--- openssh/servconf.c.config 2018-08-22 13:58:54.989808340 +0200
+++ openssh/servconf.c 2018-08-22 14:18:49.235443937 +0200
@@ -886,7 +886,7 @@ process_permitopen_list(struct ssh *ssh,
{
u_int i;
int port;
- char *host, *arg, *oarg;
+ char *host, *arg, *oarg, ch;
int where = opcode == sPermitOpen ? FORWARD_LOCAL : FORWARD_REMOTE;
const char *what = lookup_opcode_name(opcode);
@@ -904,8 +904,8 @@ process_permitopen_list(struct ssh *ssh,
/* Otherwise treat it as a list of permitted host:port */
for (i = 0; i < num_opens; i++) {
oarg = arg = xstrdup(opens[i]);
- host = hpdelim(&arg);
- if (host == NULL)
+ host = hpdelim2(&arg, &ch);
+ if (host == NULL || ch == '/')
fatal("%s: missing host in %s", __func__, what);
host = cleanhostname(host);
if (arg == NULL || ((port = permitopen_port(arg)) < 0))
@@ -1323,8 +1323,10 @@ process_server_config_line(ServerOptions
port = 0;
p = arg;
} else {
- p = hpdelim(&arg);
- if (p == NULL)
+ char ch;
+ arg2 = NULL;
+ p = hpdelim2(&arg, &ch);
+ if (p == NULL || ch == '/')
fatal("%s line %d: bad address:port usage",
filename, linenum);
p = cleanhostname(p);
@@ -1965,9 +1967,10 @@ process_server_config_line(ServerOptions
*/
xasprintf(&arg2, "*:%s", arg);
} else {
+ char ch;
arg2 = xstrdup(arg);
- p = hpdelim(&arg);
- if (p == NULL) {
+ p = hpdelim2(&arg, &ch);
+ if (p == NULL || ch == '/') {
fatal("%s line %d: missing host in %s",
filename, linenum,
lookup_opcode_name(opcode));

View file

@ -4,11 +4,11 @@ diff -up openssh/auth2.c.role-mls openssh/auth2.c
@@ -256,6 +256,9 @@ input_userauth_request(int type, u_int32
Authctxt *authctxt = ssh->authctxt;
Authmethod *m = NULL;
char *user, *service, *method, *style = NULL;
char *user = NULL, *service = NULL, *method = NULL, *style = NULL;
+#ifdef WITH_SELINUX
+ char *role = NULL;
+#endif
int authenticated = 0;
int r, authenticated = 0;
double tstart = monotime_double();
@@ -268,6 +271,11 @@ input_userauth_request(int type, u_int32
@ -37,9 +37,9 @@ diff -up openssh/auth2.c.role-mls openssh/auth2.c
+ mm_inform_authrole(role);
+#endif
+ }
userauth_banner();
userauth_banner(ssh);
if (auth2_setup_methods_lists(authctxt) != 0)
packet_disconnect("no authentication methods enabled");
ssh_packet_disconnect(ssh,
diff -up openssh/auth2-gss.c.role-mls openssh/auth2-gss.c
--- openssh/auth2-gss.c.role-mls 2018-08-20 07:57:29.000000000 +0200
+++ openssh/auth2-gss.c 2018-08-22 11:15:42.459799171 +0200
@ -57,7 +57,7 @@ diff -up openssh/auth2-gss.c.role-mls openssh/auth2-gss.c
mic.length = len;
- ssh_gssapi_buildmic(b, authctxt->user, authctxt->service,
+#ifdef WITH_SELINUX
+ if (authctxt->role && (strlen(authctxt->role) > 0))
+ if (authctxt->role && authctxt->role[0] != 0)
+ xasprintf(&micuser, "%s/%s", authctxt->user, authctxt->role);
+ else
+#endif
@ -197,15 +197,15 @@ diff -up openssh/monitor.c.role-mls openssh/monitor.c
--- openssh/monitor.c.role-mls 2018-08-20 07:57:29.000000000 +0200
+++ openssh/monitor.c 2018-08-22 11:19:56.006844867 +0200
@@ -115,6 +115,9 @@ int mm_answer_sign(int, struct sshbuf *)
int mm_answer_pwnamallow(int, struct sshbuf *);
int mm_answer_auth2_read_banner(int, struct sshbuf *);
int mm_answer_authserv(int, struct sshbuf *);
int mm_answer_pwnamallow(struct ssh *, int, struct sshbuf *);
int mm_answer_auth2_read_banner(struct ssh *, int, struct sshbuf *);
int mm_answer_authserv(struct ssh *, int, struct sshbuf *);
+#ifdef WITH_SELINUX
+int mm_answer_authrole(int, struct sshbuf *);
+int mm_answer_authrole(struct ssh *, int, struct sshbuf *);
+#endif
int mm_answer_authpassword(int, struct sshbuf *);
int mm_answer_bsdauthquery(int, struct sshbuf *);
int mm_answer_bsdauthrespond(int, struct sshbuf *);
int mm_answer_authpassword(struct ssh *, int, struct sshbuf *);
int mm_answer_bsdauthquery(struct ssh *, int, struct sshbuf *);
int mm_answer_bsdauthrespond(struct ssh *, int, struct sshbuf *);
@@ -189,6 +192,9 @@ struct mon_table mon_dispatch_proto20[]
{MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign},
{MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow},
@ -227,12 +227,12 @@ diff -up openssh/monitor.c.role-mls openssh/monitor.c
#ifdef USE_PAM
@@ -842,6 +851,26 @@ mm_answer_authserv(int sock, struct sshb
return (0);
return found;
}
+#ifdef WITH_SELINUX
+int
+mm_answer_authrole(int sock, struct sshbuf *m)
+mm_answer_authrole(struct ssh *ssh, int sock, struct sshbuf *m)
+{
+ int r;
+ monitor_permit_authentications(1);
@ -251,7 +251,7 @@ diff -up openssh/monitor.c.role-mls openssh/monitor.c
+#endif
+
int
mm_answer_authpassword(int sock, struct sshbuf *m)
mm_answer_authpassword(struct ssh *ssh, int sock, struct sshbuf *m)
{
@@ -1218,7 +1247,7 @@ monitor_valid_userblob(u_char *data, u_i
{
@ -284,7 +284,7 @@ diff -up openssh/monitor.c.role-mls openssh/monitor.c
fail++;
if ((r = sshbuf_get_cstring(b, &cp, NULL)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ if ((s = strchr(p, '/')) != NULL)
+ if ((s = strchr(cp, '/')) != NULL)
+ *s = '\0';
xasprintf(&userstyle, "%s%s%s", authctxt->user,
authctxt->style ? ":" : "",
@ -338,13 +338,13 @@ diff -up openssh/monitor_wrap.h.role-mls openssh/monitor_wrap.h
--- openssh/monitor_wrap.h.role-mls 2018-08-22 11:14:56.818430941 +0200
+++ openssh/monitor_wrap.h 2018-08-22 11:22:10.439929513 +0200
@@ -44,6 +44,9 @@ DH *mm_choose_dh(int, int, int);
int mm_sshkey_sign(struct sshkey *, u_char **, size_t *, const u_char *, size_t,
const char *, u_int compat);
int mm_sshkey_sign(struct ssh *, struct sshkey *, u_char **, size_t *,
const u_char *, size_t, const char *, u_int compat);
void mm_inform_authserv(char *, char *);
+#ifdef WITH_SELINUX
+void mm_inform_authrole(char *);
+#endif
struct passwd *mm_getpwnamallow(const char *);
struct passwd *mm_getpwnamallow(struct ssh *, const char *);
char *mm_auth2_read_banner(void);
int mm_auth_password(struct ssh *, char *);
diff -up openssh/openbsd-compat/Makefile.in.role-mls openssh/openbsd-compat/Makefile.in

View file

@ -0,0 +1,42 @@
diff -up openssh-7.9p1/contrib/ssh-copy-id.ssh-copy-id openssh-7.9p1/contrib/ssh-copy-id
--- openssh-7.9p1/contrib/ssh-copy-id.ssh-copy-id 2018-10-17 02:01:20.000000000 +0200
+++ openssh-7.9p1/contrib/ssh-copy-id 2019-01-23 20:49:30.513393667 +0100
@@ -112,7 +112,8 @@ do
usage
}
- OPT= OPTARG=
+ OPT=
+ OPTARG=
# implement something like getopt to avoid Solaris pain
case "$1" in
-i?*|-o?*|-p?*)
@@ -185,8 +185,8 @@
usage
fi
-# drop trailing colon
-USER_HOST=$(printf "%s\n" "$1" | sed 's/:$//')
+# don't drop trailing colon because it can be a valid ipv6 address
+USER_HOST=$(printf "%s\n" "$1")
# tack the hostname onto SSH_OPTS
SSH_OPTS="${SSH_OPTS:+$SSH_OPTS }'$(quote "$USER_HOST")'"
# and populate "$@" for later use (only way to get proper quoting of options)
@@ -261,7 +262,7 @@ populate_new_ids() {
fi
if [ -z "$NEW_IDS" ] ; then
printf '\n%s: WARNING: All keys were skipped because they already exist on the remote system.\n' "$0" >&2
- printf '\t\t(if you think this is a mistake, you may want to use -f option)\n\n' "$0" >&2
+ printf '\t\t(if you think this is a mistake, you may want to use -f option)\n\n' >&2
exit 0
fi
printf '%s: INFO: %d key(s) remain to be installed -- if you are prompted now it is to install the new keys\n' "$0" "$(printf '%s\n' "$NEW_IDS" | wc -l)" >&2
@@ -296,7 +297,7 @@ case "$REMOTE_VERSION" in
# in ssh below - to defend against quirky remote shells: use 'exec sh -c' to get POSIX;
# 'cd' to be at $HOME; add a newline if it's missing; and all on one line, because tcsh.
[ "$DRY_RUN" ] || printf '%s\n' "$NEW_IDS" | \
- ssh "$@" "exec sh -c 'cd ; umask 077 ; mkdir -p .ssh && { [ -z "'`tail -1c .ssh/authorized_keys 2>/dev/null`'" ] || echo >> .ssh/authorized_keys ; } && cat >> .ssh/authorized_keys || exit 1 ; if type restorecon >/dev/null 2>&1 ; then restorecon -F .ssh .ssh/authorized_keys ; fi'" \
+ ssh "$@" "exec sh -c 'cd ; umask 077 ; mkdir -p .ssh && { [ -z "'`tail -1c .ssh/authorized_keys 2>/dev/null`'" ] || echo >> .ssh/authorized_keys || exit 1; } && cat >> .ssh/authorized_keys || exit 1 ; if type restorecon >/dev/null 2>&1 ; then restorecon -F .ssh .ssh/authorized_keys ; fi'" \
|| exit 1
ADDED=$(printf '%s\n' "$NEW_IDS" | wc -l)
;;

View file

@ -0,0 +1,20 @@
diff --git a/sftp.c b/sftp.c
index b66037f1..54538ff9 100644
--- a/sftp.c
+++ b/sftp.c
@@ -220,9 +220,12 @@ static const struct CMD cmds[] = {
static void
killchild(int signo)
{
- if (sshpid > 1) {
- kill(sshpid, SIGTERM);
- waitpid(sshpid, NULL, 0);
+ pid_t pid;
+
+ pid = sshpid;
+ if (pid > 1) {
+ kill(pid, SIGTERM);
+ (void)waitpid(pid, NULL, 0);
}
_exit(1);

View file

@ -0,0 +1,13 @@
diff --git a/msg.c b/msg.c
index 99c25cd2..574a566e 100644
--- a/msg.c
+++ b/msg.c
@@ -77,7 +77,7 @@ ssh_msg_recv(int fd, struct sshbuf *m)
return (-1);
}
msg_len = get_u32(buf);
- if (msg_len > 256 * 1024) {
+ if (msg_len > sshbuf_max_size(m)) {
error("ssh_msg_recv: read: bad msg_len %u", msg_len);
return (-1);
}

View file

@ -0,0 +1,33 @@
diff -up openssh-8.0p1/channels.c.channel-limits openssh-8.0p1/channels.c
--- openssh-8.0p1/channels.c.channel-limits 2021-03-16 12:17:58.905576511 +0100
+++ openssh-8.0p1/channels.c 2021-03-16 12:17:58.925576667 +0100
@@ -354,6 +354,7 @@ channel_new(struct ssh *ssh, char *ctype
struct ssh_channels *sc = ssh->chanctxt;
u_int i, found;
Channel *c;
+ int r;
/* Try to find a free slot where to put the new channel. */
for (i = 0; i < sc->channels_alloc; i++) {
@@ -383,6 +384,8 @@ channel_new(struct ssh *ssh, char *ctype
(c->output = sshbuf_new()) == NULL ||
(c->extended = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
+ if ((r = sshbuf_set_max_size(c->input, CHAN_INPUT_MAX)) != 0)
+ fatal("%s: sshbuf_set_max_size: %s", __func__, ssh_err(r));
c->ostate = CHAN_OUTPUT_OPEN;
c->istate = CHAN_INPUT_OPEN;
channel_register_fds(ssh, c, rfd, wfd, efd, extusage, nonblock, 0);
diff -up openssh-8.0p1/channels.h.channel-limits openssh-8.0p1/channels.h
--- openssh-8.0p1/channels.h.channel-limits 2021-03-16 12:17:58.868576223 +0100
+++ openssh-8.0p1/channels.h 2021-03-16 12:17:58.907576527 +0100
@@ -215,6 +215,9 @@ struct Channel {
/* Read buffer size */
#define CHAN_RBUF (16*1024)
+/* Maximum channel input buffer size */
+#define CHAN_INPUT_MAX (16*1024*1024)
+
/* Hard limit on number of channels */
#define CHANNELS_MAX_CHANNELS (16*1024)

View file

@ -0,0 +1,28 @@
diff --git a/serverloop.c b/serverloop.c
index e16eabe2..a8c99e2e 100644
--- a/serverloop.c
+++ b/serverloop.c
@@ -184,7 +184,8 @@ client_alive_check(struct ssh *ssh)
int r, channel_id;
/* timeout, check to see how many we have had */
- if (ssh_packet_inc_alive_timeouts(ssh) >
+ if (options.client_alive_count_max > 0 &&
+ ssh_packet_inc_alive_timeouts(ssh) >
options.client_alive_count_max) {
sshpkt_fmt_connection_id(ssh, remote_id, sizeof(remote_id));
logit("Timeout, client not responding from %s", remote_id);
diff --git a/sshd_config.5 b/sshd_config.5
index d47cb0d2..2cddbd59 100644
--- a/sshd_config.5
+++ b/sshd_config.5
@@ -519,6 +519,9 @@ is set to 15, and
.Cm ClientAliveCountMax
is left at the default, unresponsive SSH clients
will be disconnected after approximately 45 seconds.
+Setting a zero
+.Cm ClientAliveCountMax
+disables connection termination.
.It Cm ClientAliveInterval
Sets a timeout interval in seconds after which if no data has been received
from the client,

View file

@ -0,0 +1,424 @@
diff -up openssh-8.0p1/ssh_config.5.crypto-policies openssh-8.0p1/ssh_config.5
--- openssh-8.0p1/ssh_config.5.crypto-policies 2020-03-24 17:32:54.821789205 +0100
+++ openssh-8.0p1/ssh_config.5 2020-03-24 17:59:58.174122920 +0100
@@ -357,17 +357,17 @@ or
.Qq *.c.example.com
domains.
.It Cm CASignatureAlgorithms
+The default is handled system-wide by
+.Xr crypto-policies 7 .
+To see the current defaults and how to modify them, see manual page
+.Xr update-crypto-policies 8 .
+.Pp
Specifies which algorithms are allowed for signing of certificates
by certificate authorities (CAs).
-The default is:
-.Bd -literal -offset indent
-ecdsa-sha2-nistp256.ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
-ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa
-.Ed
-.Pp
.Xr ssh 1
will not accept host certificates signed using algorithms other than those
specified.
+.Pp
.It Cm CertificateFile
Specifies a file from which the user's certificate is read.
A corresponding private key must be provided separately in order
@@ -420,16 +420,21 @@ If the option is set to
.Cm no ,
the check will not be executed.
.It Cm Ciphers
+The default is handled system-wide by
+.Xr crypto-policies 7 .
+To see the current defaults and how to modify them, see manual page
+.Xr update-crypto-policies 8 .
+.Pp
Specifies the ciphers allowed and their order of preference.
Multiple ciphers must be comma-separated.
If the specified value begins with a
.Sq +
-character, then the specified ciphers will be appended to the default set
+character, then the specified ciphers will be appended to the built-in default set
instead of replacing them.
If the specified value begins with a
.Sq -
character, then the specified ciphers (including wildcards) will be removed
-from the default set instead of replacing them.
+from the built-in default set instead of replacing them.
.Pp
The supported ciphers are:
.Bd -literal -offset indent
@@ -445,13 +450,6 @@ aes256-gcm@openssh.com
chacha20-poly1305@openssh.com
.Ed
.Pp
-The default is:
-.Bd -literal -offset indent
-chacha20-poly1305@openssh.com,
-aes128-ctr,aes192-ctr,aes256-ctr,
-aes128-gcm@openssh.com,aes256-gcm@openssh.com
-.Ed
-.Pp
The list of available ciphers may also be obtained using
.Qq ssh -Q cipher .
.It Cm ClearAllForwardings
@@ -800,6 +798,11 @@ command line will be passed untouched to
The default is
.Dq no .
.It Cm GSSAPIKexAlgorithms
+The default is handled system-wide by
+.Xr crypto-policies 7 .
+To see the current defaults and how to modify them, see 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
@@ -812,9 +815,8 @@ gss-nistp256-sha256-,
gss-curve25519-sha256-
.Ed
.Pp
-The default is
-.Dq gss-group14-sha256-,gss-group16-sha512-,gss-nistp256-sha256-,gss-curve25519-sha256-,gss-group14-sha1-,gss-gex-sha1- .
This option only applies to connections using GSSAPI.
+.Pp
.It Cm HashKnownHosts
Indicates that
.Xr ssh 1
@@ -1114,26 +1115,21 @@ it may be zero or more of:
and
.Cm pam .
.It Cm KexAlgorithms
+The default is handled system-wide by
+.Xr crypto-policies 7 .
+To see the current defaults and how to modify them, see manual page
+.Xr update-crypto-policies 8 .
+.Pp
Specifies the available KEX (Key Exchange) algorithms.
Multiple algorithms must be comma-separated.
Alternately if the specified value begins with a
.Sq +
-character, then the specified methods will be appended to the default set
+character, then the specified methods will be appended to the built-in default set
instead of replacing them.
If the specified value begins with a
.Sq -
character, then the specified methods (including wildcards) will be removed
-from the default set instead of replacing them.
-The default is:
-.Bd -literal -offset indent
-curve25519-sha256,curve25519-sha256@libssh.org,
-ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,
-diffie-hellman-group-exchange-sha256,
-diffie-hellman-group16-sha512,
-diffie-hellman-group18-sha512,
-diffie-hellman-group14-sha256,
-diffie-hellman-group14-sha1
-.Ed
+from the built-in default set instead of replacing them.
.Pp
The list of available key exchange algorithms may also be obtained using
.Qq ssh -Q kex .
@@ -1193,33 +1189,29 @@ The default is INFO.
DEBUG and DEBUG1 are equivalent.
DEBUG2 and DEBUG3 each specify higher levels of verbose output.
.It Cm MACs
+The default is handled system-wide by
+.Xr crypto-policies 7 .
+To see the current defaults and how to modify them, see manual page
+.Xr update-crypto-policies 8 .
+.Pp
Specifies the MAC (message authentication code) algorithms
in order of preference.
The MAC algorithm is used for data integrity protection.
Multiple algorithms must be comma-separated.
If the specified value begins with a
.Sq +
-character, then the specified algorithms will be appended to the default set
+character, then the specified algorithms will be appended to the built-in default set
instead of replacing them.
If the specified value begins with a
.Sq -
character, then the specified algorithms (including wildcards) will be removed
-from the default set instead of replacing them.
+from the built-in default set instead of replacing them.
.Pp
The algorithms that contain
.Qq -etm
calculate the MAC after encryption (encrypt-then-mac).
These are considered safer and their use recommended.
.Pp
-The default is:
-.Bd -literal -offset indent
-umac-64-etm@openssh.com,umac-128-etm@openssh.com,
-hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,
-hmac-sha1-etm@openssh.com,
-umac-64@openssh.com,umac-128@openssh.com,
-hmac-sha2-256,hmac-sha2-512,hmac-sha1
-.Ed
-.Pp
The list of available MAC algorithms may also be obtained using
.Qq ssh -Q mac .
.It Cm NoHostAuthenticationForLocalhost
@@ -1352,27 +1344,21 @@ instead of continuing to execute and pas
The default is
.Cm no .
.It Cm PubkeyAcceptedKeyTypes
+The default is handled system-wide by
+.Xr crypto-policies 7 .
+To see the current defaults and how to modify them, see manual page
+.Xr update-crypto-policies 8 .
+.Pp
Specifies the key types that will be used for public key authentication
as a comma-separated list of patterns.
Alternately if the specified value begins with a
.Sq +
-character, then the key types after it will be appended to the default
+character, then the key types after it will be appended to the built-in default
instead of replacing it.
If the specified value begins with a
.Sq -
character, then the specified key types (including wildcards) will be removed
-from the default set instead of replacing them.
-The default for this option is:
-.Bd -literal -offset 3n
-ecdsa-sha2-nistp256-cert-v01@openssh.com,
-ecdsa-sha2-nistp384-cert-v01@openssh.com,
-ecdsa-sha2-nistp521-cert-v01@openssh.com,
-ssh-ed25519-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,
-ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa
-.Ed
+from the built-in default set instead of replacing them.
.Pp
The list of available key types may also be obtained using
.Qq ssh -Q key .
diff -up openssh-8.0p1/sshd_config.5.crypto-policies openssh-8.0p1/sshd_config.5
--- openssh-8.0p1/sshd_config.5.crypto-policies 2020-03-24 17:32:54.802788908 +0100
+++ openssh-8.0p1/sshd_config.5 2020-03-24 17:54:13.347740176 +0100
@@ -383,16 +383,16 @@ If the argument is
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 current defaults and how to modify them, see manual page
+.Xr update-crypto-policies 8 .
+.Pp
Specifies which algorithms are allowed for signing of certificates
by certificate authorities (CAs).
-The default is:
-.Bd -literal -offset indent
-ecdsa-sha2-nistp256.ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
-ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa
-.Ed
-.Pp
Certificates signed using other algorithms will not be accepted for
public key or host-based authentication.
+.Pp
.It Cm ChallengeResponseAuthentication
Specifies whether challenge-response authentication is allowed (e.g. via
PAM or through authentication styles supported in
@@ -454,16 +454,21 @@ The default is
indicating not to
.Xr chroot 2 .
.It Cm Ciphers
+The default is handled system-wide by
+.Xr crypto-policies 7 .
+To see the current defaults and how to modify them, see manual page
+.Xr update-crypto-policies 8 .
+.Pp
Specifies the ciphers allowed.
Multiple ciphers must be comma-separated.
If the specified value begins with a
.Sq +
-character, then the specified ciphers will be appended to the default set
+character, then the specified ciphers will be appended to the built-in default set
instead of replacing them.
If the specified value begins with a
.Sq -
character, then the specified ciphers (including wildcards) will be removed
-from the default set instead of replacing them.
+from the built-in default set instead of replacing them.
.Pp
The supported ciphers are:
.Pp
@@ -490,13 +495,6 @@ aes256-gcm@openssh.com
chacha20-poly1305@openssh.com
.El
.Pp
-The default is:
-.Bd -literal -offset indent
-chacha20-poly1305@openssh.com,
-aes128-ctr,aes192-ctr,aes256-ctr,
-aes128-gcm@openssh.com,aes256-gcm@openssh.com
-.Ed
-.Pp
The list of available ciphers may also be obtained using
.Qq ssh -Q cipher .
.It Cm ClientAliveCountMax
@@ -688,6 +686,11 @@ For this to work
.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 current defaults and how to modify them, see manual page
+.Xr update-crypto-policies 8 .
+.Pp
The list of key exchange algorithms that are accepted by GSSAPI
key exchange. Possible values are
.Bd -literal -offset 3n
@@ -700,8 +703,6 @@ gss-nistp256-sha256-,
gss-curve25519-sha256-
.Ed
.Pp
-The default is
-.Dq gss-group14-sha256-,gss-group16-sha512-,gss-nistp256-sha256-,gss-curve25519-sha256-,gss-group14-sha1-,gss-gex-sha1- .
This option only applies to connections using GSSAPI.
.It Cm HostbasedAcceptedKeyTypes
Specifies the key types that will be accepted for hostbased authentication
@@ -791,19 +791,13 @@ is specified, the location of the socket
.Ev SSH_AUTH_SOCK
environment variable.
.It Cm HostKeyAlgorithms
+The default is handled system-wide by
+.Xr crypto-policies 7 .
+To see the current defaults and how to modify them, see manual page
+.Xr update-crypto-policies 8 .
+.Pp
Specifies the host key algorithms
that the server offers.
-The default for this option is:
-.Bd -literal -offset 3n
-ecdsa-sha2-nistp256-cert-v01@openssh.com,
-ecdsa-sha2-nistp384-cert-v01@openssh.com,
-ecdsa-sha2-nistp521-cert-v01@openssh.com,
-ssh-ed25519-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,
-ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa
-.Ed
.Pp
The list of available key types may also be obtained using
.Qq ssh -Q key .
@@ -922,16 +916,21 @@ Specifies whether to look at .k5login fi
The default is
.Cm yes .
.It Cm KexAlgorithms
+The default is handled system-wide by
+.Xr crypto-policies 7 .
+To see the current defaults and how to modify them, see manual page
+.Xr update-crypto-policies 8 .
+.Pp
Specifies the available KEX (Key Exchange) algorithms.
Multiple algorithms must be comma-separated.
Alternately if the specified value begins with a
.Sq +
-character, then the specified methods will be appended to the default set
+character, then the specified methods will be appended to the built-in default set
instead of replacing them.
If the specified value begins with a
.Sq -
character, then the specified methods (including wildcards) will be removed
-from the default set instead of replacing them.
+from the built-in default set instead of replacing them.
The supported algorithms are:
.Pp
.Bl -item -compact -offset indent
@@ -961,15 +960,6 @@ ecdh-sha2-nistp384
ecdh-sha2-nistp521
.El
.Pp
-The default is:
-.Bd -literal -offset indent
-curve25519-sha256,curve25519-sha256@libssh.org,
-ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,
-diffie-hellman-group-exchange-sha256,
-diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,
-diffie-hellman-group14-sha256,diffie-hellman-group14-sha1
-.Ed
-.Pp
The list of available key exchange algorithms may also be obtained using
.Qq ssh -Q kex .
.It Cm ListenAddress
@@ -1038,17 +1028,22 @@ DEBUG and DEBUG1 are equivalent.
DEBUG2 and DEBUG3 each specify higher levels of debugging output.
Logging with a DEBUG level violates the privacy of users and is not recommended.
.It Cm MACs
+The default is handled system-wide by
+.Xr crypto-policies 7 .
+To see the current defaults and how to modify them, see manual page
+.Xr update-crypto-policies 8 .
+.Pp
Specifies the available MAC (message authentication code) algorithms.
The MAC algorithm is used for data integrity protection.
Multiple algorithms must be comma-separated.
If the specified value begins with a
.Sq +
-character, then the specified algorithms will be appended to the default set
+character, then the specified algorithms will be appended to the built-in default set
instead of replacing them.
If the specified value begins with a
.Sq -
character, then the specified algorithms (including wildcards) will be removed
-from the default set instead of replacing them.
+from the built-in default set instead of replacing them.
.Pp
The algorithms that contain
.Qq -etm
@@ -1091,15 +1086,6 @@ umac-64-etm@openssh.com
umac-128-etm@openssh.com
.El
.Pp
-The default is:
-.Bd -literal -offset indent
-umac-64-etm@openssh.com,umac-128-etm@openssh.com,
-hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,
-hmac-sha1-etm@openssh.com,
-umac-64@openssh.com,umac-128@openssh.com,
-hmac-sha2-256,hmac-sha2-512,hmac-sha1
-.Ed
-.Pp
The list of available MAC algorithms may also be obtained using
.Qq ssh -Q mac .
.It Cm Match
@@ -1446,27 +1432,21 @@ or equivalent.)
The default is
.Cm yes .
.It Cm PubkeyAcceptedKeyTypes
+The default is handled system-wide by
+.Xr crypto-policies 7 .
+To see the current defaults and how to modify them, see manual page
+.Xr update-crypto-policies 8 .
+.Pp
Specifies the key types that will be accepted for public key authentication
as a list of comma-separated patterns.
Alternately if the specified value begins with a
.Sq +
-character, then the specified key types will be appended to the default set
+character, then the specified key types will be appended to the built-in default set
instead of replacing them.
If the specified value begins with a
.Sq -
character, then the specified key types (including wildcards) will be removed
-from the default set instead of replacing them.
-The default for this option is:
-.Bd -literal -offset 3n
-ecdsa-sha2-nistp256-cert-v01@openssh.com,
-ecdsa-sha2-nistp384-cert-v01@openssh.com,
-ecdsa-sha2-nistp521-cert-v01@openssh.com,
-ssh-ed25519-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,
-ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa
-.Ed
+from the built-in default set instead of replacing them.
.Pp
The list of available key types may also be obtained using
.Qq ssh -Q key .

View file

@ -0,0 +1,25 @@
diff --color -ru a/sshd.8 b/sshd.8
--- a/sshd.8 2022-05-31 13:39:10.231843926 +0200
+++ b/sshd.8 2022-05-31 14:34:01.460815420 +0200
@@ -78,6 +78,7 @@
.Xr sshd_config 5 ) ;
command-line options override values specified in the
configuration file.
+This mechanism is used by systemd to apply system-wide crypto-policies to ssh server.
.Nm
rereads its configuration file when it receives a hangup signal,
.Dv SIGHUP ,
@@ -207,6 +208,13 @@
rules may be applied by specifying the connection parameters using one or more
.Fl C
options.
+The configuration does not contain the system-wide crypto-policy configuration.
+To show the most accurate runtime configuration, use:
+.Bd -literal -offset 3n
+source /etc/crypto-policies/back-ends/opensshserver.config
+source /etc/sysconfig/sshd
+sshd -T $OPTIONS $CRYPTO_POLICY
+.Ed
.It Fl t
Test mode.
Only check the validity of the configuration file and sanity of the keys.

View file

@ -0,0 +1,127 @@
diff -up openssh-8.0p1/hostfile.c.cve-2020-14145 openssh-8.0p1/hostfile.c
--- openssh-8.0p1/hostfile.c.cve-2020-14145 2019-04-18 00:52:57.000000000 +0200
+++ openssh-8.0p1/hostfile.c 2021-05-17 16:53:38.694577251 +0200
@@ -409,6 +409,18 @@ lookup_key_in_hostkeys_by_type(struct ho
found) == HOST_FOUND);
}
+int
+lookup_marker_in_hostkeys(struct hostkeys *hostkeys, int want_marker)
+{
+ u_int i;
+
+ for (i = 0; i < hostkeys->num_entries; i++) {
+ if (hostkeys->entries[i].marker == (HostkeyMarker)want_marker)
+ return 1;
+ }
+ return 0;
+}
+
static int
write_host_entry(FILE *f, const char *host, const char *ip,
const struct sshkey *key, int store_hash)
diff -up openssh-8.0p1/hostfile.h.cve-2020-14145 openssh-8.0p1/hostfile.h
--- openssh-8.0p1/hostfile.h.cve-2020-14145 2019-04-18 00:52:57.000000000 +0200
+++ openssh-8.0p1/hostfile.h 2021-05-17 16:53:38.694577251 +0200
@@ -39,6 +39,7 @@ HostStatus check_key_in_hostkeys(struct
const struct hostkey_entry **);
int lookup_key_in_hostkeys_by_type(struct hostkeys *, int,
const struct hostkey_entry **);
+int lookup_marker_in_hostkeys(struct hostkeys *, int);
int hostfile_read_key(char **, u_int *, struct sshkey *);
int add_host_to_hostfile(const char *, const char *,
diff -up openssh-8.0p1/sshconnect2.c.cve-2020-14145 openssh-8.0p1/sshconnect2.c
--- openssh-8.0p1/sshconnect2.c.cve-2020-14145 2021-05-17 16:53:38.610576561 +0200
+++ openssh-8.0p1/sshconnect2.c 2021-05-17 16:54:58.169230103 +0200
@@ -98,12 +98,25 @@ verify_host_key_callback(struct sshkey *
return 0;
}
+/* Returns the first item from a comma-separated algorithm list */
+static char *
+first_alg(const char *algs)
+{
+ char *ret, *cp;
+
+ ret = xstrdup(algs);
+ if ((cp = strchr(ret, ',')) != NULL)
+ *cp = '\0';
+ return ret;
+}
+
static char *
order_hostkeyalgs(char *host, struct sockaddr *hostaddr, u_short port)
{
- char *oavail, *avail, *first, *last, *alg, *hostname, *ret;
+ char *oavail = NULL, *avail = NULL, *first = NULL, *last = NULL;
+ char *alg = NULL, *hostname = NULL, *ret = NULL, *best = NULL;
size_t maxlen;
- struct hostkeys *hostkeys;
+ struct hostkeys *hostkeys = NULL;
int ktype;
u_int i;
@@ -115,6 +128,26 @@ order_hostkeyalgs(char *host, struct soc
for (i = 0; i < options.num_system_hostfiles; i++)
load_hostkeys(hostkeys, hostname, options.system_hostfiles[i]);
+ /*
+ * If a plain public key exists that matches the type of the best
+ * preference HostkeyAlgorithms, then use the whole list as is.
+ * Note that we ignore whether the best preference algorithm is a
+ * certificate type, as sshconnect.c will downgrade certs to
+ * plain keys if necessary.
+ */
+ best = first_alg(options.hostkeyalgorithms);
+ if (lookup_key_in_hostkeys_by_type(hostkeys,
+ sshkey_type_plain(sshkey_type_from_name(best)), NULL)) {
+ debug3("%s: have matching best-preference key type %s, "
+ "using HostkeyAlgorithms verbatim", __func__, best);
+ ret = xstrdup(options.hostkeyalgorithms);
+ goto out;
+ }
+
+ /*
+ * Otherwise, prefer the host key algorithms that match known keys
+ * while keeping the ordering of HostkeyAlgorithms as much as possible.
+ */
oavail = avail = xstrdup(KEX_DEFAULT_PK_ALG);
maxlen = strlen(avail) + 1;
first = xmalloc(maxlen);
@@ -131,11 +164,23 @@ order_hostkeyalgs(char *host, struct soc
while ((alg = strsep(&avail, ",")) && *alg != '\0') {
if ((ktype = sshkey_type_from_name(alg)) == KEY_UNSPEC)
fatal("%s: unknown alg %s", __func__, alg);
+ /*
+ * If we have a @cert-authority marker in known_hosts then
+ * prefer all certificate algorithms.
+ */
+ if (sshkey_type_is_cert(ktype) &&
+ lookup_marker_in_hostkeys(hostkeys, MRK_CA)) {
+ ALG_APPEND(first, alg);
+ continue;
+ }
+ /* If the key appears in known_hosts then prefer it */
if (lookup_key_in_hostkeys_by_type(hostkeys,
- sshkey_type_plain(ktype), NULL))
+ sshkey_type_plain(ktype), NULL)) {
ALG_APPEND(first, alg);
- else
- ALG_APPEND(last, alg);
+ continue;
+ }
+ /* Otherwise, put it last */
+ ALG_APPEND(last, alg);
}
#undef ALG_APPEND
xasprintf(&ret, "%s%s%s", first,
@@ -143,6 +188,8 @@ order_hostkeyalgs(char *host, struct soc
if (*first != '\0')
debug3("%s: prefer hostkeyalgs: %s", __func__, first);
+ out:
+ free(best);
free(first);
free(last);
free(hostname);

302
openssh-8.0p1-entropy.patch Normal file
View file

@ -0,0 +1,302 @@
diff --git a/entropy.c b/entropy.c
index 2d483b3..b361a04 100644
--- a/entropy.c
+++ b/entropy.c
@@ -234,6 +234,9 @@ seed_rng(void)
}
#endif /* OPENSSL_PRNG_ONLY */
+#ifdef __linux__
+ linux_seed();
+#endif /* __linux__ */
if (RAND_status() != 1)
fatal("PRNG is not seeded");
diff --git a/openbsd-compat/Makefile.in b/openbsd-compat/Makefile.in
index b912dbe..9206337 100644
--- a/openbsd-compat/Makefile.in
+++ b/openbsd-compat/Makefile.in
@@ -20,6 +20,7 @@ OPENBSD=base64.o basename.o bcrypt_pbkdf.o bindresvport.o blowfish.o daemon.o di
port-solaris.o \
port-net.o \
port-uw.o \
+ port-linux-prng.o \
port-linux-sshd.o
.c.o:
diff -up openssh-7.4p1/openbsd-compat/port-linux.h.entropy openssh-7.4p1/openbsd-compat/port-linux.h
--- openssh-7.4p1/openbsd-compat/port-linux.h.entropy 2016-12-23 18:34:27.747753563 +0100
+++ openssh-7.4p1/openbsd-compat/port-linux.h 2016-12-23 18:34:27.769753570 +0100
@@ -34,4 +34,6 @@ void oom_adjust_restore(void);
void oom_adjust_setup(void);
#endif
+void linux_seed(void);
+
#endif /* ! _PORT_LINUX_H */
diff --git a/openbsd-compat/port-linux-prng.c b/openbsd-compat/port-linux-prng.c
new file mode 100644
index 0000000..92a617c
--- /dev/null
+++ b/openbsd-compat/port-linux-prng.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2011 - 2020 Red Hat, Inc.
+ *
+ * Authors:
+ * Jan F. Chadima <jchadima@redhat.com>
+ * Jakub Jelen <jjelen@redhat.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Linux-specific portability code - prng support
+ */
+
+#include "includes.h"
+
+#include <errno.h>
+#include <string.h>
+#include <openssl/rand.h>
+#include <sys/random.h>
+
+#include "log.h"
+
+void
+linux_seed(void)
+{
+ char *env = NULL;
+ size_t randlen = 14, left;
+ unsigned int flags = 0;
+ unsigned char buf[256], *p;
+
+ env = getenv("SSH_USE_STRONG_RNG");
+ if (env && strcmp(env, "0") != 0) {
+ size_t ienv = atoi(env);
+
+ /* Max on buffer length */
+ if (ienv > sizeof(buf))
+ ienv = sizeof(buf);
+ /* Minimum is always 14 B */
+ if (ienv > randlen)
+ randlen = ienv;
+ flags = GRND_RANDOM;
+ }
+
+ errno = 0;
+ left = randlen;
+ p = buf;
+ do {
+ ssize_t len = getrandom(p, left, flags);
+ if (len == -1) {
+ if (errno != EINTR) {
+ if (flags) {
+ /* With the variable present, this is fatal error */
+ fatal("Failed to seed from getrandom: %s", strerror(errno));
+ } else {
+ /* Otherwise we log the issue drop out from here */
+ debug("Failed to seed from getrandom: %s", strerror(errno));
+ return;
+ }
+ }
+ } else if (len > 0) {
+ left -= len;
+ p += len;
+ }
+ } while (left > 0);
+
+ RAND_seed(buf, randlen);
+}
diff --git a/ssh-add.1 b/ssh-add.1
index 4812448..16305bf 100644
--- a/ssh-add.1
+++ b/ssh-add.1
@@ -161,6 +161,22 @@ to make this work.)
Identifies the path of a
.Ux Ns -domain
socket used to communicate with the agent.
+.It Ev SSH_USE_STRONG_RNG
+The reseeding of the OpenSSL random generator is usually done from
+.Cm getrandom(1)
+without any specific flags.
+If the
+.Cm SSH_USE_STRONG_RNG
+environment variable is set to value other than
+.Cm 0
+the OpenSSL random generator is reseeded from
+.Cm getrandom(1)
+with GRND_RANDOM flag specified.
+The number of bytes read is defined by the SSH_USE_STRONG_RNG value.
+Minimum is 14 bytes.
+This setting is not recommended on the computers without the hardware
+random generator because insufficient entropy causes the connection to
+be blocked until enough entropy is available.
.El
.Sh FILES
.Bl -tag -width Ds
diff --git a/ssh-agent.1 b/ssh-agent.1
index 281ecbd..1a9a635 100644
--- a/ssh-agent.1
+++ b/ssh-agent.1
@@ -201,6 +201,26 @@ sockets used to contain the connection to the authentication agent.
These sockets should only be readable by the owner.
The sockets should get automatically removed when the agent exits.
.El
+.Sh ENVIRONMENT
+.Bl -tag -width Ds -compact
+.Pp
+.It Pa SSH_USE_STRONG_RNG
+The reseeding of the OpenSSL random generator is usually done from
+.Cm getrandom(1)
+without any specific flags.
+If the
+.Cm SSH_USE_STRONG_RNG
+environment variable is set to value other than
+.Cm 0
+the OpenSSL random generator is reseeded from
+.Cm getrandom(1)
+with GRND_RANDOM flag specified.
+The number of bytes read is defined by the SSH_USE_STRONG_RNG value.
+Minimum is 14 bytes.
+This setting is not recommended on the computers without the hardware
+random generator because insufficient entropy causes the connection to
+be blocked until enough entropy is available.
+.El
.Sh SEE ALSO
.Xr ssh 1 ,
.Xr ssh-add 1 ,
diff --git a/ssh-keygen.1 b/ssh-keygen.1
index 12e00d4..1b51a4a 100644
--- a/ssh-keygen.1
+++ b/ssh-keygen.1
@@ -832,6 +832,26 @@ Contains Diffie-Hellman groups used for DH-GEX.
The file format is described in
.Xr moduli 5 .
.El
+.Sh ENVIRONMENT
+.Bl -tag -width Ds -compact
+.Pp
+.It Pa SSH_USE_STRONG_RNG
+The reseeding of the OpenSSL random generator is usually done from
+.Cm getrandom(1)
+without any specific flags.
+If the
+.Cm SSH_USE_STRONG_RNG
+environment variable is set to value other than
+.Cm 0
+the OpenSSL random generator is reseeded from
+.Cm getrandom(1)
+with GRND_RANDOM flag specified.
+The number of bytes read is defined by the SSH_USE_STRONG_RNG value.
+Minimum is 14 bytes.
+This setting is not recommended on the computers without the hardware
+random generator because insufficient entropy causes the connection to
+be blocked until enough entropy is available.
+.El
.Sh SEE ALSO
.Xr ssh 1 ,
.Xr ssh-add 1 ,
diff --git a/ssh-keysign.8 b/ssh-keysign.8
index 69d0829..02d79f8 100644
--- a/ssh-keysign.8
+++ b/ssh-keysign.8
@@ -80,6 +80,26 @@ must be set-uid root if host-based authentication is used.
If these files exist they are assumed to contain public certificate
information corresponding with the private keys above.
.El
+.Sh ENVIRONMENT
+.Bl -tag -width Ds -compact
+.Pp
+.It Pa SSH_USE_STRONG_RNG
+The reseeding of the OpenSSL random generator is usually done from
+.Cm getrandom(1)
+without any specific flags.
+If the
+.Cm SSH_USE_STRONG_RNG
+environment variable is set to value other than
+.Cm 0
+the OpenSSL random generator is reseeded from
+.Cm getrandom(1)
+with GRND_RANDOM flag specified.
+The number of bytes read is defined by the SSH_USE_STRONG_RNG value.
+Minimum is 14 bytes.
+This setting is not recommended on the computers without the hardware
+random generator because insufficient entropy causes the connection to
+be blocked until enough entropy is available.
+.El
.Sh SEE ALSO
.Xr ssh 1 ,
.Xr ssh-keygen 1 ,
diff --git a/ssh.1 b/ssh.1
index 929904b..f65e42f 100644
--- a/ssh.1
+++ b/ssh.1
@@ -1309,6 +1309,25 @@ For more information, see the
.Cm PermitUserEnvironment
option in
.Xr sshd_config 5 .
+.Bl -tag -width "SSH_ORIGINAL_COMMAND"
+.Pp
+.It Ev SSH_USE_STRONG_RNG
+The reseeding of the OpenSSL random generator is usually done from
+.Cm getrandom(1)
+without any specific flags.
+If the
+.Cm SSH_USE_STRONG_RNG
+environment variable is set to value other than
+.Cm 0
+the OpenSSL random generator is reseeded from
+.Cm getrandom(1)
+with GRND_RANDOM flag specified.
+The number of bytes read is defined by the SSH_USE_STRONG_RNG value.
+Minimum is 14 bytes.
+This setting is not recommended on the computers without the hardware
+random generator because insufficient entropy causes the connection to
+be blocked until enough entropy is available.
+.El
.Sh FILES
.Bl -tag -width Ds -compact
.It Pa ~/.rhosts
diff --git a/sshd.8 b/sshd.8
index c2c237f..058d37a 100644
--- a/sshd.8
+++ b/sshd.8
@@ -951,6 +951,26 @@ concurrently for different ports, this contains the process ID of the one
started last).
The content of this file is not sensitive; it can be world-readable.
.El
+.Sh ENVIRONMENT
+.Bl -tag -width Ds -compact
+.Pp
+.It Ev SSH_USE_STRONG_RNG
+The reseeding of the OpenSSL random generator is usually done from
+.Cm getrandom(1)
+without any specific flags.
+If the
+.Cm SSH_USE_STRONG_RNG
+environment variable is set to value other than
+.Cm 0
+the OpenSSL random generator is reseeded from
+.Cm getrandom(1)
+with GRND_RANDOM flag specified.
+The number of bytes read is defined by the SSH_USE_STRONG_RNG value.
+Minimum is 14 bytes.
+This setting is not recommended on the computers without the hardware
+random generator because insufficient entropy causes the connection to
+be blocked until enough entropy is available.
+.El
.Sh IPV6
IPv6 address can be used everywhere where IPv4 address. In all entries must be the IPv6 address enclosed in square brackets. Note: The square brackets are metacharacters for the shell and must be escaped in shell.
.Sh SEE ALSO

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,27 @@
diff --git a/sftp.c b/sftp.c
index 04881c83..03c7a5c7 100644
--- a/sftp.c
+++ b/sftp.c
@@ -2527,12 +2527,17 @@ main(int argc, char **argv)
port = tmp;
break;
default:
+ /* Try with user, host and path. */
if (parse_user_host_path(*argv, &user, &host,
- &file1) == -1) {
- /* Treat as a plain hostname. */
- host = xstrdup(*argv);
- host = cleanhostname(host);
- }
+ &file1) == 0)
+ break;
+ /* Try with user and host. */
+ if (parse_user_host_port(*argv, &user, &host, NULL)
+ == 0)
+ break;
+ /* Treat as a plain hostname. */
+ host = xstrdup(*argv);
+ host = cleanhostname(host);
break;
}
file2 = *(argv + 1);

View file

@ -0,0 +1,107 @@
From 4a41d245d6b13bd3882c8dc058dbd2e2b39a9f67 Mon Sep 17 00:00:00 2001
From: "djm@openbsd.org" <djm@openbsd.org>
Date: Fri, 24 Jan 2020 00:27:04 +0000
Subject: [PATCH] upstream: when signing a certificate with an RSA key, default
to
a safe signature algorithm (rsa-sha-512) if not is explicitly specified by
the user; ok markus@
OpenBSD-Commit-ID: e05f638f0be6c0266e1d3d799716b461011e83a9
---
ssh-keygen.c | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/ssh-keygen.c b/ssh-keygen.c
index 564c3c481..f2192edb9 100644
--- a/ssh-keygen.c
+++ b/ssh-keygen.c
@@ -1788,10 +1788,14 @@ do_ca_sign(struct passwd *pw, const char *ca_key_path, int prefer_agent,
}
free(tmp);
- if (key_type_name != NULL &&
- sshkey_type_from_name(key_type_name) != ca->type) {
- fatal("CA key type %s doesn't match specified %s",
- sshkey_ssh_name(ca), key_type_name);
+ if (key_type_name != NULL) {
+ if (sshkey_type_from_name(key_type_name) != ca->type) {
+ fatal("CA key type %s doesn't match specified %s",
+ sshkey_ssh_name(ca), key_type_name);
+ }
+ } else if (ca->type == KEY_RSA) {
+ /* Default to a good signature algorithm */
+ key_type_name = "rsa-sha2-512";
}
for (i = 0; i < argc; i++) {
From 476e3551b2952ef73acc43d995e832539bf9bc4d Mon Sep 17 00:00:00 2001
From: "djm@openbsd.org" <djm@openbsd.org>
Date: Mon, 20 May 2019 00:20:35 +0000
Subject: [PATCH] upstream: When signing certificates with an RSA key, default
to
using the rsa-sha2-512 signature algorithm. Certificates signed by RSA keys
will therefore be incompatible with OpenSSH < 7.2 unless the default is
overridden.
Document the ability of the ssh-keygen -t flag to override the
signature algorithm when signing certificates, and the new default.
ok deraadt@
OpenBSD-Commit-ID: 400c9c15013978204c2cb80f294b03ae4cfc8b95
---
ssh-keygen.1 | 13 +++++++++++--
sshkey.c | 9 ++++++++-
2 files changed, 19 insertions(+), 3 deletions(-)
diff --git a/ssh-keygen.1 b/ssh-keygen.1
index f29774249..673bf6e2f 100644
--- a/ssh-keygen.1
+++ b/ssh-keygen.1
@@ -35,7 +35,7 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd $Mdocdate: March 5 2019 $
+.Dd $Mdocdate: May 20 2019 $
.Dt SSH-KEYGEN 1
.Os
.Sh NAME
@@ -577,6 +577,15 @@ The possible values are
.Dq ed25519 ,
or
.Dq rsa .
+.Pp
+This flag may also be used to specify the desired signature type when
+signing certificates using a RSA CA key.
+The available RSA signature variants are
+.Dq ssh-rsa
+(SHA1 signatures, not recommended),
+.Dq rsa-sha2-256
+.Dq rsa-sha2-512
+(the default).
.It Fl U
When used in combination with
.Fl s ,
diff --git a/sshkey.c b/sshkey.c
index 9849cb237..379a579cf 100644
--- a/sshkey.c
+++ b/sshkey.c
@@ -2528,6 +2528,13 @@ sshkey_certify_custom(struct sshkey *k, struct sshkey *ca, const char *alg,
strcmp(alg, k->cert->signature_type) != 0)
return SSH_ERR_INVALID_ARGUMENT;
+ /*
+ * If no signing algorithm or signature_type was specified and we're
+ * using a RSA key, then default to a good signature algorithm.
+ */
+ if (alg == NULL && ca->type == KEY_RSA)
+ alg = "rsa-sha2-512";
+
if ((ret = sshkey_to_blob(ca, &ca_blob, &ca_len)) != 0)
return SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;

View file

@ -0,0 +1,12 @@
diff -up openssh-8.0p1/ssh-keygen.c.strip-doseol openssh-8.0p1/ssh-keygen.c
--- openssh-8.0p1/ssh-keygen.c.strip-doseol 2021-03-18 17:41:34.472404994 +0100
+++ openssh-8.0p1/ssh-keygen.c 2021-03-18 17:41:55.255538761 +0100
@@ -901,7 +901,7 @@ do_fingerprint(struct passwd *pw)
while (getline(&line, &linesize, f) != -1) {
lnum++;
cp = line;
- cp[strcspn(cp, "\n")] = '\0';
+ cp[strcspn(cp, "\r\n")] = '\0';
/* Trim leading space and comments */
cp = line + strspn(line, " \t");
if (*cp == '#' || *cp == '\0')

View file

@ -0,0 +1,33 @@
From 7250879c72d28275a53f2f220e49646c3e42ef18 Mon Sep 17 00:00:00 2001
From: "djm@openbsd.org" <djm@openbsd.org>
Date: Fri, 12 Jul 2019 04:08:39 +0000
Subject: [PATCH] upstream: include SHA2-variant RSA key algorithms in KEX
proposal;
allows ssh-keyscan to harvest keys from servers that disable olde SHA1
ssh-rsa. bz#3029 from Jakub Jelen
OpenBSD-Commit-ID: 9f95ebf76a150c2f727ca4780fb2599d50bbab7a
---
ssh-keyscan.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/ssh-keyscan.c b/ssh-keyscan.c
index d95ba1b37..d383b57b9 100644
--- a/ssh-keyscan.c
+++ b/ssh-keyscan.c
@@ -233,7 +233,12 @@ keygrab_ssh2(con *c)
break;
case KT_RSA:
myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = get_cert ?
- "ssh-rsa-cert-v01@openssh.com" : "ssh-rsa";
+ "rsa-sha2-512-cert-v01@openssh.com,"
+ "rsa-sha2-256-cert-v01@openssh.com,"
+ "ssh-rsa-cert-v01@openssh.com" :
+ "rsa-sha2-512,"
+ "rsa-sha2-256,"
+ "ssh-rsa";
break;
case KT_ED25519:
myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = get_cert ?

View file

@ -0,0 +1,720 @@
From ed7ec0cdf577ffbb0b15145340cf51596ca3eb89 Mon Sep 17 00:00:00 2001
From: Jakub Jelen <jjelen@redhat.com>
Date: Tue, 14 May 2019 10:45:45 +0200
Subject: [PATCH] Use high-level OpenSSL API for signatures
---
digest-openssl.c | 16 ++++
digest.h | 6 ++
ssh-dss.c | 65 ++++++++++------
ssh-ecdsa.c | 69 ++++++++++-------
ssh-rsa.c | 193 +++++++++--------------------------------------
sshkey.c | 77 +++++++++++++++++++
sshkey.h | 4 +
7 files changed, 221 insertions(+), 209 deletions(-)
diff --git a/digest-openssl.c b/digest-openssl.c
index da7ed72bc..6a21d8adb 100644
--- a/digest-openssl.c
+++ b/digest-openssl.c
@@ -63,6 +63,22 @@ const struct ssh_digest digests[] = {
{ -1, NULL, 0, NULL },
};
+const EVP_MD *
+ssh_digest_to_md(int digest_type)
+{
+ switch (digest_type) {
+ case SSH_DIGEST_SHA1:
+ return EVP_sha1();
+ case SSH_DIGEST_SHA256:
+ return EVP_sha256();
+ case SSH_DIGEST_SHA384:
+ return EVP_sha384();
+ case SSH_DIGEST_SHA512:
+ return EVP_sha512();
+ }
+ return NULL;
+}
+
static const struct ssh_digest *
ssh_digest_by_alg(int alg)
{
diff --git a/digest.h b/digest.h
index 274574d0e..c7ceeb36f 100644
--- a/digest.h
+++ b/digest.h
@@ -32,6 +32,12 @@
struct sshbuf;
struct ssh_digest_ctx;
+#ifdef WITH_OPENSSL
+#include <openssl/evp.h>
+/* Converts internal digest representation to the OpenSSL one */
+const EVP_MD *ssh_digest_to_md(int digest_type);
+#endif
+
/* Looks up a digest algorithm by name */
int ssh_digest_alg_by_name(const char *name);
diff --git a/ssh-dss.c b/ssh-dss.c
index a23c383dc..ea45e7275 100644
--- a/ssh-dss.c
+++ b/ssh-dss.c
@@ -52,11 +52,15 @@ int
ssh_dss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
const u_char *data, size_t datalen, u_int compat)
{
+ EVP_PKEY *pkey = NULL;
DSA_SIG *sig = NULL;
const BIGNUM *sig_r, *sig_s;
- u_char digest[SSH_DIGEST_MAX_LENGTH], sigblob[SIGBLOB_LEN];
- size_t rlen, slen, len, dlen = ssh_digest_bytes(SSH_DIGEST_SHA1);
+ u_char sigblob[SIGBLOB_LEN];
+ size_t rlen, slen;
+ int len;
struct sshbuf *b = NULL;
+ u_char *sigb = NULL;
+ const u_char *psig = NULL;
int ret = SSH_ERR_INVALID_ARGUMENT;
if (lenp != NULL)
@@ -67,17 +71,24 @@ ssh_dss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
if (key == NULL || key->dsa == NULL ||
sshkey_type_plain(key->type) != KEY_DSA)
return SSH_ERR_INVALID_ARGUMENT;
- if (dlen == 0)
- return SSH_ERR_INTERNAL_ERROR;
- if ((ret = ssh_digest_memory(SSH_DIGEST_SHA1, data, datalen,
- digest, sizeof(digest))) != 0)
+ if ((pkey = EVP_PKEY_new()) == NULL ||
+ EVP_PKEY_set1_DSA(pkey, key->dsa) != 1)
+ return SSH_ERR_ALLOC_FAIL;
+ ret = sshkey_calculate_signature(pkey, SSH_DIGEST_SHA1, &sigb, &len,
+ data, datalen);
+ EVP_PKEY_free(pkey);
+ if (ret < 0) {
goto out;
+ }
- if ((sig = DSA_do_sign(digest, dlen, key->dsa)) == NULL) {
+ psig = sigb;
+ if ((sig = d2i_DSA_SIG(NULL, &psig, len)) == NULL) {
ret = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
+ free(sigb);
+ sigb = NULL;
DSA_SIG_get0(sig, &sig_r, &sig_s);
rlen = BN_num_bytes(sig_r);
@@ -110,7 +121,7 @@ ssh_dss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
*lenp = len;
ret = 0;
out:
- explicit_bzero(digest, sizeof(digest));
+ free(sigb);
DSA_SIG_free(sig);
sshbuf_free(b);
return ret;
@@ -121,20 +132,20 @@ ssh_dss_verify(const struct sshkey *key,
const u_char *signature, size_t signaturelen,
const u_char *data, size_t datalen, u_int compat)
{
+ EVP_PKEY *pkey = NULL;
DSA_SIG *sig = NULL;
BIGNUM *sig_r = NULL, *sig_s = NULL;
- u_char digest[SSH_DIGEST_MAX_LENGTH], *sigblob = NULL;
- size_t len, dlen = ssh_digest_bytes(SSH_DIGEST_SHA1);
+ u_char *sigblob = NULL;
+ size_t len, slen;
int ret = SSH_ERR_INTERNAL_ERROR;
struct sshbuf *b = NULL;
char *ktype = NULL;
+ u_char *sigb = NULL, *psig = NULL;
if (key == NULL || key->dsa == NULL ||
sshkey_type_plain(key->type) != KEY_DSA ||
signature == NULL || signaturelen == 0)
return SSH_ERR_INVALID_ARGUMENT;
- if (dlen == 0)
- return SSH_ERR_INTERNAL_ERROR;
/* fetch signature */
if ((b = sshbuf_from(signature, signaturelen)) == NULL)
@@ -176,25 +187,31 @@ ssh_dss_verify(const struct sshkey *key,
}
sig_r = sig_s = NULL; /* transferred */
- /* sha1 the data */
- if ((ret = ssh_digest_memory(SSH_DIGEST_SHA1, data, datalen,
- digest, sizeof(digest))) != 0)
+ if ((slen = i2d_DSA_SIG(sig, NULL)) == 0) {
+ ret = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
-
- switch (DSA_do_verify(digest, dlen, sig, key->dsa)) {
- case 1:
- ret = 0;
- break;
- case 0:
- ret = SSH_ERR_SIGNATURE_INVALID;
+ }
+ if ((sigb = malloc(slen)) == NULL) {
+ ret = SSH_ERR_ALLOC_FAIL;
goto out;
- default:
+ }
+ psig = sigb;
+ if ((slen = i2d_DSA_SIG(sig, &psig)) == 0) {
ret = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
+ if ((pkey = EVP_PKEY_new()) == NULL ||
+ EVP_PKEY_set1_DSA(pkey, key->dsa) != 1) {
+ ret = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ ret = sshkey_verify_signature(pkey, SSH_DIGEST_SHA1, data, datalen,
+ sigb, slen);
+ EVP_PKEY_free(pkey);
+
out:
- explicit_bzero(digest, sizeof(digest));
+ free(sigb);
DSA_SIG_free(sig);
BN_clear_free(sig_r);
BN_clear_free(sig_s);
diff --git a/ssh-ecdsa.c b/ssh-ecdsa.c
index 599c7199d..b036796e8 100644
--- a/ssh-ecdsa.c
+++ b/ssh-ecdsa.c
@@ -50,11 +50,13 @@ int
ssh_ecdsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
const u_char *data, size_t datalen, u_int compat)
{
+ EVP_PKEY *pkey = NULL;
ECDSA_SIG *sig = NULL;
+ unsigned char *sigb = NULL;
+ const unsigned char *psig;
const BIGNUM *sig_r, *sig_s;
int hash_alg;
- u_char digest[SSH_DIGEST_MAX_LENGTH];
- size_t len, dlen;
+ int len;
struct sshbuf *b = NULL, *bb = NULL;
int ret = SSH_ERR_INTERNAL_ERROR;
@@ -67,18 +69,24 @@ ssh_ecdsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
sshkey_type_plain(key->type) != KEY_ECDSA)
return SSH_ERR_INVALID_ARGUMENT;
- if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1 ||
- (dlen = ssh_digest_bytes(hash_alg)) == 0)
+ if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1)
return SSH_ERR_INTERNAL_ERROR;
- if ((ret = ssh_digest_memory(hash_alg, data, datalen,
- digest, sizeof(digest))) != 0)
+
+ if ((pkey = EVP_PKEY_new()) == NULL ||
+ EVP_PKEY_set1_EC_KEY(pkey, key->ecdsa) != 1)
+ return SSH_ERR_ALLOC_FAIL;
+ ret = sshkey_calculate_signature(pkey, hash_alg, &sigb, &len, data,
+ datalen);
+ EVP_PKEY_free(pkey);
+ if (ret < 0) {
goto out;
+ }
- if ((sig = ECDSA_do_sign(digest, dlen, key->ecdsa)) == NULL) {
+ psig = sigb;
+ if ((sig = d2i_ECDSA_SIG(NULL, &psig, len)) == NULL) {
ret = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
-
if ((bb = sshbuf_new()) == NULL || (b = sshbuf_new()) == NULL) {
ret = SSH_ERR_ALLOC_FAIL;
goto out;
@@ -102,7 +110,7 @@ ssh_ecdsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
*lenp = len;
ret = 0;
out:
- explicit_bzero(digest, sizeof(digest));
+ free(sigb);
sshbuf_free(b);
sshbuf_free(bb);
ECDSA_SIG_free(sig);
@@ -115,22 +123,21 @@ ssh_ecdsa_verify(const struct sshkey *key,
const u_char *signature, size_t signaturelen,
const u_char *data, size_t datalen, u_int compat)
{
+ EVP_PKEY *pkey = NULL;
ECDSA_SIG *sig = NULL;
BIGNUM *sig_r = NULL, *sig_s = NULL;
- int hash_alg;
- u_char digest[SSH_DIGEST_MAX_LENGTH];
- size_t dlen;
+ int hash_alg, len;
int ret = SSH_ERR_INTERNAL_ERROR;
struct sshbuf *b = NULL, *sigbuf = NULL;
char *ktype = NULL;
+ unsigned char *sigb = NULL, *psig = NULL;
if (key == NULL || key->ecdsa == NULL ||
sshkey_type_plain(key->type) != KEY_ECDSA ||
signature == NULL || signaturelen == 0)
return SSH_ERR_INVALID_ARGUMENT;
- if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1 ||
- (dlen = ssh_digest_bytes(hash_alg)) == 0)
+ if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1)
return SSH_ERR_INTERNAL_ERROR;
/* fetch signature */
@@ -166,28 +173,36 @@ ssh_ecdsa_verify(const struct sshkey *key,
}
sig_r = sig_s = NULL; /* transferred */
- if (sshbuf_len(sigbuf) != 0) {
- ret = SSH_ERR_UNEXPECTED_TRAILING_DATA;
+ /* Figure out the length */
+ if ((len = i2d_ECDSA_SIG(sig, NULL)) == 0) {
+ ret = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+ if ((sigb = malloc(len)) == NULL) {
+ ret = SSH_ERR_ALLOC_FAIL;
goto out;
}
- if ((ret = ssh_digest_memory(hash_alg, data, datalen,
- digest, sizeof(digest))) != 0)
+ psig = sigb;
+ if ((len = i2d_ECDSA_SIG(sig, &psig)) == 0) {
+ ret = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
+ }
- switch (ECDSA_do_verify(digest, dlen, sig, key->ecdsa)) {
- case 1:
- ret = 0;
- break;
- case 0:
- ret = SSH_ERR_SIGNATURE_INVALID;
+ if (sshbuf_len(sigbuf) != 0) {
+ ret = SSH_ERR_UNEXPECTED_TRAILING_DATA;
goto out;
- default:
- ret = SSH_ERR_LIBCRYPTO_ERROR;
+ }
+
+ if ((pkey = EVP_PKEY_new()) == NULL ||
+ EVP_PKEY_set1_EC_KEY(pkey, key->ecdsa) != 1) {
+ ret = SSH_ERR_ALLOC_FAIL;
goto out;
}
+ ret = sshkey_verify_signature(pkey, hash_alg, data, datalen, sigb, len);
+ EVP_PKEY_free(pkey);
out:
- explicit_bzero(digest, sizeof(digest));
+ free(sigb);
sshbuf_free(sigbuf);
sshbuf_free(b);
ECDSA_SIG_free(sig);
diff --git a/ssh-rsa.c b/ssh-rsa.c
index 9b14f9a9a..8ef3a6aca 100644
--- a/ssh-rsa.c
+++ b/ssh-rsa.c
@@ -37,7 +37,7 @@
#include "openbsd-compat/openssl-compat.h"
-static int openssh_RSA_verify(int, u_char *, size_t, u_char *, size_t, RSA *);
+static int openssh_RSA_verify(int, const u_char *, size_t, u_char *, size_t, EVP_PKEY *);
static const char *
rsa_hash_alg_ident(int hash_alg)
@@ -90,21 +90,6 @@ rsa_hash_id_from_keyname(const char *alg)
return -1;
}
-static int
-rsa_hash_alg_nid(int type)
-{
- switch (type) {
- case SSH_DIGEST_SHA1:
- return NID_sha1;
- case SSH_DIGEST_SHA256:
- return NID_sha256;
- case SSH_DIGEST_SHA512:
- return NID_sha512;
- default:
- return -1;
- }
-}
-
int
ssh_rsa_complete_crt_parameters(struct sshkey *key, const BIGNUM *iqmp)
{
@@ -164,11 +149,10 @@ int
ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
const u_char *data, size_t datalen, const char *alg_ident)
{
- const BIGNUM *rsa_n;
- u_char digest[SSH_DIGEST_MAX_LENGTH], *sig = NULL;
- size_t slen = 0;
- u_int dlen, len;
- int nid, hash_alg, ret = SSH_ERR_INTERNAL_ERROR;
+ EVP_PKEY *pkey = NULL;
+ u_char *sig = NULL;
+ int len, slen = 0;
+ int hash_alg, ret = SSH_ERR_INTERNAL_ERROR;
struct sshbuf *b = NULL;
if (lenp != NULL)
@@ -180,33 +164,24 @@ ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
hash_alg = SSH_DIGEST_SHA1;
else
hash_alg = rsa_hash_id_from_keyname(alg_ident);
+
if (key == NULL || key->rsa == NULL || hash_alg == -1 ||
sshkey_type_plain(key->type) != KEY_RSA)
return SSH_ERR_INVALID_ARGUMENT;
- RSA_get0_key(key->rsa, &rsa_n, NULL, NULL);
- if (BN_num_bits(rsa_n) < SSH_RSA_MINIMUM_MODULUS_SIZE)
- return SSH_ERR_KEY_LENGTH;
slen = RSA_size(key->rsa);
- if (slen <= 0 || slen > SSHBUF_MAX_BIGNUM)
- return SSH_ERR_INVALID_ARGUMENT;
-
- /* hash the data */
- nid = rsa_hash_alg_nid(hash_alg);
- if ((dlen = ssh_digest_bytes(hash_alg)) == 0)
- return SSH_ERR_INTERNAL_ERROR;
- if ((ret = ssh_digest_memory(hash_alg, data, datalen,
- digest, sizeof(digest))) != 0)
- goto out;
+ if (RSA_bits(key->rsa) < SSH_RSA_MINIMUM_MODULUS_SIZE)
+ return SSH_ERR_KEY_LENGTH;
- if ((sig = malloc(slen)) == NULL) {
- ret = SSH_ERR_ALLOC_FAIL;
+ if ((pkey = EVP_PKEY_new()) == NULL ||
+ EVP_PKEY_set1_RSA(pkey, key->rsa) != 1)
+ return SSH_ERR_ALLOC_FAIL;
+ ret = sshkey_calculate_signature(pkey, hash_alg, &sig, &len, data,
+ datalen);
+ EVP_PKEY_free(pkey);
+ if (ret < 0) {
goto out;
}
- if (RSA_sign(nid, digest, dlen, sig, &len, key->rsa) != 1) {
- ret = SSH_ERR_LIBCRYPTO_ERROR;
- goto out;
- }
if (len < slen) {
size_t diff = slen - len;
memmove(sig + diff, sig, len);
@@ -215,6 +190,7 @@ ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
ret = SSH_ERR_INTERNAL_ERROR;
goto out;
}
+
/* encode signature */
if ((b = sshbuf_new()) == NULL) {
ret = SSH_ERR_ALLOC_FAIL;
@@ -235,7 +211,6 @@ ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
*lenp = len;
ret = 0;
out:
- explicit_bzero(digest, sizeof(digest));
freezero(sig, slen);
sshbuf_free(b);
return ret;
@@ -246,10 +221,10 @@ ssh_rsa_verify(const struct sshkey *key,
const u_char *sig, size_t siglen, const u_char *data, size_t datalen,
const char *alg)
{
- const BIGNUM *rsa_n;
+ EVP_PKEY *pkey = NULL;
char *sigtype = NULL;
int hash_alg, want_alg, ret = SSH_ERR_INTERNAL_ERROR;
- size_t len = 0, diff, modlen, dlen;
+ size_t len = 0, diff, modlen;
struct sshbuf *b = NULL;
u_char digest[SSH_DIGEST_MAX_LENGTH], *osigblob, *sigblob = NULL;
@@ -257,8 +232,7 @@ ssh_rsa_verify(const struct sshkey *key,
sshkey_type_plain(key->type) != KEY_RSA ||
sig == NULL || siglen == 0)
return SSH_ERR_INVALID_ARGUMENT;
- RSA_get0_key(key->rsa, &rsa_n, NULL, NULL);
- if (BN_num_bits(rsa_n) < SSH_RSA_MINIMUM_MODULUS_SIZE)
+ if (RSA_bits(key->rsa) < SSH_RSA_MINIMUM_MODULUS_SIZE)
return SSH_ERR_KEY_LENGTH;
if ((b = sshbuf_from(sig, siglen)) == NULL)
@@ -310,16 +284,15 @@ ssh_rsa_verify(const struct sshkey *key,
explicit_bzero(sigblob, diff);
len = modlen;
}
- if ((dlen = ssh_digest_bytes(hash_alg)) == 0) {
- ret = SSH_ERR_INTERNAL_ERROR;
+
+ if ((pkey = EVP_PKEY_new()) == NULL ||
+ EVP_PKEY_set1_RSA(pkey, key->rsa) != 1) {
+ ret = SSH_ERR_ALLOC_FAIL;
goto out;
}
- if ((ret = ssh_digest_memory(hash_alg, data, datalen,
- digest, sizeof(digest))) != 0)
- goto out;
+ ret = openssh_RSA_verify(hash_alg, data, datalen, sigblob, len, pkey);
+ EVP_PKEY_free(pkey);
- ret = openssh_RSA_verify(hash_alg, digest, dlen, sigblob, len,
- key->rsa);
out:
freezero(sigblob, len);
free(sigtype);
@@ -328,122 +301,26 @@ ssh_rsa_verify(const struct sshkey *key,
return ret;
}
-/*
- * See:
- * http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/
- * ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.asn
- */
-
-/*
- * id-sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3)
- * oiw(14) secsig(3) algorithms(2) 26 }
- */
-static const u_char id_sha1[] = {
- 0x30, 0x21, /* type Sequence, length 0x21 (33) */
- 0x30, 0x09, /* type Sequence, length 0x09 */
- 0x06, 0x05, /* type OID, length 0x05 */
- 0x2b, 0x0e, 0x03, 0x02, 0x1a, /* id-sha1 OID */
- 0x05, 0x00, /* NULL */
- 0x04, 0x14 /* Octet string, length 0x14 (20), followed by sha1 hash */
-};
-
-/*
- * See http://csrc.nist.gov/groups/ST/crypto_apps_infra/csor/algorithms.html
- * id-sha256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840)
- * organization(1) gov(101) csor(3) nistAlgorithm(4) hashAlgs(2)
- * id-sha256(1) }
- */
-static const u_char id_sha256[] = {
- 0x30, 0x31, /* type Sequence, length 0x31 (49) */
- 0x30, 0x0d, /* type Sequence, length 0x0d (13) */
- 0x06, 0x09, /* type OID, length 0x09 */
- 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, /* id-sha256 */
- 0x05, 0x00, /* NULL */
- 0x04, 0x20 /* Octet string, length 0x20 (32), followed by sha256 hash */
-};
-
-/*
- * See http://csrc.nist.gov/groups/ST/crypto_apps_infra/csor/algorithms.html
- * id-sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840)
- * organization(1) gov(101) csor(3) nistAlgorithm(4) hashAlgs(2)
- * id-sha256(3) }
- */
-static const u_char id_sha512[] = {
- 0x30, 0x51, /* type Sequence, length 0x51 (81) */
- 0x30, 0x0d, /* type Sequence, length 0x0d (13) */
- 0x06, 0x09, /* type OID, length 0x09 */
- 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, /* id-sha512 */
- 0x05, 0x00, /* NULL */
- 0x04, 0x40 /* Octet string, length 0x40 (64), followed by sha512 hash */
-};
-
static int
-rsa_hash_alg_oid(int hash_alg, const u_char **oidp, size_t *oidlenp)
+openssh_RSA_verify(int hash_alg, const u_char *data, size_t datalen,
+ u_char *sigbuf, size_t siglen, EVP_PKEY *pkey)
{
- switch (hash_alg) {
- case SSH_DIGEST_SHA1:
- *oidp = id_sha1;
- *oidlenp = sizeof(id_sha1);
- break;
- case SSH_DIGEST_SHA256:
- *oidp = id_sha256;
- *oidlenp = sizeof(id_sha256);
- break;
- case SSH_DIGEST_SHA512:
- *oidp = id_sha512;
- *oidlenp = sizeof(id_sha512);
- break;
- default:
- return SSH_ERR_INVALID_ARGUMENT;
- }
- return 0;
-}
+ size_t rsasize = 0;
+ const RSA *rsa;
+ int ret;
-static int
-openssh_RSA_verify(int hash_alg, u_char *hash, size_t hashlen,
- u_char *sigbuf, size_t siglen, RSA *rsa)
-{
- size_t rsasize = 0, oidlen = 0, hlen = 0;
- int ret, len, oidmatch, hashmatch;
- const u_char *oid = NULL;
- u_char *decrypted = NULL;
-
- if ((ret = rsa_hash_alg_oid(hash_alg, &oid, &oidlen)) != 0)
- return ret;
- ret = SSH_ERR_INTERNAL_ERROR;
- hlen = ssh_digest_bytes(hash_alg);
- if (hashlen != hlen) {
- ret = SSH_ERR_INVALID_ARGUMENT;
- goto done;
- }
+ rsa = EVP_PKEY_get0_RSA(pkey);
rsasize = RSA_size(rsa);
if (rsasize <= 0 || rsasize > SSHBUF_MAX_BIGNUM ||
siglen == 0 || siglen > rsasize) {
ret = SSH_ERR_INVALID_ARGUMENT;
goto done;
}
- if ((decrypted = malloc(rsasize)) == NULL) {
- ret = SSH_ERR_ALLOC_FAIL;
- goto done;
- }
- if ((len = RSA_public_decrypt(siglen, sigbuf, decrypted, rsa,
- RSA_PKCS1_PADDING)) < 0) {
- ret = SSH_ERR_LIBCRYPTO_ERROR;
- goto done;
- }
- if (len < 0 || (size_t)len != hlen + oidlen) {
- ret = SSH_ERR_INVALID_FORMAT;
- goto done;
- }
- oidmatch = timingsafe_bcmp(decrypted, oid, oidlen) == 0;
- hashmatch = timingsafe_bcmp(decrypted + oidlen, hash, hlen) == 0;
- if (!oidmatch || !hashmatch) {
- ret = SSH_ERR_SIGNATURE_INVALID;
- goto done;
- }
- ret = 0;
+
+ ret = sshkey_verify_signature(pkey, hash_alg, data, datalen,
+ sigbuf, siglen);
+
done:
- freezero(decrypted, rsasize);
return ret;
}
#endif /* WITH_OPENSSL */
diff --git a/sshkey.c b/sshkey.c
index ad1957762..b95ed0b10 100644
--- a/sshkey.c
+++ b/sshkey.c
@@ -358,6 +358,83 @@ sshkey_type_plain(int type)
}
#ifdef WITH_OPENSSL
+int
+sshkey_calculate_signature(EVP_PKEY *pkey, int hash_alg, u_char **sigp,
+ int *lenp, const u_char *data, size_t datalen)
+{
+ EVP_MD_CTX *ctx = NULL;
+ u_char *sig = NULL;
+ int ret, slen, len;
+
+ if (sigp == NULL || lenp == NULL) {
+ return SSH_ERR_INVALID_ARGUMENT;
+ }
+
+ slen = EVP_PKEY_size(pkey);
+ if (slen <= 0 || slen > SSHBUF_MAX_BIGNUM)
+ return SSH_ERR_INVALID_ARGUMENT;
+
+ len = slen;
+ if ((sig = malloc(slen)) == NULL) {
+ return SSH_ERR_ALLOC_FAIL;
+ }
+
+ if ((ctx = EVP_MD_CTX_new()) == NULL) {
+ 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) {
+ ret = SSH_ERR_LIBCRYPTO_ERROR;
+ goto error;
+ }
+
+ *sigp = sig;
+ *lenp = len;
+ /* Now owned by the caller */
+ sig = NULL;
+ ret = 0;
+
+error:
+ EVP_MD_CTX_free(ctx);
+ free(sig);
+ return ret;
+}
+
+int
+sshkey_verify_signature(EVP_PKEY *pkey, int hash_alg, const u_char *data,
+ size_t datalen, u_char *sigbuf, int siglen)
+{
+ EVP_MD_CTX *ctx = NULL;
+ int ret;
+
+ 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) {
+ ret = SSH_ERR_LIBCRYPTO_ERROR;
+ goto done;
+ }
+ ret = EVP_VerifyFinal(ctx, sigbuf, siglen, pkey);
+ switch (ret) {
+ case 1:
+ ret = 0;
+ break;
+ case 0:
+ ret = SSH_ERR_SIGNATURE_INVALID;
+ break;
+ default:
+ ret = SSH_ERR_LIBCRYPTO_ERROR;
+ break;
+ }
+
+done:
+ EVP_MD_CTX_free(ctx);
+ return ret;
+}
+
/* XXX: these are really begging for a table-driven approach */
int
sshkey_curve_name_to_nid(const char *name)
diff --git a/sshkey.h b/sshkey.h
index a91e60436..270901a87 100644
--- a/sshkey.h
+++ b/sshkey.h
@@ -179,6 +179,10 @@ const char *sshkey_ssh_name(const struct sshkey *);
const char *sshkey_ssh_name_plain(const struct sshkey *);
int sshkey_names_valid2(const char *, int);
char *sshkey_alg_list(int, int, int, char);
+int sshkey_calculate_signature(EVP_PKEY*, int, u_char **,
+ int *, const u_char *, size_t);
+int sshkey_verify_signature(EVP_PKEY *, int, const u_char *,
+ size_t, u_char *, int);
int sshkey_from_blob(const u_char *, size_t, struct sshkey **);
int sshkey_fromb(struct sshbuf *, struct sshkey **);

View file

@ -0,0 +1,137 @@
commit 2c3ef499bfffce3cfd315edeebf202850ba4e00a
Author: Jakub Jelen <jjelen@redhat.com>
Date: Tue Apr 16 15:35:18 2019 +0200
Use the new OpenSSL KDF
diff --git a/configure.ac b/configure.ac
index 2a455e4e..e01c3d43 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2712,6 +2712,7 @@ if test "x$openssl" = "xyes" ; then
HMAC_CTX_init \
RSA_generate_key_ex \
RSA_get_default_method \
+ EVP_KDF_CTX_new_id \
])
# OpenSSL_add_all_algorithms may be a macro.
diff --git a/kex.c b/kex.c
index b6f041f4..1fbce2bb 100644
--- a/kex.c
+++ b/kex.c
@@ -38,6 +38,9 @@
#ifdef WITH_OPENSSL
#include <openssl/crypto.h>
#include <openssl/dh.h>
+# ifdef HAVE_EVP_KDF_CTX_NEW_ID
+# include <openssl/kdf.h>
+# endif
#endif
#include "ssh.h"
@@ -942,6 +945,95 @@ kex_choose_conf(struct ssh *ssh)
return r;
}
+#ifdef HAVE_EVP_KDF_CTX_NEW_ID
+static const EVP_MD *
+digest_to_md(int digest_type)
+{
+ switch (digest_type) {
+ case SSH_DIGEST_SHA1:
+ return EVP_sha1();
+ case SSH_DIGEST_SHA256:
+ return EVP_sha256();
+ case SSH_DIGEST_SHA384:
+ return EVP_sha384();
+ case SSH_DIGEST_SHA512:
+ return EVP_sha512();
+ }
+ return NULL;
+}
+
+static int
+derive_key(struct ssh *ssh, int id, u_int need, u_char *hash, u_int hashlen,
+ 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;
+ 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 = 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) {
+ 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,
+ kex->session_id, kex->session_id_len);
+ if (r != 1) {
+ r = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+ r = EVP_KDF_derive(ctx, key, key_len);
+ if (r != 1) {
+ r = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+#ifdef DEBUG_KEX
+ fprintf(stderr, "key '%c'== ", id);
+ dump_digest("key", key, key_len);
+#endif
+ *keyp = key;
+ key = NULL;
+ r = 0;
+
+out:
+ free (key);
+ EVP_KDF_CTX_free(ctx);
+ if (r < 0) {
+ return r;
+ }
+ return 0;
+}
+#else
static int
derive_key(struct ssh *ssh, int id, u_int need, u_char *hash, u_int hashlen,
const struct sshbuf *shared_secret, u_char **keyp)
@@ -1004,6 +1096,7 @@ derive_key(struct ssh *ssh, int id, u_int need, u_char *hash, u_int hashlen,
ssh_digest_free(hashctx);
return r;
}
+#endif /* HAVE_OPENSSL_EVP_KDF_CTX_NEW_ID */
#define NKEYS 6
int

View file

@ -0,0 +1,324 @@
From eb0d8e708a1f958aecd2d6e2ff2450af488d4c2a Mon Sep 17 00:00:00 2001
From: "djm@openbsd.org" <djm@openbsd.org>
Date: Mon, 15 Jul 2019 13:16:29 +0000
Subject: [PATCH] upstream: support PKCS8 as an optional format for storage of
private keys, enabled via "ssh-keygen -m PKCS8" on operations that save
private keys to disk.
The OpenSSH native key format remains the default, but PKCS8 is a
superior format to PEM if interoperability with non-OpenSSH software
is required, as it may use a less terrible KDF (IIRC PEM uses a single
round of MD5 as a KDF).
adapted from patch by Jakub Jelen via bz3013; ok markus
OpenBSD-Commit-ID: 027824e3bc0b1c243dc5188504526d73a55accb1
---
authfile.c | 6 ++--
ssh-keygen.1 | 9 +++---
ssh-keygen.c | 25 +++++++++--------
sshkey.c | 78 +++++++++++++++++++++++++++++++++++++---------------
sshkey.h | 11 ++++++--
5 files changed, 87 insertions(+), 42 deletions(-)
diff --git a/authfile.c b/authfile.c
index 2166c1689..851c1a8a1 100644
--- a/authfile.c
+++ b/authfile.c
@@ -74,7 +74,7 @@ sshkey_save_private_blob(struct sshbuf *keybuf, const char *filename)
int
sshkey_save_private(struct sshkey *key, const char *filename,
const char *passphrase, const char *comment,
- int force_new_format, const char *new_format_cipher, int new_format_rounds)
+ int format, const char *openssh_format_cipher, int openssh_format_rounds)
{
struct sshbuf *keyblob = NULL;
int r;
@@ -82,7 +82,7 @@ sshkey_save_private(struct sshkey *key, const char *filename,
if ((keyblob = sshbuf_new()) == NULL)
return SSH_ERR_ALLOC_FAIL;
if ((r = sshkey_private_to_fileblob(key, keyblob, passphrase, comment,
- force_new_format, new_format_cipher, new_format_rounds)) != 0)
+ format, openssh_format_cipher, openssh_format_rounds)) != 0)
goto out;
if ((r = sshkey_save_private_blob(keyblob, filename)) != 0)
goto out;
diff --git a/ssh-keygen.1 b/ssh-keygen.1
index f42127c60..8184a1797 100644
--- a/ssh-keygen.1
+++ b/ssh-keygen.1
@@ -419,11 +419,12 @@ The supported key formats are:
.Dq RFC4716
(RFC 4716/SSH2 public or private key),
.Dq PKCS8
-(PEM PKCS8 public key)
+(PKCS8 public or private key)
or
.Dq PEM
(PEM public key).
-The default conversion format is
+By default OpenSSH will write newly-generated private keys in its own
+format, but when converting public keys for export the default format is
.Dq RFC4716 .
Setting a format of
.Dq PEM
diff --git a/ssh-keygen.c b/ssh-keygen.c
index b019a02ff..5dcad1f61 100644
--- a/ssh-keygen.c
+++ b/ssh-keygen.c
@@ -147,11 +147,11 @@ static char *key_type_name = NULL;
/* Load key from this PKCS#11 provider */
static char *pkcs11provider = NULL;
-/* Use new OpenSSH private key format when writing SSH2 keys instead of PEM */
-static int use_new_format = 1;
+/* Format for writing private keys */
+static int private_key_format = SSHKEY_PRIVATE_OPENSSH;
/* Cipher for new-format private keys */
-static char *new_format_cipher = NULL;
+static char *openssh_format_cipher = NULL;
/*
* Number of KDF rounds to derive new format keys /
@@ -1048,7 +1048,8 @@ do_gen_all_hostkeys(struct passwd *pw)
snprintf(comment, sizeof comment, "%s@%s", pw->pw_name,
hostname);
if ((r = sshkey_save_private(private, prv_tmp, "",
- comment, use_new_format, new_format_cipher, rounds)) != 0) {
+ comment, private_key_format, openssh_format_cipher,
+ rounds)) != 0) {
error("Saving key \"%s\" failed: %s",
prv_tmp, ssh_err(r));
goto failnext;
@@ -1391,7 +1392,7 @@ do_change_passphrase(struct passwd *pw)
/* Save the file using the new passphrase. */
if ((r = sshkey_save_private(private, identity_file, passphrase1,
- comment, use_new_format, new_format_cipher, rounds)) != 0) {
+ comment, private_key_format, openssh_format_cipher, rounds)) != 0) {
error("Saving key \"%s\" failed: %s.",
identity_file, ssh_err(r));
explicit_bzero(passphrase1, strlen(passphrase1));
@@ -1480,7 +1481,7 @@ do_change_comment(struct passwd *pw, const char *identity_comment)
}
if (private->type != KEY_ED25519 && private->type != KEY_XMSS &&
- !use_new_format) {
+ private_key_format != SSHKEY_PRIVATE_OPENSSH) {
error("Comments are only supported for keys stored in "
"the new format (-o).");
explicit_bzero(passphrase, strlen(passphrase));
@@ -1514,7 +1515,8 @@ do_change_comment(struct passwd *pw, const char *identity_comment)
/* Save the file using the new passphrase. */
if ((r = sshkey_save_private(private, identity_file, passphrase,
- new_comment, use_new_format, new_format_cipher, rounds)) != 0) {
+ new_comment, private_key_format, openssh_format_cipher,
+ rounds)) != 0) {
error("Saving key \"%s\" failed: %s",
identity_file, ssh_err(r));
explicit_bzero(passphrase, strlen(passphrase));
@@ -2525,11 +2527,12 @@ main(int argc, char **argv)
}
if (strcasecmp(optarg, "PKCS8") == 0) {
convert_format = FMT_PKCS8;
+ private_key_format = SSHKEY_PRIVATE_PKCS8;
break;
}
if (strcasecmp(optarg, "PEM") == 0) {
convert_format = FMT_PEM;
- use_new_format = 0;
+ private_key_format = SSHKEY_PRIVATE_PEM;
break;
}
fatal("Unsupported conversion format \"%s\"", optarg);
@@ -2567,7 +2570,7 @@ main(int argc, char **argv)
add_cert_option(optarg);
break;
case 'Z':
- new_format_cipher = optarg;
+ openssh_format_cipher = optarg;
break;
case 'C':
identity_comment = optarg;
@@ -2912,7 +2915,7 @@ main(int argc, char **argv)
/* Save the key with the given passphrase and comment. */
if ((r = sshkey_save_private(private, identity_file, passphrase1,
- comment, use_new_format, new_format_cipher, rounds)) != 0) {
+ comment, private_key_format, openssh_format_cipher, rounds)) != 0) {
error("Saving key \"%s\" failed: %s",
identity_file, ssh_err(r));
explicit_bzero(passphrase1, strlen(passphrase1));
diff --git a/sshkey.c b/sshkey.c
index 6b5ff0485..a0cea9257 100644
--- a/sshkey.c
+++ b/sshkey.c
@@ -3975,10 +3975,10 @@ sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase,
#ifdef WITH_OPENSSL
-/* convert SSH v2 key in OpenSSL PEM format */
+/* convert SSH v2 key to PEM or PKCS#8 format */
static int
-sshkey_private_pem_to_blob(struct sshkey *key, struct sshbuf *blob,
- const char *_passphrase, const char *comment)
+sshkey_private_to_blob_pem_pkcs8(struct sshkey *key, struct sshbuf *blob,
+ int format, const char *_passphrase, const char *comment)
{
int success, r;
int blen, len = strlen(_passphrase);
@@ -3988,26 +3988,46 @@ sshkey_private_pem_to_blob(struct sshkey *key, struct sshbuf *buf,
const EVP_CIPHER *cipher = (len > 0) ? EVP_aes_128_cbc() : NULL;
char *bptr;
BIO *bio = NULL;
+ EVP_PKEY *pkey = NULL;
if (len > 0 && len <= 4)
return SSH_ERR_PASSPHRASE_TOO_SHORT;
- if ((bio = BIO_new(BIO_s_mem())) == NULL)
- return SSH_ERR_ALLOC_FAIL;
+ if ((bio = BIO_new(BIO_s_mem())) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+
+ if (format == SSHKEY_PRIVATE_PKCS8 && (pkey = EVP_PKEY_new()) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
switch (key->type) {
case KEY_DSA:
- success = PEM_write_bio_DSAPrivateKey(bio, key->dsa,
- cipher, passphrase, len, NULL, NULL);
+ if (format == SSHKEY_PRIVATE_PEM) {
+ success = PEM_write_bio_DSAPrivateKey(bio, key->dsa,
+ cipher, passphrase, len, NULL, NULL);
+ } else {
+ success = EVP_PKEY_set1_DSA(pkey, key->dsa);
+ }
break;
#ifdef OPENSSL_HAS_ECC
case KEY_ECDSA:
- success = PEM_write_bio_ECPrivateKey(bio, key->ecdsa,
- cipher, passphrase, len, NULL, NULL);
+ if (format == SSHKEY_PRIVATE_PEM) {
+ success = PEM_write_bio_ECPrivateKey(bio, key->ecdsa,
+ cipher, passphrase, len, NULL, NULL);
+ } else {
+ success = EVP_PKEY_set1_EC_KEY(pkey, key->ecdsa);
+ }
break;
#endif
case KEY_RSA:
- success = PEM_write_bio_RSAPrivateKey(bio, key->rsa,
- cipher, passphrase, len, NULL, NULL);
+ if (format == SSHKEY_PRIVATE_PEM) {
+ success = PEM_write_bio_RSAPrivateKey(bio, key->rsa,
+ cipher, passphrase, len, NULL, NULL);
+ } else {
+ success = EVP_PKEY_set1_RSA(pkey, key->rsa);
+ }
break;
default:
success = 0;
@@ -4023,6 +4040,13 @@ sshkey_private_pem_to_blob(struct sshkey *key, struct sshbuf *buf,
r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
+ if (format == SSHKEY_PRIVATE_PKCS8) {
+ if ((success = PEM_write_bio_PrivateKey(bio, pkey, cipher,
+ passphrase, len, NULL, NULL)) == 0) {
+ r = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+ }
if ((blen = BIO_get_mem_data(bio, &bptr)) <= 0) {
r = SSH_ERR_INTERNAL_ERROR;
goto out;
@@ -4035,6 +4059,7 @@ sshkey_private_pem_to_blob(struct sshkey *key, struct sshbuf *buf,
goto out;
r = 0;
out:
+ EVP_PKEY_free(pkey);
BIO_free(bio);
return r;
}
@@ -4046,29 +4071,38 @@ sshkey_private_pem_to_blob(struct sshkey *key, struct sshbuf *buf,
int
sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob,
const char *passphrase, const char *comment,
- int force_new_format, const char *new_format_cipher, int new_format_rounds)
+ int format, const char *openssh_format_cipher, int openssh_format_rounds)
{
switch (key->type) {
#ifdef WITH_OPENSSL
case KEY_DSA:
case KEY_ECDSA:
case KEY_RSA:
- if (force_new_format) {
- return sshkey_private_to_blob2(key, blob, passphrase,
- comment, new_format_cipher, new_format_rounds);
- }
- return sshkey_private_pem_to_blob(key, blob,
- passphrase, comment);
+ break; /* see below */
#endif /* WITH_OPENSSL */
case KEY_ED25519:
#ifdef WITH_XMSS
case KEY_XMSS:
#endif /* WITH_XMSS */
return sshkey_private_to_blob2(key, blob, passphrase,
- comment, new_format_cipher, new_format_rounds);
+ comment, openssh_format_cipher, openssh_format_rounds);
default:
return SSH_ERR_KEY_TYPE_UNKNOWN;
}
+
+#ifdef WITH_OPENSSL
+ switch (format) {
+ case SSHKEY_PRIVATE_OPENSSH:
+ return sshkey_private_to_blob2(key, blob, passphrase,
+ comment, openssh_format_cipher, openssh_format_rounds);
+ case SSHKEY_PRIVATE_PEM:
+ case SSHKEY_PRIVATE_PKCS8:
+ return sshkey_private_to_blob_pem_pkcs8(key, blob,
+ format, passphrase, comment);
+ default:
+ return SSH_ERR_INVALID_ARGUMENT;
+ }
+#endif /* WITH_OPENSSL */
}
diff --git a/sshkey.h b/sshkey.h
index 41d159a1b..d30a69cc9 100644
--- a/sshkey.h
+++ b/sshkey.h
@@ -88,6 +88,13 @@ enum sshkey_serialize_rep {
SSHKEY_SERIALIZE_INFO = 254,
};
+/* Private key disk formats */
+enum sshkey_private_format {
+ SSHKEY_PRIVATE_OPENSSH = 0,
+ SSHKEY_PRIVATE_PEM = 1,
+ SSHKEY_PRIVATE_PKCS8 = 2,
+};
+
/* key is stored in external hardware */
#define SSHKEY_FLAG_EXT 0x0001
@@ -221,7 +228,7 @@ int sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **keyp);
/* private key file format parsing and serialisation */
int sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob,
const char *passphrase, const char *comment,
- int force_new_format, const char *new_format_cipher, int new_format_rounds);
+ int format, const char *openssh_format_cipher, int openssh_format_rounds);
int sshkey_parse_private_fileblob(struct sshbuf *buffer,
const char *passphrase, struct sshkey **keyp, char **commentp);
int sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type,

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,44 @@
diff -up openssh-8.0p1/auth-pam.c.preserve-pam-errors openssh-8.0p1/auth-pam.c
--- openssh-8.0p1/auth-pam.c.preserve-pam-errors 2021-03-31 17:03:15.618592347 +0200
+++ openssh-8.0p1/auth-pam.c 2021-03-31 17:06:58.115220014 +0200
@@ -511,7 +511,11 @@ sshpam_thread(void *ctxtp)
goto auth_fail;
if (!do_pam_account()) {
- sshpam_err = PAM_ACCT_EXPIRED;
+ /* Preserve PAM_PERM_DENIED and PAM_USER_UNKNOWN.
+ * Backward compatibility for other errors. */
+ if (sshpam_err != PAM_PERM_DENIED
+ && sshpam_err != PAM_USER_UNKNOWN)
+ sshpam_err = PAM_ACCT_EXPIRED;
goto auth_fail;
}
if (sshpam_authctxt->force_pwchange) {
@@ -568,8 +572,10 @@ sshpam_thread(void *ctxtp)
pam_strerror(sshpam_handle, sshpam_err))) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
/* XXX - can't do much about an error here */
- if (sshpam_err == PAM_ACCT_EXPIRED)
- ssh_msg_send(ctxt->pam_csock, PAM_ACCT_EXPIRED, buffer);
+ if (sshpam_err == PAM_PERM_DENIED
+ || sshpam_err == PAM_USER_UNKNOWN
+ || sshpam_err == PAM_ACCT_EXPIRED)
+ ssh_msg_send(ctxt->pam_csock, sshpam_err, buffer);
else if (sshpam_maxtries_reached)
ssh_msg_send(ctxt->pam_csock, PAM_MAXTRIES, buffer);
else
@@ -856,10 +862,12 @@ sshpam_query(void *ctx, char **name, cha
plen++;
free(msg);
break;
+ case PAM_USER_UNKNOWN:
+ case PAM_PERM_DENIED:
case PAM_ACCT_EXPIRED:
+ sshpam_account_status = 0;
+ /* FALLTHROUGH */
case PAM_MAXTRIES:
- if (type == PAM_ACCT_EXPIRED)
- sshpam_account_status = 0;
if (type == PAM_MAXTRIES)
sshpam_set_maxtries_reached(1);
/* FALLTHROUGH */

View file

@ -0,0 +1,33 @@
From de1f3564cd85915b3002859873a37cb8d31ac9ce Mon Sep 17 00:00:00 2001
From: "dtucker@openbsd.org" <dtucker@openbsd.org>
Date: Tue, 18 Feb 2020 08:49:49 +0000
Subject: [PATCH] upstream: Detect and prevent simple configuration loops when
using
ProxyJump. bz#3057, ok djm@
OpenBSD-Commit-ID: 077d21c564c886c98309d871ed6f8ef267b9f037
---
ssh.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/ssh.c b/ssh.c
index 15aee569e..a983a108b 100644
--- a/ssh.c
+++ b/ssh.c
@@ -1208,6 +1208,14 @@ main(int ac, char **av)
if (options.jump_host != NULL) {
char port_s[8];
const char *sshbin = argv0;
+ int port = options.port, jumpport = options.jump_port;
+
+ if (port <= 0)
+ port = default_ssh_port();
+ if (jumpport <= 0)
+ jumpport = default_ssh_port();
+ if (strcmp(options.jump_host, host) == 0 && port == jumpport)
+ fatal("jumphost loop via %s", options.jump_host);
/*
* Try to use SSH indicated by argv[0], but fall back to

View file

@ -0,0 +1,44 @@
commit 5481d0b4036b33b92c372ee36258ed11bff57d5d
Author: Jakub Jelen <jjelen@redhat.com>
Date: Thu Feb 27 10:07:33 2020 +0100
Mark the RDomain configuration option unsupported on non-openbsd builds
diff --git a/servconf.c b/servconf.c
index db80e943..153d2525 100644
--- a/servconf.c
+++ b/servconf.c
@@ -698,7 +698,11 @@ static struct {
{ "fingerprinthash", sFingerprintHash, SSHCFG_GLOBAL },
{ "disableforwarding", sDisableForwarding, SSHCFG_ALL },
{ "exposeauthinfo", sExposeAuthInfo, SSHCFG_ALL },
+#if defined(__OpenBSD__)
{ "rdomain", sRDomain, SSHCFG_ALL },
+#else
+ { "rdomain", sUnsupported, SSHCFG_ALL },
+#endif
{ "casignaturealgorithms", sCASignatureAlgorithms, SSHCFG_ALL },
{ NULL, sBadOption, 0 }
};
@@ -2841,7 +2845,9 @@ dump_config(ServerOptions *o)
o->hostkeyalgorithms : KEX_DEFAULT_PK_ALG);
dump_cfg_string(sPubkeyAcceptedKeyTypes, o->pubkey_key_types ?
o->pubkey_key_types : KEX_DEFAULT_PK_ALG);
+#if defined(__OpenBSD__)
dump_cfg_string(sRDomain, o->routing_domain);
+#endif
/* string arguments requiring a lookup */
dump_cfg_string(sLogLevel, log_level_name(o->log_level));
diff --git a/sshd_config.5 b/sshd_config.5
index 5dca8981..766e9b90 100644
--- a/sshd_config.5
+++ b/sshd_config.5
@@ -1542,6 +1542,7 @@ will be bound to this
If the routing domain is set to
.Cm \&%D ,
then the domain in which the incoming connection was received will be applied.
+This feature is available on OpenBSD only.
.It Cm SetEnv
Specifies one or more environment variables to set in child sessions started
by

View file

@ -0,0 +1,311 @@
diff -up openssh-8.0p1/channels.c.restore-nonblock openssh-8.0p1/channels.c
--- openssh-8.0p1/channels.c.restore-nonblock 2021-06-21 10:44:26.380559612 +0200
+++ openssh-8.0p1/channels.c 2021-06-21 10:48:47.754579151 +0200
@@ -333,7 +333,27 @@ channel_register_fds(struct ssh *ssh, Ch
#endif
/* enable nonblocking mode */
- if (nonblock) {
+ c->restore_block = 0;
+ if (nonblock == CHANNEL_NONBLOCK_STDIO) {
+ /*
+ * Special handling for stdio file descriptors: do not set
+ * non-blocking mode if they are TTYs. Otherwise prepare to
+ * restore their blocking state on exit to avoid interfering
+ * with other programs that follow.
+ */
+ if (rfd != -1 && !isatty(rfd) && fcntl(rfd, F_GETFL) == 0) {
+ c->restore_block |= CHANNEL_RESTORE_RFD;
+ set_nonblock(rfd);
+ }
+ if (wfd != -1 && !isatty(wfd) && fcntl(wfd, F_GETFL) == 0) {
+ c->restore_block |= CHANNEL_RESTORE_WFD;
+ set_nonblock(wfd);
+ }
+ if (efd != -1 && !isatty(efd) && fcntl(efd, F_GETFL) == 0) {
+ c->restore_block |= CHANNEL_RESTORE_EFD;
+ set_nonblock(efd);
+ }
+ } else if (nonblock) {
if (rfd != -1)
set_nonblock(rfd);
if (wfd != -1)
@@ -422,17 +442,23 @@ channel_find_maxfd(struct ssh_channels *
}
int
-channel_close_fd(struct ssh *ssh, int *fdp)
+channel_close_fd(struct ssh *ssh, Channel *c, int *fdp)
{
struct ssh_channels *sc = ssh->chanctxt;
- int ret = 0, fd = *fdp;
+ int ret, fd = *fdp;
- if (fd != -1) {
- ret = close(fd);
- *fdp = -1;
- if (fd == sc->channel_max_fd)
- channel_find_maxfd(sc);
- }
+ if (fd == -1)
+ return 0;
+
+ if ((*fdp == c->rfd && (c->restore_block & CHANNEL_RESTORE_RFD) != 0) ||
+ (*fdp == c->wfd && (c->restore_block & CHANNEL_RESTORE_WFD) != 0) ||
+ (*fdp == c->efd && (c->restore_block & CHANNEL_RESTORE_EFD) != 0))
+ (void)fcntl(*fdp, F_SETFL, 0); /* restore blocking */
+
+ ret = close(fd);
+ *fdp = -1;
+ if (fd == sc->channel_max_fd)
+ channel_find_maxfd(sc);
return ret;
}
@@ -442,13 +468,13 @@ channel_close_fds(struct ssh *ssh, Chann
{
int sock = c->sock, rfd = c->rfd, wfd = c->wfd, efd = c->efd;
- channel_close_fd(ssh, &c->sock);
+ channel_close_fd(ssh, c, &c->sock);
if (rfd != sock)
- channel_close_fd(ssh, &c->rfd);
+ channel_close_fd(ssh, c, &c->rfd);
if (wfd != sock && wfd != rfd)
- channel_close_fd(ssh, &c->wfd);
+ channel_close_fd(ssh, c, &c->wfd);
if (efd != sock && efd != rfd && efd != wfd)
- channel_close_fd(ssh, &c->efd);
+ channel_close_fd(ssh, c, &c->efd);
}
static void
@@ -681,7 +707,7 @@ channel_stop_listening(struct ssh *ssh)
case SSH_CHANNEL_X11_LISTENER:
case SSH_CHANNEL_UNIX_LISTENER:
case SSH_CHANNEL_RUNIX_LISTENER:
- channel_close_fd(ssh, &c->sock);
+ channel_close_fd(ssh, c, &c->sock);
channel_free(ssh, c);
break;
}
@@ -1487,7 +1513,8 @@ channel_decode_socks5(Channel *c, struct
Channel *
channel_connect_stdio_fwd(struct ssh *ssh,
- const char *host_to_connect, u_short port_to_connect, int in, int out)
+ const char *host_to_connect, u_short port_to_connect,
+ int in, int out, int nonblock)
{
Channel *c;
@@ -1495,7 +1522,7 @@ channel_connect_stdio_fwd(struct ssh *ss
c = channel_new(ssh, "stdio-forward", SSH_CHANNEL_OPENING, in, out,
-1, CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
- 0, "stdio-forward", /*nonblock*/0);
+ 0, "stdio-forward", nonblock);
c->path = xstrdup(host_to_connect);
c->host_port = port_to_connect;
@@ -1650,7 +1677,7 @@ channel_post_x11_listener(struct ssh *ss
if (c->single_connection) {
oerrno = errno;
debug2("single_connection: closing X11 listener.");
- channel_close_fd(ssh, &c->sock);
+ channel_close_fd(ssh, c, &c->sock);
chan_mark_dead(ssh, c);
errno = oerrno;
}
@@ -2087,7 +2114,7 @@ channel_handle_efd_write(struct ssh *ssh
return 1;
if (len <= 0) {
debug2("channel %d: closing write-efd %d", c->self, c->efd);
- channel_close_fd(ssh, &c->efd);
+ channel_close_fd(ssh, c, &c->efd);
} else {
if ((r = sshbuf_consume(c->extended, len)) != 0) {
fatal("%s: channel %d: consume: %s",
@@ -2119,7 +2146,7 @@ channel_handle_efd_read(struct ssh *ssh,
if (len <= 0) {
debug2("channel %d: closing read-efd %d",
c->self, c->efd);
- channel_close_fd(ssh, &c->efd);
+ channel_close_fd(ssh, c, &c->efd);
} else {
if (c->extended_usage == CHAN_EXTENDED_IGNORE) {
debug3("channel %d: discard efd",
diff -up openssh-8.0p1/channels.h.restore-nonblock openssh-8.0p1/channels.h
--- openssh-8.0p1/channels.h.restore-nonblock 2021-06-21 10:44:26.380559612 +0200
+++ openssh-8.0p1/channels.h 2021-06-21 10:44:26.387559665 +0200
@@ -63,6 +63,16 @@
#define CHANNEL_CANCEL_PORT_STATIC -1
+/* nonblocking flags for channel_new */
+#define CHANNEL_NONBLOCK_LEAVE 0 /* don't modify non-blocking state */
+#define CHANNEL_NONBLOCK_SET 1 /* set non-blocking state */
+#define CHANNEL_NONBLOCK_STDIO 2 /* set non-blocking and restore on close */
+
+/* c->restore_block mask flags */
+#define CHANNEL_RESTORE_RFD 0x01
+#define CHANNEL_RESTORE_WFD 0x02
+#define CHANNEL_RESTORE_EFD 0x04
+
/* TCP forwarding */
#define FORWARD_DENY 0
#define FORWARD_REMOTE (1)
@@ -131,6 +141,7 @@ struct Channel {
* to a matching pre-select handler.
* this way post-select handlers are not
* accidentally called if a FD gets reused */
+ int restore_block; /* fd mask to restore blocking status */
struct sshbuf *input; /* data read from socket, to be sent over
* encrypted connection */
struct sshbuf *output; /* data received over encrypted connection for
@@ -258,7 +269,7 @@ void channel_register_filter(struct ssh
void channel_register_status_confirm(struct ssh *, int,
channel_confirm_cb *, channel_confirm_abandon_cb *, void *);
void channel_cancel_cleanup(struct ssh *, int);
-int channel_close_fd(struct ssh *, int *);
+int channel_close_fd(struct ssh *, Channel *, int *);
void channel_send_window_changes(struct ssh *);
/* mux proxy support */
@@ -305,7 +316,7 @@ Channel *channel_connect_to_port(struct
char *, char *, int *, const char **);
Channel *channel_connect_to_path(struct ssh *, const char *, char *, char *);
Channel *channel_connect_stdio_fwd(struct ssh *, const char*,
- u_short, int, int);
+ u_short, int, int, int);
Channel *channel_connect_by_listen_address(struct ssh *, const char *,
u_short, char *, char *);
Channel *channel_connect_by_listen_path(struct ssh *, const char *,
diff -up openssh-8.0p1/clientloop.c.restore-nonblock openssh-8.0p1/clientloop.c
--- openssh-8.0p1/clientloop.c.restore-nonblock 2021-06-21 10:44:26.290558923 +0200
+++ openssh-8.0p1/clientloop.c 2021-06-21 10:44:26.387559665 +0200
@@ -1436,14 +1436,6 @@ client_loop(struct ssh *ssh, int have_pt
if (have_pty)
leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
- /* restore blocking io */
- if (!isatty(fileno(stdin)))
- unset_nonblock(fileno(stdin));
- if (!isatty(fileno(stdout)))
- unset_nonblock(fileno(stdout));
- if (!isatty(fileno(stderr)))
- unset_nonblock(fileno(stderr));
-
/*
* If there was no shell or command requested, there will be no remote
* exit status to be returned. In that case, clear error code if the
diff -up openssh-8.0p1/mux.c.restore-nonblock openssh-8.0p1/mux.c
--- openssh-8.0p1/mux.c.restore-nonblock 2019-04-18 00:52:57.000000000 +0200
+++ openssh-8.0p1/mux.c 2021-06-21 10:50:51.007537336 +0200
@@ -454,14 +454,6 @@ mux_master_process_new_session(struct ss
if (cctx->want_tty && tcgetattr(new_fd[0], &cctx->tio) == -1)
error("%s: tcgetattr: %s", __func__, strerror(errno));
- /* enable nonblocking unless tty */
- if (!isatty(new_fd[0]))
- set_nonblock(new_fd[0]);
- if (!isatty(new_fd[1]))
- set_nonblock(new_fd[1]);
- if (!isatty(new_fd[2]))
- set_nonblock(new_fd[2]);
-
window = CHAN_SES_WINDOW_DEFAULT;
packetmax = CHAN_SES_PACKET_DEFAULT;
if (cctx->want_tty) {
@@ -471,7 +463,7 @@ mux_master_process_new_session(struct ss
nc = channel_new(ssh, "session", SSH_CHANNEL_OPENING,
new_fd[0], new_fd[1], new_fd[2], window, packetmax,
- CHAN_EXTENDED_WRITE, "client-session", /*nonblock*/0);
+ CHAN_EXTENDED_WRITE, "client-session", CHANNEL_NONBLOCK_STDIO);
nc->ctl_chan = c->self; /* link session -> control channel */
c->remote_id = nc->self; /* link control -> session channel */
@@ -1033,13 +1025,8 @@ mux_master_process_stdio_fwd(struct ssh
}
}
- /* enable nonblocking unless tty */
- if (!isatty(new_fd[0]))
- set_nonblock(new_fd[0]);
- if (!isatty(new_fd[1]))
- set_nonblock(new_fd[1]);
-
- nc = channel_connect_stdio_fwd(ssh, chost, cport, new_fd[0], new_fd[1]);
+ nc = channel_connect_stdio_fwd(ssh, chost, cport, new_fd[0], new_fd[1],
+ CHANNEL_NONBLOCK_STDIO);
free(chost);
nc->ctl_chan = c->self; /* link session -> control channel */
diff -up openssh-8.0p1/nchan.c.restore-nonblock openssh-8.0p1/nchan.c
--- openssh-8.0p1/nchan.c.restore-nonblock 2021-06-21 10:44:26.388559673 +0200
+++ openssh-8.0p1/nchan.c 2021-06-21 10:52:42.685405537 +0200
@@ -387,7 +387,7 @@ chan_shutdown_write(struct ssh *ssh, Cha
strerror(errno));
}
} else {
- if (channel_close_fd(ssh, &c->wfd) < 0) {
+ if (channel_close_fd(ssh, c, &c->wfd) < 0) {
logit("channel %d: %s: close() failed for "
"fd %d [i%d o%d]: %.100s",
c->self, __func__, c->wfd, c->istate, c->ostate,
@@ -417,7 +417,7 @@ chan_shutdown_read(struct ssh *ssh, Chan
strerror(errno));
}
} else {
- if (channel_close_fd(ssh, &c->rfd) < 0) {
+ if (channel_close_fd(ssh, c, &c->rfd) < 0) {
logit("channel %d: %s: close() failed for "
"fd %d [i%d o%d]: %.100s",
c->self, __func__, c->rfd, c->istate, c->ostate,
@@ -437,7 +437,7 @@ chan_shutdown_extended_read(struct ssh *
debug2("channel %d: %s (i%d o%d sock %d wfd %d efd %d [%s])",
c->self, __func__, c->istate, c->ostate, c->sock, c->rfd, c->efd,
channel_format_extended_usage(c));
- if (channel_close_fd(ssh, &c->efd) < 0) {
+ if (channel_close_fd(ssh, c, &c->efd) < 0) {
logit("channel %d: %s: close() failed for "
"extended fd %d [i%d o%d]: %.100s",
c->self, __func__, c->efd, c->istate, c->ostate,
diff -up openssh-8.0p1/ssh.c.restore-nonblock openssh-8.0p1/ssh.c
--- openssh-8.0p1/ssh.c.restore-nonblock 2021-06-21 10:44:26.389559681 +0200
+++ openssh-8.0p1/ssh.c 2021-06-21 10:54:47.651377045 +0200
@@ -1709,7 +1709,8 @@ ssh_init_stdio_forwarding(struct ssh *ss
(out = dup(STDOUT_FILENO)) < 0)
fatal("channel_connect_stdio_fwd: dup() in/out failed");
if ((c = channel_connect_stdio_fwd(ssh, options.stdio_forward_host,
- options.stdio_forward_port, in, out)) == NULL)
+ options.stdio_forward_port, in, out,
+ CHANNEL_NONBLOCK_STDIO)) == NULL)
fatal("%s: channel_connect_stdio_fwd failed", __func__);
channel_register_cleanup(ssh, c->self, client_cleanup_stdio_fwd, 0);
channel_register_open_confirm(ssh, c->self, ssh_stdio_confirm, NULL);
@@ -1862,14 +1863,6 @@ ssh_session2_open(struct ssh *ssh)
if (in < 0 || out < 0 || err < 0)
fatal("dup() in/out/err failed");
- /* enable nonblocking unless tty */
- if (!isatty(in))
- set_nonblock(in);
- if (!isatty(out))
- set_nonblock(out);
- if (!isatty(err))
- set_nonblock(err);
-
window = CHAN_SES_WINDOW_DEFAULT;
packetmax = CHAN_SES_PACKET_DEFAULT;
if (tty_flag) {
@@ -1879,7 +1872,7 @@ ssh_session2_open(struct ssh *ssh)
c = channel_new(ssh,
"session", SSH_CHANNEL_OPENING, in, out, err,
window, packetmax, CHAN_EXTENDED_WRITE,
- "client-session", /*nonblock*/0);
+ "client-session", CHANNEL_NONBLOCK_STDIO);
debug3("%s: channel_new: %d", __func__, c->self);

View file

@ -0,0 +1,61 @@
diff --git a/regress/scp-ssh-wrapper.sh b/regress/scp-ssh-wrapper.sh
index 59f1ff63..dd48a482 100644
--- a/regress/scp-ssh-wrapper.sh
+++ b/regress/scp-ssh-wrapper.sh
@@ -51,6 +51,18 @@ badserver_4)
echo "C755 2 file"
echo "X"
;;
+badserver_5)
+ echo "D0555 0 "
+ echo "X"
+ ;;
+badserver_6)
+ echo "D0555 0 ."
+ echo "X"
+ ;;
+badserver_7)
+ echo "C0755 2 extrafile"
+ echo "X"
+ ;;
*)
set -- $arg
shift
diff --git a/regress/scp.sh b/regress/scp.sh
index 57cc7706..104c89e1 100644
--- a/regress/scp.sh
+++ b/regress/scp.sh
@@ -25,6 +25,7 @@ export SCP # used in scp-ssh-wrapper.scp
scpclean() {
rm -rf ${COPY} ${COPY2} ${DIR} ${DIR2}
mkdir ${DIR} ${DIR2}
+ chmod 755 ${DIR} ${DIR2}
}
verbose "$tid: simple copy local file to local file"
@@ -101,7 +102,7 @@ if [ ! -z "$SUDO" ]; then
$SUDO rm ${DIR2}/copy
fi
-for i in 0 1 2 3 4; do
+for i in 0 1 2 3 4 5 6 7; do
verbose "$tid: disallow bad server #$i"
SCPTESTMODE=badserver_$i
export DIR SCPTESTMODE
@@ -113,6 +114,15 @@ for i in 0 1 2 3 4; do
scpclean
$SCP -r $scpopts somehost:${DATA} ${DIR2} >/dev/null 2>/dev/null
[ -d ${DIR}/dotpathdir ] && fail "allows dir creation outside of subdir"
+
+ scpclean
+ $SCP -pr $scpopts somehost:${DATA} ${DIR2} >/dev/null 2>/dev/null
+ [ ! -w ${DIR2} ] && fail "allows target root attribute change"
+
+ scpclean
+ $SCP $scpopts somehost:${DATA} ${DIR2} >/dev/null 2>/dev/null
+ [ -e ${DIR2}/extrafile ] && fail "allows extranous object creation"
+ rm -f ${DIR2}/extrafile
done
verbose "$tid: detect non-directory target"

View file

@ -0,0 +1,273 @@
diff --color -ruN a/Makefile.in b/Makefile.in
--- a/Makefile.in 2022-06-23 11:31:10.168186838 +0200
+++ b/Makefile.in 2022-06-23 11:32:19.146513347 +0200
@@ -125,7 +125,7 @@
monitor.o monitor_wrap.o auth-krb5.o \
auth2-gss.o gss-serv.o gss-serv-krb5.o kexgsss.o \
loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \
- sftp-server.o sftp-common.o \
+ sftp-server.o sftp-common.o sftp-realpath.o \
sandbox-null.o sandbox-rlimit.o sandbox-systrace.o sandbox-darwin.o \
sandbox-seccomp-filter.o sandbox-capsicum.o sandbox-pledge.o \
sandbox-solaris.o uidswap.o
@@ -217,8 +217,8 @@
ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keyscan.o
$(LD) -o $@ ssh-keyscan.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS)
-sftp-server$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-common.o sftp-server.o sftp-server-main.o
- $(LD) -o $@ sftp-server.o sftp-common.o sftp-server-main.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
+sftp-server$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-common.o sftp-realpath.o sftp-server.o sftp-server-main.o
+ $(LD) -o $@ sftp-server.o sftp-common.o sftp-realpath.o sftp-server-main.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
sftp$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-client.o sftp-common.o sftp-glob.o progressmeter.o
$(LD) -o $@ progressmeter.o sftp.o sftp-client.o sftp-common.o sftp-glob.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) $(LIBEDIT)
diff --color -ruN a/sftp-realpath.c b/sftp-realpath.c
--- a/sftp-realpath.c 1970-01-01 01:00:00.000000000 +0100
+++ b/sftp-realpath.c 2022-06-23 11:35:33.193244873 +0200
@@ -0,0 +1,225 @@
+/* $OpenBSD: sftp-realpath.c,v 1.2 2021/09/02 21:03:54 deraadt Exp $ */
+/*
+ * Copyright (c) 2003 Constantin S. Svintsoff <kostik@iclub.nsu.ru>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The names of the authors may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <unistd.h>
+#include <limits.h>
+
+#ifndef SYMLOOP_MAX
+# define SYMLOOP_MAX 32
+#endif
+
+/* XXX rewrite sftp-server to use POSIX realpath and remove this hack */
+
+char *sftp_realpath(const char *path, char *resolved);
+
+/*
+ * char *realpath(const char *path, char resolved[PATH_MAX]);
+ *
+ * Find the real name of path, by removing all ".", ".." and symlink
+ * components. Returns (resolved) on success, or (NULL) on failure,
+ * in which case the path which caused trouble is left in (resolved).
+ */
+char *
+sftp_realpath(const char *path, char *resolved)
+{
+ struct stat sb;
+ char *p, *q, *s;
+ size_t left_len, resolved_len;
+ unsigned symlinks;
+ int serrno, slen, mem_allocated;
+ char left[PATH_MAX], next_token[PATH_MAX], symlink[PATH_MAX];
+
+ if (path[0] == '\0') {
+ errno = ENOENT;
+ return (NULL);
+ }
+
+ serrno = errno;
+
+ if (resolved == NULL) {
+ resolved = malloc(PATH_MAX);
+ if (resolved == NULL)
+ return (NULL);
+ mem_allocated = 1;
+ } else
+ mem_allocated = 0;
+
+ symlinks = 0;
+ if (path[0] == '/') {
+ resolved[0] = '/';
+ resolved[1] = '\0';
+ if (path[1] == '\0')
+ return (resolved);
+ resolved_len = 1;
+ left_len = strlcpy(left, path + 1, sizeof(left));
+ } else {
+ if (getcwd(resolved, PATH_MAX) == NULL) {
+ if (mem_allocated)
+ free(resolved);
+ else
+ strlcpy(resolved, ".", PATH_MAX);
+ return (NULL);
+ }
+ resolved_len = strlen(resolved);
+ left_len = strlcpy(left, path, sizeof(left));
+ }
+ if (left_len >= sizeof(left) || resolved_len >= PATH_MAX) {
+ errno = ENAMETOOLONG;
+ goto err;
+ }
+
+ /*
+ * Iterate over path components in `left'.
+ */
+ while (left_len != 0) {
+ /*
+ * Extract the next path component and adjust `left'
+ * and its length.
+ */
+ p = strchr(left, '/');
+ s = p ? p : left + left_len;
+ if (s - left >= (ptrdiff_t)sizeof(next_token)) {
+ errno = ENAMETOOLONG;
+ goto err;
+ }
+ memcpy(next_token, left, s - left);
+ next_token[s - left] = '\0';
+ left_len -= s - left;
+ if (p != NULL)
+ memmove(left, s + 1, left_len + 1);
+ if (resolved[resolved_len - 1] != '/') {
+ if (resolved_len + 1 >= PATH_MAX) {
+ errno = ENAMETOOLONG;
+ goto err;
+ }
+ resolved[resolved_len++] = '/';
+ resolved[resolved_len] = '\0';
+ }
+ if (next_token[0] == '\0')
+ continue;
+ else if (strcmp(next_token, ".") == 0)
+ continue;
+ else if (strcmp(next_token, "..") == 0) {
+ /*
+ * Strip the last path component except when we have
+ * single "/"
+ */
+ if (resolved_len > 1) {
+ resolved[resolved_len - 1] = '\0';
+ q = strrchr(resolved, '/') + 1;
+ *q = '\0';
+ resolved_len = q - resolved;
+ }
+ continue;
+ }
+
+ /*
+ * Append the next path component and lstat() it. If
+ * lstat() fails we still can return successfully if
+ * there are no more path components left.
+ */
+ resolved_len = strlcat(resolved, next_token, PATH_MAX);
+ if (resolved_len >= PATH_MAX) {
+ errno = ENAMETOOLONG;
+ goto err;
+ }
+ if (lstat(resolved, &sb) != 0) {
+ if (errno == ENOENT && p == NULL) {
+ errno = serrno;
+ return (resolved);
+ }
+ goto err;
+ }
+ if (S_ISLNK(sb.st_mode)) {
+ if (symlinks++ > SYMLOOP_MAX) {
+ errno = ELOOP;
+ goto err;
+ }
+ slen = readlink(resolved, symlink, sizeof(symlink) - 1);
+ if (slen < 0)
+ goto err;
+ symlink[slen] = '\0';
+ if (symlink[0] == '/') {
+ resolved[1] = 0;
+ resolved_len = 1;
+ } else if (resolved_len > 1) {
+ /* Strip the last path component. */
+ resolved[resolved_len - 1] = '\0';
+ q = strrchr(resolved, '/') + 1;
+ *q = '\0';
+ resolved_len = q - resolved;
+ }
+
+ /*
+ * If there are any path components left, then
+ * append them to symlink. The result is placed
+ * in `left'.
+ */
+ if (p != NULL) {
+ if (symlink[slen - 1] != '/') {
+ if (slen + 1 >=
+ (ptrdiff_t)sizeof(symlink)) {
+ errno = ENAMETOOLONG;
+ goto err;
+ }
+ symlink[slen] = '/';
+ symlink[slen + 1] = 0;
+ }
+ left_len = strlcat(symlink, left, sizeof(symlink));
+ if (left_len >= sizeof(symlink)) {
+ errno = ENAMETOOLONG;
+ goto err;
+ }
+ }
+ left_len = strlcpy(left, symlink, sizeof(left));
+ }
+ }
+
+ /*
+ * Remove trailing slash except when the resolved pathname
+ * is a single "/".
+ */
+ if (resolved_len > 1 && resolved[resolved_len - 1] == '/')
+ resolved[resolved_len - 1] = '\0';
+ return (resolved);
+
+err:
+ if (mem_allocated)
+ free(resolved);
+ return (NULL);
+}
diff --color -ruN a/sftp-server.c b/sftp-server.c
--- a/sftp-server.c 2022-06-23 11:31:10.147186434 +0200
+++ b/sftp-server.c 2022-06-23 11:32:19.147513366 +0200
@@ -51,6 +51,8 @@
#include "sftp.h"
#include "sftp-common.h"
+char *sftp_realpath(const char *, char *); /* sftp-realpath.c */
+
/* Our verbosity */
static LogLevel log_level = SYSLOG_LEVEL_ERROR;
@@ -1185,7 +1187,7 @@
}
debug3("request %u: realpath", id);
verbose("realpath \"%s\"", path);
- if (realpath(path, resolvedname) == NULL) {
+ if (sftp_realpath(path, resolvedname) == NULL) {
send_status(id, errno_to_portable(errno));
} else {
Stat s;

View file

@ -0,0 +1,16 @@
diff -up openssh-8.0p1/sftp.c.original openssh-8.0p1/sftp.c
--- openssh-8.0p1/sftp.c.original 2020-12-22 17:05:02.105698989 +0900
+++ openssh-8.0p1/sftp.c 2020-12-22 17:05:42.922035780 +0900
@@ -937,7 +937,11 @@ sglob_comp(const void *aa, const void *b
return (rmul * strcmp(ap, bp));
else if (sort_flag & LS_TIME_SORT) {
#if defined(HAVE_STRUCT_STAT_ST_MTIM)
- return (rmul * timespeccmp(&as->st_mtim, &bs->st_mtim, <));
+ if (timespeccmp(&as->st_mtim, &bs->st_mtim, <)){
+ return rmul;
+ } else {
+ return -rmul;
+ }
#elif defined(HAVE_STRUCT_STAT_ST_MTIME)
return (rmul * NCMP(as->st_mtime, bs->st_mtime));
#else

View file

@ -0,0 +1,97 @@
diff --git a/servconf.c b/servconf.c
index ffac5d2c..340045b2 100644
--- a/servconf.c
+++ b/servconf.c
@@ -1042,7 +1042,7 @@ match_cfg_line(char **condition, int line, struct connection_info *ci)
return -1;
}
if (strcasecmp(attrib, "user") == 0) {
- if (ci == NULL) {
+ if (ci == NULL || (ci->test && ci->user == NULL)) {
result = 0;
continue;
}
@@ -1054,7 +1054,7 @@ match_cfg_line(char **condition, int line, struct connection_info *ci)
debug("user %.100s matched 'User %.100s' at "
"line %d", ci->user, arg, line);
} else if (strcasecmp(attrib, "group") == 0) {
- if (ci == NULL) {
+ if (ci == NULL || (ci->test && ci->user == NULL)) {
result = 0;
continue;
}
@@ -1067,7 +1067,7 @@ match_cfg_line(char **condition, int line, struct connection_info *ci)
result = 0;
}
} else if (strcasecmp(attrib, "host") == 0) {
- if (ci == NULL) {
+ if (ci == NULL || (ci->test && ci->host == NULL)) {
result = 0;
continue;
}
@@ -1079,7 +1079,7 @@ match_cfg_line(char **condition, int line, struct connection_info *ci)
debug("connection from %.100s matched 'Host "
"%.100s' at line %d", ci->host, arg, line);
} else if (strcasecmp(attrib, "address") == 0) {
- if (ci == NULL) {
+ if (ci == NULL || (ci->test && ci->address == NULL)) {
result = 0;
continue;
}
@@ -1098,7 +1098,7 @@ match_cfg_line(char **condition, int line, struct connection_info *ci)
return -1;
}
} else if (strcasecmp(attrib, "localaddress") == 0){
- if (ci == NULL) {
+ if (ci == NULL || (ci->test && ci->laddress == NULL)) {
result = 0;
continue;
}
@@ -1124,7 +1124,7 @@ match_cfg_line(char **condition, int line, struct connection_info *ci)
arg);
return -1;
}
- if (ci == NULL) {
+ if (ci == NULL || (ci->test && ci->lport == -1)) {
result = 0;
continue;
}
@@ -1138,10 +1138,12 @@ match_cfg_line(char **condition, int line, struct connection_info *ci)
else
result = 0;
} else if (strcasecmp(attrib, "rdomain") == 0) {
- if (ci == NULL || ci->rdomain == NULL) {
+ if (ci == NULL || (ci->test && ci->rdomain == NULL)) {
result = 0;
continue;
}
+ if (ci->rdomain == NULL)
+ match_test_missing_fatal("RDomain", "rdomain");
if (match_pattern_list(ci->rdomain, arg, 0) != 1)
result = 0;
else
diff --git a/servconf.h b/servconf.h
index 54e0a8d8..5483da05 100644
--- a/servconf.h
+++ b/servconf.h
@@ -221,6 +221,8 @@ struct connection_info {
const char *laddress; /* local address */
int lport; /* local port */
const char *rdomain; /* routing domain if available */
+ int test; /* test mode, allow some attributes to be
+ * unspecified */
};
diff --git a/sshd.c b/sshd.c
index cbd3bce9..1fcde502 100644
--- a/sshd.c
+++ b/sshd.c
@@ -1843,6 +1843,7 @@ main(int ac, char **av)
*/
if (connection_info == NULL)
connection_info = get_connection_info(ssh, 0, 0);
+ connection_info->test = 1;
parse_server_match_config(&options, connection_info);
dump_config(&options);
}

View file

@ -0,0 +1,805 @@
diff -up openssh-8.0p1/auth.c.sshdinclude openssh-8.0p1/auth.c
--- openssh-8.0p1/auth.c.sshdinclude 2021-10-20 15:18:49.740331098 +0200
+++ openssh-8.0p1/auth.c 2021-10-20 15:19:41.324781344 +0200
@@ -80,6 +80,7 @@
/* import */
extern ServerOptions options;
+extern struct include_list includes;
extern int use_privsep;
extern struct sshbuf *loginmsg;
extern struct passwd *privsep_pw;
@@ -573,7 +574,7 @@ getpwnamallow(struct ssh *ssh, const cha
ci = get_connection_info(ssh, 1, options.use_dns);
ci->user = user;
- parse_server_match_config(&options, ci);
+ parse_server_match_config(&options, &includes, ci);
log_change_level(options.log_level);
process_permitopen(ssh, &options);
diff -up openssh-8.0p1/readconf.c.sshdinclude openssh-8.0p1/readconf.c
--- openssh-8.0p1/readconf.c.sshdinclude 2021-10-20 15:21:43.541848103 +0200
+++ openssh-8.0p1/readconf.c 2021-10-20 15:22:06.302046768 +0200
@@ -711,7 +711,7 @@ match_cfg_line(Options *options, char **
static void
rm_env(Options *options, const char *arg, const char *filename, int linenum)
{
- int i, j;
+ int i, j, onum_send_env = options->num_send_env;
char *cp;
/* Remove an environment variable */
@@ -734,6 +734,11 @@ rm_env(Options *options, const char *arg
options->num_send_env--;
/* NB. don't increment i */
}
+ if (onum_send_env != options->num_send_env) {
+ options->send_env = xrecallocarray(options->send_env,
+ onum_send_env, options->num_send_env,
+ sizeof(*options->send_env));
+ }
}
/*
diff -up openssh-8.0p1/regress/Makefile.sshdinclude openssh-8.0p1/regress/Makefile
--- openssh-8.0p1/regress/Makefile.sshdinclude 2021-10-20 15:18:49.742331115 +0200
+++ openssh-8.0p1/regress/Makefile 2021-10-20 15:19:41.324781344 +0200
@@ -82,6 +82,7 @@ LTESTS= connect \
principals-command \
cert-file \
cfginclude \
+ servcfginclude \
allow-deny-users \
authinfo
@@ -118,7 +119,7 @@ CLEANFILES= *.core actual agent-key.* au
sftp-server.sh sftp.log ssh-log-wrapper.sh ssh.log \
ssh_config ssh_config.* ssh_proxy ssh_proxy_bak \
ssh_proxy_envpass sshd.log sshd_config sshd_config_minimal \
- sshd_config.orig sshd_proxy sshd_proxy.* sshd_proxy_bak \
+ sshd_config.* sshd_proxy sshd_proxy.* sshd_proxy_bak \
sshd_proxy_orig t10.out t10.out.pub t12.out t12.out.pub \
t2.out t3.out t6.out1 t6.out2 t7.out t7.out.pub \
t8.out t8.out.pub t9.out t9.out.pub testdata \
diff -up openssh-8.0p1/regress/servcfginclude.sh.sshdinclude openssh-8.0p1/regress/servcfginclude.sh
--- openssh-8.0p1/regress/servcfginclude.sh.sshdinclude 2021-10-20 15:18:49.744331132 +0200
+++ openssh-8.0p1/regress/servcfginclude.sh 2021-10-20 15:22:06.303046777 +0200
@@ -0,0 +1,188 @@
+# Placed in the Public Domain.
+
+tid="server config include"
+
+cat > $OBJ/sshd_config.i << _EOF
+HostKey $OBJ/host.ssh-ed25519
+Match host a
+ Banner /aa
+
+Match host b
+ Banner /bb
+ Include $OBJ/sshd_config.i.*
+
+Match host c
+ Include $OBJ/sshd_config.i.*
+ Banner /cc
+
+Match host m
+ Include $OBJ/sshd_config.i.*
+
+Match Host d
+ Banner /dd
+
+Match Host e
+ Banner /ee
+ Include $OBJ/sshd_config.i.*
+
+Match Host f
+ Include $OBJ/sshd_config.i.*
+ Banner /ff
+
+Match Host n
+ Include $OBJ/sshd_config.i.*
+_EOF
+
+cat > $OBJ/sshd_config.i.0 << _EOF
+Match host xxxxxx
+_EOF
+
+cat > $OBJ/sshd_config.i.1 << _EOF
+Match host a
+ Banner /aaa
+
+Match host b
+ Banner /bbb
+
+Match host c
+ Banner /ccc
+
+Match Host d
+ Banner /ddd
+
+Match Host e
+ Banner /eee
+
+Match Host f
+ Banner /fff
+_EOF
+
+cat > $OBJ/sshd_config.i.2 << _EOF
+Match host a
+ Banner /aaaa
+
+Match host b
+ Banner /bbbb
+
+Match host c
+ Banner /cccc
+
+Match Host d
+ Banner /dddd
+
+Match Host e
+ Banner /eeee
+
+Match Host f
+ Banner /ffff
+
+Match all
+ Banner /xxxx
+_EOF
+
+trial() {
+ _host="$1"
+ _exp="$2"
+ _desc="$3"
+ test -z "$_desc" && _desc="test match"
+ trace "$_desc host=$_host expect=$_exp"
+ ${SUDO} ${REAL_SSHD} -f $OBJ/sshd_config.i -T \
+ -C "host=$_host,user=test,addr=127.0.0.1" > $OBJ/sshd_config.out ||
+ fatal "ssh config parse failed: $_desc host=$_host expect=$_exp"
+ _got=`grep -i '^banner ' $OBJ/sshd_config.out | awk '{print $2}'`
+ if test "x$_exp" != "x$_got" ; then
+ fail "$desc_ host $_host include fail: expected $_exp got $_got"
+ fi
+}
+
+trial a /aa
+trial b /bb
+trial c /ccc
+trial d /dd
+trial e /ee
+trial f /fff
+trial m /xxxx
+trial n /xxxx
+trial x none
+
+# Prepare an included config with an error.
+
+cat > $OBJ/sshd_config.i.3 << _EOF
+Banner xxxx
+ Junk
+_EOF
+
+trace "disallow invalid config host=a"
+${SUDO} ${REAL_SSHD} -f $OBJ/sshd_config.i \
+ -C "host=a,user=test,addr=127.0.0.1" 2>/dev/null && \
+ fail "sshd include allowed invalid config"
+
+trace "disallow invalid config host=x"
+${SUDO} ${REAL_SSHD} -f $OBJ/sshd_config.i \
+ -C "host=x,user=test,addr=127.0.0.1" 2>/dev/null && \
+ fail "sshd include allowed invalid config"
+
+rm -f $OBJ/sshd_config.i.*
+
+# Ensure that a missing include is not fatal.
+cat > $OBJ/sshd_config.i << _EOF
+HostKey $OBJ/host.ssh-ed25519
+Include $OBJ/sshd_config.i.*
+Banner /aa
+_EOF
+
+trial a /aa "missing include non-fatal"
+
+# Ensure that Match/Host in an included config does not affect parent.
+cat > $OBJ/sshd_config.i.x << _EOF
+Match host x
+_EOF
+
+trial a /aa "included file does not affect match state"
+
+# Ensure the empty include directive is not accepted
+cat > $OBJ/sshd_config.i.x << _EOF
+Include
+_EOF
+
+trace "disallow invalid with no argument"
+${SUDO} ${REAL_SSHD} -f $OBJ/sshd_config.i.x -T \
+ -C "host=x,user=test,addr=127.0.0.1" 2>/dev/null && \
+ fail "sshd allowed Include with no argument"
+
+# Ensure the Include before any Match block works as expected (bug #3122)
+cat > $OBJ/sshd_config.i << _EOF
+Banner /xx
+HostKey $OBJ/host.ssh-ed25519
+Include $OBJ/sshd_config.i.2
+Match host a
+ Banner /aaaa
+_EOF
+cat > $OBJ/sshd_config.i.2 << _EOF
+Match host a
+ Banner /aa
+_EOF
+
+trace "Include before match blocks"
+trial a /aa "included file before match blocks is properly evaluated"
+
+# Port in included file is correctly interpretted (bug #3169)
+cat > $OBJ/sshd_config.i << _EOF
+Include $OBJ/sshd_config.i.2
+Port 7722
+_EOF
+cat > $OBJ/sshd_config.i.2 << _EOF
+HostKey $OBJ/host.ssh-ed25519
+_EOF
+
+trace "Port after included files"
+${SUDO} ${REAL_SSHD} -f $OBJ/sshd_config.i -T \
+ -C "host=x,user=test,addr=127.0.0.1" > $OBJ/sshd_config.out || \
+ fail "failed to parse Port after included files"
+_port=`grep -i '^port ' $OBJ/sshd_config.out | awk '{print $2}'`
+if test "x7722" != "x$_port" ; then
+ fail "The Port in included file was intertepretted wrongly. Expected 7722, got $_port"
+fi
+
+# cleanup
+rm -f $OBJ/sshd_config.i $OBJ/sshd_config.i.* $OBJ/sshd_config.out
diff -up openssh-8.0p1/regress/test-exec.sh.sshdinclude openssh-8.0p1/regress/test-exec.sh
--- openssh-8.0p1/regress/test-exec.sh.sshdinclude 2021-10-20 15:18:49.746331150 +0200
+++ openssh-8.0p1/regress/test-exec.sh 2021-10-20 15:19:41.324781344 +0200
@@ -220,6 +220,7 @@ echo "exec ${SSH} -E${TEST_SSH_LOGFILE}
chmod a+rx $OBJ/ssh-log-wrapper.sh
REAL_SSH="$SSH"
+REAL_SSHD="$SSHD"
SSH="$SSHLOGWRAP"
# Some test data. We make a copy because some tests will overwrite it.
diff -up openssh-8.0p1/servconf.c.sshdinclude openssh-8.0p1/servconf.c
--- openssh-8.0p1/servconf.c.sshdinclude 2021-10-20 15:18:49.748331167 +0200
+++ openssh-8.0p1/servconf.c 2021-10-20 15:22:06.303046777 +0200
@@ -40,6 +40,11 @@
#ifdef HAVE_UTIL_H
#include <util.h>
#endif
+#ifdef USE_SYSTEM_GLOB
+# include <glob.h>
+#else
+# include "openbsd-compat/glob.h"
+#endif
#include "openbsd-compat/sys-queue.h"
#include "xmalloc.h"
@@ -70,6 +75,9 @@ static void add_listen_addr(ServerOption
const char *, int);
static void add_one_listen_addr(ServerOptions *, const char *,
const char *, int);
+static void parse_server_config_depth(ServerOptions *options,
+ const char *filename, struct sshbuf *conf, struct include_list *includes,
+ struct connection_info *connectinfo, int flags, int *activep, int depth);
/* Use of privilege separation or not */
extern int use_privsep;
@@ -528,7 +536,7 @@ typedef enum {
sAcceptEnv, sSetEnv, sPermitTunnel,
sMatch, sPermitOpen, sPermitListen, sForceCommand, sChrootDirectory,
sUsePrivilegeSeparation, sAllowAgentForwarding,
- sHostCertificate,
+ sHostCertificate, sInclude,
sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile,
sAuthorizedPrincipalsCommand, sAuthorizedPrincipalsCommandUser,
sKexAlgorithms, sCASignatureAlgorithms, sIPQoS, sVersionAddendum,
@@ -540,9 +548,11 @@ typedef enum {
sDeprecated, sIgnore, sUnsupported
} ServerOpCodes;
-#define SSHCFG_GLOBAL 0x01 /* allowed in main section of sshd_config */
-#define SSHCFG_MATCH 0x02 /* allowed inside a Match section */
-#define SSHCFG_ALL (SSHCFG_GLOBAL|SSHCFG_MATCH)
+#define SSHCFG_GLOBAL 0x01 /* allowed in main section of config */
+#define SSHCFG_MATCH 0x02 /* allowed inside a Match section */
+#define SSHCFG_ALL (SSHCFG_GLOBAL|SSHCFG_MATCH)
+#define SSHCFG_NEVERMATCH 0x04 /* Match never matches; internal only */
+#define SSHCFG_MATCH_ONLY 0x08 /* Match only in conditional blocks; internal only */
/* Textual representation of the tokens. */
static struct {
@@ -687,6 +697,7 @@ static struct {
{ "trustedusercakeys", sTrustedUserCAKeys, SSHCFG_ALL },
{ "authorizedprincipalsfile", sAuthorizedPrincipalsFile, SSHCFG_ALL },
{ "kexalgorithms", sKexAlgorithms, SSHCFG_GLOBAL },
+ { "include", sInclude, SSHCFG_ALL },
{ "ipqos", sIPQoS, SSHCFG_ALL },
{ "authorizedkeyscommand", sAuthorizedKeysCommand, SSHCFG_ALL },
{ "authorizedkeyscommanduser", sAuthorizedKeysCommandUser, SSHCFG_ALL },
@@ -1259,13 +1270,14 @@ static const struct multistate multistat
{ NULL, -1 }
};
-int
-process_server_config_line(ServerOptions *options, char *line,
+static int
+process_server_config_line_depth(ServerOptions *options, char *line,
const char *filename, int linenum, int *activep,
- struct connection_info *connectinfo)
+ struct connection_info *connectinfo, int *inc_flags, int depth,
+ struct include_list *includes)
{
char ch, *cp, ***chararrayptr, **charptr, *arg, *arg2, *p;
- int cmdline = 0, *intptr, value, value2, n, port;
+ int cmdline = 0, *intptr, value, value2, n, port, oactive, r, found;
SyslogFacility *log_facility_ptr;
LogLevel *log_level_ptr;
ServerOpCodes opcode;
@@ -1274,6 +1286,8 @@ process_server_config_line(ServerOptions
long long val64;
const struct multistate *multistate_ptr;
const char *errstr;
+ struct include_item *item;
+ glob_t gbuf;
/* Strip trailing whitespace. Allow \f (form feed) at EOL only */
if ((len = strlen(line)) == 0)
@@ -1300,7 +1314,7 @@ process_server_config_line(ServerOptions
cmdline = 1;
activep = &cmdline;
}
- if (*activep && opcode != sMatch)
+ if (*activep && opcode != sMatch && opcode != sInclude)
debug3("%s:%d setting %s %s", filename, linenum, arg, cp);
if (*activep == 0 && !(flags & SSHCFG_MATCH)) {
if (connectinfo == NULL) {
@@ -1980,15 +1994,112 @@ process_server_config_line(ServerOptions
*intptr = value;
break;
+ case sInclude:
+ if (cmdline) {
+ fatal("Include directive not supported as a "
+ "command-line option");
+ }
+ value = 0;
+ while ((arg2 = strdelim(&cp)) != NULL && *arg2 != '\0') {
+ value++;
+ found = 0;
+ if (*arg2 != '/' && *arg2 != '~') {
+ xasprintf(&arg, "%s/%s", SSHDIR, arg2);
+ } else
+ arg = xstrdup(arg2);
+
+ /*
+ * Don't let included files clobber the containing
+ * file's Match state.
+ */
+ oactive = *activep;
+
+ /* consult cache of include files */
+ TAILQ_FOREACH(item, includes, entry) {
+ if (strcmp(item->selector, arg) != 0)
+ continue;
+ if (item->filename != NULL) {
+ parse_server_config_depth(options,
+ item->filename, item->contents,
+ includes, connectinfo,
+ (*inc_flags & SSHCFG_MATCH_ONLY
+ ? SSHCFG_MATCH_ONLY : (oactive
+ ? 0 : SSHCFG_NEVERMATCH)),
+ activep, depth + 1);
+ }
+ found = 1;
+ *activep = oactive;
+ }
+ if (found != 0) {
+ free(arg);
+ continue;
+ }
+
+ /* requested glob was not in cache */
+ debug2("%s line %d: new include %s",
+ filename, linenum, arg);
+ if ((r = glob(arg, 0, NULL, &gbuf)) != 0) {
+ if (r != GLOB_NOMATCH) {
+ fatal("%s line %d: include \"%s\" "
+ "glob failed", filename,
+ linenum, arg);
+ }
+ /*
+ * If no entry matched then record a
+ * placeholder to skip later glob calls.
+ */
+ debug2("%s line %d: no match for %s",
+ filename, linenum, arg);
+ item = xcalloc(1, sizeof(*item));
+ item->selector = strdup(arg);
+ TAILQ_INSERT_TAIL(includes,
+ item, entry);
+ }
+ if (gbuf.gl_pathc > INT_MAX)
+ fatal("%s: too many glob results", __func__);
+ for (n = 0; n < (int)gbuf.gl_pathc; n++) {
+ debug2("%s line %d: including %s",
+ filename, linenum, gbuf.gl_pathv[n]);
+ item = xcalloc(1, sizeof(*item));
+ item->selector = strdup(arg);
+ item->filename = strdup(gbuf.gl_pathv[n]);
+ if ((item->contents = sshbuf_new()) == NULL) {
+ fatal("%s: sshbuf_new failed",
+ __func__);
+ }
+ load_server_config(item->filename,
+ item->contents);
+ parse_server_config_depth(options,
+ item->filename, item->contents,
+ includes, connectinfo,
+ (*inc_flags & SSHCFG_MATCH_ONLY
+ ? SSHCFG_MATCH_ONLY : (oactive
+ ? 0 : SSHCFG_NEVERMATCH)),
+ activep, depth + 1);
+ *activep = oactive;
+ TAILQ_INSERT_TAIL(includes, item, entry);
+ }
+ globfree(&gbuf);
+ free(arg);
+ }
+ if (value == 0) {
+ fatal("%s line %d: Include missing filename argument",
+ filename, linenum);
+ }
+ break;
+
case sMatch:
if (cmdline)
fatal("Match directive not supported as a command-line "
"option");
- value = match_cfg_line(&cp, linenum, connectinfo);
+ value = match_cfg_line(&cp, linenum,
+ (*inc_flags & SSHCFG_NEVERMATCH ? NULL : connectinfo));
if (value < 0)
fatal("%s line %d: Bad Match condition", filename,
linenum);
- *activep = value;
+ *activep = (*inc_flags & SSHCFG_NEVERMATCH) ? 0 : value;
+ /* The MATCH_ONLY is applicable only until the first match block */
+ *inc_flags &= ~SSHCFG_MATCH_ONLY;
break;
case sKerberosUseKuserok:
@@ -2275,6 +2386,18 @@ process_server_config_line(ServerOptions
return 0;
}
+int
+process_server_config_line(ServerOptions *options, char *line,
+ const char *filename, int linenum, int *activep,
+ struct connection_info *connectinfo, struct include_list *includes)
+{
+ int inc_flags = 0;
+
+ return process_server_config_line_depth(options, line, filename,
+ linenum, activep, connectinfo, &inc_flags, 0, includes);
+}
+
+
/* Reads the server configuration file. */
void
@@ -2313,12 +2436,13 @@ load_server_config(const char *filename,
void
parse_server_match_config(ServerOptions *options,
- struct connection_info *connectinfo)
+ struct include_list *includes, struct connection_info *connectinfo)
{
ServerOptions mo;
initialize_server_options(&mo);
- parse_server_config(&mo, "reprocess config", cfg, connectinfo);
+ parse_server_config(&mo, "reprocess config", cfg, includes,
+ connectinfo);
copy_set_server_options(options, &mo, 0);
}
@@ -2464,28 +2588,44 @@ copy_set_server_options(ServerOptions *d
#undef M_CP_STROPT
#undef M_CP_STRARRAYOPT
-void
-parse_server_config(ServerOptions *options, const char *filename,
- struct sshbuf *conf, struct connection_info *connectinfo)
+#define SERVCONF_MAX_DEPTH 16
+static void
+parse_server_config_depth(ServerOptions *options, const char *filename,
+ struct sshbuf *conf, struct include_list *includes,
+ struct connection_info *connectinfo, int flags, int *activep, int depth)
{
- int active, linenum, bad_options = 0;
+ int linenum, bad_options = 0;
char *cp, *obuf, *cbuf;
- debug2("%s: config %s len %zu", __func__, filename, sshbuf_len(conf));
+ if (depth < 0 || depth > SERVCONF_MAX_DEPTH)
+ fatal("Too many recursive configuration includes");
+
+ debug2("%s: config %s len %zu%s", __func__, filename, sshbuf_len(conf),
+ (flags & SSHCFG_NEVERMATCH ? " [checking syntax only]" : ""));
if ((obuf = cbuf = sshbuf_dup_string(conf)) == NULL)
fatal("%s: sshbuf_dup_string failed", __func__);
- active = connectinfo ? 0 : 1;
linenum = 1;
while ((cp = strsep(&cbuf, "\n")) != NULL) {
- if (process_server_config_line(options, cp, filename,
- linenum++, &active, connectinfo) != 0)
+ if (process_server_config_line_depth(options, cp,
+ filename, linenum++, activep, connectinfo, &flags,
+ depth, includes) != 0)
bad_options++;
}
free(obuf);
if (bad_options > 0)
fatal("%s: terminating, %d bad configuration options",
filename, bad_options);
+}
+
+void
+parse_server_config(ServerOptions *options, const char *filename,
+ struct sshbuf *conf, struct include_list *includes,
+ struct connection_info *connectinfo)
+{
+ int active = connectinfo ? 0 : 1;
+ parse_server_config_depth(options, filename, conf, includes,
+ connectinfo, (connectinfo ? SSHCFG_MATCH_ONLY : 0), &active, 0);
process_queued_listen_addrs(options);
}
diff -up openssh-8.0p1/servconf.h.sshdinclude openssh-8.0p1/servconf.h
--- openssh-8.0p1/servconf.h.sshdinclude 2021-10-20 15:18:49.750331185 +0200
+++ openssh-8.0p1/servconf.h 2021-10-20 15:19:41.325781353 +0200
@@ -16,6 +16,8 @@
#ifndef SERVCONF_H
#define SERVCONF_H
+#include <sys/queue.h>
+
#define MAX_PORTS 256 /* Max # ports. */
#define MAX_SUBSYSTEMS 256 /* Max # subsystems. */
@@ -234,6 +236,15 @@ struct connection_info {
* unspecified */
};
+/* List of included files for re-exec from the parsed configuration */
+struct include_item {
+ char *selector;
+ char *filename;
+ struct sshbuf *contents;
+ TAILQ_ENTRY(include_item) entry;
+};
+TAILQ_HEAD(include_list, include_item);
+
/*
* These are string config options that must be copied between the
@@ -273,12 +284,13 @@ struct connection_info *get_connection_i
void initialize_server_options(ServerOptions *);
void fill_default_server_options(ServerOptions *);
int process_server_config_line(ServerOptions *, char *, const char *, int,
- int *, struct connection_info *);
+ int *, struct connection_info *, struct include_list *includes);
void process_permitopen(struct ssh *ssh, ServerOptions *options);
void load_server_config(const char *, struct sshbuf *);
void parse_server_config(ServerOptions *, const char *, struct sshbuf *,
- struct connection_info *);
-void parse_server_match_config(ServerOptions *, struct connection_info *);
+ struct include_list *includes, struct connection_info *);
+void parse_server_match_config(ServerOptions *,
+ struct include_list *includes, struct connection_info *);
int parse_server_match_testspec(struct connection_info *, char *);
int server_match_spec_complete(struct connection_info *);
void copy_set_server_options(ServerOptions *, ServerOptions *, int);
diff -up openssh-8.0p1/sshd_config.5.sshdinclude openssh-8.0p1/sshd_config.5
--- openssh-8.0p1/sshd_config.5.sshdinclude 2021-10-20 15:18:49.754331220 +0200
+++ openssh-8.0p1/sshd_config.5 2021-10-20 15:19:41.325781353 +0200
@@ -825,7 +825,20 @@ during
and use only the system-wide known hosts file
.Pa /etc/ssh/known_hosts .
The default is
-.Cm no .
+.Dq no .
+.It Cm Include
+Include the specified configuration file(s).
+Multiple path names may be specified and each pathname may contain
+.Xr glob 7
+wildcards.
+Files without absolute paths are assumed to be in
+.Pa /etc/ssh .
+A
+.Cm Include
+directive may appear inside a
+.Cm Match
+block
+to perform conditional inclusion.
.It Cm IPQoS
Specifies the IPv4 type-of-service or DSCP class for the connection.
Accepted values are
diff -up openssh-8.0p1/sshd.c.sshdinclude openssh-8.0p1/sshd.c
--- openssh-8.0p1/sshd.c.sshdinclude 2021-10-20 15:18:49.752331202 +0200
+++ openssh-8.0p1/sshd.c 2021-10-20 15:19:41.325781353 +0200
@@ -257,6 +257,9 @@ struct sshauthopt *auth_opts = NULL;
/* sshd_config buffer */
struct sshbuf *cfg;
+/* Included files from the configuration file */
+struct include_list includes = TAILQ_HEAD_INITIALIZER(includes);
+
/* message to be displayed after login */
struct sshbuf *loginmsg;
@@ -927,30 +930,45 @@ usage(void)
static void
send_rexec_state(int fd, struct sshbuf *conf)
{
- struct sshbuf *m;
+ struct sshbuf *m = NULL, *inc = NULL;
+ struct include_item *item = NULL;
int r;
debug3("%s: entering fd = %d config len %zu", __func__, fd,
sshbuf_len(conf));
+ if ((m = sshbuf_new()) == NULL || (inc = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
+
+ /* pack includes into a string */
+ TAILQ_FOREACH(item, &includes, entry) {
+ if ((r = sshbuf_put_cstring(inc, item->selector)) != 0 ||
+ (r = sshbuf_put_cstring(inc, item->filename)) != 0 ||
+ (r = sshbuf_put_stringb(inc, item->contents)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ }
+
/*
* Protocol from reexec master to child:
* string configuration
- * string rngseed (only if OpenSSL is not self-seeded)
+ * string included_files[] {
+ * string selector
+ * string filename
+ * string contents
+ * }
+ * string rng_seed (if required)
*/
- if ((m = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
- if ((r = sshbuf_put_stringb(m, conf)) != 0)
+ if ((r = sshbuf_put_stringb(m, conf)) != 0 ||
+ (r = sshbuf_put_stringb(m, inc)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
-
#if defined(WITH_OPENSSL) && !defined(OPENSSL_PRNG_ONLY)
rexec_send_rng_seed(m);
#endif
-
if (ssh_msg_send(fd, 0, m) == -1)
fatal("%s: ssh_msg_send failed", __func__);
sshbuf_free(m);
+ sshbuf_free(inc);
debug3("%s: done", __func__);
}
@@ -958,14 +976,15 @@ send_rexec_state(int fd, struct sshbuf *
static void
recv_rexec_state(int fd, struct sshbuf *conf)
{
- struct sshbuf *m;
+ struct sshbuf *m, *inc;
u_char *cp, ver;
size_t len;
int r;
+ struct include_item *item;
debug3("%s: entering fd = %d", __func__, fd);
- if ((m = sshbuf_new()) == NULL)
+ if ((m = sshbuf_new()) == NULL || (inc = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
if (ssh_msg_recv(fd, m) == -1)
fatal("%s: ssh_msg_recv failed", __func__);
@@ -973,14 +992,28 @@ recv_rexec_state(int fd, struct sshbuf *
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (ver != 0)
fatal("%s: rexec version mismatch", __func__);
- if ((r = sshbuf_get_string(m, &cp, &len)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
- if (conf != NULL && (r = sshbuf_put(conf, cp, len)))
+ if ((r = sshbuf_get_string(m, &cp, &len)) != 0 ||
+ (r = sshbuf_get_stringb(m, inc)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
+
#if defined(WITH_OPENSSL) && !defined(OPENSSL_PRNG_ONLY)
rexec_recv_rng_seed(m);
#endif
+ if (conf != NULL && (r = sshbuf_put(conf, cp, len)))
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+
+ while (sshbuf_len(inc) != 0) {
+ item = xcalloc(1, sizeof(*item));
+ if ((item->contents = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
+ if ((r = sshbuf_get_cstring(inc, &item->selector, NULL)) != 0 ||
+ (r = sshbuf_get_cstring(inc, &item->filename, NULL)) != 0 ||
+ (r = sshbuf_get_stringb(inc, item->contents)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ TAILQ_INSERT_TAIL(&includes, item, entry);
+ }
+
free(cp);
sshbuf_free(m);
@@ -1661,7 +1694,7 @@ main(int ac, char **av)
case 'o':
line = xstrdup(optarg);
if (process_server_config_line(&options, line,
- "command-line", 0, NULL, NULL) != 0)
+ "command-line", 0, NULL, NULL, &includes) != 0)
exit(1);
free(line);
break;
@@ -1692,7 +1725,7 @@ main(int ac, char **av)
SYSLOG_LEVEL_INFO : options.log_level,
options.log_facility == SYSLOG_FACILITY_NOT_SET ?
SYSLOG_FACILITY_AUTH : options.log_facility,
- log_stderr || !inetd_flag);
+ log_stderr || !inetd_flag || debug_flag);
/*
* Unset KRB5CCNAME, otherwise the user's session may inherit it from
@@ -1725,12 +1758,11 @@ main(int ac, char **av)
*/
(void)atomicio(vwrite, startup_pipe, "\0", 1);
}
- }
- else if (strcasecmp(config_file_name, "none") != 0)
+ } else if (strcasecmp(config_file_name, "none") != 0)
load_server_config(config_file_name, cfg);
parse_server_config(&options, rexeced_flag ? "rexec" : config_file_name,
- cfg, NULL);
+ cfg, &includes, NULL);
/* 'UsePAM no' is not supported in RHEL */
if (! options.use_pam)
@@ -1946,7 +1978,7 @@ main(int ac, char **av)
if (connection_info == NULL)
connection_info = get_connection_info(ssh, 0, 0);
connection_info->test = 1;
- parse_server_match_config(&options, connection_info);
+ parse_server_match_config(&options, &includes, connection_info);
dump_config(&options);
}
diff -up openssh-8.0p1/sshbuf-getput-basic.c.stringb openssh-8.0p1/sshbuf-getput-basic.c
--- openssh-8.0p1/sshbuf-getput-basic.c.stringb 2022-12-21 12:18:43.274799163 +0100
+++ openssh-8.0p1/sshbuf-getput-basic.c 2022-12-21 12:19:19.758081516 +0100
@@ -371,6 +371,9 @@ sshbuf_put_cstring(struct sshbuf *buf, c
int
sshbuf_put_stringb(struct sshbuf *buf, const struct sshbuf *v)
{
+ if (v == NULL)
+ return sshbuf_put_string(buf, NULL, 0);
+
return sshbuf_put_string(buf, sshbuf_ptr(v), sshbuf_len(v));
}

View file

@ -0,0 +1,38 @@
From d33ff14309e33aa79fdf95e1bc4facafa80b90a9 Mon Sep 17 00:00:00 2001
From: Stepan Broz <sbroz@redhat.com>
Date: Tue, 25 Jun 2024 17:38:22 +0200
Subject: [PATCH] upstream: ignore SIGPIPE earlier in main(), specifically
before
muxclient() which performs operations that could cause one; Reported by Noam
Lewis via bz3454, ok dtucker@
OpenBSD-Commit-ID: 63d8e13276869eebac6d7a05d5a96307f9026e47
---
ssh.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/ssh.c b/ssh.c
index 786e26d..e037c66 100644
--- a/ssh.c
+++ b/ssh.c
@@ -1115,6 +1115,8 @@ main(int ac, char **av)
}
}
+ 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.
@@ -1545,7 +1547,6 @@ main(int ac, char **av)
options.num_system_hostfiles);
tilde_expand_paths(options.user_hostfiles, options.num_user_hostfiles);
- signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE early */
signal(SIGCHLD, main_sigchld_handler);
/* Log into the remote system. Never returns if the login fails. */
--
2.45.2

View file

@ -0,0 +1,30 @@
diff --git a/channels.c b/channels.c
--- a/channels.c
+++ b/channels.c
@@ -3933,16 +3933,26 @@ x11_create_display_inet(int x11_display_
if (ai->ai_family == AF_INET6)
sock_set_v6only(sock);
if (x11_use_localhost)
set_reuseaddr(sock);
if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) {
debug2("%s: bind port %d: %.100s", __func__,
port, strerror(errno));
close(sock);
+
+ /* do not remove successfully opened
+ * sockets if the request failed because
+ * the protocol IPv4/6 is not available
+ * (e.g. IPv6 may be disabled while being
+ * supported)
+ */
+ if (EADDRNOTAVAIL == errno)
+ continue;
+
for (n = 0; n < num_socks; n++)
close(socks[n]);
num_socks = 0;
break;
}
socks[num_socks++] = sock;
if (num_socks == NUM_SOCKS)
break;

View file

@ -0,0 +1,166 @@
diff --color -ru a/kex.c b/kex.c
--- a/kex.c 2022-06-23 10:25:29.529922670 +0200
+++ b/kex.c 2022-06-23 10:26:12.911762100 +0200
@@ -906,6 +906,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)
{
@@ -941,6 +953,16 @@
free(ext);
}
+ /* Check whether client supports rsa-sha2 algorithms */
+ if (kex->server && (kex->flags & KEX_INITIAL)) {
+ 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;
+ 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;
+ }
+
/* Algorithm Negotiation */
if ((r = choose_kex(kex, cprop[PROPOSAL_KEX_ALGS],
sprop[PROPOSAL_KEX_ALGS])) != 0) {
diff --color -ru a/kex.h b/kex.h
--- a/kex.h 2022-06-23 10:25:29.511922322 +0200
+++ b/kex.h 2022-06-23 10:26:12.902761926 +0200
@@ -117,6 +117,8 @@
#define KEX_INIT_SENT 0x0001
#define KEX_INITIAL 0x0002
+#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 --color -ru a/serverloop.c b/serverloop.c
--- a/serverloop.c 2022-06-23 10:25:29.537922825 +0200
+++ b/serverloop.c 2022-06-23 10:26:12.918762235 +0200
@@ -736,16 +736,17 @@
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;
if ((resp = sshbuf_new()) == NULL || (sigbuf = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new", __func__);
-
- 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) {
sshkey_free(key);
key = NULL;
@@ -780,16 +781,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 (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("%s: sign %s key (index %d) using sigalg %s", __func__,
+ sshkey_type(key), ndx, sigalg == NULL ? "default" : sigalg);
if ((r = sshbuf_put_cstring(sigbuf,
"hostkeys-prove-00@openssh.com")) != 0 ||
(r = sshbuf_put_string(sigbuf,
ssh->kex->session_id, ssh->kex->session_id_len)) != 0 ||
(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 ||
+ sshbuf_ptr(sigbuf), sshbuf_len(sigbuf), sigalg)) != 0 ||
(r = sshbuf_put_string(resp, sig, slen)) != 0) {
error("%s: couldn't prepare signature: %s",
__func__, ssh_err(r));
diff --color -ru a/sshkey.c b/sshkey.c
--- a/sshkey.c 2022-06-23 10:25:29.532922728 +0200
+++ b/sshkey.c 2022-06-23 10:26:12.914762158 +0200
@@ -82,7 +82,6 @@
struct sshbuf *buf, enum sshkey_serialize_rep);
static int sshkey_from_blob_internal(struct sshbuf *buf,
struct sshkey **keyp, int allow_cert);
-static int get_sigtype(const u_char *sig, size_t siglen, char **sigtypep);
/* Supported key types */
struct keytype {
@@ -2092,7 +2091,8 @@
if ((ret = sshkey_verify(key->cert->signature_key, sig, slen,
sshbuf_ptr(key->cert->certblob), signed_len, NULL, 0)) != 0)
goto out;
- if ((ret = get_sigtype(sig, slen, &key->cert->signature_type)) != 0)
+ if ((ret = sshkey_get_sigtype(sig, slen,
+ &key->cert->signature_type)) != 0)
goto out;
/* Success */
@@ -2394,8 +2394,8 @@
return r;
}
-static int
-get_sigtype(const u_char *sig, size_t siglen, char **sigtypep)
+int
+sshkey_get_sigtype(const u_char *sig, size_t siglen, char **sigtypep)
{
int r;
struct sshbuf *b = NULL;
@@ -2477,7 +2477,7 @@
return 0;
if ((expected_alg = sshkey_sigalg_by_name(requested_alg)) == NULL)
return SSH_ERR_INVALID_ARGUMENT;
- if ((r = get_sigtype(sig, siglen, &sigtype)) != 0)
+ if ((r = sshkey_get_sigtype(sig, siglen, &sigtype)) != 0)
return r;
r = strcmp(expected_alg, sigtype) == 0;
free(sigtype);
@@ -2739,7 +2739,7 @@
sshbuf_len(cert), alg, 0, signer_ctx)) != 0)
goto out;
/* Check and update signature_type against what was actually used */
- if ((ret = get_sigtype(sig_blob, sig_len, &sigtype)) != 0)
+ if ((ret = sshkey_get_sigtype(sig_blob, sig_len, &sigtype)) != 0)
goto out;
if (alg != NULL && strcmp(alg, sigtype) != 0) {
ret = SSH_ERR_SIGN_ALG_UNSUPPORTED;
diff --color -ru a/sshkey.h b/sshkey.h
--- a/sshkey.h 2022-06-23 10:25:29.521922515 +0200
+++ b/sshkey.h 2022-06-23 10:26:12.907762022 +0200
@@ -211,6 +211,7 @@
const u_char *, size_t, const char *, u_int);
int sshkey_check_sigtype(const u_char *, size_t, const char *);
const char *sshkey_sigalg_by_name(const char *);
+int sshkey_get_sigtype(const u_char *, size_t, char **);
/* for debug */
void sshkey_dump_ec_point(const EC_GROUP *, const EC_POINT *);

View file

@ -0,0 +1,46 @@
diff -up openssh-8.7p1/pathnames.h.kill-scp openssh-8.7p1/pathnames.h
--- openssh-8.7p1/pathnames.h.kill-scp 2021-09-16 11:37:57.240171687 +0200
+++ openssh-8.7p1/pathnames.h 2021-09-16 11:42:29.183427917 +0200
@@ -42,6 +42,7 @@
#define _PATH_HOST_XMSS_KEY_FILE SSHDIR "/ssh_host_xmss_key"
#define _PATH_HOST_RSA_KEY_FILE SSHDIR "/ssh_host_rsa_key"
#define _PATH_DH_MODULI SSHDIR "/moduli"
+#define _PATH_SCP_KILL_SWITCH SSHDIR "/disable_scp"
#ifndef _PATH_SSH_PROGRAM
#define _PATH_SSH_PROGRAM "/usr/bin/ssh"
diff -up openssh-8.7p1/scp.1.kill-scp openssh-8.7p1/scp.1
--- openssh-8.7p1/scp.1.kill-scp 2021-09-16 12:09:02.646714578 +0200
+++ openssh-8.7p1/scp.1 2021-09-16 12:26:49.978628226 +0200
@@ -278,6 +278,13 @@ to print debugging messages about their
This is helpful in
debugging connection, authentication, and configuration problems.
.El
+.Pp
+Usage of SCP protocol can be blocked by creating a world-readable
+.Ar /etc/ssh/disable_scp
+file. If this file exists, when SCP protocol is in use (either remotely or
+via the
+.Fl O
+option), the program will exit.
.Sh EXIT STATUS
.Ex -std scp
.Sh SEE ALSO
diff -up openssh-8.7p1/scp.c.kill-scp openssh-8.7p1/scp.c
--- openssh-8.7p1/scp.c.kill-scp 2021-09-16 11:42:56.013650519 +0200
+++ openssh-8.7p1/scp.c 2021-09-16 11:53:03.249713836 +0200
@@ -596,6 +596,14 @@ main(int argc, char **argv)
argc -= optind;
argv += optind;
+ {
+ FILE *f = fopen(_PATH_SCP_KILL_SWITCH, "r");
+ if (f != NULL) {
+ fclose(f);
+ fatal("SCP protocol is forbidden via %s", _PATH_SCP_KILL_SWITCH);
+ }
+ }
+
if ((pwd = getpwuid(userid = getuid())) == NULL)
fatal("unknown user %u", (u_int) userid);

View file

@ -0,0 +1,25 @@
diff --git a/auth.c b/auth.c
index b8d1040d..0134d694 100644
--- a/auth.c
+++ b/auth.c
@@ -56,6 +56,7 @@
# include <paths.h>
#endif
#include <pwd.h>
+#include <grp.h>
#ifdef HAVE_LOGIN_H
#include <login.h>
#endif
@@ -2695,6 +2696,12 @@ subprocess(const char *tag, const char *command,
}
closefrom(STDERR_FILENO + 1);
+ if (geteuid() == 0 &&
+ initgroups(pw->pw_name, pw->pw_gid) == -1) {
+ error("%s: initgroups(%s, %u): %s", tag,
+ pw->pw_name, (u_int)pw->pw_gid, strerror(errno));
+ _exit(1);
+ }
/* Don't use permanently_set_uid() here to avoid fatal() */
if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) != 0) {
error("%s: setresgid %u: %s", tag, (u_int)pw->pw_gid,

View file

@ -0,0 +1,32 @@
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);

View file

@ -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 */

View file

@ -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("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);

View file

@ -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("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)
if (kex == NULL)
return SSH_ERR_INVALID_ARGUMENT;
- 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("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("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("resetting read seqnr %u", state->p_read.seqnr);
+ state->p_read.seqnr = 0;
+ }
/* do we need to rekey? */
if (ssh_packet_need_rekeying(ssh, 0)) {
@@ -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("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
xxx_host = host;
xxx_hostaddr = hostaddr;
- 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("%s: kex_names_cat", __func__);
myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal(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)
{
char *myproposal[PROPOSAL_MAX] = { KEX_SERVER };
struct kex *kex;
+ char *cp;
int r;
- myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal(
- options.kex_algorithms);
+ if ((cp = kex_names_cat(options.kex_algorithms,
+ "kex-strict-s-v00@openssh.com")) == NULL)
+ fatal("kex_names_cat");
+
+ myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal(cp);
myproposal[PROPOSAL_ENC_ALGS_CTOS] = compat_cipher_proposal(
options.ciphers);
myproposal[PROPOSAL_ENC_ALGS_STOC] = compat_cipher_proposal(
@@ -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)
packet_send();
packet_write_wait();
#endif
+ free(cp);
debug("KEX done");
}

View file

@ -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)
}
}
+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. */

View file

@ -1,3 +1,3 @@
SHA512 (openssh-7.8p1.tar.gz) = 8e5b0c8682a9243e4e8b7c374ec989dccd1a752eb6f84e593b67141e8b23dcc8b9a7322b1f7525d18e2ce8830a767d0d9793f997486339db201a57986b910705
SHA512 (openssh-7.8p1.tar.gz.asc) = 3a7bef84df3c07aa78965a11a6bbd6ca6e5d1e9265ac08871b3e5d304646be651b74f5302a195e86a56e6a83b19d79292e5599c9a9cf6f003a513d4354e8ad2f
SHA512 (openssh-8.0p1.tar.gz) = e280fa2d56f550efd37c5d2477670326261aa8b94d991f9eb17aad90e0c6c9c939efa90fe87d33260d0f709485cb05c379f0fd1bd44fc0d5190298b6398c9982
SHA512 (openssh-8.0p1.tar.gz.asc) = fe9e7383d9467e869762864f2b719165d9a3f2c5316c07067df1d45fc7819bd2cb8ef758454865595688804a4c160dd3d3aaee4c5f887859555d2c7bb8c4592b
SHA512 (DJM-GPG-KEY.gpg) = db1191ed9b6495999e05eed2ef863fb5179bdb63e94850f192dad68eed8579836f88fbcfffd9f28524fe1457aff8cd248ee3e0afc112c8f609b99a34b80ecc0d